From a1f2f69be95bb62550b6483598b08ef41c0cb02b Mon Sep 17 00:00:00 2001 From: "Nalivaiko, Aleksej" Date: Fri, 7 Jun 2024 12:39:47 +0300 Subject: [PATCH] M2-6837: [Mobile] Complete test coverage for ScheduledDateCalculator --- .../operations/ScheduledDateCalculator.ts | 30 +++++---- ...ScheduledDateCalculator.edge-cases.test.ts | 64 +++++++++++++++++++ .../ScheduledDateCalculator.monthly.test.ts | 6 +- .../ScheduledDateCalculator.test.js | 4 +- 4 files changed, 85 insertions(+), 19 deletions(-) create mode 100644 src/entities/event/model/operations/tests/ScheduledDateCalculator.edge-cases.test.ts rename src/entities/event/model/operations/{ => tests}/ScheduledDateCalculator.monthly.test.ts (98%) rename src/entities/event/model/operations/{ => tests}/ScheduledDateCalculator.test.js (99%) diff --git a/src/entities/event/model/operations/ScheduledDateCalculator.ts b/src/entities/event/model/operations/ScheduledDateCalculator.ts index ea11cba20..48744ef02 100644 --- a/src/entities/event/model/operations/ScheduledDateCalculator.ts +++ b/src/entities/event/model/operations/ScheduledDateCalculator.ts @@ -18,9 +18,9 @@ import { type EventParseInput = Parameters[0]; -const cache = new Map(); - export class ScheduledDateCalculator { + private cache = new Map(); + constructor() {} private setTime(target: Date, availability: EventAvailability) { @@ -34,6 +34,12 @@ export class ScheduledDateCalculator { return new Date(); } + private getCacheKey(event: ScheduleEvent): string { + const today = this.getNow().toDateString(); + + return `${JSON.stringify(event.availability)}${event.selectedDate?.getTime() ?? ''}${today}`; + } + private calculateForMonthly( selectedDate: Date, availability: EventAvailability, @@ -87,7 +93,7 @@ export class ScheduledDateCalculator { return result; } - private calculateScheduledAt(event: ScheduleEvent): Date | null { + private calculateInternal(event: ScheduleEvent): Date | null { const { availability, selectedDate } = event; const now = this.getNow(); @@ -158,22 +164,18 @@ export class ScheduledDateCalculator { useCache: boolean = true, ): Date | null { if (!useCache) { - return this.calculateScheduledAt(event); + return this.calculateInternal(event); } - const today = this.getNow().toDateString(); - - const key = - JSON.stringify(event.availability) + - (event.selectedDate?.getTime() ?? '') + - today; + const key = this.getCacheKey(event); - if (cache.has(key)) { - return cache.get(key); + if (this.cache.has(key)) { + return this.cache.get(key) as Date; } - const result = this.calculateScheduledAt(event); - cache.set(key, result); + const result = this.calculateInternal(event); + + this.cache.set(key, result); return result; } diff --git a/src/entities/event/model/operations/tests/ScheduledDateCalculator.edge-cases.test.ts b/src/entities/event/model/operations/tests/ScheduledDateCalculator.edge-cases.test.ts new file mode 100644 index 000000000..e7003644e --- /dev/null +++ b/src/entities/event/model/operations/tests/ScheduledDateCalculator.edge-cases.test.ts @@ -0,0 +1,64 @@ +import { AvailabilityType, PeriodicityType } from '@app/abstract/lib'; + +import { + EventAvailability, + ScheduleEvent, +} from '../../../lib/types/scheduledDateCalculator'; +import { ScheduledDateCalculator } from '../ScheduledDateCalculator'; + +const createEvent = () => { + const eventAvailability: EventAvailability = { + availabilityType: AvailabilityType.AlwaysAvailable, + periodicityType: PeriodicityType.Always, + timeFrom: null, + timeTo: null, + startDate: null, + endDate: null, + }; + + const scheduleEvent: ScheduleEvent = { + id: 'eventTestId', + entityId: 'entityTestId', + availability: eventAvailability, + selectedDate: null, + scheduledAt: null, + }; + + return scheduleEvent; +}; + +describe('Test ScheduledDateCalculator: edge cases and cache', () => { + it('Should take value from cache when call calculate 2nd time with the same event settings', () => { + const calculator = new ScheduledDateCalculator(); + + const mockDate = new Date(2023, 5, 10); + + const calculateInternalMock = jest.fn().mockReturnValue(mockDate); + //@ts-expect-error + calculator.calculateInternal = calculateInternalMock; + + const scheduleEvent = createEvent(); + + const result = calculator.calculate(scheduleEvent); + + expect(result).toEqual(mockDate); + + const secondResult = calculator.calculate({ ...scheduleEvent }); + + expect(secondResult).toEqual(mockDate); + + expect(calculateInternalMock).toHaveBeenCalledTimes(1); + }); + + it('Should throw error if to pass event with time set in the selectedDate', () => { + const calculator = new ScheduledDateCalculator(); + + const scheduleEvent = createEvent(); + + scheduleEvent.selectedDate = new Date(2023, 10, 5, 15, 30); + + expect(() => calculator.calculate(scheduleEvent)).toThrow( + '[ScheduledDateCalculator]: selectedDate contains time set', + ); + }); +}); diff --git a/src/entities/event/model/operations/ScheduledDateCalculator.monthly.test.ts b/src/entities/event/model/operations/tests/ScheduledDateCalculator.monthly.test.ts similarity index 98% rename from src/entities/event/model/operations/ScheduledDateCalculator.monthly.test.ts rename to src/entities/event/model/operations/tests/ScheduledDateCalculator.monthly.test.ts index c46391bba..f9ed97072 100644 --- a/src/entities/event/model/operations/ScheduledDateCalculator.monthly.test.ts +++ b/src/entities/event/model/operations/tests/ScheduledDateCalculator.monthly.test.ts @@ -2,10 +2,10 @@ import { addDays, addMonths, startOfDay, subDays, subMonths } from 'date-fns'; import { AvailabilityType, PeriodicityType } from '@app/abstract/lib'; -import { ScheduledDateCalculator } from './ScheduledDateCalculator'; -import { ScheduleEvent } from '../../lib/types/scheduledDateCalculator'; +import { ScheduleEvent } from '../../../lib/types/scheduledDateCalculator'; +import { ScheduledDateCalculator } from '../ScheduledDateCalculator'; -describe('ScheduledDateCalculator: test monthly events', () => { +describe('Test ScheduledDateCalculator: monthly events', () => { const getScheduledDateCalculator = (now: Date) => { const instance = new ScheduledDateCalculator(); //@ts-expect-error diff --git a/src/entities/event/model/operations/ScheduledDateCalculator.test.js b/src/entities/event/model/operations/tests/ScheduledDateCalculator.test.js similarity index 99% rename from src/entities/event/model/operations/ScheduledDateCalculator.test.js rename to src/entities/event/model/operations/tests/ScheduledDateCalculator.test.js index eaa6c428d..17831ed35 100644 --- a/src/entities/event/model/operations/ScheduledDateCalculator.test.js +++ b/src/entities/event/model/operations/tests/ScheduledDateCalculator.test.js @@ -1,10 +1,10 @@ import { addDays, startOfDay, subDays } from 'date-fns'; -import ScheduledDateCalculator from './ScheduledDateCalculator'; +import ScheduledDateCalculator from '../ScheduledDateCalculator'; const now = new Date(2024, 0, 25); -describe('ScheduledDateCalculator', () => { +describe('Test ScheduledDateCalculator', () => { let tempGetNow; beforeAll(() => {