Skip to content

Commit

Permalink
Merge branch 'develop' of https://github.com/vector-im/element-web in…
Browse files Browse the repository at this point in the history
…to t3chguy/playwright-homeservers

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

# Conflicts:
#	.github/workflows/end-to-end-tests.yaml
#	playwright/e2e/crypto/backups.spec.ts
#	playwright/e2e/login/login-consent.spec.ts
#	playwright/e2e/login/soft_logout.spec.ts
#	playwright/e2e/oidc/oidc-native.spec.ts
#	playwright/e2e/register/register.spec.ts
#	playwright/e2e/spaces/threads-activity-centre/threadsActivityCentre.spec.ts
#	playwright/element-web-test.ts
#	playwright/plugins/homeserver/dendrite/index.ts
#	playwright/plugins/homeserver/synapse/consentHomeserver.ts
#	playwright/plugins/homeserver/synapse/emailHomeserver.ts
#	playwright/plugins/homeserver/synapse/legacyOAuthHomeserver.ts
#	playwright/plugins/homeserver/synapse/masHomeserver.ts
#	playwright/services.ts
#	playwright/testcontainers/synapse.ts
  • Loading branch information
t3chguy committed Jan 8, 2025
2 parents 4a2a93e + 50ac509 commit b10fa4e
Show file tree
Hide file tree
Showing 38 changed files with 758 additions and 627 deletions.
91 changes: 91 additions & 0 deletions playwright/e2e/crypto/backups-mas.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
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 { test, expect } from "../../element-web-test";
import { registerAccountMas } from "../oidc";
import { isDendrite } from "../../plugins/homeserver/dendrite";
import { TestClientServerAPI } from "../csAPI";
import { masHomeserver } from "../../plugins/homeserver/synapse/masHomeserver.ts";

// These tests register an account with MAS because then we go through the "normal" registration flow
// and crypto gets set up. Using the 'user' fixture create a user and synthesizes an existing login,
// which is faster but leaves us without crypto set up.
test.use(masHomeserver);
test.describe("Encryption state after registration", () => {
test.skip(isDendrite, "does not yet support MAS");

test("Key backup is enabled by default", async ({ page, mailhogClient, app }) => {
await page.goto("/#/login");
await page.getByRole("button", { name: "Continue" }).click();
await registerAccountMas(page, mailhogClient, "alice", "alice@email.com", "Pa$sW0rD!");

await app.settings.openUserSettings("Security & Privacy");
await expect(page.getByText("This session is backing up your keys.")).toBeVisible();
});

test("user is prompted to set up recovery", async ({ page, mailhogClient, app }) => {
await page.goto("/#/login");
await page.getByRole("button", { name: "Continue" }).click();
await registerAccountMas(page, mailhogClient, "alice", "alice@email.com", "Pa$sW0rD!");

await page.getByRole("button", { name: "Add room" }).click();
await page.getByRole("menuitem", { name: "New room" }).click();
await page.getByRole("textbox", { name: "Name" }).fill("test room");
await page.getByRole("button", { name: "Create room" }).click();

await expect(page.getByRole("heading", { name: "Set up recovery" })).toBeVisible();
});
});

test.describe("Key backup reset from elsewhere", () => {
test.skip(isDendrite, "does not yet support MAS");

test("Key backup is disabled when reset from elsewhere", async ({ page, mailhogClient, request, homeserver }) => {
const testUsername = "alice";
const testPassword = "Pa$sW0rD!";

// there's a delay before keys are uploaded so the error doesn't appear immediately: use a fake
// clock so we can skip the delay
await page.clock.install();

await page.goto("/#/login");
await page.getByRole("button", { name: "Continue" }).click();
await registerAccountMas(page, mailhogClient, testUsername, "alice@email.com", testPassword);

await page.getByRole("button", { name: "Add room" }).click();
await page.getByRole("menuitem", { name: "New room" }).click();
await page.getByRole("textbox", { name: "Name" }).fill("test room");
await page.getByRole("button", { name: "Create room" }).click();

// @ts-ignore - this runs in the browser scope where mxMatrixClientPeg is a thing. Here, it is not.
const accessToken = await page.evaluate(() => mxMatrixClientPeg.get().getAccessToken());

const csAPI = new TestClientServerAPI(request, homeserver, accessToken);

const backupInfo = await csAPI.getCurrentBackupInfo();

await csAPI.deleteBackupVersion(backupInfo.version);

await page.getByRole("textbox", { name: "Send an encrypted message…" }).fill("/discardsession");
await page.getByRole("button", { name: "Send message" }).click();

await page.getByRole("textbox", { name: "Send an encrypted message…" }).fill("Message with broken key backup");
await page.getByRole("button", { name: "Send message" }).click();

// Should be the message we sent plus the room creation event
await expect(page.locator(".mx_EventTile")).toHaveCount(2);
await expect(
page.locator(".mx_RoomView_MessageList > .mx_EventTile_last .mx_EventTile_receiptSent"),
).toBeVisible();

// Wait for it to try uploading the key
await page.clock.fastForward(20000);

await expect(page.getByRole("heading", { level: 1, name: "New Recovery Method" })).toBeVisible();
});
});
80 changes: 0 additions & 80 deletions playwright/e2e/crypto/backups.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ Please see LICENSE files in the repository root for full details.
import { type Page } from "@playwright/test";

