Skip to content

Commit

Permalink
Fix flaky playwright tests (#28984)
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Telatynski <[email protected]>
  • Loading branch information
t3chguy authored Jan 13, 2025
1 parent 1a21b71 commit 5405805
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 23 deletions.
17 changes: 11 additions & 6 deletions playwright/e2e/crypto/backups-mas.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,19 @@ 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 }) => {
test("Key backup is enabled by default", async ({ page, mailhogClient, app }, testInfo) => {
await page.goto("/#/login");
await page.getByRole("button", { name: "Continue" }).click();
await registerAccountMas(page, mailhogClient, "alice", "[email protected]", "Pa$sW0rD!");
await registerAccountMas(page, mailhogClient, `alice_${testInfo.testId}`, "[email protected]", "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 }) => {
test("user is prompted to set up recovery", async ({ page, mailhogClient, app }, testInfo) => {
await page.goto("/#/login");
await page.getByRole("button", { name: "Continue" }).click();
await registerAccountMas(page, mailhogClient, "alice", "[email protected]", "Pa$sW0rD!");
await registerAccountMas(page, mailhogClient, `alice_${testInfo.testId}`, "[email protected]", "Pa$sW0rD!");

await page.getByRole("button", { name: "Add room" }).click();
await page.getByRole("menuitem", { name: "New room" }).click();
Expand All @@ -45,8 +45,13 @@ test.describe("Encryption state after registration", () => {
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";
test("Key backup is disabled when reset from elsewhere", async ({
page,
mailhogClient,
request,
homeserver,
}, testInfo) => {
const testUsername = `alice_${testInfo.testId}`;
const testPassword = "Pa$sW0rD!";

// there's a delay before keys are uploaded so the error doesn't appear immediately: use a fake
Expand Down
4 changes: 2 additions & 2 deletions playwright/e2e/login/login-sso.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ test.use(legacyOAuthHomeserver);
test.describe("SSO login", () => {
test.skip(isDendrite, "does not yet support SSO");

test("logs in with SSO and lands on the home screen", async ({ page, homeserver }) => {
test("logs in with SSO and lands on the home screen", async ({ page, homeserver }, testInfo) => {
// If this test fails with a screen showing "Timeout connecting to remote server", it is most likely due to
// your firewall settings: Synapse is unable to reach the OIDC server.
//
// If you are using ufw, try something like:
// sudo ufw allow in on docker0
//
await doTokenRegistration(page, homeserver);
await doTokenRegistration(page, homeserver, testInfo);
});
});
4 changes: 2 additions & 2 deletions playwright/e2e/login/soft_logout_oauth.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ test.use({
test.use(legacyOAuthHomeserver);
test.describe("Soft logout with SSO user", () => {
test.use({
user: async ({ page, homeserver }, use) => {
const user = await doTokenRegistration(page, homeserver);
user: async ({ page, homeserver }, use, testInfo) => {
const user = await doTokenRegistration(page, homeserver, testInfo);

// Eventually, we should end up at the home screen.
await expect(page).toHaveURL(/\/#\/home$/);
Expand Down
5 changes: 3 additions & 2 deletions playwright/e2e/login/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/

import { Page, expect } from "@playwright/test";
import { Page, expect, TestInfo } from "@playwright/test";

import { Credentials, HomeserverInstance } from "../../plugins/homeserver";

Expand All @@ -15,6 +15,7 @@ import { Credentials, HomeserverInstance } from "../../plugins/homeserver";
export async function doTokenRegistration(
page: Page,
homeserver: HomeserverInstance,
testInfo: TestInfo,
): Promise<Credentials & { displayName: string }> {
await page.goto("/#/login");

Expand All @@ -35,7 +36,7 @@ export async function doTokenRegistration(

// Synapse prompts us to pick a user ID
await expect(page.getByRole("heading", { name: "Create your account" })).toBeVisible();
await page.getByRole("textbox", { name: "Username (required)" }).fill("alice");
await page.getByRole("textbox", { name: "Username (required)" }).fill(`alice_${testInfo.testId}`);

// wait for username validation to start, and complete
await expect(page.locator("#field-username-output")).toHaveText("");
Expand Down
29 changes: 20 additions & 9 deletions playwright/plugins/homeserver/synapse/legacyOAuthHomeserver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,31 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/

import { Fixtures } from "@playwright/test";
import { Fixtures, PlaywrightTestArgs } from "@playwright/test";
import { TestContainers } from "testcontainers";

import { Services } from "../../../services.ts";
import { OAuthServer } from "../../oauth_server";

export const legacyOAuthHomeserver: Fixtures<{}, Services> = {
_homeserver: [
async ({ _homeserver: container }, use) => {
export const legacyOAuthHomeserver: Fixtures<PlaywrightTestArgs, Services, PlaywrightTestArgs> = {
oAuthServer: [
// eslint-disable-next-line no-empty-pattern
async ({}, use) => {
const server = new OAuthServer();
const port = server.start();

await use(server);
server.stop();
},
{ scope: "worker" },
],
context: async ({ context, oAuthServer }, use, testInfo) => {
oAuthServer.onTestStarted(testInfo);
await use(context);
},
_homeserver: [
async ({ oAuthServer, _homeserver: homeserver }, use) => {
const port = oAuthServer.start();
await TestContainers.exposeHostPorts(port);
container.withConfig({
homeserver.withConfig({
oidc_providers: [
{
idp_id: "test",
Expand All @@ -43,8 +54,8 @@ export const legacyOAuthHomeserver: Fixtures<{}, Services> = {
},
],
});
await use(container);
server.stop();

await use(homeserver);
},
{ scope: "worker" },
],
Expand Down
13 changes: 11 additions & 2 deletions playwright/plugins/oauth_server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,21 @@ Please see LICENSE files in the repository root for full details.
import http from "http";
import express from "express";
import { AddressInfo } from "net";
import { TestInfo } from "@playwright/test";

import { randB64Bytes } from "../utils/rand.ts";

export class OAuthServer {
private server?: http.Server;
private sub?: string;

public onTestStarted(testInfo: TestInfo): void {
this.sub = testInfo.testId;
}

public start(): number {
if (this.server) this.stop();
const token = randB64Bytes(16);

const app = express();

Expand All @@ -28,7 +37,7 @@ export class OAuthServer {
const code = req.body.code;
if (code === "valid_auth_code") {
res.send({
access_token: "oauth_access_token",
access_token: token,
token_type: "Bearer",
expires_in: "3600",
});
Expand All @@ -43,7 +52,7 @@ export class OAuthServer {

// return an OAuth2 user info object
res.send({
sub: "alice",
sub: this.sub,
name: "Alice",
});
});
Expand Down
4 changes: 4 additions & 0 deletions playwright/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { Logger } from "./logger.ts";
import { StartedMatrixAuthenticationServiceContainer } from "./testcontainers/mas.ts";
import { HomeserverContainer, StartedHomeserverContainer } from "./testcontainers/HomeserverContainer.ts";
import { MailhogContainer, StartedMailhogContainer } from "./testcontainers/mailhog.ts";
import { OAuthServer } from "./plugins/oauth_server";

interface TestFixtures {
mailhogClient: mailhog.API;
Expand All @@ -30,7 +31,10 @@ export interface Services {
synapseConfigOptions: SynapseConfigOptions;
_homeserver: HomeserverContainer<any>;
homeserver: StartedHomeserverContainer;
// Set in masHomeserver only
mas?: StartedMatrixAuthenticationServiceContainer;
// Set in legacyOAuthHomeserver only
oAuthServer?: OAuthServer;
}

export const test = base.extend<TestFixtures, Services>({
Expand Down

0 comments on commit 5405805

Please sign in to comment.