From 565ff7625a219115c0c26e6a36bc9e2ef946c3c3 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Mon, 24 Oct 2022 16:26:31 -0500 Subject: [PATCH 01/52] adding tests for layouts --- .../layouts/DayOfWeekLayout.spec.tsx | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx diff --git a/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx new file mode 100644 index 00000000..e2abba30 --- /dev/null +++ b/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx @@ -0,0 +1,52 @@ +import { BreakpointProvider, CalendarProvider } from '@/providers'; +import { CalendarState, ComponentSize } from '@/types'; +import { DayOfWeekLayout } from '@/layouts'; +import { createDefaultAdapter } from '@/dateAdapters'; +import { render } from '@testing-library/react'; +import { useCalendar } from '../../src/hooks/useCalendar'; +import React from 'react'; + +jest.mock('../../src/hooks/useCalendar'); +const mockUseCalendar = useCalendar as jest.MockedFunction; + +const hook: CalendarState = { + currentMonth: new Date(), + dateAdapter: createDefaultAdapter(), + getDaysOfWeek: (componentSize: ComponentSize) => [ + 'Sunday', + 'Monday', + 'Tueday', + 'Wednesday', + 'Thursday', + 'Friday', + 'Saturday', + ], + onNextMonth: () => null, + onPrevMonth: () => null, + onNextYear: () => null, + onPrevYear: () => null, + calendarWithEvents: [], +}; + +describe('DayOfWeekLayout', () => { + mockUseCalendar.mockReturnValue(hook); + + const testFixture = render( + + + + ); + + var testObject = testFixture.baseElement.querySelector('.day-of-week-layout'); + var individualDays = testFixture.baseElement.querySelector( + '.default-day-of-week' + ); + + it('renders the correct number of days', () => { + expect(testObject?.children.length).toEqual(hook.getDaysOfWeek('large')); + }); + + it('renders the correct names of the days', () => { + expect(testObject?.children.length).toEqual(hook.getDaysOfWeek('large')); + }); +}); From fcbf908d4ae52279546847498ae40615d38077a3 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Mon, 24 Oct 2022 16:27:28 -0500 Subject: [PATCH 02/52] wip --- packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx index e2abba30..f59a6b48 100644 --- a/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx @@ -28,7 +28,7 @@ const hook: CalendarState = { calendarWithEvents: [], }; -describe('DayOfWeekLayout', () => { +xdescribe('DayOfWeekLayout', () => { mockUseCalendar.mockReturnValue(hook); const testFixture = render( From 121c797c149de6bf4211733a954fee8e2221b203 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Mon, 24 Oct 2022 16:50:46 -0500 Subject: [PATCH 03/52] wip --- .../layouts/DayOfWeekLayout.spec.tsx | 37 ++++++++----------- .../dayOfWeekLayout/DayOfWeekLayout.tsx | 2 +- 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx index f59a6b48..dbf432fe 100644 --- a/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx @@ -2,25 +2,27 @@ import { BreakpointProvider, CalendarProvider } from '@/providers'; import { CalendarState, ComponentSize } from '@/types'; import { DayOfWeekLayout } from '@/layouts'; import { createDefaultAdapter } from '@/dateAdapters'; -import { render } from '@testing-library/react'; +import { render, within } from '@testing-library/react'; import { useCalendar } from '../../src/hooks/useCalendar'; import React from 'react'; jest.mock('../../src/hooks/useCalendar'); const mockUseCalendar = useCalendar as jest.MockedFunction; +const daysOfWeek = [ + 'Sunday', + 'Monday', + 'Tueday', + 'Wednesday', + 'Thursday', + 'Friday', + 'Saturday', +]; + const hook: CalendarState = { currentMonth: new Date(), dateAdapter: createDefaultAdapter(), - getDaysOfWeek: (componentSize: ComponentSize) => [ - 'Sunday', - 'Monday', - 'Tueday', - 'Wednesday', - 'Thursday', - 'Friday', - 'Saturday', - ], + getDaysOfWeek: (componentSize: ComponentSize) => daysOfWeek, onNextMonth: () => null, onPrevMonth: () => null, onNextYear: () => null, @@ -31,22 +33,13 @@ const hook: CalendarState = { xdescribe('DayOfWeekLayout', () => { mockUseCalendar.mockReturnValue(hook); - const testFixture = render( + const testObject = render( ); - var testObject = testFixture.baseElement.querySelector('.day-of-week-layout'); - var individualDays = testFixture.baseElement.querySelector( - '.default-day-of-week' - ); - - it('renders the correct number of days', () => { - expect(testObject?.children.length).toEqual(hook.getDaysOfWeek('large')); - }); - - it('renders the correct names of the days', () => { - expect(testObject?.children.length).toEqual(hook.getDaysOfWeek('large')); + test.each(daysOfWeek)('%s is rendered', (value) => { + expect(testObject.findByText(value)).toBeInTheDocument(); }); }); diff --git a/packages/Schedulely/src/layouts/dayOfWeekLayout/DayOfWeekLayout.tsx b/packages/Schedulely/src/layouts/dayOfWeekLayout/DayOfWeekLayout.tsx index 7f6b596d..b04ddaa6 100644 --- a/packages/Schedulely/src/layouts/dayOfWeekLayout/DayOfWeekLayout.tsx +++ b/packages/Schedulely/src/layouts/dayOfWeekLayout/DayOfWeekLayout.tsx @@ -14,7 +14,7 @@ export const DayOfWeekLayout = () => { {getDaysOfWeek(breakpoint).map((dayOfWeek, idx) => (
{/* wrap with extra div so we can control borders without touching the DayOfWeek component */} -
{dayOfWeek}
+ {dayOfWeek}
))} From 69497dd986329295a105a2e5de349515fcac85fa Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Tue, 25 Oct 2022 13:21:51 -0500 Subject: [PATCH 04/52] add tests for dayofweeklayout --- package.json | 1 + .../layouts/DayOfWeekLayout.spec.tsx | 23 +++++++++++-------- turbo.json | 12 ++++------ 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index c0c3080e..a8389524 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ ], "scripts": { "build": "turbo run build --no-daemon", + "barrels": "turbo run barrels --no-daemon", "build-ladle": "turbo run build-ladle --no-daemon", "rollup": "turbo run rollup --no-daemon", "ssr-test": "turbo run ssr-test --no-daemon", diff --git a/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx index dbf432fe..fb904c92 100644 --- a/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx @@ -1,8 +1,8 @@ -import { BreakpointProvider, CalendarProvider } from '@/providers'; +import { BreakpointProvider } from '@/providers'; import { CalendarState, ComponentSize } from '@/types'; import { DayOfWeekLayout } from '@/layouts'; +import { RenderResult, render } from '@testing-library/react'; import { createDefaultAdapter } from '@/dateAdapters'; -import { render, within } from '@testing-library/react'; import { useCalendar } from '../../src/hooks/useCalendar'; import React from 'react'; @@ -22,7 +22,7 @@ const daysOfWeek = [ const hook: CalendarState = { currentMonth: new Date(), dateAdapter: createDefaultAdapter(), - getDaysOfWeek: (componentSize: ComponentSize) => daysOfWeek, + getDaysOfWeek: () => daysOfWeek, onNextMonth: () => null, onPrevMonth: () => null, onNextYear: () => null, @@ -30,16 +30,19 @@ const hook: CalendarState = { calendarWithEvents: [], }; -xdescribe('DayOfWeekLayout', () => { +describe('DayOfWeekLayout', () => { mockUseCalendar.mockReturnValue(hook); + let testObject: RenderResult; - const testObject = render( - - - - ); + beforeEach(() => { + testObject = render( + + + + ); + }); test.each(daysOfWeek)('%s is rendered', (value) => { - expect(testObject.findByText(value)).toBeInTheDocument(); + expect(testObject.queryByText(value)).not.toBeNull(); }); }); diff --git a/turbo.json b/turbo.json index ea98d154..b9c4f888 100644 --- a/turbo.json +++ b/turbo.json @@ -12,15 +12,13 @@ ] }, "test": { - "dependsOn": [ - "barrels" - ], + "dependsOn": [], "outputs": [], "inputs": [ - "src/**/*.tsx", - "src/**/*.ts", - "__tests__/**/*.tsx", - "__tests__/**/*.ts" + "./src/**/*.tsx", + "./src/**/*.ts", + "./__tests__/**/*.tsx", + "./__tests__/**/*.ts" ] }, "rollup": { From eefb0af99a836ce0294a91ae89d4ae16d9aa221e Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Tue, 25 Oct 2022 13:31:22 -0500 Subject: [PATCH 05/52] enforce naming convention --- .../Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx | 4 ++-- .../Schedulely/src/layouts/monthLayout/MonthLayout.tsx | 5 +---- packages/Schedulely/src/layouts/weekLayout/WeekLayout.tsx | 4 +--- packages/Schedulely/src/providers/ActionProvider.tsx | 8 ++++---- packages/Schedulely/src/providers/CalendarProvider.tsx | 6 +++--- packages/Schedulely/src/providers/HightlightProvider.tsx | 7 ++++--- packages/Schedulely/src/types/SchedulelyProps.ts | 4 ++-- .../types/state/{ActionState.ts => ActionContextState.ts} | 2 +- .../state/{CalendarState.ts => CalendarContextState.ts} | 2 +- ...ghlightEventState.ts => HighlightEventContextState.ts} | 2 +- packages/Schedulely/src/types/state/index.ts | 6 +++--- 11 files changed, 23 insertions(+), 27 deletions(-) rename packages/Schedulely/src/types/state/{ActionState.ts => ActionContextState.ts} (92%) rename packages/Schedulely/src/types/state/{CalendarState.ts => CalendarContextState.ts} (95%) rename packages/Schedulely/src/types/state/{HighlightEventState.ts => HighlightEventContextState.ts} (86%) diff --git a/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx index fb904c92..4c52b59e 100644 --- a/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx @@ -1,5 +1,5 @@ import { BreakpointProvider } from '@/providers'; -import { CalendarState, ComponentSize } from '@/types'; +import { CalendarContextState, ComponentSize } from '@/types'; import { DayOfWeekLayout } from '@/layouts'; import { RenderResult, render } from '@testing-library/react'; import { createDefaultAdapter } from '@/dateAdapters'; @@ -19,7 +19,7 @@ const daysOfWeek = [ 'Saturday', ]; -const hook: CalendarState = { +const hook: CalendarContextState = { currentMonth: new Date(), dateAdapter: createDefaultAdapter(), getDaysOfWeek: () => daysOfWeek, diff --git a/packages/Schedulely/src/layouts/monthLayout/MonthLayout.tsx b/packages/Schedulely/src/layouts/monthLayout/MonthLayout.tsx index 267ff833..f10dfb2c 100644 --- a/packages/Schedulely/src/layouts/monthLayout/MonthLayout.tsx +++ b/packages/Schedulely/src/layouts/monthLayout/MonthLayout.tsx @@ -24,10 +24,7 @@ export const MonthLayout = () => { events={week.events} daysInweek={week.daysInWeek} /> - + ))} diff --git a/packages/Schedulely/src/layouts/weekLayout/WeekLayout.tsx b/packages/Schedulely/src/layouts/weekLayout/WeekLayout.tsx index 4ba77a5e..18372e86 100644 --- a/packages/Schedulely/src/layouts/weekLayout/WeekLayout.tsx +++ b/packages/Schedulely/src/layouts/weekLayout/WeekLayout.tsx @@ -1,4 +1,3 @@ -import { InternalCalendarEvent } from '@/types/InternalCalendarEvent'; import { useActions, useCalendar, @@ -8,14 +7,13 @@ import { interface WeekLayoutProps { dates: Date[]; - eventsOnDays: { date: Date; events: InternalCalendarEvent[] }[]; } /** * This component controls the layout of an individual weeks worth of days * @returns WeekLayout Component */ -export const WeekLayout = ({ dates, eventsOnDays }: WeekLayoutProps) => { +export const WeekLayout = ({ dates }: WeekLayoutProps) => { const { dateAdapter, currentMonth } = useCalendar(); const { dayComponent: DayComponent } = useComponents(); const { onMoreEventClick } = useActions(); diff --git a/packages/Schedulely/src/providers/ActionProvider.tsx b/packages/Schedulely/src/providers/ActionProvider.tsx index 6de2f839..7080c3ee 100644 --- a/packages/Schedulely/src/providers/ActionProvider.tsx +++ b/packages/Schedulely/src/providers/ActionProvider.tsx @@ -1,11 +1,11 @@ -import { ActionState, InternalCalendarEvent } from '@/types'; +import { ActionContextState, InternalCalendarEvent } from '@/types'; import { PropsWithChildren, createContext, useCallback } from 'react'; -export const ActionContext = createContext(null); +export const ActionContext = createContext(null); ActionContext.displayName = 'ActionContext'; interface ActionProviderProps { - actions?: Partial; + actions?: Partial; } /** @@ -42,7 +42,7 @@ export const ActionProvider = ({ onMonthChangeClick, ]); - const context: ActionState = { + const context: ActionContextState = { onEventClick: memoizedOnEventClick, onMoreEventClick: memoizedOnMoreEventClick, onMonthChangeClick: memoizedOnMonthChangeClick, diff --git a/packages/Schedulely/src/providers/CalendarProvider.tsx b/packages/Schedulely/src/providers/CalendarProvider.tsx index e0bc17ba..e570885b 100644 --- a/packages/Schedulely/src/providers/CalendarProvider.tsx +++ b/packages/Schedulely/src/providers/CalendarProvider.tsx @@ -1,6 +1,6 @@ import { + CalendarContextState, CalendarEvent, - CalendarState, ComponentSize, DateTimeAdapter, InternalCalendarEvent, @@ -14,7 +14,7 @@ import { useState, } from 'react'; -export const CalendarContext = createContext(null); +export const CalendarContext = createContext(null); CalendarContext.displayName = 'CalendarContext'; interface CalendarProviderProps { @@ -109,7 +109,7 @@ export const CalendarProvider = ({ [dateAdapter] ); - const contextValue: CalendarState = { + const contextValue: CalendarContextState = { currentMonth, dateAdapter, getDaysOfWeek, diff --git a/packages/Schedulely/src/providers/HightlightProvider.tsx b/packages/Schedulely/src/providers/HightlightProvider.tsx index 05816e78..84f20038 100644 --- a/packages/Schedulely/src/providers/HightlightProvider.tsx +++ b/packages/Schedulely/src/providers/HightlightProvider.tsx @@ -1,7 +1,8 @@ -import { HighlightEventState } from '@/types'; +import { HighlightEventContextState } from '@/types'; import { ReactNode, createContext, useCallback, useState } from 'react'; -export const HighlightContext = createContext(null); +export const HighlightContext = + createContext(null); HighlightContext.displayName = 'HighlightContext'; /** @@ -19,7 +20,7 @@ export const HighlightProvider = ({ children }: { children: ReactNode }) => { [highlightedEvent] ); - const context: HighlightEventState = { + const context: HighlightEventContextState = { setHighlight: (eventId: string) => setHighlightedEvent(eventId), clearHighlight: () => setHighlightedEvent(undefined), isHighlighted, diff --git a/packages/Schedulely/src/types/SchedulelyProps.ts b/packages/Schedulely/src/types/SchedulelyProps.ts index f35415bd..58c13e9a 100644 --- a/packages/Schedulely/src/types/SchedulelyProps.ts +++ b/packages/Schedulely/src/types/SchedulelyProps.ts @@ -1,5 +1,5 @@ import { - ActionState, + ActionContextState, CalendarEvent, DateTimeAdapter, SchedulelyComponents, @@ -26,7 +26,7 @@ export interface SchedulelyProps { dark?: boolean; /** Schedulely actions */ - actions?: Partial; + actions?: Partial; /** Initial Date that Schedulely should be opened to */ initialDate?: string; diff --git a/packages/Schedulely/src/types/state/ActionState.ts b/packages/Schedulely/src/types/state/ActionContextState.ts similarity index 92% rename from packages/Schedulely/src/types/state/ActionState.ts rename to packages/Schedulely/src/types/state/ActionContextState.ts index d6d65d8a..188d925a 100644 --- a/packages/Schedulely/src/types/state/ActionState.ts +++ b/packages/Schedulely/src/types/state/ActionContextState.ts @@ -1,7 +1,7 @@ import { InternalCalendarEvent } from '../InternalCalendarEvent'; /** Represents the state of the ActionProvider */ -export interface ActionState { +export interface ActionContextState { /** function that will run when an event is clicked on */ onEventClick: (event: InternalCalendarEvent) => void; diff --git a/packages/Schedulely/src/types/state/CalendarState.ts b/packages/Schedulely/src/types/state/CalendarContextState.ts similarity index 95% rename from packages/Schedulely/src/types/state/CalendarState.ts rename to packages/Schedulely/src/types/state/CalendarContextState.ts index ce4b4431..ad5af3db 100644 --- a/packages/Schedulely/src/types/state/CalendarState.ts +++ b/packages/Schedulely/src/types/state/CalendarContextState.ts @@ -2,7 +2,7 @@ import { ComponentSize } from '../ComponentSize'; import { DateTimeAdapter } from '..'; import { InternalEventWeek } from '../InternalEventWeek'; -export type CalendarState = { +export type CalendarContextState = { /** The current visible month */ currentMonth: Date; diff --git a/packages/Schedulely/src/types/state/HighlightEventState.ts b/packages/Schedulely/src/types/state/HighlightEventContextState.ts similarity index 86% rename from packages/Schedulely/src/types/state/HighlightEventState.ts rename to packages/Schedulely/src/types/state/HighlightEventContextState.ts index 4f075fe6..55c0802d 100644 --- a/packages/Schedulely/src/types/state/HighlightEventState.ts +++ b/packages/Schedulely/src/types/state/HighlightEventContextState.ts @@ -1,4 +1,4 @@ -export interface HighlightEventState { +export interface HighlightEventContextState { /** Set the ID of the currently highlighted event */ setHighlight: (eventId: string) => void; diff --git a/packages/Schedulely/src/types/state/index.ts b/packages/Schedulely/src/types/state/index.ts index 0de9ed78..3ef4d0fe 100644 --- a/packages/Schedulely/src/types/state/index.ts +++ b/packages/Schedulely/src/types/state/index.ts @@ -2,8 +2,8 @@ * @file Automatically generated by barrelsby. */ -export * from './ActionState'; +export * from './ActionContextState'; export * from './BreakpointContextState'; -export * from './CalendarState'; +export * from './CalendarContextState'; export * from './EventIntersectionContextState'; -export * from './HighlightEventState'; +export * from './HighlightEventContextState'; From d63abbe88818e304a831aa1616ef02b0c7f3075a Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Wed, 26 Oct 2022 10:57:45 -0500 Subject: [PATCH 06/52] move date functions into date adapter --- .../dateAdapters/dateAdapter.spec.ts | 60 +++++++++++++++++++ packages/Schedulely/src/dateAdapters/date.ts | 8 +++ .../src/layouts/headerLayout/HeaderLayout.tsx | 23 +++---- packages/Schedulely/src/types/DateAdapter.ts | 6 ++ 4 files changed, 83 insertions(+), 14 deletions(-) diff --git a/packages/Schedulely/__tests__/dateAdapters/dateAdapter.spec.ts b/packages/Schedulely/__tests__/dateAdapters/dateAdapter.spec.ts index b2c10467..d24b6276 100644 --- a/packages/Schedulely/__tests__/dateAdapters/dateAdapter.spec.ts +++ b/packages/Schedulely/__tests__/dateAdapters/dateAdapter.spec.ts @@ -376,5 +376,65 @@ describe('Date Adapter', () => { } ); }); + + describe('getFirstDayOfMonth', () => { + it.each<{ + inputDate: Date; + expectedDate: Date; + }>([ + { + inputDate: new Date(2022, 1, 8, 0, 0, 0, 0), + expectedDate: new Date(2022, 1, 1, 0, 0, 0, 0), + }, + { + inputDate: new Date(2022, 6, 30, 0, 0, 0, 0), + expectedDate: new Date(2022, 6, 1, 0, 0, 0, 0), + }, + { + inputDate: new Date(2022, 3, 15, 0, 0, 0, 0), + expectedDate: new Date(2022, 3, 1, 0, 0, 0, 0), + }, + { + inputDate: new Date(2022, 12, 25, 0, 0, 0, 0), + expectedDate: new Date(2022, 12, 1, 0, 0, 0, 0), + }, + ])( + 'First of month for $inputDate returns $expectedDate', + ({ inputDate, expectedDate }) => { + const result = adapter.getFirstDayOfMonth(inputDate); + expect(result).toEqual(expectedDate); + } + ); + }); + + describe('getLastDayOfMonth', () => { + it.each<{ + inputIso: Date; + expectedDate: Date; + }>([ + { + inputIso: new Date(2022, 1, 8, 0, 0, 0, 0), + expectedDate: new Date(2022, 1, 28, 0, 0, 0, 0), + }, + { + inputIso: new Date(2022, 6, 7, 0, 0, 0, 0), + expectedDate: new Date(2022, 6, 31, 0, 0, 0, 0), + }, + { + inputIso: new Date(2022, 3, 15, 0, 0, 0, 0), + expectedDate: new Date(2022, 3, 30, 0, 0, 0, 0), + }, + { + inputIso: new Date(2022, 6, 11, 0, 0, 0, 0), + expectedDate: new Date(2022, 6, 31, 0, 0, 0, 0), + }, + ])( + 'Last of month for $inputIso returns $expectedDate', + ({ inputIso, expectedDate }) => { + const result = adapter.getLastDayOfMonth(inputIso); + expect(result).toEqual(expectedDate); + } + ); + }); }); }); diff --git a/packages/Schedulely/src/dateAdapters/date.ts b/packages/Schedulely/src/dateAdapters/date.ts index 6d6f1374..80a95cef 100644 --- a/packages/Schedulely/src/dateAdapters/date.ts +++ b/packages/Schedulely/src/dateAdapters/date.ts @@ -139,6 +139,12 @@ export const createDefaultAdapter = (locale = 'en'): DateTimeAdapter => { return targetDate >= dateOne && targetDate <= dateTwo; }; + const getFirstDayOfMonth = (date: Date) => + new Date(date.getFullYear(), date.getMonth(), 1); + + const getLastDayOfMonth = (date: Date) => + new Date(date.getFullYear(), date.getMonth() + 1, 0, 0, 0, 0); + return { getCalendarView, getDaysOfWeek, @@ -154,5 +160,7 @@ export const createDefaultAdapter = (locale = 'en'): DateTimeAdapter => { convertIsoToDate, isCurrentMonth, isDateBetween, + getFirstDayOfMonth, + getLastDayOfMonth, }; }; diff --git a/packages/Schedulely/src/layouts/headerLayout/HeaderLayout.tsx b/packages/Schedulely/src/layouts/headerLayout/HeaderLayout.tsx index 3da949d4..fad05e55 100644 --- a/packages/Schedulely/src/layouts/headerLayout/HeaderLayout.tsx +++ b/packages/Schedulely/src/layouts/headerLayout/HeaderLayout.tsx @@ -18,26 +18,21 @@ export const HeaderLayout = () => { onNextYear, onPrevYear, onPrevMonth, - dateAdapter: { getMonthName, getYear, isCurrentMonth }, + dateAdapter: { + getMonthName, + getYear, + isCurrentMonth, + getFirstDayOfMonth, + getLastDayOfMonth, + }, } = useCalendar(); const { onMonthChangeClick } = useActions(); const { headerComponent: Header } = useComponents(); const { breakpoint } = useBreakpoint(); useEffect(() => { - const firstOfMonth = new Date( - currentMonth.getFullYear(), - currentMonth.getMonth(), - 1 - ); - const lastOfMonth = new Date( - firstOfMonth.getFullYear(), - firstOfMonth.getMonth() + 1, - 1, - 0, - 0, - -1 - ); + const firstOfMonth = getFirstDayOfMonth(currentMonth); + const lastOfMonth = getLastDayOfMonth(currentMonth); onMonthChangeClick(firstOfMonth, lastOfMonth); }, [currentMonth, onMonthChangeClick]); diff --git a/packages/Schedulely/src/types/DateAdapter.ts b/packages/Schedulely/src/types/DateAdapter.ts index a974d5e7..03f10527 100644 --- a/packages/Schedulely/src/types/DateAdapter.ts +++ b/packages/Schedulely/src/types/DateAdapter.ts @@ -49,4 +49,10 @@ export interface DateTimeAdapter { /** Does the target date fall between the supplied dates */ isDateBetween: (targetDate: Date, dateOne: Date, dateTwo: Date) => boolean; + + /** Get the first day of the supplied month */ + getFirstDayOfMonth: (date: Date) => Date; + + /** Get the last day of the supplied month */ + getLastDayOfMonth: (date: Date) => Date; } From 68c2ee213ce5dc3ed2c80b72021716c1e6da6362 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Wed, 26 Oct 2022 11:56:35 -0500 Subject: [PATCH 07/52] extract grid functions from date adapter --- .../dateAdapters/dateAdapter.spec.ts | 71 ---------------- .../layouts/EventWeekLayout.spec.tsx | 82 +++++++++++++++++++ packages/Schedulely/src/dateAdapters/date.ts | 11 --- .../eventWeekLayout/EventWeekLayout.tsx | 13 ++- packages/Schedulely/src/types/DateAdapter.ts | 6 -- 5 files changed, 91 insertions(+), 92 deletions(-) create mode 100644 packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx diff --git a/packages/Schedulely/__tests__/dateAdapters/dateAdapter.spec.ts b/packages/Schedulely/__tests__/dateAdapters/dateAdapter.spec.ts index d24b6276..8174a00f 100644 --- a/packages/Schedulely/__tests__/dateAdapters/dateAdapter.spec.ts +++ b/packages/Schedulely/__tests__/dateAdapters/dateAdapter.spec.ts @@ -163,77 +163,6 @@ describe('Date Adapter', () => { ); }); - describe('getGridEndIndex', () => { - it.each<{ eventEnd: Date; endOfWeek: Date; expected: number }>([ - { - eventEnd: new Date(2022, 1, 11), - endOfWeek: new Date(2022, 1, 12), - expected: 7, - }, - { - // event ends after end of week - eventEnd: new Date(2022, 1, 13), - endOfWeek: new Date(2022, 1, 12), - expected: 8, - }, - { - eventEnd: new Date(2022, 1, 9), - endOfWeek: new Date(2022, 1, 12), - expected: 5, - }, - { - // event ends on Sunday - eventEnd: new Date(2021, 8, 26), - endOfWeek: new Date(2021, 9, 2), - expected: 2, - }, - { - // event that starts and ends on Sunday - eventEnd: new Date(2022, 0, 2), - endOfWeek: new Date(2022, 0, 8), - expected: 2, - }, - ])( - '$eventEnd with $endOfWeek returns $expected', - ({ eventEnd, endOfWeek, expected }) => { - const result = adapter.getGridEndIndex(eventEnd, endOfWeek); - expect(result).toBe(expected); - } - ); - }); - - describe('getGridStartIndex', () => { - it.each<{ eventStart: Date; startOfWeek: Date; expected: number }>([ - { - eventStart: new Date(2022, 1, 7), - startOfWeek: new Date(2022, 1, 6), - expected: 2, - }, - { - eventStart: new Date(2022, 1, 9), - startOfWeek: new Date(2022, 1, 6), - expected: 4, - }, - { - eventStart: new Date(2022, 3, 10), - startOfWeek: new Date(2022, 3, 10), - expected: 1, - }, - { - // event that starts and ends on Sunday - eventStart: new Date(2022, 0, 2), - startOfWeek: new Date(2022, 0, 2), - expected: 1, - }, - ])( - '$eventStart with $startOfWeek returns $expected', - ({ eventStart, startOfWeek, expected }) => { - const result = adapter.getGridStartIndex(eventStart, startOfWeek); - expect(result).toBe(expected); - } - ); - }); - describe('isEventInWeek', () => { it.each<{ message: string; diff --git a/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx new file mode 100644 index 00000000..7f047f7d --- /dev/null +++ b/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx @@ -0,0 +1,82 @@ +import { BreakpointProvider } from '@/providers'; +import { CalendarContextState, ComponentSize } from '@/types'; +import { DayOfWeekLayout } from '@/layouts'; +import { RenderResult, render } from '@testing-library/react'; +import { createDefaultAdapter } from '@/dateAdapters'; +import { useCalendar } from '../../src/hooks/useCalendar'; +import React from 'react'; + +describe('EventWeekLayout', () => { + it('skip', () => { + expect(true).toBe(true); + }); + // describe('getGridEndIndex', () => { + // it.each<{ eventEnd: Date; endOfWeek: Date; expected: number }>([ + // { + // eventEnd: new Date(2022, 1, 11), + // endOfWeek: new Date(2022, 1, 12), + // expected: 7, + // }, + // { + // // event ends after end of week + // eventEnd: new Date(2022, 1, 13), + // endOfWeek: new Date(2022, 1, 12), + // expected: 8, + // }, + // { + // eventEnd: new Date(2022, 1, 9), + // endOfWeek: new Date(2022, 1, 12), + // expected: 5, + // }, + // { + // // event ends on Sunday + // eventEnd: new Date(2021, 8, 26), + // endOfWeek: new Date(2021, 9, 2), + // expected: 2, + // }, + // { + // // event that starts and ends on Sunday + // eventEnd: new Date(2022, 0, 2), + // endOfWeek: new Date(2022, 0, 8), + // expected: 2, + // }, + // ])( + // '$eventEnd with $endOfWeek returns $expected', + // ({ eventEnd, endOfWeek, expected }) => { + // const result = adapter.getGridEndIndex(eventEnd, endOfWeek); + // expect(result).toBe(expected); + // } + // ); + // }); + // describe('getGridStartIndex', () => { + // it.each<{ eventStart: Date; startOfWeek: Date; expected: number }>([ + // { + // eventStart: new Date(2022, 1, 7), + // startOfWeek: new Date(2022, 1, 6), + // expected: 2, + // }, + // { + // eventStart: new Date(2022, 1, 9), + // startOfWeek: new Date(2022, 1, 6), + // expected: 4, + // }, + // { + // eventStart: new Date(2022, 3, 10), + // startOfWeek: new Date(2022, 3, 10), + // expected: 1, + // }, + // { + // // event that starts and ends on Sunday + // eventStart: new Date(2022, 0, 2), + // startOfWeek: new Date(2022, 0, 2), + // expected: 1, + // }, + // ])( + // '$eventStart with $startOfWeek returns $expected', + // ({ eventStart, startOfWeek, expected }) => { + // const result = adapter.getGridStartIndex(eventStart, startOfWeek); + // expect(result).toBe(expected); + // } + // ); + // }); +}); diff --git a/packages/Schedulely/src/dateAdapters/date.ts b/packages/Schedulely/src/dateAdapters/date.ts index 80a95cef..f9662d34 100644 --- a/packages/Schedulely/src/dateAdapters/date.ts +++ b/packages/Schedulely/src/dateAdapters/date.ts @@ -103,15 +103,6 @@ export const createDefaultAdapter = (locale = 'en'): DateTimeAdapter => { const addMonthsToDate = (date: Date, amount: number) => new Date(date.getFullYear(), date.getMonth() + amount, 1); - const getGridStartIndex = (eventDate: Date, startOfWeek: Date) => - eventDate <= startOfWeek ? 1 : eventDate.getDay() + 1; //add one because css-grid isn't zero-index'd - - const getGridEndIndex = (eventEndDate: Date, endOfWeek: Date) => { - if (eventEndDate > endOfWeek) return 8; - const end = eventEndDate.getDay() + 2; // add two because css-grid isn't zero index'd, and day of week is zero-index'd - return end; - }; - const isEventInWeek = ( eventStartDate: Date, eventEndDate: Date, @@ -154,8 +145,6 @@ export const createDefaultAdapter = (locale = 'en'): DateTimeAdapter => { isSameMonth, isDateToday, addMonthsToDate, - getGridEndIndex, - getGridStartIndex, isEventInWeek, convertIsoToDate, isCurrentMonth, diff --git a/packages/Schedulely/src/layouts/eventWeekLayout/EventWeekLayout.tsx b/packages/Schedulely/src/layouts/eventWeekLayout/EventWeekLayout.tsx index 68881223..58de9704 100644 --- a/packages/Schedulely/src/layouts/eventWeekLayout/EventWeekLayout.tsx +++ b/packages/Schedulely/src/layouts/eventWeekLayout/EventWeekLayout.tsx @@ -1,7 +1,6 @@ import { InternalCalendarEvent } from '@/types/InternalCalendarEvent'; import { useActions, - useCalendar, useComponents, useEventHighlight, useEventIntersection, @@ -12,14 +11,20 @@ interface EventLayoutProps { daysInweek: Date[]; } +const getGridStartIndex = (eventDate: Date, startOfWeek: Date) => + eventDate <= startOfWeek ? 1 : eventDate.getDay() + 1; //add one because css-grid isn't zero-index'd + +const getGridEndIndex = (eventEndDate: Date, endOfWeek: Date) => { + if (eventEndDate > endOfWeek) return 8; + const end = eventEndDate.getDay() + 2; // add two because css-grid isn't zero index'd, and day of week is zero-index'd + return end; +}; + /** * This component controls the layout of an individual events within a week * @returns EventLayout Component */ export const EventWeekLayout = ({ events, daysInweek }: EventLayoutProps) => { - const { - dateAdapter: { getGridStartIndex, getGridEndIndex }, - } = useCalendar(); const { eventComponent: EventComponent } = useComponents(); const { setHighlight, clearHighlight, isHighlighted } = useEventHighlight(); const { onEventClick } = useActions(); diff --git a/packages/Schedulely/src/types/DateAdapter.ts b/packages/Schedulely/src/types/DateAdapter.ts index 03f10527..fb8dbefb 100644 --- a/packages/Schedulely/src/types/DateAdapter.ts +++ b/packages/Schedulely/src/types/DateAdapter.ts @@ -16,12 +16,6 @@ export interface DateTimeAdapter { /** Get full names of all days of the week */ getDaysOfWeek: (componentSize: ComponentSize) => string[]; - /** Get the day of week grid index for the end of the event. Used for positioning within the Week css-grid. */ - getGridEndIndex: (eventEndDate: Date, endOfWeek: Date) => number; - - /** Get the day of week index for the start of the event. Used for positioning within the Week css-grid */ - getGridStartIndex: (eventDate: Date, startOfWeek: Date) => number; - /** Get the full name of the month for a given date */ getMonthName: (date: Date) => string; From 68d8a30d1af6dfae0bc8ff901662dbc3993b4c37 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Wed, 26 Oct 2022 12:47:29 -0500 Subject: [PATCH 08/52] move computed props into context --- .../src/layouts/headerLayout/HeaderLayout.tsx | 24 ++++++-------- .../src/layouts/weekLayout/WeekLayout.tsx | 13 +++++--- .../src/providers/CalendarProvider.tsx | 32 +++++++++++++------ .../src/types/state/CalendarContextState.ts | 10 ++++-- 4 files changed, 48 insertions(+), 31 deletions(-) diff --git a/packages/Schedulely/src/layouts/headerLayout/HeaderLayout.tsx b/packages/Schedulely/src/layouts/headerLayout/HeaderLayout.tsx index fad05e55..3216ff42 100644 --- a/packages/Schedulely/src/layouts/headerLayout/HeaderLayout.tsx +++ b/packages/Schedulely/src/layouts/headerLayout/HeaderLayout.tsx @@ -13,36 +13,32 @@ import { useEffect } from 'react'; */ export const HeaderLayout = () => { const { - currentMonth, + currentDate, onNextMonth, onNextYear, onPrevYear, onPrevMonth, - dateAdapter: { - getMonthName, - getYear, - isCurrentMonth, - getFirstDayOfMonth, - getLastDayOfMonth, - }, + currentMonth, + currentYear, + dateAdapter: { isCurrentMonth, getFirstDayOfMonth, getLastDayOfMonth }, } = useCalendar(); const { onMonthChangeClick } = useActions(); const { headerComponent: Header } = useComponents(); const { breakpoint } = useBreakpoint(); useEffect(() => { - const firstOfMonth = getFirstDayOfMonth(currentMonth); - const lastOfMonth = getLastDayOfMonth(currentMonth); + const firstOfMonth = getFirstDayOfMonth(currentDate); + const lastOfMonth = getLastDayOfMonth(currentDate); onMonthChangeClick(firstOfMonth, lastOfMonth); - }, [currentMonth, onMonthChangeClick]); + }, [currentDate, onMonthChangeClick]); useKeyboardControls(); return (
{ - const { dateAdapter, currentMonth } = useCalendar(); + const { + dateAdapter: { isDateToday, isSameMonth, getDayNumber }, + currentDate, + } = useCalendar(); const { dayComponent: DayComponent } = useComponents(); const { onMoreEventClick } = useActions(); const { getEventsOnDate } = useEventIntersection(); @@ -25,12 +28,12 @@ export const WeekLayout = ({ dates }: WeekLayoutProps) => {
!x.visible).length > 0 } diff --git a/packages/Schedulely/src/providers/CalendarProvider.tsx b/packages/Schedulely/src/providers/CalendarProvider.tsx index e570885b..9a5f572a 100644 --- a/packages/Schedulely/src/providers/CalendarProvider.tsx +++ b/packages/Schedulely/src/providers/CalendarProvider.tsx @@ -34,18 +34,28 @@ export const CalendarProvider = ({ calendarEvents, children, }: PropsWithChildren) => { - const [currentMonth, setCurrentMonth] = useState( + const [currentDate, setCurrentDate] = useState( dateAdapter.convertIsoToDate(initialDate) ); + const currentMonth = useMemo( + () => dateAdapter.getMonthName(currentDate), + [currentDate] + ); + + const currentYear = useMemo( + () => dateAdapter.getYear(currentDate), + [currentDate] + ); + const getDaysOfWeek = useCallback( (componentSize: ComponentSize) => dateAdapter.getDaysOfWeek(componentSize), [dateAdapter] ); const calendarView = useMemo( - () => dateAdapter.getCalendarView(currentMonth), - [currentMonth, dateAdapter] + () => dateAdapter.getCalendarView(currentDate), + [currentDate, dateAdapter] ); const events = useMemo( @@ -64,10 +74,10 @@ export const CalendarProvider = ({ }) .filter( (event) => - dateAdapter.isSameMonth(event.start, currentMonth) || - dateAdapter.isSameMonth(event.end, currentMonth) + dateAdapter.isSameMonth(event.start, currentDate) || + dateAdapter.isSameMonth(event.end, currentDate) ), - [currentMonth, calendarEvents, dateAdapter] + [currentDate, calendarEvents, dateAdapter] ); const calendarWithEvents = useMemo( @@ -90,27 +100,29 @@ export const CalendarProvider = ({ ); const onNextMonth = useCallback( - () => setCurrentMonth((month) => dateAdapter.addMonthsToDate(month, 1)), + () => setCurrentDate((month) => dateAdapter.addMonthsToDate(month, 1)), [dateAdapter] ); const onNextYear = useCallback( - () => setCurrentMonth((month) => dateAdapter.addMonthsToDate(month, 12)), + () => setCurrentDate((month) => dateAdapter.addMonthsToDate(month, 12)), [dateAdapter] ); const onPrevMonth = useCallback( - () => setCurrentMonth((month) => dateAdapter.addMonthsToDate(month, -1)), + () => setCurrentDate((month) => dateAdapter.addMonthsToDate(month, -1)), [dateAdapter] ); const onPrevYear = useCallback( - () => setCurrentMonth((month) => dateAdapter.addMonthsToDate(month, -12)), + () => setCurrentDate((month) => dateAdapter.addMonthsToDate(month, -12)), [dateAdapter] ); const contextValue: CalendarContextState = { + currentDate, currentMonth, + currentYear, dateAdapter, getDaysOfWeek, onNextMonth, diff --git a/packages/Schedulely/src/types/state/CalendarContextState.ts b/packages/Schedulely/src/types/state/CalendarContextState.ts index ad5af3db..c673b0a1 100644 --- a/packages/Schedulely/src/types/state/CalendarContextState.ts +++ b/packages/Schedulely/src/types/state/CalendarContextState.ts @@ -3,8 +3,14 @@ import { DateTimeAdapter } from '..'; import { InternalEventWeek } from '../InternalEventWeek'; export type CalendarContextState = { - /** The current visible month */ - currentMonth: Date; + /** The current active date (this controls calendar position) */ + currentDate: Date; + + /** The current active month */ + currentMonth: string; + + /** The current active year */ + currentYear: number; /** The DateTimeAdapter that is being utilized */ dateAdapter: DateTimeAdapter; From 80f4de24f17223468f3a85b0eeba8278e91def64 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Wed, 26 Oct 2022 13:44:05 -0500 Subject: [PATCH 09/52] fix day header misplacement --- .../Schedulely/src/layouts/dayOfWeekLayout/DayOfWeekLayout.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/Schedulely/src/layouts/dayOfWeekLayout/DayOfWeekLayout.tsx b/packages/Schedulely/src/layouts/dayOfWeekLayout/DayOfWeekLayout.tsx index b04ddaa6..7f6b596d 100644 --- a/packages/Schedulely/src/layouts/dayOfWeekLayout/DayOfWeekLayout.tsx +++ b/packages/Schedulely/src/layouts/dayOfWeekLayout/DayOfWeekLayout.tsx @@ -14,7 +14,7 @@ export const DayOfWeekLayout = () => { {getDaysOfWeek(breakpoint).map((dayOfWeek, idx) => (
{/* wrap with extra div so we can control borders without touching the DayOfWeek component */} - {dayOfWeek} +
{dayOfWeek}
))}
From 5e9379087d1bcae9e200ecce01c3bb1b9d249a94 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Wed, 26 Oct 2022 13:47:27 -0500 Subject: [PATCH 10/52] move keyboard control init --- packages/Schedulely/src/layouts/headerLayout/HeaderLayout.tsx | 2 -- packages/Schedulely/src/layouts/monthLayout/MonthLayout.tsx | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/Schedulely/src/layouts/headerLayout/HeaderLayout.tsx b/packages/Schedulely/src/layouts/headerLayout/HeaderLayout.tsx index 3216ff42..477c25e7 100644 --- a/packages/Schedulely/src/layouts/headerLayout/HeaderLayout.tsx +++ b/packages/Schedulely/src/layouts/headerLayout/HeaderLayout.tsx @@ -32,8 +32,6 @@ export const HeaderLayout = () => { onMonthChangeClick(firstOfMonth, lastOfMonth); }, [currentDate, onMonthChangeClick]); - useKeyboardControls(); - return (
{ const { calendarWithEvents } = useCalendar(); + useKeyboardControls(); return (
From ea62f1075ea396dc4ae593f419100f2526b93660 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Wed, 26 Oct 2022 14:01:22 -0500 Subject: [PATCH 11/52] move a more calculated values into context --- .../src/layouts/headerLayout/HeaderLayout.tsx | 21 +++------------- .../src/providers/CalendarProvider.tsx | 25 +++++++++++++++++++ .../src/types/state/CalendarContextState.ts | 9 +++++++ 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/packages/Schedulely/src/layouts/headerLayout/HeaderLayout.tsx b/packages/Schedulely/src/layouts/headerLayout/HeaderLayout.tsx index 477c25e7..61a32ed0 100644 --- a/packages/Schedulely/src/layouts/headerLayout/HeaderLayout.tsx +++ b/packages/Schedulely/src/layouts/headerLayout/HeaderLayout.tsx @@ -1,11 +1,4 @@ -import { - useActions, - useBreakpoint, - useCalendar, - useComponents, - useKeyboardControls, -} from '@/hooks'; -import { useEffect } from 'react'; +import { useBreakpoint, useCalendar, useComponents } from '@/hooks'; /** * This component controls the layout of the header that display the controls and the current month/year description @@ -13,28 +6,20 @@ import { useEffect } from 'react'; */ export const HeaderLayout = () => { const { - currentDate, onNextMonth, onNextYear, onPrevYear, onPrevMonth, currentMonth, currentYear, - dateAdapter: { isCurrentMonth, getFirstDayOfMonth, getLastDayOfMonth }, + isCurrentMonth, } = useCalendar(); - const { onMonthChangeClick } = useActions(); const { headerComponent: Header } = useComponents(); const { breakpoint } = useBreakpoint(); - useEffect(() => { - const firstOfMonth = getFirstDayOfMonth(currentDate); - const lastOfMonth = getLastDayOfMonth(currentDate); - onMonthChangeClick(firstOfMonth, lastOfMonth); - }, [currentDate, onMonthChangeClick]); - return (
(null); CalendarContext.displayName = 'CalendarContext'; @@ -34,6 +36,8 @@ export const CalendarProvider = ({ calendarEvents, children, }: PropsWithChildren) => { + const { onMonthChangeClick } = useActions(); + const [currentDate, setCurrentDate] = useState( dateAdapter.convertIsoToDate(initialDate) ); @@ -48,6 +52,11 @@ export const CalendarProvider = ({ [currentDate] ); + const isCurrentMonth = useMemo( + () => dateAdapter.isCurrentMonth(currentDate), + [currentDate] + ); + const getDaysOfWeek = useCallback( (componentSize: ComponentSize) => dateAdapter.getDaysOfWeek(componentSize), [dateAdapter] @@ -80,6 +89,19 @@ export const CalendarProvider = ({ [currentDate, calendarEvents, dateAdapter] ); + const firstDateInView = useMemo(() => calendarView[0][0], [calendarView]); + const lastDateInView = useMemo( + () => + calendarView[calendarView.length - 1][ + calendarView[calendarView.length - 1].length - 1 + ], + [calendarView] + ); + + useEffect(() => { + onMonthChangeClick(firstDateInView, lastDateInView); + }, [firstDateInView, lastDateInView]); + const calendarWithEvents = useMemo( () => calendarView.map((week) => ({ @@ -124,6 +146,9 @@ export const CalendarProvider = ({ currentMonth, currentYear, dateAdapter, + firstDateInView, + lastDateInView, + isCurrentMonth, getDaysOfWeek, onNextMonth, onNextYear, diff --git a/packages/Schedulely/src/types/state/CalendarContextState.ts b/packages/Schedulely/src/types/state/CalendarContextState.ts index c673b0a1..454422b4 100644 --- a/packages/Schedulely/src/types/state/CalendarContextState.ts +++ b/packages/Schedulely/src/types/state/CalendarContextState.ts @@ -15,6 +15,15 @@ export type CalendarContextState = { /** The DateTimeAdapter that is being utilized */ dateAdapter: DateTimeAdapter; + /** The first visible date on the active month */ + firstDateInView: Date; + + /** The last visible date on the active month */ + lastDateInView: Date; + + /** Indicates if the active month is the current month */ + isCurrentMonth: boolean; + /** Array with localized names of the days of the week */ getDaysOfWeek: (componentSize: ComponentSize) => string[]; From d5c2af67c185b155b967091c8b0bcd8c32d79814 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Wed, 26 Oct 2022 14:05:18 -0500 Subject: [PATCH 12/52] refactor away --- .../src/providers/CalendarProvider.tsx | 16 +++++----------- .../src/types/state/CalendarContextState.ts | 6 ------ 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/packages/Schedulely/src/providers/CalendarProvider.tsx b/packages/Schedulely/src/providers/CalendarProvider.tsx index d2cce406..21d60150 100644 --- a/packages/Schedulely/src/providers/CalendarProvider.tsx +++ b/packages/Schedulely/src/providers/CalendarProvider.tsx @@ -89,18 +89,14 @@ export const CalendarProvider = ({ [currentDate, calendarEvents, dateAdapter] ); - const firstDateInView = useMemo(() => calendarView[0][0], [calendarView]); - const lastDateInView = useMemo( - () => + useEffect(() => { + const firstDateInView = calendarView[0][0]; + const lastDateInView = calendarView[calendarView.length - 1][ calendarView[calendarView.length - 1].length - 1 - ], - [calendarView] - ); - - useEffect(() => { + ]; onMonthChangeClick(firstDateInView, lastDateInView); - }, [firstDateInView, lastDateInView]); + }, [onMonthChangeClick, calendarView]); const calendarWithEvents = useMemo( () => @@ -146,8 +142,6 @@ export const CalendarProvider = ({ currentMonth, currentYear, dateAdapter, - firstDateInView, - lastDateInView, isCurrentMonth, getDaysOfWeek, onNextMonth, diff --git a/packages/Schedulely/src/types/state/CalendarContextState.ts b/packages/Schedulely/src/types/state/CalendarContextState.ts index 454422b4..4e54fa55 100644 --- a/packages/Schedulely/src/types/state/CalendarContextState.ts +++ b/packages/Schedulely/src/types/state/CalendarContextState.ts @@ -15,12 +15,6 @@ export type CalendarContextState = { /** The DateTimeAdapter that is being utilized */ dateAdapter: DateTimeAdapter; - /** The first visible date on the active month */ - firstDateInView: Date; - - /** The last visible date on the active month */ - lastDateInView: Date; - /** Indicates if the active month is the current month */ isCurrentMonth: boolean; From 6fb3e1674e3bf62705c8aad8d2160aea928f43a6 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Wed, 26 Oct 2022 14:06:30 -0500 Subject: [PATCH 13/52] remove dead tests --- .../dateAdapters/dateAdapter.spec.ts | 60 ------------------- packages/Schedulely/src/dateAdapters/date.ts | 8 --- packages/Schedulely/src/types/DateAdapter.ts | 6 -- 3 files changed, 74 deletions(-) diff --git a/packages/Schedulely/__tests__/dateAdapters/dateAdapter.spec.ts b/packages/Schedulely/__tests__/dateAdapters/dateAdapter.spec.ts index 8174a00f..07004bad 100644 --- a/packages/Schedulely/__tests__/dateAdapters/dateAdapter.spec.ts +++ b/packages/Schedulely/__tests__/dateAdapters/dateAdapter.spec.ts @@ -305,65 +305,5 @@ describe('Date Adapter', () => { } ); }); - - describe('getFirstDayOfMonth', () => { - it.each<{ - inputDate: Date; - expectedDate: Date; - }>([ - { - inputDate: new Date(2022, 1, 8, 0, 0, 0, 0), - expectedDate: new Date(2022, 1, 1, 0, 0, 0, 0), - }, - { - inputDate: new Date(2022, 6, 30, 0, 0, 0, 0), - expectedDate: new Date(2022, 6, 1, 0, 0, 0, 0), - }, - { - inputDate: new Date(2022, 3, 15, 0, 0, 0, 0), - expectedDate: new Date(2022, 3, 1, 0, 0, 0, 0), - }, - { - inputDate: new Date(2022, 12, 25, 0, 0, 0, 0), - expectedDate: new Date(2022, 12, 1, 0, 0, 0, 0), - }, - ])( - 'First of month for $inputDate returns $expectedDate', - ({ inputDate, expectedDate }) => { - const result = adapter.getFirstDayOfMonth(inputDate); - expect(result).toEqual(expectedDate); - } - ); - }); - - describe('getLastDayOfMonth', () => { - it.each<{ - inputIso: Date; - expectedDate: Date; - }>([ - { - inputIso: new Date(2022, 1, 8, 0, 0, 0, 0), - expectedDate: new Date(2022, 1, 28, 0, 0, 0, 0), - }, - { - inputIso: new Date(2022, 6, 7, 0, 0, 0, 0), - expectedDate: new Date(2022, 6, 31, 0, 0, 0, 0), - }, - { - inputIso: new Date(2022, 3, 15, 0, 0, 0, 0), - expectedDate: new Date(2022, 3, 30, 0, 0, 0, 0), - }, - { - inputIso: new Date(2022, 6, 11, 0, 0, 0, 0), - expectedDate: new Date(2022, 6, 31, 0, 0, 0, 0), - }, - ])( - 'Last of month for $inputIso returns $expectedDate', - ({ inputIso, expectedDate }) => { - const result = adapter.getLastDayOfMonth(inputIso); - expect(result).toEqual(expectedDate); - } - ); - }); }); }); diff --git a/packages/Schedulely/src/dateAdapters/date.ts b/packages/Schedulely/src/dateAdapters/date.ts index f9662d34..59ccc859 100644 --- a/packages/Schedulely/src/dateAdapters/date.ts +++ b/packages/Schedulely/src/dateAdapters/date.ts @@ -130,12 +130,6 @@ export const createDefaultAdapter = (locale = 'en'): DateTimeAdapter => { return targetDate >= dateOne && targetDate <= dateTwo; }; - const getFirstDayOfMonth = (date: Date) => - new Date(date.getFullYear(), date.getMonth(), 1); - - const getLastDayOfMonth = (date: Date) => - new Date(date.getFullYear(), date.getMonth() + 1, 0, 0, 0, 0); - return { getCalendarView, getDaysOfWeek, @@ -149,7 +143,5 @@ export const createDefaultAdapter = (locale = 'en'): DateTimeAdapter => { convertIsoToDate, isCurrentMonth, isDateBetween, - getFirstDayOfMonth, - getLastDayOfMonth, }; }; diff --git a/packages/Schedulely/src/types/DateAdapter.ts b/packages/Schedulely/src/types/DateAdapter.ts index fb8dbefb..9f69f4f2 100644 --- a/packages/Schedulely/src/types/DateAdapter.ts +++ b/packages/Schedulely/src/types/DateAdapter.ts @@ -43,10 +43,4 @@ export interface DateTimeAdapter { /** Does the target date fall between the supplied dates */ isDateBetween: (targetDate: Date, dateOne: Date, dateTwo: Date) => boolean; - - /** Get the first day of the supplied month */ - getFirstDayOfMonth: (date: Date) => Date; - - /** Get the last day of the supplied month */ - getLastDayOfMonth: (date: Date) => Date; } From 88db65b943c5d39dec76e2b82387541c62eba3ec Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Wed, 26 Oct 2022 14:27:41 -0500 Subject: [PATCH 14/52] extract day of week into context --- .../__tests__/layouts/DayOfWeekLayout.spec.tsx | 7 +++++-- .../src/layouts/dayOfWeekLayout/DayOfWeekLayout.tsx | 7 +++---- .../Schedulely/src/providers/CalendarProvider.tsx | 13 +++++++------ .../src/types/state/CalendarContextState.ts | 4 ++-- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx index 4c52b59e..669684a7 100644 --- a/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx @@ -20,9 +20,12 @@ const daysOfWeek = [ ]; const hook: CalendarContextState = { - currentMonth: new Date(), + currentDate: new Date(), + currentMonth: '', + currentYear: 1, + isCurrentMonth: false, dateAdapter: createDefaultAdapter(), - getDaysOfWeek: () => daysOfWeek, + daysOfWeek: daysOfWeek, onNextMonth: () => null, onPrevMonth: () => null, onNextYear: () => null, diff --git a/packages/Schedulely/src/layouts/dayOfWeekLayout/DayOfWeekLayout.tsx b/packages/Schedulely/src/layouts/dayOfWeekLayout/DayOfWeekLayout.tsx index 7f6b596d..307c2741 100644 --- a/packages/Schedulely/src/layouts/dayOfWeekLayout/DayOfWeekLayout.tsx +++ b/packages/Schedulely/src/layouts/dayOfWeekLayout/DayOfWeekLayout.tsx @@ -1,17 +1,16 @@ -import { useBreakpoint, useCalendar } from '@/hooks'; +import { useCalendar } from '@/hooks'; /** * This component controls the layout of the names of the days of the week at the top of the calendar * @returns DayOfWeekLayout Component */ export const DayOfWeekLayout = () => { - const { getDaysOfWeek } = useCalendar(); - const { breakpoint } = useBreakpoint(); + const { daysOfWeek } = useCalendar(); return (
{/* We cheat a bit here and use the index as part of the key. This is because short day names can be identical. */} - {getDaysOfWeek(breakpoint).map((dayOfWeek, idx) => ( + {daysOfWeek.map((dayOfWeek, idx) => (
{/* wrap with extra div so we can control borders without touching the DayOfWeek component */}
{dayOfWeek}
diff --git a/packages/Schedulely/src/providers/CalendarProvider.tsx b/packages/Schedulely/src/providers/CalendarProvider.tsx index 21d60150..a9044bd3 100644 --- a/packages/Schedulely/src/providers/CalendarProvider.tsx +++ b/packages/Schedulely/src/providers/CalendarProvider.tsx @@ -14,7 +14,7 @@ import { useMemo, useState, } from 'react'; -import { useActions } from '@/hooks'; +import { useActions, useBreakpoint } from '@/hooks'; export const CalendarContext = createContext(null); CalendarContext.displayName = 'CalendarContext'; @@ -37,6 +37,7 @@ export const CalendarProvider = ({ children, }: PropsWithChildren) => { const { onMonthChangeClick } = useActions(); + const { breakpoint } = useBreakpoint(); const [currentDate, setCurrentDate] = useState( dateAdapter.convertIsoToDate(initialDate) @@ -57,9 +58,9 @@ export const CalendarProvider = ({ [currentDate] ); - const getDaysOfWeek = useCallback( - (componentSize: ComponentSize) => dateAdapter.getDaysOfWeek(componentSize), - [dateAdapter] + const daysOfWeek = useMemo( + () => dateAdapter.getDaysOfWeek(breakpoint), + [breakpoint] ); const calendarView = useMemo( @@ -143,12 +144,12 @@ export const CalendarProvider = ({ currentYear, dateAdapter, isCurrentMonth, - getDaysOfWeek, + daysOfWeek, + calendarWithEvents, onNextMonth, onNextYear, onPrevMonth, onPrevYear, - calendarWithEvents, }; return ( diff --git a/packages/Schedulely/src/types/state/CalendarContextState.ts b/packages/Schedulely/src/types/state/CalendarContextState.ts index 4e54fa55..a048a7db 100644 --- a/packages/Schedulely/src/types/state/CalendarContextState.ts +++ b/packages/Schedulely/src/types/state/CalendarContextState.ts @@ -18,8 +18,8 @@ export type CalendarContextState = { /** Indicates if the active month is the current month */ isCurrentMonth: boolean; - /** Array with localized names of the days of the week */ - getDaysOfWeek: (componentSize: ComponentSize) => string[]; + /** The days of the week, for use in the calendar header */ + daysOfWeek: string[]; /** Advance the calendar one month */ onNextMonth: () => void; From c1f67c6758142f4a7b1c4e74ca88f4bd364c3dec Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Wed, 26 Oct 2022 15:12:32 -0500 Subject: [PATCH 15/52] setup test --- .../dateAdapters/dateAdapter.spec.ts | 2 +- .../layouts/DayOfWeekLayout.spec.tsx | 17 ++----------- .../__tests__/layouts/HeaderLayout.spec.tsx | 25 +++++++++++++++++++ .../testHelpers/component.testHelper.ts | 21 ++++++++++++++++ .../dateAdapter.testHelper.ts | 0 .../src/layouts/headerLayout/HeaderLayout.tsx | 3 ++- 6 files changed, 51 insertions(+), 17 deletions(-) create mode 100644 packages/Schedulely/__tests__/layouts/HeaderLayout.spec.tsx create mode 100644 packages/Schedulely/__tests__/testHelpers/component.testHelper.ts rename packages/Schedulely/__tests__/{dateAdapters => testHelpers}/dateAdapter.testHelper.ts (100%) diff --git a/packages/Schedulely/__tests__/dateAdapters/dateAdapter.spec.ts b/packages/Schedulely/__tests__/dateAdapters/dateAdapter.spec.ts index 07004bad..78d82022 100644 --- a/packages/Schedulely/__tests__/dateAdapters/dateAdapter.spec.ts +++ b/packages/Schedulely/__tests__/dateAdapters/dateAdapter.spec.ts @@ -9,7 +9,7 @@ import { getIsTodayTestCases, getMonthNameFromDateTestCases, getYearFromDateTestCases, -} from './dateAdapter.testHelper'; +} from '../testHelpers/dateAdapter.testHelper'; /** * Additional adapters should just be added to this array diff --git a/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx index 669684a7..51705b3c 100644 --- a/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx @@ -1,8 +1,7 @@ import { BreakpointProvider } from '@/providers'; -import { CalendarContextState, ComponentSize } from '@/types'; import { DayOfWeekLayout } from '@/layouts'; import { RenderResult, render } from '@testing-library/react'; -import { createDefaultAdapter } from '@/dateAdapters'; +import { getCalendarProviderProps } from '../testHelpers/component.testHelper'; import { useCalendar } from '../../src/hooks/useCalendar'; import React from 'react'; @@ -19,19 +18,7 @@ const daysOfWeek = [ 'Saturday', ]; -const hook: CalendarContextState = { - currentDate: new Date(), - currentMonth: '', - currentYear: 1, - isCurrentMonth: false, - dateAdapter: createDefaultAdapter(), - daysOfWeek: daysOfWeek, - onNextMonth: () => null, - onPrevMonth: () => null, - onNextYear: () => null, - onPrevYear: () => null, - calendarWithEvents: [], -}; +const hook = getCalendarProviderProps({ daysOfWeek: daysOfWeek }); describe('DayOfWeekLayout', () => { mockUseCalendar.mockReturnValue(hook); diff --git a/packages/Schedulely/__tests__/layouts/HeaderLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/HeaderLayout.spec.tsx new file mode 100644 index 00000000..bca2f81b --- /dev/null +++ b/packages/Schedulely/__tests__/layouts/HeaderLayout.spec.tsx @@ -0,0 +1,25 @@ +import { BreakpointProvider, ComponentProvider } from '@/providers'; +import { HeaderLayout } from '@/layouts'; +import { getCalendarProviderProps } from '../testHelpers/component.testHelper'; +import { render } from '@testing-library/react'; +import { useCalendar } from '../../src/hooks/useCalendar'; +import React from 'react'; + +jest.mock('../../src/hooks/useCalendar'); +const mockUseCalendar = useCalendar as jest.MockedFunction; +const hook = getCalendarProviderProps({}); + +describe('HeaderLayout', () => { + mockUseCalendar.mockReturnValue(hook); + + const testObject = render( + + + + + + ); + it('skip', () => { + expect(true).toBe(true); + }); +}); diff --git a/packages/Schedulely/__tests__/testHelpers/component.testHelper.ts b/packages/Schedulely/__tests__/testHelpers/component.testHelper.ts new file mode 100644 index 00000000..254443ba --- /dev/null +++ b/packages/Schedulely/__tests__/testHelpers/component.testHelper.ts @@ -0,0 +1,21 @@ +import { CalendarContextState } from '@/types'; +import { createDefaultAdapter } from '@/dateAdapters'; + +export const getCalendarProviderProps = ( + overrides: Partial +) => { + const hook: CalendarContextState = { + currentDate: new Date(), + currentMonth: '', + currentYear: 1, + isCurrentMonth: false, + dateAdapter: createDefaultAdapter(), + daysOfWeek: [], + onNextMonth: () => null, + onPrevMonth: () => null, + onNextYear: () => null, + onPrevYear: () => null, + calendarWithEvents: [], + }; + return { hook, ...overrides } as CalendarContextState; +}; diff --git a/packages/Schedulely/__tests__/dateAdapters/dateAdapter.testHelper.ts b/packages/Schedulely/__tests__/testHelpers/dateAdapter.testHelper.ts similarity index 100% rename from packages/Schedulely/__tests__/dateAdapters/dateAdapter.testHelper.ts rename to packages/Schedulely/__tests__/testHelpers/dateAdapter.testHelper.ts diff --git a/packages/Schedulely/src/layouts/headerLayout/HeaderLayout.tsx b/packages/Schedulely/src/layouts/headerLayout/HeaderLayout.tsx index 61a32ed0..55006f4d 100644 --- a/packages/Schedulely/src/layouts/headerLayout/HeaderLayout.tsx +++ b/packages/Schedulely/src/layouts/headerLayout/HeaderLayout.tsx @@ -1,7 +1,8 @@ import { useBreakpoint, useCalendar, useComponents } from '@/hooks'; /** - * This component controls the layout of the header that display the controls and the current month/year description + * This component controls the layout of the header that display the controls and the current month/year description. + * This is just a wrapper so we can access context and pass it into user supplied components * @returns HeaderLayout component */ export const HeaderLayout = () => { From 6c42dc47fc8a2feecdb1871244a66f3e5c582b35 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Wed, 26 Oct 2022 15:37:07 -0500 Subject: [PATCH 16/52] basic test for header layout --- .../__tests__/layouts/HeaderLayout.spec.tsx | 12 +++++++++--- .../__tests__/testHelpers/component.testHelper.ts | 14 +++++++++++++- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/packages/Schedulely/__tests__/layouts/HeaderLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/HeaderLayout.spec.tsx index bca2f81b..c2d03061 100644 --- a/packages/Schedulely/__tests__/layouts/HeaderLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/HeaderLayout.spec.tsx @@ -1,4 +1,5 @@ import { BreakpointProvider, ComponentProvider } from '@/providers'; +import { HeaderComponent } from '@/types'; import { HeaderLayout } from '@/layouts'; import { getCalendarProviderProps } from '../testHelpers/component.testHelper'; import { render } from '@testing-library/react'; @@ -9,17 +10,22 @@ jest.mock('../../src/hooks/useCalendar'); const mockUseCalendar = useCalendar as jest.MockedFunction; const hook = getCalendarProviderProps({}); +const testHeaderComponent: HeaderComponent = () =>
HEADER COMPONENT
; + describe('HeaderLayout', () => { mockUseCalendar.mockReturnValue(hook); const testObject = render( - + ); - it('skip', () => { - expect(true).toBe(true); + + it('uses custom header component', () => { + expect(testObject.queryByText('HEADER COMPONENT')).not.toBeNull(); }); }); diff --git a/packages/Schedulely/__tests__/testHelpers/component.testHelper.ts b/packages/Schedulely/__tests__/testHelpers/component.testHelper.ts index 254443ba..2dff589b 100644 --- a/packages/Schedulely/__tests__/testHelpers/component.testHelper.ts +++ b/packages/Schedulely/__tests__/testHelpers/component.testHelper.ts @@ -1,4 +1,5 @@ -import { CalendarContextState } from '@/types'; +import { CalendarContextState, SchedulelyComponents } from '@/types'; +import { DefaultDay, DefaultEvent, DefaultHeader } from '@/components'; import { createDefaultAdapter } from '@/dateAdapters'; export const getCalendarProviderProps = ( @@ -19,3 +20,14 @@ export const getCalendarProviderProps = ( }; return { hook, ...overrides } as CalendarContextState; }; + +export const getComponentProviderProps = ( + overrides: Partial +) => { + const hook: SchedulelyComponents = { + dayComponent: DefaultDay, + headerComponent: DefaultHeader, + eventComponent: DefaultEvent, + }; + return { hook, ...overrides }; +}; From d732c7ffe5022e250ade69ff73f3b2233be66d7a Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Wed, 26 Oct 2022 15:52:28 -0500 Subject: [PATCH 17/52] start building out event week test --- .../layouts/EventWeekLayout.spec.tsx | 30 +++++++++++++++---- .../testHelpers/component.testHelper.ts | 2 +- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx index 7f047f7d..49844adc 100644 --- a/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx @@ -1,12 +1,30 @@ -import { BreakpointProvider } from '@/providers'; -import { CalendarContextState, ComponentSize } from '@/types'; -import { DayOfWeekLayout } from '@/layouts'; -import { RenderResult, render } from '@testing-library/react'; -import { createDefaultAdapter } from '@/dateAdapters'; +import { + BreakpointProvider, + CalendarProvider, + ComponentProvider, + EventIntersectionProvider, + HighlightProvider, +} from '@/providers'; +import { EventWeekLayout } from '@/layouts'; +import { getCalendarProviderProps } from '../testHelpers/component.testHelper'; +import { render } from '@testing-library/react'; import { useCalendar } from '../../src/hooks/useCalendar'; import React from 'react'; -describe('EventWeekLayout', () => { +jest.mock('../../src/hooks/useCalendar'); +const mockUseCalendar = useCalendar as jest.MockedFunction; +const useCalendarMockContext = getCalendarProviderProps(null); + +xdescribe('EventWeekLayout', () => { + console.log(useCalendarMockContext); + mockUseCalendar.mockReturnValue(useCalendarMockContext); + + // const testObject = render( + // + // + // + // ); + it('skip', () => { expect(true).toBe(true); }); diff --git a/packages/Schedulely/__tests__/testHelpers/component.testHelper.ts b/packages/Schedulely/__tests__/testHelpers/component.testHelper.ts index 2dff589b..a575718d 100644 --- a/packages/Schedulely/__tests__/testHelpers/component.testHelper.ts +++ b/packages/Schedulely/__tests__/testHelpers/component.testHelper.ts @@ -3,7 +3,7 @@ import { DefaultDay, DefaultEvent, DefaultHeader } from '@/components'; import { createDefaultAdapter } from '@/dateAdapters'; export const getCalendarProviderProps = ( - overrides: Partial + overrides: Partial | null ) => { const hook: CalendarContextState = { currentDate: new Date(), From 25c679707a7fdc68c063da1387fb21b4bcf5e556 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Wed, 26 Oct 2022 16:18:03 -0500 Subject: [PATCH 18/52] simplify test --- .../layouts/DayOfWeekLayout.spec.tsx | 41 +++++++++---------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx index 51705b3c..45513fb3 100644 --- a/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx @@ -1,38 +1,37 @@ -import { BreakpointProvider } from '@/providers'; +import { + ActionProvider, + BreakpointProvider, + CalendarProvider, +} from '@/providers'; import { DayOfWeekLayout } from '@/layouts'; import { RenderResult, render } from '@testing-library/react'; -import { getCalendarProviderProps } from '../testHelpers/component.testHelper'; -import { useCalendar } from '../../src/hooks/useCalendar'; +import { createDefaultAdapter } from '@/dateAdapters'; import React from 'react'; -jest.mock('../../src/hooks/useCalendar'); -const mockUseCalendar = useCalendar as jest.MockedFunction; - -const daysOfWeek = [ - 'Sunday', - 'Monday', - 'Tueday', - 'Wednesday', - 'Thursday', - 'Friday', - 'Saturday', -]; - -const hook = getCalendarProviderProps({ daysOfWeek: daysOfWeek }); +const smallDaysOfWeek = ['S', 'M', 'T', 'W', 'T', 'F', 'S']; describe('DayOfWeekLayout', () => { - mockUseCalendar.mockReturnValue(hook); let testObject: RenderResult; beforeEach(() => { testObject = render( - + null }}> + + + + ); }); - test.each(daysOfWeek)('%s is rendered', (value) => { - expect(testObject.queryByText(value)).not.toBeNull(); + describe('small display header text', () => { + test.each(smallDaysOfWeek)('%s is rendered', (value) => { + expect(testObject.queryAllByText(value)).not.toBeNull(); + }); }); }); From 1bf5ebdb5d78d437748533d1ae321382a47bb0a6 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Wed, 26 Oct 2022 16:20:28 -0500 Subject: [PATCH 19/52] build out next test --- .../Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx index 45513fb3..2fdd1a7a 100644 --- a/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx @@ -9,6 +9,7 @@ import { createDefaultAdapter } from '@/dateAdapters'; import React from 'react'; const smallDaysOfWeek = ['S', 'M', 'T', 'W', 'T', 'F', 'S']; +const mediumDaysOfWeek = ['Sun', 'Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat']; describe('DayOfWeekLayout', () => { let testObject: RenderResult; @@ -31,6 +32,13 @@ describe('DayOfWeekLayout', () => { describe('small display header text', () => { test.each(smallDaysOfWeek)('%s is rendered', (value) => { + // lazily check because Sun/Sat will match on small mode + expect(testObject.queryAllByText(value)).not.toBeNull(); + }); + }); + + xdescribe('medium display header text', () => { + test.each(mediumDaysOfWeek)('%s is rendered', (value) => { expect(testObject.queryAllByText(value)).not.toBeNull(); }); }); From 1453f1a2145df7745b36b6b73795218ecc1e7737 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Fri, 28 Oct 2022 11:08:03 -0500 Subject: [PATCH 20/52] use better mocking method for hook in test --- .../layouts/DayOfWeekLayout.spec.tsx | 45 +++++-------------- .../dayOfWeekLayout/DayOfWeekLayout.tsx | 2 +- 2 files changed, 13 insertions(+), 34 deletions(-) diff --git a/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx index 2fdd1a7a..e78486ae 100644 --- a/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx @@ -1,45 +1,24 @@ -import { - ActionProvider, - BreakpointProvider, - CalendarProvider, -} from '@/providers'; import { DayOfWeekLayout } from '@/layouts'; import { RenderResult, render } from '@testing-library/react'; -import { createDefaultAdapter } from '@/dateAdapters'; -import React from 'react'; -const smallDaysOfWeek = ['S', 'M', 'T', 'W', 'T', 'F', 'S']; -const mediumDaysOfWeek = ['Sun', 'Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat']; +const mockDaysOfTheWeek = ['Sun', 'Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat']; + +jest.mock('@/hooks/useCalendar', () => ({ + useCalendar: jest.fn(() => ({ + daysOfWeek: mockDaysOfTheWeek, + })), +})); describe('DayOfWeekLayout', () => { let testObject: RenderResult; beforeEach(() => { - testObject = render( - - null }}> - - - - - - ); + testObject = render(); }); - describe('small display header text', () => { - test.each(smallDaysOfWeek)('%s is rendered', (value) => { - // lazily check because Sun/Sat will match on small mode - expect(testObject.queryAllByText(value)).not.toBeNull(); - }); - }); - - xdescribe('medium display header text', () => { - test.each(mediumDaysOfWeek)('%s is rendered', (value) => { - expect(testObject.queryAllByText(value)).not.toBeNull(); - }); + describe('headers are all rendered', () => { + test.each(mockDaysOfTheWeek)('%s is rendered', (value) => + expect(testObject.getByText(value)).toBeTruthy() + ); }); }); diff --git a/packages/Schedulely/src/layouts/dayOfWeekLayout/DayOfWeekLayout.tsx b/packages/Schedulely/src/layouts/dayOfWeekLayout/DayOfWeekLayout.tsx index 307c2741..6d1a1e7b 100644 --- a/packages/Schedulely/src/layouts/dayOfWeekLayout/DayOfWeekLayout.tsx +++ b/packages/Schedulely/src/layouts/dayOfWeekLayout/DayOfWeekLayout.tsx @@ -1,4 +1,4 @@ -import { useCalendar } from '@/hooks'; +import { useCalendar } from '@/hooks/useCalendar'; /** * This component controls the layout of the names of the days of the week at the top of the calendar From b8bb6867dc96a5bbc2cb6e1a66d7c4488986bb32 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Fri, 28 Oct 2022 11:11:29 -0500 Subject: [PATCH 21/52] randomize test data --- .../Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx index e78486ae..dc06a90c 100644 --- a/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx @@ -1,7 +1,10 @@ +import { Chance } from 'chance'; import { DayOfWeekLayout } from '@/layouts'; import { RenderResult, render } from '@testing-library/react'; -const mockDaysOfTheWeek = ['Sun', 'Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat']; +// randomize day names for the hell of it +const chance = Chance(); +const mockDaysOfTheWeek = chance.unique(() => chance.string(), 7); jest.mock('@/hooks/useCalendar', () => ({ useCalendar: jest.fn(() => ({ From ba695e5ecde47aa2c40e67572a339148e5034967 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Fri, 28 Oct 2022 11:20:09 -0500 Subject: [PATCH 22/52] cleanup circular dep, better test mocks --- .../layouts/DayOfWeekLayout.spec.tsx | 2 +- .../__tests__/layouts/HeaderLayout.spec.tsx | 30 +++++++------------ packages/Schedulely/src/hooks/useActions.tsx | 2 +- .../dayOfWeekLayout/DayOfWeekLayout.tsx | 2 +- .../src/providers/CalendarProvider.tsx | 4 +-- 5 files changed, 15 insertions(+), 25 deletions(-) diff --git a/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx index dc06a90c..390ff2eb 100644 --- a/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/DayOfWeekLayout.spec.tsx @@ -6,7 +6,7 @@ import { RenderResult, render } from '@testing-library/react'; const chance = Chance(); const mockDaysOfTheWeek = chance.unique(() => chance.string(), 7); -jest.mock('@/hooks/useCalendar', () => ({ +jest.mock('@/hooks', () => ({ useCalendar: jest.fn(() => ({ daysOfWeek: mockDaysOfTheWeek, })), diff --git a/packages/Schedulely/__tests__/layouts/HeaderLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/HeaderLayout.spec.tsx index c2d03061..e9a8cec2 100644 --- a/packages/Schedulely/__tests__/layouts/HeaderLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/HeaderLayout.spec.tsx @@ -1,31 +1,21 @@ -import { BreakpointProvider, ComponentProvider } from '@/providers'; import { HeaderComponent } from '@/types'; import { HeaderLayout } from '@/layouts'; -import { getCalendarProviderProps } from '../testHelpers/component.testHelper'; import { render } from '@testing-library/react'; -import { useCalendar } from '../../src/hooks/useCalendar'; -import React from 'react'; -jest.mock('../../src/hooks/useCalendar'); -const mockUseCalendar = useCalendar as jest.MockedFunction; -const hook = getCalendarProviderProps({}); +const mockHeaderComponent: HeaderComponent = () =>
HEADER COMPONENT
; -const testHeaderComponent: HeaderComponent = () =>
HEADER COMPONENT
; +jest.mock('@/hooks', () => ({ + useComponents: jest.fn(() => ({ + headerComponent: mockHeaderComponent, + })), + useCalendar: jest.fn(() => ({})), + useBreakpoint: jest.fn(() => ({})), +})); describe('HeaderLayout', () => { - mockUseCalendar.mockReturnValue(hook); - - const testObject = render( - - - - - - ); + const testObject = render(); it('uses custom header component', () => { - expect(testObject.queryByText('HEADER COMPONENT')).not.toBeNull(); + expect(testObject.getByText('HEADER COMPONENT')).toBeTruthy(); }); }); diff --git a/packages/Schedulely/src/hooks/useActions.tsx b/packages/Schedulely/src/hooks/useActions.tsx index 01c3568d..26b19784 100644 --- a/packages/Schedulely/src/hooks/useActions.tsx +++ b/packages/Schedulely/src/hooks/useActions.tsx @@ -1,4 +1,4 @@ -import { ActionContext } from '@/providers'; +import { ActionContext } from '@/providers/ActionProvider'; import { useContext } from 'react'; export const useActions = () => { diff --git a/packages/Schedulely/src/layouts/dayOfWeekLayout/DayOfWeekLayout.tsx b/packages/Schedulely/src/layouts/dayOfWeekLayout/DayOfWeekLayout.tsx index 6d1a1e7b..307c2741 100644 --- a/packages/Schedulely/src/layouts/dayOfWeekLayout/DayOfWeekLayout.tsx +++ b/packages/Schedulely/src/layouts/dayOfWeekLayout/DayOfWeekLayout.tsx @@ -1,4 +1,4 @@ -import { useCalendar } from '@/hooks/useCalendar'; +import { useCalendar } from '@/hooks'; /** * This component controls the layout of the names of the days of the week at the top of the calendar diff --git a/packages/Schedulely/src/providers/CalendarProvider.tsx b/packages/Schedulely/src/providers/CalendarProvider.tsx index a9044bd3..fb963197 100644 --- a/packages/Schedulely/src/providers/CalendarProvider.tsx +++ b/packages/Schedulely/src/providers/CalendarProvider.tsx @@ -1,7 +1,6 @@ import { CalendarContextState, CalendarEvent, - ComponentSize, DateTimeAdapter, InternalCalendarEvent, InternalEventWeek, @@ -14,7 +13,8 @@ import { useMemo, useState, } from 'react'; -import { useActions, useBreakpoint } from '@/hooks'; +import { useActions } from '@/hooks/useActions'; +import { useBreakpoint } from '@/hooks/useBreakpoint'; export const CalendarContext = createContext(null); CalendarContext.displayName = 'CalendarContext'; From 3cebd6ed4dce42c9e3bbd0db14bf98d2026eb46d Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Fri, 28 Oct 2022 12:16:56 -0500 Subject: [PATCH 23/52] add more tests to header --- .../__tests__/layouts/HeaderLayout.spec.tsx | 56 ++++++++++++++++--- 1 file changed, 49 insertions(+), 7 deletions(-) diff --git a/packages/Schedulely/__tests__/layouts/HeaderLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/HeaderLayout.spec.tsx index e9a8cec2..1ce3db0b 100644 --- a/packages/Schedulely/__tests__/layouts/HeaderLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/HeaderLayout.spec.tsx @@ -1,21 +1,63 @@ +import { Chance } from 'chance'; +import { DefaultHeader } from '@/components'; import { HeaderComponent } from '@/types'; import { HeaderLayout } from '@/layouts'; -import { render } from '@testing-library/react'; +import { RenderResult, render } from '@testing-library/react'; -const mockHeaderComponent: HeaderComponent = () =>
HEADER COMPONENT
; +let mockHeaderComponent: HeaderComponent = DefaultHeader; +const mockCurrentMonth = Chance().month(); +const mockCurrentYear = Chance().year(); +const mockIsCurrentMonth = Chance().bool(); jest.mock('@/hooks', () => ({ useComponents: jest.fn(() => ({ headerComponent: mockHeaderComponent, })), - useCalendar: jest.fn(() => ({})), - useBreakpoint: jest.fn(() => ({})), + useCalendar: jest.fn(() => ({ + currentMonth: mockCurrentMonth, + currentYear: mockCurrentYear, + isCurrentMonth: mockIsCurrentMonth, + })), + useBreakpoint: jest.fn(() => ({ + breakpoint: 'small', + })), })); describe('HeaderLayout', () => { - const testObject = render(); + describe('with DefaultHeader component', () => { + let testObject: RenderResult; + + beforeEach(() => { + testObject = render(); + }); + + it('passes currentMonth value', () => + expect( + testObject.getByText(mockCurrentMonth, { exact: false }) + ).toBeTruthy()); + + it('passes currentYear value', () => + expect( + testObject.getByText(mockCurrentYear, { exact: false }) + ).toBeTruthy()); + + it('passes isCurrentMonth', () => { + const result = expect(testObject.queryByRole('alert')); + mockIsCurrentMonth ? result.toBeTruthy() : result.toBeFalsy(); + }); + }); + + describe('with custom header component', () => { + let testObject: RenderResult; + let mockHeaderText: string; + + beforeEach(() => { + mockHeaderText = Chance().string(); + mockHeaderComponent = () =>
{mockHeaderText}
; + testObject = render(); + }); - it('uses custom header component', () => { - expect(testObject.getByText('HEADER COMPONENT')).toBeTruthy(); + it('uses custom header component', () => + expect(testObject.getByText(mockHeaderText)).toBeTruthy()); }); }); From 2420a3829591998dcd1880ca6b2f5fc98298b0ca Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Fri, 28 Oct 2022 12:38:50 -0500 Subject: [PATCH 24/52] add more tests to header layout --- .../__tests__/layouts/HeaderLayout.spec.tsx | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/packages/Schedulely/__tests__/layouts/HeaderLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/HeaderLayout.spec.tsx index 1ce3db0b..7cdeea9b 100644 --- a/packages/Schedulely/__tests__/layouts/HeaderLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/HeaderLayout.spec.tsx @@ -2,12 +2,16 @@ import { Chance } from 'chance'; import { DefaultHeader } from '@/components'; import { HeaderComponent } from '@/types'; import { HeaderLayout } from '@/layouts'; -import { RenderResult, render } from '@testing-library/react'; +import { RenderResult, fireEvent, render } from '@testing-library/react'; let mockHeaderComponent: HeaderComponent = DefaultHeader; const mockCurrentMonth = Chance().month(); const mockCurrentYear = Chance().year(); const mockIsCurrentMonth = Chance().bool(); +const mockOnNextMonthClick = jest.fn(); +const mockOnNextYearHandler = jest.fn(); +const mockOnPrevMonthHandler = jest.fn(); +const mockOnPrevYearHandler = jest.fn(); jest.mock('@/hooks', () => ({ useComponents: jest.fn(() => ({ @@ -17,6 +21,10 @@ jest.mock('@/hooks', () => ({ currentMonth: mockCurrentMonth, currentYear: mockCurrentYear, isCurrentMonth: mockIsCurrentMonth, + onNextMonth: mockOnNextMonthClick, + onNextYear: mockOnNextYearHandler, + onPrevYear: mockOnPrevYearHandler, + onPrevMonth: mockOnPrevMonthHandler, })), useBreakpoint: jest.fn(() => ({ breakpoint: 'small', @@ -45,6 +53,26 @@ describe('HeaderLayout', () => { const result = expect(testObject.queryByRole('alert')); mockIsCurrentMonth ? result.toBeTruthy() : result.toBeFalsy(); }); + + it('passes onNextMonthHandler', () => { + fireEvent.click(testObject.getByTitle('Next Month')); + expect(mockOnNextMonthClick).toHaveBeenCalledTimes(1); + }); + + it('passes onNextYearHandler', () => { + fireEvent.click(testObject.getByTitle('Next Year')); + expect(mockOnNextYearHandler).toHaveBeenCalledTimes(1); + }); + + it('passes onPrevMonthHandler', () => { + fireEvent.click(testObject.getByTitle('Previous Month')); + expect(mockOnPrevMonthHandler).toHaveBeenCalledTimes(1); + }); + + it('passes onPrevYearHandler', () => { + fireEvent.click(testObject.getByTitle('Previous Year')); + expect(mockOnPrevYearHandler).toHaveBeenCalledTimes(1); + }); }); describe('with custom header component', () => { From 9e17c2ab43091fb3ff4c856fba49993a22dcf9cd Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Fri, 28 Oct 2022 14:54:48 -0500 Subject: [PATCH 25/52] setup tests for eventweeklayout --- .../layouts/EventWeekLayout.spec.tsx | 94 ++++++++++++++----- .../eventWeekLayout/EventWeekLayout.tsx | 18 ++-- 2 files changed, 79 insertions(+), 33 deletions(-) diff --git a/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx index 49844adc..02dc0506 100644 --- a/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx @@ -1,32 +1,78 @@ -import { - BreakpointProvider, - CalendarProvider, - ComponentProvider, - EventIntersectionProvider, - HighlightProvider, -} from '@/providers'; +import { DefaultEvent } from '@/components'; import { EventWeekLayout } from '@/layouts'; -import { getCalendarProviderProps } from '../testHelpers/component.testHelper'; -import { render } from '@testing-library/react'; -import { useCalendar } from '../../src/hooks/useCalendar'; -import React from 'react'; +import { InternalCalendarEvent } from '@/types'; +import { RenderResult, render } from '@testing-library/react'; -jest.mock('../../src/hooks/useCalendar'); -const mockUseCalendar = useCalendar as jest.MockedFunction; -const useCalendarMockContext = getCalendarProviderProps(null); +// Oct 2-8 2022 is the test week +const daysInWeek = [ + new Date(2022, 9, 2), + new Date(2022, 9, 3), + new Date(2022, 9, 4), + new Date(2022, 9, 5), + new Date(2022, 9, 6), + new Date(2022, 9, 7), + new Date(2022, 9, 8), +]; -xdescribe('EventWeekLayout', () => { - console.log(useCalendarMockContext); - mockUseCalendar.mockReturnValue(useCalendarMockContext); +let events: InternalCalendarEvent[] = [ + { + id: 'event-1', + color: 'red', + start: new Date(2022, 9, 2), + end: new Date(2022, 9, 2), + summary: 'event-1', + visible: true, + }, +]; - // const testObject = render( - // - // - // - // ); +let mockSetHighlight: (eventId: string) => void = jest.fn( + (eventId: string) => {} +); +let mockClearHighlight: () => void = jest.fn(() => {}); +let mockIsHighlighted: (eventId: string) => boolean = jest.fn( + (eventId: string) => false +); - it('skip', () => { - expect(true).toBe(true); +let mockEventOnClickHandler: () => void = jest.fn(() => {}); + +let mockSetParentContainerRef: (eventId: string) => void = jest.fn( + (eventId: string) => {} +); +let mockSetRefFromKey: () => void = jest.fn(() => {}); +let mockIsEventVisible: (eventId: string) => boolean = jest.fn( + (eventId: string) => true +); + +jest.mock('@/hooks', () => ({ + useComponents: jest.fn(() => ({ + eventComponent: DefaultEvent, + })), + useEventHighlight: jest.fn(() => ({ + setHighlight: mockSetHighlight, + clearHighlight: mockClearHighlight, + isHighlighted: mockIsHighlighted, + })), + useActions: jest.fn(() => ({ + onEventClick: mockEventOnClickHandler, + })), + useEventIntersection: jest.fn(() => ({ + setParentContainerRef: mockSetParentContainerRef, + setRefFromKey: mockSetRefFromKey, + isEventVisible: mockIsEventVisible, + })), +})); + +describe('EventWeekLayout', () => { + let testObject: RenderResult; + + beforeEach(() => { + testObject = render( + + ); + }); + + it('displays correct number of events', () => { + expect(testObject.getByText('event-1')).toBeTruthy(); }); // describe('getGridEndIndex', () => { // it.each<{ eventEnd: Date; endOfWeek: Date; expected: number }>([ diff --git a/packages/Schedulely/src/layouts/eventWeekLayout/EventWeekLayout.tsx b/packages/Schedulely/src/layouts/eventWeekLayout/EventWeekLayout.tsx index 58de9704..082e9e96 100644 --- a/packages/Schedulely/src/layouts/eventWeekLayout/EventWeekLayout.tsx +++ b/packages/Schedulely/src/layouts/eventWeekLayout/EventWeekLayout.tsx @@ -11,15 +11,6 @@ interface EventLayoutProps { daysInweek: Date[]; } -const getGridStartIndex = (eventDate: Date, startOfWeek: Date) => - eventDate <= startOfWeek ? 1 : eventDate.getDay() + 1; //add one because css-grid isn't zero-index'd - -const getGridEndIndex = (eventEndDate: Date, endOfWeek: Date) => { - if (eventEndDate > endOfWeek) return 8; - const end = eventEndDate.getDay() + 2; // add two because css-grid isn't zero index'd, and day of week is zero-index'd - return end; -}; - /** * This component controls the layout of an individual events within a week * @returns EventLayout Component @@ -31,6 +22,15 @@ export const EventWeekLayout = ({ events, daysInweek }: EventLayoutProps) => { const { setParentContainerRef, setRefFromKey, isEventVisible } = useEventIntersection(); + const getGridStartIndex = (eventDate: Date, startOfWeek: Date) => + eventDate <= startOfWeek ? 1 : eventDate.getDay() + 1; //add one because css-grid isn't zero-index'd + + const getGridEndIndex = (eventEndDate: Date, endOfWeek: Date) => { + if (eventEndDate > endOfWeek) return 8; + const end = eventEndDate.getDay() + 2; // add two because css-grid isn't zero index'd, and day of week is zero-index'd + return end; + }; + return (
From f461b475a263da3d5a1ec14ba4bd12999abc3330 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Fri, 28 Oct 2022 15:20:00 -0500 Subject: [PATCH 26/52] more tests --- .../layouts/EventWeekLayout.spec.tsx | 43 +++++++++++++++++-- turbo.json | 8 +++- 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx index 02dc0506..2b25a7f6 100644 --- a/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx @@ -1,7 +1,7 @@ import { DefaultEvent } from '@/components'; import { EventWeekLayout } from '@/layouts'; import { InternalCalendarEvent } from '@/types'; -import { RenderResult, render } from '@testing-library/react'; +import { RenderResult, fireEvent, render } from '@testing-library/react'; // Oct 2-8 2022 is the test week const daysInWeek = [ @@ -23,6 +23,22 @@ let events: InternalCalendarEvent[] = [ summary: 'event-1', visible: true, }, + { + id: 'event-2', + color: 'red', + start: new Date(2022, 9, 2), + end: new Date(2022, 9, 2), + summary: 'event-2', + visible: true, + }, + { + id: 'event-3', + color: 'red', + start: new Date(2022, 9, 2), + end: new Date(2022, 9, 2), + summary: 'event-3', + visible: true, + }, ]; let mockSetHighlight: (eventId: string) => void = jest.fn( @@ -71,9 +87,30 @@ describe('EventWeekLayout', () => { ); }); - it('displays correct number of events', () => { - expect(testObject.getByText('event-1')).toBeTruthy(); + describe.each(events.map((x) => x.summary))('event %s', (value) => { + let eventDomObject: HTMLElement; + + beforeEach(() => { + eventDomObject = testObject.getByText(value); + }); + + it('is in document', () => { + expect(eventDomObject).toBeTruthy(); + }); + + describe('highlight', () => { + it('is set onMouseOver', () => { + fireEvent.mouseOver(eventDomObject); + expect(mockSetHighlight).toHaveBeenCalled(); + }); + + it('is cleared onMouseLeave', () => { + fireEvent.mouseLeave(eventDomObject); + expect(mockClearHighlight).toHaveBeenCalled(); + }); + }); }); + // describe('getGridEndIndex', () => { // it.each<{ eventEnd: Date; endOfWeek: Date; expected: number }>([ // { diff --git a/turbo.json b/turbo.json index b9c4f888..9cfdd4cd 100644 --- a/turbo.json +++ b/turbo.json @@ -51,7 +51,13 @@ ] }, "lint": { - "outputs": [] + "outputs": [], + "inputs": [ + "./src/**/*.tsx", + "./src/**/*.ts", + "./__tests__/**/*.tsx", + "./__tests__/**/*.ts" + ] }, "dev": { "cache": false From ad7ca39eedd5af86fdb0c82d42f3a113d0e70d04 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Fri, 28 Oct 2022 16:00:15 -0500 Subject: [PATCH 27/52] finish set highlight tests --- .../layouts/EventWeekLayout.spec.tsx | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx index 2b25a7f6..d1d4928d 100644 --- a/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx @@ -41,23 +41,15 @@ let events: InternalCalendarEvent[] = [ }, ]; -let mockSetHighlight: (eventId: string) => void = jest.fn( - (eventId: string) => {} -); -let mockClearHighlight: () => void = jest.fn(() => {}); -let mockIsHighlighted: (eventId: string) => boolean = jest.fn( - (eventId: string) => false -); +let mockSetHighlight = jest.fn((eventId: string) => {}); +let mockClearHighlight = jest.fn(() => {}); +let mockIsHighlighted = jest.fn((eventId: string) => false); -let mockEventOnClickHandler: () => void = jest.fn(() => {}); +let mockEventOnClickHandler = jest.fn(() => {}); -let mockSetParentContainerRef: (eventId: string) => void = jest.fn( - (eventId: string) => {} -); -let mockSetRefFromKey: () => void = jest.fn(() => {}); -let mockIsEventVisible: (eventId: string) => boolean = jest.fn( - (eventId: string) => true -); +let mockSetParentContainerRef = jest.fn((eventId: string) => {}); +let mockSetRefFromKey = jest.fn(() => {}); +let mockIsEventVisible = jest.fn((eventId: string) => true); jest.mock('@/hooks', () => ({ useComponents: jest.fn(() => ({ @@ -91,6 +83,8 @@ describe('EventWeekLayout', () => { let eventDomObject: HTMLElement; beforeEach(() => { + mockSetHighlight.mockClear(); + mockClearHighlight.mockClear(); eventDomObject = testObject.getByText(value); }); @@ -99,14 +93,20 @@ describe('EventWeekLayout', () => { }); describe('highlight', () => { - it('is set onMouseOver', () => { + it('calls setHighlight onMouseOver', () => { fireEvent.mouseOver(eventDomObject); - expect(mockSetHighlight).toHaveBeenCalled(); + expect(mockSetHighlight).toHaveBeenCalledTimes(1); + expect(mockSetHighlight.mock.calls[0][0]).toEqual(value); + }); + + it('passes eventID to set highlight onMouseOver', () => { + fireEvent.mouseOver(eventDomObject); + expect(mockSetHighlight.mock.calls[0][0]).toEqual(value); }); it('is cleared onMouseLeave', () => { fireEvent.mouseLeave(eventDomObject); - expect(mockClearHighlight).toHaveBeenCalled(); + expect(mockClearHighlight).toHaveBeenCalledTimes(1); }); }); }); From 5d331483e345bea2dd3ba48b58a280b94f4b1546 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Fri, 28 Oct 2022 16:36:44 -0500 Subject: [PATCH 28/52] more tests --- .../layouts/EventWeekLayout.spec.tsx | 48 +++++++++++++++++-- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx index d1d4928d..6066665a 100644 --- a/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx @@ -48,7 +48,7 @@ let mockIsHighlighted = jest.fn((eventId: string) => false); let mockEventOnClickHandler = jest.fn(() => {}); let mockSetParentContainerRef = jest.fn((eventId: string) => {}); -let mockSetRefFromKey = jest.fn(() => {}); +let mockSetRefFromKey = jest.fn((eventId: string) => {}); let mockIsEventVisible = jest.fn((eventId: string) => true); jest.mock('@/hooks', () => ({ @@ -74,34 +74,43 @@ describe('EventWeekLayout', () => { let testObject: RenderResult; beforeEach(() => { + mockSetParentContainerRef.mockClear(); testObject = render( ); }); + afterEach(() => { + mockIsEventVisible.mockClear(); + mockSetRefFromKey.mockClear(); + }); + describe.each(events.map((x) => x.summary))('event %s', (value) => { let eventDomObject: HTMLElement; beforeEach(() => { + eventDomObject = testObject.getByText(value); + }); + + afterEach(() => { mockSetHighlight.mockClear(); mockClearHighlight.mockClear(); - eventDomObject = testObject.getByText(value); + mockEventOnClickHandler.mockClear(); }); it('is in document', () => { expect(eventDomObject).toBeTruthy(); }); - describe('highlight', () => { + describe('useEventHighlight', () => { it('calls setHighlight onMouseOver', () => { fireEvent.mouseOver(eventDomObject); expect(mockSetHighlight).toHaveBeenCalledTimes(1); - expect(mockSetHighlight.mock.calls[0][0]).toEqual(value); }); it('passes eventID to set highlight onMouseOver', () => { fireEvent.mouseOver(eventDomObject); - expect(mockSetHighlight.mock.calls[0][0]).toEqual(value); + expect(mockSetHighlight).toHaveBeenLastCalledWith(value); }); it('is cleared onMouseLeave', () => { @@ -109,6 +118,35 @@ describe('EventWeekLayout', () => { expect(mockClearHighlight).toHaveBeenCalledTimes(1); }); }); + + describe('action', () => { + it('event onClick handler is called', () => { + fireEvent.click(eventDomObject.parentElement!); + expect(mockEventOnClickHandler).toHaveBeenCalledTimes(1); + }); + }); + }); + + describe('useEventIntersection', () => { + it('setParentContainerRef is called on the parent', () => { + expect(mockSetParentContainerRef).toHaveBeenCalledTimes(1); + }); + + it('isEventVisible is called', () => { + expect(mockIsEventVisible).toHaveBeenCalledTimes(events.length); + }); + + // it('isEventVisible is called with eventId', () => { + // expect(mockIsEventVisible).toHaveBeenLastCalledWith(value); + // }); + + it('setRefFromKey is called', () => { + expect(mockSetRefFromKey).toHaveBeenCalledTimes(events.length); + }); + + // it('setRefFromKey is called with eventId', () => { + // expect(mockSetRefFromKey).toHaveBeenLastCalledWith(value); + // }); }); // describe('getGridEndIndex', () => { From a4310fb9cb9aa72398b7842ff45c683f0c286cb1 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Fri, 28 Oct 2022 16:44:18 -0500 Subject: [PATCH 29/52] wip --- .../layouts/EventWeekLayout.spec.tsx | 67 +++++++++---------- 1 file changed, 30 insertions(+), 37 deletions(-) diff --git a/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx index 6066665a..b1c3cfc7 100644 --- a/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx @@ -98,55 +98,48 @@ describe('EventWeekLayout', () => { mockEventOnClickHandler.mockClear(); }); - it('is in document', () => { - expect(eventDomObject).toBeTruthy(); + it('is in document', () => expect(eventDomObject).toBeTruthy()); + + it('calls setHighlight onMouseOver', () => { + fireEvent.mouseOver(eventDomObject); + expect(mockSetHighlight).toHaveBeenCalledTimes(1); + }); + + it('passes eventID to set highlight onMouseOver', () => { + fireEvent.mouseOver(eventDomObject); + expect(mockSetHighlight).toHaveBeenLastCalledWith(value); }); - describe('useEventHighlight', () => { - it('calls setHighlight onMouseOver', () => { - fireEvent.mouseOver(eventDomObject); - expect(mockSetHighlight).toHaveBeenCalledTimes(1); - }); - - it('passes eventID to set highlight onMouseOver', () => { - fireEvent.mouseOver(eventDomObject); - expect(mockSetHighlight).toHaveBeenLastCalledWith(value); - }); - - it('is cleared onMouseLeave', () => { - fireEvent.mouseLeave(eventDomObject); - expect(mockClearHighlight).toHaveBeenCalledTimes(1); - }); + it('is cleared onMouseLeave', () => { + fireEvent.mouseLeave(eventDomObject); + expect(mockClearHighlight).toHaveBeenCalledTimes(1); }); - describe('action', () => { - it('event onClick handler is called', () => { - fireEvent.click(eventDomObject.parentElement!); - expect(mockEventOnClickHandler).toHaveBeenCalledTimes(1); - }); + it('event onClick handler is called when clicked', () => { + fireEvent.click(eventDomObject.parentElement!); + expect(mockEventOnClickHandler).toHaveBeenCalledTimes(1); }); }); describe('useEventIntersection', () => { - it('setParentContainerRef is called on the parent', () => { - expect(mockSetParentContainerRef).toHaveBeenCalledTimes(1); - }); + it('setParentContainerRef is called on the parent', () => + expect(mockSetParentContainerRef).toHaveBeenCalledTimes(1)); - it('isEventVisible is called', () => { - expect(mockIsEventVisible).toHaveBeenCalledTimes(events.length); - }); + it('isEventVisible is called', () => + expect(mockIsEventVisible).toHaveBeenCalledTimes(events.length)); - // it('isEventVisible is called with eventId', () => { - // expect(mockIsEventVisible).toHaveBeenLastCalledWith(value); - // }); + it('isEventVisible is called with each eventId', () => + expect(mockIsEventVisible.mock.calls.flat().sort()).toEqual( + events.map((x) => x.id).sort() + )); - it('setRefFromKey is called', () => { - expect(mockSetRefFromKey).toHaveBeenCalledTimes(events.length); - }); + it('setRefFromKey is called', () => + expect(mockSetRefFromKey).toHaveBeenCalledTimes(events.length)); - // it('setRefFromKey is called with eventId', () => { - // expect(mockSetRefFromKey).toHaveBeenLastCalledWith(value); - // }); + it('setRefFromKey is called with each eventId', () => + expect(mockSetRefFromKey.mock.calls.flat().sort()).toEqual( + events.map((x) => x.id).sort() + )); }); // describe('getGridEndIndex', () => { From 6015d63ed7a5164412cd2878c5e8e5980323dcbe Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Fri, 28 Oct 2022 16:46:28 -0500 Subject: [PATCH 30/52] add note --- packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx index b1c3cfc7..603bd349 100644 --- a/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx @@ -121,6 +121,7 @@ describe('EventWeekLayout', () => { }); }); + // we can't really test this well in jest without a massive setup. Maybe later. describe('useEventIntersection', () => { it('setParentContainerRef is called on the parent', () => expect(mockSetParentContainerRef).toHaveBeenCalledTimes(1)); From 92e633cd907eb7e481a0093583bd631d46dd4e97 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Fri, 28 Oct 2022 16:50:16 -0500 Subject: [PATCH 31/52] move functions out of component for performance --- .../eventWeekLayout/EventWeekLayout.tsx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/Schedulely/src/layouts/eventWeekLayout/EventWeekLayout.tsx b/packages/Schedulely/src/layouts/eventWeekLayout/EventWeekLayout.tsx index 082e9e96..58de9704 100644 --- a/packages/Schedulely/src/layouts/eventWeekLayout/EventWeekLayout.tsx +++ b/packages/Schedulely/src/layouts/eventWeekLayout/EventWeekLayout.tsx @@ -11,6 +11,15 @@ interface EventLayoutProps { daysInweek: Date[]; } +const getGridStartIndex = (eventDate: Date, startOfWeek: Date) => + eventDate <= startOfWeek ? 1 : eventDate.getDay() + 1; //add one because css-grid isn't zero-index'd + +const getGridEndIndex = (eventEndDate: Date, endOfWeek: Date) => { + if (eventEndDate > endOfWeek) return 8; + const end = eventEndDate.getDay() + 2; // add two because css-grid isn't zero index'd, and day of week is zero-index'd + return end; +}; + /** * This component controls the layout of an individual events within a week * @returns EventLayout Component @@ -22,15 +31,6 @@ export const EventWeekLayout = ({ events, daysInweek }: EventLayoutProps) => { const { setParentContainerRef, setRefFromKey, isEventVisible } = useEventIntersection(); - const getGridStartIndex = (eventDate: Date, startOfWeek: Date) => - eventDate <= startOfWeek ? 1 : eventDate.getDay() + 1; //add one because css-grid isn't zero-index'd - - const getGridEndIndex = (eventEndDate: Date, endOfWeek: Date) => { - if (eventEndDate > endOfWeek) return 8; - const end = eventEndDate.getDay() + 2; // add two because css-grid isn't zero index'd, and day of week is zero-index'd - return end; - }; - return (
From 4544d738988c6f2fcbad9b9db85869e55c955e03 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Fri, 28 Oct 2022 16:52:57 -0500 Subject: [PATCH 32/52] add tests for grid positions --- .../layouts/EventWeekLayout.spec.tsx | 141 +++++++++--------- .../eventWeekLayout/EventWeekLayout.tsx | 4 +- 2 files changed, 73 insertions(+), 72 deletions(-) diff --git a/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx index 603bd349..37d2451a 100644 --- a/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/EventWeekLayout.spec.tsx @@ -1,5 +1,5 @@ import { DefaultEvent } from '@/components'; -import { EventWeekLayout } from '@/layouts'; +import { EventWeekLayout, getGridEndIndex, getGridStartIndex } from '@/layouts'; import { InternalCalendarEvent } from '@/types'; import { RenderResult, fireEvent, render } from '@testing-library/react'; @@ -143,73 +143,74 @@ describe('EventWeekLayout', () => { )); }); - // describe('getGridEndIndex', () => { - // it.each<{ eventEnd: Date; endOfWeek: Date; expected: number }>([ - // { - // eventEnd: new Date(2022, 1, 11), - // endOfWeek: new Date(2022, 1, 12), - // expected: 7, - // }, - // { - // // event ends after end of week - // eventEnd: new Date(2022, 1, 13), - // endOfWeek: new Date(2022, 1, 12), - // expected: 8, - // }, - // { - // eventEnd: new Date(2022, 1, 9), - // endOfWeek: new Date(2022, 1, 12), - // expected: 5, - // }, - // { - // // event ends on Sunday - // eventEnd: new Date(2021, 8, 26), - // endOfWeek: new Date(2021, 9, 2), - // expected: 2, - // }, - // { - // // event that starts and ends on Sunday - // eventEnd: new Date(2022, 0, 2), - // endOfWeek: new Date(2022, 0, 8), - // expected: 2, - // }, - // ])( - // '$eventEnd with $endOfWeek returns $expected', - // ({ eventEnd, endOfWeek, expected }) => { - // const result = adapter.getGridEndIndex(eventEnd, endOfWeek); - // expect(result).toBe(expected); - // } - // ); - // }); - // describe('getGridStartIndex', () => { - // it.each<{ eventStart: Date; startOfWeek: Date; expected: number }>([ - // { - // eventStart: new Date(2022, 1, 7), - // startOfWeek: new Date(2022, 1, 6), - // expected: 2, - // }, - // { - // eventStart: new Date(2022, 1, 9), - // startOfWeek: new Date(2022, 1, 6), - // expected: 4, - // }, - // { - // eventStart: new Date(2022, 3, 10), - // startOfWeek: new Date(2022, 3, 10), - // expected: 1, - // }, - // { - // // event that starts and ends on Sunday - // eventStart: new Date(2022, 0, 2), - // startOfWeek: new Date(2022, 0, 2), - // expected: 1, - // }, - // ])( - // '$eventStart with $startOfWeek returns $expected', - // ({ eventStart, startOfWeek, expected }) => { - // const result = adapter.getGridStartIndex(eventStart, startOfWeek); - // expect(result).toBe(expected); - // } - // ); - // }); + describe('getGridEndIndex', () => { + it.each<{ eventEnd: Date; endOfWeek: Date; expected: number }>([ + { + eventEnd: new Date(2022, 1, 11), + endOfWeek: new Date(2022, 1, 12), + expected: 7, + }, + { + // event ends after end of week + eventEnd: new Date(2022, 1, 13), + endOfWeek: new Date(2022, 1, 12), + expected: 8, + }, + { + eventEnd: new Date(2022, 1, 9), + endOfWeek: new Date(2022, 1, 12), + expected: 5, + }, + { + // event ends on Sunday + eventEnd: new Date(2021, 8, 26), + endOfWeek: new Date(2021, 9, 2), + expected: 2, + }, + { + // event that starts and ends on Sunday + eventEnd: new Date(2022, 0, 2), + endOfWeek: new Date(2022, 0, 8), + expected: 2, + }, + ])( + '$eventEnd with $endOfWeek returns $expected', + ({ eventEnd, endOfWeek, expected }) => { + const result = getGridEndIndex(eventEnd, endOfWeek); + expect(result).toBe(expected); + } + ); + }); + + describe('getGridStartIndex', () => { + it.each<{ eventStart: Date; startOfWeek: Date; expected: number }>([ + { + eventStart: new Date(2022, 1, 7), + startOfWeek: new Date(2022, 1, 6), + expected: 2, + }, + { + eventStart: new Date(2022, 1, 9), + startOfWeek: new Date(2022, 1, 6), + expected: 4, + }, + { + eventStart: new Date(2022, 3, 10), + startOfWeek: new Date(2022, 3, 10), + expected: 1, + }, + { + // event that starts and ends on Sunday + eventStart: new Date(2022, 0, 2), + startOfWeek: new Date(2022, 0, 2), + expected: 1, + }, + ])( + '$eventStart with $startOfWeek returns $expected', + ({ eventStart, startOfWeek, expected }) => { + const result = getGridStartIndex(eventStart, startOfWeek); + expect(result).toBe(expected); + } + ); + }); }); diff --git a/packages/Schedulely/src/layouts/eventWeekLayout/EventWeekLayout.tsx b/packages/Schedulely/src/layouts/eventWeekLayout/EventWeekLayout.tsx index 58de9704..23fcaa61 100644 --- a/packages/Schedulely/src/layouts/eventWeekLayout/EventWeekLayout.tsx +++ b/packages/Schedulely/src/layouts/eventWeekLayout/EventWeekLayout.tsx @@ -11,10 +11,10 @@ interface EventLayoutProps { daysInweek: Date[]; } -const getGridStartIndex = (eventDate: Date, startOfWeek: Date) => +export const getGridStartIndex = (eventDate: Date, startOfWeek: Date) => eventDate <= startOfWeek ? 1 : eventDate.getDay() + 1; //add one because css-grid isn't zero-index'd -const getGridEndIndex = (eventEndDate: Date, endOfWeek: Date) => { +export const getGridEndIndex = (eventEndDate: Date, endOfWeek: Date) => { if (eventEndDate > endOfWeek) return 8; const end = eventEndDate.getDay() + 2; // add two because css-grid isn't zero index'd, and day of week is zero-index'd return end; From f0ca59ec816d8b0af7204494301004508a8a1121 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Fri, 28 Oct 2022 16:58:45 -0500 Subject: [PATCH 33/52] add vscode extension for test coverage --- .vscode/settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 7bcc48c8..cbdc803e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,4 @@ { - "jest.jestCommandLine": "npm run test --", + "jest.jestCommandLine": "npm run test -- --", "cSpell.words": ["Schedulely"] } From d9c7f113b594263839e05656a6e537e26b78891e Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Fri, 28 Oct 2022 21:54:02 -0500 Subject: [PATCH 34/52] add tests for weeklayout --- .../__tests__/layouts/WeekLayout.spec.tsx | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 packages/Schedulely/__tests__/layouts/WeekLayout.spec.tsx diff --git a/packages/Schedulely/__tests__/layouts/WeekLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/WeekLayout.spec.tsx new file mode 100644 index 00000000..e5c28ee0 --- /dev/null +++ b/packages/Schedulely/__tests__/layouts/WeekLayout.spec.tsx @@ -0,0 +1,98 @@ +import { DefaultDay } from '@/components'; +import { InternalCalendarEvent } from '@/types'; +import { RenderResult, render } from '@testing-library/react'; +import { WeekLayout } from '@/layouts'; + +// Oct 2-8 2022 is the test week +const dates = [ + new Date(2022, 9, 2), + new Date(2022, 9, 3), + new Date(2022, 9, 4), + new Date(2022, 9, 5), + new Date(2022, 9, 6), + new Date(2022, 9, 7), + new Date(2022, 9, 8), +]; + +let mockOnMoreEventClick = jest.fn((events: InternalCalendarEvent[]) => {}); +let mockGetEventsOnDate = jest.fn( + (date: Date) => [] as InternalCalendarEvent[] +); +let mockIsDateToday = jest.fn((date: Date) => true); +let mockIsSameMonth = jest.fn((date: Date, date2: Date) => true); +let mockGetDayNumber = jest.fn((date: Date) => 1); +let mockCurrentDate = jest.fn(() => Date); + +jest.mock('@/hooks', () => ({ + useComponents: jest.fn(() => ({ + dayComponent: DefaultDay, + })), + useCalendar: jest.fn(() => ({ + dateAdapter: { + isDateToday: mockIsDateToday, + isSameMonth: mockIsSameMonth, + getDayNumber: mockGetDayNumber, + }, + currentDate: mockCurrentDate, + })), + useActions: jest.fn(() => ({ + onMoreEventClick: mockOnMoreEventClick, + })), + useEventIntersection: jest.fn(() => ({ + getEventsOnDate: mockGetEventsOnDate, + })), +})); + +describe('WeekLayout', () => { + let testObject: RenderResult; + + beforeEach(() => { + testObject = render(); + }); + + afterEach(() => { + mockOnMoreEventClick.mockClear(); + mockGetEventsOnDate.mockClear(); + mockIsDateToday.mockClear(); + mockGetDayNumber.mockClear(); + mockIsSameMonth.mockClear(); + }); + + // This is called twice, once for the day component and again for the container data attribute + it('calls isDateToday', () => + expect(mockIsDateToday).toHaveBeenCalledTimes(dates.length * 2)); + + it('isDateToday is called with each date', () => + expect( + mockIsDateToday.mock.calls + .flat() + .filter((x, i, a) => a.indexOf(x) == i) + .sort() + ).toEqual(dates.map((x) => x).sort())); + + it('calls getDayNumber', () => + expect(mockGetDayNumber).toHaveBeenCalledTimes(dates.length)); + + it('getDayNumber is called with each date', () => + expect( + mockGetDayNumber.mock.calls + .flat() + .filter((x, i, a) => a.indexOf(x) == i) + .sort() + ).toEqual(dates.map((x) => x).sort())); + + it('calls isSameMonth', () => + expect(mockIsSameMonth).toHaveBeenCalledTimes(dates.length)); + + // it('isSameMonth is called with each date', () => + // expect( + // mockIsSameMonth.mock.calls + // .flat() + // .filter((x, i, a) => a.indexOf(x) == i) + // .sort() + // ).toEqual(dates.map((x) => x).sort())); + + // This is called twice, once for the overflow indicator, and again for the indicator itself + it('calls getEventsOnDate', () => + expect(mockGetEventsOnDate).toHaveBeenCalledTimes(dates.length * 2)); +}); From cb41ff90787a99b2b57c4772874e1e9ea9b80869 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Fri, 28 Oct 2022 22:01:49 -0500 Subject: [PATCH 35/52] optimize function calls --- .../__tests__/layouts/WeekLayout.spec.tsx | 4 +- .../src/layouts/weekLayout/WeekLayout.tsx | 38 ++++++++++--------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/packages/Schedulely/__tests__/layouts/WeekLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/WeekLayout.spec.tsx index e5c28ee0..63730ee6 100644 --- a/packages/Schedulely/__tests__/layouts/WeekLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/WeekLayout.spec.tsx @@ -60,7 +60,7 @@ describe('WeekLayout', () => { // This is called twice, once for the day component and again for the container data attribute it('calls isDateToday', () => - expect(mockIsDateToday).toHaveBeenCalledTimes(dates.length * 2)); + expect(mockIsDateToday).toHaveBeenCalledTimes(dates.length)); it('isDateToday is called with each date', () => expect( @@ -94,5 +94,5 @@ describe('WeekLayout', () => { // This is called twice, once for the overflow indicator, and again for the indicator itself it('calls getEventsOnDate', () => - expect(mockGetEventsOnDate).toHaveBeenCalledTimes(dates.length * 2)); + expect(mockGetEventsOnDate).toHaveBeenCalledTimes(dates.length)); }); diff --git a/packages/Schedulely/src/layouts/weekLayout/WeekLayout.tsx b/packages/Schedulely/src/layouts/weekLayout/WeekLayout.tsx index a62256ae..ea753b92 100644 --- a/packages/Schedulely/src/layouts/weekLayout/WeekLayout.tsx +++ b/packages/Schedulely/src/layouts/weekLayout/WeekLayout.tsx @@ -24,24 +24,26 @@ export const WeekLayout = ({ dates }: WeekLayoutProps) => { return (
- {dates.map((day) => ( -
- !x.visible).length > 0 - } - events={getEventsOnDate(day)} - onClick={onMoreEventClick} - /> -
- ))} + {dates.map((day) => { + const isToday = isDateToday(day); + const events = getEventsOnDate(day); + return ( +
+ !x.visible).length > 0} + events={events} + onClick={onMoreEventClick} + /> +
+ ); + })}
); }; From fdb24e568e74dc01002546597244ebf02a6e9028 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Fri, 28 Oct 2022 22:10:59 -0500 Subject: [PATCH 36/52] simplfy weeklayout --- .../Schedulely/__tests__/layouts/WeekLayout.spec.tsx | 12 +++++++++++- .../Schedulely/src/layouts/weekLayout/WeekLayout.tsx | 8 +++----- .../src/types/state/EventIntersectionContextState.ts | 2 +- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/packages/Schedulely/__tests__/layouts/WeekLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/WeekLayout.spec.tsx index 63730ee6..74491f05 100644 --- a/packages/Schedulely/__tests__/layouts/WeekLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/WeekLayout.spec.tsx @@ -16,7 +16,17 @@ const dates = [ let mockOnMoreEventClick = jest.fn((events: InternalCalendarEvent[]) => {}); let mockGetEventsOnDate = jest.fn( - (date: Date) => [] as InternalCalendarEvent[] + (date: Date) => + [ + { + id: 'event-1', + color: 'red', + start: new Date(2022, 9, 2), + end: new Date(2022, 9, 2), + summary: 'event-1', + visible: true, + }, + ] as InternalCalendarEvent[] ); let mockIsDateToday = jest.fn((date: Date) => true); let mockIsSameMonth = jest.fn((date: Date, date2: Date) => true); diff --git a/packages/Schedulely/src/layouts/weekLayout/WeekLayout.tsx b/packages/Schedulely/src/layouts/weekLayout/WeekLayout.tsx index ea753b92..6d7907cc 100644 --- a/packages/Schedulely/src/layouts/weekLayout/WeekLayout.tsx +++ b/packages/Schedulely/src/layouts/weekLayout/WeekLayout.tsx @@ -27,12 +27,10 @@ export const WeekLayout = ({ dates }: WeekLayoutProps) => { {dates.map((day) => { const isToday = isDateToday(day); const events = getEventsOnDate(day); + const date = day.getDate(); + return ( -
+
(element: HTMLElement | null) => void; /** Lookup an event and retrieve its visibility */ isEventVisible: (key: string) => boolean; - /** Gets an array of hidden overflow events for the supplied date. An empty array is returned if no days are hidden. */ + /** Gets an array of events that occur on or span the supplied date. */ getEventsOnDate: (date: Date) => InternalCalendarEvent[]; }; From 22afd04410c1d08a256dd8e690bfee14851bec5d Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Sat, 29 Oct 2022 21:10:21 -0500 Subject: [PATCH 37/52] add test --- .../__tests__/layouts/WeekLayout.spec.tsx | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/Schedulely/__tests__/layouts/WeekLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/WeekLayout.spec.tsx index 74491f05..96bf62a1 100644 --- a/packages/Schedulely/__tests__/layouts/WeekLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/WeekLayout.spec.tsx @@ -68,7 +68,6 @@ describe('WeekLayout', () => { mockIsSameMonth.mockClear(); }); - // This is called twice, once for the day component and again for the container data attribute it('calls isDateToday', () => expect(mockIsDateToday).toHaveBeenCalledTimes(dates.length)); @@ -94,15 +93,15 @@ describe('WeekLayout', () => { it('calls isSameMonth', () => expect(mockIsSameMonth).toHaveBeenCalledTimes(dates.length)); - // it('isSameMonth is called with each date', () => - // expect( - // mockIsSameMonth.mock.calls - // .flat() - // .filter((x, i, a) => a.indexOf(x) == i) - // .sort() - // ).toEqual(dates.map((x) => x).sort())); + it('isSameMonth is called with each date', () => { + expect( + mockIsSameMonth.mock.calls + .map((x) => x[0]) + .filter((x, i, a) => a.indexOf(x) == i) + .sort() + ).toEqual(dates.map((x) => x).sort()); + }); - // This is called twice, once for the overflow indicator, and again for the indicator itself it('calls getEventsOnDate', () => expect(mockGetEventsOnDate).toHaveBeenCalledTimes(dates.length)); }); From 5e53c7dfb6ebcfeffcfdf3da7760b3d1cb5f3c06 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Sat, 29 Oct 2022 21:39:37 -0500 Subject: [PATCH 38/52] add test for more event handler --- .../__tests__/layouts/WeekLayout.spec.tsx | 35 +++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/packages/Schedulely/__tests__/layouts/WeekLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/WeekLayout.spec.tsx index 96bf62a1..f092b0a3 100644 --- a/packages/Schedulely/__tests__/layouts/WeekLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/WeekLayout.spec.tsx @@ -1,6 +1,6 @@ import { DefaultDay } from '@/components'; import { InternalCalendarEvent } from '@/types'; -import { RenderResult, render } from '@testing-library/react'; +import { RenderResult, fireEvent, render } from '@testing-library/react'; import { WeekLayout } from '@/layouts'; // Oct 2-8 2022 is the test week @@ -26,11 +26,19 @@ let mockGetEventsOnDate = jest.fn( summary: 'event-1', visible: true, }, + { + id: 'event-1', + color: 'red', + start: new Date(2022, 9, 2), + end: new Date(2022, 9, 8), + summary: 'event-1', + visible: false, + }, ] as InternalCalendarEvent[] ); let mockIsDateToday = jest.fn((date: Date) => true); let mockIsSameMonth = jest.fn((date: Date, date2: Date) => true); -let mockGetDayNumber = jest.fn((date: Date) => 1); +let mockGetDayNumber = jest.fn((date: Date) => date.getDate()); let mockCurrentDate = jest.fn(() => Date); jest.mock('@/hooks', () => ({ @@ -61,7 +69,6 @@ describe('WeekLayout', () => { }); afterEach(() => { - mockOnMoreEventClick.mockClear(); mockGetEventsOnDate.mockClear(); mockIsDateToday.mockClear(); mockGetDayNumber.mockClear(); @@ -104,4 +111,26 @@ describe('WeekLayout', () => { it('calls getEventsOnDate', () => expect(mockGetEventsOnDate).toHaveBeenCalledTimes(dates.length)); + + describe.each(dates.map((x) => x))('date container for %s', (value) => { + let dayDomObject: HTMLElement; + + beforeEach(() => { + dayDomObject = testObject + .getByText(value.getDate()) + .closest('[role="cell"]')!; + }); + + afterEach(() => { + mockOnMoreEventClick.mockClear(); + }); + + it('is rendered', () => expect(dayDomObject).toBeTruthy()); + + it('calls onMoreEventClick when clicked', () => { + const moreEventObject = dayDomObject.querySelector('[role="note"]')!; + fireEvent.click(moreEventObject); + expect(mockGetEventsOnDate).toHaveBeenCalledTimes(dates.length); + }); + }); }); From 2dc107f3dea1e26cec12fbb00dc26bfbc6cb0051 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Sun, 30 Oct 2022 20:13:34 -0500 Subject: [PATCH 39/52] scaffold monthlayout tests --- .../__tests__/layouts/MonthLayout.spec.tsx | 24 +++++++++++++++++++ .../src/layouts/monthLayout/MonthLayout.tsx | 3 +-- 2 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 packages/Schedulely/__tests__/layouts/MonthLayout.spec.tsx diff --git a/packages/Schedulely/__tests__/layouts/MonthLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/MonthLayout.spec.tsx new file mode 100644 index 00000000..8deda8aa --- /dev/null +++ b/packages/Schedulely/__tests__/layouts/MonthLayout.spec.tsx @@ -0,0 +1,24 @@ +import { InternalEventWeek } from '@/types'; +import { MonthLayout } from '@/layouts'; +import { RenderResult, render } from '@testing-library/react'; + +const mockCalendarWithEvents = [] as InternalEventWeek[]; +const mockUseKeyboardControls = jest.fn(() => null); + +jest.mock('@/hooks', () => ({ + useCalendar: jest.fn(() => ({ + calendarWithEvents: mockCalendarWithEvents, + })), + useKeyboardControls: jest.fn(() => mockUseKeyboardControls()), +})); + +describe('MonthLayout', () => { + let testObject: RenderResult; + + beforeEach(() => { + testObject = render(); + }); + + it('initializes keyboard controls', () => + expect(mockUseKeyboardControls).toHaveBeenCalledTimes(1)); +}); diff --git a/packages/Schedulely/src/layouts/monthLayout/MonthLayout.tsx b/packages/Schedulely/src/layouts/monthLayout/MonthLayout.tsx index 29c21be3..dfb65311 100644 --- a/packages/Schedulely/src/layouts/monthLayout/MonthLayout.tsx +++ b/packages/Schedulely/src/layouts/monthLayout/MonthLayout.tsx @@ -1,8 +1,7 @@ import { EventIntersectionProvider, HighlightProvider } from '@/providers'; import { EventWeekLayout } from '@/layouts/eventWeekLayout'; import { WeekLayout } from '@/layouts/weekLayout'; -import { useCalendar } from '@/hooks/useCalendar'; -import { useKeyboardControls } from '@/hooks'; +import { useCalendar, useKeyboardControls } from '@/hooks'; /** * This component controls the layout of the weeks of the calendar From d9813442289a5f10ac3e4523765869641b4c3201 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Mon, 31 Oct 2022 12:39:57 -0500 Subject: [PATCH 40/52] get month layout tests started --- .../__tests__/layouts/MonthLayout.spec.tsx | 150 +++++++++++++++++- .../eventWeekLayout/EventWeekLayout.tsx | 2 +- .../src/layouts/weekLayout/WeekLayout.tsx | 2 +- 3 files changed, 149 insertions(+), 5 deletions(-) diff --git a/packages/Schedulely/__tests__/layouts/MonthLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/MonthLayout.spec.tsx index 8deda8aa..656fec3d 100644 --- a/packages/Schedulely/__tests__/layouts/MonthLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/MonthLayout.spec.tsx @@ -1,8 +1,101 @@ -import { InternalEventWeek } from '@/types'; -import { MonthLayout } from '@/layouts'; +import { EventLayoutProps, MonthLayout, WeekLayoutProps } from '@/layouts'; +import { InternalCalendarEvent, InternalEventWeek } from '@/types'; +import { ReactNode } from 'react'; import { RenderResult, render } from '@testing-library/react'; -const mockCalendarWithEvents = [] as InternalEventWeek[]; +const mockCalendarWithEvents = [ + { + weekStart: new Date(8, 25, 2022), + weekEnd: new Date(9, 1, 2022), + daysInWeek: [ + new Date(8, 25, 2022), + new Date(8, 26, 2022), + new Date(8, 27, 2022), + new Date(8, 28, 2022), + new Date(8, 29, 2022), + new Date(8, 30, 2022), + new Date(9, 1, 2022), + ], + events: [] as InternalCalendarEvent[], + eventsOnDays: {}, + }, + { + weekStart: new Date(9, 2, 2022), + weekEnd: new Date(9, 8, 2022), + daysInWeek: [ + new Date(9, 2, 2022), + new Date(9, 3, 2022), + new Date(9, 4, 2022), + new Date(9, 5, 2022), + new Date(9, 6, 2022), + new Date(9, 7, 2022), + new Date(9, 8, 2022), + ], + events: [] as InternalCalendarEvent[], + eventsOnDays: {}, + }, + { + weekStart: new Date(9, 9, 2022), + weekEnd: new Date(9, 15, 2022), + daysInWeek: [ + new Date(9, 9, 2022), + new Date(9, 10, 2022), + new Date(9, 11, 2022), + new Date(9, 12, 2022), + new Date(9, 13, 2022), + new Date(9, 14, 2022), + new Date(9, 15, 2022), + ], + events: [] as InternalCalendarEvent[], + eventsOnDays: {}, + }, + { + weekStart: new Date(9, 16, 2022), + weekEnd: new Date(9, 22, 2022), + daysInWeek: [ + new Date(9, 16, 2022), + new Date(9, 17, 2022), + new Date(9, 18, 2022), + new Date(9, 19, 2022), + new Date(9, 20, 2022), + new Date(9, 21, 2022), + new Date(9, 22, 2022), + ], + events: [] as InternalCalendarEvent[], + eventsOnDays: {}, + }, + { + weekStart: new Date(9, 23, 2022), + weekEnd: new Date(9, 29, 2022), + daysInWeek: [ + new Date(9, 23, 2022), + new Date(9, 24, 2022), + new Date(9, 25, 2022), + new Date(9, 26, 2022), + new Date(9, 27, 2022), + new Date(9, 28, 2022), + new Date(9, 29, 2022), + ], + events: [] as InternalCalendarEvent[], + eventsOnDays: {}, + }, + { + weekStart: new Date(9, 30, 2022), + weekEnd: new Date(10, 5, 2022), + daysInWeek: [ + new Date(9, 30, 2022), + new Date(9, 31, 2022), + new Date(1, 1, 2022), + new Date(1, 2, 2022), + new Date(1, 3, 2022), + new Date(1, 4, 2022), + new Date(1, 5, 2022), + ], + events: [] as InternalCalendarEvent[], + eventsOnDays: {}, + }, +] as InternalEventWeek[]; + const mockUseKeyboardControls = jest.fn(() => null); jest.mock('@/hooks', () => ({ @@ -12,6 +105,33 @@ jest.mock('@/hooks', () => ({ useKeyboardControls: jest.fn(() => mockUseKeyboardControls()), })); +jest.mock('@/providers', () => ({ + EventIntersectionProvider: jest.fn( + ({ children }: { children: ReactNode }) => ( +
{children}
+ ) + ), + HighlightProvider: jest.fn(({ children }: { children: ReactNode }) => ( +
{children}
+ )), +})); + +const mockEventWeekPropsCheck = jest.fn(); +jest.mock('@/layouts/eventWeekLayout', () => ({ + EventWeekLayout: jest.fn(({ events, daysInweek }: EventLayoutProps) => { + mockEventWeekPropsCheck(events, daysInweek); + return
; + }), +})); + +const mockWeekLayoutPropsCheck = jest.fn(); +jest.mock('@/layouts/weekLayout', () => ({ + WeekLayout: jest.fn(({ dates }: WeekLayoutProps) => { + mockWeekLayoutPropsCheck(dates); + return
; + }), +})); + describe('MonthLayout', () => { let testObject: RenderResult; @@ -19,6 +139,30 @@ describe('MonthLayout', () => { testObject = render(); }); + afterEach(() => { + mockUseKeyboardControls.mockClear(); + }); + it('initializes keyboard controls', () => expect(mockUseKeyboardControls).toHaveBeenCalledTimes(1)); + + it('renders one highlight provider', () => + expect(testObject.getAllByTestId('highlight-provider-mock').length).toEqual( + 1 + )); + + it('renders the correct number of intersection providers', () => + expect( + testObject.queryAllByTestId('intersection-provider-mock').length + ).toEqual(mockCalendarWithEvents.length)); + + it('renders the correct number of EventWeekLayout', () => + expect( + testObject.queryAllByTestId('event-week-layout-mock').length + ).toEqual(mockCalendarWithEvents.length)); + + it('renders the correct number of WeekLayout', () => + expect(testObject.queryAllByTestId('week-layout-mock').length).toEqual( + mockCalendarWithEvents.length + )); }); diff --git a/packages/Schedulely/src/layouts/eventWeekLayout/EventWeekLayout.tsx b/packages/Schedulely/src/layouts/eventWeekLayout/EventWeekLayout.tsx index 23fcaa61..3928371c 100644 --- a/packages/Schedulely/src/layouts/eventWeekLayout/EventWeekLayout.tsx +++ b/packages/Schedulely/src/layouts/eventWeekLayout/EventWeekLayout.tsx @@ -6,7 +6,7 @@ import { useEventIntersection, } from '@/hooks'; -interface EventLayoutProps { +export interface EventLayoutProps { events: InternalCalendarEvent[]; daysInweek: Date[]; } diff --git a/packages/Schedulely/src/layouts/weekLayout/WeekLayout.tsx b/packages/Schedulely/src/layouts/weekLayout/WeekLayout.tsx index 6d7907cc..17309880 100644 --- a/packages/Schedulely/src/layouts/weekLayout/WeekLayout.tsx +++ b/packages/Schedulely/src/layouts/weekLayout/WeekLayout.tsx @@ -5,7 +5,7 @@ import { useEventIntersection, } from '@/hooks'; -interface WeekLayoutProps { +export interface WeekLayoutProps { dates: Date[]; } From 38a28a5e5e6f7cf9c0642712e8891bc526640814 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Mon, 31 Oct 2022 13:16:43 -0500 Subject: [PATCH 41/52] finish month layout tests --- .../__tests__/layouts/MonthLayout.spec.tsx | 157 +++++++++++------- 1 file changed, 100 insertions(+), 57 deletions(-) diff --git a/packages/Schedulely/__tests__/layouts/MonthLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/MonthLayout.spec.tsx index 656fec3d..893fdd82 100644 --- a/packages/Schedulely/__tests__/layouts/MonthLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/MonthLayout.spec.tsx @@ -5,91 +5,91 @@ import { RenderResult, render } from '@testing-library/react'; const mockCalendarWithEvents = [ { - weekStart: new Date(8, 25, 2022), - weekEnd: new Date(9, 1, 2022), + weekStart: new Date(2022, 8, 25), + weekEnd: new Date(2022, 9, 1), daysInWeek: [ - new Date(8, 25, 2022), - new Date(8, 26, 2022), - new Date(8, 27, 2022), - new Date(8, 28, 2022), - new Date(8, 29, 2022), - new Date(8, 30, 2022), - new Date(9, 1, 2022), + new Date(2022, 8, 25), + new Date(2022, 8, 26), + new Date(2022, 8, 27), + new Date(2022, 8, 28), + new Date(2022, 8, 29), + new Date(2022, 8, 30), + new Date(2022, 9, 1), ], events: [] as InternalCalendarEvent[], eventsOnDays: {}, }, { - weekStart: new Date(9, 2, 2022), - weekEnd: new Date(9, 8, 2022), + weekStart: new Date(2022, 9, 2), + weekEnd: new Date(2022, 9, 8), daysInWeek: [ - new Date(9, 2, 2022), - new Date(9, 3, 2022), - new Date(9, 4, 2022), - new Date(9, 5, 2022), - new Date(9, 6, 2022), - new Date(9, 7, 2022), - new Date(9, 8, 2022), + new Date(2022, 9, 2), + new Date(2022, 9, 3), + new Date(2022, 9, 4), + new Date(2022, 9, 5), + new Date(2022, 9, 6), + new Date(2022, 9, 7), + new Date(2022, 9, 8), ], events: [] as InternalCalendarEvent[], eventsOnDays: {}, }, { - weekStart: new Date(9, 9, 2022), - weekEnd: new Date(9, 15, 2022), + weekStart: new Date(2022, 9, 9), + weekEnd: new Date(2022, 9, 15), daysInWeek: [ - new Date(9, 9, 2022), - new Date(9, 10, 2022), - new Date(9, 11, 2022), - new Date(9, 12, 2022), - new Date(9, 13, 2022), - new Date(9, 14, 2022), - new Date(9, 15, 2022), + new Date(2022, 9, 9), + new Date(2022, 9, 10), + new Date(2022, 9, 11), + new Date(2022, 9, 12), + new Date(2022, 9, 13), + new Date(2022, 9, 14), + new Date(2022, 9, 15), ], events: [] as InternalCalendarEvent[], eventsOnDays: {}, }, { - weekStart: new Date(9, 16, 2022), - weekEnd: new Date(9, 22, 2022), + weekStart: new Date(2022, 9, 16), + weekEnd: new Date(2022, 9, 22), daysInWeek: [ - new Date(9, 16, 2022), - new Date(9, 17, 2022), - new Date(9, 18, 2022), - new Date(9, 19, 2022), - new Date(9, 20, 2022), - new Date(9, 21, 2022), - new Date(9, 22, 2022), + new Date(2022, 9, 16), + new Date(2022, 9, 17), + new Date(2022, 9, 18), + new Date(2022, 9, 19), + new Date(2022, 9, 20), + new Date(2022, 9, 21), + new Date(2022, 9, 22), ], events: [] as InternalCalendarEvent[], eventsOnDays: {}, }, { - weekStart: new Date(9, 23, 2022), - weekEnd: new Date(9, 29, 2022), + weekStart: new Date(2022, 9, 23), + weekEnd: new Date(2022, 9, 29), daysInWeek: [ - new Date(9, 23, 2022), - new Date(9, 24, 2022), - new Date(9, 25, 2022), - new Date(9, 26, 2022), - new Date(9, 27, 2022), - new Date(9, 28, 2022), - new Date(9, 29, 2022), + new Date(2022, 9, 23), + new Date(2022, 9, 24), + new Date(2022, 9, 25), + new Date(2022, 9, 26), + new Date(2022, 9, 27), + new Date(2022, 9, 28), + new Date(2022, 9, 29), ], events: [] as InternalCalendarEvent[], eventsOnDays: {}, }, { - weekStart: new Date(9, 30, 2022), - weekEnd: new Date(10, 5, 2022), + weekStart: new Date(2022, 9, 30), + weekEnd: new Date(2022, 10, 5), daysInWeek: [ - new Date(9, 30, 2022), - new Date(9, 31, 2022), - new Date(1, 1, 2022), - new Date(1, 2, 2022), - new Date(1, 3, 2022), - new Date(1, 4, 2022), - new Date(1, 5, 2022), + new Date(2022, 9, 30), + new Date(2022, 9, 31), + new Date(2022, 1, 1), + new Date(2022, 1, 2), + new Date(2022, 1, 3), + new Date(2022, 1, 4), + new Date(2022, 1, 5), ], events: [] as InternalCalendarEvent[], eventsOnDays: {}, @@ -105,11 +105,19 @@ jest.mock('@/hooks', () => ({ useKeyboardControls: jest.fn(() => mockUseKeyboardControls()), })); +const mockEventIntersectionProviderPropsCheck = jest.fn(); jest.mock('@/providers', () => ({ EventIntersectionProvider: jest.fn( - ({ children }: { children: ReactNode }) => ( -
{children}
- ) + ({ + children, + events, + }: { + children: ReactNode; + events: InternalCalendarEvent[]; + }) => { + mockEventIntersectionProviderPropsCheck(events); + return
{children}
; + } ), HighlightProvider: jest.fn(({ children }: { children: ReactNode }) => (
{children}
@@ -143,6 +151,41 @@ describe('MonthLayout', () => { mockUseKeyboardControls.mockClear(); }); + describe.each(mockCalendarWithEvents.map((row, i) => ({ ...row, index: i })))( + 'Week $index', + (week) => { + describe('EventWeekLayout', () => { + it('receives array of days', () => { + expect(mockEventWeekPropsCheck.mock.calls[week.index][1]).toEqual( + mockCalendarWithEvents[week.index].daysInWeek + ); + }); + + it('receives array of events', () => { + expect(mockEventWeekPropsCheck.mock.calls[week.index][0]).toEqual( + mockCalendarWithEvents[week.index].events + ); + }); + }); + + describe('WeekLayout', () => { + it('receives array of days', () => { + expect(mockWeekLayoutPropsCheck.mock.calls[week.index][0]).toEqual( + mockCalendarWithEvents[week.index].daysInWeek + ); + }); + }); + + describe('EventIntersectionProvider', () => { + it('receives array of days', () => { + expect( + mockEventIntersectionProviderPropsCheck.mock.calls[week.index][0] + ).toEqual(mockCalendarWithEvents[week.index].events); + }); + }); + } + ); + it('initializes keyboard controls', () => expect(mockUseKeyboardControls).toHaveBeenCalledTimes(1)); From e2a817fcc777519a3fb624919965926b29485b75 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Mon, 31 Oct 2022 13:31:05 -0500 Subject: [PATCH 42/52] make test a bit shallower --- .../__tests__/layouts/WeekLayout.spec.tsx | 47 +++++++++---------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/packages/Schedulely/__tests__/layouts/WeekLayout.spec.tsx b/packages/Schedulely/__tests__/layouts/WeekLayout.spec.tsx index f092b0a3..7adadd30 100644 --- a/packages/Schedulely/__tests__/layouts/WeekLayout.spec.tsx +++ b/packages/Schedulely/__tests__/layouts/WeekLayout.spec.tsx @@ -1,6 +1,5 @@ -import { DefaultDay } from '@/components'; -import { InternalCalendarEvent } from '@/types'; -import { RenderResult, fireEvent, render } from '@testing-library/react'; +import { DayComponentProps, InternalCalendarEvent } from '@/types'; +import { RenderResult, render } from '@testing-library/react'; import { WeekLayout } from '@/layouts'; // Oct 2-8 2022 is the test week @@ -41,9 +40,13 @@ let mockIsSameMonth = jest.fn((date: Date, date2: Date) => true); let mockGetDayNumber = jest.fn((date: Date) => date.getDate()); let mockCurrentDate = jest.fn(() => Date); +const mockDayComponentPropsCheck = jest.fn(); jest.mock('@/hooks', () => ({ useComponents: jest.fn(() => ({ - dayComponent: DefaultDay, + dayComponent: jest.fn((props: DayComponentProps) => { + mockDayComponentPropsCheck(props); + return
; + }), })), useCalendar: jest.fn(() => ({ dateAdapter: { @@ -112,25 +115,19 @@ describe('WeekLayout', () => { it('calls getEventsOnDate', () => expect(mockGetEventsOnDate).toHaveBeenCalledTimes(dates.length)); - describe.each(dates.map((x) => x))('date container for %s', (value) => { - let dayDomObject: HTMLElement; - - beforeEach(() => { - dayDomObject = testObject - .getByText(value.getDate()) - .closest('[role="cell"]')!; - }); - - afterEach(() => { - mockOnMoreEventClick.mockClear(); - }); - - it('is rendered', () => expect(dayDomObject).toBeTruthy()); - - it('calls onMoreEventClick when clicked', () => { - const moreEventObject = dayDomObject.querySelector('[role="note"]')!; - fireEvent.click(moreEventObject); - expect(mockGetEventsOnDate).toHaveBeenCalledTimes(dates.length); - }); - }); + describe.each(dates.map((x, index) => ({ value: x, index })))( + 'date container for %s', + ({ value, index }) => { + it('is rendered', () => + expect( + testObject.getByTestId(value.getDate().toString()) + ).toBeTruthy()); + + it('passes OnMoreEventClickHandler', () => { + expect(mockOnMoreEventClick).toEqual( + mockDayComponentPropsCheck.mock.calls[index][0].onClick + ); + }); + } + ); }); From ff627df0167b861b7b4b99622efc30c08323c3bf Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Mon, 31 Oct 2022 13:34:56 -0500 Subject: [PATCH 43/52] cleanup --- packages/Schedulely/jest.config.js | 1 - packages/Schedulely/src/types/state/CalendarContextState.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/packages/Schedulely/jest.config.js b/packages/Schedulely/jest.config.js index 2c4edc82..6800ea3d 100644 --- a/packages/Schedulely/jest.config.js +++ b/packages/Schedulely/jest.config.js @@ -3,7 +3,6 @@ module.exports = { moduleNameMapper: { '@/(.*)$': '/src/$1', - // '^.+\\.scss$': 'jest-transform-scss', }, testEnvironment: 'jsdom', transform: { diff --git a/packages/Schedulely/src/types/state/CalendarContextState.ts b/packages/Schedulely/src/types/state/CalendarContextState.ts index a048a7db..a96a3e0b 100644 --- a/packages/Schedulely/src/types/state/CalendarContextState.ts +++ b/packages/Schedulely/src/types/state/CalendarContextState.ts @@ -1,4 +1,3 @@ -import { ComponentSize } from '../ComponentSize'; import { DateTimeAdapter } from '..'; import { InternalEventWeek } from '../InternalEventWeek'; From 1e343ca340aa088dcdc9963723d2a19c45941c1f Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Mon, 31 Oct 2022 14:07:02 -0500 Subject: [PATCH 44/52] add keyboard control tests --- .../__tests__/hooks/useActions.spec.tsx | 2 +- .../hooks/useKeyboardControls.spec.tsx | 48 +++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 packages/Schedulely/__tests__/hooks/useKeyboardControls.spec.tsx diff --git a/packages/Schedulely/__tests__/hooks/useActions.spec.tsx b/packages/Schedulely/__tests__/hooks/useActions.spec.tsx index c3fbcfde..df60f4e7 100644 --- a/packages/Schedulely/__tests__/hooks/useActions.spec.tsx +++ b/packages/Schedulely/__tests__/hooks/useActions.spec.tsx @@ -39,7 +39,7 @@ const wrapper = ({ children }: { children: ReactNode }) => ( describe('useActions', () => { const { result: { - current: { onEventClick, onMonthChangeClick, onMoreEventClick }, + current: { onEventClick, onMonthChangeClick }, }, } = renderHook(() => useActions(), { wrapper }); diff --git a/packages/Schedulely/__tests__/hooks/useKeyboardControls.spec.tsx b/packages/Schedulely/__tests__/hooks/useKeyboardControls.spec.tsx new file mode 100644 index 00000000..9942bf8f --- /dev/null +++ b/packages/Schedulely/__tests__/hooks/useKeyboardControls.spec.tsx @@ -0,0 +1,48 @@ +import { RenderResult, fireEvent, render } from '@testing-library/react'; +import { useKeyboardControls } from '@/hooks/useKeyboardControls'; + +const mockOnNextMonth = jest.fn(); +const mockOnPrevMonth = jest.fn(); +const mockOnNextYear = jest.fn(); +const mockOnPrevYear = jest.fn(); +jest.mock('@/hooks/useCalendar', () => ({ + useCalendar: jest.fn(() => ({ + onNextMonth: mockOnNextMonth, + onPrevMonth: mockOnPrevMonth, + onNextYear: mockOnNextYear, + onPrevYear: mockOnPrevYear, + })), +})); + +const TestWrapper = () => { + useKeyboardControls(); + return
; +}; + +describe('useKeyboardControls', () => { + let testObject: RenderResult; + + beforeEach(() => { + testObject = render(); + }); + + it('ArrowUp calls onNextYear', () => { + fireEvent.keyDown(testObject.container, { key: 'ArrowUp' }); + expect(mockOnNextYear).toHaveBeenCalledTimes(1); + }); + + it('ArrowRight calls onNextMonth', () => { + fireEvent.keyDown(testObject.container, { key: 'ArrowRight' }); + expect(mockOnNextMonth).toHaveBeenCalledTimes(1); + }); + + it('ArrowLeft calls onPrevMonth', () => { + fireEvent.keyDown(testObject.container, { key: 'ArrowLeft' }); + expect(mockOnPrevMonth).toHaveBeenCalledTimes(1); + }); + + it('ArrowDown calls onPrevYear', () => { + fireEvent.keyDown(testObject.container, { key: 'ArrowDown' }); + expect(mockOnPrevYear).toHaveBeenCalledTimes(1); + }); +}); From 0215775308910cc1a78c91918c950d25861ebb82 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Mon, 31 Oct 2022 16:23:57 -0500 Subject: [PATCH 45/52] add test --- packages/Schedulely/__tests__/hooks/useActions.spec.tsx | 9 +++++++++ .../__tests__/hooks/useEventHighlight.spec.tsx | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/packages/Schedulely/__tests__/hooks/useActions.spec.tsx b/packages/Schedulely/__tests__/hooks/useActions.spec.tsx index df60f4e7..5a310a2c 100644 --- a/packages/Schedulely/__tests__/hooks/useActions.spec.tsx +++ b/packages/Schedulely/__tests__/hooks/useActions.spec.tsx @@ -2,6 +2,7 @@ import { ActionProvider } from '@/providers'; import { InternalCalendarEvent } from '@/types'; import { ReactNode } from 'react'; import { act } from 'react-test-renderer'; +import { render } from '@testing-library/react'; import { renderHook } from '@testing-library/react-hooks'; import { useActions } from '@/hooks'; @@ -85,4 +86,12 @@ describe('useActions', () => { it('passes correct args', () => expect(onMoreEventClickHandler.mock.calls[0][0]).toEqual(testEvents)); }); + + it('throws when called outside of provider', () => { + const ExceptionWrapper = () => { + expect(useActions).toThrowError(/must be used within/); + return <>; + }; + render(); + }); }); diff --git a/packages/Schedulely/__tests__/hooks/useEventHighlight.spec.tsx b/packages/Schedulely/__tests__/hooks/useEventHighlight.spec.tsx index 0ef70a9e..516b8daf 100644 --- a/packages/Schedulely/__tests__/hooks/useEventHighlight.spec.tsx +++ b/packages/Schedulely/__tests__/hooks/useEventHighlight.spec.tsx @@ -1,6 +1,7 @@ import { HighlightProvider } from '@/providers'; import { ReactNode } from 'react'; import { act } from 'react-test-renderer'; +import { render } from '@testing-library/react'; import { renderHook } from '@testing-library/react-hooks'; import { useEventHighlight } from '@/hooks'; import Chance from 'chance'; @@ -38,4 +39,12 @@ describe('useEventHighlight', () => { act(() => result.current.setHighlight('new-value')); expect(result.current.isHighlighted('new-value')).toBeTruthy(); }); + + it('throws when called outside of provider', () => { + const ExceptionWrapper = () => { + expect(useEventHighlight).toThrowError(/must be used within/); + return <>; + }; + render(); + }); }); From 645e8e7a32350793b982a4d2cb942d51c266bbff Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Mon, 31 Oct 2022 17:19:58 -0500 Subject: [PATCH 46/52] remove extra props --- .../Schedulely/src/layouts/monthLayout/MonthLayout.tsx | 2 +- packages/Schedulely/src/providers/CalendarProvider.tsx | 4 ++-- packages/Schedulely/src/types/InternalEventWeek.ts | 8 ++++++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/Schedulely/src/layouts/monthLayout/MonthLayout.tsx b/packages/Schedulely/src/layouts/monthLayout/MonthLayout.tsx index dfb65311..9d511e7b 100644 --- a/packages/Schedulely/src/layouts/monthLayout/MonthLayout.tsx +++ b/packages/Schedulely/src/layouts/monthLayout/MonthLayout.tsx @@ -16,7 +16,7 @@ export const MonthLayout = () => { {calendarWithEvents.map((week, idx) => (
diff --git a/packages/Schedulely/src/providers/CalendarProvider.tsx b/packages/Schedulely/src/providers/CalendarProvider.tsx index fb963197..c6646810 100644 --- a/packages/Schedulely/src/providers/CalendarProvider.tsx +++ b/packages/Schedulely/src/providers/CalendarProvider.tsx @@ -102,8 +102,8 @@ export const CalendarProvider = ({ const calendarWithEvents = useMemo( () => calendarView.map((week) => ({ - weekStart: week[0], - weekEnd: week[6], + // weekStart: week[0], + // weekEnd: week[6], daysInWeek: week, events: events.filter((event) => dateAdapter.isEventInWeek(event.start, event.end, week) diff --git a/packages/Schedulely/src/types/InternalEventWeek.ts b/packages/Schedulely/src/types/InternalEventWeek.ts index 941ab4f8..115cea96 100644 --- a/packages/Schedulely/src/types/InternalEventWeek.ts +++ b/packages/Schedulely/src/types/InternalEventWeek.ts @@ -1,9 +1,13 @@ import { InternalCalendarEvent } from '@/types'; +/** This represents a single calendar week, including both days, events, and their relationships */ export interface InternalEventWeek { - weekStart: Date; - weekEnd: Date; + /** The calendar days in the week */ daysInWeek: Date[]; + + /** The events that occur within the week */ events: InternalCalendarEvent[]; + + /** The days of the week, with the events that occur on the given date */ eventsOnDays: { date: Date; events: InternalCalendarEvent[] }[]; } From df39fbe56f5b349467dfa9db9e1fcf0980cdfedb Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Mon, 31 Oct 2022 17:22:35 -0500 Subject: [PATCH 47/52] add more docs --- packages/Schedulely/src/types/ComponentSize.ts | 1 + packages/Schedulely/src/types/state/ActionContextState.ts | 1 + packages/Schedulely/src/types/state/BreakpointContextState.ts | 1 + 3 files changed, 3 insertions(+) diff --git a/packages/Schedulely/src/types/ComponentSize.ts b/packages/Schedulely/src/types/ComponentSize.ts index a68c5131..5ec902a7 100644 --- a/packages/Schedulely/src/types/ComponentSize.ts +++ b/packages/Schedulely/src/types/ComponentSize.ts @@ -1 +1,2 @@ +/** The current size of the root schedulely container, based on width */ export type ComponentSize = 'small' | 'medium' | 'large'; diff --git a/packages/Schedulely/src/types/state/ActionContextState.ts b/packages/Schedulely/src/types/state/ActionContextState.ts index 188d925a..ecf1b239 100644 --- a/packages/Schedulely/src/types/state/ActionContextState.ts +++ b/packages/Schedulely/src/types/state/ActionContextState.ts @@ -8,5 +8,6 @@ export interface ActionContextState { /** function that will run when the 'more events' indicator is clicked on */ onMoreEventClick: (event: InternalCalendarEvent[]) => void; + /** function that will run whenever the month of the calendar is changed */ onMonthChangeClick: (firstOfMonth: Date, lastOfMonth: Date) => void; } diff --git a/packages/Schedulely/src/types/state/BreakpointContextState.ts b/packages/Schedulely/src/types/state/BreakpointContextState.ts index 463d949d..14c7ec74 100644 --- a/packages/Schedulely/src/types/state/BreakpointContextState.ts +++ b/packages/Schedulely/src/types/state/BreakpointContextState.ts @@ -1,5 +1,6 @@ import { ComponentSize } from '../ComponentSize'; export type BreakpointContextState = { + /** The current size of the root container */ breakpoint: ComponentSize; }; From e0334ec5c8c0313b076661d7a37a5da0dbfde40f Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Mon, 31 Oct 2022 17:29:33 -0500 Subject: [PATCH 48/52] dead code --- packages/Schedulely/src/providers/CalendarProvider.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/Schedulely/src/providers/CalendarProvider.tsx b/packages/Schedulely/src/providers/CalendarProvider.tsx index c6646810..0da5fab9 100644 --- a/packages/Schedulely/src/providers/CalendarProvider.tsx +++ b/packages/Schedulely/src/providers/CalendarProvider.tsx @@ -102,8 +102,6 @@ export const CalendarProvider = ({ const calendarWithEvents = useMemo( () => calendarView.map((week) => ({ - // weekStart: week[0], - // weekEnd: week[6], daysInWeek: week, events: events.filter((event) => dateAdapter.isEventInWeek(event.start, event.end, week) From 9f4032d857e8e66608141359946a2a5d254db24f Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Mon, 31 Oct 2022 17:44:41 -0500 Subject: [PATCH 49/52] add test files for other hooks --- .../__tests__/hooks/useBreakpoint.spec.tsx | 12 ++++++++++++ .../Schedulely/__tests__/hooks/useCalendar.spec.tsx | 12 ++++++++++++ .../__tests__/hooks/useComponents.spec.tsx | 12 ++++++++++++ .../__tests__/hooks/useEventIntersection.spec.tsx | 12 ++++++++++++ 4 files changed, 48 insertions(+) create mode 100644 packages/Schedulely/__tests__/hooks/useBreakpoint.spec.tsx create mode 100644 packages/Schedulely/__tests__/hooks/useCalendar.spec.tsx create mode 100644 packages/Schedulely/__tests__/hooks/useComponents.spec.tsx create mode 100644 packages/Schedulely/__tests__/hooks/useEventIntersection.spec.tsx diff --git a/packages/Schedulely/__tests__/hooks/useBreakpoint.spec.tsx b/packages/Schedulely/__tests__/hooks/useBreakpoint.spec.tsx new file mode 100644 index 00000000..e88692f3 --- /dev/null +++ b/packages/Schedulely/__tests__/hooks/useBreakpoint.spec.tsx @@ -0,0 +1,12 @@ +import { render } from '@testing-library/react'; +import { useBreakpoint } from '@/hooks'; + +describe('useBreakpoint', () => { + it('throws when called outside of provider', () => { + const ExceptionWrapper = () => { + expect(useBreakpoint).toThrowError(/must be used within/); + return <>; + }; + render(); + }); +}); diff --git a/packages/Schedulely/__tests__/hooks/useCalendar.spec.tsx b/packages/Schedulely/__tests__/hooks/useCalendar.spec.tsx new file mode 100644 index 00000000..15a93fcf --- /dev/null +++ b/packages/Schedulely/__tests__/hooks/useCalendar.spec.tsx @@ -0,0 +1,12 @@ +import { render } from '@testing-library/react'; +import { useCalendar } from '@/hooks'; + +describe('useCalendar', () => { + it('throws when called outside of provider', () => { + const ExceptionWrapper = () => { + expect(useCalendar).toThrowError(/must be used within/); + return <>; + }; + render(); + }); +}); diff --git a/packages/Schedulely/__tests__/hooks/useComponents.spec.tsx b/packages/Schedulely/__tests__/hooks/useComponents.spec.tsx new file mode 100644 index 00000000..6e38c97b --- /dev/null +++ b/packages/Schedulely/__tests__/hooks/useComponents.spec.tsx @@ -0,0 +1,12 @@ +import { render } from '@testing-library/react'; +import { useComponents } from '@/hooks'; + +describe('useComponents', () => { + it('throws when called outside of provider', () => { + const ExceptionWrapper = () => { + expect(useComponents).toThrowError(/must be used within/); + return <>; + }; + render(); + }); +}); diff --git a/packages/Schedulely/__tests__/hooks/useEventIntersection.spec.tsx b/packages/Schedulely/__tests__/hooks/useEventIntersection.spec.tsx new file mode 100644 index 00000000..0cc21e45 --- /dev/null +++ b/packages/Schedulely/__tests__/hooks/useEventIntersection.spec.tsx @@ -0,0 +1,12 @@ +import { render } from '@testing-library/react'; +import { useEventIntersection } from '@/hooks'; + +describe('useEventIntersection', () => { + it('throws when called outside of provider', () => { + const ExceptionWrapper = () => { + expect(useEventIntersection).toThrowError(/must be used within/); + return <>; + }; + render(); + }); +}); From 17694f669b14b4c41cefae6bbd9570df55f70d17 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Mon, 31 Oct 2022 17:51:24 -0500 Subject: [PATCH 50/52] fix turborepo cache issue by upgrading --- package-lock.json | 110 +++++++++++++++++++++++----------------------- package.json | 2 +- turbo.json | 12 ++--- 3 files changed, 63 insertions(+), 61 deletions(-) diff --git a/package-lock.json b/package-lock.json index b4937f5a..93f1a347 100644 --- a/package-lock.json +++ b/package-lock.json @@ -50,7 +50,7 @@ "rollup-plugin-progress": "^1.1.2", "rollup-plugin-ts": "^3.0.2", "sass": "^1.55.0", - "turbo": "1.6.1", + "turbo": "1.6.2", "typescript": "^4.8.3" }, "engines": { @@ -18849,27 +18849,27 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/turbo": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/turbo/-/turbo-1.6.1.tgz", - "integrity": "sha512-CkcJo17cbwfTzmxtxJo2AbbeVqaz1yQotBUqVwZDdcrVSNKci2nvw+JHJ3sy/z9YY9xOJmoRaZifbkja3UXUWA==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/turbo/-/turbo-1.6.2.tgz", + "integrity": "sha512-a6UM9HaAjM5ai+vxDFI/z0l4Bf6zWjf7wCf9Ip2iyd4XZkZZnhRtM6FpaUWzorjz9Dsqnfwu3nkWY3wPdH02IQ==", "dev": true, "hasInstallScript": true, "bin": { "turbo": "bin/turbo" }, "optionalDependencies": { - "turbo-darwin-64": "1.6.1", - "turbo-darwin-arm64": "1.6.1", - "turbo-linux-64": "1.6.1", - "turbo-linux-arm64": "1.6.1", - "turbo-windows-64": "1.6.1", - "turbo-windows-arm64": "1.6.1" + "turbo-darwin-64": "1.6.2", + "turbo-darwin-arm64": "1.6.2", + "turbo-linux-64": "1.6.2", + "turbo-linux-arm64": "1.6.2", + "turbo-windows-64": "1.6.2", + "turbo-windows-arm64": "1.6.2" } }, "node_modules/turbo-darwin-64": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-1.6.1.tgz", - "integrity": "sha512-xsItJ/hmnd6R8V60cCe0RAZQjO+En/LVXVkZhiw0Fyfxoo+iKcAA4sVeWkaL+cg5sQd5UWlWfD1EOKbHDjVb9Q==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-1.6.2.tgz", + "integrity": "sha512-qzqVdJZcVeu1d0mzeSxffgeOToSgM+Hl1y9yDiJQ4QQjiR/WGCzS9FtydLnk0ori8T1j/lxiiQz2sHjHYfLCTg==", "cpu": [ "x64" ], @@ -18880,9 +18880,9 @@ ] }, "node_modules/turbo-darwin-arm64": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-1.6.1.tgz", - "integrity": "sha512-wRfAJWCLYB29IGTx6sF6QvexK/89AbAgnfYA5yVcuUJT+xz2/zLeGcOODQBCnP4rB+vX5ipXLY0XjkLGl+z6fA==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-1.6.2.tgz", + "integrity": "sha512-EJvgWSjLwzJbAsqRuqeaYSdXNKwyiUfOfEOPerYCvwxC+ILiqpladjteMCzzF/z2OmIbPzuqZpyik30TfpIC9A==", "cpu": [ "arm64" ], @@ -18893,9 +18893,9 @@ ] }, "node_modules/turbo-linux-64": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-1.6.1.tgz", - "integrity": "sha512-NZ88muC3hHbWW/cBgl9DFFbyzDcFVvZHQBXKTwVA8l2yLOOvesX+aQ2Knr4Pxu9Kb0F3t6ABsOSf8SbI7CpJsg==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-1.6.2.tgz", + "integrity": "sha512-SJ5ThDApOyOavjvkYb6a1MKJbOvX4JEvSYxoZv+ZpN8g7A7x1SE9b7EnxFl26S4eyy0J4+r+YJBDBZ7sFkqRWQ==", "cpu": [ "x64" ], @@ -18906,9 +18906,9 @@ ] }, "node_modules/turbo-linux-arm64": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-1.6.1.tgz", - "integrity": "sha512-HDgx+0ozqMpoDBOSzWz43nYMDp/+giEz8+vmLOB6mTQU/9IlZQVwachzwkqLRsJyBUhYALBlWGcuRWO3KqXMmg==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-1.6.2.tgz", + "integrity": "sha512-0vHojVlvAelsYZo6p/xE9H9Dg8spNjXx+PO5RwP12ui8GuEqHb3Vomdb7AKDnWkIH7bpysNb9GbKEk7awQpGSg==", "cpu": [ "arm64" ], @@ -18919,9 +18919,9 @@ ] }, "node_modules/turbo-windows-64": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-1.6.1.tgz", - "integrity": "sha512-jnR0V0YBlFJKEoAeq0GQFLmZ1UNl6vh+RHTHX546+o5jKcE6nfp9oTOEwtR0PLutiuxxDDm6roAc+9mSfycffw==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-1.6.2.tgz", + "integrity": "sha512-j4mJmY5pEt7OaBXDM99BpDnJuSpiLVbVbUl4Ezp8w3gyIcGuxy3wAfLbQyZSLu8ke6R9SdmXIBAM2Y0MjS/Z1g==", "cpu": [ "x64" ], @@ -18932,9 +18932,9 @@ ] }, "node_modules/turbo-windows-arm64": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/turbo-windows-arm64/-/turbo-windows-arm64-1.6.1.tgz", - "integrity": "sha512-vOqw/iPgLjkwpni2vNFK9YO19lN9QZ8JG8v1unvL09/rnXyKpHygrYECj+efJptEVJKBG2xLIauJYmZ/2LV1Uw==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/turbo-windows-arm64/-/turbo-windows-arm64-1.6.2.tgz", + "integrity": "sha512-AlDYjxPU21YSefP3qMl/Zys5spglXtaBt2ZF5N2+OWcjiJZ/0mIIc69oFdzuAuiyoYkyWMdkoCSGwuljtl31vg==", "cpu": [ "arm64" ], @@ -34404,58 +34404,58 @@ } }, "turbo": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/turbo/-/turbo-1.6.1.tgz", - "integrity": "sha512-CkcJo17cbwfTzmxtxJo2AbbeVqaz1yQotBUqVwZDdcrVSNKci2nvw+JHJ3sy/z9YY9xOJmoRaZifbkja3UXUWA==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/turbo/-/turbo-1.6.2.tgz", + "integrity": "sha512-a6UM9HaAjM5ai+vxDFI/z0l4Bf6zWjf7wCf9Ip2iyd4XZkZZnhRtM6FpaUWzorjz9Dsqnfwu3nkWY3wPdH02IQ==", "dev": true, "requires": { - "turbo-darwin-64": "1.6.1", - "turbo-darwin-arm64": "1.6.1", - "turbo-linux-64": "1.6.1", - "turbo-linux-arm64": "1.6.1", - "turbo-windows-64": "1.6.1", - "turbo-windows-arm64": "1.6.1" + "turbo-darwin-64": "1.6.2", + "turbo-darwin-arm64": "1.6.2", + "turbo-linux-64": "1.6.2", + "turbo-linux-arm64": "1.6.2", + "turbo-windows-64": "1.6.2", + "turbo-windows-arm64": "1.6.2" } }, "turbo-darwin-64": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-1.6.1.tgz", - "integrity": "sha512-xsItJ/hmnd6R8V60cCe0RAZQjO+En/LVXVkZhiw0Fyfxoo+iKcAA4sVeWkaL+cg5sQd5UWlWfD1EOKbHDjVb9Q==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-1.6.2.tgz", + "integrity": "sha512-qzqVdJZcVeu1d0mzeSxffgeOToSgM+Hl1y9yDiJQ4QQjiR/WGCzS9FtydLnk0ori8T1j/lxiiQz2sHjHYfLCTg==", "dev": true, "optional": true }, "turbo-darwin-arm64": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-1.6.1.tgz", - "integrity": "sha512-wRfAJWCLYB29IGTx6sF6QvexK/89AbAgnfYA5yVcuUJT+xz2/zLeGcOODQBCnP4rB+vX5ipXLY0XjkLGl+z6fA==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-1.6.2.tgz", + "integrity": "sha512-EJvgWSjLwzJbAsqRuqeaYSdXNKwyiUfOfEOPerYCvwxC+ILiqpladjteMCzzF/z2OmIbPzuqZpyik30TfpIC9A==", "dev": true, "optional": true }, "turbo-linux-64": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-1.6.1.tgz", - "integrity": "sha512-NZ88muC3hHbWW/cBgl9DFFbyzDcFVvZHQBXKTwVA8l2yLOOvesX+aQ2Knr4Pxu9Kb0F3t6ABsOSf8SbI7CpJsg==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-1.6.2.tgz", + "integrity": "sha512-SJ5ThDApOyOavjvkYb6a1MKJbOvX4JEvSYxoZv+ZpN8g7A7x1SE9b7EnxFl26S4eyy0J4+r+YJBDBZ7sFkqRWQ==", "dev": true, "optional": true }, "turbo-linux-arm64": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-1.6.1.tgz", - "integrity": "sha512-HDgx+0ozqMpoDBOSzWz43nYMDp/+giEz8+vmLOB6mTQU/9IlZQVwachzwkqLRsJyBUhYALBlWGcuRWO3KqXMmg==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-1.6.2.tgz", + "integrity": "sha512-0vHojVlvAelsYZo6p/xE9H9Dg8spNjXx+PO5RwP12ui8GuEqHb3Vomdb7AKDnWkIH7bpysNb9GbKEk7awQpGSg==", "dev": true, "optional": true }, "turbo-windows-64": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-1.6.1.tgz", - "integrity": "sha512-jnR0V0YBlFJKEoAeq0GQFLmZ1UNl6vh+RHTHX546+o5jKcE6nfp9oTOEwtR0PLutiuxxDDm6roAc+9mSfycffw==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-1.6.2.tgz", + "integrity": "sha512-j4mJmY5pEt7OaBXDM99BpDnJuSpiLVbVbUl4Ezp8w3gyIcGuxy3wAfLbQyZSLu8ke6R9SdmXIBAM2Y0MjS/Z1g==", "dev": true, "optional": true }, "turbo-windows-arm64": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/turbo-windows-arm64/-/turbo-windows-arm64-1.6.1.tgz", - "integrity": "sha512-vOqw/iPgLjkwpni2vNFK9YO19lN9QZ8JG8v1unvL09/rnXyKpHygrYECj+efJptEVJKBG2xLIauJYmZ/2LV1Uw==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/turbo-windows-arm64/-/turbo-windows-arm64-1.6.2.tgz", + "integrity": "sha512-AlDYjxPU21YSefP3qMl/Zys5spglXtaBt2ZF5N2+OWcjiJZ/0mIIc69oFdzuAuiyoYkyWMdkoCSGwuljtl31vg==", "dev": true, "optional": true }, diff --git a/package.json b/package.json index a8389524..3ff6358d 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "rollup-plugin-progress": "^1.1.2", "rollup-plugin-ts": "^3.0.2", "sass": "^1.55.0", - "turbo": "1.6.1", + "turbo": "1.6.2", "typescript": "^4.8.3" }, "engines": { diff --git a/turbo.json b/turbo.json index 9cfdd4cd..337fcbd0 100644 --- a/turbo.json +++ b/turbo.json @@ -12,13 +12,15 @@ ] }, "test": { - "dependsOn": [], + "dependsOn": [ + "lint" + ], "outputs": [], "inputs": [ - "./src/**/*.tsx", - "./src/**/*.ts", - "./__tests__/**/*.tsx", - "./__tests__/**/*.ts" + "src/**/*.tsx", + "src/**/*.ts", + "__tests__/**/*.tsx", + "__tests__/**/*.ts" ] }, "rollup": { From 7e1b1958fd13f926a62b2b429ff2a8509b230fd1 Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Mon, 31 Oct 2022 17:54:00 -0500 Subject: [PATCH 51/52] turborepo is fixed, so additional build tasks can be queued now --- .husky/pre-commit | 1 - turbo.json | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.husky/pre-commit b/.husky/pre-commit index 660b8209..d1096ab1 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,5 +1,4 @@ #!/bin/sh . "$(dirname "$0")/_/husky.sh" -npm run lint npm run test diff --git a/turbo.json b/turbo.json index 337fcbd0..37d9a360 100644 --- a/turbo.json +++ b/turbo.json @@ -13,7 +13,8 @@ }, "test": { "dependsOn": [ - "lint" + "lint", + "barrels" ], "outputs": [], "inputs": [ From f5b68f65ea62d328bdfd1c19caf7b96ee4cdae3a Mon Sep 17 00:00:00 2001 From: Bruce Harrison Date: Tue, 1 Nov 2022 10:11:13 -0500 Subject: [PATCH 52/52] cover useActions --- .../__tests__/hooks/useActions.spec.tsx | 66 +++++++++++++------ .../src/providers/ActionProvider.tsx | 37 ++++------- 2 files changed, 61 insertions(+), 42 deletions(-) diff --git a/packages/Schedulely/__tests__/hooks/useActions.spec.tsx b/packages/Schedulely/__tests__/hooks/useActions.spec.tsx index 5a310a2c..13c742fa 100644 --- a/packages/Schedulely/__tests__/hooks/useActions.spec.tsx +++ b/packages/Schedulely/__tests__/hooks/useActions.spec.tsx @@ -18,12 +18,10 @@ const testEvents: InternalCalendarEvent[] = [ ]; const onEventClickHandler = jest.fn((event: InternalCalendarEvent) => null); -const onMonthChangeClickHandler = jest.fn( +let onMonthChangeClickHandler = jest.fn( (firstOfMonth: Date, lastOfMonth: Date) => null ); -const onMoreEventClickHandler = jest.fn( - (event: InternalCalendarEvent[]) => null -); +let onMoreEventClickHandler = jest.fn((event: InternalCalendarEvent[]) => null); const wrapper = ({ children }: { children: ReactNode }) => ( ( describe('useActions', () => { const { result: { - current: { onEventClick, onMonthChangeClick }, + current: { onEventClick, onMonthChangeClick, onMoreEventClick }, }, } = renderHook(() => useActions(), { wrapper }); describe('onEventClick', () => { - act(() => { - onEventClick(testEvents[0]); - }); + onEventClick(testEvents[0]); it('invokes correct function', () => { expect(onEventClickHandler).toHaveBeenCalled(); @@ -60,9 +56,8 @@ describe('useActions', () => { describe('onMonthChangeClick', () => { const monthStart = new Date(2000, 1, 1); const monthEnd = new Date(2000, 2, 1); - act(() => { - onMonthChangeClick(monthStart, monthEnd); - }); + + onMonthChangeClick(monthStart, monthEnd); it('invokes correct function', () => { expect(onMonthChangeClickHandler).toHaveBeenCalled(); @@ -75,16 +70,16 @@ describe('useActions', () => { }); describe('onMoreEventClick', () => { - act(() => { - onMoreEventClickHandler(testEvents); - }); + describe('when defined', () => { + onMoreEventClick(testEvents); - it('invokes correct function', () => { - expect(onMoreEventClickHandler).toHaveBeenCalled(); - }); + it('invokes correct function', () => { + expect(onMoreEventClickHandler).toHaveBeenCalled(); + }); - it('passes correct args', () => - expect(onMoreEventClickHandler.mock.calls[0][0]).toEqual(testEvents)); + it('passes correct args', () => + expect(onMoreEventClickHandler.mock.calls[0][0]).toEqual(testEvents)); + }); }); it('throws when called outside of provider', () => { @@ -94,4 +89,37 @@ describe('useActions', () => { }; render(); }); + + describe('if Action undefined', () => { + const emptyWrapper = ({ children }: { children: ReactNode }) => ( + {children} + ); + + const { + result: { + current: { onEventClick, onMonthChangeClick, onMoreEventClick }, + }, + } = renderHook(() => useActions(), { wrapper: emptyWrapper }); + + beforeEach(() => { + onMoreEventClickHandler.mockClear(); + onEventClickHandler.mockClear(); + onMonthChangeClickHandler.mockClear(); + }); + + it('does not invoke onMoreEventClick if not defined', () => { + onMoreEventClick(testEvents); + expect(onMoreEventClickHandler).not.toHaveBeenCalled(); + }); + + it('does not invoke onEventClick if not defined', () => { + onEventClick(testEvents[0]); + expect(onEventClickHandler).not.toHaveBeenCalled(); + }); + + it('does not invoke onMonthChangeClick if not defined', () => { + onMonthChangeClick(new Date(), new Date()); + expect(onMonthChangeClickHandler).not.toHaveBeenCalled(); + }); + }); }); diff --git a/packages/Schedulely/src/providers/ActionProvider.tsx b/packages/Schedulely/src/providers/ActionProvider.tsx index 7080c3ee..3f41b41a 100644 --- a/packages/Schedulely/src/providers/ActionProvider.tsx +++ b/packages/Schedulely/src/providers/ActionProvider.tsx @@ -1,4 +1,4 @@ -import { ActionContextState, InternalCalendarEvent } from '@/types'; +import { ActionContextState } from '@/types'; import { PropsWithChildren, createContext, useCallback } from 'react'; export const ActionContext = createContext(null); @@ -19,33 +19,24 @@ export const ActionProvider = ({ children, actions, }: PropsWithChildren) => { - const onEventClick = actions?.onEventClick - ? actions?.onEventClick - : (event: InternalCalendarEvent) => console.log(event); - - const onMoreEventClick = actions?.onMoreEventClick - ? actions?.onMoreEventClick - : (events: InternalCalendarEvent[]) => console.log(events); + const onEventClick = useCallback(actions?.onEventClick || (() => null), [ + actions?.onEventClick, + ]); - const onMonthChangeClick = actions?.onMonthChangeClick - ? actions?.onMonthChangeClick - : (firstOfMonth: Date, lastOfMonth: Date) => - console.log({ firstOfMonth, lastOfMonth }); + const onMoreEventClick = useCallback( + actions?.onMoreEventClick || (() => null), + [actions?.onMoreEventClick] + ); - const memoizedOnEventClick = useCallback(onEventClick, [onEventClick]); + const onMonthChangeClick = useCallback( + actions?.onMonthChangeClick || (() => null), + [actions?.onMonthChangeClick] + ); - const memoizedOnMoreEventClick = useCallback(onMoreEventClick, [ + const context: ActionContextState = { + onEventClick, onMoreEventClick, - ]); - - const memoizedOnMonthChangeClick = useCallback(onMonthChangeClick, [ onMonthChangeClick, - ]); - - const context: ActionContextState = { - onEventClick: memoizedOnEventClick, - onMoreEventClick: memoizedOnMoreEventClick, - onMonthChangeClick: memoizedOnMonthChangeClick, }; return (