import { test, expect } from "../../element-web-test";
import { registerAccountMas } from "../oidc";
import { isDendrite } from "../../plugins/homeserver/dendrite";
import { TestClientServerAPI } from "../csAPI";
import { masHomeserver } from "../../plugins/homeserver/synapse/masHomeserver.ts";

async function expectBackupVersionToBe(page: Page, version: string) {
await expect(page.locator(".mx_SecureBackupPanel_statusList tr:nth-child(5) td")).toHaveText(
Expand All @@ -22,83 +19,6 @@ async function expectBackupVersionToBe(page: Page, version: string) {
await expect(page.locator(".mx_SecureBackupPanel_statusList tr:nth-child(6) td")).toHaveText(version);
}

// These tests register an account with MAS because then we go through the "normal" registration flow
// and crypto gets set up. Using the 'user' fixture create a user and synthesizes an existing login,
// which is faster but leaves us without crypto set up.
test.describe("Encryption state after registration", () => {
test.use(masHomeserver);

test("Key backup is enabled by default", async ({ page, mailhogClient, app }) => {
await page.goto("/#/login");
await page.getByRole("button", { name: "Continue" }).click();
await registerAccountMas(page, mailhogClient, "alice", "alice@email.com", "Pa$sW0rD!");

await app.settings.openUserSettings("Security & Privacy");
await expect(page.getByText("This session is backing up your keys.")).toBeVisible();
});

test("user is prompted to set up recovery", async ({ page, mailhogClient, app }) => {
await page.goto("/#/login");
await page.getByRole("button", { name: "Continue" }).click();
await registerAccountMas(page, mailhogClient, "alice", "alice@email.com", "Pa$sW0rD!");

await page.getByRole("button", { name: "Add room" }).click();
await page.getByRole("menuitem", { name: "New room" }).click();
await page.getByRole("textbox", { name: "Name" }).fill("test room");
await page.getByRole("button", { name: "Create room" }).click();

await expect(page.getByRole("heading", { name: "Set up recovery" })).toBeVisible();
});
});

test.describe("Key backup reset from elsewhere", () => {
test.use(masHomeserver);

test("Key backup is disabled when reset from elsewhere", async ({ page, mailhogClient, request, homeserver }) => {
const testUsername = "alice";
const testPassword = "Pa$sW0rD!";

// there's a delay before keys are uploaded so the error doesn't appear immediately: use a fake
// clock so we can skip the delay
await page.clock.install();

await page.goto("/#/login");
await page.getByRole("button", { name: "Continue" }).click();
await registerAccountMas(page, mailhogClient, testUsername, "alice@email.com", testPassword);

await page.getByRole("button", { name: "Add room" }).click();
await page.getByRole("menuitem", { name: "New room" }).click();
await page.getByRole("textbox", { name: "Name" }).fill("test room");
await page.getByRole("button", { name: "Create room" }).click();

// @ts-ignore - this runs in the browser scope where mxMatrixClientPeg is a thing. Here, it is not.
const accessToken = await page.evaluate(() => mxMatrixClientPeg.get().getAccessToken());

const csAPI = new TestClientServerAPI(request, homeserver, accessToken);

const backupInfo = await csAPI.getCurrentBackupInfo();

await csAPI.deleteBackupVersion(backupInfo.version);

await page.getByRole("textbox", { name: "Send an encrypted message…" }).fill("/discardsession");
await page.getByRole("button", { name: "Send message" }).click();

await page.getByRole("textbox", { name: "Send an encrypted message…" }).fill("Message with broken key backup");
await page.getByRole("button", { name: "Send message" }).click();

// Should be the message we sent plus the room creation event
await expect(page.locator(".mx_EventTile")).toHaveCount(2);
await expect(
page.locator(".mx_RoomView_MessageList > .mx_EventTile_last .mx_EventTile_receiptSent"),
).toBeVisible();

// Wait for it to try uploading the key
await page.clock.fastForward(20000);

await expect(page.getByRole("heading", { level: 1, name: "New Recovery Method" })).toBeVisible();
});
});

test.describe("Backups", () => {
test.skip(isDendrite, "Dendrite lacks support for MSC3967 so requires additional auth here");
test.use({
Expand Down
44 changes: 22 additions & 22 deletions playwright/e2e/crypto/dehydration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,30 +19,30 @@ function getMemberTileByName(page: Page, name: string): Locator {
return page.locator(`.mx_EntityTile, [title="${name}"]`);
}

test.describe("Dehydration", () => {
test.skip(isDendrite, "does not yet support dehydration v2");

test.use({
displayName: NAME,
synapseConfigOptions: {
experimental_features: {
msc2697_enabled: false,
msc3814_enabled: true,
},
test.use({
displayName: NAME,
synapseConfigOptions: {
experimental_features: {
msc2697_enabled: false,
msc3814_enabled: true,
},
config: async ({ config, context }, use) => {
const wellKnown = {
...config.default_server_config,
"org.matrix.msc3814": true,
};

await context.route("https://localhost/.well-known/matrix/client", async (route) => {
await route.fulfill({ json: wellKnown });
});
},
config: async ({ config, context }, use) => {
const wellKnown = {
...config.default_server_config,
"org.matrix.msc3814": true,
};

await context.route("https://localhost/.well-known/matrix/client", async (route) => {
await route.fulfill({ json: wellKnown });
});

await use(config);
},
});

await use(config);
},
});
test.describe("Dehydration", () => {
test.skip(isDendrite, "does not yet support dehydration v2");

test("Create dehydrated device", async ({ page, user, app }, workerInfo) => {
// Create a backup (which will create SSSS, and dehydrated device)
Expand Down
25 changes: 13 additions & 12 deletions playwright/e2e/forgot-password/forgot-password.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,21 @@ const username = "user1234";
const password = "oETo7MPf0o";
const email = "user@nowhere.dummy";

test.describe("Forgot Password", () => {
test.skip(isDendrite, "not yet wired up");
test.use(emailHomeserver);
test.use({
config: {
// The only thing that we really *need* (otherwise Element refuses to load) is a default homeserver.
// We point that to a guaranteed-invalid domain.
default_server_config: {
"m.homeserver": {
base_url: "https://server.invalid",
},
test.use(emailHomeserver);
test.use({
config: {
// The only thing that we really *need* (otherwise Element refuses to load) is a default homeserver.
// We point that to a guaranteed-invalid domain.
default_server_config: {
"m.homeserver": {
base_url: "https://server.invalid",
},
},
});
},
});

test.describe("Forgot Password", () => {
test.skip(isDendrite, "not yet wired up");

test("renders properly", { tag: "@screenshot" }, async ({ page, homeserver }) => {
await page.goto("/");
Expand Down
10 changes: 5 additions & 5 deletions playwright/e2e/login/consent.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ Please see LICENSE files in the repository root for full details.
import { test, expect } from "../../element-web-test";
import { consentHomeserver } from "../../plugins/homeserver/synapse/consentHomeserver.ts";

test.describe("Consent", () => {
test.use(consentHomeserver);
test.use({
displayName: "Bob",
});
test.use(consentHomeserver);
test.use({
displayName: "Bob",
});

test.describe("Consent", () => {
test("should prompt the user to consent to terms when server deems it necessary", async ({
context,
page,
Expand Down
Loading

0 comments on commit b10fa4e

Please sign in to comment.