diff --git a/__test__/components/CalendarSelection.test.tsx b/__test__/components/CalendarSelection.test.tsx new file mode 100644 index 0000000..5ba982b --- /dev/null +++ b/__test__/components/CalendarSelection.test.tsx @@ -0,0 +1,193 @@ +import { CalendarApi } from "@fullcalendar/core"; +import { jest } from "@jest/globals"; +import { ThunkDispatch } from "@reduxjs/toolkit"; +import "@testing-library/jest-dom"; +import { screen } from "@testing-library/react"; +import * as appHooks from "../../src/app/hooks"; +import CalendarApp from "../../src/components/Calendar/Calendar"; +import { renderWithProviders } from "../utils/Renderwithproviders"; +import CalendarSelection from "../../src/components/Calendar/CalendarSelection"; + +describe("CalendarSelection", () => { + const today = new Date(); + const start = new Date(today); + start.setHours(10, 0, 0, 0); + const end = new Date(today); + end.setHours(11, 0, 0, 0); + + it("renders the all the calendars in list", async () => { + const preloadedState = { + user: { + userData: { + sub: "test", + email: "test@test.com", + sid: "mockSid", + openpaasId: "user1", + }, + tokens: { accessToken: "token" }, // required to avoid redirect + }, + calendars: { + list: { + "user1/cal1": { + name: "Calendar personnal", + id: "user1/cal1", + color: "#FF0000", + ownerEmails: ["alice@example.com"], + events: { + event1: { + id: "event1", + calId: "user1/cal1", + uid: "event1", + title: "Test Event", + start: start.toISOString(), + end: end.toISOString(), + partstat: "ACCEPTED", + organizer: { + cn: "Alice", + cal_address: "alice@example.com", + }, + attendee: [ + { + cn: "Alice", + partstat: "ACCEPTED", + rsvp: "TRUE", + role: "REQ-PARTICIPANT", + cutype: "INDIVIDUAL", + cal_address: "alice@example.com", + }, + ], + }, + }, + }, + "user2/cal1": { + name: "Calendar delegated", + delegated: true, + id: "user2/cal1", + color: "#FF0000", + ownerEmails: ["alice@example.com"], + events: { + event1: { + id: "event1", + calId: "user2/cal1", + uid: "event1", + title: "Test Event", + start: start.toISOString(), + end: end.toISOString(), + partstat: "ACCEPTED", + organizer: { + cn: "Alice", + cal_address: "alice@example.com", + }, + attendee: [ + { + cn: "Alice", + partstat: "ACCEPTED", + rsvp: "TRUE", + role: "REQ-PARTICIPANT", + cutype: "INDIVIDUAL", + cal_address: "alice@example.com", + }, + ], + }, + }, + }, + "user3/cal1": { + name: "Calendar shared", + id: "user3/cal1", + color: "#FF0000", + ownerEmails: ["alice@example.com"], + events: { + event1: { + id: "event1", + calId: "user3/cal1", + uid: "event1", + title: "Test Event", + start: start.toISOString(), + end: end.toISOString(), + partstat: "ACCEPTED", + organizer: { + cn: "Alice", + cal_address: "alice@example.com", + }, + attendee: [ + { + cn: "Alice", + partstat: "ACCEPTED", + rsvp: "TRUE", + role: "REQ-PARTICIPANT", + cutype: "INDIVIDUAL", + cal_address: "alice@example.com", + }, + ], + }, + }, + }, + }, + pending: false, + }, + }; + renderWithProviders(, preloadedState); + expect(screen.getByText("personnalCalendars")).toBeInTheDocument(); + expect(screen.getByText("delegatedCalendars")).toBeInTheDocument(); + expect(screen.getByText("sharedCalendars")).toBeInTheDocument(); + + expect(screen.getByLabelText("Calendar personnal")).toBeInTheDocument(); + expect(screen.getByLabelText("Calendar delegated")).toBeInTheDocument(); + expect(screen.getByLabelText("Calendar shared")).toBeInTheDocument(); + }); + it("renders only personnal calendars in list", async () => { + const preloadedState = { + user: { + userData: { + sub: "test", + email: "test@test.com", + sid: "mockSid", + openpaasId: "user1", + }, + tokens: { accessToken: "token" }, // required to avoid redirect + }, + calendars: { + list: { + "user1/cal1": { + name: "Calendar personnal", + id: "user1/cal1", + color: "#FF0000", + ownerEmails: ["alice@example.com"], + events: { + event1: { + id: "event1", + calId: "user1/cal1", + uid: "event1", + title: "Test Event", + start: start.toISOString(), + end: end.toISOString(), + partstat: "ACCEPTED", + organizer: { + cn: "Alice", + cal_address: "alice@example.com", + }, + attendee: [ + { + cn: "Alice", + partstat: "ACCEPTED", + rsvp: "TRUE", + role: "REQ-PARTICIPANT", + cutype: "INDIVIDUAL", + cal_address: "alice@example.com", + }, + ], + }, + }, + }, + }, + pending: false, + }, + }; + renderWithProviders(, preloadedState); + expect(screen.getByText("personnalCalendars")).toBeInTheDocument(); + expect(screen.queryByText("delegatedCalendars")).not.toBeInTheDocument(); + expect(screen.queryByText("sharedCalendars")).not.toBeInTheDocument(); + + expect(screen.getByLabelText("Calendar personnal")).toBeInTheDocument(); + }); +}); diff --git a/src/components/Calendar/CalendarSelection.tsx b/src/components/Calendar/CalendarSelection.tsx index 0c98fcc..4dab623 100644 --- a/src/components/Calendar/CalendarSelection.tsx +++ b/src/components/Calendar/CalendarSelection.tsx @@ -7,11 +7,18 @@ export default function CalendarSelection({ selectedCalendars: string[]; setSelectedCalendars: Function; }) { - const tokens = useAppSelector((state) => state.user.tokens); const userId = useAppSelector((state) => state.user.userData.openpaasId); const dispatch = useAppDispatch(); const calendars = useAppSelector((state) => state.calendars.list); - + const personnalCalendars = Object.keys(calendars).filter( + (id) => id.split("/")[0] === userId + ); + const delegatedCalendars = Object.keys(calendars).filter( + (id) => id.split("/")[0] !== userId && calendars[id].delegated + ); + const sharedCalendars = Object.keys(calendars).filter( + (id) => id.split("/")[0] !== userId && !calendars[id].delegated + ); const handleCalendarToggle = (name: string) => { setSelectedCalendars((prev: string[]) => prev.includes(name) ? prev.filter((n) => n !== name) : [...prev, name] @@ -21,27 +28,8 @@ export default function CalendarSelection({ return (

personnalCalendars

- {Object.keys(calendars) - .filter((id) => id.split("/")[0] === userId) - .map((id) => { - return ( -
- -
- ); - })} -

sharedCalendars

- {Object.keys(calendars) - .filter((id) => id.split("/")[0] !== userId) - .map((id) => ( + {personnalCalendars.map((id) => { + return (
- ))} + ); + })} + {delegatedCalendars.length > 0 && ( + <> +

delegatedCalendars

+ {delegatedCalendars.map((id) => ( +
+ +
+ ))} + + )} + {sharedCalendars.length > 0 && ( + <> +

sharedCalendars

+ {sharedCalendars.map((id) => ( +
+ +
+ ))} + + )}
); } diff --git a/src/features/Calendars/CalendarSlice.ts b/src/features/Calendars/CalendarSlice.ts index 016bb50..aaee08a 100644 --- a/src/features/Calendars/CalendarSlice.ts +++ b/src/features/Calendars/CalendarSlice.ts @@ -6,7 +6,6 @@ import { getOpenPaasUser, getUserDetails } from "../User/userAPI"; import { parseCalendarEvent } from "../Events/eventUtils"; import { deleteEvent, putEvent } from "../Events/EventApi"; import { formatDateToYYYYMMDDTHHMMSS } from "../../utils/dateUtils"; -import { responsiveFontSizes } from "@mui/material"; export const getCalendarsListAsync = createAsyncThunk< Record // Return type @@ -19,11 +18,17 @@ export const getCalendarsListAsync = createAsyncThunk< for (const cal of rawCalendars) { const name = cal["dav:name"]; const description = cal["dav:description"]; - const id = cal["calendarserver:source"] + let delegated = false; + let source = cal["calendarserver:source"] ? cal["calendarserver:source"]._links.self.href - .replace("/calendars/", "") - .replace(".json", "") - : cal._links.self.href.replace("/calendars/", "").replace(".json", ""); + : cal._links.self.href; + if (cal["calendarserver:delegatedsource"]) { + source = cal["calendarserver:delegatedsource"]; + delegated = true; + } + console.log(source); + const id = source.replace("/calendars/", "").replace(".json", ""); + const ownerData: any = await getUserDetails(id.split("/")[0]); const color = cal["apple:color"]; importedCalendars[id] = { @@ -31,6 +36,7 @@ export const getCalendarsListAsync = createAsyncThunk< name, ownerEmails: ownerData.emails, description, + delegated, color, events: {}, }; diff --git a/src/features/Calendars/CalendarTypes.ts b/src/features/Calendars/CalendarTypes.ts index 1d6556b..70fcf3d 100644 --- a/src/features/Calendars/CalendarTypes.ts +++ b/src/features/Calendars/CalendarTypes.ts @@ -3,6 +3,7 @@ import { CalendarEvent } from "../Events/EventsTypes"; export interface Calendars { id: string; name: string; + delegated?: boolean; prodid?: string; color?: string; ownerEmails?: string[];