[#317] improved event error management + test (#358)

Co-authored-by: Camille Moussu <cmoussu@linagora.com>
This commit is contained in:
Camille Moussu
2025-11-25 15:46:30 +01:00
committed by GitHub
parent 9151ff5563
commit d8c931e02e
3 changed files with 115 additions and 5 deletions
@@ -0,0 +1,96 @@
import { act, fireEvent, screen, waitFor } from "@testing-library/react";
import { renderWithProviders } from "../utils/Renderwithproviders";
import CalendarLayout from "../../src/components/Calendar/CalendarLayout";
describe("Event Error Handling", () => {
beforeEach(() => {
localStorage.clear();
jest.clearAllMocks();
});
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);
const erroredState = {
user: {
userData: {
sub: "test",
email: "test@test.com",
sid: "mockSid",
openpaasId: "user1",
},
tokens: { accessToken: "token" },
},
calendars: {
list: {
"user1/cal1": {
name: "Calendar personal",
id: "user1/cal1",
color: { light: "#FF0000", dark: "#000" },
ownerEmails: ["alice@example.com"],
events: {
event1: {
id: "event1",
calId: "user1/cal1",
uid: "event1",
title: "Test Event",
start: start.toISOString(),
end: start.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,
},
};
it("BUGFIX: does not re-report errors after clearing error snackbar", async () => {
const consoleWarnSpy = jest.spyOn(console, "warn").mockImplementation();
await act(async () =>
renderWithProviders(<CalendarLayout />, erroredState)
);
await waitFor(() => {
expect(screen.getByText("Test Event"));
expect(screen.getByRole("alert")).toBeInTheDocument();
});
const closeButton = screen.queryByRole("button", { name: "common.ok" });
if (closeButton) {
const initialWarnCount = consoleWarnSpy.mock.calls.length;
await act(async () => {
fireEvent.click(closeButton);
});
await waitFor(() => {
expect(screen.queryByRole("alert")).not.toBeInTheDocument();
});
const afterCloseWarnCount = consoleWarnSpy.mock.calls.length;
expect(afterCloseWarnCount).toBe(initialWarnCount);
}
consoleWarnSpy.mockRestore();
});
});
+3 -1
View File
@@ -1,5 +1,6 @@
export class EventErrorHandler {
private errors = new Map<string, string>();
private reportedEvents = new Set<string>();
private onErrorCallback?: (messages: string[]) => void;
setErrorCallback(callback: (messages: string[]) => void) {
@@ -7,7 +8,8 @@ export class EventErrorHandler {
}
reportError(eventId: string, message: string) {
if (!this.errors.has(eventId)) {
if (!this.reportedEvents.has(eventId)) {
this.reportedEvents.add(eventId);
this.errors.set(eventId, message);
console.warn(`[EventErrorHandler] ${eventId}: ${message}`);
this.emit();
@@ -1,5 +1,5 @@
import React from "react";
import { Card, Typography } from "@mui/material";
import { useRef, useEffect } from "react";
import { EventErrorHandler } from "../../Error/EventErrorHandler";
export function ErrorEventChip({
@@ -11,9 +11,21 @@ export function ErrorEventChip({
errorHandler: EventErrorHandler;
error: any;
}) {
const message =
error instanceof Error ? error.message : "Unknown error during rendering";
errorHandler.reportError(event._def.extendedProps.uid || event.id, message);
const hasReported = useRef(false);
useEffect(() => {
if (!hasReported.current) {
const message =
error instanceof Error
? error.message
: `${error.class} error during rendering ${event._def.extendedProps.uid || event.id}`;
errorHandler.reportError(
event._def.extendedProps.uid || event.id,
message
);
hasReported.current = true;
}
}, [event, errorHandler, error]);
return (
<Card