Refactor CreateCrossSigningDialog (#28218)
* Refactor CreateCrossSigningDialog * Converts CreateCrossSigningDialog to a functional component * Pulls logic out to its own class * Updates usage of deprecated cross signing bootstrap method on client to be on the crypto object and updates test to match Moved from https://github.com/element-hq/matrix-react-sdk/pull/131 * Add mock here too * Use the right mock * Remove duplicate mock * Stray jest mock line * Un-move mocks * tsdoc * Typo Co-authored-by: Andy Balaam <andy.balaam@matrix.org> --------- Co-authored-by: Andy Balaam <andy.balaam@matrix.org>
This commit is contained in:
parent
539025cf8c
commit
19ef3267c0
8 changed files with 406 additions and 157 deletions
93
test/CreateCrossSigning-test.ts
Normal file
93
test/CreateCrossSigning-test.ts
Normal file
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2018-2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { MatrixClient, MatrixError } from "matrix-js-sdk/src/matrix";
|
||||
import { mocked } from "jest-mock";
|
||||
|
||||
import { createCrossSigning } from "../src/CreateCrossSigning";
|
||||
import { createTestClient } from "./test-utils";
|
||||
import Modal from "../src/Modal";
|
||||
|
||||
describe("CreateCrossSigning", () => {
|
||||
let client: MatrixClient;
|
||||
|
||||
beforeEach(() => {
|
||||
client = createTestClient();
|
||||
});
|
||||
|
||||
it("should call bootstrapCrossSigning with an authUploadDeviceSigningKeys function", async () => {
|
||||
await createCrossSigning(client, false, "password");
|
||||
|
||||
expect(client.getCrypto()?.bootstrapCrossSigning).toHaveBeenCalledWith({
|
||||
authUploadDeviceSigningKeys: expect.any(Function),
|
||||
});
|
||||
});
|
||||
|
||||
it("should upload with password auth if possible", async () => {
|
||||
client.uploadDeviceSigningKeys = jest.fn().mockRejectedValueOnce(
|
||||
new MatrixError({
|
||||
flows: [
|
||||
{
|
||||
stages: ["m.login.password"],
|
||||
},
|
||||
],
|
||||
}),
|
||||
);
|
||||
|
||||
await createCrossSigning(client, false, "password");
|
||||
|
||||
const { authUploadDeviceSigningKeys } = mocked(client.getCrypto()!).bootstrapCrossSigning.mock.calls[0][0];
|
||||
|
||||
const makeRequest = jest.fn();
|
||||
await authUploadDeviceSigningKeys!(makeRequest);
|
||||
expect(makeRequest).toHaveBeenCalledWith({
|
||||
type: "m.login.password",
|
||||
identifier: {
|
||||
type: "m.id.user",
|
||||
user: client.getUserId(),
|
||||
},
|
||||
password: "password",
|
||||
});
|
||||
});
|
||||
|
||||
it("should attempt to upload keys without auth if using token login", async () => {
|
||||
await createCrossSigning(client, true, undefined);
|
||||
|
||||
const { authUploadDeviceSigningKeys } = mocked(client.getCrypto()!).bootstrapCrossSigning.mock.calls[0][0];
|
||||
|
||||
const makeRequest = jest.fn();
|
||||
await authUploadDeviceSigningKeys!(makeRequest);
|
||||
expect(makeRequest).toHaveBeenCalledWith({});
|
||||
});
|
||||
|
||||
it("should prompt user if password upload not possible", async () => {
|
||||
const createDialog = jest.spyOn(Modal, "createDialog").mockReturnValue({
|
||||
finished: Promise.resolve([true]),
|
||||
close: jest.fn(),
|
||||
});
|
||||
|
||||
client.uploadDeviceSigningKeys = jest.fn().mockRejectedValueOnce(
|
||||
new MatrixError({
|
||||
flows: [
|
||||
{
|
||||
stages: ["dummy.mystery_flow_nobody_knows"],
|
||||
},
|
||||
],
|
||||
}),
|
||||
);
|
||||
|
||||
await createCrossSigning(client, false, "password");
|
||||
|
||||
const { authUploadDeviceSigningKeys } = mocked(client.getCrypto()!).bootstrapCrossSigning.mock.calls[0][0];
|
||||
|
||||
const makeRequest = jest.fn();
|
||||
await authUploadDeviceSigningKeys!(makeRequest);
|
||||
expect(makeRequest).not.toHaveBeenCalledWith();
|
||||
expect(createDialog).toHaveBeenCalled();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2018-2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import { render, screen, waitFor } from "jest-matrix-react";
|
||||
import { mocked } from "jest-mock";
|
||||
import { MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import { createCrossSigning } from "../../../../../src/CreateCrossSigning";
|
||||
import CreateCrossSigningDialog from "../../../../../src/components/views/dialogs/security/CreateCrossSigningDialog";
|
||||
import { createTestClient } from "../../../../test-utils";
|
||||
|
||||
jest.mock("../../../../../src/CreateCrossSigning", () => ({
|
||||
createCrossSigning: jest.fn(),
|
||||
}));
|
||||
|
||||
describe("CreateCrossSigningDialog", () => {
|
||||
let client: MatrixClient;
|
||||
let createCrossSigningResolve: () => void;
|
||||
let createCrossSigningReject: (e: Error) => void;
|
||||
|
||||
beforeEach(() => {
|
||||
client = createTestClient();
|
||||
mocked(createCrossSigning).mockImplementation(() => {
|
||||
return new Promise((resolve, reject) => {
|
||||
createCrossSigningResolve = resolve;
|
||||
createCrossSigningReject = reject;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("should call createCrossSigning and show a spinner while it runs", async () => {
|
||||
const onFinished = jest.fn();
|
||||
|
||||
render(
|
||||
<CreateCrossSigningDialog
|
||||
matrixClient={client}
|
||||
accountPassword="hunter2"
|
||||
tokenLogin={false}
|
||||
onFinished={onFinished}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(createCrossSigning).toHaveBeenCalledWith(client, false, "hunter2");
|
||||
expect(screen.getByTestId("spinner")).toBeInTheDocument();
|
||||
|
||||
createCrossSigningResolve!();
|
||||
|
||||
await waitFor(() => expect(onFinished).toHaveBeenCalledWith(true));
|
||||
});
|
||||
|
||||
it("should display an error if createCrossSigning fails", async () => {
|
||||
render(
|
||||
<CreateCrossSigningDialog
|
||||
matrixClient={client}
|
||||
accountPassword="hunter2"
|
||||
tokenLogin={false}
|
||||
onFinished={jest.fn()}
|
||||
/>,
|
||||
);
|
||||
|
||||
createCrossSigningReject!(new Error("generic error message"));
|
||||
|
||||
await expect(await screen.findByRole("button", { name: "Retry" })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("ignores failures when tokenLogin is true", async () => {
|
||||
const onFinished = jest.fn();
|
||||
|
||||
render(
|
||||
<CreateCrossSigningDialog
|
||||
matrixClient={client}
|
||||
accountPassword="hunter2"
|
||||
tokenLogin={true}
|
||||
onFinished={onFinished}
|
||||
/>,
|
||||
);
|
||||
|
||||
createCrossSigningReject!(new Error("generic error message"));
|
||||
|
||||
await waitFor(() => expect(onFinished).toHaveBeenCalledWith(false));
|
||||
});
|
||||
|
||||
it("cancels the dialog when the cancel button is clicked", async () => {
|
||||
const onFinished = jest.fn();
|
||||
|
||||
render(
|
||||
<CreateCrossSigningDialog
|
||||
matrixClient={client}
|
||||
accountPassword="hunter2"
|
||||
tokenLogin={false}
|
||||
onFinished={onFinished}
|
||||
/>,
|
||||
);
|
||||
|
||||
createCrossSigningReject!(new Error("generic error message"));
|
||||
|
||||
const cancelButton = await screen.findByRole("button", { name: "Cancel" });
|
||||
cancelButton.click();
|
||||
|
||||
expect(onFinished).toHaveBeenCalledWith(false);
|
||||
});
|
||||
|
||||
it("should retry when the retry button is clicked", async () => {
|
||||
render(
|
||||
<CreateCrossSigningDialog
|
||||
matrixClient={client}
|
||||
accountPassword="hunter2"
|
||||
tokenLogin={false}
|
||||
onFinished={jest.fn()}
|
||||
/>,
|
||||
);
|
||||
|
||||
createCrossSigningReject!(new Error("generic error message"));
|
||||
|
||||
const retryButton = await screen.findByRole("button", { name: "Retry" });
|
||||
retryButton.click();
|
||||
|
||||
expect(createCrossSigning).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
|
@ -125,6 +125,7 @@ export function createTestClient(): MatrixClient {
|
|||
getVerificationRequestsToDeviceInProgress: jest.fn().mockReturnValue([]),
|
||||
setDeviceIsolationMode: jest.fn(),
|
||||
prepareToEncrypt: jest.fn(),
|
||||
bootstrapCrossSigning: jest.fn(),
|
||||
getActiveSessionBackupVersion: jest.fn().mockResolvedValue(null),
|
||||
}),
|
||||
|
||||
|
|
|
@ -1112,8 +1112,6 @@ describe("<MatrixChat />", () => {
|
|||
|
||||
expect(loginClient.getCrypto()!.userHasCrossSigningKeys).toHaveBeenCalled();
|
||||
|
||||
await flushPromises();
|
||||
|
||||
// set up keys screen is rendered
|
||||
expect(screen.getByText("Setting up keys")).toBeInTheDocument();
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue