Co-authored-by: Camille Moussu <cmoussu@linagora.com>
This commit is contained in:
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user