From de1304a9a7f13213ac2e1e216875fb6b39204653 Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 3 Apr 2026 11:12:39 +0200 Subject: [PATCH 1/2] Report group call errors to sentry --- src/room/GroupCallErrorBoundary.test.tsx | 37 ++++++++++++++++++++++++ src/room/GroupCallErrorBoundary.tsx | 7 +++++ 2 files changed, 44 insertions(+) diff --git a/src/room/GroupCallErrorBoundary.test.tsx b/src/room/GroupCallErrorBoundary.test.tsx index 86921710..57e38d04 100644 --- a/src/room/GroupCallErrorBoundary.test.tsx +++ b/src/room/GroupCallErrorBoundary.test.tsx @@ -16,6 +16,7 @@ import { } from "react"; import { BrowserRouter } from "react-router-dom"; import userEvent from "@testing-library/user-event"; +import * as Sentry from "@sentry/react"; import { type CallErrorRecoveryAction, @@ -32,6 +33,15 @@ import { import { mockConfig } from "../utils/test.ts"; import { ElementWidgetActions, type WidgetHelpers } from "../widget.ts"; +// Mock Sentry before importing the component +vi.mock("@sentry/react", async () => { + const actual = await vi.importActual("@sentry/react"); + return { + ...actual, + captureException: vi.fn(), + }; +}); + test.each([ { error: new MatrixRTCTransportMissingError("example.com"), @@ -212,6 +222,33 @@ describe("Rageshake button", () => { }); }); +test("should call Sentry.captureException for unknown errors", async () => { + vi.mocked(Sentry.captureException).mockClear(); // Clear previous calls + + const originalError = new Error("Unknown test error"); + const error = new UnknownCallError(originalError); + const TestComponent = (): ReactNode => { + throw error; + }; + + render( + + + + + , + ); + + await screen.findByText(/Something went wrong/); + + expect(Sentry.captureException).toHaveBeenCalledWith(error); + expect(Sentry.captureException).toHaveBeenCalledOnce(); +}); + test("should have a close button in widget mode", async () => { const error = new MatrixRTCTransportMissingError("example.com"); const TestComponent = (): ReactNode => { diff --git a/src/room/GroupCallErrorBoundary.tsx b/src/room/GroupCallErrorBoundary.tsx index ca407ed4..a056b790 100644 --- a/src/room/GroupCallErrorBoundary.tsx +++ b/src/room/GroupCallErrorBoundary.tsx @@ -13,7 +13,9 @@ import { type ReactNode, type SVGAttributes, useCallback, + useEffect, } from "react"; +import * as Sentry from "@sentry/react"; import { Trans, useTranslation } from "react-i18next"; import { ErrorSolidIcon, @@ -53,6 +55,11 @@ const ErrorPage: FC = ({ recoveryActionHandler, widget, }: ErrorPageProps): ReactElement => { + // We want to auto capture to sentry + useEffect(() => { + Sentry.captureException(error); + }, [error]); + const { t } = useTranslation(); logger.error("Error boundary caught:", error); let icon: ComponentType>; From 76dcd3ac3f471fa3d4a9b76ef2dbec615c98d9d0 Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 7 Apr 2026 14:10:31 +0200 Subject: [PATCH 2/2] review: Improve test --- src/room/GroupCallErrorBoundary.test.tsx | 59 +++++++++++++++--------- 1 file changed, 37 insertions(+), 22 deletions(-) diff --git a/src/room/GroupCallErrorBoundary.test.tsx b/src/room/GroupCallErrorBoundary.test.tsx index 57e38d04..994d1b86 100644 --- a/src/room/GroupCallErrorBoundary.test.tsx +++ b/src/room/GroupCallErrorBoundary.test.tsx @@ -26,8 +26,12 @@ import { ConnectionLostError, E2EENotSupportedError, type ElementCallError, + FailToGetOpenIdToken, + FailToStartLivekitConnection, InsufficientCapacityError, MatrixRTCTransportMissingError, + NoMatrix2AuthorizationService, + SFURoomCreationRestrictedError, UnknownCallError, } from "../utils/errors.ts"; import { mockConfig } from "../utils/test.ts"; @@ -222,32 +226,43 @@ describe("Rageshake button", () => { }); }); -test("should call Sentry.captureException for unknown errors", async () => { - vi.mocked(Sentry.captureException).mockClear(); // Clear previous calls +test.each([ + { error: new MatrixRTCTransportMissingError("example.com") }, + { error: new ConnectionLostError() }, + { error: new UnknownCallError(new Error("FOO")) }, + { error: new E2EENotSupportedError() }, + { error: new InsufficientCapacityError() }, + { error: new SFURoomCreationRestrictedError() }, + { error: new FailToStartLivekitConnection() }, + { error: new NoMatrix2AuthorizationService(new Error("FOO")) }, + { error: new FailToGetOpenIdToken(new Error("FOO")) }, +])( + "should call Sentry.captureException for group call errors $error", + ({ error }) => { + vi.mocked(Sentry.captureException).mockClear(); // Clear previous calls - const originalError = new Error("Unknown test error"); - const error = new UnknownCallError(originalError); - const TestComponent = (): ReactNode => { - throw error; - }; + const TestComponent = (): ReactNode => { + throw error; + }; - render( - - - - - , - ); + render( + + + + + , + ); - await screen.findByText(/Something went wrong/); + // await screen.findByText(/Something went wrong/); - expect(Sentry.captureException).toHaveBeenCalledWith(error); - expect(Sentry.captureException).toHaveBeenCalledOnce(); -}); + expect(Sentry.captureException).toHaveBeenCalledWith(error); + expect(Sentry.captureException).toHaveBeenCalledOnce(); + }, +); test("should have a close button in widget mode", async () => { const error = new MatrixRTCTransportMissingError("example.com");