Skip to content

Commit ed5c900

Browse files
committed
test(dev tools): add tests for crypto component
1 parent e9f728b commit ed5c900

File tree

3 files changed

+385
-0
lines changed

3 files changed

+385
-0
lines changed

test/test-utils/test-utils.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ export function createTestClient(): MatrixClient {
152152
}),
153153
isCrossSigningReady: jest.fn().mockResolvedValue(false),
154154
resetEncryption: jest.fn(),
155+
getSessionBackupPrivateKey: jest.fn().mockResolvedValue(null),
156+
isSecretStorageReady: jest.fn().mockResolvedValue(false),
155157
}),
156158

157159
getPushActionsForEvent: jest.fn(),
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Copyright 2025 New Vector Ltd.
3+
*
4+
* SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
5+
* Please see LICENSE files in the repository root for full details.
6+
*/
7+
8+
import React from "react";
9+
import { MatrixClient } from "matrix-js-sdk/src/matrix";
10+
import { render, screen, waitFor } from "jest-matrix-react";
11+
import { KeyBackupInfo } from "matrix-js-sdk/src/crypto-api";
12+
13+
import { createTestClient, withClientContextRenderOptions } from "../../../../../test-utils";
14+
import { Crypto } from "../../../../../../src/components/views/dialogs/devtools/Crypto";
15+
16+
describe("<Crypto />", () => {
17+
let matrixClient: MatrixClient;
18+
beforeEach(() => {
19+
matrixClient = createTestClient();
20+
});
21+
22+
function renderComponent() {
23+
return render(<Crypto onBack={jest.fn} />, withClientContextRenderOptions(matrixClient));
24+
}
25+
26+
it("should display message if crypto is not available", async () => {
27+
jest.spyOn(matrixClient, "getCrypto").mockReturnValue(undefined);
28+
renderComponent();
29+
expect(screen.getByText("Cryptographic module is not available")).toBeInTheDocument();
30+
});
31+
32+
describe("<KeyStorage />", () => {
33+
it("should display loading spinner while loading", async () => {
34+
jest.spyOn(matrixClient.getCrypto()!, "getKeyBackupInfo").mockImplementation(() => new Promise(() => {}));
35+
renderComponent();
36+
await waitFor(() => expect(screen.getByLabelText("Loading…")).toBeInTheDocument());
37+
});
38+
39+
it("should display when the key storage data are missing", async () => {
40+
renderComponent();
41+
await waitFor(() => expect(screen.getByRole("table", { name: "Key Storage" })).toBeInTheDocument());
42+
expect(screen.getByRole("table", { name: "Key Storage" })).toMatchSnapshot();
43+
});
44+
45+
it("should display when the key storage data are available", async () => {
46+
jest.spyOn(matrixClient.getCrypto()!, "getKeyBackupInfo").mockResolvedValue({
47+
algorithm: "m.megolm_backup.v1",
48+
version: "1",
49+
} as unknown as KeyBackupInfo);
50+
jest.spyOn(matrixClient, "isKeyBackupKeyStored").mockResolvedValue({});
51+
jest.spyOn(matrixClient.getCrypto()!, "getSessionBackupPrivateKey").mockResolvedValue(new Uint8Array(32));
52+
jest.spyOn(matrixClient.getCrypto()!, "getActiveSessionBackupVersion").mockResolvedValue("2");
53+
jest.spyOn(matrixClient.secretStorage, "hasKey").mockResolvedValue(true);
54+
jest.spyOn(matrixClient.getCrypto()!, "isSecretStorageReady").mockResolvedValue(true);
55+
56+
renderComponent();
57+
await waitFor(() => expect(screen.getByRole("table", { name: "Key Storage" })).toBeInTheDocument());
58+
expect(screen.getByRole("table", { name: "Key Storage" })).toMatchSnapshot();
59+
});
60+
});
61+
62+
describe("<CrossSigning />", () => {
63+
it("should display loading spinner while loading", async () => {
64+
jest.spyOn(matrixClient.getCrypto()!, "getCrossSigningStatus").mockImplementation(
65+
() => new Promise(() => {}),
66+
);
67+
renderComponent();
68+
await waitFor(() => expect(screen.getByLabelText("Loading…")).toBeInTheDocument());
69+
});
70+
71+
it("should display when the cross-signing data are missing", async () => {
72+
renderComponent();
73+
await waitFor(() => expect(screen.getByRole("table", { name: "Cross-signing" })).toBeInTheDocument());
74+
expect(screen.getByRole("table", { name: "Cross-signing" })).toMatchSnapshot();
75+
});
76+
77+
it("should display when the cross-signing data are available", async () => {
78+
jest.spyOn(matrixClient.getCrypto()!, "getCrossSigningStatus").mockResolvedValue({
79+
publicKeysOnDevice: true,
80+
privateKeysInSecretStorage: true,
81+
privateKeysCachedLocally: {
82+
masterKey: true,
83+
selfSigningKey: true,
84+
userSigningKey: true,
85+
},
86+
});
87+
jest.spyOn(matrixClient.getCrypto()!, "isCrossSigningReady").mockResolvedValue(true);
88+
89+
renderComponent();
90+
await waitFor(() => expect(screen.getByRole("table", { name: "Cross-signing" })).toBeInTheDocument());
91+
expect(screen.getByRole("table", { name: "Cross-signing" })).toMatchSnapshot();
92+
});
93+
});
94+
});
Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`<Crypto /> <CrossSigning /> should display when the cross-signing data are available 1`] = `
4+
<table
5+
aria-label="Cross-signing"
6+
>
7+
<thead>
8+
Cross-signing
9+
</thead>
10+
<tbody>
11+
<tr>
12+
<th
13+
scope="row"
14+
>
15+
Cross-signing status:
16+
</th>
17+
<td>
18+
Cross-signing is ready for use.
19+
</td>
20+
</tr>
21+
<tr>
22+
<th
23+
scope="row"
24+
>
25+
Cross-signing public keys:
26+
</th>
27+
<td>
28+
in memory
29+
</td>
30+
</tr>
31+
<tr>
32+
<th
33+
scope="row"
34+
>
35+
Cross-signing private keys:
36+
</th>
37+
<td>
38+
in secret storage
39+
</td>
40+
</tr>
41+
<tr>
42+
<th
43+
scope="row"
44+
>
45+
Master private key:
46+
</th>
47+
<td>
48+
cached locally
49+
</td>
50+
</tr>
51+
<tr>
52+
<th
53+
scope="row"
54+
>
55+
Self signing private key:
56+
</th>
57+
<td>
58+
cached locally
59+
</td>
60+
</tr>
61+
<tr>
62+
<th
63+
scope="row"
64+
>
65+
User signing private key:
66+
</th>
67+
<td>
68+
cached locally
69+
</td>
70+
</tr>
71+
</tbody>
72+
</table>
73+
`;
74+
75+
exports[`<Crypto /> <CrossSigning /> should display when the cross-signing data are missing 1`] = `
76+
<table
77+
aria-label="Cross-signing"
78+
>
79+
<thead>
80+
Cross-signing
81+
</thead>
82+
<tbody>
83+
<tr>
84+
<th
85+
scope="row"
86+
>
87+
Cross-signing status:
88+
</th>
89+
<td>
90+
Cross-signing is not set up.
91+
</td>
92+
</tr>
93+
<tr>
94+
<th
95+
scope="row"
96+
>
97+
Cross-signing public keys:
98+
</th>
99+
<td>
100+
not found
101+
</td>
102+
</tr>
103+
<tr>
104+
<th
105+
scope="row"
106+
>
107+
Cross-signing private keys:
108+
</th>
109+
<td>
110+
not found in storage
111+
</td>
112+
</tr>
113+
<tr>
114+
<th
115+
scope="row"
116+
>
117+
Master private key:
118+
</th>
119+
<td>
120+
not found locally
121+
</td>
122+
</tr>
123+
<tr>
124+
<th
125+
scope="row"
126+
>
127+
Self signing private key:
128+
</th>
129+
<td>
130+
not found locally
131+
</td>
132+
</tr>
133+
<tr>
134+
<th
135+
scope="row"
136+
>
137+
User signing private key:
138+
</th>
139+
<td>
140+
not found locally
141+
</td>
142+
</tr>
143+
</tbody>
144+
</table>
145+
`;
146+
147+
exports[`<Crypto /> <KeyStorage /> should display when the key storage data are available 1`] = `
148+
<table
149+
aria-label="Key Storage"
150+
>
151+
<thead>
152+
Key Storage
153+
</thead>
154+
<tbody>
155+
<tr>
156+
<th
157+
scope="row"
158+
>
159+
Latest backup version on server:
160+
</th>
161+
<td>
162+
1 (Algorithm: m.megolm_backup.v1)
163+
</td>
164+
</tr>
165+
<tr>
166+
<th
167+
scope="row"
168+
>
169+
Backup key stored:
170+
</th>
171+
<td>
172+
in secret storage
173+
</td>
174+
</tr>
175+
<tr>
176+
<th
177+
scope="row"
178+
>
179+
Active backup version:
180+
</th>
181+
<td>
182+
2
183+
</td>
184+
</tr>
185+
<tr>
186+
<th
187+
scope="row"
188+
>
189+
Backup key cached:
190+
</th>
191+
<td>
192+
cached locally, well formed
193+
</td>
194+
</tr>
195+
<tr>
196+
<th
197+
scope="row"
198+
>
199+
Secret storage public key:
200+
</th>
201+
<td>
202+
in account data
203+
</td>
204+
</tr>
205+
<tr>
206+
<th
207+
scope="row"
208+
>
209+
Secret storage:
210+
</th>
211+
<td>
212+
ready
213+
</td>
214+
</tr>
215+
</tbody>
216+
</table>
217+
`;
218+
219+
exports[`<Crypto /> <KeyStorage /> should display when the key storage data are missing 1`] = `
220+
<table
221+
aria-label="Key Storage"
222+
>
223+
<thead>
224+
Key Storage
225+
</thead>
226+
<tbody>
227+
<tr>
228+
<th
229+
scope="row"
230+
>
231+
Latest backup version on server:
232+
</th>
233+
<td>
234+
Your keys are not being backed up from this session.
235+
</td>
236+
</tr>
237+
<tr>
238+
<th
239+
scope="row"
240+
>
241+
Backup key stored:
242+
</th>
243+
<td>
244+
not stored
245+
</td>
246+
</tr>
247+
<tr>
248+
<th
249+
scope="row"
250+
>
251+
Active backup version:
252+
</th>
253+
<td>
254+
None
255+
</td>
256+
</tr>
257+
<tr>
258+
<th
259+
scope="row"
260+
>
261+
Backup key cached:
262+
</th>
263+
<td>
264+
not found locally, unexpected type
265+
</td>
266+
</tr>
267+
<tr>
268+
<th
269+
scope="row"
270+
>
271+
Secret storage public key:
272+
</th>
273+
<td>
274+
not found
275+
</td>
276+
</tr>
277+
<tr>
278+
<th
279+
scope="row"
280+
>
281+
Secret storage:
282+
</th>
283+
<td>
284+
not ready
285+
</td>
286+
</tr>
287+
</tbody>
288+
</table>
289+
`;

0 commit comments

Comments
 (0)