From 5eaabcf74d558990f1c3cc53a1f75d77a457b6f1 Mon Sep 17 00:00:00 2001 From: Robin Date: Tue, 27 Aug 2024 09:45:39 -0400 Subject: [PATCH] Clean up our tests in preparation for the testing sprint (#2466) * Fix coverage reporting Codecov hasn't been working recently because Vitest doesn't report coverage by default. * Suppress some noisy log lines Closes https://github.com/element-hq/element-call/issues/686 * Store test files alongside source files This way we benefit from not having to maintain the same directory structure twice, and our linters etc. will actually lint test files by default. * Stop using Vitest globals Vitest provides globals primarily to make the transition from Jest more smooth. But importing its functions explicitly is considered a better pattern, and we have so few tests right now that it's trivial to migrate them all. * Remove Storybook directory We no longer use Storybook. * Configure Codecov Add a coverage gate for all new changes and disable its comments. * upgrade vitest --------- Co-authored-by: Timo --- .github/workflows/test.yaml | 3 +- .storybook/main.js | 25 -- .storybook/preview.jsx | 24 -- codecov.yaml | 13 + package.json | 6 +- src/Avatar.tsx | 2 +- src/ClientContext.tsx | 2 +- src/Toast.test.tsx | 55 ++++ src/Toast.tsx | 2 +- .../UrlParams.test.ts | 11 +- .../__snapshots__/Toast-test.tsx.snap | 1 - src/__snapshots__/Toast.test.tsx.snap | 21 ++ src/analytics/PosthogAnalytics.ts | 2 +- src/auth/useInteractiveLogin.ts | 2 +- src/auth/useInteractiveRegistration.ts | 2 +- src/auth/useRecaptcha.ts | 4 +- src/config/Config.ts | 12 + .../home/CallList.test.tsx | 15 +- src/home/CallList.tsx | 2 +- src/home/RegisteredView.tsx | 2 +- src/home/UnauthenticatedView.tsx | 2 +- .../initializer.test.ts | 2 + .../otel/ObjectFlattener.test.ts | 18 ++ src/room/AppSelectionModal.tsx | 2 +- src/room/GroupCallView.tsx | 2 +- src/room/InviteModal.tsx | 2 +- .../room/checkForParallelCalls.test.ts | 9 +- .../rtcSessionHelper.test.ts | 1 + src/state/CallViewModel.ts | 2 +- .../useCallViewKeyboardShortcuts.test.tsx | 2 +- src/{array-utils.ts => utils/array.ts} | 0 src/{matrix-utils.ts => utils/matrix.ts} | 10 +- src/{media-utils.ts => utils/media.ts} | 0 .../observable.ts} | 0 test/utils.ts => src/utils/test.ts | 0 src/vitest.setup.ts | 39 +++ src/widget.ts | 3 +- test/Toast-test.tsx | 60 ---- tsconfig.json | 5 +- vitest.config.js | 8 +- yarn.lock | 277 +++++++++++++++++- 41 files changed, 470 insertions(+), 180 deletions(-) delete mode 100644 .storybook/main.js delete mode 100644 .storybook/preview.jsx create mode 100644 codecov.yaml create mode 100644 src/Toast.test.tsx rename test/UrlParams-test.ts => src/UrlParams.test.ts (91%) rename {test => src}/__snapshots__/Toast-test.tsx.snap (92%) create mode 100644 src/__snapshots__/Toast.test.tsx.snap rename test/home/CallList-test.tsx => src/home/CallList.test.tsx (85%) rename test/initializer-test.ts => src/initializer.test.ts (96%) rename test/otel/ObjectFlattener-test.ts => src/otel/ObjectFlattener.test.ts (94%) rename test/room/checkForParallelCalls-test.ts => src/room/checkForParallelCalls.test.ts (96%) rename test/rtcSessionHelper-test.ts => src/rtcSessionHelper.test.ts (98%) rename test/useCallViewKeyboardShortcuts-test.tsx => src/useCallViewKeyboardShortcuts.test.tsx (98%) rename src/{array-utils.ts => utils/array.ts} (100%) rename src/{matrix-utils.ts => utils/matrix.ts} (97%) rename src/{media-utils.ts => utils/media.ts} (100%) rename src/{observable-utils.ts => utils/observable.ts} (100%) rename test/utils.ts => src/utils/test.ts (100%) create mode 100644 src/vitest.setup.ts delete mode 100644 test/Toast-test.tsx diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 73358acc..eaefe652 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -18,8 +18,9 @@ jobs: - name: Install dependencies run: "yarn install" - name: Vitest - run: "yarn run test" + run: "yarn run test:coverage" - name: Upload to codecov uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4 with: flags: unittests + fail_ci_if_error: true diff --git a/.storybook/main.js b/.storybook/main.js deleted file mode 100644 index 9d03e947..00000000 --- a/.storybook/main.js +++ /dev/null @@ -1,25 +0,0 @@ -const svgrPlugin = require("vite-plugin-svgr"); -const path = require("path"); - -module.exports = { - stories: ["../src/**/*.stories.@(js|jsx|ts|tsx)"], - framework: "@storybook/react", - core: { - builder: "storybook-builder-vite", - }, - async viteFinal(config) { - config.plugins = config.plugins.filter( - (item) => - !( - Array.isArray(item) && - item.length > 0 && - item[0].name === "vite-plugin-mdx" - ), - ); - config.plugins.push(svgrPlugin()); - config.resolve = config.resolve || {}; - config.resolve.dedupe = config.resolve.dedupe || []; - config.resolve.dedupe.push("react", "react-dom", "matrix-js-sdk"); - return config; - }, -}; diff --git a/.storybook/preview.jsx b/.storybook/preview.jsx deleted file mode 100644 index 928e10eb..00000000 --- a/.storybook/preview.jsx +++ /dev/null @@ -1,24 +0,0 @@ -import { addDecorator } from "@storybook/react"; -import { MemoryRouter } from "react-router-dom"; -import { usePageFocusStyle } from "../src/usePageFocusStyle"; -import { OverlayProvider } from "@react-aria/overlays"; -import "../src/index.css"; - -export const parameters = { - actions: { argTypesRegex: "^on[A-Z].*" }, - controls: { - matchers: { - color: /(background|color)$/i, - date: /Date$/, - }, - }, -}; - -addDecorator((story) => { - usePageFocusStyle(); - return ( - - {story()} - - ); -}); diff --git a/codecov.yaml b/codecov.yaml new file mode 100644 index 00000000..30c038ec --- /dev/null +++ b/codecov.yaml @@ -0,0 +1,13 @@ +# Don't post comments on PRs; they're noisy and the same information can be +# gotten through the checks section at the bottom of the PR anyways +comment: false +coverage: + status: + project: + default: + # Track the impact of changes on overall coverage without blocking PRs + informational: true + patch: + default: + # Expect 80% coverage on all lines that a PR touches + target: 80% diff --git a/package.json b/package.json index f020b70e..175a5655 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "i18n": "node_modules/i18next-parser/bin/cli.js", "i18n:check": "node_modules/i18next-parser/bin/cli.js --fail-on-warnings --fail-on-update", "test": "vitest", - "test:coverage": "vitest run --coverage", + "test:coverage": "vitest --coverage", "backend": "docker-compose -f backend-docker-compose.yml up" }, "dependencies": { @@ -95,7 +95,7 @@ "@types/content-type": "^1.1.5", "@types/dom-screen-wake-lock": "^1.0.1", "@types/dompurify": "^3.0.2", - "@types/grecaptcha": "^3.0.4", + "@types/grecaptcha": "^3.0.9", "@types/node": "^20.0.0", "@types/react-dom": "^18.3.0", "@types/react-router-dom": "^5.3.3", @@ -104,6 +104,7 @@ "@types/uuid": "10", "@typescript-eslint/eslint-plugin": "^7.0.0", "@typescript-eslint/parser": "^7.0.0", + "@vitest/coverage-v8": "^2.0.5", "babel-loader": "^9.0.0", "babel-plugin-transform-vite-meta-env": "^1.0.3", "eslint": "^8.14.0", @@ -116,6 +117,7 @@ "eslint-plugin-react": "^7.29.4", "eslint-plugin-react-hooks": "^4.5.0", "eslint-plugin-unicorn": "^55.0.0", + "global-jsdom": "^24.0.0", "i18next-parser": "^9.0.0", "jsdom": "^25.0.0", "prettier": "^3.0.0", diff --git a/src/Avatar.tsx b/src/Avatar.tsx index 06583445..abe01539 100644 --- a/src/Avatar.tsx +++ b/src/Avatar.tsx @@ -17,7 +17,7 @@ limitations under the License. import { useMemo, FC } from "react"; import { Avatar as CompoundAvatar } from "@vector-im/compound-web"; -import { getAvatarUrl } from "./matrix-utils"; +import { getAvatarUrl } from "./utils/matrix"; import { useClient } from "./ClientContext"; export enum Size { diff --git a/src/ClientContext.tsx b/src/ClientContext.tsx index 8d13e315..8516a13d 100644 --- a/src/ClientContext.tsx +++ b/src/ClientContext.tsx @@ -39,7 +39,7 @@ import { CryptoStoreIntegrityError, fallbackICEServerAllowed, initClient, -} from "./matrix-utils"; +} from "./utils/matrix"; import { widget } from "./widget"; import { PosthogAnalytics, diff --git a/src/Toast.test.tsx b/src/Toast.test.tsx new file mode 100644 index 00000000..e35e135c --- /dev/null +++ b/src/Toast.test.tsx @@ -0,0 +1,55 @@ +/* +Copyright 2023 New Vector Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { describe, expect, test, vi } from "vitest"; +import { render, configure } from "@testing-library/react"; + +import { Toast } from "../src/Toast"; +import { withFakeTimers } from "./utils/test"; + +configure({ + defaultHidden: true, +}); + +describe("Toast", () => { + test("renders", () => { + const { queryByRole } = render( + {}}> + Hello world! + , + ); + expect(queryByRole("dialog")).toBe(null); + const { getByRole } = render( + {}}> + Hello world! + , + ); + expect(getByRole("dialog")).toMatchSnapshot(); + }); + + test("dismisses itself after the specified timeout", () => { + withFakeTimers(() => { + const onDismiss = vi.fn(); + render( + + Hello world! + , + ); + vi.advanceTimersByTime(2000); + expect(onDismiss).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/Toast.tsx b/src/Toast.tsx index fffbec97..e9c534f1 100644 --- a/src/Toast.tsx +++ b/src/Toast.tsx @@ -86,7 +86,7 @@ export const Toast: FC = ({ - + { - beforeAll(() => { - vi.mocked(Config.defaultServerName).mockReturnValue("call.ems.host"); - }); - describe("handles URL with /room/", () => { it("and nothing else", () => { expect( diff --git a/test/__snapshots__/Toast-test.tsx.snap b/src/__snapshots__/Toast-test.tsx.snap similarity index 92% rename from test/__snapshots__/Toast-test.tsx.snap rename to src/__snapshots__/Toast-test.tsx.snap index 7edfdcf7..2a424474 100644 --- a/test/__snapshots__/Toast-test.tsx.snap +++ b/src/__snapshots__/Toast-test.tsx.snap @@ -2,7 +2,6 @@ exports[`Toast renders 1`] = ` +`; diff --git a/src/analytics/PosthogAnalytics.ts b/src/analytics/PosthogAnalytics.ts index 5cbc552b..b46ebf5f 100644 --- a/src/analytics/PosthogAnalytics.ts +++ b/src/analytics/PosthogAnalytics.ts @@ -144,7 +144,7 @@ export class PosthogAnalytics { advanced_disable_decide: true, }); this.enabled = true; - } else { + } else if (import.meta.env.MODE !== "test") { logger.info( "Posthog is not enabled because there is no api key or no host given in the config", ); diff --git a/src/auth/useInteractiveLogin.ts b/src/auth/useInteractiveLogin.ts index 7ea01811..28b005ff 100644 --- a/src/auth/useInteractiveLogin.ts +++ b/src/auth/useInteractiveLogin.ts @@ -22,7 +22,7 @@ import { MatrixClient, } from "matrix-js-sdk/src/matrix"; -import { initClient } from "../matrix-utils"; +import { initClient } from "../utils/matrix"; import { Session } from "../ClientContext"; export function useInteractiveLogin(): ( diff --git a/src/auth/useInteractiveRegistration.ts b/src/auth/useInteractiveRegistration.ts index f7a7854e..57c62355 100644 --- a/src/auth/useInteractiveRegistration.ts +++ b/src/auth/useInteractiveRegistration.ts @@ -22,7 +22,7 @@ import { RegisterResponse, } from "matrix-js-sdk/src/matrix"; -import { initClient } from "../matrix-utils"; +import { initClient } from "../utils/matrix"; import { Session } from "../ClientContext"; import { Config } from "../config/Config"; import { widget } from "../widget"; diff --git a/src/auth/useRecaptcha.ts b/src/auth/useRecaptcha.ts index 4eea468a..03a9fe49 100644 --- a/src/auth/useRecaptcha.ts +++ b/src/auth/useRecaptcha.ts @@ -13,17 +13,17 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ - +// import "@types/grecaptcha"; import { useEffect, useCallback, useRef, useState } from "react"; import { randomString } from "matrix-js-sdk/src/randomstring"; import { useTranslation } from "react-i18next"; import { logger } from "matrix-js-sdk/src/logger"; import { translatedError } from "../TranslatedError"; - declare global { interface Window { mxOnRecaptchaLoaded: () => void; + // grecaptcha: any; } } diff --git a/src/config/Config.ts b/src/config/Config.ts index a36cec33..382e7eab 100644 --- a/src/config/Config.ts +++ b/src/config/Config.ts @@ -44,6 +44,18 @@ export class Config { return Config.internalInstance.initPromise; } + /** + * This is a alternative initializer that does not load anything + * from a hosted config file but instead just initializes the conifg using the + * default config. + * + * It is supposed to only be used in tests. (It is executed in `vite.setup.js`) + */ + public static initDefault(): void { + Config.internalInstance = new Config(); + Config.internalInstance.config = { ...DEFAULT_CONFIG }; + } + // Convenience accessors public static defaultHomeserverUrl(): string | undefined { return ( diff --git a/test/home/CallList-test.tsx b/src/home/CallList.test.tsx similarity index 85% rename from test/home/CallList-test.tsx rename to src/home/CallList.test.tsx index 3920be89..4703d544 100644 --- a/test/home/CallList-test.tsx +++ b/src/home/CallList.test.tsx @@ -15,20 +15,19 @@ limitations under the License. */ import { render, RenderResult } from "@testing-library/react"; -import { CallList } from "../../src/home/CallList"; import { MatrixClient } from "matrix-js-sdk"; -import { GroupCallRoom } from "../../src/home/useGroupCallRooms"; import { MemoryRouter } from "react-router-dom"; -import { ClientProvider } from "../../src/ClientContext"; +import { describe, expect, it } from "vitest"; + +import { CallList } from "../../src/home/CallList"; +import { GroupCallRoom } from "../../src/home/useGroupCallRooms"; describe("CallList", () => { const renderComponent = (rooms: GroupCallRoom[]): RenderResult => { return render( - - - - - , + + + , ); }; diff --git a/src/home/CallList.tsx b/src/home/CallList.tsx index bb22d4e8..f272a61c 100644 --- a/src/home/CallList.tsx +++ b/src/home/CallList.tsx @@ -23,7 +23,7 @@ import { FC } from "react"; import { CopyButton } from "../button"; import { Avatar, Size } from "../Avatar"; import styles from "./CallList.module.css"; -import { getAbsoluteRoomUrl, getRelativeRoomUrl } from "../matrix-utils"; +import { getAbsoluteRoomUrl, getRelativeRoomUrl } from "../utils/matrix"; import { Body } from "../typography/Typography"; import { GroupCallRoom } from "./useGroupCallRooms"; import { useRoomEncryptionSystem } from "../e2ee/sharedKeyManagement"; diff --git a/src/home/RegisteredView.tsx b/src/home/RegisteredView.tsx index 1c1b0d3a..3d798453 100644 --- a/src/home/RegisteredView.tsx +++ b/src/home/RegisteredView.tsx @@ -26,7 +26,7 @@ import { getRelativeRoomUrl, roomAliasLocalpartFromRoomName, sanitiseRoomNameInput, -} from "../matrix-utils"; +} from "../utils/matrix"; import { useGroupCallRooms } from "./useGroupCallRooms"; import { Header, HeaderLogo, LeftNav, RightNav } from "../Header"; import commonStyles from "./common.module.css"; diff --git a/src/home/UnauthenticatedView.tsx b/src/home/UnauthenticatedView.tsx index 35cc832e..8950115e 100644 --- a/src/home/UnauthenticatedView.tsx +++ b/src/home/UnauthenticatedView.tsx @@ -31,7 +31,7 @@ import { getRelativeRoomUrl, roomAliasLocalpartFromRoomName, sanitiseRoomNameInput, -} from "../matrix-utils"; +} from "../utils/matrix"; import { useInteractiveRegistration } from "../auth/useInteractiveRegistration"; import { JoinExistingCallModal } from "./JoinExistingCallModal"; import { useRecaptcha } from "../auth/useRecaptcha"; diff --git a/test/initializer-test.ts b/src/initializer.test.ts similarity index 96% rename from test/initializer-test.ts rename to src/initializer.test.ts index 33cb6854..062e5cac 100644 --- a/test/initializer-test.ts +++ b/src/initializer.test.ts @@ -14,6 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ +import { expect, test } from "vitest"; + import { Initializer } from "../src/initializer"; test("initBeforeReact sets font family from URL param", () => { diff --git a/test/otel/ObjectFlattener-test.ts b/src/otel/ObjectFlattener.test.ts similarity index 94% rename from test/otel/ObjectFlattener-test.ts rename to src/otel/ObjectFlattener.test.ts index bee81a6e..56a7d648 100644 --- a/test/otel/ObjectFlattener-test.ts +++ b/src/otel/ObjectFlattener.test.ts @@ -1,9 +1,27 @@ +/* +Copyright 2024 New Vector Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + import { GroupCallStatsReport } from "matrix-js-sdk/src/webrtc/groupCall"; import { AudioConcealment, ByteSentStatsReport, ConnectionStatsReport, } from "matrix-js-sdk/src/webrtc/stats/statsReport"; +import { describe, expect, it } from "vitest"; + import { ObjectFlattener } from "../../src/otel/ObjectFlattener"; /* diff --git a/src/room/AppSelectionModal.tsx b/src/room/AppSelectionModal.tsx index 5868c9d8..de0c0b24 100644 --- a/src/room/AppSelectionModal.tsx +++ b/src/room/AppSelectionModal.tsx @@ -22,7 +22,7 @@ import { logger } from "matrix-js-sdk/src/logger"; import { Modal } from "../Modal"; import { useRoomEncryptionSystem } from "../e2ee/sharedKeyManagement"; -import { getAbsoluteRoomUrl } from "../matrix-utils"; +import { getAbsoluteRoomUrl } from "../utils/matrix"; import styles from "./AppSelectionModal.module.css"; import { editFragmentQuery } from "../UrlParams"; import { E2eeType } from "../e2ee/e2eeType"; diff --git a/src/room/GroupCallView.tsx b/src/room/GroupCallView.tsx index 6d1438b0..8339e749 100644 --- a/src/room/GroupCallView.tsx +++ b/src/room/GroupCallView.tsx @@ -35,7 +35,7 @@ import { MatrixInfo } from "./VideoPreview"; import { CallEndedView } from "./CallEndedView"; import { PosthogAnalytics } from "../analytics/PosthogAnalytics"; import { useProfile } from "../profile/useProfile"; -import { findDeviceByName } from "../media-utils"; +import { findDeviceByName } from "../utils/media"; import { ActiveCall } from "./InCallView"; import { MUTE_PARTICIPANT_COUNT, MuteStates } from "./MuteStates"; import { useMediaDevices, MediaDevices } from "../livekit/MediaDevicesContext"; diff --git a/src/room/InviteModal.tsx b/src/room/InviteModal.tsx index 8d1a4ead..22209a6c 100644 --- a/src/room/InviteModal.tsx +++ b/src/room/InviteModal.tsx @@ -25,7 +25,7 @@ import { import useClipboard from "react-use-clipboard"; import { Modal } from "../Modal"; -import { getAbsoluteRoomUrl } from "../matrix-utils"; +import { getAbsoluteRoomUrl } from "../utils/matrix"; import styles from "./InviteModal.module.css"; import { Toast } from "../Toast"; import { useRoomEncryptionSystem } from "../e2ee/sharedKeyManagement"; diff --git a/test/room/checkForParallelCalls-test.ts b/src/room/checkForParallelCalls.test.ts similarity index 96% rename from test/room/checkForParallelCalls-test.ts rename to src/room/checkForParallelCalls.test.ts index 605a2431..584a62a4 100644 --- a/test/room/checkForParallelCalls-test.ts +++ b/src/room/checkForParallelCalls.test.ts @@ -14,15 +14,16 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { vi, Mocked } from "vitest"; +import { vi, Mocked, test, expect } from "vitest"; import { RoomState } from "matrix-js-sdk/src/models/room-state"; + import { PosthogAnalytics } from "../../src/analytics/PosthogAnalytics"; import { checkForParallelCalls } from "../../src/room/checkForParallelCalls"; -import { withFakeTimers } from "../utils"; +import { withFakeTimers } from "../utils/test"; const withMockedPosthog = ( continuation: (posthog: Mocked) => void, -) => { +): void => { const posthog = vi.mocked({ trackEvent: vi.fn(), } as unknown as PosthogAnalytics); @@ -40,7 +41,7 @@ const mockRoomState = ( groupCallMemberContents: Record[], ): RoomState => { const stateEvents = groupCallMemberContents.map((content) => ({ - getContent: () => content, + getContent: (): Record => content, })); return { getStateEvents: () => stateEvents } as unknown as RoomState; }; diff --git a/test/rtcSessionHelper-test.ts b/src/rtcSessionHelper.test.ts similarity index 98% rename from test/rtcSessionHelper-test.ts rename to src/rtcSessionHelper.test.ts index f9c85964..fc00aa61 100644 --- a/test/rtcSessionHelper-test.ts +++ b/src/rtcSessionHelper.test.ts @@ -15,6 +15,7 @@ limitations under the License. */ import { MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession"; +import { expect, test, vi } from "vitest"; import { enterRTCSession } from "../src/rtcSessionHelpers"; import { Config } from "../src/config/Config"; diff --git a/src/state/CallViewModel.ts b/src/state/CallViewModel.ts index 0ba14845..144b0937 100644 --- a/src/state/CallViewModel.ts +++ b/src/state/CallViewModel.ts @@ -67,7 +67,7 @@ import { ScreenShareViewModel, UserMediaViewModel, } from "./MediaViewModel"; -import { accumulate, finalizeValue } from "../observable-utils"; +import { accumulate, finalizeValue } from "../utils/observable"; import { ObservableScope } from "./ObservableScope"; import { duplicateTiles } from "../settings/settings"; import { isFirefox } from "../Platform"; diff --git a/test/useCallViewKeyboardShortcuts-test.tsx b/src/useCallViewKeyboardShortcuts.test.tsx similarity index 98% rename from test/useCallViewKeyboardShortcuts-test.tsx rename to src/useCallViewKeyboardShortcuts.test.tsx index c1826797..7fecf63e 100644 --- a/test/useCallViewKeyboardShortcuts-test.tsx +++ b/src/useCallViewKeyboardShortcuts.test.tsx @@ -16,7 +16,7 @@ limitations under the License. import { render } from "@testing-library/react"; import { FC, useRef } from "react"; -import { test } from "vitest"; +import { expect, test, vi } from "vitest"; import { Button } from "@vector-im/compound-web"; import userEvent from "@testing-library/user-event"; diff --git a/src/array-utils.ts b/src/utils/array.ts similarity index 100% rename from src/array-utils.ts rename to src/utils/array.ts diff --git a/src/matrix-utils.ts b/src/utils/matrix.ts similarity index 97% rename from src/matrix-utils.ts rename to src/utils/matrix.ts index 16904870..a992b5ce 100644 --- a/src/matrix-utils.ts +++ b/src/utils/matrix.ts @@ -32,11 +32,11 @@ import { secureRandomBase64Url } from "matrix-js-sdk/src/randomstring"; import type { MatrixClient } from "matrix-js-sdk/src/client"; import type { Room } from "matrix-js-sdk/src/models/room"; -import IndexedDBWorker from "./IndexedDBWorker?worker"; -import { generateUrlSearchParams, getUrlParams } from "./UrlParams"; -import { Config } from "./config/Config"; -import { E2eeType } from "./e2ee/e2eeType"; -import { EncryptionSystem, saveKeyForRoom } from "./e2ee/sharedKeyManagement"; +import IndexedDBWorker from "../IndexedDBWorker?worker"; +import { generateUrlSearchParams, getUrlParams } from "../UrlParams"; +import { Config } from "../config/Config"; +import { E2eeType } from "../e2ee/e2eeType"; +import { EncryptionSystem, saveKeyForRoom } from "../e2ee/sharedKeyManagement"; export const fallbackICEServerAllowed = import.meta.env.VITE_FALLBACK_STUN_ALLOWED === "true"; diff --git a/src/media-utils.ts b/src/utils/media.ts similarity index 100% rename from src/media-utils.ts rename to src/utils/media.ts diff --git a/src/observable-utils.ts b/src/utils/observable.ts similarity index 100% rename from src/observable-utils.ts rename to src/utils/observable.ts diff --git a/test/utils.ts b/src/utils/test.ts similarity index 100% rename from test/utils.ts rename to src/utils/test.ts diff --git a/src/vitest.setup.ts b/src/vitest.setup.ts new file mode 100644 index 00000000..a97fc335 --- /dev/null +++ b/src/vitest.setup.ts @@ -0,0 +1,39 @@ +/* +Copyright 2024 New Vector Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import "global-jsdom/register"; + +import i18n from "i18next"; +import posthog from "posthog-js"; +import { initReactI18next } from "react-i18next"; +import { afterEach } from "vitest"; +import { cleanup } from "@testing-library/react"; + +import { Config } from "./config/Config"; + +// Bare-minimum i18n config +i18n.use(initReactI18next).init({ + lng: "en-GB", + fallbackLng: "en-GB", + interpolation: { + escapeValue: false, // React has built-in XSS protections + }, +}); + +Config.initDefault(); +posthog.opt_out_capturing(); + +afterEach(cleanup); diff --git a/src/widget.ts b/src/widget.ts index d3c98867..c376791c 100644 --- a/src/widget.ts +++ b/src/widget.ts @@ -200,7 +200,8 @@ export const widget = ((): WidgetHelpers | null => { return { api, lazyActions, client: clientPromise }; } else { - logger.info("No widget API available"); + if (import.meta.env.MODE !== "test") + logger.info("No widget API available"); return null; } } catch (e) { diff --git a/test/Toast-test.tsx b/test/Toast-test.tsx deleted file mode 100644 index 6b573523..00000000 --- a/test/Toast-test.tsx +++ /dev/null @@ -1,60 +0,0 @@ -/* -Copyright 2023 New Vector Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -import { vi } from "vitest"; -import { screen, render } from "@testing-library/react"; -import { Toast } from "../src/Toast"; -import userEvent from "@testing-library/user-event"; -import { withFakeTimers } from "./utils"; - -test("Toast renders", () => { - render( - {}}> - Hello world! - , - ); - expect(screen.queryByRole("dialog")).toBe(null); - render( - {}}> - Hello world! - , - ); - expect(screen.getByRole("dialog")).toMatchSnapshot(); -}); - -test("Toast dismisses when clicked", async () => { - const onDismiss = vi.fn(); - render( - - Hello world! - , - ); - await userEvent.click(screen.getByRole("dialog")); - expect(onDismiss).toHaveBeenCalled(); -}); - -test("Toast dismisses itself after the specified timeout", async () => { - withFakeTimers(() => { - const onDismiss = vi.fn(); - render( - - Hello world! - , - ); - vi.advanceTimersByTime(2000); - expect(onDismiss).toHaveBeenCalled(); - }); -}); diff --git a/tsconfig.json b/tsconfig.json index 099a2ef1..0c970386 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -48,10 +48,7 @@ }, "include": [ "./node_modules/matrix-js-sdk/src/@types/*.d.ts", - "./node_modules/vitest/globals.d.ts", "./src/**/*.ts", - "./src/**/*.tsx", - "./test/**/*.ts", - "./test/**/*.tsx" + "./src/**/*.tsx" ] } diff --git a/vitest.config.js b/vitest.config.js index 9511ab99..b90f74c2 100644 --- a/vitest.config.js +++ b/vitest.config.js @@ -6,17 +6,17 @@ export default defineConfig((configEnv) => viteConfig(configEnv), defineConfig({ test: { - globals: true, environment: "jsdom", css: { modules: { classNameStrategy: "non-scoped", }, }, - include: ["test/**/*-test.[jt]s?(x)"], + isolate: false, + setupFiles: ["src/vitest.setup.ts"], coverage: { - reporter: ["text", "html"], - exclude: ["node_modules/"], + reporter: ["html", "json"], + include: ["src/"], }, }, }), diff --git a/yarn.lock b/yarn.lock index 0d2de0d3..ba73d1b0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -260,13 +260,20 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.7.tgz#9a5226f92f0c5c8ead550b750f5608e766c8ce85" integrity sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw== -"@babel/parser@^7.25.0", "@babel/parser@^7.25.4": +"@babel/parser@^7.24.4", "@babel/parser@^7.25.4": version "7.25.4" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.25.4.tgz#af4f2df7d02440286b7de57b1c21acfb2a6f257a" integrity sha512-nq+eWrOgdtu3jG5Os4TQP3x3cLA8hR8TvJNjD8vnPa20WGycimcparWnLK4jJhElTK6SDyuJo1weMKO/5LpmLA== dependencies: "@babel/types" "^7.25.4" +"@babel/parser@^7.25.0": + version "7.25.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.25.3.tgz#91fb126768d944966263f0657ab222a642b82065" + integrity sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw== + dependencies: + "@babel/types" "^7.25.2" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.25.3": version "7.25.3" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.3.tgz#dca427b45a6c0f5c095a1c639dfe2476a3daba7f" @@ -1101,7 +1108,7 @@ debug "^4.3.1" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.20.7": +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.24.7", "@babel/types@^7.4.4": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.7.tgz#6027fe12bc1aa724cd32ab113fb7f1988f1f66f2" integrity sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q== @@ -1119,7 +1126,7 @@ "@babel/helper-validator-identifier" "^7.22.20" to-fast-properties "^2.0.0" -"@babel/types@^7.24.7", "@babel/types@^7.24.8", "@babel/types@^7.25.0", "@babel/types@^7.25.2", "@babel/types@^7.25.4", "@babel/types@^7.4.4": +"@babel/types@^7.24.0", "@babel/types@^7.25.4": version "7.25.4" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.25.4.tgz#6bcb46c72fdf1012a209d016c07f769e10adcb5f" integrity sha512-zQ1ijeeCXVEh+aNL0RlmkPkG8HUiDcU2pzQQFjtbntgAczRASFzj4H+6+bV+dy1ntKR14I/DypeuRG1uma98iQ== @@ -1128,6 +1135,20 @@ "@babel/helper-validator-identifier" "^7.24.7" to-fast-properties "^2.0.0" +"@babel/types@^7.24.8", "@babel/types@^7.25.0", "@babel/types@^7.25.2": + version "7.25.2" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.25.2.tgz#55fb231f7dc958cd69ea141a4c2997e819646125" + integrity sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q== + dependencies: + "@babel/helper-string-parser" "^7.24.8" + "@babel/helper-validator-identifier" "^7.24.7" + to-fast-properties "^2.0.0" + +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + "@bufbuild/protobuf@^1.7.2": version "1.10.0" resolved "https://registry.yarnpkg.com/@bufbuild/protobuf/-/protobuf-1.10.0.tgz#1a67ac889c2d464a3492b3e54c38f80517963b16" @@ -1845,6 +1866,23 @@ dependencies: "@babel/runtime" "^7.6.2" +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + +"@istanbuljs/schema@^0.1.2": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + "@jridgewell/gen-mapping@^0.3.5": version "0.3.5" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" @@ -1869,7 +1907,7 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== -"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": +"@jridgewell/trace-mapping@^0.3.23", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": version "0.3.25" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== @@ -2127,6 +2165,11 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.24.0.tgz#f074db930a7feb4d64103a9a576c5fbad046fcac" integrity sha512-yL0jI6Ltuz8R+Opj7jClGrul6pOoYrdfVmzQS4SITXRPH7I5IRZbrwe/6/v8v4WYMa6MYZG480S1+uc/IGfqsA== +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" @@ -3411,7 +3454,7 @@ resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.3.tgz#a8ef894305af28d1fc6d2dfdfc98e899591ea529" integrity sha512-trOc4AAUThEz9hapPtSd7wf5tiQKvTtu5b371UxXdTuqzIh0ArcRspRP0i0Viu+LXstIQ1z96t1nsPxT9ol01g== -"@types/grecaptcha@^3.0.4": +"@types/grecaptcha@^3.0.9": version "3.0.9" resolved "https://registry.yarnpkg.com/@types/grecaptcha/-/grecaptcha-3.0.9.tgz#9f3b07ec06c8fff221aa6fc124fe5b8a0e2c3349" integrity sha512-fFxMtjAvXXMYTzDFK5NpcVB7WHnrHVLl00QzEGpuFxSAC789io6M+vjcn+g5FTEamIJtJr/IHkCDsqvJxeWDyw== @@ -3677,6 +3720,24 @@ "@types/babel__core" "^7.20.5" react-refresh "^0.14.2" +"@vitest/coverage-v8@^2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@vitest/coverage-v8/-/coverage-v8-2.0.5.tgz#411961ce4fd1177a32b4dd74ab576ed3b859155e" + integrity sha512-qeFcySCg5FLO2bHHSa0tAZAOnAUbp4L6/A5JDuj9+bt53JREl8hpLjLHEWF0e/gWc8INVpJaqA7+Ene2rclpZg== + dependencies: + "@ampproject/remapping" "^2.3.0" + "@bcoe/v8-coverage" "^0.2.3" + debug "^4.3.5" + istanbul-lib-coverage "^3.2.2" + istanbul-lib-report "^3.0.1" + istanbul-lib-source-maps "^5.0.6" + istanbul-reports "^3.1.7" + magic-string "^0.30.10" + magicast "^0.3.4" + std-env "^3.7.0" + test-exclude "^7.0.1" + tinyrainbow "^1.2.0" + "@vitest/expect@2.0.5": version "2.0.5" resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-2.0.5.tgz#f3745a6a2c18acbea4d39f5935e913f40d26fa86" @@ -3811,6 +3872,11 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-regex@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" + integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== + ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -3818,7 +3884,7 @@ ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -ansi-styles@^4.1.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== @@ -3830,6 +3896,11 @@ ansi-styles@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== +ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + anymatch@^3.1.3, anymatch@~3.1.2: version "3.1.3" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" @@ -4446,7 +4517,7 @@ cross-fetch@4.0.0: dependencies: node-fetch "^2.6.12" -cross-spawn@^7.0.2, cross-spawn@^7.0.3: +cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -4736,11 +4807,21 @@ dotenv@^16.3.1: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + electron-to-chromium@^1.5.4: version "1.5.13" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz#1abf0410c5344b2b829b7247e031f02810d442e6" integrity sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q== +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + emoji-regex@^9.2.2: version "9.2.2" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" @@ -5360,6 +5441,14 @@ for-each@^0.3.3: dependencies: is-callable "^1.1.3" +foreground-child@^3.1.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.0.tgz#0ac8644c06e431439f8561db8ecf29a7b5519c77" + integrity sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^4.0.1" + form-data@^2.5.0: version "2.5.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" @@ -5529,6 +5618,18 @@ glob-stream@^8.0.0: normalize-path "^3.0.0" streamx "^2.12.5" +glob@^10.4.1: + version "10.4.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" + integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== + dependencies: + foreground-child "^3.1.0" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" + glob@^7.0.0, glob@^7.1.3: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" @@ -5551,6 +5652,11 @@ glob@^9.3.2: minipass "^4.2.4" path-scurry "^1.6.1" +global-jsdom@^24.0.0: + version "24.0.0" + resolved "https://registry.yarnpkg.com/global-jsdom/-/global-jsdom-24.0.0.tgz#be2a5f0392a8626fde76c4d8037618c7a0f1079c" + integrity sha512-CARBUWkqZ3O9VOc2PIVE5kQpdQeJh9eF9kQ7zSeNtmqx5vAFDKMr9XnDt1epVMMrz1s9uK/yFCa4HLwpa6TcPA== + globals@^11.1.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" @@ -5714,6 +5820,11 @@ html-encoding-sniffer@^4.0.0: dependencies: whatwg-encoding "^3.1.1" +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + html-parse-stringify@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz#dfc1017347ce9f77c8141a507f233040c59c55d2" @@ -6000,6 +6111,11 @@ is-finalizationregistry@^1.0.2: dependencies: call-bind "^1.0.2" +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + is-generator-function@^1.0.10: version "1.0.10" resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" @@ -6147,6 +6263,37 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" + integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== + +istanbul-lib-report@^3.0.0, istanbul-lib-report@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" + integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^4.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^5.0.6: + version "5.0.6" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz#acaef948df7747c8eb5fbf1265cb980f6353a441" + integrity sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A== + dependencies: + "@jridgewell/trace-mapping" "^0.3.23" + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + +istanbul-reports@^3.1.7: + version "3.1.7" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz#daed12b9e1dca518e15c056e1e537e741280fa0b" + integrity sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + iterator.prototype@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.2.tgz#5e29c8924f01916cb9335f1ff80619dcff22b0c0" @@ -6158,6 +6305,15 @@ iterator.prototype@^1.1.2: reflect.getprototypeof "^1.0.4" set-function-name "^2.0.1" +jackspeak@^3.1.2: + version "3.4.3" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" + integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + jaeger-client@^3.15.0: version "3.19.0" resolved "https://registry.yarnpkg.com/jaeger-client/-/jaeger-client-3.19.0.tgz#9b5bd818ebd24e818616ee0f5cffe1722a53ae6e" @@ -6462,6 +6618,22 @@ magic-string@^0.30.10: dependencies: "@jridgewell/sourcemap-codec" "^1.5.0" +magicast@^0.3.4: + version "0.3.4" + resolved "https://registry.yarnpkg.com/magicast/-/magicast-0.3.4.tgz#bbda1791d03190a24b00ff3dd18151e7fd381d19" + integrity sha512-TyDF/Pn36bBji9rWKHlZe+PZb6Mx5V8IHCSxk7X4aljM4e/vyDvZZYwHewdVaqiA0nb3ghfHU/6AUpDxWoER2Q== + dependencies: + "@babel/parser" "^7.24.4" + "@babel/types" "^7.24.0" + source-map-js "^1.2.0" + +make-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" + integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== + dependencies: + semver "^7.5.3" + matcher-collection@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/matcher-collection/-/matcher-collection-2.0.1.tgz#90be1a4cf58d6f2949864f65bb3b0f3e41303b29" @@ -6574,7 +6746,7 @@ minipass@^4.2.4: resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.2.8.tgz#f0010f64393ecfc1d1ccb5f582bcaf45f48e1a3a" integrity sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ== -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0": +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== @@ -6877,6 +7049,11 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== +package-json-from-dist@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz#e501cd3094b278495eb4258d4c9f6d5ac3019f00" + integrity sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw== + pako@^2.0.4: version "2.1.0" resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86" @@ -6956,7 +7133,7 @@ path-posix@^1.0.0: resolved "https://registry.yarnpkg.com/path-posix/-/path-posix-1.0.0.tgz#06b26113f56beab042545a23bfa88003ccac260f" integrity sha512-1gJ0WpNIiYcQydgg3Ed8KzvIqTsDpNwq+cjBCssvBtuTWjEqY1AW+i+OepiEMqDCzyro9B2sLAe4RBPajMYFiA== -path-scurry@^1.6.1: +path-scurry@^1.11.1, path-scurry@^1.6.1: version "1.11.1" resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== @@ -7908,12 +8085,12 @@ semver@^7.5.2: dependencies: lru-cache "^6.0.0" -semver@^7.6.0: +semver@^7.5.3: version "7.6.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== -semver@^7.6.1: +semver@^7.6.0, semver@^7.6.1: version "7.6.2" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== @@ -7981,7 +8158,7 @@ siginfo@^2.0.0: resolved "https://registry.yarnpkg.com/siginfo/-/siginfo-2.0.0.tgz#32e76c70b79724e3bb567cb9d543eb858ccfaf30" integrity sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g== -signal-exit@^4.1.0: +signal-exit@^4.0.1, signal-exit@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== @@ -8082,6 +8259,33 @@ string-template@~0.2.1: resolved "https://registry.yarnpkg.com/string-template/-/string-template-0.2.1.tgz#42932e598a352d01fc22ec3367d9d84eec6c9add" integrity sha512-Yptehjogou2xm4UJbxJ4CxgZx12HBfeystp0y3x7s4Dj32ltVVG1Gg8YhKjHZkHicuKpZX/ffilA8505VbUbpw== +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + string.prototype.includes@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/string.prototype.includes/-/string.prototype.includes-2.0.0.tgz#8986d57aee66d5460c144620a6d873778ad7289f" @@ -8158,13 +8362,27 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: ansi-regex "^5.0.1" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== + dependencies: + ansi-regex "^6.0.1" + strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" @@ -8233,6 +8451,15 @@ teex@^1.0.1: dependencies: streamx "^2.12.5" +test-exclude@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-7.0.1.tgz#20b3ba4906ac20994e275bbcafd68d510264c2a2" + integrity sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^10.4.1" + minimatch "^9.0.4" + text-decoder@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/text-decoder/-/text-decoder-1.1.1.tgz#5df9c224cebac4a7977720b9f083f9efa1aefde8" @@ -8278,9 +8505,9 @@ tinybench@^2.8.0: integrity sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg== tinypool@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-1.0.0.tgz#a68965218e04f4ad9de037d2a1cd63cda9afb238" - integrity sha512-KIKExllK7jp3uvrNtvRBYBWBOAXSX8ZvoaD8T+7KB/QHIuoJW3Pmr60zucywjAlMb5TeXUkcs/MWeWLu0qvuAQ== + version "1.0.1" + resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-1.0.1.tgz#c64233c4fac4304e109a64340178760116dbe1fe" + integrity sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA== tinyqueue@^3.0.0: version "3.0.0" @@ -8898,6 +9125,24 @@ why-is-node-running@^2.3.0: siginfo "^2.0.0" stackback "0.0.2" +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"