From 8b8c27d09b8bcf5ab7d05763700f0360cb04e917 Mon Sep 17 00:00:00 2001 From: ajuvonen Date: Tue, 21 May 2024 13:40:32 +0300 Subject: [PATCH] Test hooks --- .../__tests__/EditTrainingDialog.spec.ts | 1 + .../{calendarExport.spec.ts => hooks.spec.ts} | 378 ++++++++++++------ 2 files changed, 247 insertions(+), 132 deletions(-) rename src/components/__tests__/{calendarExport.spec.ts => hooks.spec.ts} (63%) diff --git a/src/components/__tests__/EditTrainingDialog.spec.ts b/src/components/__tests__/EditTrainingDialog.spec.ts index db711ec..495eb3e 100644 --- a/src/components/__tests__/EditTrainingDialog.spec.ts +++ b/src/components/__tests__/EditTrainingDialog.spec.ts @@ -19,6 +19,7 @@ describe('EditTrainingDialog', () => { }); it('mounts', () => { + appStateStore.trainingData = getEmptyTraining(); const wrapper = mount(EditTrainingDialog); expect(wrapper.findComponent(VCard).html()).toMatchSnapshot(); }); diff --git a/src/components/__tests__/calendarExport.spec.ts b/src/components/__tests__/hooks.spec.ts similarity index 63% rename from src/components/__tests__/calendarExport.spec.ts rename to src/components/__tests__/hooks.spec.ts index 0274792..9dd994a 100644 --- a/src/components/__tests__/calendarExport.spec.ts +++ b/src/components/__tests__/hooks.spec.ts @@ -1,37 +1,210 @@ -import {onMounted} from 'vue'; -import {describe, it, expect, beforeEach} from 'vitest'; -import {mount} from '@vue/test-utils'; +import {describe, it, expect, vi, beforeEach} from 'vitest'; +import {shallowMount} from '@vue/test-utils'; import {v4 as uuid} from 'uuid'; +import {useAppStateStore} from '@/stores/appState'; import {useScheduleStore} from '@/stores/schedule'; -import useCalendarExport from '@/hooks/calendarExport'; -import {Intensity, type Week, type ScheduleSettings, type CalendarEvent} from '@/types'; import {getEmptySettings, getEmptyTraining} from '@/utils'; +import {Intensity, type ScheduleSettings, type Week} from '@/types'; +import useReset from '@/hooks/reset'; +import useScreen from '@/hooks/screen'; +import useCalendarExport from '@/hooks/calendarExport'; +import useWeekDays from '@/hooks/weekdays'; +import {nextTick} from 'vue'; + +const withSetup = (hook: () => T) => + new Promise((resolve) => { + shallowMount({ + template: '
', + setup() { + resolve(hook()); + }, + }); + }); -describe('useCalendarExport', () => { +describe('hooks', () => { + let appStateStore: ReturnType; let scheduleStore: ReturnType; beforeEach(() => { + appStateStore = useAppStateStore(); scheduleStore = useScheduleStore(); }); - const createTestComponent = (settings: ScheduleSettings, weeks: Week[]) => { - scheduleStore.$patch((state) => { - state.settings = settings; - state.weeks = weeks; + it('opens a confirmation dialog which resets the stores', async () => { + const resetFn = await withSetup(useReset); + appStateStore.trainingData = getEmptyTraining(); + scheduleStore.settings.name = 'Test schedule'; + resetFn(); + expect(appStateStore.openConfirmDialog).toHaveBeenCalled(); + }); + + it('uses preferred dark mode', async () => { + const {isDark} = await withSetup(useScreen); + + expect(isDark.value).toBe(false); + scheduleStore.settings.darkMode = 'dark'; + expect(isDark.value).toBe(true); + scheduleStore.settings.darkMode = 'light'; + expect(isDark.value).toBe(false); + }); + + it('announces small size', async () => { + vi.stubGlobal('innerWidth', 599); + const {isSmallScreen, isLargeScreen} = await withSetup(useScreen); + expect(isSmallScreen.value).toBe(true); + expect(isLargeScreen.value).toBe(false); + vi.unstubAllGlobals(); + }); + + it('announces medium size 1', async () => { + vi.stubGlobal('innerWidth', 600); + const {isSmallScreen, isLargeScreen} = await withSetup(useScreen); + expect(isSmallScreen.value).toBe(false); + expect(isLargeScreen.value).toBe(false); + vi.unstubAllGlobals(); + }); + + it('announces medium size 2', async () => { + vi.stubGlobal('innerWidth', 959); + const {isSmallScreen, isLargeScreen} = await withSetup(useScreen); + expect(isSmallScreen.value).toBe(false); + expect(isLargeScreen.value).toBe(false); + vi.unstubAllGlobals(); + }); + + it('announces large size', async () => { + vi.stubGlobal('innerWidth', 960); + const {isSmallScreen, isLargeScreen} = await withSetup(useScreen); + expect(isSmallScreen.value).toBe(false); + expect(isLargeScreen.value).toBe(true); + vi.unstubAllGlobals(); + }); + + it('gives calendar event a default duration', async () => { + const weekId = uuid(); + const mockWeeks: Week[] = [ + { + id: weekId, + trainings: [ + getEmptyTraining({ + weekId, + activity: 'running', + duration: 12, + unitOfDuration: 'km', + }), + ], + }, + ]; + + const mockSettings: ScheduleSettings = getEmptySettings({ + name: '', + startDate: new Date('2024-01-01'), }); - const promise: Promise = new Promise((resolve) => { - mount({ - template: '
', - setup() { - const {createCalendarEvents} = useCalendarExport(); - onMounted(() => { - resolve(createCalendarEvents()); - }); - }, - }); + + const {createCalendarEvents} = await withSetup(useCalendarExport); + scheduleStore.weeks = mockWeeks; + scheduleStore.settings = mockSettings; + const events = createCalendarEvents(); + expect(events).toHaveLength(1); + expect(events[0].duration.minutes).toBe(60); + }); + + it('gives calendar a default name', async () => { + const weekId = uuid(); + const mockWeeks: Week[] = [ + { + id: weekId, + trainings: [ + getEmptyTraining({ + weekId, + activity: 'running', + }), + ], + }, + ]; + + const mockSettings: ScheduleSettings = getEmptySettings({ + name: '', + startDate: new Date('2024-01-01'), }); - return promise; - }; + + const {createCalendarEvents} = await withSetup(useCalendarExport); + scheduleStore.weeks = mockWeeks; + scheduleStore.settings = mockSettings; + const events = createCalendarEvents(); + + expect(events).toHaveLength(1); + expect(events[0].calName).toBe('TrainingSchedule'); + }); + + it('moves to next date when durations cross over', async () => { + const weekId1 = uuid(); + const mockWeeks: Week[] = [ + { + id: weekId1, + trainings: [ + getEmptyTraining({ + weekId: weekId1, + activity: 'running', + title: 'Test Training', + instructions: 'Test Instructions', + location: 'Test Location', + }), + getEmptyTraining({ + weekId: weekId1, + activity: 'swimming', + intensity: Intensity.DEMANDING, + title: 'Test Training 2', + instructions: 'Test Instructions 2', + duration: 0.5, + location: 'Test Location 2', + }), + ], + }, + ]; + + const mockSettings: ScheduleSettings = getEmptySettings({ + name: 'Test Schedule', + startDate: new Date('2024-01-01'), + defaultStartTime: {hours: 23, minutes: 30, seconds: 0}, + }); + + const {createCalendarEvents} = await withSetup(useCalendarExport); + scheduleStore.weeks = mockWeeks; + scheduleStore.settings = mockSettings; + const events = createCalendarEvents(); + + expect(events).toHaveLength(2); + + // Assertions for the first activity + expect(events[0].title).toBe('Test Training'); + expect(events[0].description).toBe('Test Instructions'); + expect(events[0].duration.minutes).toBe(60); + expect(events[0].location).toBe('Test Location'); + expect(events[0].categories).toEqual(['Running', 'Normal']); + expect(events[0].status).toBe('CONFIRMED'); + expect(events[0].busyStatus).toBe('BUSY'); + expect(events[0].transp).toBe('OPAQUE'); + expect(events[0].productId).toBe('ajuvonen/getfit'); + expect(events[0].classification).toBe('PRIVATE'); + expect(events[0].calName).toBe('Test Schedule'); + expect(events[0].start).toEqual([2024, 1, 1, 23, 30]); + + // Assertions for the second activity + expect(events[1].title).toBe('Test Training 2'); + expect(events[1].description).toBe('Test Instructions 2'); + expect(events[1].duration.minutes).toBe(30); + expect(events[1].location).toBe('Test Location 2'); + expect(events[1].categories).toEqual(['Swimming', 'Demanding']); + expect(events[1].status).toBe('CONFIRMED'); + expect(events[1].busyStatus).toBe('BUSY'); + expect(events[1].transp).toBe('OPAQUE'); + expect(events[1].productId).toBe('ajuvonen/getfit'); + expect(events[1].classification).toBe('PRIVATE'); + expect(events[1].calName).toBe('Test Schedule'); + expect(events[1].start).toEqual([2024, 1, 2, 0, 30]); + }); + it('creates correct calendar events', async () => { const weekId1 = uuid(); const weekId2 = uuid(); @@ -96,7 +269,10 @@ describe('useCalendarExport', () => { startDate: new Date('2024-01-01'), }); - const events = await createTestComponent(mockSettings, mockWeeks); + const {createCalendarEvents} = await withSetup(useCalendarExport); + scheduleStore.weeks = mockWeeks; + scheduleStore.settings = mockSettings; + const events = createCalendarEvents(); expect(events).toHaveLength(5); @@ -171,120 +347,58 @@ describe('useCalendarExport', () => { expect(events[4].start).toEqual([2024, 1, 14, 13, 0]); }); - it('moves to next date when durations cross over', async () => { - const weekId1 = uuid(); - const mockWeeks: Week[] = [ - { - id: weekId1, - trainings: [ - getEmptyTraining({ - weekId: weekId1, - activity: 'running', - title: 'Test Training', - instructions: 'Test Instructions', - location: 'Test Location', - }), - getEmptyTraining({ - weekId: weekId1, - activity: 'swimming', - intensity: Intensity.DEMANDING, - title: 'Test Training 2', - instructions: 'Test Instructions 2', - duration: 0.5, - location: 'Test Location 2', - }), - ], - }, - ]; - - const mockSettings: ScheduleSettings = getEmptySettings({ - name: 'Test Schedule', - startDate: new Date('2024-01-01'), - defaultStartTime: {hours: 23, minutes: 30, seconds: 0}, - }); - - const events = await createTestComponent(mockSettings, mockWeeks); - - expect(events).toHaveLength(2); - - // Assertions for the first activity - expect(events[0].title).toBe('Test Training'); - expect(events[0].description).toBe('Test Instructions'); - expect(events[0].duration.minutes).toBe(60); - expect(events[0].location).toBe('Test Location'); - expect(events[0].categories).toEqual(['Running', 'Normal']); - expect(events[0].status).toBe('CONFIRMED'); - expect(events[0].busyStatus).toBe('BUSY'); - expect(events[0].transp).toBe('OPAQUE'); - expect(events[0].productId).toBe('ajuvonen/getfit'); - expect(events[0].classification).toBe('PRIVATE'); - expect(events[0].calName).toBe('Test Schedule'); - expect(events[0].start).toEqual([2024, 1, 1, 23, 30]); - - // Assertions for the second activity - expect(events[1].title).toBe('Test Training 2'); - expect(events[1].description).toBe('Test Instructions 2'); - expect(events[1].duration.minutes).toBe(30); - expect(events[1].location).toBe('Test Location 2'); - expect(events[1].categories).toEqual(['Swimming', 'Demanding']); - expect(events[1].status).toBe('CONFIRMED'); - expect(events[1].busyStatus).toBe('BUSY'); - expect(events[1].transp).toBe('OPAQUE'); - expect(events[1].productId).toBe('ajuvonen/getfit'); - expect(events[1].classification).toBe('PRIVATE'); - expect(events[1].calName).toBe('Test Schedule'); - expect(events[1].start).toEqual([2024, 1, 2, 0, 30]); + it('lists weekdays in correct order', async () => { + const {weekdays} = await withSetup(useWeekDays); + expect(weekdays.value).toEqual([ + 'Monday', + 'Tuesday', + 'Wednesday', + 'Thursday', + 'Friday', + 'Saturday', + 'Sunday', + ]); + scheduleStore.settings.startsOnSunday = true; + expect(weekdays.value).toEqual([ + 'Sunday', + 'Monday', + 'Tuesday', + 'Wednesday', + 'Thursday', + 'Friday', + 'Saturday', + ]); }); - it('gives calendar a default name', async () => { - const weekId = uuid(); - const mockWeeks: Week[] = [ - { - id: weekId, - trainings: [ - getEmptyTraining({ - weekId, - activity: 'running', - }), - ], - }, - ]; - - const mockSettings: ScheduleSettings = getEmptySettings({ - name: '', - startDate: new Date('2024-01-01'), - }); - - const events = await createTestComponent(mockSettings, mockWeeks); - - expect(events).toHaveLength(1); - expect(events[0].calName).toBe('TrainingSchedule'); + it('lists short weekdays in correct order', async () => { + const {shortWeekdays} = await withSetup(useWeekDays); + expect(shortWeekdays.value).toEqual(['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']); + scheduleStore.settings.startsOnSunday = true; + expect(shortWeekdays.value).toEqual(['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']); }); - it('gives calendar event a default duration', async () => { - const weekId = uuid(); - const mockWeeks: Week[] = [ - { - id: weekId, - trainings: [ - getEmptyTraining({ - weekId, - activity: 'running', - duration: 12, - unitOfDuration: 'km', - }), - ], - }, - ]; - - const mockSettings: ScheduleSettings = getEmptySettings({ - name: '', - startDate: new Date('2024-01-01'), - }); + it('returns a date interval for selected week', async () => { + const {getDateInterval} = await withSetup(useWeekDays); + scheduleStore.settings.startDate = new Date('05-20-2024'); + expect(getDateInterval.value(0)).toEqual('05/20/2024 - 05/26/2024'); + expect(getDateInterval.value(1)).toEqual('05/27/2024 - 06/02/2024'); + expect(getDateInterval.value(2)).toEqual('06/03/2024 - 06/09/2024'); + }); - const events = await createTestComponent(mockSettings, mockWeeks); + it('returns display week number', async () => { + const {getDisplayWeekNumber} = await withSetup(useWeekDays); + expect(getDisplayWeekNumber.value(0)).toBe(1); + expect(getDisplayWeekNumber.value(1)).toBe(2); + scheduleStore.settings.startDate = new Date('05-20-2024'); + scheduleStore.settings.actualWeekNumbering = true; + expect(getDisplayWeekNumber.value(0)).toBe(21); + expect(getDisplayWeekNumber.value(1)).toBe(22); + }); - expect(events).toHaveLength(1); - expect(events[0].duration.minutes).toBe(60); + it('returns short date', async () => { + const {getShortDate} = await withSetup(useWeekDays); + scheduleStore.settings.startDate = new Date('05-20-2024'); + expect(getShortDate.value(0, 1)).toBe('05/21'); + expect(getShortDate.value(1, 3)).toBe('05/30'); }); });