Merge remote-tracking branch 'origin/develop' into dbkr/refactor_createcrosssigningdialog

This commit is contained in:
David Baker
2024-10-21 13:35:35 +01:00
286 changed files with 1159 additions and 1611 deletions
+14 -19
View File
@@ -14,7 +14,7 @@ import encrypt, { IEncryptedFile } from "matrix-encrypt-attachment";
import ContentMessages, { UploadCanceledError, uploadFile } from "../../src/ContentMessages";
import { doMaybeLocalRoomAction } from "../../src/utils/local-room";
import { createTestClient, mkEvent } from "../test-utils";
import { createTestClient, flushPromises, mkEvent } from "../test-utils";
import { BlurhashEncoder } from "../../src/BlurhashEncoder";
jest.mock("matrix-encrypt-attachment", () => ({ encryptAttachment: jest.fn().mockResolvedValue({}) }));
@@ -43,13 +43,7 @@ describe("ContentMessages", () => {
let prom: Promise<ISendEventResponse>;
beforeEach(() => {
client = {
getSafeUserId: jest.fn().mockReturnValue("@alice:test"),
sendStickerMessage: jest.fn(),
sendMessage: jest.fn(),
isRoomEncrypted: jest.fn().mockReturnValue(false),
uploadContent: jest.fn().mockResolvedValue({ content_uri: "mxc://server/file" }),
} as unknown as MatrixClient;
client = createTestClient();
contentMessages = new ContentMessages();
prom = Promise.resolve<ISendEventResponse>({ event_id: "$event_id" });
});
@@ -262,6 +256,7 @@ describe("ContentMessages", () => {
expect(upload.loaded).toBe(0);
expect(upload.total).toBe(file.size);
await flushPromises();
const { progressHandler } = mocked(client.uploadContent).mock.calls[0][1]!;
progressHandler!({ loaded: 123, total: 1234 });
expect(upload.loaded).toBe(123);
@@ -342,6 +337,7 @@ describe("ContentMessages", () => {
mocked(client.uploadContent).mockReturnValue(deferred.promise);
const file1 = new File([], "file1");
const prom = contentMessages.sendContentToRoom(file1, roomId, undefined, client, undefined);
await flushPromises();
const { abortController } = mocked(client.uploadContent).mock.calls[0][1]!;
expect(abortController!.signal.aborted).toBeFalsy();
const [upload] = contentMessages.getCurrentUploads();
@@ -354,14 +350,14 @@ describe("ContentMessages", () => {
});
describe("uploadFile", () => {
let client: MatrixClient;
beforeEach(() => {
jest.clearAllMocks();
client = createTestClient();
});
const client = createTestClient();
it("should not encrypt the file if the room isn't encrypted", async () => {
mocked(client.isRoomEncrypted).mockReturnValue(false);
mocked(client.uploadContent).mockResolvedValue({ content_uri: "mxc://server/file" });
const progressHandler = jest.fn();
const file = new Blob([]);
@@ -375,7 +371,7 @@ describe("uploadFile", () => {
});
it("should encrypt the file if the room is encrypted", async () => {
mocked(client.isRoomEncrypted).mockReturnValue(true);
jest.spyOn(client.getCrypto()!, "isEncryptionEnabledInRoom").mockResolvedValue(true);
mocked(client.uploadContent).mockResolvedValue({ content_uri: "mxc://server/file" });
mocked(encrypt.encryptAttachment).mockResolvedValue({
data: new ArrayBuffer(123),
@@ -405,14 +401,13 @@ describe("uploadFile", () => {
});
it("should throw UploadCanceledError upon aborting the upload", async () => {
mocked(client.isRoomEncrypted).mockReturnValue(false);
const deferred = defer<UploadResponse>();
mocked(client.uploadContent).mockReturnValue(deferred.promise);
mocked(client.uploadContent).mockResolvedValue({ content_uri: "mxc://foo/bar" });
const file = new Blob([]);
const controller = new AbortController();
controller.abort();
const prom = uploadFile(client, "!roomId:server", file);
mocked(client.uploadContent).mock.calls[0][1]!.abortController!.abort();
deferred.resolve({ content_uri: "mxc://foo/bar" });
await expect(prom).rejects.toThrow(UploadCanceledError);
await expect(uploadFile(client, "!roomId:server", file, undefined, controller)).rejects.toThrow(
UploadCanceledError,
);
});
});
+1 -1
View File
@@ -630,7 +630,7 @@ describe("Lifecycle", () => {
deviceId,
freshLogin: true,
guest: false,
pickleKey: null,
pickleKey: undefined,
},
undefined,
);
-2
View File
@@ -83,12 +83,10 @@ describe("MatrixClientPeg", () => {
it("should initialise the rust crypto library by default", async () => {
const mockSetValue = jest.spyOn(SettingsStore, "setValue").mockResolvedValue(undefined);
const mockInitCrypto = jest.spyOn(testPeg.safeGet(), "initCrypto").mockResolvedValue(undefined);
const mockInitRustCrypto = jest.spyOn(testPeg.safeGet(), "initRustCrypto").mockResolvedValue(undefined);
const cryptoStoreKey = new Uint8Array([1, 2, 3, 4]);
await testPeg.start({ rustCryptoStoreKey: cryptoStoreKey });
expect(mockInitCrypto).not.toHaveBeenCalled();
expect(mockInitRustCrypto).toHaveBeenCalledWith({ storageKey: cryptoStoreKey });
// we should have stashed the setting in the settings store
-1
View File
@@ -86,7 +86,6 @@ describe("Terms", function () {
policy_the_first: POLICY_ONE,
},
});
mockClient.agreeToTerms;
const interactionCallback = jest.fn();
await startTermsFlow(mockClient, [IM_SERVICE_ONE], interactionCallback);
@@ -125,7 +125,6 @@ describe("<MatrixChat />", () => {
}),
getVisibleRooms: jest.fn().mockReturnValue([]),
getRooms: jest.fn().mockReturnValue([]),
setGlobalBlacklistUnverifiedDevices: jest.fn(),
setGlobalErrorOnUnknownDevices: jest.fn(),
getCrypto: jest.fn().mockReturnValue({
getVerificationRequestsToDeviceInProgress: jest.fn().mockReturnValue([]),
@@ -138,6 +137,9 @@ describe("<MatrixChat />", () => {
// This needs to not finish immediately because we need to test the screen appears
bootstrapCrossSigning: jest.fn().mockImplementation(() => bootstrapDeferred.promise),
getActiveSessionBackupVersion: jest.fn().mockResolvedValue(null),
globalBlacklistUnverifiedDevices: false,
// This needs to not finish immediately because we need to test the screen appears
bootstrapCrossSigning: jest.fn().mockImplementation(() => bootstrapDeferred.promise),
}),
secretStorage: {
isStored: jest.fn().mockReturnValue(null),
@@ -18,7 +18,7 @@ import dispatcher from "../../../../../src/dispatcher/dispatcher";
import { Action } from "../../../../../src/dispatcher/actions";
jest.mock("../../../../../src/stores/OwnBeaconStore", () => {
// eslint-disable-next-line @typescript-eslint/no-var-requires
// eslint-disable-next-line @typescript-eslint/no-require-imports
const EventEmitter = require("events");
class MockOwnBeaconStore extends EventEmitter {
public getLiveBeaconIdsWithLocationPublishError = jest.fn().mockReturnValue([]);
@@ -34,7 +34,7 @@ describe("CreateKeyBackupDialog", () => {
it("should display an error message when backup creation failed", async () => {
const matrixClient = createTestClient();
mocked(matrixClient.hasSecretStorageKey).mockResolvedValue(true);
jest.spyOn(matrixClient.secretStorage, "hasKey").mockResolvedValue(true);
mocked(matrixClient.getCrypto()!.resetKeyBackup).mockImplementation(() => {
throw new Error("failed");
});
@@ -49,7 +49,7 @@ describe("CreateKeyBackupDialog", () => {
it("should display an error message when there is no Crypto available", async () => {
const matrixClient = createTestClient();
mocked(matrixClient.hasSecretStorageKey).mockResolvedValue(true);
jest.spyOn(matrixClient.secretStorage, "hasKey").mockResolvedValue(true);
mocked(matrixClient.getCrypto).mockReturnValue(undefined);
MatrixClientPeg.safeGet = MatrixClientPeg.get = () => matrixClient;
@@ -122,7 +122,6 @@ describe("CreateSecretStorageDialog", () => {
expect(modalSpy).toHaveBeenCalledWith(
RestoreKeyBackupDialog,
{
keyCallback: expect.any(Function),
showSummary: false,
},
undefined,
@@ -200,7 +199,6 @@ describe("CreateSecretStorageDialog", () => {
expect(modalSpy).toHaveBeenCalledWith(
RestoreKeyBackupDialog,
{
keyCallback: expect.any(Function),
showSummary: false,
},
undefined,
@@ -57,12 +57,12 @@ describe("Field", () => {
// When invalid
fireEvent.focus(screen.getByRole("textbox"));
// Expect 'alert' role
await expect(screen.findByRole("alert")).resolves.toBeInTheDocument();
// Expect 'aria-live=assertive'
await expect(screen.findByRole("tooltip")).resolves.toHaveAttribute("aria-live", "assertive");
// Close the feedback is Escape is pressed
fireEvent.keyDown(screen.getByRole("textbox"), { key: "Escape" });
expect(screen.queryByRole("alert")).toBeNull();
expect(screen.queryByRole("tooltip")).not.toBeInTheDocument();
});
it("Should mark the feedback as status if valid", async () => {
@@ -77,12 +77,12 @@ describe("Field", () => {
// When valid
fireEvent.focus(screen.getByRole("textbox"));
// Expect 'status' role
await expect(screen.findByRole("status")).resolves.toBeInTheDocument();
// Expect 'aria-live=polite' role
await expect(screen.findByRole("tooltip")).resolves.toHaveAttribute("aria-live", "polite");
// Close the feedback is Escape is pressed
fireEvent.keyDown(screen.getByRole("textbox"), { key: "Escape" });
expect(screen.queryByRole("status")).toBeNull();
expect(screen.queryByRole("tooltip")).not.toBeInTheDocument();
});
it("Should mark the feedback as tooltip if custom tooltip set", async () => {
@@ -153,9 +153,18 @@ exports[`AppTile for a pinned widget should render 1`] = `
role="button"
tabindex="0"
>
<div
<svg
class="mx_Icon mx_Icon_12"
/>
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 11.034a.996.996 0 0 0 .29.702l.005.005c.18.18.43.29.705.29h8a1 1 0 1 0 0-2h-5.586L22 3.446a1 1 0 0 0-1.414-1.415L14 8.617V3.031a1 1 0 1 0-2 0v8.003Zm0 1.963a.997.997 0 0 0-.29-.702l-.005-.004A.997.997 0 0 0 11 12H3a1 1 0 0 0 0 2h5.586L2 20.586A1 1 0 1 0 3.414 22L10 15.414V21a1 1 0 1 0 2 0v-8.003Z"
/>
</svg>
</div>
<div
aria-label="Minimise"
@@ -163,9 +172,18 @@ exports[`AppTile for a pinned widget should render 1`] = `
role="button"
tabindex="0"
>
<div
class="mx_Icon mx_Icon_12"
/>
<svg
class="mx_Icon mx_Icon_16"
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M6 13a.967.967 0 0 1-.713-.287A.968.968 0 0 1 5 12c0-.283.096-.52.287-.713A.967.967 0 0 1 6 11h12a.97.97 0 0 1 .712.287c.192.192.288.43.288.713s-.096.52-.288.713A.968.968 0 0 1 18 13H6Z"
/>
</svg>
</div>
<div
aria-expanded="false"
@@ -247,9 +265,18 @@ exports[`AppTile for a pinned widget should render permission request 1`] = `
role="button"
tabindex="0"
>
<div
<svg
class="mx_Icon mx_Icon_12"
/>
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 11.034a.996.996 0 0 0 .29.702l.005.005c.18.18.43.29.705.29h8a1 1 0 1 0 0-2h-5.586L22 3.446a1 1 0 0 0-1.414-1.415L14 8.617V3.031a1 1 0 1 0-2 0v8.003Zm0 1.963a.997.997 0 0 0-.29-.702l-.005-.004A.997.997 0 0 0 11 12H3a1 1 0 0 0 0 2h5.586L2 20.586A1 1 0 1 0 3.414 22L10 15.414V21a1 1 0 1 0 2 0v-8.003Z"
/>
</svg>
</div>
<div
aria-label="Minimise"
@@ -257,9 +284,18 @@ exports[`AppTile for a pinned widget should render permission request 1`] = `
role="button"
tabindex="0"
>
<div
class="mx_Icon mx_Icon_12"
/>
<svg
class="mx_Icon mx_Icon_16"
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M6 13a.967.967 0 0 1-.713-.287A.968.968 0 0 1 5 12c0-.283.096-.52.287-.713A.967.967 0 0 1 6 11h12a.97.97 0 0 1 .712.287c.192.192.288.43.288.713s-.096.52-.288.713A.968.968 0 0 1 18 13H6Z"
/>
</svg>
</div>
<div
aria-expanded="false"
@@ -420,9 +456,18 @@ exports[`AppTile preserves non-persisted widget on container move 1`] = `
role="button"
tabindex="0"
>
<div
<svg
class="mx_Icon mx_Icon_12"
/>
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M21 3.997a.996.996 0 0 0-.29-.702l-.005-.004A.997.997 0 0 0 20 3h-8a1 1 0 1 0 0 2h5.586L5 17.586V12a1 1 0 1 0-2 0v8.003a.997.997 0 0 0 .29.702l.005.004c.18.18.43.291.705.291h8a1 1 0 1 0 0-2H6.414L19 6.414V12a1 1 0 1 0 2 0V3.997Z"
/>
</svg>
</div>
<div
aria-label="Minimise"
@@ -430,9 +475,18 @@ exports[`AppTile preserves non-persisted widget on container move 1`] = `
role="button"
tabindex="0"
>
<div
class="mx_Icon mx_Icon_12"
/>
<svg
class="mx_Icon mx_Icon_16"
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M6 13a.967.967 0 0 1-.713-.287A.968.968 0 0 1 5 12c0-.283.096-.52.287-.713A.967.967 0 0 1 6 11h12a.97.97 0 0 1 .712.287c.192.192.288.43.288.713s-.096.52-.288.713A.968.968 0 0 1 18 13H6Z"
/>
</svg>
</div>
<div
aria-expanded="false"
@@ -219,9 +219,18 @@ exports[`<Pill> should render the expected pill for an uknown user not in the ro
class="mx_Pill mx_UserPill"
href="https://matrix.to/#/@user3:example.com"
>
<div
<svg
class="mx_Pill_UserIcon mx_BaseAvatar"
/>
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 12c-1.1 0-2.042-.392-2.825-1.175C8.392 10.042 8 9.1 8 8s.392-2.042 1.175-2.825C9.958 4.392 10.9 4 12 4s2.042.392 2.825 1.175C15.608 5.958 16 6.9 16 8s-.392 2.042-1.175 2.825C14.042 11.608 13.1 12 12 12Zm-8 6v-.8c0-.567.146-1.087.438-1.563A2.911 2.911 0 0 1 5.6 14.55a14.843 14.843 0 0 1 3.15-1.163A13.76 13.76 0 0 1 12 13c1.1 0 2.183.13 3.25.387 1.067.259 2.117.646 3.15 1.163.483.25.87.612 1.163 1.087.291.476.437.996.437 1.563v.8c0 .55-.196 1.02-.587 1.413A1.926 1.926 0 0 1 18 20H6c-.55 0-1.02-.196-1.412-.587A1.926 1.926 0 0 1 4 18Z"
/>
</svg>
<span
class="mx_Pill_text"
>
@@ -102,7 +102,7 @@ describe("<Map />", () => {
const logSpy = jest.spyOn(logger, "error").mockImplementation();
getComponent({ centerGeoUri: "123 Sesame Street" });
expect(mockMap.setCenter).not.toHaveBeenCalled();
expect(logSpy).toHaveBeenCalledWith("Could not set map center");
expect(logSpy).toHaveBeenCalledWith("Could not set map center", expect.any(Error));
});
it("updates map center when centerGeoUri prop changes", () => {
@@ -136,7 +136,7 @@ describe("<Map />", () => {
const bounds = { north: "a", south: "b", east: 42, west: 41 };
getComponent({ bounds });
expect(mockMap.fitBounds).not.toHaveBeenCalled();
expect(logSpy).toHaveBeenCalledWith("Invalid map bounds");
expect(logSpy).toHaveBeenCalledWith("Invalid map bounds", expect.any(Error));
});
it("updates map bounds when bounds prop changes", () => {
@@ -30,9 +30,18 @@ exports[`<LocationViewDialog /> renders map correctly 1`] = `
role="button"
tabindex="0"
>
<div
<svg
class="mx_ZoomButtons_icon"
/>
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M11 13H6a.967.967 0 0 1-.713-.287A.968.968 0 0 1 5 12c0-.283.096-.52.287-.713A.967.967 0 0 1 6 11h5V6c0-.283.096-.52.287-.713A.968.968 0 0 1 12 5c.283 0 .52.096.713.287.191.192.287.43.287.713v5h5a.97.97 0 0 1 .712.287c.192.192.288.43.288.713s-.096.52-.288.713A.968.968 0 0 1 18 13h-5v5a.97.97 0 0 1-.287.712A.968.968 0 0 1 12 19a.968.968 0 0 1-.713-.288A.968.968 0 0 1 11 18v-5Z"
/>
</svg>
</div>
<div
aria-label="Zoom out"
@@ -41,9 +50,18 @@ exports[`<LocationViewDialog /> renders map correctly 1`] = `
role="button"
tabindex="0"
>
<div
<svg
class="mx_ZoomButtons_icon"
/>
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M6 13a.967.967 0 0 1-.713-.287A.968.968 0 0 1 5 12c0-.283.096-.52.287-.713A.967.967 0 0 1 6 11h12a.97.97 0 0 1 .712.287c.192.192.288.43.288.713s-.096.52-.288.713A.968.968 0 0 1 18 13H6Z"
/>
</svg>
</div>
</div>
</div>
@@ -12,9 +12,18 @@ exports[`<ZoomButtons /> renders buttons 1`] = `
role="button"
tabindex="0"
>
<div
<svg
class="mx_ZoomButtons_icon"
/>
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M11 13H6a.967.967 0 0 1-.713-.287A.968.968 0 0 1 5 12c0-.283.096-.52.287-.713A.967.967 0 0 1 6 11h5V6c0-.283.096-.52.287-.713A.968.968 0 0 1 12 5c.283 0 .52.096.713.287.191.192.287.43.287.713v5h5a.97.97 0 0 1 .712.287c.192.192.288.43.288.713s-.096.52-.288.713A.968.968 0 0 1 18 13h-5v5a.97.97 0 0 1-.287.712A.968.968 0 0 1 12 19a.968.968 0 0 1-.713-.288A.968.968 0 0 1 11 18v-5Z"
/>
</svg>
</div>
<div
aria-label="Zoom out"
@@ -23,9 +32,18 @@ exports[`<ZoomButtons /> renders buttons 1`] = `
role="button"
tabindex="0"
>
<div
<svg
class="mx_ZoomButtons_icon"
/>
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M6 13a.967.967 0 0 1-.713-.287A.968.968 0 0 1 5 12c0-.283.096-.52.287-.713A.967.967 0 0 1 6 11h12a.97.97 0 0 1 .712.287c.192.192.288.43.288.713s-.096.52-.288.713A.968.968 0 0 1 18 13H6Z"
/>
</svg>
</div>
</div>
</DocumentFragment>
@@ -9,7 +9,7 @@ Please see LICENSE files in the repository root for full details.
import React from "react";
import { MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix";
import { mocked, MockedObject } from "jest-mock";
import { render } from "jest-matrix-react";
import { render, waitFor } from "jest-matrix-react";
import { getMockClientWithEventEmitter, mkEvent, mkMessage, mkStubRoom } from "../../../../test-utils";
import { MatrixClientPeg } from "../../../../../src/MatrixClientPeg";
@@ -279,6 +279,17 @@ describe("<TextualBody />", () => {
expect(content).toMatchSnapshot();
});
it("should syntax highlight code blocks", async () => {
const ev = mkFormattedMessage(
"```py\n# Python Program to calculate the square root\n\n# Note: change this value for a different result\nnum = 8 \n\n# To take the input from the user\n#num = float(input('Enter a number: '))\n\nnum_sqrt = num ** 0.5\nprint('The square root of %0.3f is %0.3f'%(num ,num_sqrt))",
"<pre><code class=\"language-py\"># Python Program to calculate the square root\n\n# Note: change this value for a different result\nnum = 8 \n\n# To take the input from the user\n#num = float(input('Enter a number: '))\n\nnum_sqrt = num ** 0.5\nprint('The square root of %0.3f is %0.3f'%(num ,num_sqrt))\n</code></pre>\n",
);
const { container } = getComponent({ mxEvent: ev }, matrixClient);
await waitFor(() => expect(container.querySelector(".hljs-built_in")).toBeInTheDocument());
const content = container.querySelector(".mx_EventTile_body");
expect(content).toMatchSnapshot();
});
// If pills were rendered within a Portal/same shadow DOM then it'd be easier to test
it("pills get injected correctly into the DOM", () => {
const ev = mkFormattedMessage("Hey User", 'Hey <a href="https://matrix.to/#/@user:server">Member</a>');
@@ -50,14 +50,20 @@ exports[`<TextualBody /> renders formatted m.text correctly linkification is not
1
</span>
</span>
<code>
https://matrix.org/
<div
style="display: contents;"
>
<code>
https://matrix.org/
</code>
<span />
</code>
</div>
</pre>
<span
class="mx_EventTile_button mx_EventTile_copyButton "
<div
aria-label="Copy"
class="mx_AccessibleButton mx_EventTile_button mx_EventTile_copyButton"
role="button"
tabindex="0"
/>
</div>
@@ -254,14 +260,20 @@ exports[`<TextualBody /> renders formatted m.text correctly pills do not appear
1
</span>
</span>
<code>
@room
<div
style="display: contents;"
>
<code>
@room
</code>
<span />
</code>
</div>
</pre>
<span
class="mx_EventTile_button mx_EventTile_copyButton "
<div
aria-label="Copy"
class="mx_AccessibleButton mx_EventTile_button mx_EventTile_copyButton"
role="button"
tabindex="0"
/>
</div>
@@ -321,6 +333,133 @@ exports[`<TextualBody /> renders formatted m.text correctly renders formatted bo
</div>
`;
exports[`<TextualBody /> renders formatted m.text correctly should syntax highlight code blocks 1`] = `
<div
class="mx_EventTile_body markdown-body translate"
dir="auto"
>
<div
class="mx_EventTile_pre_container"
>
<pre
class="mx_EventTile_collapsedCodeBlock"
>
<span
class="mx_EventTile_lineNumbers"
>
<span>
1
</span>
<span>
2
</span>
<span>
3
</span>
<span>
4
</span>
<span>
5
</span>
<span>
6
</span>
<span>
7
</span>
<span>
8
</span>
<span>
9
</span>
<span>
10
</span>
</span>
<div
style="display: contents;"
>
<code
class="language-py"
>
<span
class="hljs-comment"
>
# Python Program to calculate the square root
</span>
<span
class="hljs-comment"
>
# Note: change this value for a different result
</span>
num =
<span
class="hljs-number"
>
8
</span>
<span
class="hljs-comment"
>
# To take the input from the user
</span>
<span
class="hljs-comment"
>
#num = float(input('Enter a number: '))
</span>
num_sqrt = num **
<span
class="hljs-number"
>
0.5
</span>
<span
class="hljs-built_in"
>
print
</span>
(
<span
class="hljs-string"
>
'The square root of %0.3f is %0.3f'
</span>
%(num ,num_sqrt))
</code>
</div>
</pre>
<span
class="mx_EventTile_button mx_EventTile_expandButton"
/>
<div
aria-label="Copy"
class="mx_AccessibleButton mx_EventTile_button mx_EventTile_copyButton mx_EventTile_buttonBottom"
role="button"
tabindex="0"
/>
</div>
</div>
`;
exports[`<TextualBody /> renders formatted m.text correctly spoilers get injected properly into the DOM 1`] = `
<div
class="mx_EventTile_body markdown-body translate"
@@ -15,7 +15,6 @@ import { makePollStartEvent, mockIntlDateTimeFormat, unmockIntlDateTimeFormat }
describe("<PollListItem />", () => {
const event = makePollStartEvent("Question?", "@me:domain.org");
event.getContent().origin;
const defaultProps = { event, onClick: jest.fn() };
const getComponent = (props = {}) => render(<PollListItem {...defaultProps} {...props} />);
@@ -160,7 +160,6 @@ beforeEach(() => {
getRoom: jest.fn(),
credentials: {},
setPowerLevel: jest.fn(),
downloadKeys: jest.fn(),
getCrypto: jest.fn().mockReturnValue(mockCrypto),
} as unknown as MatrixClient);
@@ -247,11 +247,11 @@ describe("MessageComposer", () => {
});
describe("UIStore interactions", () => {
let resizeCallback: Function;
let resizeCallback: (key: string, data: object) => void;
beforeEach(() => {
jest.spyOn(UIStore.instance, "on").mockImplementation(
(_event: string | symbol, listener: Function): any => {
(_event: string | symbol, listener: (key: string, data: object) => void): any => {
resizeCallback = listener;
},
);
@@ -564,7 +564,7 @@ describe("RoomHeader", () => {
jest.spyOn(SdkContextClass.instance.roomViewStore, "isViewingCall").mockReturnValue(true);
render(<RoomHeader room={room} />, getWrapper()).container;
render(<RoomHeader room={room} />, getWrapper());
expect(getByLabelText(document.body, _t("voip|get_call_link"))).toBeInTheDocument();
});
@@ -210,7 +210,6 @@ describe("RoomList", () => {
beforeEach(async () => {
cleanup();
const rooms: Room[] = [];
RoomListStore.instance;
testUtils.mkRoom(client, videoRoomPrivate, rooms);
testUtils.mkRoom(client, videoRoomPublic, rooms);
testUtils.mkRoom(client, videoRoomKnock, rooms);
@@ -100,7 +100,7 @@ describe("<RoomPreviewBar />", () => {
afterEach(() => {
const container = document.body.firstChild;
container && document.body.removeChild(container);
if (container) document.body.removeChild(container);
});
it("renders joining message", () => {
@@ -34,7 +34,6 @@ describe("<CrossSigningPanel />", () => {
});
mockClient.doesServerSupportUnstableFeature.mockResolvedValue(true);
mockClient.isCrossSigningReady.mockResolvedValue(false);
});
afterEach(() => {
@@ -90,10 +90,17 @@ exports[`PeopleRoomSettingsTab with requests to join renders requests fully 1`]
role="button"
tabindex="0"
>
<div
<svg
fill="currentColor"
height="18"
viewBox="0 0 24 24"
width="18"
/>
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M9.55 17.575c-.133 0-.258-.02-.375-.063a.876.876 0 0 1-.325-.212L4.55 13c-.183-.183-.27-.42-.263-.713.009-.291.105-.529.288-.712a.948.948 0 0 1 .7-.275.95.95 0 0 1 .7.275L9.55 15.15l8.475-8.475c.183-.183.42-.275.713-.275.291 0 .529.092.712.275.183.183.275.42.275.713 0 .291-.092.529-.275.712l-9.2 9.2c-.1.1-.208.17-.325.212a1.106 1.106 0 0 1-.375.063Z"
/>
</svg>
</div>
</div>
</div>
@@ -164,10 +171,17 @@ exports[`PeopleRoomSettingsTab with requests to join renders requests reduced 1`
role="button"
tabindex="0"
>
<div
<svg
fill="currentColor"
height="18"
viewBox="0 0 24 24"
width="18"
/>
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M9.55 17.575c-.133 0-.258-.02-.375-.063a.876.876 0 0 1-.325-.212L4.55 13c-.183-.183-.27-.42-.263-.713.009-.291.105-.529.288-.712a.948.948 0 0 1 .7-.275.95.95 0 0 1 .7.275L9.55 15.15l8.475-8.475c.183-.183.42-.275.713-.275.291 0 .529.092.712.275.183.183.275.42.275.713 0 .291-.092.529-.275.712l-9.2 9.2c-.1.1-.208.17-.325.212a1.106 1.106 0 0 1-.375.063Z"
/>
</svg>
</div>
</div>
</div>
@@ -17,7 +17,6 @@ import {
waitForElementToBeRemoved,
within,
} from "jest-matrix-react";
import { DeviceInfo } from "matrix-js-sdk/src/crypto/deviceinfo";
import { logger } from "matrix-js-sdk/src/logger";
import { CryptoApi, DeviceVerificationStatus, VerificationRequest } from "matrix-js-sdk/src/crypto-api";
import { defer, sleep } from "matrix-js-sdk/src/utils";
@@ -205,7 +204,6 @@ describe("<SessionManagerTab />", () => {
...mockClientMethodsServer(),
getCrypto: jest.fn().mockReturnValue(mockCrypto),
getDevices: jest.fn(),
getStoredDevice: jest.fn(),
getDeviceId: jest.fn().mockReturnValue(deviceId),
deleteMultipleDevices: jest.fn(),
generateClientSecret: jest.fn(),
@@ -220,10 +218,6 @@ describe("<SessionManagerTab />", () => {
});
jest.clearAllMocks();
jest.spyOn(logger, "error").mockRestore();
mockClient.getStoredDevice.mockImplementation((_userId, id) => {
const device = [alicesDevice, alicesMobileDevice].find((device) => device.device_id === id);
return device ? new DeviceInfo(device.device_id) : null;
});
mockCrypto.getDeviceVerificationStatus.mockReset().mockResolvedValue(new DeviceVerificationStatus({}));
mockClient.getDevices.mockReset().mockResolvedValue({ devices: [alicesDevice, alicesMobileDevice] });
@@ -292,7 +286,6 @@ describe("<SessionManagerTab />", () => {
mockClient.getDevices.mockResolvedValue({
devices: [alicesDevice, alicesMobileDevice, alicesOlderMobileDevice],
});
mockClient.getStoredDevice.mockImplementation((_userId, deviceId) => new DeviceInfo(deviceId));
mockCrypto.getDeviceVerificationStatus.mockImplementation(async (_userId, deviceId) => {
// alices device is trusted
if (deviceId === alicesDevice.device_id) {
@@ -464,7 +457,6 @@ describe("<SessionManagerTab />", () => {
mockClient.getDevices.mockResolvedValue({
devices: [alicesDevice, alicesMobileDevice],
});
mockClient.getStoredDevice.mockImplementation(() => new DeviceInfo(alicesDevice.device_id));
mockCrypto.getDeviceVerificationStatus.mockResolvedValue(
new DeviceVerificationStatus({ crossSigningVerified: true, localVerified: true }),
);
@@ -568,7 +560,6 @@ describe("<SessionManagerTab />", () => {
mockClient.getDevices.mockResolvedValue({
devices: [alicesDevice, alicesMobileDevice],
});
mockClient.getStoredDevice.mockImplementation((_userId, deviceId) => new DeviceInfo(deviceId));
mockCrypto.getDeviceVerificationStatus.mockImplementation(async (_userId, deviceId) => {
if (deviceId === alicesDevice.device_id) {
return new DeviceVerificationStatus({ crossSigningVerified: true, localVerified: true });
@@ -595,7 +586,6 @@ describe("<SessionManagerTab />", () => {
mockClient.getDevices.mockResolvedValue({
devices: [alicesDevice, alicesMobileDevice],
});
mockClient.getStoredDevice.mockImplementation((_userId, deviceId) => new DeviceInfo(deviceId));
mockCrypto.getDeviceVerificationStatus.mockImplementation(async (_userId, deviceId) => {
// current session verified = able to verify other sessions
if (deviceId === alicesDevice.device_id) {
@@ -629,7 +619,6 @@ describe("<SessionManagerTab />", () => {
mockClient.getDevices.mockResolvedValue({
devices: [alicesDevice, alicesMobileDevice],
});
mockClient.getStoredDevice.mockImplementation((_userId, deviceId) => new DeviceInfo(deviceId));
mockCrypto.getDeviceVerificationStatus.mockImplementation(async (_userId, deviceId) => {
if (deviceId === alicesDevice.device_id) {
return new DeviceVerificationStatus({ crossSigningVerified: true, localVerified: true });
@@ -667,7 +656,6 @@ describe("<SessionManagerTab />", () => {
mockClient.getDevices.mockResolvedValue({
devices: [alicesDevice, alicesMobileDevice, alicesDehydratedDevice],
});
mockClient.getStoredDevice.mockImplementation((_userId, deviceId) => new DeviceInfo(deviceId));
const devicesMap = new Map<string, Device>([
[alicesDeviceObj.deviceId, alicesDeviceObj],
@@ -708,7 +696,6 @@ describe("<SessionManagerTab />", () => {
mockClient.getDevices.mockResolvedValue({
devices: [alicesDevice, alicesMobileDevice, alicesDehydratedDevice],
});
mockClient.getStoredDevice.mockImplementation((_userId, deviceId) => new DeviceInfo(deviceId));
const devicesMap = new Map<string, Device>([
[alicesDeviceObj.deviceId, alicesDeviceObj],
@@ -749,7 +736,6 @@ describe("<SessionManagerTab />", () => {
mockClient.getDevices.mockResolvedValue({
devices: [alicesDevice, alicesMobileDevice, alicesDehydratedDevice, alicesOtherDehydratedDevice],
});
mockClient.getStoredDevice.mockImplementation((_userId, deviceId) => new DeviceInfo(deviceId));
const devicesMap = new Map<string, Device>([
[alicesDeviceObj.deviceId, alicesDeviceObj],
@@ -85,7 +85,7 @@ const drop = async (element: HTMLElement) => {
};
jest.mock("../../../../../src/stores/spaces/SpaceStore", () => {
// eslint-disable-next-line @typescript-eslint/no-var-requires
// eslint-disable-next-line @typescript-eslint/no-require-imports
const EventEmitter = require("events");
class MockSpaceStore extends EventEmitter {
invitedSpaces: SpaceKey[] = [];
@@ -21,7 +21,7 @@ import { StaticNotificationState } from "../../../../../src/stores/notifications
import { NotificationLevel } from "../../../../../src/stores/notifications/NotificationLevel";
jest.mock("../../../../../src/stores/spaces/SpaceStore", () => {
// eslint-disable-next-line @typescript-eslint/no-var-requires
// eslint-disable-next-line @typescript-eslint/no-require-imports
const EventEmitter = require("events");
class MockSpaceStore extends EventEmitter {
activeSpace: SpaceKey = "!space1";
+2 -6
View File
@@ -40,15 +40,11 @@ describe("SdkContextClass", () => {
});
it("userProfilesStore should raise an error without a client", () => {
expect(() => {
sdkContext.userProfilesStore;
}).toThrow("Unable to create UserProfilesStore without a client");
expect(() => sdkContext.userProfilesStore).toThrow("Unable to create UserProfilesStore without a client");
});
it("oidcClientStore should raise an error without a client", () => {
expect(() => {
sdkContext.oidcClientStore;
}).toThrow("Unable to create OidcClientStore without a client");
expect(() => sdkContext.oidcClientStore).toThrow("Unable to create OidcClientStore without a client");
});
describe("when SDKContext has a client", () => {
+6 -6
View File
@@ -358,12 +358,12 @@ describe("JitsiCall", () => {
new CustomEvent("widgetapirequest", { detail: {} }),
);
await waitFor(() => {
expect(callback).toHaveBeenNthCalledWith(1, ConnectionState.Disconnected, ConnectionState.Connected),
expect(callback).toHaveBeenNthCalledWith(
2,
ConnectionState.WidgetLoading,
ConnectionState.Disconnected,
);
expect(callback).toHaveBeenNthCalledWith(1, ConnectionState.Disconnected, ConnectionState.Connected);
expect(callback).toHaveBeenNthCalledWith(
2,
ConnectionState.WidgetLoading,
ConnectionState.Disconnected,
);
expect(callback).toHaveBeenNthCalledWith(3, ConnectionState.Connecting, ConnectionState.WidgetLoading);
});
// in video rooms we expect the call to immediately reconnect
@@ -49,7 +49,7 @@ describe("BreadcrumbsStore", () => {
it("passes through the dynamic room precessors flag", () => {
mocked(client.getVisibleRooms).mockReturnValue(fakeRooms(25));
store.meetsRoomRequirement;
expect(store.meetsRoomRequirement).toBeTruthy();
expect(client.getVisibleRooms).toHaveBeenCalledWith(true);
});
});
@@ -57,7 +57,7 @@ describe("BreadcrumbsStore", () => {
describe("And the feature_dynamic_room_predecessors is not enabled", () => {
it("passes through the dynamic room precessors flag", () => {
mocked(client.getVisibleRooms).mockReturnValue(fakeRooms(25));
store.meetsRoomRequirement;
expect(store.meetsRoomRequirement).toBeTruthy();
expect(client.getVisibleRooms).toHaveBeenCalledWith(false);
});
});
@@ -70,7 +70,7 @@ describe("OwnProfileStore", () => {
);
try {
await ownProfileStore.start();
} catch (ignore) {}
} catch {}
expect(onUpdate).not.toHaveBeenCalled();
expect(ownProfileStore.displayName).toBe(client.getSafeUserId());
+1 -1
View File
@@ -465,7 +465,7 @@ describe("RoomViewStore", function () {
try {
expect(setRoomVisible.mock.calls[i][0]).toEqual(v[0]);
expect(setRoomVisible.mock.calls[i][1]).toEqual(v[1]);
} catch (err) {
} catch {
throw new Error(`i=${i} got ${setRoomVisible.mock.calls[i]} want ${v}`);
}
});
@@ -353,7 +353,6 @@ describe("RoomListStore", () => {
const videoRoomKnock = "!videoRoomKnock_server";
const rooms: Room[] = [];
RoomListStore.instance;
mkRoom(client, videoRoomPrivate, rooms);
mkRoom(client, videoRoomPublic, rooms);
mkRoom(client, videoRoomKnock, rooms);
@@ -17,7 +17,7 @@ import SpaceStore from "../../../../../src/stores/spaces/SpaceStore";
jest.mock("../../../../../src/settings/SettingsStore");
jest.mock("../../../../../src/stores/spaces/SpaceStore", () => {
// eslint-disable-next-line @typescript-eslint/no-var-requires
// eslint-disable-next-line @typescript-eslint/no-require-imports
const EventEmitter = require("events");
class MockSpaceStore extends EventEmitter {
isRoomInSpace = jest.fn();
@@ -11,7 +11,6 @@ import { render, RenderResult, screen } from "jest-matrix-react";
import userEvent from "@testing-library/user-event";
import { mocked, Mocked } from "jest-mock";
import { IMyDevice, MatrixClient } from "matrix-js-sdk/src/matrix";
import { DeviceInfo } from "matrix-js-sdk/src/crypto/deviceinfo";
import { CryptoApi, DeviceVerificationStatus } from "matrix-js-sdk/src/crypto-api";
import dis from "../../../src/dispatcher/dispatcher";
@@ -25,7 +24,6 @@ describe("UnverifiedSessionToast", () => {
const otherDevice: IMyDevice = {
device_id: "ABC123",
};
const otherDeviceInfo = new DeviceInfo(otherDevice.device_id);
let client: Mocked<MatrixClient>;
let renderResult: RenderResult;
@@ -40,13 +38,6 @@ describe("UnverifiedSessionToast", () => {
throw new Error(`Unknown device ${deviceId}`);
});
client.getStoredDevice.mockImplementation((userId: string, deviceId: string) => {
if (deviceId === otherDevice.device_id) {
return otherDeviceInfo;
}
return null;
});
client.getCrypto.mockReturnValue({
getDeviceVerificationStatus: jest
.fn()
@@ -74,6 +74,7 @@ describe("MegolmExportEncryption", function () {
subtle: webCrypto.subtle,
},
});
// eslint-disable-next-line @typescript-eslint/no-require-imports
MegolmExportEncryption = require("../../../src/utils/MegolmExportEncryption");
});
@@ -218,7 +218,9 @@ describe("SessionLock", () => {
const window2 = createWindow();
// import the dependencies of getSessionLock into the new context
// eslint-disable-next-line @typescript-eslint/no-require-imports
window2._uuid = require("uuid");
// eslint-disable-next-line @typescript-eslint/no-require-imports
window2._logger = require("matrix-js-sdk/src/logger");
window2.SESSION_LOCK_CONSTANTS = SESSION_LOCK_CONSTANTS;
+1 -1
View File
@@ -14,7 +14,7 @@ describe("Singleflight", () => {
});
it("should throw for bad context variables", () => {
const permutations: [Object | null, string | null][] = [
const permutations: [object | null, string | null][] = [
[null, null],
[{}, null],
[null, "test"],
+1 -1
View File
@@ -76,7 +76,7 @@ describe("local-room", () => {
it("should resolve the promise after invoking the callback", async () => {
localRoom.afterCreateCallbacks.forEach((callback) => {
callback(localRoom.actualRoomId);
callback(localRoom.actualRoomId!);
});
await prom;
});
@@ -47,7 +47,9 @@ describe("ElectronPlatform", () => {
setupLanguageMock();
});
const getElectronEventHandlerCall = (eventType: string): [type: string, handler: Function] | undefined =>
const getElectronEventHandlerCall = (
eventType: string,
): [type: string, handler: (...args: any) => void] | undefined =>
mockElectron.on.mock.calls.find(([type]) => type === eventType);
it("flushes rageshake before quitting", () => {
@@ -162,7 +162,11 @@ describe("VoiceBroadcastPlayback", () => {
jest.spyOn(playback, "removeAllListeners");
jest.spyOn(playback, "destroy");
playback.on(VoiceBroadcastPlaybackEvent.StateChanged, onStateChanged);
fakeTimers ? await flushPromisesWithFakeTimers() : await flushPromises();
if (fakeTimers) {
await flushPromisesWithFakeTimers();
} else {
await flushPromises();
}
return playback;
};
@@ -453,7 +453,7 @@ describe("VoiceBroadcastRecording", () => {
describe.each([
["pause", async () => voiceBroadcastRecording.pause()],
["toggle", async () => voiceBroadcastRecording.toggle()],
])("and calling %s", (_case: string, action: Function) => {
])("and calling %s", (_case: string, action: () => Promise<void>) => {
beforeEach(async () => {
await action();
});
@@ -480,7 +480,7 @@ describe("VoiceBroadcastRecording", () => {
describe.each([
["pause", async () => voiceBroadcastRecording.pause()],
["toggle", async () => voiceBroadcastRecording.toggle()],
])("and calling %s", (_case: string, action: Function) => {
])("and calling %s", (_case: string, action: () => Promise<void>) => {
beforeEach(async () => {
await action();
});
@@ -590,7 +590,7 @@ describe("VoiceBroadcastRecording", () => {
describe.each([
["resume", async () => voiceBroadcastRecording.resume()],
["toggle", async () => voiceBroadcastRecording.toggle()],
])("and calling %s", (_case: string, action: Function) => {
])("and calling %s", (_case: string, action: () => Promise<void>) => {
beforeEach(async () => {
await action();
});