[#259] added check to prevent no applecolor from breaking the commponent (#260)

Co-authored-by: Camille Moussu <cmoussu@linagora.com>
This commit is contained in:
Camille Moussu
2025-10-29 11:25:20 +01:00
committed by GitHub
parent 2355ee8771
commit fc962057c0
2 changed files with 385 additions and 5 deletions
+378
View File
@@ -0,0 +1,378 @@
import { fireEvent, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { act } from "react";
import CalendarSearch from "../../src/components/Calendar/CalendarSearch";
import * as CalendarApi from "../../src/features/Calendars/CalendarApi";
import * as CalendarSlice from "../../src/features/Calendars/CalendarSlice";
import { searchUsers } from "../../src/features/User/userAPI";
import { renderWithProviders } from "../utils/Renderwithproviders";
jest.mock("../../src/features/User/userAPI");
jest.mock("../../src/features/Calendars/CalendarApi");
const mockedSearchUsers = searchUsers as jest.MockedFunction<
typeof searchUsers
>;
const mockedGetCalendars = CalendarApi.getCalendars as jest.MockedFunction<
typeof CalendarApi.getCalendars
>;
describe("CalendarSearch", () => {
const mockOnClose = jest.fn();
const mockUser = {
email: "user@example.com",
displayName: "Test User",
avatarUrl: "https://example.com/avatar.jpg",
openpaasId: "user123",
};
const mockCalendar = {
"dav:name": "Test Calendar",
"apple:color": "#FF0000",
_links: {
self: {
href: "/calendars/user123/cal1.json",
},
},
};
const preloadedState = {
user: {
userData: {
sub: "test",
email: "test@test.com",
sid: "mockSid",
openpaasId: "user1",
},
tokens: { accessToken: "token" },
},
calendars: {
list: {
"user1/cal1": {
name: "My Calendar",
id: "user1/cal1",
color: "#0000FF",
ownerEmails: ["test@test.com"],
events: {},
},
},
pending: false,
},
};
beforeEach(() => {
jest.clearAllMocks();
});
it("searches for users and displays their calendars", async () => {
mockedSearchUsers.mockResolvedValueOnce([mockUser]);
mockedGetCalendars.mockResolvedValueOnce({
_embedded: {
"dav:calendar": [mockCalendar],
},
});
await act(async () => {
renderWithProviders(
<CalendarSearch anchorEl={null} open={true} onClose={mockOnClose} />,
preloadedState
);
});
const input = screen.getByRole("combobox");
await act(async () => {
userEvent.type(input, "Test");
});
const option = await screen.findByText("Test User");
await act(async () => {
fireEvent.click(option);
});
await waitFor(() => {
expect(mockedGetCalendars).toHaveBeenCalledWith(
"user123",
"sharedPublic=true&withRights=true"
);
});
await waitFor(() => {
expect(screen.getByText("Test Calendar")).toBeInTheDocument();
expect(screen.getByText("user@example.com")).toBeInTheDocument();
});
});
it("adds selected calendars on save", async () => {
const addSharedCalendarSpy = jest
.spyOn(CalendarSlice, "addSharedCalendarAsync")
.mockImplementation((payload) => {
return () => Promise.resolve(payload) as any;
});
mockedSearchUsers.mockResolvedValueOnce([mockUser]);
mockedGetCalendars.mockResolvedValueOnce({
_embedded: {
"dav:calendar": [mockCalendar],
},
});
await act(async () => {
renderWithProviders(
<CalendarSearch anchorEl={null} open={true} onClose={mockOnClose} />,
preloadedState
);
});
const input = screen.getByRole("combobox");
await act(async () => {
userEvent.type(input, "Test");
});
const option = await screen.findByText("Test User");
await act(async () => {
fireEvent.click(option);
});
await waitFor(() => {
expect(screen.getByText("Test Calendar")).toBeInTheDocument();
});
const addButton = screen.getByRole("button", { name: /add/i });
await act(async () => {
fireEvent.click(addButton);
});
expect(addSharedCalendarSpy).toHaveBeenCalled();
expect(mockOnClose).toHaveBeenCalled();
});
it("does not add calendars that already exist", async () => {
const addSharedCalendarSpy = jest
.spyOn(CalendarSlice, "addSharedCalendarAsync")
.mockImplementation((payload) => {
return () => Promise.resolve(payload) as any;
});
const existingCalendar = {
...mockCalendar,
_links: {
self: {
href: "/calendars/user1/cal1.json",
},
},
};
mockedSearchUsers.mockResolvedValueOnce([mockUser]);
mockedGetCalendars.mockResolvedValueOnce({
_embedded: {
"dav:calendar": [existingCalendar],
},
});
await act(async () => {
renderWithProviders(
<CalendarSearch anchorEl={null} open={true} onClose={mockOnClose} />,
preloadedState
);
});
const input = screen.getByRole("combobox");
await act(async () => {
userEvent.type(input, "Test");
});
const option = await screen.findByText("Test User");
await act(async () => {
fireEvent.click(option);
});
await waitFor(() => {
expect(
screen.getByText("No more Calendar for Test User")
).toBeInTheDocument();
});
const addButton = screen.getByRole("button", { name: /add/i });
await act(async () => {
fireEvent.click(addButton);
});
expect(addSharedCalendarSpy).not.toHaveBeenCalled();
});
it("displays message when user has no publicly available calendars", async () => {
mockedSearchUsers.mockResolvedValueOnce([mockUser]);
mockedGetCalendars.mockResolvedValueOnce({});
await act(async () => {
renderWithProviders(
<CalendarSearch anchorEl={null} open={true} onClose={mockOnClose} />,
preloadedState
);
});
const input = screen.getByRole("combobox");
await act(async () => {
userEvent.type(input, "Test");
});
const option = await screen.findByText("Test User");
await act(async () => {
fireEvent.click(option);
});
await waitFor(() => {
expect(
screen.getByText("No publicly available calendars for Test User")
).toBeInTheDocument();
});
});
it("changes calendar color", async () => {
mockedSearchUsers.mockResolvedValueOnce([mockUser]);
mockedGetCalendars.mockResolvedValueOnce({
_embedded: {
"dav:calendar": [mockCalendar],
},
});
await act(async () => {
renderWithProviders(
<CalendarSearch anchorEl={null} open={true} onClose={mockOnClose} />,
preloadedState
);
});
const input = screen.getByRole("combobox");
await act(async () => {
userEvent.type(input, "Test");
});
const option = await screen.findByText("Test User");
await act(async () => {
fireEvent.click(option);
});
await waitFor(() => {
expect(screen.getByText("Test Calendar")).toBeInTheDocument();
});
// ColorPicker would need to be interacted with based on its implementation
// This is a placeholder for color change interaction
const colorPicker = document.querySelector('[data-testid="color-picker"]');
if (colorPicker) {
await act(async () => {
fireEvent.click(colorPicker);
});
}
});
it("handles multiple calendars from the same user", async () => {
const secondCalendar = {
"dav:name": "Second Calendar",
"apple:color": "#00FF00",
_links: {
self: {
href: "/calendars/user123/cal2.json",
},
},
};
mockedSearchUsers.mockResolvedValueOnce([mockUser]);
mockedGetCalendars.mockResolvedValueOnce({
_embedded: {
"dav:calendar": [mockCalendar, secondCalendar],
},
});
await act(async () => {
renderWithProviders(
<CalendarSearch anchorEl={null} open={true} onClose={mockOnClose} />,
preloadedState
);
});
const input = screen.getByRole("combobox");
await act(async () => {
userEvent.type(input, "Test");
});
const option = await screen.findByText("Test User");
await act(async () => {
fireEvent.click(option);
});
await waitFor(() => {
expect(screen.getByText("Test Calendar")).toBeInTheDocument();
expect(screen.getByText("Second Calendar")).toBeInTheDocument();
});
});
it("does not call addSharedCalendarAsync when no calendars are selected", async () => {
const addSharedCalendarSpy = jest
.spyOn(CalendarSlice, "addSharedCalendarAsync")
.mockImplementation((payload) => {
return () => Promise.resolve(payload) as any;
});
await act(async () => {
renderWithProviders(
<CalendarSearch anchorEl={null} open={true} onClose={mockOnClose} />,
preloadedState
);
});
const addButton = screen.getByRole("button", { name: /add/i });
await act(async () => {
fireEvent.click(addButton);
});
expect(addSharedCalendarSpy).not.toHaveBeenCalled();
});
it("BUGFIX : handles calendar with no apple:color", async () => {
const mockCalendarNoColor = {
"dav:name": "Test Calendar",
_links: {
self: {
href: "/calendars/user123/cal1.json",
},
},
};
mockedSearchUsers.mockResolvedValueOnce([mockUser]);
mockedGetCalendars.mockResolvedValueOnce({
_embedded: {
"dav:calendar": [mockCalendarNoColor],
},
});
await act(async () => {
renderWithProviders(
<CalendarSearch anchorEl={null} open={true} onClose={mockOnClose} />,
preloadedState
);
});
const input = screen.getByRole("combobox");
await act(async () => {
userEvent.type(input, "Test");
});
const option = await screen.findByText("Test User");
await act(async () => {
fireEvent.click(option);
});
await waitFor(() => {
expect(mockedGetCalendars).toHaveBeenCalledWith(
"user123",
"sharedPublic=true&withRights=true"
);
});
await waitFor(() => {
expect(screen.getByText("Test Calendar")).toBeInTheDocument();
expect(screen.getByText("user@example.com")).toBeInTheDocument();
});
});
});