mv element.io @types __mocks__/ debian docker module_system/ playwright res src test webapp Dockerfile .dockerignore .eslintignore .stylelintrc.cjs babel.config.cjs recorder-worklet-loader.cjs .modernizr.json components.json config.json config.sample.json package.json project.json tsconfig.json tsconfig.module_system.json jest.config.ts playwright.config.ts webpack.config.ts build_config.sample.yaml apps/web/
mkdir apps/web/scripts
mv scripts/{cleanup.sh,ci_package.sh,copy-res.ts,deploy.py,package.sh} apps/web/scripts
And a couple of gitignore tweaks
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import { type MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
import { render, screen, waitFor } from "jest-matrix-react";
|
||||
import { type KeyBackupInfo } from "matrix-js-sdk/src/crypto-api";
|
||||
|
||||
import { createTestClient, withClientContextRenderOptions } from "../../../../../test-utils";
|
||||
import { Crypto } from "../../../../../../src/components/views/dialogs/devtools/Crypto";
|
||||
|
||||
describe("<Crypto />", () => {
|
||||
let matrixClient: MatrixClient;
|
||||
beforeEach(() => {
|
||||
matrixClient = createTestClient();
|
||||
});
|
||||
|
||||
function renderComponent() {
|
||||
return render(<Crypto onBack={jest.fn} />, withClientContextRenderOptions(matrixClient));
|
||||
}
|
||||
|
||||
it("should display message if crypto is not available", async () => {
|
||||
jest.spyOn(matrixClient, "getCrypto").mockReturnValue(undefined);
|
||||
renderComponent();
|
||||
expect(screen.getByText("Cryptographic module is not available")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
describe("<KeyStorage />", () => {
|
||||
it("should display loading spinner while loading", async () => {
|
||||
jest.spyOn(matrixClient.getCrypto()!, "getKeyBackupInfo").mockImplementation(() => new Promise(() => {}));
|
||||
renderComponent();
|
||||
await waitFor(() => expect(screen.getByLabelText("Loading…")).toBeInTheDocument());
|
||||
});
|
||||
|
||||
it("should display when the key storage data are missing", async () => {
|
||||
renderComponent();
|
||||
await waitFor(() => expect(screen.getByRole("table", { name: "Key Storage" })).toBeInTheDocument());
|
||||
expect(screen.getByRole("table", { name: "Key Storage" })).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should display when the key storage data are available", async () => {
|
||||
jest.spyOn(matrixClient.getCrypto()!, "getKeyBackupInfo").mockResolvedValue({
|
||||
algorithm: "m.megolm_backup.v1",
|
||||
version: "1",
|
||||
} as unknown as KeyBackupInfo);
|
||||
jest.spyOn(matrixClient, "isKeyBackupKeyStored").mockResolvedValue({});
|
||||
jest.spyOn(matrixClient.getCrypto()!, "getSessionBackupPrivateKey").mockResolvedValue(new Uint8Array(32));
|
||||
jest.spyOn(matrixClient.getCrypto()!, "getActiveSessionBackupVersion").mockResolvedValue("2");
|
||||
jest.spyOn(matrixClient.secretStorage, "hasKey").mockResolvedValue(true);
|
||||
jest.spyOn(matrixClient.getCrypto()!, "isSecretStorageReady").mockResolvedValue(true);
|
||||
|
||||
renderComponent();
|
||||
await waitFor(() => expect(screen.getByRole("table", { name: "Key Storage" })).toBeInTheDocument());
|
||||
expect(screen.getByRole("table", { name: "Key Storage" })).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe("<CrossSigning />", () => {
|
||||
it("should display loading spinner while loading", async () => {
|
||||
jest.spyOn(matrixClient.getCrypto()!, "getCrossSigningStatus").mockImplementation(
|
||||
() => new Promise(() => {}),
|
||||
);
|
||||
renderComponent();
|
||||
await waitFor(() => expect(screen.getByLabelText("Loading…")).toBeInTheDocument());
|
||||
});
|
||||
|
||||
it("should display when the cross-signing data are missing", async () => {
|
||||
renderComponent();
|
||||
await waitFor(() => expect(screen.getByRole("table", { name: "Cross-signing" })).toBeInTheDocument());
|
||||
expect(screen.getByRole("table", { name: "Cross-signing" })).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should display when the cross-signing data are available", async () => {
|
||||
jest.spyOn(matrixClient.getCrypto()!, "getCrossSigningStatus").mockResolvedValue({
|
||||
publicKeysOnDevice: true,
|
||||
privateKeysInSecretStorage: true,
|
||||
privateKeysCachedLocally: {
|
||||
masterKey: true,
|
||||
selfSigningKey: true,
|
||||
userSigningKey: true,
|
||||
},
|
||||
});
|
||||
jest.spyOn(matrixClient.getCrypto()!, "isCrossSigningReady").mockResolvedValue(true);
|
||||
|
||||
renderComponent();
|
||||
await waitFor(() => expect(screen.getByRole("table", { name: "Cross-signing" })).toBeInTheDocument());
|
||||
expect(screen.getByRole("table", { name: "Cross-signing" })).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import { render } from "jest-matrix-react";
|
||||
import { Room, PendingEventOrdering } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import MatrixClientContext from "../../../../../../src/contexts/MatrixClientContext";
|
||||
import { MatrixClientPeg } from "../../../../../../src/MatrixClientPeg";
|
||||
import { stubClient } from "../../../../../test-utils";
|
||||
import { DevtoolsContext } from "../../../../../../src/components/views/dialogs/devtools/BaseTool";
|
||||
import { TimelineEventEditor } from "../../../../../../src/components/views/dialogs/devtools/Event";
|
||||
|
||||
describe("<EventEditor />", () => {
|
||||
beforeEach(() => {
|
||||
stubClient();
|
||||
});
|
||||
|
||||
it("should render", () => {
|
||||
const cli = MatrixClientPeg.safeGet();
|
||||
const { asFragment } = render(
|
||||
<MatrixClientContext.Provider value={cli}>
|
||||
<DevtoolsContext.Provider
|
||||
value={{
|
||||
room: new Room("!roomId", cli, "@alice:example.com", {
|
||||
pendingEventOrdering: PendingEventOrdering.Detached,
|
||||
}),
|
||||
}}
|
||||
>
|
||||
<TimelineEventEditor onBack={() => {}} />
|
||||
</DevtoolsContext.Provider>
|
||||
</MatrixClientContext.Provider>,
|
||||
);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe("thread context", () => {
|
||||
it("should pre-populate a thread relationship", () => {
|
||||
const cli = MatrixClientPeg.safeGet();
|
||||
const { asFragment } = render(
|
||||
<MatrixClientContext.Provider value={cli}>
|
||||
<DevtoolsContext.Provider
|
||||
value={{
|
||||
room: new Room("!roomId", cli, "@alice:example.com", {
|
||||
pendingEventOrdering: PendingEventOrdering.Detached,
|
||||
}),
|
||||
threadRootId: "$this_is_a_thread_id",
|
||||
}}
|
||||
>
|
||||
<TimelineEventEditor onBack={() => {}} />
|
||||
</DevtoolsContext.Provider>
|
||||
</MatrixClientContext.Provider>,
|
||||
);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import { render } from "jest-matrix-react";
|
||||
import { Room, PendingEventOrdering } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import RoomNotifications from "../../../../../../src/components/views/dialogs/devtools/RoomNotifications";
|
||||
import MatrixClientContext from "../../../../../../src/contexts/MatrixClientContext";
|
||||
import { MatrixClientPeg } from "../../../../../../src/MatrixClientPeg";
|
||||
import { stubClient } from "../../../../../test-utils";
|
||||
import { DevtoolsContext } from "../../../../../../src/components/views/dialogs/devtools/BaseTool";
|
||||
|
||||
describe("<RoomNotifications />", () => {
|
||||
beforeEach(() => {
|
||||
stubClient();
|
||||
});
|
||||
|
||||
it("should render", () => {
|
||||
const cli = MatrixClientPeg.safeGet();
|
||||
const { asFragment } = render(
|
||||
<MatrixClientContext.Provider value={cli}>
|
||||
<DevtoolsContext.Provider
|
||||
value={{
|
||||
room: new Room("!roomId", cli, "@alice:example.com", {
|
||||
pendingEventOrdering: PendingEventOrdering.Detached,
|
||||
}),
|
||||
}}
|
||||
>
|
||||
<RoomNotifications onBack={() => {}} setTool={() => {}} />
|
||||
</DevtoolsContext.Provider>
|
||||
</MatrixClientContext.Provider>,
|
||||
);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,361 @@
|
||||
/*
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import { mocked } from "jest-mock";
|
||||
import { Device, DeviceVerification, type MatrixClient, MatrixEvent, RoomMember } from "matrix-js-sdk/src/matrix";
|
||||
import { render, screen, waitFor } from "jest-matrix-react";
|
||||
import { Room, PendingEventOrdering } from "matrix-js-sdk/src/matrix";
|
||||
import { type DeviceVerificationStatus, type UserVerificationStatus } from "matrix-js-sdk/src/crypto-api";
|
||||
|
||||
import { createTestClient } from "../../../../../test-utils";
|
||||
import MatrixClientContext from "../../../../../../src/contexts/MatrixClientContext";
|
||||
import { DevtoolsContext } from "../../../../../../src/components/views/dialogs/devtools/BaseTool";
|
||||
import { UserList } from "../../../../../../src/components/views/dialogs/devtools/Users";
|
||||
|
||||
const userId = "@alice:example.com";
|
||||
|
||||
describe("<Users />", () => {
|
||||
let matrixClient: MatrixClient;
|
||||
beforeEach(() => {
|
||||
matrixClient = createTestClient();
|
||||
});
|
||||
|
||||
it("should render a user list", () => {
|
||||
const room = new Room("!roomId", matrixClient, userId, {
|
||||
pendingEventOrdering: PendingEventOrdering.Detached,
|
||||
});
|
||||
room.getJoinedMembers = jest.fn().mockReturnValue([]);
|
||||
|
||||
const { asFragment } = render(
|
||||
<MatrixClientContext.Provider value={matrixClient}>
|
||||
<DevtoolsContext.Provider value={{ room }}>
|
||||
<UserList onBack={() => {}} />
|
||||
</DevtoolsContext.Provider>
|
||||
</MatrixClientContext.Provider>,
|
||||
);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should render a single user", async () => {
|
||||
const room = new Room("!roomId", matrixClient, userId, {
|
||||
pendingEventOrdering: PendingEventOrdering.Detached,
|
||||
});
|
||||
|
||||
const alice = new RoomMember("!roomId", userId);
|
||||
alice.setMembershipEvent(
|
||||
new MatrixEvent({
|
||||
content: {
|
||||
membership: "join",
|
||||
},
|
||||
state_key: userId,
|
||||
room_id: "!roomId",
|
||||
type: "m.room.member",
|
||||
sender: userId,
|
||||
}),
|
||||
);
|
||||
room.getJoinedMembers = jest.fn().mockReturnValue([alice]);
|
||||
|
||||
mocked(matrixClient.getCrypto()!.getUserVerificationStatus).mockResolvedValue({
|
||||
isCrossSigningVerified: jest.fn().mockReturnValue(true),
|
||||
wasCrossSigningVerified: jest.fn().mockReturnValue(true),
|
||||
needsUserApproval: false,
|
||||
} as unknown as UserVerificationStatus);
|
||||
mocked(matrixClient.getCrypto()!.getUserDeviceInfo).mockResolvedValue(
|
||||
new Map([
|
||||
[
|
||||
userId,
|
||||
new Map([
|
||||
[
|
||||
"VERIFIED",
|
||||
new Device({
|
||||
deviceId: "VERIFIED",
|
||||
userId: userId,
|
||||
algorithms: [],
|
||||
keys: new Map([
|
||||
["ed25519:VERIFIED", "an_ed25519_public_key"],
|
||||
["curve25519:VERIFIED", "a_curve25519_public_key"],
|
||||
]),
|
||||
}),
|
||||
],
|
||||
[
|
||||
"SIGNED",
|
||||
new Device({
|
||||
deviceId: "SIGNED",
|
||||
userId: userId,
|
||||
algorithms: [],
|
||||
keys: new Map([
|
||||
["ed25519:SIGNED", "an_ed25519_public_key"],
|
||||
["curve25519:SIGNED", "a_curve25519_public_key"],
|
||||
]),
|
||||
}),
|
||||
],
|
||||
[
|
||||
"UNSIGNED",
|
||||
new Device({
|
||||
deviceId: "UNSIGNED",
|
||||
userId: userId,
|
||||
algorithms: [],
|
||||
keys: new Map([
|
||||
["ed25519:UNSIGNED", "an_ed25519_public_key"],
|
||||
["curve25519:UNSIGNED", "a_curve25519_public_key"],
|
||||
]),
|
||||
}),
|
||||
],
|
||||
]),
|
||||
],
|
||||
]),
|
||||
);
|
||||
mocked(matrixClient.getCrypto()!.getDeviceVerificationStatus).mockImplementation(
|
||||
async (userId: string, deviceId: string) => {
|
||||
switch (deviceId) {
|
||||
case "VERIFIED":
|
||||
return {
|
||||
signedByOwner: true,
|
||||
crossSigningVerified: true,
|
||||
} as unknown as DeviceVerificationStatus;
|
||||
case "SIGNED":
|
||||
return {
|
||||
signedByOwner: true,
|
||||
crossSigningVerified: false,
|
||||
} as unknown as DeviceVerificationStatus;
|
||||
case "UNSIGNED":
|
||||
return {
|
||||
signedByOwner: false,
|
||||
crossSigningVerified: false,
|
||||
} as unknown as DeviceVerificationStatus;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const { asFragment } = render(
|
||||
<MatrixClientContext.Provider value={matrixClient}>
|
||||
<DevtoolsContext.Provider value={{ room }}>
|
||||
<UserList onBack={() => {}} />
|
||||
</DevtoolsContext.Provider>
|
||||
</MatrixClientContext.Provider>,
|
||||
);
|
||||
|
||||
screen.getByRole("button", { name: userId }).click();
|
||||
|
||||
await waitFor(() => expect(screen.getByText(/Verification status:/)).toHaveTextContent(/Verified/));
|
||||
await waitFor(() => expect(screen.getByRole("button", { name: "VERIFIED" })).toBeInTheDocument());
|
||||
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should render a single device - verified by cross-signing", async () => {
|
||||
const room = new Room("!roomId", matrixClient, userId, {
|
||||
pendingEventOrdering: PendingEventOrdering.Detached,
|
||||
});
|
||||
|
||||
const alice = new RoomMember("!roomId", userId);
|
||||
alice.setMembershipEvent(
|
||||
new MatrixEvent({
|
||||
content: {
|
||||
membership: "join",
|
||||
},
|
||||
state_key: userId,
|
||||
room_id: "!roomId",
|
||||
type: "m.room.member",
|
||||
sender: userId,
|
||||
}),
|
||||
);
|
||||
room.getJoinedMembers = jest.fn().mockReturnValue([alice]);
|
||||
|
||||
mocked(matrixClient.getCrypto()!.getUserVerificationStatus).mockResolvedValue({
|
||||
isCrossSigningVerified: jest.fn().mockReturnValue(true),
|
||||
wasCrossSigningVerified: jest.fn().mockReturnValue(true),
|
||||
needsUserApproval: false,
|
||||
} as unknown as UserVerificationStatus);
|
||||
mocked(matrixClient.getCrypto()!.getUserDeviceInfo).mockResolvedValue(
|
||||
new Map([
|
||||
[
|
||||
userId,
|
||||
new Map([
|
||||
[
|
||||
"VERIFIED",
|
||||
new Device({
|
||||
deviceId: "VERIFIED",
|
||||
userId: userId,
|
||||
algorithms: [],
|
||||
keys: new Map([
|
||||
["ed25519:VERIFIED", "an_ed25519_public_key"],
|
||||
["curve25519:VERIFIED", "a_curve25519_public_key"],
|
||||
]),
|
||||
}),
|
||||
],
|
||||
]),
|
||||
],
|
||||
]),
|
||||
);
|
||||
mocked(matrixClient.getCrypto()!.getDeviceVerificationStatus).mockResolvedValue({
|
||||
signedByOwner: true,
|
||||
crossSigningVerified: true,
|
||||
} as unknown as DeviceVerificationStatus);
|
||||
|
||||
const { asFragment } = render(
|
||||
<MatrixClientContext.Provider value={matrixClient}>
|
||||
<DevtoolsContext.Provider value={{ room }}>
|
||||
<UserList onBack={() => {}} />
|
||||
</DevtoolsContext.Provider>
|
||||
</MatrixClientContext.Provider>,
|
||||
);
|
||||
|
||||
screen.getByRole("button", { name: userId }).click();
|
||||
|
||||
await waitFor(() => expect(screen.getByRole("button", { name: "VERIFIED" })).toBeInTheDocument());
|
||||
screen.getByRole("button", { name: "VERIFIED" }).click();
|
||||
|
||||
await waitFor(() =>
|
||||
expect(screen.getByText(/Verification status:/)).toHaveTextContent(/Verified by cross-signing/),
|
||||
);
|
||||
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should render a single device - signed by owner", async () => {
|
||||
const room = new Room("!roomId", matrixClient, userId, {
|
||||
pendingEventOrdering: PendingEventOrdering.Detached,
|
||||
});
|
||||
|
||||
const alice = new RoomMember("!roomId", userId);
|
||||
alice.setMembershipEvent(
|
||||
new MatrixEvent({
|
||||
content: {
|
||||
membership: "join",
|
||||
},
|
||||
state_key: userId,
|
||||
room_id: "!roomId",
|
||||
type: "m.room.member",
|
||||
sender: userId,
|
||||
}),
|
||||
);
|
||||
room.getJoinedMembers = jest.fn().mockReturnValue([alice]);
|
||||
|
||||
mocked(matrixClient.getCrypto()!.getUserVerificationStatus).mockResolvedValue({
|
||||
isCrossSigningVerified: jest.fn().mockReturnValue(true),
|
||||
wasCrossSigningVerified: jest.fn().mockReturnValue(true),
|
||||
needsUserApproval: false,
|
||||
} as unknown as UserVerificationStatus);
|
||||
mocked(matrixClient.getCrypto()!.getUserDeviceInfo).mockResolvedValue(
|
||||
new Map([
|
||||
[
|
||||
userId,
|
||||
new Map([
|
||||
[
|
||||
"SIGNED",
|
||||
new Device({
|
||||
deviceId: "SIGNED",
|
||||
userId: userId,
|
||||
algorithms: [],
|
||||
keys: new Map([
|
||||
["ed25519:SIGNED", "an_ed25519_public_key"],
|
||||
["curve25519:SIGNED", "a_curve25519_public_key"],
|
||||
]),
|
||||
}),
|
||||
],
|
||||
]),
|
||||
],
|
||||
]),
|
||||
);
|
||||
mocked(matrixClient.getCrypto()!.getDeviceVerificationStatus).mockResolvedValue({
|
||||
signedByOwner: true,
|
||||
crossSigningVerified: false,
|
||||
} as unknown as DeviceVerificationStatus);
|
||||
|
||||
const { asFragment } = render(
|
||||
<MatrixClientContext.Provider value={matrixClient}>
|
||||
<DevtoolsContext.Provider value={{ room }}>
|
||||
<UserList onBack={() => {}} />
|
||||
</DevtoolsContext.Provider>
|
||||
</MatrixClientContext.Provider>,
|
||||
);
|
||||
|
||||
screen.getByRole("button", { name: userId }).click();
|
||||
|
||||
await waitFor(() => expect(screen.getByRole("button", { name: "SIGNED" })).toBeInTheDocument());
|
||||
screen.getByRole("button", { name: "SIGNED" }).click();
|
||||
|
||||
await waitFor(() => expect(screen.getByText(/Verification status:/)).toHaveTextContent(/Signed by owner/));
|
||||
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should render a single device - unsigned", async () => {
|
||||
const room = new Room("!roomId", matrixClient, userId, {
|
||||
pendingEventOrdering: PendingEventOrdering.Detached,
|
||||
});
|
||||
|
||||
const alice = new RoomMember("!roomId", userId);
|
||||
alice.setMembershipEvent(
|
||||
new MatrixEvent({
|
||||
content: {
|
||||
membership: "join",
|
||||
},
|
||||
state_key: userId,
|
||||
room_id: "!roomId",
|
||||
type: "m.room.member",
|
||||
sender: userId,
|
||||
}),
|
||||
);
|
||||
room.getJoinedMembers = jest.fn().mockReturnValue([alice]);
|
||||
|
||||
mocked(matrixClient.getCrypto()!.getUserVerificationStatus).mockResolvedValue({
|
||||
isCrossSigningVerified: jest.fn().mockReturnValue(true),
|
||||
wasCrossSigningVerified: jest.fn().mockReturnValue(true),
|
||||
needsUserApproval: false,
|
||||
} as unknown as UserVerificationStatus);
|
||||
mocked(matrixClient.getCrypto()!.getUserDeviceInfo).mockResolvedValue(
|
||||
new Map([
|
||||
[
|
||||
userId,
|
||||
new Map([
|
||||
[
|
||||
"UNSIGNED",
|
||||
new Device({
|
||||
deviceId: "UNSIGNED",
|
||||
userId: userId,
|
||||
algorithms: [],
|
||||
keys: new Map([
|
||||
["ed25519:UNSIGNED", "an_ed25519_public_key"],
|
||||
["curve25519:UNSIGNED", "a_curve25519_public_key"],
|
||||
]),
|
||||
verified: DeviceVerification.Verified,
|
||||
}),
|
||||
],
|
||||
]),
|
||||
],
|
||||
]),
|
||||
);
|
||||
mocked(matrixClient.getCrypto()!.getDeviceVerificationStatus).mockResolvedValue({
|
||||
signedByOwner: false,
|
||||
crossSigningVerified: false,
|
||||
} as unknown as DeviceVerificationStatus);
|
||||
|
||||
const { asFragment } = render(
|
||||
<MatrixClientContext.Provider value={matrixClient}>
|
||||
<DevtoolsContext.Provider value={{ room }}>
|
||||
<UserList onBack={() => {}} />
|
||||
</DevtoolsContext.Provider>
|
||||
</MatrixClientContext.Provider>,
|
||||
);
|
||||
|
||||
screen.getByRole("button", { name: userId }).click();
|
||||
|
||||
await waitFor(() => expect(screen.getByText(/Verification status:/)).toHaveTextContent(/Verified/));
|
||||
|
||||
await waitFor(() => expect(screen.getByRole("button", { name: "UNSIGNED" })).toBeInTheDocument());
|
||||
screen.getByRole("button", { name: "UNSIGNED" }).click();
|
||||
|
||||
await waitFor(() => expect(screen.getByText(/Verification status:/)).toHaveTextContent(/Not signed by owner/));
|
||||
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
+289
@@ -0,0 +1,289 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`<Crypto /> <CrossSigning /> should display when the cross-signing data are available 1`] = `
|
||||
<table
|
||||
aria-label="Cross-signing"
|
||||
>
|
||||
<thead>
|
||||
Cross-signing
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th
|
||||
scope="row"
|
||||
>
|
||||
Cross-signing status:
|
||||
</th>
|
||||
<td>
|
||||
Cross-signing is ready for use.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
scope="row"
|
||||
>
|
||||
Cross-signing public keys:
|
||||
</th>
|
||||
<td>
|
||||
in memory
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
scope="row"
|
||||
>
|
||||
Cross-signing private keys:
|
||||
</th>
|
||||
<td>
|
||||
in secret storage
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
scope="row"
|
||||
>
|
||||
Master private key:
|
||||
</th>
|
||||
<td>
|
||||
cached locally
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
scope="row"
|
||||
>
|
||||
Self signing private key:
|
||||
</th>
|
||||
<td>
|
||||
cached locally
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
scope="row"
|
||||
>
|
||||
User signing private key:
|
||||
</th>
|
||||
<td>
|
||||
cached locally
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
`;
|
||||
|
||||
exports[`<Crypto /> <CrossSigning /> should display when the cross-signing data are missing 1`] = `
|
||||
<table
|
||||
aria-label="Cross-signing"
|
||||
>
|
||||
<thead>
|
||||
Cross-signing
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th
|
||||
scope="row"
|
||||
>
|
||||
Cross-signing status:
|
||||
</th>
|
||||
<td>
|
||||
Cross-signing is not set up.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
scope="row"
|
||||
>
|
||||
Cross-signing public keys:
|
||||
</th>
|
||||
<td>
|
||||
not found
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
scope="row"
|
||||
>
|
||||
Cross-signing private keys:
|
||||
</th>
|
||||
<td>
|
||||
not found in storage
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
scope="row"
|
||||
>
|
||||
Master private key:
|
||||
</th>
|
||||
<td>
|
||||
not found locally
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
scope="row"
|
||||
>
|
||||
Self signing private key:
|
||||
</th>
|
||||
<td>
|
||||
not found locally
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
scope="row"
|
||||
>
|
||||
User signing private key:
|
||||
</th>
|
||||
<td>
|
||||
not found locally
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
`;
|
||||
|
||||
exports[`<Crypto /> <KeyStorage /> should display when the key storage data are available 1`] = `
|
||||
<table
|
||||
aria-label="Key Storage"
|
||||
>
|
||||
<thead>
|
||||
Key Storage
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th
|
||||
scope="row"
|
||||
>
|
||||
Latest backup version on server:
|
||||
</th>
|
||||
<td>
|
||||
1 (Algorithm: m.megolm_backup.v1)
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
scope="row"
|
||||
>
|
||||
Backup key stored:
|
||||
</th>
|
||||
<td>
|
||||
in secret storage
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
scope="row"
|
||||
>
|
||||
Active backup version:
|
||||
</th>
|
||||
<td>
|
||||
2
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
scope="row"
|
||||
>
|
||||
Backup key cached:
|
||||
</th>
|
||||
<td>
|
||||
cached locally, well formed
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
scope="row"
|
||||
>
|
||||
Secret storage public key:
|
||||
</th>
|
||||
<td>
|
||||
in account data
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
scope="row"
|
||||
>
|
||||
Secret storage:
|
||||
</th>
|
||||
<td>
|
||||
ready
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
`;
|
||||
|
||||
exports[`<Crypto /> <KeyStorage /> should display when the key storage data are missing 1`] = `
|
||||
<table
|
||||
aria-label="Key Storage"
|
||||
>
|
||||
<thead>
|
||||
Key Storage
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th
|
||||
scope="row"
|
||||
>
|
||||
Latest backup version on server:
|
||||
</th>
|
||||
<td>
|
||||
Your keys are not being backed up from this session.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
scope="row"
|
||||
>
|
||||
Backup key stored:
|
||||
</th>
|
||||
<td>
|
||||
not stored
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
scope="row"
|
||||
>
|
||||
Active backup version:
|
||||
</th>
|
||||
<td>
|
||||
None
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
scope="row"
|
||||
>
|
||||
Backup key cached:
|
||||
</th>
|
||||
<td>
|
||||
not found locally, unexpected type
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
scope="row"
|
||||
>
|
||||
Secret storage public key:
|
||||
</th>
|
||||
<td>
|
||||
not found
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
scope="row"
|
||||
>
|
||||
Secret storage:
|
||||
</th>
|
||||
<td>
|
||||
not ready
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
`;
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`<EventEditor /> should render 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="mx_DevTools_content"
|
||||
>
|
||||
<div
|
||||
class="mx_DevTools_eventTypeStateKeyGroup"
|
||||
>
|
||||
<div
|
||||
class="mx_Field mx_Field_input"
|
||||
>
|
||||
<input
|
||||
autocomplete="on"
|
||||
id="eventType"
|
||||
label="Event Type"
|
||||
placeholder="Event Type"
|
||||
size="42"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<label
|
||||
for="eventType"
|
||||
>
|
||||
Event Type
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_Field mx_Field_textarea mx_DevTools_textarea"
|
||||
>
|
||||
<textarea
|
||||
autocomplete="off"
|
||||
id="evContent"
|
||||
label="Event Content"
|
||||
placeholder="Event Content"
|
||||
type="text"
|
||||
>
|
||||
{
|
||||
|
||||
}
|
||||
</textarea>
|
||||
<label
|
||||
for="evContent"
|
||||
>
|
||||
Event Content
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_Dialog_buttons"
|
||||
>
|
||||
<button>
|
||||
Back
|
||||
</button>
|
||||
<button>
|
||||
Send
|
||||
</button>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`<EventEditor /> thread context should pre-populate a thread relationship 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="mx_DevTools_content"
|
||||
>
|
||||
<div
|
||||
class="mx_DevTools_eventTypeStateKeyGroup"
|
||||
>
|
||||
<div
|
||||
class="mx_Field mx_Field_input"
|
||||
>
|
||||
<input
|
||||
autocomplete="on"
|
||||
id="eventType"
|
||||
label="Event Type"
|
||||
placeholder="Event Type"
|
||||
size="42"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<label
|
||||
for="eventType"
|
||||
>
|
||||
Event Type
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_Field mx_Field_textarea mx_DevTools_textarea"
|
||||
>
|
||||
<textarea
|
||||
autocomplete="off"
|
||||
id="evContent"
|
||||
label="Event Content"
|
||||
placeholder="Event Content"
|
||||
type="text"
|
||||
>
|
||||
{
|
||||
"m.relates_to": {
|
||||
"rel_type": "m.thread",
|
||||
"event_id": "$this_is_a_thread_id"
|
||||
}
|
||||
}
|
||||
</textarea>
|
||||
<label
|
||||
for="evContent"
|
||||
>
|
||||
Event Content
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_Dialog_buttons"
|
||||
>
|
||||
<button>
|
||||
Back
|
||||
</button>
|
||||
<button>
|
||||
Send
|
||||
</button>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`<RoomNotifications /> should render 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="mx_DevTools_content"
|
||||
>
|
||||
<section>
|
||||
<h2>
|
||||
Room status
|
||||
</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<span>
|
||||
Room unread status:
|
||||
<strong>
|
||||
None
|
||||
</strong>
|
||||
, count:
|
||||
<strong>
|
||||
0
|
||||
</strong>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span>
|
||||
Notification state is
|
||||
<strong />
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span>
|
||||
Room is
|
||||
<strong>
|
||||
not encrypted 🚨
|
||||
</strong>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
<section>
|
||||
<h2>
|
||||
Main timeline
|
||||
</h2>
|
||||
<ul>
|
||||
<li>
|
||||
Total: 0
|
||||
</li>
|
||||
<li>
|
||||
Highlight: 0
|
||||
</li>
|
||||
<li>
|
||||
Dot: false
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
<section>
|
||||
<h2>
|
||||
Threads timeline
|
||||
</h2>
|
||||
<ul />
|
||||
</section>
|
||||
</div>
|
||||
<div
|
||||
class="mx_Dialog_buttons"
|
||||
>
|
||||
<button>
|
||||
Back
|
||||
</button>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
+737
@@ -0,0 +1,737 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`<Users /> should render a single device - signed by owner 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="mx_DevTools_content"
|
||||
>
|
||||
<ul>
|
||||
<li>
|
||||
<div
|
||||
class="mx_CopyableText"
|
||||
>
|
||||
User ID: @alice:example.com
|
||||
<div
|
||||
aria-label="Copy"
|
||||
class="mx_AccessibleButton mx_CopyableText_copyButton"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M14 5H5v9h1a1 1 0 1 1 0 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1a1 1 0 1 1-2 0z"
|
||||
/>
|
||||
<path
|
||||
d="M8 10a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-9a2 2 0 0 1-2-2zm2 0v9h9v-9z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div
|
||||
class="mx_CopyableText"
|
||||
>
|
||||
Device ID: SIGNED
|
||||
<div
|
||||
aria-label="Copy"
|
||||
class="mx_AccessibleButton mx_CopyableText_copyButton"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M14 5H5v9h1a1 1 0 1 1 0 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1a1 1 0 1 1-2 0z"
|
||||
/>
|
||||
<path
|
||||
d="M8 10a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-9a2 2 0 0 1-2-2zm2 0v9h9v-9z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
Displayname:
|
||||
</li>
|
||||
<li>
|
||||
<span>
|
||||
Verification status:
|
||||
<div
|
||||
class="mx_E2EIcon mx_E2EIcon_inline"
|
||||
data-testid="e2e-icon"
|
||||
>
|
||||
<svg
|
||||
color="var(--cpd-color-icon-tertiary)"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M6 22q-.824 0-1.412-.587A1.93 1.93 0 0 1 4 20V10q0-.825.588-1.412A1.93 1.93 0 0 1 6 8h1V6q0-2.075 1.463-3.537Q9.926 1 12 1q2.075 0 3.537 1.463Q17 3.925 17 6v2h1q.824 0 1.413.588Q20 9.175 20 10v10q0 .824-.587 1.413A1.93 1.93 0 0 1 18 22zM9 8h6V6q0-1.25-.875-2.125A2.9 2.9 0 0 0 12 3q-1.25 0-2.125.875A2.9 2.9 0 0 0 9 6z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
Signed by owner
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
Dehydrated: No
|
||||
</li>
|
||||
<li>
|
||||
Device keys
|
||||
<ul>
|
||||
<li>
|
||||
<div
|
||||
class="mx_CopyableText"
|
||||
>
|
||||
ed25519: an_ed25519_public_key
|
||||
<div
|
||||
aria-label="Copy"
|
||||
class="mx_AccessibleButton mx_CopyableText_copyButton"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M14 5H5v9h1a1 1 0 1 1 0 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1a1 1 0 1 1-2 0z"
|
||||
/>
|
||||
<path
|
||||
d="M8 10a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-9a2 2 0 0 1-2-2zm2 0v9h9v-9z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div
|
||||
class="mx_CopyableText"
|
||||
>
|
||||
curve25519: a_curve25519_public_key
|
||||
<div
|
||||
aria-label="Copy"
|
||||
class="mx_AccessibleButton mx_CopyableText_copyButton"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M14 5H5v9h1a1 1 0 1 1 0 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1a1 1 0 1 1-2 0z"
|
||||
/>
|
||||
<path
|
||||
d="M8 10a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-9a2 2 0 0 1-2-2zm2 0v9h9v-9z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div
|
||||
class="mx_Dialog_buttons"
|
||||
>
|
||||
<button>
|
||||
Back
|
||||
</button>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`<Users /> should render a single device - unsigned 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="mx_DevTools_content"
|
||||
>
|
||||
<ul>
|
||||
<li>
|
||||
<div
|
||||
class="mx_CopyableText"
|
||||
>
|
||||
User ID: @alice:example.com
|
||||
<div
|
||||
aria-label="Copy"
|
||||
class="mx_AccessibleButton mx_CopyableText_copyButton"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M14 5H5v9h1a1 1 0 1 1 0 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1a1 1 0 1 1-2 0z"
|
||||
/>
|
||||
<path
|
||||
d="M8 10a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-9a2 2 0 0 1-2-2zm2 0v9h9v-9z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div
|
||||
class="mx_CopyableText"
|
||||
>
|
||||
Device ID: UNSIGNED
|
||||
<div
|
||||
aria-label="Copy"
|
||||
class="mx_AccessibleButton mx_CopyableText_copyButton"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M14 5H5v9h1a1 1 0 1 1 0 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1a1 1 0 1 1-2 0z"
|
||||
/>
|
||||
<path
|
||||
d="M8 10a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-9a2 2 0 0 1-2-2zm2 0v9h9v-9z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
Displayname:
|
||||
</li>
|
||||
<li>
|
||||
<span>
|
||||
Verification status:
|
||||
<div
|
||||
class="mx_E2EIcon mx_E2EIcon_inline"
|
||||
data-testid="e2e-icon"
|
||||
>
|
||||
<svg
|
||||
color="var(--cpd-color-icon-critical-primary)"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M12 17q.424 0 .713-.288A.97.97 0 0 0 13 16a.97.97 0 0 0-.287-.713A.97.97 0 0 0 12 15a.97.97 0 0 0-.713.287A.97.97 0 0 0 11 16q0 .424.287.712.288.288.713.288m0-4q.424 0 .713-.287A.97.97 0 0 0 13 12V8a.97.97 0 0 0-.287-.713A.97.97 0 0 0 12 7a.97.97 0 0 0-.713.287A.97.97 0 0 0 11 8v4q0 .424.287.713.288.287.713.287m0 9a9.7 9.7 0 0 1-3.9-.788 10.1 10.1 0 0 1-3.175-2.137q-1.35-1.35-2.137-3.175A9.7 9.7 0 0 1 2 12q0-2.075.788-3.9a10.1 10.1 0 0 1 2.137-3.175q1.35-1.35 3.175-2.137A9.7 9.7 0 0 1 12 2q2.075 0 3.9.788a10.1 10.1 0 0 1 3.175 2.137q1.35 1.35 2.137 3.175A9.7 9.7 0 0 1 22 12a9.7 9.7 0 0 1-.788 3.9 10.1 10.1 0 0 1-2.137 3.175q-1.35 1.35-3.175 2.137A9.7 9.7 0 0 1 12 22"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
Not signed by owner
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
Dehydrated: No
|
||||
</li>
|
||||
<li>
|
||||
Device keys
|
||||
<ul>
|
||||
<li>
|
||||
<div
|
||||
class="mx_CopyableText"
|
||||
>
|
||||
ed25519: an_ed25519_public_key
|
||||
<div
|
||||
aria-label="Copy"
|
||||
class="mx_AccessibleButton mx_CopyableText_copyButton"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M14 5H5v9h1a1 1 0 1 1 0 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1a1 1 0 1 1-2 0z"
|
||||
/>
|
||||
<path
|
||||
d="M8 10a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-9a2 2 0 0 1-2-2zm2 0v9h9v-9z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div
|
||||
class="mx_CopyableText"
|
||||
>
|
||||
curve25519: a_curve25519_public_key
|
||||
<div
|
||||
aria-label="Copy"
|
||||
class="mx_AccessibleButton mx_CopyableText_copyButton"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M14 5H5v9h1a1 1 0 1 1 0 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1a1 1 0 1 1-2 0z"
|
||||
/>
|
||||
<path
|
||||
d="M8 10a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-9a2 2 0 0 1-2-2zm2 0v9h9v-9z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div
|
||||
class="mx_Dialog_buttons"
|
||||
>
|
||||
<button>
|
||||
Back
|
||||
</button>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`<Users /> should render a single device - verified by cross-signing 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="mx_DevTools_content"
|
||||
>
|
||||
<ul>
|
||||
<li>
|
||||
<div
|
||||
class="mx_CopyableText"
|
||||
>
|
||||
User ID: @alice:example.com
|
||||
<div
|
||||
aria-label="Copy"
|
||||
class="mx_AccessibleButton mx_CopyableText_copyButton"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M14 5H5v9h1a1 1 0 1 1 0 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1a1 1 0 1 1-2 0z"
|
||||
/>
|
||||
<path
|
||||
d="M8 10a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-9a2 2 0 0 1-2-2zm2 0v9h9v-9z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div
|
||||
class="mx_CopyableText"
|
||||
>
|
||||
Device ID: VERIFIED
|
||||
<div
|
||||
aria-label="Copy"
|
||||
class="mx_AccessibleButton mx_CopyableText_copyButton"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M14 5H5v9h1a1 1 0 1 1 0 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1a1 1 0 1 1-2 0z"
|
||||
/>
|
||||
<path
|
||||
d="M8 10a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-9a2 2 0 0 1-2-2zm2 0v9h9v-9z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
Displayname:
|
||||
</li>
|
||||
<li>
|
||||
<span>
|
||||
Verification status:
|
||||
<div
|
||||
class="mx_E2EIcon mx_E2EIcon_inline"
|
||||
data-testid="e2e-icon"
|
||||
>
|
||||
<svg
|
||||
color="var(--cpd-color-icon-success-primary)"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M11.106 2.447a2 2 0 0 1 1.789 0l6 3A2 2 0 0 1 20 7.237V12c0 6.742-5.773 9.246-7.51 9.846-.32.111-.66.111-.98 0C9.774 21.246 4 18.743 4 12V7.236a2 2 0 0 1 1.105-1.789zm4.601 6.846a1 1 0 0 0-1.414 0L11 12.586l-1.293-1.293a1 1 0 0 0-1.414 1.414l2 2a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0 0-1.414"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
Verified by cross-signing
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
Dehydrated: No
|
||||
</li>
|
||||
<li>
|
||||
Device keys
|
||||
<ul>
|
||||
<li>
|
||||
<div
|
||||
class="mx_CopyableText"
|
||||
>
|
||||
ed25519: an_ed25519_public_key
|
||||
<div
|
||||
aria-label="Copy"
|
||||
class="mx_AccessibleButton mx_CopyableText_copyButton"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M14 5H5v9h1a1 1 0 1 1 0 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1a1 1 0 1 1-2 0z"
|
||||
/>
|
||||
<path
|
||||
d="M8 10a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-9a2 2 0 0 1-2-2zm2 0v9h9v-9z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div
|
||||
class="mx_CopyableText"
|
||||
>
|
||||
curve25519: a_curve25519_public_key
|
||||
<div
|
||||
aria-label="Copy"
|
||||
class="mx_AccessibleButton mx_CopyableText_copyButton"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M14 5H5v9h1a1 1 0 1 1 0 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1a1 1 0 1 1-2 0z"
|
||||
/>
|
||||
<path
|
||||
d="M8 10a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-9a2 2 0 0 1-2-2zm2 0v9h9v-9z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div
|
||||
class="mx_Dialog_buttons"
|
||||
>
|
||||
<button>
|
||||
Back
|
||||
</button>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`<Users /> should render a single user 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="mx_DevTools_content"
|
||||
>
|
||||
<ul>
|
||||
<li>
|
||||
<div
|
||||
class="mx_CopyableText"
|
||||
>
|
||||
User ID: @alice:example.com
|
||||
<div
|
||||
aria-label="Copy"
|
||||
class="mx_AccessibleButton mx_CopyableText_copyButton"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M14 5H5v9h1a1 1 0 1 1 0 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1a1 1 0 1 1-2 0z"
|
||||
/>
|
||||
<path
|
||||
d="M8 10a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-9a2 2 0 0 1-2-2zm2 0v9h9v-9z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
Membership: join
|
||||
</li>
|
||||
<li>
|
||||
<span>
|
||||
Displayname:
|
||||
<i>
|
||||
None
|
||||
</i>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span>
|
||||
Avatar:
|
||||
<i>
|
||||
None
|
||||
</i>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span>
|
||||
Verification status:
|
||||
<div
|
||||
class="mx_E2EIcon mx_E2EIcon_inline"
|
||||
data-testid="e2e-icon"
|
||||
>
|
||||
<svg
|
||||
color="var(--cpd-color-icon-success-primary)"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M11.106 2.447a2 2 0 0 1 1.789 0l6 3A2 2 0 0 1 20 7.237V12c0 6.742-5.773 9.246-7.51 9.846-.32.111-.66.111-.98 0C9.774 21.246 4 18.743 4 12V7.236a2 2 0 0 1 1.105-1.789zm4.601 6.846a1 1 0 0 0-1.414 0L11 12.586l-1.293-1.293a1 1 0 0 0-1.414 1.414l2 2a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0 0-1.414"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
Verified
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<section>
|
||||
<h2>
|
||||
Cryptographic devices (3)
|
||||
</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<button
|
||||
class="mx_DevTools_button"
|
||||
>
|
||||
<div
|
||||
class="mx_E2EIcon mx_E2EIcon_inline"
|
||||
data-testid="e2e-icon"
|
||||
>
|
||||
<svg
|
||||
color="var(--cpd-color-icon-success-primary)"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M11.106 2.447a2 2 0 0 1 1.789 0l6 3A2 2 0 0 1 20 7.237V12c0 6.742-5.773 9.246-7.51 9.846-.32.111-.66.111-.98 0C9.774 21.246 4 18.743 4 12V7.236a2 2 0 0 1 1.105-1.789zm4.601 6.846a1 1 0 0 0-1.414 0L11 12.586l-1.293-1.293a1 1 0 0 0-1.414 1.414l2 2a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0 0-1.414"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
VERIFIED
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button
|
||||
class="mx_DevTools_button"
|
||||
>
|
||||
<div
|
||||
class="mx_E2EIcon mx_E2EIcon_inline"
|
||||
data-testid="e2e-icon"
|
||||
>
|
||||
<svg
|
||||
color="var(--cpd-color-icon-tertiary)"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M6 22q-.824 0-1.412-.587A1.93 1.93 0 0 1 4 20V10q0-.825.588-1.412A1.93 1.93 0 0 1 6 8h1V6q0-2.075 1.463-3.537Q9.926 1 12 1q2.075 0 3.537 1.463Q17 3.925 17 6v2h1q.824 0 1.413.588Q20 9.175 20 10v10q0 .824-.587 1.413A1.93 1.93 0 0 1 18 22zM9 8h6V6q0-1.25-.875-2.125A2.9 2.9 0 0 0 12 3q-1.25 0-2.125.875A2.9 2.9 0 0 0 9 6z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
SIGNED
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button
|
||||
class="mx_DevTools_button"
|
||||
>
|
||||
<div
|
||||
class="mx_E2EIcon mx_E2EIcon_inline"
|
||||
data-testid="e2e-icon"
|
||||
>
|
||||
<svg
|
||||
color="var(--cpd-color-icon-critical-primary)"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M12 17q.424 0 .713-.288A.97.97 0 0 0 13 16a.97.97 0 0 0-.287-.713A.97.97 0 0 0 12 15a.97.97 0 0 0-.713.287A.97.97 0 0 0 11 16q0 .424.287.712.288.288.713.288m0-4q.424 0 .713-.287A.97.97 0 0 0 13 12V8a.97.97 0 0 0-.287-.713A.97.97 0 0 0 12 7a.97.97 0 0 0-.713.287A.97.97 0 0 0 11 8v4q0 .424.287.713.288.287.713.287m0 9a9.7 9.7 0 0 1-3.9-.788 10.1 10.1 0 0 1-3.175-2.137q-1.35-1.35-2.137-3.175A9.7 9.7 0 0 1 2 12q0-2.075.788-3.9a10.1 10.1 0 0 1 2.137-3.175q1.35-1.35 3.175-2.137A9.7 9.7 0 0 1 12 2q2.075 0 3.9.788a10.1 10.1 0 0 1 3.175 2.137q1.35 1.35 2.137 3.175A9.7 9.7 0 0 1 22 12a9.7 9.7 0 0 1-.788 3.9 10.1 10.1 0 0 1-2.137 3.175q-1.35 1.35-3.175 2.137A9.7 9.7 0 0 1 12 22"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
UNSIGNED
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
</div>
|
||||
<div
|
||||
class="mx_Dialog_buttons"
|
||||
>
|
||||
<button>
|
||||
Back
|
||||
</button>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`<Users /> should render a user list 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="mx_DevTools_content"
|
||||
>
|
||||
<div
|
||||
class="mx_Field mx_Field_input mx_TextInputDialog_input mx_DevTools_RoomStateExplorer_query"
|
||||
>
|
||||
<input
|
||||
autocomplete="off"
|
||||
id="mx_Field_1"
|
||||
label="Filter results"
|
||||
placeholder="Filter results"
|
||||
size="64"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<label
|
||||
for="mx_Field_1"
|
||||
>
|
||||
Filter results
|
||||
</label>
|
||||
</div>
|
||||
No results found
|
||||
<form
|
||||
class="_root_19upo_16"
|
||||
>
|
||||
<div
|
||||
class="_inline-field_19upo_32"
|
||||
>
|
||||
<div
|
||||
class="_inline-field-control_19upo_44"
|
||||
>
|
||||
<div
|
||||
class="_container_udcm8_10"
|
||||
>
|
||||
<input
|
||||
checked=""
|
||||
class="_input_udcm8_24"
|
||||
id="_r_4_"
|
||||
role="switch"
|
||||
type="checkbox"
|
||||
/>
|
||||
<div
|
||||
class="_ui_udcm8_34"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="_inline-field-body_19upo_38"
|
||||
>
|
||||
<label
|
||||
class="_label_19upo_59"
|
||||
for="_r_4_"
|
||||
>
|
||||
Only joined users
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div
|
||||
class="mx_Dialog_buttons"
|
||||
>
|
||||
<button>
|
||||
Back
|
||||
</button>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
Reference in New Issue
Block a user