fix: update tests for new Menubar UI implementation
- Remove refresh button test from Calendar.test.tsx - Update Menubar tests to pass required props (calendarRef, onRefresh, currentDate) - Update Calendar tests to pass calendarRef prop - Remove outdated test cases from MiniCalendarColor.test.tsx that tested old headerToolbar - Format code with prettier
This commit is contained in:
@@ -127,7 +127,8 @@ describe("CalendarSelection", () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
it("renders calendars", async () => {
|
it("renders calendars", async () => {
|
||||||
renderWithProviders(<CalendarApp />, preloadedState);
|
const mockCalendarRef = { current: null };
|
||||||
|
renderWithProviders(<CalendarApp calendarRef={mockCalendarRef} />, preloadedState);
|
||||||
expect(screen.getByText("Personnal Calendars")).toBeInTheDocument();
|
expect(screen.getByText("Personnal Calendars")).toBeInTheDocument();
|
||||||
expect(screen.getByText("Delegated Calendars")).toBeInTheDocument();
|
expect(screen.getByText("Delegated Calendars")).toBeInTheDocument();
|
||||||
expect(screen.getByText("Other Calendars")).toBeInTheDocument();
|
expect(screen.getByText("Other Calendars")).toBeInTheDocument();
|
||||||
@@ -136,26 +137,9 @@ describe("CalendarSelection", () => {
|
|||||||
expect(screen.getByLabelText("Calendar delegated")).toBeInTheDocument();
|
expect(screen.getByLabelText("Calendar delegated")).toBeInTheDocument();
|
||||||
expect(screen.getByLabelText("Calendar shared")).toBeInTheDocument();
|
expect(screen.getByLabelText("Calendar shared")).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
it("refresh calendars", async () => {
|
|
||||||
const spy = jest
|
|
||||||
.spyOn(eventThunks, "getCalendarDetailAsync")
|
|
||||||
.mockImplementation((payload) => {
|
|
||||||
return () => Promise.resolve(payload) as any;
|
|
||||||
});
|
|
||||||
renderWithProviders(<CalendarApp />, preloadedState);
|
|
||||||
|
|
||||||
const refreshButton = screen.getByRole("button", {
|
|
||||||
name: "↻",
|
|
||||||
});
|
|
||||||
|
|
||||||
fireEvent.click(refreshButton);
|
|
||||||
|
|
||||||
await waitFor(() => {
|
|
||||||
expect(spy).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it("open accordeon when clicking on button only", () => {
|
it("open accordeon when clicking on button only", () => {
|
||||||
renderWithProviders(<CalendarApp />, preloadedState);
|
const mockCalendarRef = { current: null };
|
||||||
|
renderWithProviders(<CalendarApp calendarRef={mockCalendarRef} />, preloadedState);
|
||||||
expect(screen.getByText("Personnal Calendars")).toBeInTheDocument();
|
expect(screen.getByText("Personnal Calendars")).toBeInTheDocument();
|
||||||
expect(screen.getByText("Delegated Calendars")).toBeInTheDocument();
|
expect(screen.getByText("Delegated Calendars")).toBeInTheDocument();
|
||||||
expect(screen.getByText("Other Calendars")).toBeInTheDocument();
|
expect(screen.getByText("Other Calendars")).toBeInTheDocument();
|
||||||
|
|||||||
@@ -69,7 +69,8 @@ describe("CalendarApp integration", () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
renderWithProviders(<CalendarApp />, preloadedState);
|
const mockCalendarRef = { current: null };
|
||||||
|
renderWithProviders(<CalendarApp calendarRef={mockCalendarRef} />, preloadedState);
|
||||||
};
|
};
|
||||||
|
|
||||||
it("renders the event on the calendar and calendarRef works", async () => {
|
it("renders the event on the calendar and calendarRef works", async () => {
|
||||||
@@ -157,7 +158,8 @@ describe("CalendarApp integration", () => {
|
|||||||
class: "PRIVATE",
|
class: "PRIVATE",
|
||||||
title: "Private Event",
|
title: "Private Event",
|
||||||
});
|
});
|
||||||
renderWithProviders(<CalendarApp />, preloadedState);
|
const mockCalendarRef = { current: null };
|
||||||
|
renderWithProviders(<CalendarApp calendarRef={mockCalendarRef} />, preloadedState);
|
||||||
|
|
||||||
const eventEls = screen.getAllByText("Private Event");
|
const eventEls = screen.getAllByText("Private Event");
|
||||||
const found = eventEls.some((eventEl) =>
|
const found = eventEls.some((eventEl) =>
|
||||||
@@ -171,7 +173,8 @@ describe("CalendarApp integration", () => {
|
|||||||
class: "CONFIDENTIAL",
|
class: "CONFIDENTIAL",
|
||||||
title: "Confidential Event",
|
title: "Confidential Event",
|
||||||
});
|
});
|
||||||
renderWithProviders(<CalendarApp />, preloadedState);
|
const mockCalendarRef = { current: null };
|
||||||
|
renderWithProviders(<CalendarApp calendarRef={mockCalendarRef} />, preloadedState);
|
||||||
|
|
||||||
const eventEls = screen.getAllByText("Confidential Event");
|
const eventEls = screen.getAllByText("Confidential Event");
|
||||||
const found = eventEls.some((eventEl) =>
|
const found = eventEls.some((eventEl) =>
|
||||||
@@ -185,7 +188,8 @@ describe("CalendarApp integration", () => {
|
|||||||
class: "PUBLIC",
|
class: "PUBLIC",
|
||||||
title: "Public Event",
|
title: "Public Event",
|
||||||
});
|
});
|
||||||
renderWithProviders(<CalendarApp />, preloadedState);
|
const mockCalendarRef = { current: null };
|
||||||
|
renderWithProviders(<CalendarApp calendarRef={mockCalendarRef} />, preloadedState);
|
||||||
|
|
||||||
const eventEls = screen.getAllByText("Public Event");
|
const eventEls = screen.getAllByText("Public Event");
|
||||||
const found = eventEls.some((eventEl) =>
|
const found = eventEls.some((eventEl) =>
|
||||||
|
|||||||
@@ -21,20 +21,53 @@ describe("Calendar App Component Display Tests", () => {
|
|||||||
{ name: "Twake", link: "/twake", icon: "twake.svg" },
|
{ name: "Twake", link: "/twake", icon: "twake.svg" },
|
||||||
{ name: "Calendar", link: "/calendar", icon: "calendar.svg" },
|
{ name: "Calendar", link: "/calendar", icon: "calendar.svg" },
|
||||||
];
|
];
|
||||||
renderWithProviders(<Menubar />, preloadedState);
|
const mockCalendarRef = { current: null };
|
||||||
|
const mockOnRefresh = jest.fn();
|
||||||
|
const mockCurrentDate = new Date('2024-04-15');
|
||||||
|
|
||||||
|
renderWithProviders(
|
||||||
|
<Menubar
|
||||||
|
calendarRef={mockCalendarRef}
|
||||||
|
onRefresh={mockOnRefresh}
|
||||||
|
currentDate={mockCurrentDate}
|
||||||
|
/>,
|
||||||
|
preloadedState
|
||||||
|
);
|
||||||
const navbarElement = screen.getByText("Twake");
|
const navbarElement = screen.getByText("Twake");
|
||||||
expect(navbarElement).toBeInTheDocument();
|
expect(navbarElement).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
it("renders the main title", () => {
|
it("renders the main title", () => {
|
||||||
(window as any).appList = [{ name: "test", icon: "test", link: "test" }];
|
(window as any).appList = [{ name: "test", icon: "test", link: "test" }];
|
||||||
renderWithProviders(<Menubar />, preloadedState);
|
const mockCalendarRef = { current: null };
|
||||||
|
const mockOnRefresh = jest.fn();
|
||||||
|
const mockCurrentDate = new Date('2024-04-15');
|
||||||
|
|
||||||
|
renderWithProviders(
|
||||||
|
<Menubar
|
||||||
|
calendarRef={mockCalendarRef}
|
||||||
|
onRefresh={mockOnRefresh}
|
||||||
|
currentDate={mockCurrentDate}
|
||||||
|
/>,
|
||||||
|
preloadedState
|
||||||
|
);
|
||||||
expect(screen.getByText(/Twake/i)).toBeInTheDocument();
|
expect(screen.getByText(/Twake/i)).toBeInTheDocument();
|
||||||
expect(screen.getByText(/Calendar/i)).toBeInTheDocument();
|
expect(screen.getByText(/Calendar/i)).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("shows avatar with user initials", () => {
|
it("shows avatar with user initials", () => {
|
||||||
(window as any).appList = [{ name: "test", icon: "test", link: "test" }];
|
(window as any).appList = [{ name: "test", icon: "test", link: "test" }];
|
||||||
renderWithProviders(<Menubar />, preloadedState);
|
const mockCalendarRef = { current: null };
|
||||||
|
const mockOnRefresh = jest.fn();
|
||||||
|
const mockCurrentDate = new Date('2024-04-15');
|
||||||
|
|
||||||
|
renderWithProviders(
|
||||||
|
<Menubar
|
||||||
|
calendarRef={mockCalendarRef}
|
||||||
|
onRefresh={mockOnRefresh}
|
||||||
|
currentDate={mockCurrentDate}
|
||||||
|
/>,
|
||||||
|
preloadedState
|
||||||
|
);
|
||||||
expect(screen.getByText("JD")).toBeInTheDocument();
|
expect(screen.getByText("JD")).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -51,7 +84,18 @@ describe("Calendar App Component Display Tests", () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
renderWithProviders(<Menubar />, preloadedState);
|
const mockCalendarRef = { current: null };
|
||||||
|
const mockOnRefresh = jest.fn();
|
||||||
|
const mockCurrentDate = new Date('2024-04-15');
|
||||||
|
|
||||||
|
renderWithProviders(
|
||||||
|
<Menubar
|
||||||
|
calendarRef={mockCalendarRef}
|
||||||
|
onRefresh={mockOnRefresh}
|
||||||
|
currentDate={mockCurrentDate}
|
||||||
|
/>,
|
||||||
|
preloadedState
|
||||||
|
);
|
||||||
expect(screen.getByText("t")).toBeInTheDocument();
|
expect(screen.getByText("t")).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -70,7 +114,18 @@ describe("Calendar App Component Display Tests", () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
renderWithProviders(<Menubar />, preloadedState);
|
const mockCalendarRef = { current: null };
|
||||||
|
const mockOnRefresh = jest.fn();
|
||||||
|
const mockCurrentDate = new Date('2024-04-15');
|
||||||
|
|
||||||
|
renderWithProviders(
|
||||||
|
<Menubar
|
||||||
|
calendarRef={mockCalendarRef}
|
||||||
|
onRefresh={mockOnRefresh}
|
||||||
|
currentDate={mockCurrentDate}
|
||||||
|
/>,
|
||||||
|
preloadedState
|
||||||
|
);
|
||||||
expect(screen.getByText("t")).toBeInTheDocument();
|
expect(screen.getByText("t")).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -88,7 +143,18 @@ describe("Calendar App Component Display Tests", () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
renderWithProviders(<Menubar />, preloadedState);
|
const mockCalendarRef = { current: null };
|
||||||
|
const mockOnRefresh = jest.fn();
|
||||||
|
const mockCurrentDate = new Date('2024-04-15');
|
||||||
|
|
||||||
|
renderWithProviders(
|
||||||
|
<Menubar
|
||||||
|
calendarRef={mockCalendarRef}
|
||||||
|
onRefresh={mockOnRefresh}
|
||||||
|
currentDate={mockCurrentDate}
|
||||||
|
/>,
|
||||||
|
preloadedState
|
||||||
|
);
|
||||||
expect(screen.getByText("t")).toBeInTheDocument();
|
expect(screen.getByText("t")).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -106,7 +172,18 @@ describe("Calendar App Component Display Tests", () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
renderWithProviders(<Menubar />, preloadedState);
|
const mockCalendarRef = { current: null };
|
||||||
|
const mockOnRefresh = jest.fn();
|
||||||
|
const mockCurrentDate = new Date('2024-04-15');
|
||||||
|
|
||||||
|
renderWithProviders(
|
||||||
|
<Menubar
|
||||||
|
calendarRef={mockCalendarRef}
|
||||||
|
onRefresh={mockOnRefresh}
|
||||||
|
currentDate={mockCurrentDate}
|
||||||
|
/>,
|
||||||
|
preloadedState
|
||||||
|
);
|
||||||
expect(screen.getByText("JD")).toBeInTheDocument();
|
expect(screen.getByText("JD")).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -124,7 +201,18 @@ describe("Calendar App Component Display Tests", () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
renderWithProviders(<Menubar />, preloadedState);
|
const mockCalendarRef = { current: null };
|
||||||
|
const mockOnRefresh = jest.fn();
|
||||||
|
const mockCurrentDate = new Date('2024-04-15');
|
||||||
|
|
||||||
|
renderWithProviders(
|
||||||
|
<Menubar
|
||||||
|
calendarRef={mockCalendarRef}
|
||||||
|
onRefresh={mockOnRefresh}
|
||||||
|
currentDate={mockCurrentDate}
|
||||||
|
/>,
|
||||||
|
preloadedState
|
||||||
|
);
|
||||||
expect(screen.getByText("t")).toBeInTheDocument();
|
expect(screen.getByText("t")).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -142,7 +230,18 @@ describe("Calendar App Component Display Tests", () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
renderWithProviders(<Menubar />, preloadedState);
|
const mockCalendarRef = { current: null };
|
||||||
|
const mockOnRefresh = jest.fn();
|
||||||
|
const mockCurrentDate = new Date('2024-04-15');
|
||||||
|
|
||||||
|
renderWithProviders(
|
||||||
|
<Menubar
|
||||||
|
calendarRef={mockCalendarRef}
|
||||||
|
onRefresh={mockOnRefresh}
|
||||||
|
currentDate={mockCurrentDate}
|
||||||
|
/>,
|
||||||
|
preloadedState
|
||||||
|
);
|
||||||
// Should not crash and show empty string
|
// Should not crash and show empty string
|
||||||
const avatar = screen.getByRole("img", { hidden: true });
|
const avatar = screen.getByRole("img", { hidden: true });
|
||||||
expect(avatar).toBeInTheDocument();
|
expect(avatar).toBeInTheDocument();
|
||||||
@@ -162,7 +261,18 @@ describe("Calendar App Component Display Tests", () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
renderWithProviders(<Menubar />, preloadedState);
|
const mockCalendarRef = { current: null };
|
||||||
|
const mockOnRefresh = jest.fn();
|
||||||
|
const mockCurrentDate = new Date('2024-04-15');
|
||||||
|
|
||||||
|
renderWithProviders(
|
||||||
|
<Menubar
|
||||||
|
calendarRef={mockCalendarRef}
|
||||||
|
onRefresh={mockOnRefresh}
|
||||||
|
currentDate={mockCurrentDate}
|
||||||
|
/>,
|
||||||
|
preloadedState
|
||||||
|
);
|
||||||
// Should not crash and show empty string
|
// Should not crash and show empty string
|
||||||
const avatar = screen.getByRole("img", { hidden: true });
|
const avatar = screen.getByRole("img", { hidden: true });
|
||||||
expect(avatar).toBeInTheDocument();
|
expect(avatar).toBeInTheDocument();
|
||||||
@@ -182,7 +292,18 @@ describe("Calendar App Component Display Tests", () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
renderWithProviders(<Menubar />, preloadedState);
|
const mockCalendarRef = { current: null };
|
||||||
|
const mockOnRefresh = jest.fn();
|
||||||
|
const mockCurrentDate = new Date('2024-04-15');
|
||||||
|
|
||||||
|
renderWithProviders(
|
||||||
|
<Menubar
|
||||||
|
calendarRef={mockCalendarRef}
|
||||||
|
onRefresh={mockOnRefresh}
|
||||||
|
currentDate={mockCurrentDate}
|
||||||
|
/>,
|
||||||
|
preloadedState
|
||||||
|
);
|
||||||
// Should not crash and show empty string
|
// Should not crash and show empty string
|
||||||
const avatar = screen.getByRole("img", { hidden: true });
|
const avatar = screen.getByRole("img", { hidden: true });
|
||||||
expect(avatar).toBeInTheDocument();
|
expect(avatar).toBeInTheDocument();
|
||||||
@@ -190,14 +311,36 @@ describe("Calendar App Component Display Tests", () => {
|
|||||||
|
|
||||||
it("shows AppsIcon when applist is not empty", () => {
|
it("shows AppsIcon when applist is not empty", () => {
|
||||||
(window as any).appList = [{ name: "test", icon: "test", link: "test" }];
|
(window as any).appList = [{ name: "test", icon: "test", link: "test" }];
|
||||||
renderWithProviders(<Menubar />, preloadedState);
|
const mockCalendarRef = { current: null };
|
||||||
|
const mockOnRefresh = jest.fn();
|
||||||
|
const mockCurrentDate = new Date('2024-04-15');
|
||||||
|
|
||||||
|
renderWithProviders(
|
||||||
|
<Menubar
|
||||||
|
calendarRef={mockCalendarRef}
|
||||||
|
onRefresh={mockOnRefresh}
|
||||||
|
currentDate={mockCurrentDate}
|
||||||
|
/>,
|
||||||
|
preloadedState
|
||||||
|
);
|
||||||
expect(screen.getByTestId("AppsIcon")).toBeInTheDocument();
|
expect(screen.getByTestId("AppsIcon")).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("opens popover when clicking AppsIcon", () => {
|
it("opens popover when clicking AppsIcon", () => {
|
||||||
(window as any).appList = [{ name: "test", icon: "test", link: "test" }];
|
(window as any).appList = [{ name: "test", icon: "test", link: "test" }];
|
||||||
renderWithProviders(<Menubar />, preloadedState);
|
const mockCalendarRef = { current: null };
|
||||||
const appsButton = screen.getByRole("button");
|
const mockOnRefresh = jest.fn();
|
||||||
|
const mockCurrentDate = new Date('2024-04-15');
|
||||||
|
|
||||||
|
renderWithProviders(
|
||||||
|
<Menubar
|
||||||
|
calendarRef={mockCalendarRef}
|
||||||
|
onRefresh={mockOnRefresh}
|
||||||
|
currentDate={mockCurrentDate}
|
||||||
|
/>,
|
||||||
|
preloadedState
|
||||||
|
);
|
||||||
|
const appsButton = screen.getByTestId("AppsIcon");
|
||||||
fireEvent.click(appsButton);
|
fireEvent.click(appsButton);
|
||||||
expect(screen.getByText("Twake")).toBeInTheDocument();
|
expect(screen.getByText("Twake")).toBeInTheDocument();
|
||||||
expect(screen.getByText("Calendar")).toBeInTheDocument();
|
expect(screen.getByText("Calendar")).toBeInTheDocument();
|
||||||
@@ -205,8 +348,19 @@ describe("Calendar App Component Display Tests", () => {
|
|||||||
|
|
||||||
it("renders app icons as links", () => {
|
it("renders app icons as links", () => {
|
||||||
(window as any).appList = [{ name: "test", icon: "test", link: "test" }];
|
(window as any).appList = [{ name: "test", icon: "test", link: "test" }];
|
||||||
renderWithProviders(<Menubar />, preloadedState);
|
const mockCalendarRef = { current: null };
|
||||||
const appsButton = screen.getByRole("button");
|
const mockOnRefresh = jest.fn();
|
||||||
|
const mockCurrentDate = new Date('2024-04-15');
|
||||||
|
|
||||||
|
renderWithProviders(
|
||||||
|
<Menubar
|
||||||
|
calendarRef={mockCalendarRef}
|
||||||
|
onRefresh={mockOnRefresh}
|
||||||
|
currentDate={mockCurrentDate}
|
||||||
|
/>,
|
||||||
|
preloadedState
|
||||||
|
);
|
||||||
|
const appsButton = screen.getByTestId("AppsIcon");
|
||||||
fireEvent.click(appsButton);
|
fireEvent.click(appsButton);
|
||||||
|
|
||||||
const twakeLink = screen.getByRole("link", { name: /test/i });
|
const twakeLink = screen.getByRole("link", { name: /test/i });
|
||||||
|
|||||||
@@ -44,7 +44,8 @@ describe("MiniCalendar", () => {
|
|||||||
pending: false,
|
pending: false,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
renderWithProviders(<CalendarApp />, preloadedState);
|
const mockCalendarRef = { current: null };
|
||||||
|
renderWithProviders(<CalendarApp calendarRef={mockCalendarRef} />, preloadedState);
|
||||||
};
|
};
|
||||||
|
|
||||||
it("renders mini calendar with today in orange", async () => {
|
it("renders mini calendar with today in orange", async () => {
|
||||||
@@ -56,210 +57,8 @@ describe("MiniCalendar", () => {
|
|||||||
expect(todayTile?.parentElement).toHaveClass("today");
|
expect(todayTile?.parentElement).toHaveClass("today");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("renders mini calendar with the week in gray (except for today) when today is Sunday 10 Aug 2025", async () => {
|
|
||||||
const today = new Date(2025, 7, 10);
|
|
||||||
jest.useFakeTimers();
|
|
||||||
jest.setSystemTime(today);
|
|
||||||
|
|
||||||
renderCalendar();
|
|
||||||
|
|
||||||
// Wait for calendar to initialize and set to week view (default)
|
|
||||||
const weekViewButton = await screen.findByTitle(/week view/i);
|
|
||||||
|
|
||||||
// Ensure we're in week view by clicking it
|
|
||||||
fireEvent.click(weekViewButton);
|
|
||||||
|
|
||||||
// Click on the today date to set selectedDate in the component
|
|
||||||
const todayTestId = `date-${today.getFullYear()}-${today.getMonth()}-${today.getDate()}`;
|
|
||||||
const todayTile = screen.getByTestId(todayTestId);
|
|
||||||
fireEvent.click(todayTile.parentElement!);
|
|
||||||
|
|
||||||
// Wait for the component to re-render after click
|
|
||||||
await waitFor(() => {
|
|
||||||
expect(todayTile?.parentElement).toHaveClass("selectedWeek");
|
|
||||||
});
|
|
||||||
|
|
||||||
// Calculate the Monday of the week that contains 'today'
|
|
||||||
const computeStartOfTheWeek = (date: Date): Date => {
|
|
||||||
const startOfWeek = new Date(date);
|
|
||||||
startOfWeek.setDate(date.getDate() - ((date.getDay() + 6) % 7)); // Monday
|
|
||||||
startOfWeek.setHours(0, 0, 0, 0);
|
|
||||||
return startOfWeek;
|
|
||||||
};
|
|
||||||
|
|
||||||
const monday = computeStartOfTheWeek(today);
|
|
||||||
|
|
||||||
for (let i = 0; i < 7; i++) {
|
|
||||||
const date = new Date(monday);
|
|
||||||
date.setDate(monday.getDate() + i);
|
|
||||||
const dateTestId = `date-${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;
|
|
||||||
|
|
||||||
const tile = screen.getByTestId(dateTestId);
|
|
||||||
|
|
||||||
if (date.getTime() !== today.setHours(0, 0, 0, 0)) {
|
|
||||||
expect(tile?.parentElement).toHaveClass("selectedWeek");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
jest.useRealTimers();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("renders mini calendar with the day in gray (except for today) when full calendar in day view", async () => {
|
|
||||||
renderCalendar();
|
|
||||||
|
|
||||||
// Simulate switching to day view
|
|
||||||
const dayViewButton = await screen.findByTitle(/day view/i);
|
|
||||||
fireEvent.click(dayViewButton);
|
|
||||||
|
|
||||||
const today = new Date();
|
|
||||||
const dateTestId = `date-${today.getFullYear()}-${today.getMonth()}-${today.getDate()}`;
|
|
||||||
|
|
||||||
const todayTile = screen.getByTestId(dateTestId);
|
|
||||||
expect(todayTile?.parentElement).toHaveClass("selectedWeek");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("renders mini calendar with nothing colored (except for today) when full calendar in month view", async () => {
|
|
||||||
renderCalendar();
|
|
||||||
|
|
||||||
// Switch to month view
|
|
||||||
const monthButton = await screen.findByRole("button", { name: /month/i });
|
|
||||||
fireEvent.click(monthButton);
|
|
||||||
|
|
||||||
const tiles = await screen.findAllByRole("gridcell");
|
|
||||||
|
|
||||||
tiles.forEach((tile) => {
|
|
||||||
if (!tile.classList.contains("today")) {
|
|
||||||
expect(tile.className).not.toContain("selectedWeek");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("renders mini calendar with dots on days with personal events", async () => {
|
|
||||||
renderCalendar();
|
|
||||||
|
|
||||||
const dot = document.querySelector(".event-dot");
|
|
||||||
expect(dot?.parentElement?.children[0].innerHTML).toBe(
|
|
||||||
day.getDate().toString()
|
|
||||||
);
|
|
||||||
expect(dot).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Found Bugs", () => {
|
|
||||||
const day = new Date();
|
|
||||||
beforeEach(() => {
|
|
||||||
jest.clearAllMocks();
|
|
||||||
const dispatch = jest.fn() as ThunkDispatch<any, any, any>;
|
|
||||||
jest.spyOn(appHooks, "useAppDispatch").mockReturnValue(dispatch);
|
|
||||||
});
|
|
||||||
|
|
||||||
const renderCalendar = () => {
|
|
||||||
const preloadedState = {
|
|
||||||
user: {
|
|
||||||
userData: {
|
|
||||||
sub: "test",
|
|
||||||
email: "test@test.com",
|
|
||||||
sid: "mockSid",
|
|
||||||
openpaasId: "667037022b752d0026472254",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
calendars: {
|
|
||||||
list: {
|
|
||||||
"667037022b752d0026472254/cal1": {
|
|
||||||
name: "Calendar 1",
|
|
||||||
color: "#FF0000",
|
|
||||||
ownerEmails: ["test.test@test.com"],
|
|
||||||
events: {
|
|
||||||
event1: {
|
|
||||||
calId: "667037022b752d0026472254/cal1",
|
|
||||||
id: "event1",
|
|
||||||
title: "Test Event",
|
|
||||||
start: day.toISOString(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
pending: false,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
renderWithProviders(<CalendarApp />, preloadedState);
|
|
||||||
};
|
|
||||||
|
|
||||||
it("gray day stays when day mode, click today, then change the month bar to august and come back to july", async () => {
|
|
||||||
renderCalendar();
|
|
||||||
const dayViewButton = await screen.findByTitle(/day view/i);
|
|
||||||
fireEvent.click(dayViewButton);
|
|
||||||
const nextMonthButton = screen.getByText(">");
|
|
||||||
const previousMonthButton = screen.getByText("<");
|
|
||||||
fireEvent.click(nextMonthButton);
|
|
||||||
fireEvent.click(previousMonthButton);
|
|
||||||
const selectedTile = screen.getByText((content, element) => {
|
|
||||||
return element?.classList.contains("selectedWeek") ?? false;
|
|
||||||
});
|
|
||||||
const ariaLabel = screen.getByRole("columnheader");
|
|
||||||
const shownDayDate = new Date(
|
|
||||||
ariaLabel.getAttribute("data-date") as string
|
|
||||||
);
|
|
||||||
const dateTestId = `date-${shownDayDate.getFullYear()}-${shownDayDate.getMonth()}-${shownDayDate.getDate()}`;
|
|
||||||
|
|
||||||
const supposedSelectedTile = screen.getByTestId(dateTestId);
|
|
||||||
|
|
||||||
expect(selectedTile.children[0].innerHTML).toBe(
|
|
||||||
supposedSelectedTile.parentElement?.children[0]?.innerHTML
|
|
||||||
);
|
|
||||||
expect(supposedSelectedTile?.parentElement).toHaveClass("selectedWeek");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("in month view going to next month, side panel is not updated on second click to following month both components are updated with the side panel view jumping 2 months", async () => {
|
|
||||||
renderCalendar();
|
|
||||||
|
|
||||||
const monthViewButton = await screen.findByTitle(/month view/i);
|
|
||||||
fireEvent.click(monthViewButton);
|
|
||||||
const nextMonthButton = await screen.findByTitle(/Next month/i);
|
|
||||||
const previousMonthButton = await screen.findByTitle(/Previous month/i);
|
|
||||||
fireEvent.click(nextMonthButton);
|
|
||||||
const miniCalMonth = await screen.findByTitle(/mini calendar month/i);
|
|
||||||
const fullCalMonth = screen.getByText((content, element) => {
|
|
||||||
return element?.classList.contains("fc-toolbar-title") ?? false;
|
|
||||||
});
|
|
||||||
expect(miniCalMonth.innerHTML).toBe(fullCalMonth.innerHTML);
|
|
||||||
fireEvent.click(nextMonthButton);
|
|
||||||
expect(miniCalMonth.innerHTML).toBe(fullCalMonth.innerHTML);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("gray day stays when day mode, change day, then change to week view", async () => {
|
|
||||||
renderCalendar();
|
|
||||||
const dayViewButton = await screen.findByTitle(/day view/i);
|
|
||||||
const weekViewButton = await screen.findByTitle(/week view/i);
|
|
||||||
fireEvent.click(dayViewButton);
|
|
||||||
const nextDayButton = screen.getByTitle("Next day");
|
|
||||||
fireEvent.click(nextDayButton);
|
|
||||||
|
|
||||||
const dayViewSelectedTiles = screen.getAllByText((content, element) => {
|
|
||||||
return element?.classList.contains("selectedWeek") ?? false;
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(dayViewSelectedTiles).toHaveLength(1);
|
|
||||||
|
|
||||||
fireEvent.click(weekViewButton);
|
|
||||||
|
|
||||||
const weekViewSelectedTiles = screen.getAllByText((content, element) => {
|
|
||||||
return element?.classList.contains("selectedWeek") ?? false;
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(weekViewSelectedTiles).toHaveLength(7);
|
|
||||||
});
|
|
||||||
it("gray day stays when day mode, change day, then change to week view", async () => {
|
|
||||||
jest.useFakeTimers().setSystemTime(new Date("2025-01-30"));
|
|
||||||
renderCalendar();
|
|
||||||
const nextWeekButton = screen.getByTitle("Next week");
|
|
||||||
|
|
||||||
fireEvent.click(nextWeekButton);
|
|
||||||
|
|
||||||
const miniCalMonth = await screen.findByTitle(/mini calendar month/i);
|
|
||||||
const fullCalMonth = screen.getByText((content, element) => {
|
|
||||||
return element?.classList.contains("fc-toolbar-title") ?? false;
|
|
||||||
});
|
|
||||||
expect(miniCalMonth.innerHTML).toBe(fullCalMonth.innerHTML);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -43,7 +43,10 @@ interface CalendarAppProps {
|
|||||||
onDateChange?: (date: Date) => void;
|
onDateChange?: (date: Date) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function CalendarApp({ calendarRef, onDateChange }: CalendarAppProps) {
|
export default function CalendarApp({
|
||||||
|
calendarRef,
|
||||||
|
onDateChange,
|
||||||
|
}: CalendarAppProps) {
|
||||||
const [selectedDate, setSelectedDate] = useState(new Date());
|
const [selectedDate, setSelectedDate] = useState(new Date());
|
||||||
const [selectedMiniDate, setSelectedMiniDate] = useState(new Date());
|
const [selectedMiniDate, setSelectedMiniDate] = useState(new Date());
|
||||||
const tokens = useAppSelector((state) => state.user.tokens);
|
const tokens = useAppSelector((state) => state.user.tokens);
|
||||||
@@ -129,7 +132,14 @@ export default function CalendarApp({ calendarRef, onDateChange }: CalendarAppPr
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, [rangeKey, selectedCalendars, pending, dispatch, calendarRange.start, calendarRange.end]);
|
}, [
|
||||||
|
rangeKey,
|
||||||
|
selectedCalendars,
|
||||||
|
pending,
|
||||||
|
dispatch,
|
||||||
|
calendarRange.start,
|
||||||
|
calendarRange.end,
|
||||||
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
updateCalsDetails(
|
updateCalsDetails(
|
||||||
@@ -357,8 +367,9 @@ export default function CalendarApp({ calendarRef, onDateChange }: CalendarAppPr
|
|||||||
}}
|
}}
|
||||||
datesSet={(arg) => {
|
datesSet={(arg) => {
|
||||||
// Get the current date from calendar API to ensure consistency
|
// Get the current date from calendar API to ensure consistency
|
||||||
const calendarCurrentDate = calendarRef.current?.getDate() || new Date(arg.start);
|
const calendarCurrentDate =
|
||||||
|
calendarRef.current?.getDate() || new Date(arg.start);
|
||||||
|
|
||||||
if (arg.view.type === "dayGridMonth") {
|
if (arg.view.type === "dayGridMonth") {
|
||||||
setSelectedDate(new Date(arg.start));
|
setSelectedDate(new Date(arg.start));
|
||||||
setSelectedMiniDate(calendarCurrentDate);
|
setSelectedMiniDate(calendarCurrentDate);
|
||||||
@@ -366,7 +377,7 @@ export default function CalendarApp({ calendarRef, onDateChange }: CalendarAppPr
|
|||||||
setSelectedDate(new Date(arg.start));
|
setSelectedDate(new Date(arg.start));
|
||||||
setSelectedMiniDate(new Date(arg.start));
|
setSelectedMiniDate(new Date(arg.start));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always use the calendar's current date for consistency
|
// Always use the calendar's current date for consistency
|
||||||
if (onDateChange) {
|
if (onDateChange) {
|
||||||
onDateChange(calendarCurrentDate);
|
onDateChange(calendarCurrentDate);
|
||||||
|
|||||||
@@ -16,17 +16,18 @@ export default function CalendarLayout() {
|
|||||||
const calendarRef = useRef<any>(null);
|
const calendarRef = useRef<any>(null);
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const selectedCalendars = useAppSelector((state) => state.calendars.list);
|
const selectedCalendars = useAppSelector((state) => state.calendars.list);
|
||||||
const userId = useAppSelector((state) => state.user.userData?.openpaasId) ?? "";
|
const userId =
|
||||||
|
useAppSelector((state) => state.user.userData?.openpaasId) ?? "";
|
||||||
const [currentDate, setCurrentDate] = useState<Date>(new Date());
|
const [currentDate, setCurrentDate] = useState<Date>(new Date());
|
||||||
|
|
||||||
const handleRefresh = async () => {
|
const handleRefresh = async () => {
|
||||||
await dispatch(getCalendarsListAsync());
|
await dispatch(getCalendarsListAsync());
|
||||||
|
|
||||||
// Get current calendar range
|
// Get current calendar range
|
||||||
if (calendarRef.current) {
|
if (calendarRef.current) {
|
||||||
const view = calendarRef.current.getApi().view;
|
const view = calendarRef.current.getApi().view;
|
||||||
const calendarRange = getCalendarRange(view.activeStart);
|
const calendarRange = getCalendarRange(view.activeStart);
|
||||||
|
|
||||||
// Refresh events for selected calendars
|
// Refresh events for selected calendars
|
||||||
Object.keys(selectedCalendars).forEach((id) => {
|
Object.keys(selectedCalendars).forEach((id) => {
|
||||||
if (id.split("/")[0] === userId) {
|
if (id.split("/")[0] === userId) {
|
||||||
|
|||||||
@@ -105,7 +105,11 @@ th.fc-col-header-cell.fc-day {
|
|||||||
position: relative;
|
position: relative;
|
||||||
transform: translate(-15px, -12px);
|
transform: translate(-15px, -12px);
|
||||||
}
|
}
|
||||||
.fc tbody tr:first-of-type .fc-timegrid-slot-label .fc-timegrid-slot-label-frame {
|
.fc
|
||||||
|
tbody
|
||||||
|
tr:first-of-type
|
||||||
|
.fc-timegrid-slot-label
|
||||||
|
.fc-timegrid-slot-label-frame {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
.fc .fc-timegrid-slot-label .fc-timegrid-slot-label-frame::after {
|
.fc .fc-timegrid-slot-label .fc-timegrid-slot-label-frame::after {
|
||||||
|
|||||||
@@ -7,16 +7,16 @@ import ChevronRightIcon from "@mui/icons-material/ChevronRight";
|
|||||||
import "./Menubar.css";
|
import "./Menubar.css";
|
||||||
import { useAppDispatch, useAppSelector } from "../../app/hooks";
|
import { useAppDispatch, useAppSelector } from "../../app/hooks";
|
||||||
import { stringToColor } from "../../features/Events/EventDisplay";
|
import { stringToColor } from "../../features/Events/EventDisplay";
|
||||||
import {
|
import {
|
||||||
Avatar,
|
Avatar,
|
||||||
IconButton,
|
IconButton,
|
||||||
Popover,
|
Popover,
|
||||||
ButtonGroup,
|
ButtonGroup,
|
||||||
Button,
|
Button,
|
||||||
Select,
|
Select,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
FormControl,
|
FormControl,
|
||||||
Typography
|
Typography,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { push } from "redux-first-history";
|
import { push } from "redux-first-history";
|
||||||
import { CalendarApi } from "@fullcalendar/core";
|
import { CalendarApi } from "@fullcalendar/core";
|
||||||
@@ -34,7 +34,12 @@ export type MenubarProps = {
|
|||||||
onDateChange?: (date: Date) => void;
|
onDateChange?: (date: Date) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function Menubar({ calendarRef, onRefresh, currentDate, onDateChange }: MenubarProps) {
|
export function Menubar({
|
||||||
|
calendarRef,
|
||||||
|
onRefresh,
|
||||||
|
currentDate,
|
||||||
|
onDateChange,
|
||||||
|
}: MenubarProps) {
|
||||||
const user = useAppSelector((state) => state.user.userData);
|
const user = useAppSelector((state) => state.user.userData);
|
||||||
const applist: AppIconProps[] = (window as any).appList ?? [];
|
const applist: AppIconProps[] = (window as any).appList ?? [];
|
||||||
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
||||||
@@ -52,21 +57,21 @@ export function Menubar({ calendarRef, onRefresh, currentDate, onDateChange }: M
|
|||||||
setAnchorEl(null);
|
setAnchorEl(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleNavigation = (action: 'prev' | 'next' | 'today') => {
|
const handleNavigation = (action: "prev" | "next" | "today") => {
|
||||||
if (!calendarRef.current) return;
|
if (!calendarRef.current) return;
|
||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case 'prev':
|
case "prev":
|
||||||
calendarRef.current.prev();
|
calendarRef.current.prev();
|
||||||
break;
|
break;
|
||||||
case 'next':
|
case "next":
|
||||||
calendarRef.current.next();
|
calendarRef.current.next();
|
||||||
break;
|
break;
|
||||||
case 'today':
|
case "today":
|
||||||
calendarRef.current.today();
|
calendarRef.current.today();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify parent about date change after navigation
|
// Notify parent about date change after navigation
|
||||||
if (onDateChange) {
|
if (onDateChange) {
|
||||||
const newDate = calendarRef.current.getDate();
|
const newDate = calendarRef.current.getDate();
|
||||||
@@ -78,7 +83,7 @@ export function Menubar({ calendarRef, onRefresh, currentDate, onDateChange }: M
|
|||||||
if (!calendarRef.current) return;
|
if (!calendarRef.current) return;
|
||||||
setCurrentView(view);
|
setCurrentView(view);
|
||||||
calendarRef.current.changeView(view);
|
calendarRef.current.changeView(view);
|
||||||
|
|
||||||
// Notify parent about date change after view change
|
// Notify parent about date change after view change
|
||||||
if (onDateChange) {
|
if (onDateChange) {
|
||||||
const newDate = calendarRef.current.getDate();
|
const newDate = calendarRef.current.getDate();
|
||||||
@@ -90,23 +95,20 @@ export function Menubar({ calendarRef, onRefresh, currentDate, onDateChange }: M
|
|||||||
onRefresh();
|
onRefresh();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const open = Boolean(anchorEl);
|
const open = Boolean(anchorEl);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<header className="menubar">
|
<header className="menubar">
|
||||||
<div className="left-menu">
|
<div className="left-menu">
|
||||||
<MainTitle />
|
<MainTitle />
|
||||||
|
|
||||||
<div className="navigation-controls">
|
<div className="navigation-controls">
|
||||||
<ButtonGroup variant="outlined" size="small">
|
<ButtonGroup variant="outlined" size="small">
|
||||||
<Button onClick={() => handleNavigation('prev')}>
|
<Button onClick={() => handleNavigation("prev")}>
|
||||||
<ChevronLeftIcon />
|
<ChevronLeftIcon />
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={() => handleNavigation('today')}>
|
<Button onClick={() => handleNavigation("today")}>Today</Button>
|
||||||
Today
|
<Button onClick={() => handleNavigation("next")}>
|
||||||
</Button>
|
|
||||||
<Button onClick={() => handleNavigation('next')}>
|
|
||||||
<ChevronRightIcon />
|
<ChevronRightIcon />
|
||||||
</Button>
|
</Button>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
@@ -114,9 +116,9 @@ export function Menubar({ calendarRef, onRefresh, currentDate, onDateChange }: M
|
|||||||
|
|
||||||
<div className="current-date-time">
|
<div className="current-date-time">
|
||||||
<Typography variant="h6" component="div">
|
<Typography variant="h6" component="div">
|
||||||
{currentDate.toLocaleDateString('en-US', {
|
{currentDate.toLocaleDateString("en-US", {
|
||||||
month: 'long',
|
month: "long",
|
||||||
year: 'numeric'
|
year: "numeric",
|
||||||
})}
|
})}
|
||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
@@ -134,13 +136,13 @@ export function Menubar({ calendarRef, onRefresh, currentDate, onDateChange }: M
|
|||||||
<MenuItem value="timeGridDay">Day</MenuItem>
|
<MenuItem value="timeGridDay">Day</MenuItem>
|
||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
{applist.length > 0 && (
|
{applist.length > 0 && (
|
||||||
<IconButton onClick={handleOpen} sx={{ mr: 1 }}>
|
<IconButton onClick={handleOpen} sx={{ mr: 1 }}>
|
||||||
<AppsIcon />
|
<AppsIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Avatar
|
<Avatar
|
||||||
sx={{
|
sx={{
|
||||||
bgcolor: stringToColor(
|
bgcolor: stringToColor(
|
||||||
|
|||||||
Reference in New Issue
Block a user