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 73358accb..eaefe6529 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 9d03e9470..000000000 --- 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 928e10eb9..000000000 --- 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 000000000..30c038ec7 --- /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 f020b70e5..175a5655f 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 065834454..abe015395 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 8d13e3151..8516a13dd 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 000000000..e35e135c3 --- /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 fffbec97e..e9c534f1a 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 7edfdcf75..2a424474d 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 5cbc552b4..b46ebf5ff 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 7ea01811f..28b005ff3 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 f7a7854ee..57c623551 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 4eea468a9..03a9fe498 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 a36cec33e..382e7eab1 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 3920be896..4703d544d 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 bb22d4e8f..f272a61cf 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 1c1b0d3af..3d798453b 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 35cc832e2..8950115ec 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 33cb6854b..062e5cac5 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 bee81a6e5..56a7d6481 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 5868c9d8c..de0c0b240 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 6d1438b04..8339e7492 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 8d1a4eadf..22209a6c1 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 605a24317..584a62a41 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 f9c859647..fc00aa612 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 0ba14845f..144b09371 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 c18267975..7fecf63ea 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 169048703..a992b5ce1 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 000000000..a97fc3356 --- /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 d3c98867f..c376791c9 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 6b573523f..000000000 --- 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 099a2ef12..0c970386d 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 9511ab995..b90f74c20 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 0d2de0d36..ba73d1b03 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"