From 8b35bc5e259037f432a4ce5a9107d1dd2335316a Mon Sep 17 00:00:00 2001 From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com> Date: Sat, 16 Aug 2025 21:19:18 +0800 Subject: [PATCH 1/8] Create sourcemaps --- rsbuild.config.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rsbuild.config.ts b/rsbuild.config.ts index 9d815eb7d3..86ae1dbc79 100644 --- a/rsbuild.config.ts +++ b/rsbuild.config.ts @@ -151,6 +151,7 @@ export default defineConfig({ output: { distPath: { root: './build' - } + }, + sourceMap: true } }); From b9934b0a1047730b71b074a99877d95ba7055e65 Mon Sep 17 00:00:00 2001 From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com> Date: Sat, 16 Aug 2025 21:40:35 +0800 Subject: [PATCH 2/8] Replace Sentry browser with React integration --- package.json | 2 +- yarn.lock | 85 ++++++++++++++++++++++++++++++---------------------- 2 files changed, 50 insertions(+), 37 deletions(-) diff --git a/package.json b/package.json index a0113308b8..d1926b7f10 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "@mantine/hooks": "^7.11.2", "@octokit/rest": "^22.0.0", "@reduxjs/toolkit": "^1.9.7", - "@sentry/browser": "^8.33.0", + "@sentry/react": "^10.5.0", "@sourceacademy/c-slang": "^1.0.21", "@sourceacademy/sharedb-ace": "2.1.1", "@sourceacademy/sling-client": "^0.1.0", diff --git a/yarn.lock b/yarn.lock index 25641adc70..447363e4bc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3183,61 +3183,74 @@ __metadata: languageName: node linkType: hard -"@sentry-internal/browser-utils@npm:8.55.0": - version: 8.55.0 - resolution: "@sentry-internal/browser-utils@npm:8.55.0" +"@sentry-internal/browser-utils@npm:10.5.0": + version: 10.5.0 + resolution: "@sentry-internal/browser-utils@npm:10.5.0" dependencies: - "@sentry/core": "npm:8.55.0" - checksum: 10c0/201eb94ee64a4dab058153c64dd4ce0af082f3c3bc84a5441cdadf344d9554a0a67c9d9dfdff720eb42de214d67d734d5bda25a050c2efd59c03f60562bb139a + "@sentry/core": "npm:10.5.0" + checksum: 10c0/ada1cfa7f626c7272f67f10cd828e17d2054e64230c10e35b06a5d07d303c8d8dc0efd73d8624ab0f1098941009b29d239a8be9529fac58aeb0f127dadf0a1ac languageName: node linkType: hard -"@sentry-internal/feedback@npm:8.55.0": - version: 8.55.0 - resolution: "@sentry-internal/feedback@npm:8.55.0" +"@sentry-internal/feedback@npm:10.5.0": + version: 10.5.0 + resolution: "@sentry-internal/feedback@npm:10.5.0" dependencies: - "@sentry/core": "npm:8.55.0" - checksum: 10c0/2515c4eca6226e3df28a498f7f3771d7820556887bf8c06f2d5469c92474cf72ed81eaa0079f6bcf46905c54315e2631bb7b9ed7ed6741cf9b7f73a3f4875acc + "@sentry/core": "npm:10.5.0" + checksum: 10c0/a7752a08a5452b2c079f0df1c80e8b51875332cfe8fa0478095f0684dbf365432e6c0dfc1564cff6d35fd1a6f6d8e91705ba28b2e5437d133b7af88ef5120fa6 languageName: node linkType: hard -"@sentry-internal/replay-canvas@npm:8.55.0": - version: 8.55.0 - resolution: "@sentry-internal/replay-canvas@npm:8.55.0" +"@sentry-internal/replay-canvas@npm:10.5.0": + version: 10.5.0 + resolution: "@sentry-internal/replay-canvas@npm:10.5.0" dependencies: - "@sentry-internal/replay": "npm:8.55.0" - "@sentry/core": "npm:8.55.0" - checksum: 10c0/6f3c619ede1de47635035f74477dd5a11e5c2cac9d0906448a7fffb6dad1c5bd9a49a594fbc2a51ba3b1859a91f60e08ab6de2d9961ccbaa343af580f1d13fb1 + "@sentry-internal/replay": "npm:10.5.0" + "@sentry/core": "npm:10.5.0" + checksum: 10c0/306f93be5a17b1d83cc2143b33558d861fe6ad40170e33a4a5b71af524fa7a2453b2b7a17172faa2d98fd80b7aa4cc233cbf8ce6e261d3803f317be7206fa0ff languageName: node linkType: hard -"@sentry-internal/replay@npm:8.55.0": - version: 8.55.0 - resolution: "@sentry-internal/replay@npm:8.55.0" +"@sentry-internal/replay@npm:10.5.0": + version: 10.5.0 + resolution: "@sentry-internal/replay@npm:10.5.0" dependencies: - "@sentry-internal/browser-utils": "npm:8.55.0" - "@sentry/core": "npm:8.55.0" - checksum: 10c0/320fd5685c1e84c5feebaa88fc72afd0bd5189b95d690f8c24301cd8b13789431b2c1d28e3e5a93f669ca3b80cdc830e672723aa7a28ff8f0b901674ce0c0529 + "@sentry-internal/browser-utils": "npm:10.5.0" + "@sentry/core": "npm:10.5.0" + checksum: 10c0/3edb71b2d5ab27d081996c2b3358a134322f2f271c6887ba8392558fbe8f2a8e68092d04bf73b9354c0f9f058ab8eca59adb8d35a0772ace53988b1856ec910b languageName: node linkType: hard -"@sentry/browser@npm:^8.33.0": - version: 8.55.0 - resolution: "@sentry/browser@npm:8.55.0" +"@sentry/browser@npm:10.5.0": + version: 10.5.0 + resolution: "@sentry/browser@npm:10.5.0" dependencies: - "@sentry-internal/browser-utils": "npm:8.55.0" - "@sentry-internal/feedback": "npm:8.55.0" - "@sentry-internal/replay": "npm:8.55.0" - "@sentry-internal/replay-canvas": "npm:8.55.0" - "@sentry/core": "npm:8.55.0" - checksum: 10c0/a485de7385851c96ed4c2291d065594aeea2076b11b3b113f4866fdbff1522524abd97664f0d0b011e0eff6c4986a556f080bccfa1b770466c6afcb6122dfbaf + "@sentry-internal/browser-utils": "npm:10.5.0" + "@sentry-internal/feedback": "npm:10.5.0" + "@sentry-internal/replay": "npm:10.5.0" + "@sentry-internal/replay-canvas": "npm:10.5.0" + "@sentry/core": "npm:10.5.0" + checksum: 10c0/5fe68957a29b84f703ab02a4e4fb59c36ca08eb6e8c057a94690e31a05ebd42ced8029d3bc44095d1194e82d82c3455d7a9847523be75d1c438af930f63b8463 languageName: node linkType: hard -"@sentry/core@npm:8.55.0": - version: 8.55.0 - resolution: "@sentry/core@npm:8.55.0" - checksum: 10c0/51c1768f0bd940a060787b402dba9df3347c918ea4c0fdc300d45c37703ebbf6f7adee9fff332cfd6b23372b33c46e6d2f31a04227762d490aaddc14773894a0 +"@sentry/core@npm:10.5.0": + version: 10.5.0 + resolution: "@sentry/core@npm:10.5.0" + checksum: 10c0/e0b29c6647897cf6dc5f0b99c29f2bbad62ba4db57d699790f39028f0124e388728b955d794d4c07cb6f93b17e5011095c9927bf111a6f62caa9147034ef56e1 + languageName: node + linkType: hard + +"@sentry/react@npm:^10.5.0": + version: 10.5.0 + resolution: "@sentry/react@npm:10.5.0" + dependencies: + "@sentry/browser": "npm:10.5.0" + "@sentry/core": "npm:10.5.0" + hoist-non-react-statics: "npm:^3.3.2" + peerDependencies: + react: ^16.14.0 || 17.x || 18.x || 19.x + checksum: 10c0/b42fed203599d5d9e3b3d61adf9a57da0e00e1bf2e69c5d1bd8664310ff600ed53dda3cbbb5f2f5956dd10e5c52e903828b508c9d8cd41289bbdd9050948f574 languageName: node linkType: hard @@ -7543,7 +7556,7 @@ __metadata: "@rsbuild/plugin-react": "npm:^1.3.0" "@rsbuild/plugin-sass": "npm:^1.3.1" "@rsbuild/plugin-svgr": "npm:^1.2.0" - "@sentry/browser": "npm:^8.33.0" + "@sentry/react": "npm:^10.5.0" "@sourceacademy/c-slang": "npm:^1.0.21" "@sourceacademy/sharedb-ace": "npm:2.1.1" "@sourceacademy/sling-client": "npm:^0.1.0" From a9ad0457c8a754895dafdc967a033d65ce1044e2 Mon Sep 17 00:00:00 2001 From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com> Date: Sat, 16 Aug 2025 23:30:33 +0800 Subject: [PATCH 3/8] Update import sources --- src/commons/editor/UseShareAce.tsx | 2 +- src/commons/sagas/LoginSaga.ts | 2 +- src/commons/sagas/SafeEffects.ts | 2 +- src/commons/sagas/__tests__/SafeEffects.test.ts | 6 +++--- src/index.tsx | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/commons/editor/UseShareAce.tsx b/src/commons/editor/UseShareAce.tsx index 61816a7fb9..37ee930cca 100644 --- a/src/commons/editor/UseShareAce.tsx +++ b/src/commons/editor/UseShareAce.tsx @@ -5,7 +5,7 @@ import { AceMultiSelectionManager, AceRadarView } from '@convergencelabs/ace-collab-ext'; -import * as Sentry from '@sentry/browser'; +import * as Sentry from '@sentry/react'; import sharedbAce from '@sourceacademy/sharedb-ace'; import type SharedbAceBinding from '@sourceacademy/sharedb-ace/binding'; import { CollabEditingAccess } from '@sourceacademy/sharedb-ace/types'; diff --git a/src/commons/sagas/LoginSaga.ts b/src/commons/sagas/LoginSaga.ts index 655d88a5c1..8515e58a70 100644 --- a/src/commons/sagas/LoginSaga.ts +++ b/src/commons/sagas/LoginSaga.ts @@ -1,4 +1,4 @@ -import { setUser } from '@sentry/browser'; +import { setUser } from '@sentry/react'; import { call, select } from 'redux-saga/effects'; import Messages, { sendToWebview } from 'src/features/vscode/messages'; diff --git a/src/commons/sagas/SafeEffects.ts b/src/commons/sagas/SafeEffects.ts index bc88f59c4e..3631996338 100644 --- a/src/commons/sagas/SafeEffects.ts +++ b/src/commons/sagas/SafeEffects.ts @@ -1,5 +1,5 @@ import type { ActionMatchingPattern } from '@redux-saga/types'; -import * as Sentry from '@sentry/browser'; +import * as Sentry from '@sentry/react'; import { type ActionPattern, type ForkEffect, diff --git a/src/commons/sagas/__tests__/SafeEffects.test.ts b/src/commons/sagas/__tests__/SafeEffects.test.ts index 7607b19e1e..e612212ffe 100644 --- a/src/commons/sagas/__tests__/SafeEffects.test.ts +++ b/src/commons/sagas/__tests__/SafeEffects.test.ts @@ -1,12 +1,12 @@ -import * as Sentry from '@sentry/browser'; +import * as Sentry from '@sentry/react'; import { call } from 'redux-saga/effects'; import { expectSaga } from 'redux-saga-test-plan'; import { vi } from 'vitest'; import { wrapSaga } from '../SafeEffects'; -vi.mock('@sentry/browser', async () => ({ - ...(await vi.importActual('../../../../node_modules/@sentry/browser')), +vi.mock('@sentry/react', async () => ({ + ...(await vi.importActual('../../../../node_modules/@sentry/react')), captureException: vi.fn() })); diff --git a/src/index.tsx b/src/index.tsx index bb990d08d2..c600eb740a 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -2,7 +2,7 @@ import 'src/i18n/i18n'; import 'src/styles/index.scss'; import { Button, OverlaysProvider } from '@blueprintjs/core'; -import * as Sentry from '@sentry/browser'; +import * as Sentry from '@sentry/react'; import { setModulesStaticURL } from 'js-slang/dist/modules/loader'; import { createRoot } from 'react-dom/client'; import { Provider } from 'react-redux'; From b3923c489d7c7b375a649d9396894833674f044c Mon Sep 17 00:00:00 2001 From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com> Date: Sat, 16 Aug 2025 23:31:41 +0800 Subject: [PATCH 4/8] Simplify test import --- src/commons/sagas/__tests__/SafeEffects.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commons/sagas/__tests__/SafeEffects.test.ts b/src/commons/sagas/__tests__/SafeEffects.test.ts index e612212ffe..5d1b1d1289 100644 --- a/src/commons/sagas/__tests__/SafeEffects.test.ts +++ b/src/commons/sagas/__tests__/SafeEffects.test.ts @@ -5,8 +5,8 @@ import { vi } from 'vitest'; import { wrapSaga } from '../SafeEffects'; -vi.mock('@sentry/react', async () => ({ - ...(await vi.importActual('../../../../node_modules/@sentry/react')), +vi.mock('@sentry/react', async importOriginal => ({ + ...(await importOriginal()), captureException: vi.fn() })); From 786a0c955f79839a01f745d8ba1e78ca6414172c Mon Sep 17 00:00:00 2001 From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com> Date: Sat, 16 Aug 2025 23:49:08 +0800 Subject: [PATCH 5/8] Set up React Router-Sentry integration --- .../application/ApplicationWrapper.tsx | 3 ++- src/commons/navigationBar/NavigationBar.tsx | 7 ++++--- src/index.tsx | 19 ++++++++++++++++++- src/pages/achievement/Achievement.tsx | 7 ++++--- src/pages/leaderboard/Leaderboard.tsx | 7 ++++--- .../ContestLeaderboardWrapper.tsx | 9 +++++---- src/routes/routerConfig.tsx | 5 ++++- 7 files changed, 41 insertions(+), 16 deletions(-) diff --git a/src/commons/application/ApplicationWrapper.tsx b/src/commons/application/ApplicationWrapper.tsx index e60fc31780..88da52380d 100644 --- a/src/commons/application/ApplicationWrapper.tsx +++ b/src/commons/application/ApplicationWrapper.tsx @@ -1,5 +1,6 @@ import { Classes, NonIdealState } from '@blueprintjs/core'; import { IconNames } from '@blueprintjs/icons'; +import * as Sentry from '@sentry/react'; import classNames from 'classnames'; import { useEffect, useMemo, useState } from 'react'; import { useDispatch } from 'react-redux'; @@ -37,7 +38,7 @@ const ApplicationWrapper: React.FC = () => { ? playgroundOnlyRouterConfig : getFullAcademyRouterConfig({ name, isLoggedIn, courseId, academyRoutes }); - const r = createBrowserRouter(routerConfig); + const r = Sentry.wrapCreateBrowserRouterV7(createBrowserRouter)(routerConfig); dispatch(updateReactRouter(r)); return r; diff --git a/src/commons/navigationBar/NavigationBar.tsx b/src/commons/navigationBar/NavigationBar.tsx index 1b803b442f..1093e1cbb8 100644 --- a/src/commons/navigationBar/NavigationBar.tsx +++ b/src/commons/navigationBar/NavigationBar.tsx @@ -16,8 +16,9 @@ import { IconName, IconNames } from '@blueprintjs/icons'; import classNames from 'classnames'; import React, { useMemo, useState } from 'react'; import { Translation } from 'react-i18next'; -import { Location, NavLink, Route, Routes, useLocation } from 'react-router'; +import { type Location, NavLink, Route, useLocation } from 'react-router'; import { i18nDefaultLangKeys } from 'src/i18n/i18next'; +import { SentryRoutes } from 'src/routes/routerConfig'; import classes from 'src/styles/NavigationBar.module.scss'; import Dropdown from '../dropdown/Dropdown'; @@ -312,7 +313,7 @@ const NavigationBar: React.FC = () => { {commonNavbarRight} - + @@ -327,7 +328,7 @@ const NavigationBar: React.FC = () => { ) : null } /> - + ); }; diff --git a/src/index.tsx b/src/index.tsx index c600eb740a..44f5dfd2a6 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -4,8 +4,15 @@ import 'src/styles/index.scss'; import { Button, OverlaysProvider } from '@blueprintjs/core'; import * as Sentry from '@sentry/react'; import { setModulesStaticURL } from 'js-slang/dist/modules/loader'; +import { useEffect } from 'react'; import { createRoot } from 'react-dom/client'; import { Provider } from 'react-redux'; +import { + createRoutesFromChildren, + matchRoutes, + useLocation, + useNavigationType +} from 'react-router'; import Constants, { Links } from 'src/commons/utils/Constants'; import { showWarningMessage } from 'src/commons/utils/notifications/NotificationsHelper'; import { register as registerServiceWorker } from 'src/commons/utils/RegisterServiceWorker'; @@ -19,7 +26,17 @@ if (Constants.sentryDsn) { Sentry.init({ dsn: Constants.sentryDsn, environment: Constants.sourceAcademyEnvironment, - release: `cadet-frontend@${Constants.sourceAcademyVersion}` + release: `cadet-frontend@${Constants.sourceAcademyVersion}`, + integrations: [ + Sentry.reactRouterV7BrowserTracingIntegration({ + useEffect, + useLocation, + useNavigationType, + createRoutesFromChildren, + matchRoutes + }), + Sentry.replayIntegration() + ] }); const userId = store.getState().session.userId; Sentry.setUser(typeof userId !== 'undefined' ? { id: userId.toString() } : null); diff --git a/src/pages/achievement/Achievement.tsx b/src/pages/achievement/Achievement.tsx index 3ef062863d..9e12bbae21 100644 --- a/src/pages/achievement/Achievement.tsx +++ b/src/pages/achievement/Achievement.tsx @@ -1,6 +1,7 @@ import React from 'react'; -import { Route, Routes } from 'react-router'; +import { Route } from 'react-router'; import { useTypedSelector } from 'src/commons/utils/Hooks'; +import { SentryRoutes } from 'src/routes/routerConfig'; import { Role } from '../../commons/application/ApplicationTypes'; import NotFound from '../notFound/NotFound'; @@ -14,11 +15,11 @@ const Achievement: React.FC = () => { role === Role.Admin || role === Role.Staff ? : ; return ( - + }> } /> - + ); }; diff --git a/src/pages/leaderboard/Leaderboard.tsx b/src/pages/leaderboard/Leaderboard.tsx index 07331e39e7..435790fb9c 100644 --- a/src/pages/leaderboard/Leaderboard.tsx +++ b/src/pages/leaderboard/Leaderboard.tsx @@ -1,6 +1,7 @@ import React from 'react'; -import { Navigate, Route, Routes } from 'react-router'; +import { Navigate, Route } from 'react-router'; import { useTypedSelector } from 'src/commons/utils/Hooks'; +import { SentryRoutes } from 'src/routes/routerConfig'; import NotFound from '../notFound/NotFound'; import OverallLeaderboardWrapper from './subcomponents/OverallLeaderboardWrapper'; @@ -22,7 +23,7 @@ const Leaderboard: React.FC = () => { const baseLink = `/courses/${courseId}/leaderboard`; return ( - + { ) } > - + ); }; diff --git a/src/pages/leaderboard/subcomponents/ContestLeaderboardWrapper.tsx b/src/pages/leaderboard/subcomponents/ContestLeaderboardWrapper.tsx index be83693703..599c06d4ff 100644 --- a/src/pages/leaderboard/subcomponents/ContestLeaderboardWrapper.tsx +++ b/src/pages/leaderboard/subcomponents/ContestLeaderboardWrapper.tsx @@ -1,9 +1,10 @@ import React, { useEffect } from 'react'; import { useDispatch } from 'react-redux'; -import { Navigate, Route, Routes, useLocation, useParams } from 'react-router'; +import { Navigate, Route, useLocation, useParams } from 'react-router'; import { useTypedSelector } from 'src/commons/utils/Hooks'; import LeaderboardActions from 'src/features/leaderboard/LeaderboardActions'; -import { LeaderboardContestDetails } from 'src/features/leaderboard/LeaderboardTypes'; +import type { LeaderboardContestDetails } from 'src/features/leaderboard/LeaderboardTypes'; +import { SentryRoutes } from 'src/routes/routerConfig'; import NotFound from '../../notFound/NotFound'; import ContestLeaderboard from './ContestLeaderboard'; @@ -28,7 +29,7 @@ const ContestLeaderboardWrapper: React.FC = () => { const baseLink = `/courses/${courseId}/leaderboard`; return ( - + { > }> - + ); }; diff --git a/src/routes/routerConfig.tsx b/src/routes/routerConfig.tsx index 97582096ff..c99236a5cc 100644 --- a/src/routes/routerConfig.tsx +++ b/src/routes/routerConfig.tsx @@ -1,4 +1,5 @@ -import { Navigate, redirect, RouteObject } from 'react-router'; +import * as Sentry from '@sentry/react'; +import { Navigate, redirect, Routes, type RouteObject } from 'react-router'; import Constants from 'src/commons/utils/Constants'; import Application from '../commons/application/Application'; @@ -150,3 +151,5 @@ export const getFullAcademyRouterConfig = ({ } ]; }; + +export const SentryRoutes = Sentry.withSentryReactRouterV7Routing(Routes); From 43967ee0dd4643c09ddcd2fb472920ce41f851f8 Mon Sep 17 00:00:00 2001 From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com> Date: Sat, 16 Aug 2025 23:45:01 +0800 Subject: [PATCH 6/8] Add TODO --- src/pages/createStore.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/createStore.ts b/src/pages/createStore.ts index 861cdd543e..19cbf443ba 100644 --- a/src/pages/createStore.ts +++ b/src/pages/createStore.ts @@ -29,6 +29,7 @@ export function createStore() { // We already provide the generic type argument, so we put // `as any` to prevent excessively long type inference preloadedState: initialStore as any + // TODO: Sentry Redux integration once we update to RTK2 }); sagaMiddleware.run(MainSaga); From 8c21e5db3745cf1c8b3be59b584fee7eeb933814 Mon Sep 17 00:00:00 2001 From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com> Date: Sat, 16 Aug 2025 23:53:36 +0800 Subject: [PATCH 7/8] Fix lint --- src/routes/routerConfig.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/routerConfig.tsx b/src/routes/routerConfig.tsx index c99236a5cc..75d90961a7 100644 --- a/src/routes/routerConfig.tsx +++ b/src/routes/routerConfig.tsx @@ -1,5 +1,5 @@ import * as Sentry from '@sentry/react'; -import { Navigate, redirect, Routes, type RouteObject } from 'react-router'; +import { Navigate, redirect, type RouteObject, Routes } from 'react-router'; import Constants from 'src/commons/utils/Constants'; import Application from '../commons/application/Application'; From 4c74d3c997d74257616bad84be82f79f871dd836 Mon Sep 17 00:00:00 2001 From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com> Date: Sat, 16 Aug 2025 23:58:46 +0800 Subject: [PATCH 8/8] Fix tests --- src/commons/application/__tests__/Application.test.tsx | 3 ++- .../subcomponents/__tests__/AcademyNavigationBar.test.tsx | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/commons/application/__tests__/Application.test.tsx b/src/commons/application/__tests__/Application.test.tsx index 1ab602fa3f..9de2e4b7dd 100644 --- a/src/commons/application/__tests__/Application.test.tsx +++ b/src/commons/application/__tests__/Application.test.tsx @@ -4,7 +4,8 @@ import { Mock, vi } from 'vitest'; import Application from '../Application'; -vi.mock('react-redux', () => ({ +vi.mock('react-redux', async importOriginal => ({ + ...(await importOriginal()), useDispatch: vi.fn(), useSelector: vi.fn() })); diff --git a/src/commons/navigationBar/subcomponents/__tests__/AcademyNavigationBar.test.tsx b/src/commons/navigationBar/subcomponents/__tests__/AcademyNavigationBar.test.tsx index 443cae23ad..23f2c0e5d1 100644 --- a/src/commons/navigationBar/subcomponents/__tests__/AcademyNavigationBar.test.tsx +++ b/src/commons/navigationBar/subcomponents/__tests__/AcademyNavigationBar.test.tsx @@ -5,7 +5,8 @@ import { Mock, vi } from 'vitest'; import { Role } from '../../../application/ApplicationTypes'; import AcademyNavigationBar from '../AcademyNavigationBar'; -vi.mock('react-redux', () => ({ +vi.mock('react-redux', async importOriginal => ({ + ...(await importOriginal()), useSelector: vi.fn() })); const useSelectorMock = useTypedSelector as Mock;