Merge pull request #54 from linagora/4-story-manage-attendance
4 story manage attendance
This commit is contained in:
@@ -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(<CalendarApp />, preloadedState);
|
||||
expect(screen.getByText("Personnal Calendars")).toBeInTheDocument();
|
||||
expect(screen.getByText("Delegated Calendars")).toBeInTheDocument();
|
||||
expect(screen.getByText("Shared Calendars")).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(<CalendarApp />, preloadedState);
|
||||
expect(screen.getByText("Personnal Calendars")).toBeInTheDocument();
|
||||
expect(screen.queryByText("Delegated Calendars")).not.toBeInTheDocument();
|
||||
expect(screen.queryByText("Shared Calendars")).not.toBeInTheDocument();
|
||||
|
||||
expect(screen.getByLabelText("Calendar personnal")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -18,7 +18,6 @@ describe("CalendarApp integration", () => {
|
||||
jest.clearAllMocks();
|
||||
const dispatch = jest.fn() as ThunkDispatch<any, any, any>;
|
||||
jest.spyOn(appHooks, "useAppDispatch").mockReturnValue(dispatch);
|
||||
jest.useFakeTimers(); // optional
|
||||
});
|
||||
|
||||
const renderCalendar = () => {
|
||||
@@ -36,7 +35,9 @@ describe("CalendarApp integration", () => {
|
||||
list: {
|
||||
"667037022b752d0026472254/cal1": {
|
||||
name: "Calendar 1",
|
||||
id: "667037022b752d0026472254/cal1",
|
||||
color: "#FF0000",
|
||||
ownerEmails: ["alice@example.com"],
|
||||
events: {
|
||||
event1: {
|
||||
id: "event1",
|
||||
@@ -45,6 +46,21 @@ describe("CalendarApp integration", () => {
|
||||
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",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -30,6 +30,7 @@ describe("MiniCalendar", () => {
|
||||
"667037022b752d0026472254/cal1": {
|
||||
name: "Calendar 1",
|
||||
color: "#FF0000",
|
||||
ownerEmails: ["test@test.com"],
|
||||
events: {
|
||||
event1: {
|
||||
calId: "667037022b752d0026472254/cal1",
|
||||
@@ -139,6 +140,7 @@ describe("Found Bugs", () => {
|
||||
"667037022b752d0026472254/cal1": {
|
||||
name: "Calendar 1",
|
||||
color: "#FF0000",
|
||||
ownerEmails: ["test.test@test.com"],
|
||||
events: {
|
||||
event1: {
|
||||
calId: "667037022b752d0026472254/cal1",
|
||||
|
||||
@@ -169,4 +169,286 @@ describe("Event Display", () => {
|
||||
|
||||
expect(mockOnClose).toHaveBeenCalledWith({}, "backdropClick");
|
||||
});
|
||||
it("renders RSVP buttons when user is an attendee", () => {
|
||||
const rsvpStateIsOrga = {
|
||||
...preloadedState,
|
||||
calendars: {
|
||||
...preloadedState.calendars,
|
||||
list: {
|
||||
...preloadedState.calendars.list,
|
||||
"667037022b752d0026472254/cal1": {
|
||||
...preloadedState.calendars.list["667037022b752d0026472254/cal1"],
|
||||
events: {
|
||||
event1: {
|
||||
...preloadedState.calendars.list[
|
||||
"667037022b752d0026472254/cal1"
|
||||
].events.event1,
|
||||
attendee: [
|
||||
{
|
||||
cal_address: "test@test.com",
|
||||
cn: "Test User",
|
||||
partstat: "NEEDS-ACTION",
|
||||
},
|
||||
{
|
||||
cal_address: "organizer@test.com",
|
||||
cn: "Test Organizer",
|
||||
partstat: "NEEDS-ACTION",
|
||||
},
|
||||
],
|
||||
organizer: {
|
||||
cal_address: "organizer@test.com",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
renderWithProviders(
|
||||
<EventDisplayModal
|
||||
anchorEl={document.body}
|
||||
open={true}
|
||||
onClose={mockOnClose}
|
||||
calId={"667037022b752d0026472254/cal1"}
|
||||
eventId={"event1"}
|
||||
/>,
|
||||
rsvpStateIsOrga
|
||||
);
|
||||
|
||||
expect(screen.getByText("Will you attend?")).toBeInTheDocument();
|
||||
expect(screen.getByRole("button", { name: "Accept" })).toBeInTheDocument();
|
||||
expect(screen.getByRole("button", { name: "Maybe" })).toBeInTheDocument();
|
||||
expect(screen.getByRole("button", { name: "Decline" })).toBeInTheDocument();
|
||||
});
|
||||
it("doesnt renders RSVP buttons when user isnt an attendee", () => {
|
||||
const rsvpStateIsOrga = {
|
||||
...preloadedState,
|
||||
calendars: {
|
||||
...preloadedState.calendars,
|
||||
list: {
|
||||
...preloadedState.calendars.list,
|
||||
"667037022b752d0026472254/cal1": {
|
||||
...preloadedState.calendars.list["667037022b752d0026472254/cal1"],
|
||||
events: {
|
||||
event1: {
|
||||
...preloadedState.calendars.list[
|
||||
"667037022b752d0026472254/cal1"
|
||||
].events.event1,
|
||||
attendee: [
|
||||
{
|
||||
cal_address: "organizer@test.com",
|
||||
cn: "Test Organizer",
|
||||
partstat: "NEEDS-ACTION",
|
||||
},
|
||||
],
|
||||
organizer: {
|
||||
cal_address: "organizer@test.com",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
renderWithProviders(
|
||||
<EventDisplayModal
|
||||
anchorEl={document.body}
|
||||
open={true}
|
||||
onClose={mockOnClose}
|
||||
calId={"667037022b752d0026472254/cal1"}
|
||||
eventId={"event1"}
|
||||
/>,
|
||||
rsvpStateIsOrga
|
||||
);
|
||||
|
||||
expect(screen.queryByText("Will you attend?")).not.toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByRole("button", { name: "Accept" })
|
||||
).not.toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByRole("button", { name: "Maybe" })
|
||||
).not.toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByRole("button", { name: "Decline" })
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("handles RSVP Accept click", async () => {
|
||||
const spy = jest
|
||||
.spyOn(eventThunks, "putEventAsync")
|
||||
.mockImplementation((payload) => {
|
||||
return () => Promise.resolve(payload) as any;
|
||||
});
|
||||
|
||||
const rsvpState = {
|
||||
...preloadedState,
|
||||
calendars: {
|
||||
...preloadedState.calendars,
|
||||
list: {
|
||||
...preloadedState.calendars.list,
|
||||
"667037022b752d0026472254/cal1": {
|
||||
...preloadedState.calendars.list["667037022b752d0026472254/cal1"],
|
||||
events: {
|
||||
event1: {
|
||||
...preloadedState.calendars.list[
|
||||
"667037022b752d0026472254/cal1"
|
||||
].events.event1,
|
||||
attendee: [
|
||||
{
|
||||
cal_address: "test@test.com",
|
||||
cn: "Test User",
|
||||
partstat: "NEEDS-ACTION",
|
||||
},
|
||||
],
|
||||
organizer: {
|
||||
cal_address: "organizer@test.com",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
renderWithProviders(
|
||||
<EventDisplayModal
|
||||
anchorEl={document.body}
|
||||
open={true}
|
||||
onClose={mockOnClose}
|
||||
calId={"667037022b752d0026472254/cal1"}
|
||||
eventId={"event1"}
|
||||
/>,
|
||||
rsvpState
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByRole("button", { name: "Accept" }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(spy).toHaveBeenCalled();
|
||||
expect(mockOnClose).toHaveBeenCalledWith({}, "backdropClick");
|
||||
});
|
||||
|
||||
const updatedEvent = spy.mock.calls[0][0].newEvent;
|
||||
expect(updatedEvent.attendee[0].partstat).toBe("ACCEPTED");
|
||||
});
|
||||
|
||||
it("handles RSVP Maybe click", async () => {
|
||||
const spy = jest
|
||||
.spyOn(eventThunks, "putEventAsync")
|
||||
.mockImplementation((payload) => {
|
||||
return () => Promise.resolve(payload) as any;
|
||||
});
|
||||
|
||||
const rsvpState = {
|
||||
...preloadedState,
|
||||
calendars: {
|
||||
...preloadedState.calendars,
|
||||
list: {
|
||||
...preloadedState.calendars.list,
|
||||
"667037022b752d0026472254/cal1": {
|
||||
...preloadedState.calendars.list["667037022b752d0026472254/cal1"],
|
||||
events: {
|
||||
event1: {
|
||||
...preloadedState.calendars.list[
|
||||
"667037022b752d0026472254/cal1"
|
||||
].events.event1,
|
||||
attendee: [
|
||||
{
|
||||
cal_address: "test@test.com",
|
||||
cn: "Test User",
|
||||
partstat: "NEEDS-ACTION",
|
||||
},
|
||||
],
|
||||
organizer: {
|
||||
cal_address: "organizer@test.com",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
renderWithProviders(
|
||||
<EventDisplayModal
|
||||
anchorEl={document.body}
|
||||
open={true}
|
||||
onClose={mockOnClose}
|
||||
calId={"667037022b752d0026472254/cal1"}
|
||||
eventId={"event1"}
|
||||
/>,
|
||||
rsvpState
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByRole("button", { name: "Maybe" }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(spy).toHaveBeenCalled();
|
||||
expect(mockOnClose).toHaveBeenCalledWith({}, "backdropClick");
|
||||
});
|
||||
|
||||
const updatedEvent = spy.mock.calls[0][0].newEvent;
|
||||
expect(updatedEvent.attendee[0].partstat).toBe("TENTATIVE");
|
||||
});
|
||||
|
||||
it("handles RSVP Decline click", async () => {
|
||||
const spy = jest
|
||||
.spyOn(eventThunks, "putEventAsync")
|
||||
.mockImplementation((payload) => {
|
||||
return () => Promise.resolve(payload) as any;
|
||||
});
|
||||
|
||||
const rsvpState = {
|
||||
...preloadedState,
|
||||
calendars: {
|
||||
...preloadedState.calendars,
|
||||
list: {
|
||||
...preloadedState.calendars.list,
|
||||
"667037022b752d0026472254/cal1": {
|
||||
...preloadedState.calendars.list["667037022b752d0026472254/cal1"],
|
||||
events: {
|
||||
event1: {
|
||||
...preloadedState.calendars.list[
|
||||
"667037022b752d0026472254/cal1"
|
||||
].events.event1,
|
||||
attendee: [
|
||||
{
|
||||
cal_address: "test@test.com",
|
||||
cn: "Test User",
|
||||
partstat: "NEEDS-ACTION",
|
||||
},
|
||||
],
|
||||
organizer: {
|
||||
cal_address: "organizer@test.com",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
renderWithProviders(
|
||||
<EventDisplayModal
|
||||
anchorEl={document.body}
|
||||
open={true}
|
||||
onClose={mockOnClose}
|
||||
calId={"667037022b752d0026472254/cal1"}
|
||||
eventId={"event1"}
|
||||
/>,
|
||||
rsvpState
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByRole("button", { name: "Decline" }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(spy).toHaveBeenCalled();
|
||||
expect(mockOnClose).toHaveBeenCalledWith({}, "backdropClick");
|
||||
});
|
||||
|
||||
const updatedEvent = spy.mock.calls[0][0].newEvent;
|
||||
expect(updatedEvent.attendee[0].partstat).toBe("DECLINED");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -16,12 +16,12 @@ describe("parseCalendarEvent", () => {
|
||||
["SUMMARY", {}, "text", "Team Meeting"],
|
||||
["DESCRIPTION", {}, "text", "Discuss roadmap"],
|
||||
["LOCATION", {}, "text", "Zoom"],
|
||||
["ORGANIZER", { cn: "Alice" }, "cal-address", "mailto:alice@example.com"],
|
||||
["ORGANIZER", { cn: "Alice" }, "cal-address", "alice@example.com"],
|
||||
[
|
||||
"ATTENDEE",
|
||||
{ cn: "Bob", partstat: "ACCEPTED" },
|
||||
"cal-address",
|
||||
"mailto:bob@example.com",
|
||||
"bob@example.com",
|
||||
],
|
||||
["X-OPENPAAS-VIDEOCONFERENCE", {}, "text", "https://meet.link"],
|
||||
["STATUS", {}, "text", "CONFIRMED"],
|
||||
@@ -98,8 +98,8 @@ describe("parseCalendarEvent", () => {
|
||||
const rawData = [
|
||||
["UID", {}, "text", "event-4"],
|
||||
["DTSTART", {}, "date-time", "2025-07-18T09:00:00Z"],
|
||||
["ATTENDEE", {}, "cal-address", "mailto:john@example.com"],
|
||||
["ORGANIZER", {}, "cal-address", "mailto:jane@example.com"],
|
||||
["ATTENDEE", {}, "cal-address", "john@example.com"],
|
||||
["ORGANIZER", {}, "cal-address", "jane@example.com"],
|
||||
] as unknown as [string, Record<string, string>, string, any];
|
||||
|
||||
const result = parseCalendarEvent(rawData, baseColor, calendarId);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { clientConfig } from "../../../src/features/User/oidcAuth";
|
||||
import getOpenPaasUser from "../../../src/features/User/userAPI";
|
||||
import { getOpenPaasUser } from "../../../src/features/User/userAPI";
|
||||
import { api } from "../../../src/utils/apiUtils";
|
||||
|
||||
jest.mock("../../../src/utils/apiUtils");
|
||||
|
||||
Reference in New Issue
Block a user