diff --git a/packages/core/src/__mocks__/v1/events/events.misc.ts b/packages/core/src/__mocks__/v1/events/events.misc.ts index 3e817ff4d..f2938fcb9 100644 --- a/packages/core/src/__mocks__/v1/events/events.misc.ts +++ b/packages/core/src/__mocks__/v1/events/events.misc.ts @@ -74,7 +74,7 @@ export const GROCERIES: Schema_Event = { priorities: [], isAllDay: false, startDate: "2022-02-21T11:45:00-06:00", - endDate: "2022-02-212T12:45:00-06:00", + endDate: "2022-02-21T12:45:00-06:00", priority: Priorities.RELATIONS, }; export const MULTI_WEEK: Schema_Event = { diff --git a/packages/web/src/__tests__/Calendar/calendar.render.test.tsx b/packages/web/src/__tests__/Calendar/calendar.render.test.tsx index ae668978f..b10e735f1 100644 --- a/packages/web/src/__tests__/Calendar/calendar.render.test.tsx +++ b/packages/web/src/__tests__/Calendar/calendar.render.test.tsx @@ -1,6 +1,9 @@ import React from "react"; import "@testing-library/jest-dom"; import { screen, waitFor } from "@testing-library/react"; +import { GROCERIES } from "@core/__mocks__/v1/events/events.misc"; +import { findAndUpdateEventInPreloadedState } from "@web/__tests__/Calendar/calendar.render.test.utils"; +import { freshenEventStartEndDate } from "@web/__tests__/Calendar/calendar.render.test.utils"; import { preloadedState } from "@web/__tests__/__mocks__/state/state.weekEvents"; import { getWeekDayLabel } from "@web/common/utils/event.util"; import { CalendarView } from "@web/views/Calendar"; @@ -52,9 +55,15 @@ describe("Calendar: Display without State", () => { }); describe("Calendar: Display with State", () => { - it("dispays timed events", async () => { + it("displays timed events", async () => { + const newPreloadedState = findAndUpdateEventInPreloadedState( + preloadedState, + GROCERIES._id as string, + freshenEventStartEndDate, + ); + await waitFor(() => { - render(, { state: preloadedState }); + render(, { state: newPreloadedState }); }); expect( screen.getByRole("button", { name: /groceries/i }), diff --git a/packages/web/src/__tests__/Calendar/calendar.render.test.utils.ts b/packages/web/src/__tests__/Calendar/calendar.render.test.utils.ts new file mode 100644 index 000000000..35e3c494f --- /dev/null +++ b/packages/web/src/__tests__/Calendar/calendar.render.test.utils.ts @@ -0,0 +1,40 @@ +import dayjs from "dayjs"; +import { PreloadedState } from "redux"; +import { Schema_Event } from "@core/types/event.types"; + +export const freshenEventStartEndDate = (event: Schema_Event): Schema_Event => { + const newStartDate = dayjs(new Date()).add(1, "day").format(); + const newEndDate = dayjs(new Date()).add(3, "day").format(); + return { ...event, startDate: newStartDate, endDate: newEndDate }; +}; + +export const findAndUpdateEventInPreloadedState = ( + preloadedState: ReturnType, + eventId: string, + callback: (event: Schema_Event) => Schema_Event, +) => { + if (!eventId) { + throw new Error("Event ID is required"); + } + + const event = preloadedState.events.entities.value[eventId]; + if (!event) { + throw new Error(`Event with id ${eventId} not found`); + } + + const newPreloadedState = { + ...preloadedState, + events: { + ...preloadedState.events, + entities: { + ...preloadedState.events.entities, + value: { + ...preloadedState.events.entities.value, + [eventId]: callback(event), + }, + }, + }, + }; + + return newPreloadedState; +}; diff --git a/packages/web/src/__tests__/__mocks__/server/mock.handlers.ts b/packages/web/src/__tests__/__mocks__/server/mock.handlers.ts index 7a18700ec..eb1995e27 100644 --- a/packages/web/src/__tests__/__mocks__/server/mock.handlers.ts +++ b/packages/web/src/__tests__/__mocks__/server/mock.handlers.ts @@ -7,6 +7,7 @@ import { MULTI_WEEK, TY_TIM, } from "@core/__mocks__/v1/events/events.misc"; +import { freshenEventStartEndDate } from "@web/__tests__/Calendar/calendar.render.test.utils"; import { ENV_WEB } from "@web/common/constants/env.constants"; export const globalHandlers = [ @@ -28,7 +29,14 @@ export const globalHandlers = [ ); } - const events = [CLIMB, MARCH_1, MULTI_WEEK, TY_TIM, GROCERIES]; + const events = [ + CLIMB, + MARCH_1, + MULTI_WEEK, + TY_TIM, + // TODO: Need some way to inject the event into globalHandlers.events in a more dynamic way. + freshenEventStartEndDate(GROCERIES), + ]; return res(ctx.json(events)); }), rest.delete(`${ENV_WEB.API_BASEURL}/event/:id`, (req, res, ctx) => { diff --git a/packages/web/src/ducks/events/sagas/event.sagas.ts b/packages/web/src/ducks/events/sagas/event.sagas.ts index d297c2719..5732b11d1 100644 --- a/packages/web/src/ducks/events/sagas/event.sagas.ts +++ b/packages/web/src/ducks/events/sagas/event.sagas.ts @@ -37,6 +37,7 @@ import { import { getSomedayEventsSlice } from "../slices/someday.slice"; import { getWeekEventsSlice } from "../slices/week.slice"; import { + EventDateUtils, insertOptimisticEvent, normalizedEventsSchema, replaceOptimisticId, @@ -161,12 +162,21 @@ function* getEvents( yield put(eventsEntitiesSlice.actions.insert(payload.data)); return { data: payload.data }; } + + const _payload = EventDateUtils.adjustStartEndDate(payload); + const res: Response_GetEventsSuccess = (yield call( EventApi.get, - payload, + _payload, )) as Response_GetEventsSuccess; - const normalizedEvents = normalize(res.data, [ + const events = EventDateUtils.filterEventsByStartEndDate( + res.data, + payload.startDate, + payload.endDate, + ); + + const normalizedEvents = normalize(events, [ normalizedEventsSchema(), ]); diff --git a/packages/web/src/ducks/events/sagas/saga.util.ts b/packages/web/src/ducks/events/sagas/saga.util.ts index 98eb07c13..678b466b9 100644 --- a/packages/web/src/ducks/events/sagas/saga.util.ts +++ b/packages/web/src/ducks/events/sagas/saga.util.ts @@ -1,7 +1,8 @@ +import dayjs from "dayjs"; import { schema } from "normalizr"; import { normalize } from "normalizr"; import { put, select } from "redux-saga/effects"; -import { Schema_Event } from "@core/types/event.types"; +import { Params_Events, Schema_Event } from "@core/types/event.types"; import { Schema_GridEvent } from "@web/common/types/web.event.types"; import { RootState } from "@web/store"; import { selectEventById } from "../selectors/event.selectors"; @@ -63,3 +64,43 @@ export function* replaceOptimisticId( export const normalizedEventsSchema = () => new schema.Entity("events", {}, { idAttribute: "_id" }); + +// Meant to be a hotfix to address issue where backend returns date +// filtered events in an inconsistent way. +// See https://github.com/SwitchbackTech/compass/issues/428 +// Should be removed after backend is fixed +export const EventDateUtils = { + /** + * Adjusts start and end dates for event queries + */ + adjustStartEndDate: (payload: Params_Events) => { + if (payload.someday) return payload; + + // Make start date 1 day before the start date + const startDate = dayjs(payload.startDate).subtract(1, "day").format(); + const endDate = payload.endDate; + + return { + ...payload, + startDate, + endDate, + }; + }, + + /** + * Filters events by start and end date range + * Handles comparison between different date formats (raw dates vs ISO 8601) + */ + filterEventsByStartEndDate: ( + events: Schema_Event[], + startDate: string, + endDate: string, + ) => { + return events.filter((event) => { + return ( + dayjs(event.startDate).isSameOrAfter(startDate) && + dayjs(event.endDate).isSameOrBefore(endDate) + ); + }); + }, +} as const;