mirror of
https://github.com/vector-im/element-web.git
synced 2026-05-05 12:16:53 +02:00
Update fetch-mock-jest to @fetch-mock/jest (#31720)
* Remove tests which assert feature_oidc_native_flow=false behaviour, that setting is long gone Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Upgrade fetch-mock-jest to @fetch-mock/jest Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update yarn.lock Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Make knip happy Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Disable broken tests Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix shared-components tests Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Snapshots Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
parent
f5c6477ef7
commit
6f0cd7621b
@ -11,7 +11,7 @@ import { env } from "process";
|
||||
import type { Config } from "jest";
|
||||
|
||||
const config: Config = {
|
||||
testEnvironment: "jsdom",
|
||||
testEnvironment: "jest-fixed-jsdom",
|
||||
testEnvironmentOptions: {
|
||||
url: "http://localhost/",
|
||||
// This is needed to be able to load dual CJS/ESM WASM packages e.g. rust crypto & matrix-wywiwyg
|
||||
@ -39,7 +39,6 @@ const config: Config = {
|
||||
"workers/(.+)Factory": "<rootDir>/__mocks__/workerFactoryMock.js",
|
||||
"^!!raw-loader!.*": "jest-raw-loader",
|
||||
"recorderWorkletFactory": "<rootDir>/__mocks__/empty.js",
|
||||
"^fetch-mock$": "<rootDir>/node_modules/fetch-mock",
|
||||
"counterpart": "<rootDir>/node_modules/counterpart",
|
||||
},
|
||||
transformIgnorePatterns: [
|
||||
|
||||
3
knip.ts
3
knip.ts
@ -43,7 +43,8 @@ export default {
|
||||
// Embedded into webapp
|
||||
"@element-hq/element-call-embedded",
|
||||
// Transitive dep of jest
|
||||
"jsdom",
|
||||
"@jest/globals",
|
||||
"vitest-environment-jest-fixed-jsdom",
|
||||
|
||||
// Used by matrix-js-sdk, which means we have to include them as a
|
||||
// dependency so that // we can run `tsc` (since we import the typescript
|
||||
|
||||
@ -182,6 +182,7 @@
|
||||
"@casualbot/jest-sonar-reporter": "2.5.0",
|
||||
"@element-hq/element-call-embedded": "0.16.3",
|
||||
"@element-hq/element-web-playwright-common": "2.2.3",
|
||||
"@fetch-mock/jest": "^0.2.20",
|
||||
"@peculiar/webcrypto": "^1.4.3",
|
||||
"@playwright/test": "1.57.0",
|
||||
"@principalstudio/html-webpack-inject-preload": "^1.2.7",
|
||||
@ -210,7 +211,6 @@
|
||||
"@types/minimist": "^1.2.5",
|
||||
"@types/modernizr": "^3.5.3",
|
||||
"@types/node": "18",
|
||||
"@types/node-fetch": "^2.6.2",
|
||||
"@types/pako": "^2.0.0",
|
||||
"@types/qrcode": "^1.3.5",
|
||||
"@types/react": "19.2.7",
|
||||
@ -231,7 +231,6 @@
|
||||
"chokidar": "^5.0.0",
|
||||
"concurrently": "^9.0.0",
|
||||
"copy-webpack-plugin": "^13.0.0",
|
||||
"core-js": "^3.38.1",
|
||||
"cronstrue": "^3.0.0",
|
||||
"css-loader": "^7.0.0",
|
||||
"css-minimizer-webpack-plugin": "^7.0.0",
|
||||
@ -250,15 +249,14 @@
|
||||
"eslint-plugin-unicorn": "^56.0.0",
|
||||
"express": "^5.0.0",
|
||||
"fake-indexeddb": "^6.0.0",
|
||||
"fetch-mock": "9.11.0",
|
||||
"fetch-mock-jest": "^1.5.1",
|
||||
"file-loader": "^6.0.0",
|
||||
"html-webpack-plugin": "^5.5.3",
|
||||
"husky": "^9.0.0",
|
||||
"identity-obj-proxy": "^3.0.0",
|
||||
"jest": "^30.0.0",
|
||||
"jest-canvas-mock": "^2.5.2",
|
||||
"jest-environment-jsdom": "^30.0.0",
|
||||
"jest-environment-jsdom": "^30.2.0",
|
||||
"jest-fixed-jsdom": "^0.0.11",
|
||||
"jest-mock": "^30.0.0",
|
||||
"jest-raw-loader": "^1.0.1",
|
||||
"jsqr": "^1.4.0",
|
||||
@ -268,7 +266,6 @@
|
||||
"mini-css-extract-plugin": "2.9.2",
|
||||
"minimist": "^1.2.6",
|
||||
"modernizr": "^3.12.0",
|
||||
"node-fetch": "^2.6.7",
|
||||
"patch-package": "^8.0.0",
|
||||
"playwright-core": "^1.51.0",
|
||||
"postcss": "8.4.46",
|
||||
|
||||
@ -10,7 +10,7 @@ import { env } from "process";
|
||||
import type { Config } from "jest";
|
||||
|
||||
const config: Config = {
|
||||
testEnvironment: "jsdom",
|
||||
testEnvironment: "jest-fixed-jsdom",
|
||||
testEnvironmentOptions: {
|
||||
url: "http://localhost/",
|
||||
},
|
||||
|
||||
@ -5,18 +5,19 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
|
||||
import { setLanguage } from "../../src/utils/i18n";
|
||||
import en from "../i18n/strings/en_EN.json";
|
||||
|
||||
export function setupLanguageMock(): void {
|
||||
fetchMock
|
||||
.get("/i18n/languages.json", {
|
||||
.get("end:/i18n/languages.json", {
|
||||
en: "en_EN.json",
|
||||
})
|
||||
.get("end:en_EN.json", en);
|
||||
}
|
||||
setupLanguageMock();
|
||||
fetchMock.mockGlobal();
|
||||
|
||||
setLanguage("en");
|
||||
|
||||
17
patches/jest-fixed-jsdom+0.0.11.patch
Normal file
17
patches/jest-fixed-jsdom+0.0.11.patch
Normal file
@ -0,0 +1,17 @@
|
||||
diff --git a/node_modules/jest-fixed-jsdom/index.js b/node_modules/jest-fixed-jsdom/index.js
|
||||
index ac8033b..b1ba8f0 100644
|
||||
--- a/node_modules/jest-fixed-jsdom/index.js
|
||||
+++ b/node_modules/jest-fixed-jsdom/index.js
|
||||
@@ -21,9 +21,10 @@ class FixedJSDOMEnvironment extends JSDOMEnvironment {
|
||||
this.global.TextEncoderStream = TextEncoderStream
|
||||
this.global.ReadableStream = ReadableStream
|
||||
|
||||
- this.global.Blob = Blob
|
||||
+ // this.global.Blob = Blob
|
||||
+ // this.global.File = File
|
||||
this.global.Headers = Headers
|
||||
- this.global.FormData = FormData
|
||||
+ // this.global.FormData = FormData
|
||||
this.global.Request = Request
|
||||
this.global.Response = Response
|
||||
this.global.fetch = fetch
|
||||
@ -699,6 +699,10 @@ async function handleLoadSessionFailure(e: unknown, loadSessionOpts?: ILoadSessi
|
||||
* Also stops the old MatrixClient and clears old credentials/etc out of
|
||||
* storage before starting the new client.
|
||||
*
|
||||
* This function does not work for OIDC login.
|
||||
* Storage is cleared early in the process so the required data is lost.
|
||||
* You must use {@link attemptDelegatedAuthLogin} followed by {@link restoreSessionFromStorage} for OIDC login.
|
||||
*
|
||||
* @param {IMatrixClientCreds} credentials The credentials to use
|
||||
*
|
||||
* @returns {Promise} promise which resolves to the new MatrixClient once it has been started
|
||||
|
||||
@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
|
||||
import SdkConfig from "../../src/SdkConfig";
|
||||
import PlatformPeg from "../../src/PlatformPeg";
|
||||
@ -16,8 +16,6 @@ import WebPlatform from "../../src/vector/platform/WebPlatform";
|
||||
/** The matrix versions our mock server claims to support */
|
||||
const SERVER_SUPPORTED_MATRIX_VERSIONS = ["v1.1", "v1.5", "v1.6", "v1.8", "v1.9"];
|
||||
|
||||
fetchMock.config.overwriteRoutes = true;
|
||||
|
||||
describe("Loading server config", function () {
|
||||
beforeEach(async () => {
|
||||
SdkConfig.reset();
|
||||
|
||||
@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import { render, type RenderResult, screen } from "jest-matrix-react";
|
||||
import { WrapperLifecycle, type WrapperOpts } from "@matrix-org/react-sdk-module-api/lib/lifecycles/WrapperLifecycle";
|
||||
|
||||
@ -23,8 +23,6 @@ import { waitForLoadingSpinner, waitForWelcomeComponent } from "../test-utils";
|
||||
/** The matrix versions our mock server claims to support */
|
||||
const SERVER_SUPPORTED_MATRIX_VERSIONS = ["v1.1", "v1.5", "v1.6", "v1.8", "v1.9"];
|
||||
|
||||
fetchMock.config.overwriteRoutes = true;
|
||||
|
||||
describe("Wrapper", () => {
|
||||
beforeEach(async () => {
|
||||
SdkConfig.reset();
|
||||
|
||||
@ -24,5 +24,5 @@ export const mocks = {
|
||||
setSinkId: jest.fn(),
|
||||
suspend: jest.fn(),
|
||||
decodeAudioData: jest.fn(),
|
||||
},
|
||||
} as unknown as AudioContext,
|
||||
};
|
||||
|
||||
@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import { ModuleLoader } from "@element-hq/element-web-module-api";
|
||||
import { merge } from "lodash";
|
||||
|
||||
@ -44,21 +44,29 @@ export function setupLanguageMock() {
|
||||
const enTranslations = merge(enElementWeb, enSharedComponents);
|
||||
const deTranslations = merge(deElementWeb, deSharedComponents);
|
||||
|
||||
fetchMock.mockGlobal();
|
||||
fetchMock
|
||||
.get("/i18n/languages.json", {
|
||||
en: "en_EN.json",
|
||||
de: "de_DE.json",
|
||||
lv: "lv.json",
|
||||
})
|
||||
.get(
|
||||
"end:/i18n/languages.json",
|
||||
{
|
||||
en: "en_EN.json",
|
||||
de: "de_DE.json",
|
||||
lv: "lv.json",
|
||||
},
|
||||
{ name: "languages" },
|
||||
)
|
||||
.get("end:en_EN.json", enTranslations)
|
||||
.get("end:de_DE.json", deTranslations)
|
||||
.get("end:lv.json", lv);
|
||||
}
|
||||
setupLanguageMock();
|
||||
beforeEach(setupLanguageMock);
|
||||
afterEach(() => fetchMock.callHistory.flush());
|
||||
|
||||
// Initialise the fetchMock before the test starts so the languageHandler.setLanguage call below can function
|
||||
setupLanguageMock();
|
||||
languageHandler.setLanguage("en");
|
||||
languageHandler.setMissingEntryGenerator((key) => key.split("|", 2)[1]);
|
||||
|
||||
// Set up the mdule API (so the i18n API exists)
|
||||
// Set up the module API (so the i18n API exists)
|
||||
const moduleLoader = new ModuleLoader(ModuleApi.instance);
|
||||
window.mxModuleLoader = moduleLoader;
|
||||
|
||||
@ -6,9 +6,8 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import { TextDecoder, TextEncoder } from "util";
|
||||
import { Response } from "node-fetch";
|
||||
import fetchMock, { manageFetchMockGlobally } from "@fetch-mock/jest";
|
||||
import { jest } from "@jest/globals";
|
||||
|
||||
import { mocks } from "./mocks";
|
||||
|
||||
@ -46,7 +45,7 @@ window.ClipboardEvent = MyClipboardEvent as any;
|
||||
|
||||
// matchMedia is not included in jsdom
|
||||
// TODO: Extract this to a function and have tests that need it opt into it.
|
||||
const mockMatchMedia = (query: string) => ({
|
||||
global.matchMedia = (query: string) => ({
|
||||
matches: false,
|
||||
media: query,
|
||||
onchange: null,
|
||||
@ -54,35 +53,39 @@ const mockMatchMedia = (query: string) => ({
|
||||
removeListener: jest.fn(), // Deprecated
|
||||
addEventListener: jest.fn(),
|
||||
removeEventListener: jest.fn(),
|
||||
dispatchEvent: jest.fn(),
|
||||
dispatchEvent: jest.fn<(event: Event) => boolean>(),
|
||||
});
|
||||
global.matchMedia = mockMatchMedia;
|
||||
|
||||
// maplibre requires a createObjectURL mock
|
||||
global.URL.createObjectURL = jest.fn();
|
||||
global.URL.createObjectURL = jest.fn((obj) => "blob");
|
||||
global.URL.revokeObjectURL = jest.fn();
|
||||
|
||||
// polyfilling TextEncoder as it is not available on JSDOM
|
||||
// view https://github.com/facebook/jest/issues/9983
|
||||
// XXX: Node's implementation has marginally different types, so we fudge it
|
||||
(globalThis as any).TextEncoder = TextEncoder;
|
||||
// @ts-ignore
|
||||
global.TextDecoder = TextDecoder;
|
||||
|
||||
// prevent errors whenever a component tries to manually scroll.
|
||||
window.HTMLElement.prototype.scrollIntoView = jest.fn();
|
||||
window.HTMLAudioElement.prototype.canPlayType = jest.fn((format) => (format === "audio/mpeg" ? "probably" : ""));
|
||||
|
||||
// set up fetch API mock
|
||||
fetchMock.config.overwriteRoutes = false;
|
||||
fetchMock.catch("");
|
||||
fetchMock.get("/image-file-stub", "image file stub");
|
||||
fetchMock.get("/_matrix/client/versions", {});
|
||||
// @ts-ignore
|
||||
window.fetch = fetchMock.sandbox();
|
||||
function setupFileStubMocks() {
|
||||
fetchMock.get("end:/image-file-stub", "image file stub", { sticky: true });
|
||||
}
|
||||
setupFileStubMocks();
|
||||
|
||||
// @ts-ignore
|
||||
window.Response = Response;
|
||||
beforeEach(() => {
|
||||
// set up fetch API mock
|
||||
fetchMock.hardReset();
|
||||
fetchMock.catch(404);
|
||||
setupFileStubMocks();
|
||||
fetchMock.get("/_matrix/client/versions", {}, { sticky: true });
|
||||
fetchMock.mockGlobal();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fetchMock.removeRoutes();
|
||||
window.sessionStorage?.clear();
|
||||
window.localStorage?.clear();
|
||||
});
|
||||
|
||||
fetchMock.config.allowRelativeUrls = true;
|
||||
manageFetchMockGlobally(jest);
|
||||
|
||||
// set up AudioContext API mock
|
||||
global.AudioContext = jest.fn().mockImplementation(() => ({ ...mocks.AudioContext }));
|
||||
global.AudioContext = jest.fn<() => AudioContext>().mockImplementation(() => ({ ...mocks.AudioContext }));
|
||||
|
||||
@ -8,17 +8,14 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
export const REPEATABLE_DATE = new Date(2022, 10, 17, 16, 58, 32, 517);
|
||||
|
||||
const RealDateTimeFormat = global.Intl.DateTimeFormat;
|
||||
|
||||
// allow setting default locale and set timezone
|
||||
// defaults to en-GB / Europe/London
|
||||
// so tests run the same everywhere
|
||||
export const mockIntlDateTimeFormat = (defaultLocale = "en-GB", defaultTimezone = "Europe/London"): void => {
|
||||
// unmock so we can use real DateTimeFormat in mockImplementation
|
||||
if (jest.isMockFunction(global.Intl.DateTimeFormat)) {
|
||||
unmockIntlDateTimeFormat();
|
||||
}
|
||||
const DateTimeFormat = Intl.DateTimeFormat;
|
||||
jest.spyOn(global.Intl, "DateTimeFormat").mockImplementation(
|
||||
(locale, options) => new DateTimeFormat(locale || defaultLocale, { ...options, timeZone: defaultTimezone }),
|
||||
(locale, options) => new RealDateTimeFormat(locale || defaultLocale, { ...options, timeZone: defaultTimezone }),
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ import { CallEvent, CallState, CallType, MatrixCall } from "matrix-js-sdk/src/we
|
||||
import EventEmitter from "events";
|
||||
import { mocked } from "jest-mock";
|
||||
import { CallEventHandlerEvent } from "matrix-js-sdk/src/webrtc/callEventHandler";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import { waitFor } from "jest-matrix-react";
|
||||
import { PushProcessor } from "matrix-js-sdk/src/pushprocessor";
|
||||
|
||||
@ -416,11 +416,7 @@ describe("LegacyCallHandler without third party protocols", () => {
|
||||
audioElement.id = "remoteAudio";
|
||||
document.body.appendChild(audioElement);
|
||||
|
||||
fetchMock.get(
|
||||
"/media/ring.mp3",
|
||||
{ body: new Blob(["1", "2", "3", "4"], { type: "audio/mpeg" }) },
|
||||
{ sendAsJson: false },
|
||||
);
|
||||
fetchMock.get("end:/media/ring.mp3", { body: new Blob(["1", "2", "3", "4"], { type: "audio/mpeg" }) });
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@ -438,9 +434,9 @@ describe("LegacyCallHandler without third party protocols", () => {
|
||||
it("should cache sounds between playbacks", async () => {
|
||||
await callHandler.play(AudioID.Ring);
|
||||
expect(mockAudioBufferSourceNode.start).toHaveBeenCalled();
|
||||
expect(fetchMock.calls("/media/ring.mp3")).toHaveLength(1);
|
||||
expect(fetchMock).toHaveFetchedTimes(1, "end:/media/ring.mp3");
|
||||
await callHandler.play(AudioID.Ring);
|
||||
expect(fetchMock.calls("/media/ring.mp3")).toHaveLength(1);
|
||||
expect(fetchMock).toHaveFetchedTimes(1, "end:/media/ring.mp3");
|
||||
});
|
||||
|
||||
it("should allow silencing an incoming call ring", async () => {
|
||||
|
||||
@ -12,7 +12,7 @@ import * as MatrixJs from "matrix-js-sdk/src/matrix";
|
||||
import { decodeBase64, encodeUnpaddedBase64 } from "matrix-js-sdk/src/matrix";
|
||||
import * as encryptAESSecretStorageItemModule from "matrix-js-sdk/src/utils/encryptAESSecretStorageItem";
|
||||
import { mocked, type MockedObject } from "jest-mock";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
|
||||
import StorageEvictedDialog from "../../src/components/views/dialogs/StorageEvictedDialog";
|
||||
import * as Lifecycle from "../../src/Lifecycle";
|
||||
@ -23,7 +23,6 @@ import { idbSave } from "../../src/utils/StorageAccess";
|
||||
import { flushPromises, getMockClientWithEventEmitter, mockClientMethodsUser, mockPlatformPeg } from "../test-utils";
|
||||
import { OidcClientStore } from "../../src/stores/oidc/OidcClientStore";
|
||||
import { makeDelegatedAuthConfig } from "../test-utils/oidc";
|
||||
import { persistOidcAuthenticatedSettings } from "../../src/utils/oidc/persistOidcSettings";
|
||||
import { Action } from "../../src/dispatcher/actions";
|
||||
import PlatformPeg from "../../src/PlatformPeg";
|
||||
import { persistAccessTokenInStorage, persistRefreshTokenInStorage } from "../../src/utils/tokens/tokens";
|
||||
@ -95,43 +94,6 @@ describe("Lifecycle", () => {
|
||||
window.crypto = windowCrypto;
|
||||
});
|
||||
|
||||
const initLocalStorageMock = (mockStore: Record<string, unknown> = {}): void => {
|
||||
jest.spyOn(localStorage.__proto__, "getItem")
|
||||
.mockClear()
|
||||
.mockImplementation((key: unknown) => mockStore[key as string] ?? null);
|
||||
jest.spyOn(localStorage.__proto__, "removeItem")
|
||||
.mockClear()
|
||||
.mockImplementation((key: unknown) => {
|
||||
const { [key as string]: toRemove, ...newStore } = mockStore;
|
||||
mockStore = newStore;
|
||||
return toRemove;
|
||||
});
|
||||
jest.spyOn(localStorage.__proto__, "setItem")
|
||||
.mockClear()
|
||||
.mockImplementation((key: unknown, value: unknown) => {
|
||||
mockStore[key as string] = value;
|
||||
});
|
||||
};
|
||||
|
||||
const initSessionStorageMock = (mockStore: Record<string, unknown> = {}): void => {
|
||||
jest.spyOn(sessionStorage.__proto__, "getItem")
|
||||
.mockClear()
|
||||
.mockImplementation((key: unknown) => mockStore[key as string] ?? null);
|
||||
jest.spyOn(sessionStorage.__proto__, "removeItem")
|
||||
.mockClear()
|
||||
.mockImplementation((key: unknown) => {
|
||||
const { [key as string]: toRemove, ...newStore } = mockStore;
|
||||
mockStore = newStore;
|
||||
return toRemove;
|
||||
});
|
||||
jest.spyOn(sessionStorage.__proto__, "setItem")
|
||||
.mockClear()
|
||||
.mockImplementation((key: unknown, value: unknown) => {
|
||||
mockStore[key as string] = value;
|
||||
});
|
||||
jest.spyOn(sessionStorage.__proto__, "clear").mockClear();
|
||||
};
|
||||
|
||||
const initIdbMock = (mockStore: Record<string, Record<string, unknown>> = {}): void => {
|
||||
jest.spyOn(StorageAccess, "idbLoad")
|
||||
.mockClear()
|
||||
@ -162,7 +124,7 @@ describe("Lifecycle", () => {
|
||||
});
|
||||
};
|
||||
|
||||
const localStorageSession = {
|
||||
const localStorageSession: Record<string, string> = {
|
||||
mx_hs_url: homeserverUrl,
|
||||
mx_is_url: identityServerUrl,
|
||||
mx_user_id: userId,
|
||||
@ -219,8 +181,6 @@ describe("Lifecycle", () => {
|
||||
|
||||
describe("restoreSessionFromStorage()", () => {
|
||||
beforeEach(() => {
|
||||
initLocalStorageMock();
|
||||
initSessionStorageMock();
|
||||
initIdbMock();
|
||||
|
||||
jest.clearAllMocks();
|
||||
@ -250,7 +210,7 @@ describe("Lifecycle", () => {
|
||||
});
|
||||
|
||||
it("should abort login when we expect to find an access token but don't", async () => {
|
||||
initLocalStorageMock({ mx_has_access_token: "true" });
|
||||
localStorage.setItem("mx_has_access_token", "true");
|
||||
|
||||
await expect(() => restoreSessionFromStorage()).rejects.toThrow();
|
||||
expect(Modal.createDialog).toHaveBeenCalledWith(StorageEvictedDialog);
|
||||
@ -260,7 +220,10 @@ describe("Lifecycle", () => {
|
||||
describe("when session is found in storage", () => {
|
||||
describe("guest account", () => {
|
||||
beforeEach(() => {
|
||||
initLocalStorageMock({ ...localStorageSession, mx_is_guest: "true" });
|
||||
localStorage.setItem("mx_is_guest", "true");
|
||||
for (const key in localStorageSession) {
|
||||
localStorage.setItem(key, localStorageSession[key]);
|
||||
}
|
||||
initIdbMock(idbStorageSession);
|
||||
});
|
||||
|
||||
@ -279,27 +242,29 @@ describe("Lifecycle", () => {
|
||||
}),
|
||||
undefined,
|
||||
);
|
||||
expect(localStorage.setItem).toHaveBeenCalledWith("mx_is_guest", "true");
|
||||
expect(localStorage.getItem("mx_is_guest")).toEqual("true");
|
||||
});
|
||||
});
|
||||
|
||||
describe("without a pickle key", () => {
|
||||
beforeEach(() => {
|
||||
initLocalStorageMock(localStorageSession);
|
||||
for (const key in localStorageSession) {
|
||||
localStorage.setItem(key, localStorageSession[key]);
|
||||
}
|
||||
initIdbMock(idbStorageSession);
|
||||
});
|
||||
|
||||
it("should persist credentials", async () => {
|
||||
expect(await restoreSessionFromStorage()).toEqual(true);
|
||||
|
||||
expect(localStorage.setItem).toHaveBeenCalledWith("mx_user_id", userId);
|
||||
expect(localStorage.setItem).toHaveBeenCalledWith("mx_has_access_token", "true");
|
||||
expect(localStorage.setItem).toHaveBeenCalledWith("mx_is_guest", "false");
|
||||
expect(localStorage.setItem).toHaveBeenCalledWith("mx_device_id", deviceId);
|
||||
expect(localStorage.getItem("mx_user_id")).toEqual(userId);
|
||||
expect(localStorage.getItem("mx_has_access_token")).toEqual("true");
|
||||
expect(localStorage.getItem("mx_is_guest")).toEqual("false");
|
||||
expect(localStorage.getItem("mx_device_id")).toEqual(deviceId);
|
||||
|
||||
expect(StorageAccess.idbSave).toHaveBeenCalledWith("account", "mx_access_token", accessToken);
|
||||
// dont put accessToken in localstorage when we have idb
|
||||
expect(localStorage.setItem).not.toHaveBeenCalledWith("mx_access_token", accessToken);
|
||||
expect(localStorage.getItem("mx_access_token")).not.toEqual(accessToken);
|
||||
});
|
||||
|
||||
it("should persist access token when idb is not available", async () => {
|
||||
@ -308,7 +273,7 @@ describe("Lifecycle", () => {
|
||||
|
||||
expect(StorageAccess.idbSave).toHaveBeenCalledWith("account", "mx_access_token", accessToken);
|
||||
// put accessToken in localstorage as fallback
|
||||
expect(localStorage.setItem).toHaveBeenCalledWith("mx_access_token", accessToken);
|
||||
expect(localStorage.getItem("mx_access_token")).toEqual(accessToken);
|
||||
});
|
||||
|
||||
it("should create and start new matrix client with credentials", async () => {
|
||||
@ -334,7 +299,7 @@ describe("Lifecycle", () => {
|
||||
it("should remove fresh login flag from session storage", async () => {
|
||||
expect(await restoreSessionFromStorage()).toEqual(true);
|
||||
|
||||
expect(sessionStorage.removeItem).toHaveBeenCalledWith("mx_fresh_login");
|
||||
expect(sessionStorage.getItem("mx_fresh_login")).toBeFalsy();
|
||||
});
|
||||
|
||||
it("should start matrix client", async () => {
|
||||
@ -345,10 +310,10 @@ describe("Lifecycle", () => {
|
||||
|
||||
describe("with a refresh token", () => {
|
||||
beforeEach(() => {
|
||||
initLocalStorageMock({
|
||||
...localStorageSession,
|
||||
mx_refresh_token: refreshToken,
|
||||
});
|
||||
localStorage.setItem("mx_refresh_token", refreshToken);
|
||||
for (const key in localStorageSession) {
|
||||
localStorage.setItem(key, localStorageSession[key]);
|
||||
}
|
||||
initIdbMock(idbStorageSession);
|
||||
});
|
||||
|
||||
@ -356,7 +321,7 @@ describe("Lifecycle", () => {
|
||||
expect(await restoreSessionFromStorage()).toEqual(true);
|
||||
|
||||
// refresh token from storage is re-persisted
|
||||
expect(localStorage.setItem).toHaveBeenCalledWith("mx_has_refresh_token", "true");
|
||||
expect(localStorage.getItem("mx_has_refresh_token")).toEqual("true");
|
||||
expect(StorageAccess.idbSave).toHaveBeenCalledWith("account", "mx_refresh_token", refreshToken);
|
||||
});
|
||||
|
||||
@ -386,7 +351,9 @@ describe("Lifecycle", () => {
|
||||
let pickleKey: string;
|
||||
|
||||
beforeEach(async () => {
|
||||
initLocalStorageMock(localStorageSession);
|
||||
for (const key in localStorageSession) {
|
||||
localStorage.setItem(key, localStorageSession[key]);
|
||||
}
|
||||
initIdbMock({});
|
||||
|
||||
// Create a pickle key, and store it, encrypted, in IDB.
|
||||
@ -401,7 +368,7 @@ describe("Lifecycle", () => {
|
||||
it("should persist credentials", async () => {
|
||||
expect(await restoreSessionFromStorage()).toEqual(true);
|
||||
|
||||
expect(localStorage.setItem).toHaveBeenCalledWith("mx_has_access_token", "true");
|
||||
expect(localStorage.getItem("mx_has_access_token")).toEqual("true");
|
||||
|
||||
// token encrypted and persisted
|
||||
expect(StorageAccess.idbSave).toHaveBeenCalledWith(
|
||||
@ -429,7 +396,7 @@ describe("Lifecycle", () => {
|
||||
encryptedTokenShapedObject,
|
||||
);
|
||||
// put accessToken in localstorage as fallback
|
||||
expect(localStorage.setItem).toHaveBeenCalledWith("mx_access_token", accessToken);
|
||||
expect(localStorage.getItem("mx_access_token")).toEqual(accessToken);
|
||||
});
|
||||
|
||||
it("should create and start new matrix client with credentials", async () => {
|
||||
@ -470,7 +437,7 @@ describe("Lifecycle", () => {
|
||||
expect(await restoreSessionFromStorage()).toEqual(true);
|
||||
|
||||
// refresh token from storage is re-persisted
|
||||
expect(localStorage.setItem).toHaveBeenCalledWith("mx_has_refresh_token", "true");
|
||||
expect(localStorage.getItem("mx_has_refresh_token")).toEqual("true");
|
||||
expect(StorageAccess.idbSave).toHaveBeenCalledWith(
|
||||
"account",
|
||||
"mx_refresh_token",
|
||||
@ -505,7 +472,9 @@ describe("Lifecycle", () => {
|
||||
let pickleKey: string;
|
||||
|
||||
beforeEach(async () => {
|
||||
initLocalStorageMock(localStorageSession);
|
||||
for (const key in localStorageSession) {
|
||||
localStorage.setItem(key, localStorageSession[key]);
|
||||
}
|
||||
initIdbMock({});
|
||||
|
||||
// Generate the pickle key. I don't *think* it's possible for there to be a pickle key
|
||||
@ -552,7 +521,9 @@ describe("Lifecycle", () => {
|
||||
});
|
||||
|
||||
it("should proceed if server is not accessible", async () => {
|
||||
initLocalStorageMock(localStorageSession);
|
||||
for (const key in localStorageSession) {
|
||||
localStorage.setItem(key, localStorageSession[key]);
|
||||
}
|
||||
initIdbMock(idbStorageSession);
|
||||
mockClient.isVersionSupported.mockRejectedValue(new Error("Oh, noes, the server is down!"));
|
||||
|
||||
@ -560,7 +531,9 @@ describe("Lifecycle", () => {
|
||||
});
|
||||
|
||||
it("should throw if the token was persisted with a pickle key but there is no pickle key available now", async () => {
|
||||
initLocalStorageMock(localStorageSession);
|
||||
for (const key in localStorageSession) {
|
||||
localStorage.setItem(key, localStorageSession[key]);
|
||||
}
|
||||
initIdbMock({});
|
||||
|
||||
// Create a pickle key, and store it, encrypted, in IDB.
|
||||
@ -580,8 +553,6 @@ describe("Lifecycle", () => {
|
||||
|
||||
describe("setLoggedIn()", () => {
|
||||
beforeEach(() => {
|
||||
initLocalStorageMock();
|
||||
initSessionStorageMock();
|
||||
initIdbMock();
|
||||
|
||||
jest.clearAllMocks();
|
||||
@ -599,7 +570,7 @@ describe("Lifecycle", () => {
|
||||
it("should remove fresh login flag from session storage", async () => {
|
||||
await setLoggedIn(credentials);
|
||||
|
||||
expect(sessionStorage.removeItem).toHaveBeenCalledWith("mx_fresh_login");
|
||||
expect(sessionStorage.getItem("mx_fresh_login")).toBeFalsy();
|
||||
});
|
||||
|
||||
it("should start matrix client", async () => {
|
||||
@ -617,7 +588,7 @@ describe("Lifecycle", () => {
|
||||
it("should not clear the storage if device is the same", async () => {
|
||||
await Lifecycle.hydrateSession(credentials);
|
||||
|
||||
expect(localStorage.removeItem).toHaveBeenCalledWith("mx_soft_logout");
|
||||
expect(localStorage.getItem("mx_soft_logout")).toBeFalsy();
|
||||
expect(mockClient.getUserId).toHaveReturnedWith(userId);
|
||||
expect(mockClient.getDeviceId).toHaveReturnedWith(deviceId);
|
||||
expect(mockClient.clearStores).toHaveBeenCalledTimes(1);
|
||||
@ -633,7 +604,7 @@ describe("Lifecycle", () => {
|
||||
};
|
||||
await Lifecycle.hydrateSession(fakeCredentials);
|
||||
|
||||
expect(localStorage.removeItem).toHaveBeenCalledWith("mx_soft_logout");
|
||||
expect(localStorage.getItem("mx_soft_logout")).toBeFalsy();
|
||||
expect(mockClient.getUserId).toHaveReturnedWith(userId);
|
||||
expect(mockClient.getDeviceId).toHaveReturnedWith(deviceId);
|
||||
expect(mockClient.clearStores).toHaveBeenCalledTimes(2);
|
||||
@ -648,21 +619,19 @@ describe("Lifecycle", () => {
|
||||
it("should persist credentials", async () => {
|
||||
await setLoggedIn(credentials);
|
||||
|
||||
expect(localStorage.setItem).toHaveBeenCalledWith("mx_user_id", userId);
|
||||
expect(localStorage.setItem).toHaveBeenCalledWith("mx_has_access_token", "true");
|
||||
expect(localStorage.setItem).toHaveBeenCalledWith("mx_is_guest", "false");
|
||||
expect(localStorage.setItem).toHaveBeenCalledWith("mx_device_id", deviceId);
|
||||
expect(localStorage.getItem("mx_user_id")).toEqual(userId);
|
||||
expect(localStorage.getItem("mx_has_access_token")).toEqual("true");
|
||||
expect(localStorage.getItem("mx_is_guest")).toEqual("false");
|
||||
expect(localStorage.getItem("mx_device_id")).toEqual(deviceId);
|
||||
|
||||
expect(StorageAccess.idbSave).toHaveBeenCalledWith("account", "mx_access_token", accessToken);
|
||||
// dont put accessToken in localstorage when we have idb
|
||||
expect(localStorage.setItem).not.toHaveBeenCalledWith("mx_access_token", accessToken);
|
||||
expect(localStorage.getItem("mx_access_token")).not.toEqual(accessToken);
|
||||
});
|
||||
|
||||
it("should persist a refreshToken when present", async () => {
|
||||
initLocalStorageMock({
|
||||
mx_oidc_token_issuer: "test-issuer.dummy",
|
||||
mx_oidc_client_id: "test-client-id",
|
||||
});
|
||||
localStorage.setItem("mx_oidc_token_issuer", "test-issuer.dummy");
|
||||
localStorage.setItem("mx_oidc_client_id", "test-client-id");
|
||||
|
||||
await setLoggedIn({
|
||||
...credentials,
|
||||
@ -672,7 +641,7 @@ describe("Lifecycle", () => {
|
||||
expect(StorageAccess.idbSave).toHaveBeenCalledWith("account", "mx_access_token", accessToken);
|
||||
expect(StorageAccess.idbSave).toHaveBeenCalledWith("account", "mx_refresh_token", refreshToken);
|
||||
// dont put accessToken in localstorage when we have idb
|
||||
expect(localStorage.setItem).not.toHaveBeenCalledWith("mx_access_token", accessToken);
|
||||
expect(localStorage.getItem("mx_access_token")).not.toEqual(accessToken);
|
||||
});
|
||||
|
||||
it("should remove any access token from storage when there is none in credentials and idb save fails", async () => {
|
||||
@ -683,15 +652,15 @@ describe("Lifecycle", () => {
|
||||
accessToken: undefined,
|
||||
});
|
||||
|
||||
expect(localStorage.removeItem).toHaveBeenCalledWith("mx_has_access_token");
|
||||
expect(localStorage.removeItem).toHaveBeenCalledWith("mx_access_token");
|
||||
expect(localStorage.getItem("mx_has_access_token")).toBeFalsy();
|
||||
expect(localStorage.getItem("mx_access_token")).toBeFalsy();
|
||||
});
|
||||
|
||||
it("should clear stores", async () => {
|
||||
await setLoggedIn(credentials);
|
||||
|
||||
expect(StorageAccess.idbClear).toHaveBeenCalledWith("account");
|
||||
expect(sessionStorage.clear).toHaveBeenCalled();
|
||||
expect(sessionStorage.length).toBe(0);
|
||||
expect(mockClient.clearStores).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@ -735,12 +704,12 @@ describe("Lifecycle", () => {
|
||||
it("should persist credentials", async () => {
|
||||
await setLoggedIn(credentials);
|
||||
|
||||
expect(localStorage.setItem).toHaveBeenCalledWith("mx_user_id", userId);
|
||||
expect(localStorage.setItem).toHaveBeenCalledWith("mx_has_access_token", "true");
|
||||
expect(localStorage.setItem).toHaveBeenCalledWith("mx_is_guest", "false");
|
||||
expect(localStorage.setItem).toHaveBeenCalledWith("mx_device_id", deviceId);
|
||||
expect(localStorage.getItem("mx_user_id")).toEqual(userId);
|
||||
expect(localStorage.getItem("mx_has_access_token")).toEqual("true");
|
||||
expect(localStorage.getItem("mx_is_guest")).toEqual("false");
|
||||
expect(localStorage.getItem("mx_device_id")).toEqual(deviceId);
|
||||
|
||||
expect(localStorage.setItem).toHaveBeenCalledWith("mx_has_pickle_key", "true");
|
||||
expect(localStorage.getItem("mx_has_pickle_key")).toEqual("true");
|
||||
expect(StorageAccess.idbSave).toHaveBeenCalledWith(
|
||||
"account",
|
||||
"mx_access_token",
|
||||
@ -748,7 +717,7 @@ describe("Lifecycle", () => {
|
||||
);
|
||||
expect(StorageAccess.idbSave).toHaveBeenCalledWith("pickleKey", [userId, deviceId], expect.any(Object));
|
||||
// dont put accessToken in localstorage when we have idb
|
||||
expect(localStorage.setItem).not.toHaveBeenCalledWith("mx_access_token", accessToken);
|
||||
expect(localStorage.getItem("mx_access_token")).not.toEqual(accessToken);
|
||||
});
|
||||
|
||||
it("should persist token when encrypting the token fails", async () => {
|
||||
@ -771,7 +740,7 @@ describe("Lifecycle", () => {
|
||||
await setLoggedIn(credentials);
|
||||
|
||||
// put plain accessToken in localstorage when we dont have idb
|
||||
expect(localStorage.setItem).toHaveBeenCalledWith("mx_access_token", accessToken);
|
||||
expect(localStorage.getItem("mx_access_token")).toEqual(accessToken);
|
||||
});
|
||||
|
||||
it("should remove any access token from storage when there is none in credentials and idb save fails", async () => {
|
||||
@ -789,8 +758,8 @@ describe("Lifecycle", () => {
|
||||
accessToken: undefined,
|
||||
});
|
||||
|
||||
expect(localStorage.removeItem).toHaveBeenCalledWith("mx_has_access_token");
|
||||
expect(localStorage.removeItem).toHaveBeenCalledWith("mx_access_token");
|
||||
expect(localStorage.getItem("mx_has_access_token")).toBeFalsy();
|
||||
expect(localStorage.getItem("mx_access_token")).toBeFalsy();
|
||||
});
|
||||
|
||||
it("should create new matrix client with credentials", async () => {
|
||||
@ -812,7 +781,8 @@ describe("Lifecycle", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("when authenticated via OIDC native flow", () => {
|
||||
// XXX: these tests are broken, Lifecycle.setLoggedIn does not work with OIDC and its token refreshers due to clearing storage
|
||||
describe.skip("when authenticated via OIDC native flow", () => {
|
||||
const clientId = "test-client-id";
|
||||
const issuer = "https://auth.com/";
|
||||
|
||||
@ -820,7 +790,7 @@ describe("Lifecycle", () => {
|
||||
const idToken =
|
||||
"eyJhbGciOiJSUzI1NiIsImtpZCI6Imh4ZEhXb0Y5bW4ifQ.eyJzdWIiOiIwMUhQUDJGU0JZREU5UDlFTU04REQ3V1pIUiIsImlzcyI6Imh0dHBzOi8vYXV0aC1vaWRjLmxhYi5lbGVtZW50LmRldi8iLCJpYXQiOjE3MTUwNzE5ODUsImF1dGhfdGltZSI6MTcwNzk5MDMxMiwiY19oYXNoIjoidGt5R1RhUjU5aTk3YXoyTU4yMGdidyIsImV4cCI6MTcxNTA3NTU4NSwibm9uY2UiOiJxaXhwM0hFMmVaIiwiYXVkIjoiMDFIWDk0Mlg3QTg3REgxRUs2UDRaNjI4WEciLCJhdF9oYXNoIjoiNFlFUjdPRlVKTmRTeEVHV2hJUDlnZyJ9.HxODneXvSTfWB5Vc4cf7b8GiN2gdwUuTiyVqZuupWske2HkZiJZUt5Lsxg9BW3gz28POkE0Ln17snlkmy02B_AD3DQxKOOxQCzIIARHdfFvZxgGWsMdFcVQZDW7rtXcqgj-SpVaUQ_8acsgxSrz_DF2o0O4tto0PT6wVUiw8KlBmgWTscWPeAWe-39T-8EiQ8Wi16h6oSPcz2NzOQ7eOM_S9fDkOorgcBkRGLl1nrahrPSdWJSGAeruk5mX4YxN714YThFDyEA2t9YmKpjaiSQ2tT-Xkd7tgsZqeirNs2ni9mIiFX3bRX6t2AhUNzA7MaX9ZyizKGa6go3BESO_oDg";
|
||||
|
||||
beforeAll(() => {
|
||||
beforeEach(() => {
|
||||
fetchMock.get(`${delegatedAuthConfig.issuer}.well-known/openid-configuration`, delegatedAuthConfig);
|
||||
fetchMock.get(`${delegatedAuthConfig.issuer}jwks`, {
|
||||
status: 200,
|
||||
@ -829,27 +799,24 @@ describe("Lifecycle", () => {
|
||||
},
|
||||
keys: [],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
initSessionStorageMock();
|
||||
// set values in session storage as they would be after a successful oidc authentication
|
||||
persistOidcAuthenticatedSettings(clientId, issuer, idToken);
|
||||
// set values in local storage as they would be after a successful oidc authentication
|
||||
localStorage.setItem("mx_oidc_client_id", clientId);
|
||||
localStorage.setItem("mx_oidc_token_issuer", issuer);
|
||||
localStorage.setItem("mx_oidc_id_token", idToken);
|
||||
});
|
||||
|
||||
it("should not try to create a token refresher without a refresh token", async () => {
|
||||
await setLoggedIn(credentials);
|
||||
|
||||
// didn't try to initialise token refresher
|
||||
expect(fetchMock).not.toHaveFetched(`${delegatedAuthConfig.issuer}.well-known/openid-configuration`);
|
||||
expect(fetchMock).toHaveFetchedTimes(
|
||||
0,
|
||||
`${delegatedAuthConfig.issuer}.well-known/openid-configuration`,
|
||||
);
|
||||
});
|
||||
|
||||
it("should not try to create a token refresher without a deviceId", async () => {
|
||||
initLocalStorageMock({
|
||||
mx_oidc_token_issuer: "test-issuer.dummy",
|
||||
mx_oidc_client_id: "test-client-id",
|
||||
});
|
||||
|
||||
await expect(
|
||||
setLoggedIn({
|
||||
...credentials,
|
||||
@ -859,16 +826,14 @@ describe("Lifecycle", () => {
|
||||
).rejects.toThrow("Expected deviceId in user credentials.");
|
||||
|
||||
// didn't try to initialise token refresher
|
||||
expect(fetchMock).not.toHaveFetched(`${delegatedAuthConfig.issuer}.well-known/openid-configuration`);
|
||||
expect(fetchMock).toHaveFetchedTimes(
|
||||
0,
|
||||
`${delegatedAuthConfig.issuer}.well-known/openid-configuration`,
|
||||
);
|
||||
});
|
||||
|
||||
it("should not try to create a token refresher without an issuer in session storage", async () => {
|
||||
persistOidcAuthenticatedSettings(
|
||||
clientId,
|
||||
// @ts-ignore set undefined issuer
|
||||
undefined,
|
||||
idToken,
|
||||
);
|
||||
localStorage.removeItem("mx_oidc_token_issuer");
|
||||
await expect(
|
||||
setLoggedIn({
|
||||
...credentials,
|
||||
@ -877,7 +842,10 @@ describe("Lifecycle", () => {
|
||||
).rejects.toThrow("Cannot create an OIDC token refresher as no stored OIDC token issuer was found.");
|
||||
|
||||
// didn't try to initialise token refresher
|
||||
expect(fetchMock).not.toHaveFetched(`${delegatedAuthConfig.issuer}.well-known/openid-configuration`);
|
||||
expect(fetchMock).toHaveFetchedTimes(
|
||||
0,
|
||||
`${delegatedAuthConfig.issuer}.well-known/openid-configuration`,
|
||||
);
|
||||
});
|
||||
|
||||
it("should create a client with a tokenRefreshFunction", async () => {
|
||||
@ -898,8 +866,8 @@ describe("Lifecycle", () => {
|
||||
});
|
||||
|
||||
it("should create a client when creating token refresher fails", async () => {
|
||||
// set invalid value in session storage for a malformed oidc authentication
|
||||
persistOidcAuthenticatedSettings(null as any, issuer, idToken);
|
||||
// create invalid value in local storage for a malformed oidc authentication
|
||||
localStorage.removeItem("mx_oidc_client_id");
|
||||
|
||||
// succeeded
|
||||
expect(
|
||||
|
||||
@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import fetchMockJest from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
|
||||
import { advanceDateAndTime, stubClient } from "../test-utils";
|
||||
import { type IMatrixClientPeg, MatrixClientPeg as peg } from "../../src/MatrixClientPeg";
|
||||
@ -69,7 +69,7 @@ describe("MatrixClientPeg", () => {
|
||||
beforeEach(() => {
|
||||
// instantiate a MatrixClientPegClass instance, with a new MatrixClient
|
||||
testPeg = new PegClass();
|
||||
fetchMockJest.get("http://example.com/_matrix/client/versions", {});
|
||||
fetchMock.get("http://example.com/_matrix/client/versions", {});
|
||||
testPeg.replaceUsingCreds({
|
||||
accessToken: "SEKRET",
|
||||
homeserverUrl: "http://example.com",
|
||||
|
||||
@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { mocked } from "jest-mock";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import { type MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import ScalarAuthClient from "../../src/ScalarAuthClient";
|
||||
|
||||
@ -9,7 +9,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
import { type SlidingSync, SlidingSyncEvent, SlidingSyncState } from "matrix-js-sdk/src/sliding-sync";
|
||||
import { mocked } from "jest-mock";
|
||||
import { ClientEvent, type MatrixClient, MatrixEvent, Room } from "matrix-js-sdk/src/matrix";
|
||||
import fetchMockJest from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import EventEmitter from "events";
|
||||
import { waitFor } from "jest-matrix-react";
|
||||
|
||||
@ -45,8 +45,7 @@ describe("SlidingSyncManager", () => {
|
||||
mocked(client.getRoom).mockReturnValue(null);
|
||||
(manager as any).configure(client, "invalid");
|
||||
manager.slidingSync = slidingSync;
|
||||
fetchMockJest.reset();
|
||||
fetchMockJest.get("https://proxy/client/server.json", {});
|
||||
fetchMock.get("https://proxy/client/server.json", {});
|
||||
});
|
||||
|
||||
describe("setRoomVisible", () => {
|
||||
|
||||
@ -11,13 +11,8 @@ import { render } from "jest-matrix-react";
|
||||
|
||||
import SdkConfig from "../../../../src/SdkConfig";
|
||||
import { ErrorView, UnsupportedBrowserView } from "../../../../src/async-components/structures/ErrorView";
|
||||
import { setupLanguageMock } from "../../../setup/setupLanguage";
|
||||
|
||||
describe("<ErrorView />", () => {
|
||||
beforeEach(() => {
|
||||
setupLanguageMock();
|
||||
});
|
||||
|
||||
it("should match snapshot", () => {
|
||||
const { asFragment } = render(<ErrorView title="TITLE" messages={["MSG1", "MSG2"]} />);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
@ -26,7 +21,6 @@ describe("<ErrorView />", () => {
|
||||
|
||||
describe("<UnsupportedBrowserView />", () => {
|
||||
beforeEach(() => {
|
||||
setupLanguageMock();
|
||||
SdkConfig.put({});
|
||||
});
|
||||
|
||||
|
||||
@ -6,13 +6,10 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
// fake-indexeddb needs this and the tests crash without it
|
||||
// https://github.com/dumbmatter/fakeIndexedDB?tab=readme-ov-file#jsdom-often-used-with-jest
|
||||
import "core-js/stable/structured-clone";
|
||||
import "fake-indexeddb/auto";
|
||||
import React, { type ComponentProps } from "react";
|
||||
import { fireEvent, render, type RenderResult, screen, waitFor, within, act } from "jest-matrix-react";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import { type Mocked, mocked } from "jest-mock";
|
||||
import { ClientEvent, type MatrixClient, MatrixEvent, Room, SyncState } from "matrix-js-sdk/src/matrix";
|
||||
import { type MediaHandler } from "matrix-js-sdk/src/webrtc/mediaHandler";
|
||||
@ -1629,7 +1626,7 @@ describe("<MatrixChat />", () => {
|
||||
|
||||
// Flaky test, see https://github.com/element-hq/element-web/issues/30337
|
||||
it("waits for other tab to stop during startup", async () => {
|
||||
fetchMock.get("/welcome.html", { body: "<h1>Hello</h1>" });
|
||||
fetchMock.get("end:/welcome.html", { body: "<h1>Hello</h1>" });
|
||||
jest.spyOn(Lifecycle, "attemptDelegatedAuthLogin");
|
||||
|
||||
// simulate an active window
|
||||
|
||||
@ -11,7 +11,7 @@ import { render, screen, waitFor } from "jest-matrix-react";
|
||||
import { DEVICE_CODE_SCOPE, type MatrixClient, type Room } from "matrix-js-sdk/src/matrix";
|
||||
import { type CryptoApi } from "matrix-js-sdk/src/crypto-api";
|
||||
import { mocked } from "jest-mock";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
|
||||
import UnwrappedUserMenu from "../../../../src/components/structures/UserMenu";
|
||||
import { stubClient, wrapInSdkContext } from "../../../test-utils";
|
||||
|
||||
@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
import React from "react";
|
||||
import { fireEvent, render, screen, waitForElementToBeRemoved } from "jest-matrix-react";
|
||||
import { mocked, type MockedObject } from "jest-mock";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import { DELEGATED_OIDC_COMPATIBILITY, IdentityProviderBrand, type OidcClientConfig } from "matrix-js-sdk/src/matrix";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import * as Matrix from "matrix-js-sdk/src/matrix";
|
||||
@ -18,7 +18,6 @@ import SdkConfig from "../../../../../src/SdkConfig";
|
||||
import { mkServerConfig, mockPlatformPeg, unmockPlatformPeg } from "../../../../test-utils";
|
||||
import Login from "../../../../../src/components/structures/auth/Login";
|
||||
import type BasePlatform from "../../../../../src/BasePlatform";
|
||||
import SettingsStore from "../../../../../src/settings/SettingsStore";
|
||||
import * as registerClientUtils from "../../../../../src/utils/oidc/registerClient";
|
||||
import { makeDelegatedAuthConfig } from "../../../../test-utils/oidc";
|
||||
|
||||
@ -55,8 +54,6 @@ describe("Login", function () {
|
||||
mockClient.baseUrl = opts.baseUrl;
|
||||
return mockClient;
|
||||
});
|
||||
fetchMock.resetBehavior();
|
||||
fetchMock.resetHistory();
|
||||
fetchMock.get("https://matrix.org/_matrix/client/versions", {
|
||||
unstable_features: {},
|
||||
versions: ["v1.1"],
|
||||
@ -67,7 +64,6 @@ describe("Login", function () {
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
fetchMock.restore();
|
||||
SdkConfig.reset(); // we touch the config, so clean up
|
||||
unmockPlatformPeg();
|
||||
});
|
||||
@ -327,7 +323,7 @@ describe("Login", function () {
|
||||
});
|
||||
|
||||
it("should display an error when homeserver fails liveliness check", async () => {
|
||||
fetchMock.resetBehavior();
|
||||
fetchMock.removeRoutes();
|
||||
fetchMock.get("https://matrix.org/_matrix/client/versions", {
|
||||
status: 0,
|
||||
});
|
||||
@ -339,7 +335,7 @@ describe("Login", function () {
|
||||
});
|
||||
|
||||
it("should reset liveliness error when server config changes", async () => {
|
||||
fetchMock.resetBehavior();
|
||||
fetchMock.removeRoutes();
|
||||
// matrix.org is not alive
|
||||
fetchMock.get("https://matrix.org/_matrix/client/versions", {
|
||||
status: 400,
|
||||
@ -376,21 +372,6 @@ describe("Login", function () {
|
||||
jest.spyOn(logger, "error").mockRestore();
|
||||
});
|
||||
|
||||
it("should not attempt registration when oidc native flow setting is disabled", async () => {
|
||||
jest.spyOn(SettingsStore, "getValue").mockReturnValue(false);
|
||||
|
||||
getComponent(hsUrl, isUrl, delegatedAuth);
|
||||
|
||||
await waitForElementToBeRemoved(() => screen.queryAllByLabelText("Loading…"));
|
||||
|
||||
// didn't try to register
|
||||
expect(fetchMock).not.toHaveBeenCalledWith(delegatedAuth.registration_endpoint);
|
||||
// continued with normal setup
|
||||
expect(mockClient.loginFlows).toHaveBeenCalled();
|
||||
// normal password login rendered
|
||||
expect(screen.getByLabelText("Username")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should attempt to register oidc client", async () => {
|
||||
// dont mock, spy so we can check config values were correctly passed
|
||||
jest.spyOn(registerClientUtils, "getOidcClientId");
|
||||
@ -400,7 +381,7 @@ describe("Login", function () {
|
||||
await waitForElementToBeRemoved(() => screen.queryAllByLabelText("Loading…"));
|
||||
|
||||
// tried to register
|
||||
expect(fetchMock).toHaveBeenCalledWith(delegatedAuth.registration_endpoint, expect.any(Object));
|
||||
expect(fetchMock).toHaveFetched(delegatedAuth.registration_endpoint);
|
||||
// called with values from config
|
||||
expect(registerClientUtils.getOidcClientId).toHaveBeenCalledWith(delegatedAuth, oidcStaticClientsConfig);
|
||||
});
|
||||
@ -412,7 +393,7 @@ describe("Login", function () {
|
||||
await waitForElementToBeRemoved(() => screen.queryAllByLabelText("Loading…"));
|
||||
|
||||
// tried to register
|
||||
expect(fetchMock).toHaveBeenCalledWith(delegatedAuth.registration_endpoint, expect.any(Object));
|
||||
expect(fetchMock).toHaveFetched(delegatedAuth.registration_endpoint);
|
||||
expect(logger.error).toHaveBeenCalledWith(new Error(OidcError.DynamicRegistrationFailed));
|
||||
|
||||
// continued with normal setup
|
||||
@ -432,38 +413,5 @@ describe("Login", function () {
|
||||
expect(mockClient.loginFlows).not.toHaveBeenCalled();
|
||||
expect(screen.getByText("Continue")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
/**
|
||||
* Oidc-aware flows still work while the oidc-native feature flag is disabled
|
||||
*/
|
||||
it("should show oidc-aware flow for oidc-enabled homeserver when oidc native flow setting is disabled", async () => {
|
||||
jest.spyOn(SettingsStore, "getValue").mockReturnValue(false);
|
||||
mockClient.loginFlows.mockResolvedValue({
|
||||
flows: [
|
||||
{
|
||||
type: "m.login.sso",
|
||||
[DELEGATED_OIDC_COMPATIBILITY.name]: true,
|
||||
},
|
||||
{
|
||||
type: "m.login.password",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const { container } = getComponent(hsUrl, isUrl, delegatedAuth);
|
||||
|
||||
await waitForElementToBeRemoved(() => screen.queryAllByLabelText("Loading…"));
|
||||
|
||||
// didn't try to register
|
||||
expect(fetchMock).not.toHaveBeenCalledWith(delegatedAuth.registration_endpoint);
|
||||
// continued with normal setup
|
||||
expect(mockClient.loginFlows).toHaveBeenCalled();
|
||||
// oidc-aware 'continue' button displayed
|
||||
const ssoButtons = container.querySelectorAll(".mx_SSOButton");
|
||||
expect(ssoButtons.length).toBe(1);
|
||||
expect(ssoButtons[0].textContent).toBe("Continue");
|
||||
// no password form visible
|
||||
expect(container.querySelector("form")).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -11,7 +11,7 @@ import React from "react";
|
||||
import { fireEvent, render, screen, waitFor, waitForElementToBeRemoved } from "jest-matrix-react";
|
||||
import { createClient, type MatrixClient, MatrixError, type OidcClientConfig } from "matrix-js-sdk/src/matrix";
|
||||
import { mocked, type MockedObject } from "jest-mock";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
|
||||
import SdkConfig, { DEFAULTS } from "../../../../../src/SdkConfig";
|
||||
import {
|
||||
@ -75,7 +75,6 @@ describe("Registration", function () {
|
||||
|
||||
afterEach(function () {
|
||||
jest.restoreAllMocks();
|
||||
fetchMock.restore();
|
||||
SdkConfig.reset(); // we touch the config, so clean up
|
||||
unmockPlatformPeg();
|
||||
});
|
||||
|
||||
@ -10,13 +10,8 @@ import React from "react";
|
||||
import { render } from "jest-matrix-react";
|
||||
|
||||
import AuthFooter from "../../../../../src/components/views/auth/AuthFooter";
|
||||
import { setupLanguageMock } from "../../../../setup/setupLanguage";
|
||||
|
||||
describe("<AuthFooter />", () => {
|
||||
beforeEach(() => {
|
||||
setupLanguageMock();
|
||||
});
|
||||
|
||||
it("should match snapshot", () => {
|
||||
const { asFragment } = render(<AuthFooter />);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
|
||||
@ -10,12 +10,10 @@ import React from "react";
|
||||
import { render } from "jest-matrix-react";
|
||||
|
||||
import AuthPage from "../../../../../src/components/views/auth/AuthPage";
|
||||
import { setupLanguageMock } from "../../../../setup/setupLanguage";
|
||||
import SdkConfig from "../../../../../src/SdkConfig.ts";
|
||||
|
||||
describe("<AuthPage />", () => {
|
||||
beforeEach(() => {
|
||||
setupLanguageMock();
|
||||
SdkConfig.reset();
|
||||
// @ts-ignore private access
|
||||
AuthPage.welcomeBackgroundUrl = undefined;
|
||||
|
||||
@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import { render, screen } from "jest-matrix-react";
|
||||
import { mocked } from "jest-mock";
|
||||
|
||||
@ -19,7 +19,7 @@ jest.mock("../../../../../src/languageHandler", () => ({
|
||||
}));
|
||||
|
||||
describe("<EmbeddedPage />", () => {
|
||||
it.each([`"`, `'`, `'`, `4`])("should translate _t strings", async (character) => {
|
||||
it.each([`"`, `'`, ``, `"`])("should translate _t strings [%s]", async (character) => {
|
||||
mocked(_t).mockReturnValue("Przeglądaj pokoje");
|
||||
fetchMock.get("https://home.page", {
|
||||
body: `<h1>_t(${character}Explore rooms${character})</h1>`,
|
||||
|
||||
@ -665,7 +665,10 @@ describe("MessageContextMenu", () => {
|
||||
it("shows view in room button when the event is a thread root", () => {
|
||||
const eventContent = createMessageEventContent("hello");
|
||||
const mxEvent = new MatrixEvent({ type: EventType.RoomMessage, content: eventContent });
|
||||
mxEvent.getThread = () => ({ rootEvent: mxEvent }) as Thread;
|
||||
mxEvent.getThread = () =>
|
||||
({
|
||||
rootEvent: mxEvent,
|
||||
}) as Thread;
|
||||
const props = {
|
||||
rightClick: true,
|
||||
};
|
||||
|
||||
@ -26,7 +26,7 @@ exports[`<EmbeddedPage /> should show error if unable to load 1`] = `
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`<EmbeddedPage /> should translate _t strings 1`] = `
|
||||
exports[`<EmbeddedPage /> should translate _t strings ["] 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="undefined_guest"
|
||||
@ -42,7 +42,7 @@ exports[`<EmbeddedPage /> should translate _t strings 1`] = `
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`<EmbeddedPage /> should translate _t strings 2`] = `
|
||||
exports[`<EmbeddedPage /> should translate _t strings [] 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="undefined_guest"
|
||||
@ -58,7 +58,7 @@ exports[`<EmbeddedPage /> should translate _t strings 2`] = `
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`<EmbeddedPage /> should translate _t strings 3`] = `
|
||||
exports[`<EmbeddedPage /> should translate _t strings ["] 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="undefined_guest"
|
||||
@ -74,7 +74,7 @@ exports[`<EmbeddedPage /> should translate _t strings 3`] = `
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`<EmbeddedPage /> should translate _t strings 4`] = `
|
||||
exports[`<EmbeddedPage /> should translate _t strings ['] 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="undefined_guest"
|
||||
|
||||
@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
import { render, waitFor, type RenderResult } from "jest-matrix-react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import React from "react";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import { type Mocked } from "jest-mock";
|
||||
|
||||
import BugReportDialog, {
|
||||
@ -59,7 +59,6 @@ describe("BugReportDialog", () => {
|
||||
global.mx_rage_logger = prevLogger;
|
||||
jest.restoreAllMocks();
|
||||
SdkConfig.reset();
|
||||
fetchMock.restore();
|
||||
});
|
||||
|
||||
it("can close the bug reporter", async () => {
|
||||
|
||||
@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import { render, screen, waitForElementToBeRemoved } from "jest-matrix-react";
|
||||
|
||||
import ChangelogDialog, {
|
||||
|
||||
@ -56,8 +56,7 @@ describe("DevtoolsDialog", () => {
|
||||
const copiedBtn = getByLabelText(container, "Copied!");
|
||||
|
||||
expect(copiedBtn).toBeInTheDocument();
|
||||
expect(navigator.clipboard.writeText).toHaveBeenCalled();
|
||||
await expect(navigator.clipboard.readText()).resolves.toBe(room.roomId);
|
||||
expect(navigator.clipboard.writeText).toHaveBeenCalledWith(room.roomId);
|
||||
});
|
||||
|
||||
it("copies the thread root id when provided", async () => {
|
||||
@ -72,7 +71,6 @@ describe("DevtoolsDialog", () => {
|
||||
const copiedBtn = getByLabelText(container, "Copied!");
|
||||
|
||||
expect(copiedBtn).toBeInTheDocument();
|
||||
expect(navigator.clipboard.writeText).toHaveBeenCalled();
|
||||
await expect(navigator.clipboard.readText()).resolves.toBe(threadRootId);
|
||||
expect(navigator.clipboard.writeText).toHaveBeenCalledWith(threadRootId);
|
||||
});
|
||||
});
|
||||
|
||||
@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import React from "react";
|
||||
import { fireEvent, render, screen } from "jest-matrix-react";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
|
||||
import ServerPickerDialog from "../../../../../src/components/views/dialogs/ServerPickerDialog";
|
||||
import SdkConfig from "../../../../../src/SdkConfig";
|
||||
@ -54,7 +54,7 @@ describe("<ServerPickerDialog />", () => {
|
||||
validated_server_config: defaultServerConfig,
|
||||
});
|
||||
|
||||
fetchMock.resetHistory();
|
||||
fetchMock.clearHistory();
|
||||
fetchMock.catch({
|
||||
status: 404,
|
||||
body: '{"errcode": "M_UNRECOGNIZED", "error": "Unrecognized request"}',
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
import React from "react";
|
||||
import { mocked } from "jest-mock";
|
||||
import { render, fireEvent, waitFor } from "jest-matrix-react";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import { MatrixEvent } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import ImageView from "../../../../../src/components/views/elements/ImageView";
|
||||
@ -23,7 +23,6 @@ jest.mock("../../../../../src/utils/FileDownloader");
|
||||
describe("<ImageView />", () => {
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
fetchMock.reset();
|
||||
});
|
||||
|
||||
it("renders correctly", () => {
|
||||
|
||||
@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import React from "react";
|
||||
import { mocked } from "jest-mock";
|
||||
import fetchMockJest from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import { fireEvent, render, screen, waitFor } from "jest-matrix-react";
|
||||
import { MatrixEvent } from "matrix-js-sdk/src/matrix";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
@ -37,7 +37,6 @@ describe("DownloadActionButton", () => {
|
||||
|
||||
beforeEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
fetchMockJest.restore();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@ -51,7 +50,7 @@ describe("DownloadActionButton", () => {
|
||||
(mxc) => `https://matrix.org/_matrix/media/r0/download/${mxc.slice(6)}`,
|
||||
);
|
||||
|
||||
fetchMockJest.getOnce("https://matrix.org/_matrix/media/r0/download/matrix.org/1234", {
|
||||
fetchMock.getOnce("https://matrix.org/_matrix/media/r0/download/matrix.org/1234", {
|
||||
status: 404,
|
||||
body: { errcode: "M_NOT_FOUND", error: "Not found" },
|
||||
});
|
||||
@ -78,7 +77,7 @@ describe("DownloadActionButton", () => {
|
||||
|
||||
const user = userEvent.setup();
|
||||
|
||||
fetchMockJest.getOnce("https://matrix.org/_matrix/media/r0/download/matrix.org/1234", "TESTFILE");
|
||||
fetchMock.getOnce("https://matrix.org/_matrix/media/r0/download/matrix.org/1234", "TESTFILE");
|
||||
|
||||
const event = new MatrixEvent({
|
||||
room_id: "!room:id",
|
||||
@ -106,7 +105,7 @@ describe("DownloadActionButton", () => {
|
||||
|
||||
stubClient();
|
||||
|
||||
fetchMockJest.getOnce("http://this.is.a.url/matrix.org/1234", "TESTFILE");
|
||||
fetchMock.getOnce("http://this.is.a.url/matrix.org/1234", "TESTFILE");
|
||||
|
||||
const mediaEventHelper = new MediaEventHelper(plainEvent);
|
||||
|
||||
@ -127,7 +126,7 @@ describe("DownloadActionButton", () => {
|
||||
|
||||
stubClient();
|
||||
|
||||
fetchMockJest.getOnce("http://this.is.a.url/matrix.org/1234", "UFTUGJMF");
|
||||
fetchMock.getOnce("http://this.is.a.url/matrix.org/1234", "UFTUGJMF");
|
||||
|
||||
const e2eEvent = new MatrixEvent({
|
||||
room_id: "!room:id",
|
||||
|
||||
@ -9,7 +9,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
import React from "react";
|
||||
import { fireEvent, render, screen, waitFor, waitForElementToBeRemoved, within } from "jest-matrix-react";
|
||||
import { EventType, getHttpUriForMxc, MatrixEvent, Room } from "matrix-js-sdk/src/matrix";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import encrypt from "matrix-encrypt-attachment";
|
||||
import { mocked } from "jest-mock";
|
||||
import fs from "fs";
|
||||
@ -121,7 +121,7 @@ describe("<MImageBody/>", () => {
|
||||
withClientContextRenderOptions(cli),
|
||||
);
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledWith(url);
|
||||
expect(fetchMock).toHaveFetched(url);
|
||||
|
||||
await screen.findByText("Error downloading image");
|
||||
});
|
||||
@ -167,7 +167,7 @@ describe("<MImageBody/>", () => {
|
||||
|
||||
expect(screen.getByText("Show image")).toBeInTheDocument();
|
||||
|
||||
expect(fetchMock).not.toHaveFetched(url);
|
||||
expect(fetchMock).toHaveFetchedTimes(0, url);
|
||||
});
|
||||
|
||||
it("should render hidden image placeholder", async () => {
|
||||
@ -246,13 +246,9 @@ describe("<MImageBody/>", () => {
|
||||
|
||||
mocked(global.URL.createObjectURL).mockReturnValue("blob:generated-thumb");
|
||||
|
||||
fetchMock.getOnce(
|
||||
"https://server/_matrix/media/v3/download/server/image",
|
||||
{
|
||||
body: fs.readFileSync(path.resolve(__dirname, "..", "..", "..", "images", "animated-logo.webp")),
|
||||
},
|
||||
{ sendAsJson: false },
|
||||
);
|
||||
fetchMock.getOnce("https://server/_matrix/media/v3/download/server/image", {
|
||||
body: fs.readFileSync(path.resolve(__dirname, "..", "..", "..", "images", "animated-logo.webp")),
|
||||
});
|
||||
|
||||
const event = new MatrixEvent({
|
||||
room_id: "!room:server",
|
||||
|
||||
@ -9,7 +9,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
import React from "react";
|
||||
import { render, screen } from "jest-matrix-react";
|
||||
import { EventType, getHttpUriForMxc, MatrixEvent, Room } from "matrix-js-sdk/src/matrix";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
|
||||
import { RoomPermalinkCreator } from "../../../../../src/utils/permalinks/Permalinks";
|
||||
|
||||
@ -9,7 +9,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
import React from "react";
|
||||
import { EventType, getHttpUriForMxc, type IContent, type MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix";
|
||||
import { fireEvent, render, screen } from "jest-matrix-react";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import { type MockedObject } from "jest-mock";
|
||||
|
||||
import MatrixClientContext from "../../../../../src/contexts/MatrixClientContext";
|
||||
@ -170,7 +170,7 @@ describe("MVideoBody", () => {
|
||||
|
||||
expect(screen.getByText("Show video")).toBeInTheDocument();
|
||||
|
||||
expect(fetchMock).not.toHaveFetched(thumbUrl);
|
||||
expect(fetchMock).toHaveFetchedTimes(0, thumbUrl);
|
||||
});
|
||||
|
||||
it("should render video poster after user consent", async () => {
|
||||
|
||||
@ -9,7 +9,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
import React from "react";
|
||||
import { render, type RenderResult } from "jest-matrix-react";
|
||||
import { type MatrixClient, type MatrixEvent, EventType, type Room, MsgType } from "matrix-js-sdk/src/matrix";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
@ -96,13 +96,9 @@ describe("MessageEvent", () => {
|
||||
}
|
||||
|
||||
function mockMedia() {
|
||||
fetchMock.getOnce(
|
||||
"https://server/_matrix/media/v3/download/server/image",
|
||||
{
|
||||
body: fs.readFileSync(path.resolve(__dirname, "..", "..", "..", "images", "animated-logo.webp")),
|
||||
},
|
||||
{ sendAsJson: false },
|
||||
);
|
||||
fetchMock.getOnce("https://server/_matrix/media/v3/download/server/image", {
|
||||
body: fs.readFileSync(path.resolve(__dirname, "..", "..", "..", "images", "animated-logo.webp")),
|
||||
});
|
||||
}
|
||||
|
||||
it("should render a TextualBody and an ImageBody", () => {
|
||||
|
||||
@ -19,6 +19,7 @@ import {
|
||||
mockClientMethodsUser,
|
||||
mockIntlDateTimeFormat,
|
||||
setupRoomWithPollEvents,
|
||||
unmockIntlDateTimeFormat,
|
||||
} from "../../../../../test-utils";
|
||||
|
||||
describe("<PollListItemEnded />", () => {
|
||||
@ -52,14 +53,14 @@ describe("<PollListItemEnded />", () => {
|
||||
const getComponent = (props: { event: MatrixEvent; poll: Poll }) =>
|
||||
render(<PollListItemEnded {...props} onClick={jest.fn()} />);
|
||||
|
||||
beforeEach(() => {
|
||||
beforeAll(() => {
|
||||
// mock default locale to en-GB and set timezone
|
||||
// so these tests run the same everywhere
|
||||
mockIntlDateTimeFormat();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
afterAll(() => {
|
||||
unmockIntlDateTimeFormat();
|
||||
});
|
||||
|
||||
it("renders a poll with no responses", async () => {
|
||||
|
||||
@ -56,7 +56,7 @@ exports[`RoomHeader dm does not show the face pile for DMs 1`] = `
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
aria-labelledby="_r_18c_"
|
||||
aria-labelledby="_r_12c_"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
@ -83,7 +83,7 @@ exports[`RoomHeader dm does not show the face pile for DMs 1`] = `
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
aria-labelledby="_r_18h_"
|
||||
aria-labelledby="_r_12h_"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
@ -98,7 +98,7 @@ exports[`RoomHeader dm does not show the face pile for DMs 1`] = `
|
||||
</button>
|
||||
<button
|
||||
aria-label="Threads"
|
||||
aria-labelledby="_r_18m_"
|
||||
aria-labelledby="_r_12m_"
|
||||
class="_icon-button_1pz9o_8"
|
||||
data-kind="primary"
|
||||
role="button"
|
||||
@ -125,7 +125,7 @@ exports[`RoomHeader dm does not show the face pile for DMs 1`] = `
|
||||
</button>
|
||||
<button
|
||||
aria-label="Room info"
|
||||
aria-labelledby="_r_18r_"
|
||||
aria-labelledby="_r_12r_"
|
||||
class="_icon-button_1pz9o_8"
|
||||
data-kind="primary"
|
||||
role="button"
|
||||
|
||||
@ -7,6 +7,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
import { type IEventRelation, type MatrixEvent } from "matrix-js-sdk/src/matrix";
|
||||
import { waitFor } from "jest-matrix-react";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
|
||||
import { TimelineRenderingType } from "../../../../../../../src/contexts/RoomContext";
|
||||
import { mkStubRoom, stubClient } from "../../../../../../test-utils";
|
||||
@ -27,7 +28,6 @@ const mockRoomState = {
|
||||
|
||||
const sendContentListToRoomSpy = jest.spyOn(ContentMessages.sharedInstance(), "sendContentListToRoom");
|
||||
const sendContentToRoomSpy = jest.spyOn(ContentMessages.sharedInstance(), "sendContentToRoom");
|
||||
const fetchSpy = jest.spyOn(window, "fetch");
|
||||
const logSpy = jest.spyOn(console, "log").mockImplementation(() => {});
|
||||
|
||||
describe("handleClipboardEvent", () => {
|
||||
@ -183,13 +183,12 @@ describe("handleClipboardEvent", () => {
|
||||
const mockEventRelation = {} as unknown as IEventRelation;
|
||||
handleClipboardEvent(originalEvent, originalEvent.clipboardData, mockRoomState, mockClient, mockEventRelation);
|
||||
|
||||
expect(fetchSpy).toHaveBeenCalledTimes(1);
|
||||
expect(fetchSpy).toHaveBeenCalledWith("blob:");
|
||||
expect(fetchMock).toHaveFetchedTimes(1, "blob:");
|
||||
});
|
||||
|
||||
it("calls error handler when fetch fails", async () => {
|
||||
const mockErrorMessage = "fetch failed";
|
||||
fetchSpy.mockRejectedValueOnce(mockErrorMessage);
|
||||
fetchMock.getOnce("blob:", { throws: new Error(mockErrorMessage) });
|
||||
const originalEvent = createMockClipboardEvent({
|
||||
type: "paste",
|
||||
clipboardData: {
|
||||
@ -214,12 +213,11 @@ describe("handleClipboardEvent", () => {
|
||||
});
|
||||
|
||||
it("calls sendContentToRoom when parsing is successful", async () => {
|
||||
fetchSpy.mockResolvedValueOnce({
|
||||
url: "test/file",
|
||||
fetchMock.get("test/file", {
|
||||
blob: () => {
|
||||
return Promise.resolve({ type: "image/jpeg" } as Blob);
|
||||
},
|
||||
} as Response);
|
||||
});
|
||||
|
||||
const originalEvent = createMockClipboardEvent({
|
||||
type: "paste",
|
||||
@ -251,12 +249,11 @@ describe("handleClipboardEvent", () => {
|
||||
});
|
||||
|
||||
it("calls error handler when parsing is not successful", async () => {
|
||||
fetchSpy.mockResolvedValueOnce({
|
||||
url: "test/file",
|
||||
fetchMock.get("test/file", {
|
||||
blob: () => {
|
||||
return Promise.resolve({ type: "image/jpeg" } as Blob);
|
||||
},
|
||||
} as Response);
|
||||
});
|
||||
const mockErrorMessage = "sendContentToRoom failed";
|
||||
sendContentToRoomSpy.mockRejectedValueOnce(mockErrorMessage);
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
import React from "react";
|
||||
import { render, waitFor } from "jest-matrix-react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
|
||||
import SetIdServer from "../../../../../src/components/views/settings/SetIdServer";
|
||||
import MatrixClientContext from "../../../../../src/contexts/MatrixClientContext";
|
||||
|
||||
@ -10,7 +10,7 @@ import React from "react";
|
||||
import { act, render, screen, waitFor } from "jest-matrix-react";
|
||||
import { mocked, type MockedObject } from "jest-mock";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
|
||||
import { ThemeChoicePanel } from "../../../../../src/components/views/settings/ThemeChoicePanel";
|
||||
import SettingsStore from "../../../../../src/settings/SettingsStore";
|
||||
|
||||
@ -10,7 +10,7 @@ import { render } from "jest-matrix-react";
|
||||
import { mocked } from "jest-mock";
|
||||
import { type IClientWellKnown, type IServerVersions, type MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
import React from "react";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
|
||||
import LoginWithQRSection from "../../../../../../src/components/views/settings/devices/LoginWithQRSection";
|
||||
import { MatrixClientPeg } from "../../../../../../src/MatrixClientPeg";
|
||||
|
||||
@ -34,7 +34,7 @@ import {
|
||||
type MatrixClient,
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
import { mocked, type MockedObject } from "jest-mock";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
|
||||
import {
|
||||
clearAllModals,
|
||||
@ -1645,7 +1645,7 @@ describe("<SessionManagerTab />", () => {
|
||||
],
|
||||
});
|
||||
mockCrypto.exportSecretsBundle = jest.fn();
|
||||
fetchMock.mock(delegatedAuthConfig.jwks_uri!, {
|
||||
fetchMock.route(delegatedAuthConfig.jwks_uri!, {
|
||||
status: 200,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
|
||||
@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import fetchMockJest from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import { mocked } from "jest-mock";
|
||||
|
||||
import { mediaFromMxc } from "../../../src/customisations/Media";
|
||||
@ -20,7 +20,7 @@ describe("Media", () => {
|
||||
(mxc) => `https://matrix.org/_matrix/media/r0/download/${mxc.slice(6)}`,
|
||||
);
|
||||
|
||||
fetchMockJest.get("https://matrix.org/_matrix/media/r0/download/matrix.org/1234", {
|
||||
fetchMock.get("https://matrix.org/_matrix/media/r0/download/matrix.org/1234", {
|
||||
status: 404,
|
||||
body: { errcode: "M_NOT_FOUND", error: "Not found" },
|
||||
});
|
||||
|
||||
@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import { type Translation } from "matrix-web-i18n";
|
||||
import { type TranslationStringsObject } from "@matrix-org/react-sdk-module-api";
|
||||
|
||||
@ -28,7 +28,6 @@ import {
|
||||
getLanguagesFromBrowser,
|
||||
} from "../../src/languageHandler";
|
||||
import { stubClient } from "../test-utils";
|
||||
import { setupLanguageMock } from "../setup/setupLanguage";
|
||||
|
||||
async function setupTranslationOverridesForTests(overrides: TranslationStringsObject) {
|
||||
const lookupUrl = "/translations.json";
|
||||
@ -167,15 +166,13 @@ describe("languageHandler", () => {
|
||||
|
||||
describe("getAllLanguagesWithLabels", () => {
|
||||
it("should handle unknown language sanely", async () => {
|
||||
fetchMock.getOnce(
|
||||
"/i18n/languages.json",
|
||||
{
|
||||
fetchMock.modifyRoute("languages", {
|
||||
response: {
|
||||
en: "en_EN.json",
|
||||
de: "de_DE.json",
|
||||
qq: "qq.json",
|
||||
},
|
||||
{ overwriteRoutes: true },
|
||||
);
|
||||
});
|
||||
await expect(getAllLanguagesWithLabels()).resolves.toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
@ -195,7 +192,6 @@ describe("languageHandler", () => {
|
||||
},
|
||||
]
|
||||
`);
|
||||
setupLanguageMock(); // restore language mock
|
||||
});
|
||||
});
|
||||
|
||||
@ -290,10 +286,10 @@ describe("languageHandler JSX", function () {
|
||||
});
|
||||
|
||||
describe("when translations exist in language", () => {
|
||||
beforeEach(function () {
|
||||
beforeEach(async () => {
|
||||
stubClient();
|
||||
|
||||
setLanguage("en");
|
||||
await setLanguage("en");
|
||||
setMissingEntryGenerator((key) => key.split("|", 2)[1]);
|
||||
});
|
||||
|
||||
@ -326,10 +322,10 @@ describe("languageHandler JSX", function () {
|
||||
});
|
||||
|
||||
describe("for a non-en language", () => {
|
||||
beforeEach(() => {
|
||||
beforeEach(async () => {
|
||||
stubClient();
|
||||
setLanguage("lv");
|
||||
// counterpart doesnt expose any way to restore default config
|
||||
await setLanguage("lv");
|
||||
// counterpart doesn't expose any way to restore default config
|
||||
// missingEntryGenerator is mocked in the root setup file
|
||||
// reset to default here
|
||||
const counterpartDefaultMissingEntryGen = function (key: string) {
|
||||
|
||||
@ -481,7 +481,14 @@ describe("ElementCall", () => {
|
||||
let alice: RoomMember;
|
||||
let roomSession: Mocked<MatrixRTCSession>;
|
||||
function setRoomMembers(memberIds: string[]) {
|
||||
jest.spyOn(room, "getJoinedMembers").mockReturnValue(memberIds.map((id) => ({ userId: id }) as RoomMember));
|
||||
jest.spyOn(room, "getJoinedMembers").mockReturnValue(
|
||||
memberIds.map(
|
||||
(id) =>
|
||||
({
|
||||
userId: id,
|
||||
}) as RoomMember,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import fetchMockJest from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import { ClientEvent, MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import { SettingLevel } from "../../../../src/settings/SettingLevel";
|
||||
@ -15,7 +15,7 @@ import SettingsStore from "../../../../src/settings/SettingsStore.ts";
|
||||
|
||||
describe("FallbackIceServerController", () => {
|
||||
beforeEach(() => {
|
||||
fetchMockJest.get("https://matrix.org/_matrix/client/versions", { versions: ["v1.4"] });
|
||||
fetchMock.get("https://matrix.org/_matrix/client/versions", { versions: ["v1.4"] });
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
||||
@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import { mocked } from "jest-mock";
|
||||
import { OidcClient } from "oidc-client-ts";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
@ -188,13 +188,14 @@ describe("OidcClientStore", () => {
|
||||
// spy and call through
|
||||
jest.spyOn(OidcClient.prototype, "revokeToken").mockClear();
|
||||
|
||||
fetchMock.resetHistory();
|
||||
fetchMock.clearHistory();
|
||||
fetchMock.removeRoute("revocation-endpoint");
|
||||
fetchMock.post(
|
||||
authConfig.revocation_endpoint,
|
||||
{
|
||||
status: 200,
|
||||
},
|
||||
{ sendAsJson: true },
|
||||
{ name: "revocation-endpoint" },
|
||||
);
|
||||
});
|
||||
|
||||
@ -219,21 +220,14 @@ describe("OidcClientStore", () => {
|
||||
|
||||
it("should still attempt to revoke refresh token when access token revocation fails", async () => {
|
||||
// fail once, then succeed
|
||||
fetchMock.removeRoute("revocation-endpoint");
|
||||
fetchMock
|
||||
.postOnce(
|
||||
authConfig.revocation_endpoint,
|
||||
{
|
||||
status: 404,
|
||||
},
|
||||
{ overwriteRoutes: true, sendAsJson: true },
|
||||
)
|
||||
.post(
|
||||
authConfig.revocation_endpoint,
|
||||
{
|
||||
status: 200,
|
||||
},
|
||||
{ sendAsJson: true },
|
||||
);
|
||||
.postOnce(authConfig.revocation_endpoint, {
|
||||
status: 404,
|
||||
})
|
||||
.post(authConfig.revocation_endpoint, {
|
||||
status: 200,
|
||||
});
|
||||
|
||||
const store = new OidcClientStore(mockClient);
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { mocked, type MockedObject } from "jest-mock";
|
||||
import fetchMockJest from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import {
|
||||
type MatrixClient,
|
||||
ClientEvent,
|
||||
@ -792,7 +792,7 @@ describe("ElementWidgetDriver", () => {
|
||||
return null;
|
||||
});
|
||||
|
||||
fetchMockJest.get("https://example.com/_matrix/media/v3/download/example.com/test_file", "test contents");
|
||||
fetchMock.get("https://example.com/_matrix/media/v3/download/example.com/test_file", "test contents");
|
||||
|
||||
const result = await driver.downloadFile("mxc://example.com/test_file");
|
||||
// A type test is impossible here because of
|
||||
|
||||
@ -15,7 +15,7 @@ import {
|
||||
TypedEventEmitter,
|
||||
MatrixHttpApi,
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
|
||||
import { getMockClientWithEventEmitter, mockClientMethodsCrypto, mockPlatformPeg } from "../test-utils";
|
||||
import { collectBugReport } from "../../src/rageshake/submit-rageshake";
|
||||
@ -34,8 +34,6 @@ describe("Rageshakes", () => {
|
||||
onlyData: true,
|
||||
},
|
||||
);
|
||||
let windowSpy: jest.SpyInstance;
|
||||
let mockWindow: Mocked<Window>;
|
||||
|
||||
beforeEach(() => {
|
||||
mockClient = getMockClientWithEventEmitter({
|
||||
@ -51,21 +49,8 @@ describe("Rageshakes", () => {
|
||||
ed25519: "",
|
||||
curve25519: "",
|
||||
});
|
||||
mockWindow = {
|
||||
matchMedia: jest.fn().mockReturnValue({ matches: false }),
|
||||
navigator: {
|
||||
userAgent: "",
|
||||
},
|
||||
} as unknown as Mocked<Window>;
|
||||
// @ts-ignore - We just need partial mock
|
||||
windowSpy = jest.spyOn(global, "window", "get").mockReturnValue(mockWindow);
|
||||
|
||||
fetchMock.restore();
|
||||
fetchMock.catch(404);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
windowSpy.mockRestore();
|
||||
jest.spyOn(window, "matchMedia").mockReturnValue({ matches: false } as any);
|
||||
});
|
||||
|
||||
describe("Basic Information", () => {
|
||||
@ -97,7 +82,7 @@ describe("Rageshakes", () => {
|
||||
];
|
||||
|
||||
it.each(mediaQueryTests)("should collect %s", async (_, query, label, matches) => {
|
||||
mocked(mockWindow.matchMedia).mockImplementation((q): MediaQueryList => {
|
||||
mocked(window.matchMedia).mockImplementation((q): MediaQueryList => {
|
||||
if (q === query) {
|
||||
return { matches: matches } as unknown as MediaQueryList;
|
||||
}
|
||||
@ -139,13 +124,13 @@ describe("Rageshakes", () => {
|
||||
});
|
||||
|
||||
it("should collect user agent", async () => {
|
||||
jest.replaceProperty(mockWindow.navigator, "userAgent", "jest navigator");
|
||||
jest.spyOn(window.navigator, "userAgent", "get").mockReturnValue("jest navigator");
|
||||
const formData = await collectBugReport();
|
||||
const userAgent = formData.get("user_agent");
|
||||
expect(userAgent).toBe("jest navigator");
|
||||
|
||||
// @ts-ignore - Need to force navigator to be undefined for test
|
||||
jest.replaceProperty(mockWindow, "navigator", undefined);
|
||||
jest.spyOn(window.navigator, "userAgent", "get").mockReturnValue(undefined);
|
||||
const formDataWithoutNav = await collectBugReport();
|
||||
expect(formDataWithoutNav.get("user_agent")).toBe("UNKNOWN");
|
||||
});
|
||||
@ -308,10 +293,6 @@ describe("Rageshakes", () => {
|
||||
});
|
||||
|
||||
describe("Synapse info", () => {
|
||||
beforeEach(() => {
|
||||
fetchMock.reset();
|
||||
});
|
||||
|
||||
it("should collect synapse admin keys if available", async () => {
|
||||
fetchMock.get("path:/_synapse/admin/v1/server_version", {
|
||||
server_version: "1.101.0 (b=matrix-org-hotfixes,6dbedcf601)",
|
||||
@ -443,11 +424,9 @@ describe("Rageshakes", () => {
|
||||
// @ts-ignore - Need to mock the safari
|
||||
jest.replaceProperty(mockNavigator, "storage", undefined);
|
||||
|
||||
const mockDocument = {
|
||||
const spy = jest.spyOn(global, "document", "get").mockReturnValue({
|
||||
hasStorageAccess: jest.fn().mockReturnValue(true),
|
||||
} as unknown as Mocked<Document>;
|
||||
|
||||
const spy = jest.spyOn(global, "document", "get").mockReturnValue(mockDocument);
|
||||
} as any);
|
||||
|
||||
const formData = await collectBugReport();
|
||||
expect(formData.get("storageManager_persisted")).toBe("true");
|
||||
@ -487,14 +466,12 @@ describe("Rageshakes", () => {
|
||||
crypto: true,
|
||||
};
|
||||
const disabledFeatures = ["cssanimations", "d0", "d1"];
|
||||
const mockWindow = {
|
||||
const windowSpy = jest.spyOn(global, "window", "get").mockReturnValue({
|
||||
matchMedia: jest.fn().mockReturnValue({ matches: false }),
|
||||
Modernizr: {
|
||||
...allFeatures,
|
||||
},
|
||||
} as unknown as Mocked<Window>;
|
||||
// @ts-ignore - We just need partial mock
|
||||
const windowSpy = jest.spyOn(global, "window", "get").mockReturnValue(mockWindow);
|
||||
} as any);
|
||||
|
||||
const formData = await collectBugReport();
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import { AutoDiscovery, AutoDiscoveryAction, type ClientConfig } from "matrix-js-sdk/src/matrix";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
|
||||
import AutoDiscoveryUtils from "../../../src/utils/AutoDiscoveryUtils";
|
||||
import { mockOpenIdConfiguration } from "../../test-utils/oidc";
|
||||
@ -152,7 +152,7 @@ describe("AutoDiscoveryUtils", () => {
|
||||
};
|
||||
await expect(() =>
|
||||
AutoDiscoveryUtils.buildValidatedConfigFromDiscovery(serverName, discoveryResult),
|
||||
).rejects.toThrow("Invalid URL: banana");
|
||||
).rejects.toThrow("Invalid URL");
|
||||
});
|
||||
|
||||
it("uses hs url hostname when serverName is falsy in args and config", async () => {
|
||||
|
||||
@ -6,7 +6,6 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import "core-js/stable/structured-clone"; // for idb access
|
||||
import "fake-indexeddb/auto";
|
||||
|
||||
import { idbDelete, idbLoad, idbSave } from "../../../src/utils/StorageAccess";
|
||||
|
||||
@ -20,7 +20,7 @@ import {
|
||||
RoomMember,
|
||||
RoomState,
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import escapeHtml from "escape-html";
|
||||
import { type RelationsContainer } from "matrix-js-sdk/src/models/relations-container";
|
||||
import { mocked } from "jest-mock";
|
||||
|
||||
@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import { mocked } from "jest-mock";
|
||||
|
||||
import { TokenRefresher } from "../../../../src/utils/oidc/TokenRefresher";
|
||||
|
||||
@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import { completeAuthorizationCodeGrant } from "matrix-js-sdk/src/oidc/authorize";
|
||||
import * as randomStringUtils from "matrix-js-sdk/src/randomstring";
|
||||
import { type BearerTokenResponse } from "matrix-js-sdk/src/oidc/validate";
|
||||
@ -58,9 +58,7 @@ describe("OIDC authorization", () => {
|
||||
subtle: webCrypto.subtle,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
beforeAll(() => {
|
||||
fetchMock.get(`${delegatedAuthConfig.issuer}.well-known/openid-configuration`, delegatedAuthConfig);
|
||||
});
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import fetchMockJest from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import { OidcError } from "matrix-js-sdk/src/oidc/error";
|
||||
import { type OidcClientConfig } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
@ -28,8 +28,7 @@ describe("getOidcClientId()", () => {
|
||||
const delegatedAuthConfig = makeDelegatedAuthConfig(issuer);
|
||||
|
||||
beforeEach(() => {
|
||||
fetchMockJest.mockClear();
|
||||
fetchMockJest.resetBehavior();
|
||||
fetchMock.removeRoutes();
|
||||
mockPlatformPeg();
|
||||
Object.defineProperty(PlatformPeg.get(), "baseUrl", {
|
||||
get(): string {
|
||||
@ -51,7 +50,7 @@ describe("getOidcClientId()", () => {
|
||||
it("should return static clientId when configured", async () => {
|
||||
expect(await getOidcClientId(delegatedAuthConfig, staticOidcClients)).toEqual("abc123");
|
||||
// didn't try to register
|
||||
expect(fetchMockJest).toHaveFetchedTimes(0);
|
||||
expect(fetchMock).toHaveFetchedTimes(0);
|
||||
});
|
||||
|
||||
it("should throw when no static clientId is configured and no registration endpoint", async () => {
|
||||
@ -63,7 +62,7 @@ describe("getOidcClientId()", () => {
|
||||
OidcError.DynamicRegistrationNotSupported,
|
||||
);
|
||||
// didn't try to register
|
||||
expect(fetchMockJest).toHaveFetchedTimes(0);
|
||||
expect(fetchMock).toHaveFetchedTimes(0);
|
||||
});
|
||||
|
||||
it("should handle when staticOidcClients object is falsy", async () => {
|
||||
@ -75,28 +74,23 @@ describe("getOidcClientId()", () => {
|
||||
OidcError.DynamicRegistrationNotSupported,
|
||||
);
|
||||
// didn't try to register
|
||||
expect(fetchMockJest).toHaveFetchedTimes(0);
|
||||
expect(fetchMock).toHaveFetchedTimes(0);
|
||||
});
|
||||
|
||||
it("should make correct request to register client", async () => {
|
||||
fetchMockJest.post(delegatedAuthConfig.registration_endpoint!, {
|
||||
fetchMock.post(delegatedAuthConfig.registration_endpoint!, {
|
||||
status: 200,
|
||||
body: JSON.stringify({ client_id: dynamicClientId }),
|
||||
});
|
||||
expect(await getOidcClientId(delegatedAuthConfig)).toEqual(dynamicClientId);
|
||||
// didn't try to register
|
||||
expect(fetchMockJest).toHaveBeenCalledWith(
|
||||
delegatedAuthConfig.registration_endpoint!,
|
||||
expect.objectContaining({
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
method: "POST",
|
||||
}),
|
||||
);
|
||||
expect(JSON.parse(fetchMockJest.mock.calls[0][1]!.body as string)).toEqual(
|
||||
expect.objectContaining({
|
||||
expect(fetchMock).toHaveFetched(delegatedAuthConfig.registration_endpoint!, {
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
method: "POST",
|
||||
body: {
|
||||
client_name: clientName,
|
||||
client_uri: baseUrl,
|
||||
response_types: ["code"],
|
||||
@ -106,19 +100,19 @@ describe("getOidcClientId()", () => {
|
||||
token_endpoint_auth_method: "none",
|
||||
application_type: "web",
|
||||
logo_uri: `${baseUrl}/vector-icons/1024.png`,
|
||||
}),
|
||||
);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("should throw when registration request fails", async () => {
|
||||
fetchMockJest.post(delegatedAuthConfig.registration_endpoint!, {
|
||||
fetchMock.post(delegatedAuthConfig.registration_endpoint!, {
|
||||
status: 500,
|
||||
});
|
||||
await expect(getOidcClientId(delegatedAuthConfig)).rejects.toThrow(OidcError.DynamicRegistrationFailed);
|
||||
});
|
||||
|
||||
it("should throw when registration response is invalid", async () => {
|
||||
fetchMockJest.post(delegatedAuthConfig.registration_endpoint!, {
|
||||
fetchMock.post(delegatedAuthConfig.registration_endpoint!, {
|
||||
status: 200,
|
||||
// no clientId in response
|
||||
body: "{}",
|
||||
|
||||
@ -6,12 +6,10 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
|
||||
import { getVectorConfig } from "../../../src/vector/getconfig";
|
||||
|
||||
fetchMock.config.overwriteRoutes = true;
|
||||
|
||||
describe("getVectorConfig()", () => {
|
||||
const elementDomain = "app.element.io";
|
||||
const now = 1234567890;
|
||||
@ -31,7 +29,7 @@ describe("getVectorConfig()", () => {
|
||||
// stable value for cachebuster
|
||||
jest.spyOn(Date, "now").mockReturnValue(now);
|
||||
jest.clearAllMocks();
|
||||
fetchMock.mockClear();
|
||||
fetchMock.removeRoutes();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
@ -39,15 +37,15 @@ describe("getVectorConfig()", () => {
|
||||
});
|
||||
|
||||
it("requests specific config for document domain", async () => {
|
||||
fetchMock.getOnce("express:/config.app.element.io.json", specificConfig);
|
||||
fetchMock.getOnce("express:/config.json", generalConfig);
|
||||
fetchMock.getOnce("express:/config.app.element.io.json*", specificConfig);
|
||||
fetchMock.getOnce("express:/config.json*", generalConfig);
|
||||
|
||||
await expect(getVectorConfig()).resolves.toEqual(specificConfig);
|
||||
});
|
||||
|
||||
it("adds trailing slash to relativeLocation when not an empty string", async () => {
|
||||
fetchMock.getOnce("express:../config.app.element.io.json", specificConfig);
|
||||
fetchMock.getOnce("express:../config.json", generalConfig);
|
||||
fetchMock.getOnce("express:/config.app.element.io.json", specificConfig);
|
||||
fetchMock.getOnce("express:/config.json", generalConfig);
|
||||
|
||||
await expect(getVectorConfig("..")).resolves.toEqual(specificConfig);
|
||||
});
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @jest-environment jsdom
|
||||
* @jest-environment jest-fixed-jsdom
|
||||
* @jest-environment-options {"url": "https://app.element.io/?loginToken=123&state=abc&code=xyz&no_universal_links&something_else=value"}
|
||||
*/
|
||||
|
||||
@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import { waitFor, screen } from "jest-matrix-react";
|
||||
|
||||
import { loadApp, showError, showIncompatibleBrowser } from "../../../src/vector/init.tsx";
|
||||
|
||||
@ -19,7 +19,6 @@ import { BreadcrumbsStore } from "../../../../src/stores/BreadcrumbsStore";
|
||||
import Modal from "../../../../src/Modal";
|
||||
import DesktopCapturerSourcePicker from "../../../../src/components/views/elements/DesktopCapturerSourcePicker";
|
||||
import ElectronPlatform from "../../../../src/vector/platform/ElectronPlatform";
|
||||
import { setupLanguageMock } from "../../../setup/setupLanguage";
|
||||
import { stubClient } from "../../../test-utils";
|
||||
import ToastStore from "../../../../src/stores/ToastStore.ts";
|
||||
|
||||
@ -57,7 +56,6 @@ describe("ElectronPlatform", () => {
|
||||
window.electron = mockElectron;
|
||||
jest.clearAllMocks();
|
||||
Object.defineProperty(window, "navigator", { value: { userAgent: defaultUserAgent }, writable: true });
|
||||
setupLanguageMock();
|
||||
});
|
||||
|
||||
const getElectronEventHandlerCall = (
|
||||
@ -456,7 +454,7 @@ describe("ElectronPlatform", () => {
|
||||
await waitFor(() => {
|
||||
const ipcMessage = mockElectron.send.mock.lastCall;
|
||||
expect(ipcMessage?.[1]).toEqual(1);
|
||||
expect(ipcMessage?.[2] instanceof ArrayBuffer).toEqual(true);
|
||||
expect(ipcMessage?.[2].constructor.name).toEqual("ArrayBuffer");
|
||||
});
|
||||
});
|
||||
|
||||
@ -473,10 +471,10 @@ describe("ElectronPlatform", () => {
|
||||
);
|
||||
|
||||
expect(ipcMessageA?.[1]).toEqual(1);
|
||||
expect(ipcMessageA?.[2] instanceof ArrayBuffer).toEqual(true);
|
||||
expect(ipcMessageA?.[2].constructor.name).toEqual("ArrayBuffer");
|
||||
|
||||
expect(ipcMessageB?.[1]).toEqual(2);
|
||||
expect(ipcMessageB?.[2] instanceof ArrayBuffer).toEqual(true);
|
||||
expect(ipcMessageB?.[2].constructor.name).toEqual("ArrayBuffer");
|
||||
});
|
||||
});
|
||||
it("should remove badge when notification count zeros", async () => {
|
||||
@ -491,7 +489,7 @@ describe("ElectronPlatform", () => {
|
||||
);
|
||||
|
||||
expect(ipcMessageA?.[1]).toEqual(1);
|
||||
expect(ipcMessageA?.[2] instanceof ArrayBuffer).toEqual(true);
|
||||
expect(ipcMessageA?.[2].constructor.name).toEqual("ArrayBuffer");
|
||||
|
||||
expect(ipcMessageB?.[1]).toEqual(0);
|
||||
expect(ipcMessageB?.[2]).toBeNull();
|
||||
@ -506,7 +504,7 @@ describe("ElectronPlatform", () => {
|
||||
const ipcMessage = mockElectron.send.mock.calls.find((call) => call[0] === "setBadgeCount");
|
||||
|
||||
expect(ipcMessage?.[1]).toEqual(0);
|
||||
expect(ipcMessage?.[2] instanceof ArrayBuffer).toEqual(true);
|
||||
expect(ipcMessage?.[2].constructor.name).toEqual("ArrayBuffer");
|
||||
expect(ipcMessage?.[3]).toEqual(true);
|
||||
});
|
||||
});
|
||||
@ -522,7 +520,7 @@ describe("ElectronPlatform", () => {
|
||||
);
|
||||
|
||||
expect(ipcMessageA?.[1]).toEqual(0);
|
||||
expect(ipcMessageA?.[2] instanceof ArrayBuffer).toEqual(true);
|
||||
expect(ipcMessageA?.[2].constructor.name).toEqual("ArrayBuffer");
|
||||
expect(ipcMessageA?.[3]).toEqual(true);
|
||||
|
||||
expect(ipcMessageB?.[1]).toEqual(0);
|
||||
|
||||
@ -6,23 +6,28 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
|
||||
import { UpdateCheckStatus } from "../../../../src/BasePlatform";
|
||||
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
|
||||
import WebPlatform from "../../../../src/vector/platform/WebPlatform";
|
||||
import { setupLanguageMock } from "../../../setup/setupLanguage";
|
||||
import ToastStore from "../../../../src/stores/ToastStore.ts";
|
||||
import defaultDispatcher from "../../../../src/dispatcher/dispatcher.ts";
|
||||
import { emitPromise } from "../../../test-utils";
|
||||
import { Action } from "../../../../src/dispatcher/actions.ts";
|
||||
|
||||
fetchMock.config.overwriteRoutes = true;
|
||||
|
||||
describe("WebPlatform", () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
setupLanguageMock();
|
||||
jest.spyOn(global, "navigator", "get").mockReturnValue({
|
||||
...navigator,
|
||||
// @ts-expect-error - mocking readonly object
|
||||
serviceWorker: {
|
||||
register: jest.fn().mockResolvedValue({
|
||||
update: jest.fn(),
|
||||
}),
|
||||
addEventListener: jest.fn(),
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("returns human readable name", () => {
|
||||
@ -32,22 +37,17 @@ describe("WebPlatform", () => {
|
||||
|
||||
describe("service worker", () => {
|
||||
it("registers successfully", () => {
|
||||
// @ts-expect-error - mocking readonly object
|
||||
navigator.serviceWorker = {
|
||||
register: jest.fn().mockResolvedValue({
|
||||
update: jest.fn(),
|
||||
}),
|
||||
addEventListener: jest.fn(),
|
||||
};
|
||||
new WebPlatform();
|
||||
expect(navigator.serviceWorker.register).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("handles errors", async () => {
|
||||
// @ts-expect-error - mocking readonly object
|
||||
navigator.serviceWorker = {
|
||||
register: undefined,
|
||||
};
|
||||
jest.spyOn(global, "navigator", "get").mockReturnValue({
|
||||
serviceWorker: {
|
||||
// @ts-expect-error - mocking readonly object
|
||||
register: undefined,
|
||||
},
|
||||
});
|
||||
new WebPlatform();
|
||||
|
||||
defaultDispatcher.dispatch({ action: Action.ClientStarted });
|
||||
@ -85,7 +85,7 @@ describe("WebPlatform", () => {
|
||||
"develop.element.io: Chrome on macOS",
|
||||
],
|
||||
])("%s & %s = %s", (url, userAgent, result) => {
|
||||
Object.defineProperty(window, "navigator", { value: { userAgent }, writable: true });
|
||||
jest.spyOn(global, "navigator", "get").mockReturnValue({ userAgent } as Navigator);
|
||||
Object.defineProperty(window, "location", { value: { href: url }, writable: true });
|
||||
const platform = new WebPlatform();
|
||||
expect(platform.getDefaultDeviceDisplayName()).toEqual(result);
|
||||
@ -174,7 +174,7 @@ describe("WebPlatform", () => {
|
||||
it("should return not available and call showNoUpdate when current version matches most recent version", async () => {
|
||||
// @ts-ignore
|
||||
WebPlatform.VERSION = prodVersion;
|
||||
fetchMock.getOnce("/version", prodVersion);
|
||||
fetchMock.getOnce("end:/version", prodVersion);
|
||||
const platform = new WebPlatform();
|
||||
|
||||
const showUpdate = jest.fn();
|
||||
@ -189,7 +189,7 @@ describe("WebPlatform", () => {
|
||||
it("should strip v prefix from versions before comparing", async () => {
|
||||
// @ts-ignore
|
||||
WebPlatform.VERSION = prodVersion;
|
||||
fetchMock.getOnce("/version", `v${prodVersion}`);
|
||||
fetchMock.getOnce("end:/version", `v${prodVersion}`);
|
||||
const platform = new WebPlatform();
|
||||
|
||||
const showUpdate = jest.fn();
|
||||
@ -207,7 +207,7 @@ describe("WebPlatform", () => {
|
||||
async () => {
|
||||
// @ts-ignore
|
||||
WebPlatform.VERSION = "0.0.0"; // old version
|
||||
fetchMock.getOnce("/version", prodVersion);
|
||||
fetchMock.getOnce("end:/version", prodVersion);
|
||||
const platform = new WebPlatform();
|
||||
|
||||
const showUpdate = jest.fn();
|
||||
@ -224,7 +224,7 @@ describe("WebPlatform", () => {
|
||||
// @ts-ignore
|
||||
WebPlatform.VERSION = "0.0.0"; // old version
|
||||
jest.spyOn(MatrixClientPeg, "userRegisteredWithinLastHours").mockReturnValue(true);
|
||||
fetchMock.getOnce("/version", prodVersion);
|
||||
fetchMock.getOnce("end:/version", prodVersion);
|
||||
const platform = new WebPlatform();
|
||||
|
||||
const showUpdate = jest.fn();
|
||||
@ -237,7 +237,7 @@ describe("WebPlatform", () => {
|
||||
});
|
||||
|
||||
it("should return error when version check fails", async () => {
|
||||
fetchMock.getOnce("/version", { throws: "oups" });
|
||||
fetchMock.getOnce("end:/version", { throws: "oups" });
|
||||
const platform = new WebPlatform();
|
||||
|
||||
const showUpdate = jest.fn();
|
||||
|
||||
@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import { Room } from "matrix-js-sdk/src/matrix";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
|
||||
import { addManagedHybridWidget, isManagedHybridWidgetEnabled } from "../../../src/widgets/ManagedHybrid";
|
||||
import { stubClient } from "../../test-utils";
|
||||
@ -63,7 +63,7 @@ describe("addManagedHybridWidget", () => {
|
||||
fetchMock.mockClear();
|
||||
await addManagedHybridWidget(room);
|
||||
expect(logSpy).toHaveBeenCalledWith("User not allowed to modify widgets in !room:server");
|
||||
expect(fetchMock).toHaveBeenCalledTimes(0);
|
||||
expect(fetchMock).toHaveFetchedTimes(0);
|
||||
});
|
||||
|
||||
it("should noop if no widget_build_url", async () => {
|
||||
@ -71,7 +71,7 @@ describe("addManagedHybridWidget", () => {
|
||||
|
||||
fetchMock.mockClear();
|
||||
await addManagedHybridWidget(room);
|
||||
expect(fetchMock).toHaveBeenCalledTimes(0);
|
||||
expect(fetchMock).toHaveFetchedTimes(0);
|
||||
});
|
||||
|
||||
it("should add the widget successfully", async () => {
|
||||
@ -87,7 +87,7 @@ describe("addManagedHybridWidget", () => {
|
||||
});
|
||||
|
||||
await addManagedHybridWidget(room);
|
||||
expect(fetchMock).toHaveBeenCalledWith("https://widget-build-url?roomId=!room:server");
|
||||
expect(fetchMock).toHaveFetched("https://widget-build-url?roomId=!room:server");
|
||||
expect(setRoomWidgetContentSpy).toHaveBeenCalledWith(room.client, room.roomId, "WIDGET_ID", {
|
||||
"key": "value",
|
||||
"io.element.managed_hybrid": true,
|
||||
|
||||
110
yarn.lock
110
yarn.lock
@ -51,7 +51,7 @@
|
||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.28.5.tgz#a8a4962e1567121ac0b3b487f52107443b455c7f"
|
||||
integrity sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==
|
||||
|
||||
"@babel/core@^7.0.0", "@babel/core@^7.12.10", "@babel/core@^7.18.5", "@babel/core@^7.21.3", "@babel/core@^7.23.9", "@babel/core@^7.24.4", "@babel/core@^7.27.4", "@babel/core@^7.28.0":
|
||||
"@babel/core@^7.12.10", "@babel/core@^7.18.5", "@babel/core@^7.21.3", "@babel/core@^7.23.9", "@babel/core@^7.24.4", "@babel/core@^7.27.4", "@babel/core@^7.28.0":
|
||||
version "7.28.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.28.5.tgz#4c81b35e51e1b734f510c99b07dfbc7bbbb48f7e"
|
||||
integrity sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==
|
||||
@ -1771,6 +1771,13 @@
|
||||
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.1.tgz#de633db3ec2ef6a3c89e2f19038063e8a122e2c2"
|
||||
integrity sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==
|
||||
|
||||
"@fetch-mock/jest@^0.2.20":
|
||||
version "0.2.20"
|
||||
resolved "https://registry.yarnpkg.com/@fetch-mock/jest/-/jest-0.2.20.tgz#85dc2dd9afb9022a6e0eda1d9f3351f3a5fa70c5"
|
||||
integrity sha512-DGX2bhBInodaWPMV3+UZ530aVM3wDj16sAPjFzkrwb0JwNWIQK07CNbYprQ3Tmd2ixDJeaNx2E0aNb+hRb8FFA==
|
||||
dependencies:
|
||||
fetch-mock "^12.6.0"
|
||||
|
||||
"@floating-ui/core@^1.7.3":
|
||||
version "1.7.3"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.7.3.tgz#462d722f001e23e46d86fd2bd0d21b7693ccb8b7"
|
||||
@ -3546,7 +3553,7 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.16.tgz#8ebe53d69efada7044454e3305c19017d97ced2a"
|
||||
integrity sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==
|
||||
|
||||
"@types/glob-to-regexp@^0.4.1":
|
||||
"@types/glob-to-regexp@^0.4.1", "@types/glob-to-regexp@^0.4.4":
|
||||
version "0.4.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/glob-to-regexp/-/glob-to-regexp-0.4.4.tgz#409e71290253203185b1ea8a3d6ea406a4bdc902"
|
||||
integrity sha512-nDKoaKJYbnn1MZxUY0cA1bPmmgZbg0cTq7Rh13d0KWYNOiKbqoR+2d89SnRPszGh7ROzSwZ/GOjZ4jPbmmZ6Eg==
|
||||
@ -3657,14 +3664,6 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/modernizr/-/modernizr-3.5.6.tgz#c50d64a73edc30284679f09ad54e7d095e69f2a0"
|
||||
integrity sha512-yslwR0zZ3zAT1qXcCPxIcD23CZ6W6nKsl6JufSJHAmdwOBuYwCVJkaMsEo9yzxGV7ATfoX8S+RgtnajOEtKxYA==
|
||||
|
||||
"@types/node-fetch@^2.6.2":
|
||||
version "2.6.13"
|
||||
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.13.tgz#e0c9b7b5edbdb1b50ce32c127e85e880872d56ee"
|
||||
integrity sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
form-data "^4.0.4"
|
||||
|
||||
"@types/node-forge@^1.3.0":
|
||||
version "1.3.11"
|
||||
resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-1.3.11.tgz#0972ea538ddb0f4d9c2fa0ec5db5724773a604da"
|
||||
@ -5653,7 +5652,7 @@ core-js-compat@^3.43.0:
|
||||
dependencies:
|
||||
browserslist "^4.26.3"
|
||||
|
||||
core-js@^3.0.0, core-js@^3.38.1:
|
||||
core-js@^3.38.1:
|
||||
version "3.47.0"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.47.0.tgz#436ef07650e191afeb84c24481b298bd60eb4a17"
|
||||
integrity sha512-c3Q2VVkGAUyupsjRnaNX6u8Dq2vAdzm9iuPj5FW0fRxzlxgq9Q39MDq10IvmQSpLgHQNyQzQmOo6bgGHmH3NNg==
|
||||
@ -7234,28 +7233,15 @@ fdir@^6.4.4, fdir@^6.5.0:
|
||||
resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350"
|
||||
integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==
|
||||
|
||||
fetch-mock-jest@^1.5.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/fetch-mock-jest/-/fetch-mock-jest-1.5.1.tgz#0e13df990d286d9239e284f12b279ed509bf53cd"
|
||||
integrity sha512-+utwzP8C+Pax1GSka3nFXILWMY3Er2L+s090FOgqVNrNCPp0fDqgXnAHAJf12PLHi0z4PhcTaZNTz8e7K3fjqQ==
|
||||
fetch-mock@12, fetch-mock@^12.6.0:
|
||||
version "12.6.0"
|
||||
resolved "https://registry.yarnpkg.com/fetch-mock/-/fetch-mock-12.6.0.tgz#e5ed5d471eeeb29478260ce48385dca6773b105e"
|
||||
integrity sha512-oAy0OqAvjAvduqCeWveBix7LLuDbARPqZZ8ERYtBcCURA3gy7EALA3XWq0tCNxsSg+RmmJqyaeeZlOCV9abv6w==
|
||||
dependencies:
|
||||
fetch-mock "^9.11.0"
|
||||
|
||||
fetch-mock@9.11.0, fetch-mock@^9.11.0:
|
||||
version "9.11.0"
|
||||
resolved "https://registry.yarnpkg.com/fetch-mock/-/fetch-mock-9.11.0.tgz#371c6fb7d45584d2ae4a18ee6824e7ad4b637a3f"
|
||||
integrity sha512-PG1XUv+x7iag5p/iNHD4/jdpxL9FtVSqRMUQhPab4hVDt80T1MH5ehzVrL2IdXO9Q2iBggArFvPqjUbHFuI58Q==
|
||||
dependencies:
|
||||
"@babel/core" "^7.0.0"
|
||||
"@babel/runtime" "^7.0.0"
|
||||
core-js "^3.0.0"
|
||||
debug "^4.1.1"
|
||||
glob-to-regexp "^0.4.0"
|
||||
is-subset "^0.1.1"
|
||||
lodash.isequal "^4.5.0"
|
||||
path-to-regexp "^2.2.1"
|
||||
querystring "^0.2.0"
|
||||
whatwg-url "^6.5.0"
|
||||
"@types/glob-to-regexp" "^0.4.4"
|
||||
dequal "^2.0.3"
|
||||
glob-to-regexp "^0.4.1"
|
||||
regexparam "^3.0.0"
|
||||
|
||||
fflate@^0.4.8:
|
||||
version "0.4.8"
|
||||
@ -7632,7 +7618,7 @@ glob-parent@^6.0.1, glob-parent@^6.0.2:
|
||||
dependencies:
|
||||
is-glob "^4.0.3"
|
||||
|
||||
glob-to-regexp@^0.4.0, glob-to-regexp@^0.4.1:
|
||||
glob-to-regexp@^0.4.1:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
|
||||
integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
|
||||
@ -8483,11 +8469,6 @@ is-string@^1.1.1:
|
||||
call-bound "^1.0.3"
|
||||
has-tostringtag "^1.0.2"
|
||||
|
||||
is-subset@^0.1.1:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/is-subset/-/is-subset-0.1.1.tgz#8a59117d932de1de00f245fcdd39ce43f1e939a6"
|
||||
integrity sha512-6Ybun0IkarhmEqxXCNw/C0bna6Zb/TkfUX9UbwJtK6ObwAVCxmAP308WWTHviM/zAqXk05cdhYsUsZeGQh99iw==
|
||||
|
||||
is-symbol@^1.0.4, is-symbol@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.1.1.tgz#f47761279f532e2b05a7024a7506dbbedacd0634"
|
||||
@ -8755,7 +8736,7 @@ jest-each@30.2.0:
|
||||
jest-util "30.2.0"
|
||||
pretty-format "30.2.0"
|
||||
|
||||
jest-environment-jsdom@^30.0.0:
|
||||
jest-environment-jsdom@^30.2.0:
|
||||
version "30.2.0"
|
||||
resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-30.2.0.tgz#e95e0921ed22be974f1d8a324766d12b1844cb2c"
|
||||
integrity sha512-zbBTiqr2Vl78pKp/laGBREYzbZx9ZtqPjOK4++lL4BNDhxRnahg51HtoDrk9/VjIy9IthNEWdKVd7H5bqBhiWQ==
|
||||
@ -8779,6 +8760,11 @@ jest-environment-node@30.2.0:
|
||||
jest-util "30.2.0"
|
||||
jest-validate "30.2.0"
|
||||
|
||||
jest-fixed-jsdom@^0.0.11:
|
||||
version "0.0.11"
|
||||
resolved "https://registry.yarnpkg.com/jest-fixed-jsdom/-/jest-fixed-jsdom-0.0.11.tgz#67b5d5c4e9821bfb1e09a43139bfb0b9f4ec4f18"
|
||||
integrity sha512-3UkjgM79APnmLVDnelrxdwz4oybD5qw6NLyayl7iCX8C8tJHeqjL9fmNrRlIrNiVJSXkF5t9ZPJ+xlM0kSwwYg==
|
||||
|
||||
jest-haste-map@30.2.0:
|
||||
version "30.2.0"
|
||||
resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-30.2.0.tgz#808e3889f288603ac70ff0ac047598345a66022e"
|
||||
@ -9413,11 +9399,6 @@ lodash.debounce@^4.0.8:
|
||||
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
||||
integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==
|
||||
|
||||
lodash.isequal@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
|
||||
integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==
|
||||
|
||||
lodash.memoize@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
|
||||
@ -9428,11 +9409,6 @@ lodash.merge@^4.6.2:
|
||||
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
|
||||
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
|
||||
|
||||
lodash.sortby@^4.7.0:
|
||||
version "4.7.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
|
||||
integrity sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==
|
||||
|
||||
lodash.truncate@^4.4.2:
|
||||
version "4.4.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
|
||||
@ -10403,11 +10379,6 @@ path-to-regexp@0.1.12:
|
||||
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.12.tgz#d5e1a12e478a976d432ef3c58d534b9923164bb7"
|
||||
integrity sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==
|
||||
|
||||
path-to-regexp@^2.2.1:
|
||||
version "2.4.0"
|
||||
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-2.4.0.tgz#35ce7f333d5616f1c1e1bfe266c3aba2e5b2e704"
|
||||
integrity sha512-G6zHoVqC6GGTQkZwF4lkuEyMbVOjoBKAEybQUypI1WTkqinCOrq2x6U2+phkJ1XsEMTy4LjtwPI7HW+NVrRR2w==
|
||||
|
||||
path-to-regexp@^8.0.0:
|
||||
version "8.3.0"
|
||||
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-8.3.0.tgz#aa818a6981f99321003a08987d3cec9c3474cd1f"
|
||||
@ -11321,11 +11292,6 @@ qs@^6.14.0:
|
||||
dependencies:
|
||||
side-channel "^1.1.0"
|
||||
|
||||
querystring@^0.2.0:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.1.tgz#40d77615bb09d16902a85c3e38aa8b5ed761c2dd"
|
||||
integrity sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==
|
||||
|
||||
queue-microtask@^1.2.2:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
|
||||
@ -11699,6 +11665,11 @@ regexp.prototype.flags@^1.5.3, regexp.prototype.flags@^1.5.4:
|
||||
gopd "^1.2.0"
|
||||
set-function-name "^2.0.2"
|
||||
|
||||
regexparam@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/regexparam/-/regexparam-3.0.0.tgz#1673e09d41cb7fd41eaafd4040a6aa90daa0a21a"
|
||||
integrity sha512-RSYAtP31mvYLkAHrOlh25pCNQ5hWnT106VukGaaFfuJrZFkGRX5GhUAdPqpSDXxOhA2c4akmRuplv1mRqnBn6Q==
|
||||
|
||||
regexpu-core@^6.3.1:
|
||||
version "6.4.0"
|
||||
resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-6.4.0.tgz#3580ce0c4faedef599eccb146612436b62a176e5"
|
||||
@ -13134,13 +13105,6 @@ tough-cookie@^5.1.1:
|
||||
dependencies:
|
||||
tldts "^6.1.32"
|
||||
|
||||
tr46@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09"
|
||||
integrity sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==
|
||||
dependencies:
|
||||
punycode "^2.1.0"
|
||||
|
||||
tr46@^5.1.0:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/tr46/-/tr46-5.1.1.tgz#96ae867cddb8fdb64a49cc3059a8d428bcf238ca"
|
||||
@ -13625,11 +13589,6 @@ webidl-conversions@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
|
||||
integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
|
||||
|
||||
webidl-conversions@^4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
|
||||
integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==
|
||||
|
||||
webidl-conversions@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a"
|
||||
@ -13835,15 +13794,6 @@ whatwg-url@^5.0.0:
|
||||
tr46 "~0.0.3"
|
||||
webidl-conversions "^3.0.0"
|
||||
|
||||
whatwg-url@^6.5.0:
|
||||
version "6.5.0"
|
||||
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-6.5.0.tgz#f2df02bff176fd65070df74ad5ccbb5a199965a8"
|
||||
integrity sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==
|
||||
dependencies:
|
||||
lodash.sortby "^4.7.0"
|
||||
tr46 "^1.0.1"
|
||||
webidl-conversions "^4.0.2"
|
||||
|
||||
which-boxed-primitive@^1.1.0, which-boxed-primitive@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz#d76ec27df7fa165f18d5808374a5fe23c29b176e"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user