From 381b2ea343971775c3b74e8e430ccff7e11d1cf4 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Tue, 14 Jan 2025 06:16:25 +0000 Subject: [PATCH 1/3] [create-pull-request] automated change (#28992) Co-authored-by: t3chguy <2403652+t3chguy@users.noreply.github.com> --- playwright/testcontainers/synapse.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright/testcontainers/synapse.ts b/playwright/testcontainers/synapse.ts index 5165815361..6ef0ff60cf 100644 --- a/playwright/testcontainers/synapse.ts +++ b/playwright/testcontainers/synapse.ts @@ -17,7 +17,7 @@ import { Credentials } from "../plugins/homeserver"; import { deepCopy } from "../plugins/utils/object.ts"; import { HomeserverContainer, StartedHomeserverContainer } from "./HomeserverContainer.ts"; -const TAG = "develop@sha256:b69222d98abe9625d46f5d3cb01683d5dc173ae339215297138392cfeec935d9"; +const TAG = "develop@sha256:7be2e00da62dfbb2bad071c6d408fecb1fabf740a538d08768b9b3e0a8c45350"; const DEFAULT_CONFIG = { server_name: "localhost", From e2bd040c88349664c395b34cf27d2c7b89daa889 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 14 Jan 2025 08:58:06 +0000 Subject: [PATCH 2/3] Simplify playwright (#28988) * Simplify types Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix typos Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .../app-loading/guest-registration.spec.ts | 2 +- playwright/e2e/crypto/backups-mas.spec.ts | 2 +- playwright/e2e/crypto/dehydration.spec.ts | 2 +- playwright/e2e/right-panel/memberlist.spec.ts | 2 +- playwright/element-web-test.ts | 20 ++++++++++++++----- playwright/pages/bot.ts | 2 +- .../plugins/homeserver/dendrite/index.ts | 6 ++---- .../homeserver/synapse/consentHomeserver.ts | 6 ++---- .../homeserver/synapse/emailHomeserver.ts | 6 ++---- .../synapse/legacyOAuthHomeserver.ts | 5 ++--- .../homeserver/synapse/masHomeserver.ts | 8 ++------ .../uiaLongSessionTimeoutHomeserver.ts | 12 +++++------ playwright/services.ts | 16 ++++++++------- playwright/testcontainers/synapse.ts | 2 +- 14 files changed, 45 insertions(+), 46 deletions(-) diff --git a/playwright/e2e/app-loading/guest-registration.spec.ts b/playwright/e2e/app-loading/guest-registration.spec.ts index 1c38177ec7..960b6a6692 100644 --- a/playwright/e2e/app-loading/guest-registration.spec.ts +++ b/playwright/e2e/app-loading/guest-registration.spec.ts @@ -13,7 +13,7 @@ Please see LICENSE files in the repository root for full details. import { expect, test } from "../../element-web-test"; test.use({ - synapseConfigOptions: { + synapseConfig: { allow_guest_access: true, }, }); diff --git a/playwright/e2e/crypto/backups-mas.spec.ts b/playwright/e2e/crypto/backups-mas.spec.ts index b51f737255..a6f4fb9390 100644 --- a/playwright/e2e/crypto/backups-mas.spec.ts +++ b/playwright/e2e/crypto/backups-mas.spec.ts @@ -13,7 +13,7 @@ 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 a user an synthesizes an existing login, +// 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", () => { diff --git a/playwright/e2e/crypto/dehydration.spec.ts b/playwright/e2e/crypto/dehydration.spec.ts index 6d7b6c0c7e..9beb053932 100644 --- a/playwright/e2e/crypto/dehydration.spec.ts +++ b/playwright/e2e/crypto/dehydration.spec.ts @@ -21,7 +21,7 @@ function getMemberTileByName(page: Page, name: string): Locator { test.use({ displayName: NAME, - synapseConfigOptions: { + synapseConfig: { experimental_features: { msc2697_enabled: false, msc3814_enabled: true, diff --git a/playwright/e2e/right-panel/memberlist.spec.ts b/playwright/e2e/right-panel/memberlist.spec.ts index 1275e243b6..25d5f34663 100644 --- a/playwright/e2e/right-panel/memberlist.spec.ts +++ b/playwright/e2e/right-panel/memberlist.spec.ts @@ -12,7 +12,7 @@ const ROOM_NAME = "Test room"; const NAME = "Alice"; test.use({ - synapseConfigOptions: { + synapseConfig: { presence: { enabled: false, include_offline_users_on_sync: false, diff --git a/playwright/element-web-test.ts b/playwright/element-web-test.ts index 0c6392fdc2..1a43820341 100644 --- a/playwright/element-web-test.ts +++ b/playwright/element-web-test.ts @@ -6,7 +6,15 @@ 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 { expect as baseExpect, Locator, Page, ExpectMatcherState, ElementHandle } from "@playwright/test"; +import { + expect as baseExpect, + Locator, + Page, + ExpectMatcherState, + ElementHandle, + PlaywrightTestArgs, + Fixtures as _Fixtures, +} from "@playwright/test"; import { sanitizeForFilePath } from "playwright-core/lib/utils"; import AxeBuilder from "@axe-core/playwright"; import _ from "lodash"; @@ -19,7 +27,7 @@ import { Crypto } from "./pages/crypto"; import { Toasts } from "./pages/toasts"; import { Bot, CreateBotOpts } from "./pages/bot"; import { Webserver } from "./plugins/webserver"; -import { test as base } from "./services.ts"; +import { Options, Services, test as base } from "./services.ts"; // Enable experimental service worker support // See https://playwright.dev/docs/service-workers-experimental#how-to-enable @@ -45,7 +53,7 @@ interface CredentialsWithDisplayName extends Credentials { displayName: string; } -export interface Fixtures { +export interface TestFixtures { axe: AxeBuilder; checkA11y: () => Promise; @@ -102,7 +110,9 @@ export interface Fixtures { disablePresence: boolean; } -export const test = base.extend({ +type CombinedTestFixtures = PlaywrightTestArgs & TestFixtures; +export type Fixtures = _Fixtures; +export const test = base.extend({ context: async ({ context }, use, testInfo) => { // We skip tests instead of using grep-invert to still surface the counts in the html report test.skip( @@ -150,7 +160,7 @@ export const test = base.extend({ const displayName = testDisplayName ?? _.sample(names)!; const credentials = await homeserver.registerUser(`user_${testInfo.testId}`, password, displayName); - console.log(`Registered test user @user:localhost with displayname ${displayName}`); + console.log(`Registered test user ${credentials.userId} with displayname ${displayName}`); await use({ ...credentials, diff --git a/playwright/pages/bot.ts b/playwright/pages/bot.ts index 200f83e2f6..435e4a1cbb 100644 --- a/playwright/pages/bot.ts +++ b/playwright/pages/bot.ts @@ -121,7 +121,7 @@ export class Bot extends Client { return logger as unknown as Logger; } - const logger = getLogger(`cypress bot ${credentials.userId}`); + const logger = getLogger(`bot ${credentials.userId}`); const keys = {}; diff --git a/playwright/plugins/homeserver/dendrite/index.ts b/playwright/plugins/homeserver/dendrite/index.ts index 897cafc5a3..e199de261b 100644 --- a/playwright/plugins/homeserver/dendrite/index.ts +++ b/playwright/plugins/homeserver/dendrite/index.ts @@ -6,12 +6,10 @@ 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 { DendriteContainer, PineconeContainer } from "../../../testcontainers/dendrite.ts"; -import { Services } from "../../../services.ts"; +import { Fixtures } from "../../../element-web-test.ts"; -export const dendriteHomeserver: Fixtures<{}, Services> = { +export const dendriteHomeserver: Fixtures = { _homeserver: [ // eslint-disable-next-line no-empty-pattern async ({}, use) => { diff --git a/playwright/plugins/homeserver/synapse/consentHomeserver.ts b/playwright/plugins/homeserver/synapse/consentHomeserver.ts index 4abf22b16e..a35fa8edc7 100644 --- a/playwright/plugins/homeserver/synapse/consentHomeserver.ts +++ b/playwright/plugins/homeserver/synapse/consentHomeserver.ts @@ -6,11 +6,9 @@ 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 } from "../../../element-web-test.ts"; -import { Services } from "../../../services.ts"; - -export const consentHomeserver: Fixtures<{}, Services> = { +export const consentHomeserver: Fixtures = { _homeserver: [ async ({ _homeserver: container, mailhog }, use) => { container diff --git a/playwright/plugins/homeserver/synapse/emailHomeserver.ts b/playwright/plugins/homeserver/synapse/emailHomeserver.ts index 0df3a67048..4faaa8ad00 100644 --- a/playwright/plugins/homeserver/synapse/emailHomeserver.ts +++ b/playwright/plugins/homeserver/synapse/emailHomeserver.ts @@ -6,11 +6,9 @@ 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 } from "../../../element-web-test.ts"; -import { Services } from "../../../services.ts"; - -export const emailHomeserver: Fixtures<{}, Services> = { +export const emailHomeserver: Fixtures = { _homeserver: [ async ({ _homeserver: container, mailhog }, use) => { container.withConfig({ diff --git a/playwright/plugins/homeserver/synapse/legacyOAuthHomeserver.ts b/playwright/plugins/homeserver/synapse/legacyOAuthHomeserver.ts index 2e3d20c9c0..1752794f40 100644 --- a/playwright/plugins/homeserver/synapse/legacyOAuthHomeserver.ts +++ b/playwright/plugins/homeserver/synapse/legacyOAuthHomeserver.ts @@ -6,13 +6,12 @@ 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, PlaywrightTestArgs } from "@playwright/test"; import { TestContainers } from "testcontainers"; -import { Services } from "../../../services.ts"; import { OAuthServer } from "../../oauth_server"; +import { Fixtures } from "../../../element-web-test.ts"; -export const legacyOAuthHomeserver: Fixtures = { +export const legacyOAuthHomeserver: Fixtures = { oAuthServer: [ // eslint-disable-next-line no-empty-pattern async ({}, use) => { diff --git a/playwright/plugins/homeserver/synapse/masHomeserver.ts b/playwright/plugins/homeserver/synapse/masHomeserver.ts index bf2dd13a1c..45169f1c90 100644 --- a/playwright/plugins/homeserver/synapse/masHomeserver.ts +++ b/playwright/plugins/homeserver/synapse/masHomeserver.ts @@ -6,14 +6,10 @@ 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, PlaywrightTestArgs } from "@playwright/test"; - -import { Services } from "../../../services.ts"; -import { Fixtures as BaseFixtures } from "../../../element-web-test.ts"; import { MatrixAuthenticationServiceContainer } from "../../../testcontainers/mas.ts"; +import { Fixtures } from "../../../element-web-test.ts"; -type Fixture = PlaywrightTestArgs & BaseFixtures; -export const masHomeserver: Fixtures = { +export const masHomeserver: Fixtures = { mas: [ async ({ _homeserver: homeserver, logger, network, postgres, mailhog }, use) => { const config = { diff --git a/playwright/plugins/homeserver/synapse/uiaLongSessionTimeoutHomeserver.ts b/playwright/plugins/homeserver/synapse/uiaLongSessionTimeoutHomeserver.ts index 1a0e41a71f..87d2a0f752 100644 --- a/playwright/plugins/homeserver/synapse/uiaLongSessionTimeoutHomeserver.ts +++ b/playwright/plugins/homeserver/synapse/uiaLongSessionTimeoutHomeserver.ts @@ -5,15 +5,13 @@ 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 } from "../../../element-web-test.ts"; -import { Services } from "../../../services.ts"; - -export const uiaLongSessionTimeoutHomeserver: Fixtures<{}, Services> = { - synapseConfigOptions: [ - async ({ synapseConfigOptions }, use) => { +export const uiaLongSessionTimeoutHomeserver: Fixtures = { + synapseConfig: [ + async ({ synapseConfig }, use) => { await use({ - ...synapseConfigOptions, + ...synapseConfig, ui_auth: { session_timeout: "300s", }, diff --git a/playwright/services.ts b/playwright/services.ts index 3abed280e9..0703df60d6 100644 --- a/playwright/services.ts +++ b/playwright/services.ts @@ -10,14 +10,14 @@ import mailhog from "mailhog"; import { Network, StartedNetwork } from "testcontainers"; import { PostgreSqlContainer, StartedPostgreSqlContainer } from "@testcontainers/postgresql"; -import { SynapseConfigOptions, SynapseContainer } from "./testcontainers/synapse.ts"; +import { SynapseConfig, SynapseContainer } from "./testcontainers/synapse.ts"; 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 { +export interface TestFixtures { mailhogClient: mailhog.API; } @@ -28,7 +28,7 @@ export interface Services { postgres: StartedPostgreSqlContainer; mailhog: StartedMailhogContainer; - synapseConfigOptions: SynapseConfigOptions; + synapseConfig: SynapseConfig; _homeserver: HomeserverContainer; homeserver: StartedHomeserverContainer; // Set in masHomeserver only @@ -37,7 +37,9 @@ export interface Services { oAuthServer?: OAuthServer; } -export const test = base.extend({ +export interface Options {} + +export const test = base.extend({ logger: [ // eslint-disable-next-line no-empty-pattern async ({}, use) => { @@ -101,7 +103,7 @@ export const test = base.extend({ await container.client.deleteAll(); }, - synapseConfigOptions: [{}, { option: true, scope: "worker" }], + synapseConfig: [{}, { scope: "worker" }], _homeserver: [ // eslint-disable-next-line no-empty-pattern async ({}, use) => { @@ -111,12 +113,12 @@ export const test = base.extend({ { scope: "worker" }, ], homeserver: [ - async ({ logger, network, _homeserver: homeserver, synapseConfigOptions, mas }, use) => { + async ({ logger, network, _homeserver: homeserver, synapseConfig, mas }, use) => { const container = await homeserver .withNetwork(network) .withNetworkAliases("homeserver") .withLogConsumer(logger.getConsumer("synapse")) - .withConfig(synapseConfigOptions) + .withConfig(synapseConfig) .start(); await use(container); diff --git a/playwright/testcontainers/synapse.ts b/playwright/testcontainers/synapse.ts index 6ef0ff60cf..22bfd9f665 100644 --- a/playwright/testcontainers/synapse.ts +++ b/playwright/testcontainers/synapse.ts @@ -138,7 +138,7 @@ const DEFAULT_CONFIG = { }, }; -export type SynapseConfigOptions = Partial; +export type SynapseConfig = Partial; export class SynapseContainer extends GenericContainer implements HomeserverContainer { private config: typeof DEFAULT_CONFIG; From 37f8d70d896d6bc710533d826748e0b52812af5e Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 14 Jan 2025 09:58:32 +0000 Subject: [PATCH 3/3] Fix flaky playwright tests (#28989) * Fix flaky playwright tests Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix flaky test Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Add slow Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .../e2e/crypto/invisible-crypto.spec.ts | 1 + .../e2e/integration-manager/kick.spec.ts | 28 ++++--------------- .../reactions-in-threads.spec.ts | 6 +--- playwright/e2e/timeline/timeline.spec.ts | 7 ++++- playwright/services.ts | 3 +- playwright/testcontainers/synapse.ts | 4 +-- 6 files changed, 17 insertions(+), 32 deletions(-) diff --git a/playwright/e2e/crypto/invisible-crypto.spec.ts b/playwright/e2e/crypto/invisible-crypto.spec.ts index f1272ec710..198abdac6d 100644 --- a/playwright/e2e/crypto/invisible-crypto.spec.ts +++ b/playwright/e2e/crypto/invisible-crypto.spec.ts @@ -11,6 +11,7 @@ import { bootstrapCrossSigningForClient } from "../../pages/client.ts"; /** Tests for the "invisible crypto" behaviour -- i.e., when the "exclude insecure devices" setting is enabled */ test.describe("Invisible cryptography", () => { + test.slow(); test.use({ displayName: "Alice", botCreateOpts: { displayName: "Bob" }, diff --git a/playwright/e2e/integration-manager/kick.spec.ts b/playwright/e2e/integration-manager/kick.spec.ts index b12215fe33..b1aa9eff52 100644 --- a/playwright/e2e/integration-manager/kick.spec.ts +++ b/playwright/e2e/integration-manager/kick.spec.ts @@ -69,29 +69,13 @@ async function sendActionFromIntegrationManager( await iframe.getByRole("button", { name: "Press to send action" }).click(); } -async function clickUntilGone(page: Page, selector: string, attempt = 0) { - if (attempt === 11) { - throw new Error("clickUntilGone attempt count exceeded"); - } - - await page.locator(selector).last().click(); - - const count = await page.locator(selector).count(); - if (count > 0) { - return clickUntilGone(page, selector, ++attempt); - } -} - async function expectKickedMessage(page: Page, shouldExist: boolean) { - // Expand any event summaries, we can't use a click multiple here because clicking one might de-render others - // This is quite horrible but seems the most stable way of clicking 0-N buttons, - // one at a time with a full re-evaluation after each click - await clickUntilGone(page, ".mx_GenericEventListSummary_toggle[aria-expanded=false]"); - - // Check for the event message (or lack thereof) - await expect(page.getByText(`${USER_DISPLAY_NAME} removed ${BOT_DISPLAY_NAME}: ${KICK_REASON}`)).toBeVisible({ - visible: shouldExist, - }); + await expect(async () => { + await page.locator(".mx_GenericEventListSummary_toggle[aria-expanded=false]").last().click(); + await expect(page.getByText(`${USER_DISPLAY_NAME} removed ${BOT_DISPLAY_NAME}: ${KICK_REASON}`)).toBeVisible({ + visible: shouldExist, + }); + }).toPass(); } test.describe("Integration Manager: Kick", () => { diff --git a/playwright/e2e/read-receipts/reactions-in-threads.spec.ts b/playwright/e2e/read-receipts/reactions-in-threads.spec.ts index eb733d3a12..350140965c 100644 --- a/playwright/e2e/read-receipts/reactions-in-threads.spec.ts +++ b/playwright/e2e/read-receipts/reactions-in-threads.spec.ts @@ -70,11 +70,7 @@ test.describe("Read receipts", { tag: "@mergequeue" }, () => { // Given a thread exists and I have marked it as read await util.goTo(room1); await util.assertRead(room2); - await util.receiveMessages(room2, [ - "Msg1", - msg.threadedOff("Msg1", "Reply1"), - msg.reactionTo("Reply1", "🪿"), - ]); + await util.receiveMessages(room2, ["Msg1", msg.threadedOff("Msg1", "Reply1")]); await util.assertUnread(room2, 1); await util.markAsRead(room2); await util.assertRead(room2); diff --git a/playwright/e2e/timeline/timeline.spec.ts b/playwright/e2e/timeline/timeline.spec.ts index 26d286b53a..885c15d90f 100644 --- a/playwright/e2e/timeline/timeline.spec.ts +++ b/playwright/e2e/timeline/timeline.spec.ts @@ -603,7 +603,12 @@ test.describe("Timeline", () => { await messageEdit(page); // Click timestamp to highlight hidden event line - await page.locator(".mx_RoomView_body .mx_EventTile_info .mx_MessageTimestamp").click(); + const timestamp = page.locator(".mx_RoomView_body .mx_EventTile_info a", { + has: page.locator(".mx_MessageTimestamp"), + }); + // wait for the remote echo otherwise we get an error modal due to a 404 on the /event/ API + await expect(timestamp).not.toHaveAttribute("href", /~!/); + await timestamp.locator(".mx_MessageTimestamp").click(); // should not add inline start padding to a hidden event line on IRC layout await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.IRC); diff --git a/playwright/services.ts b/playwright/services.ts index 0703df60d6..c5d1e278d1 100644 --- a/playwright/services.ts +++ b/playwright/services.ts @@ -99,8 +99,8 @@ export const test = base.extend({ { scope: "worker" }, ], mailhogClient: async ({ mailhog: container }, use) => { - await use(container.client); await container.client.deleteAll(); + await use(container.client); }, synapseConfig: [{}, { scope: "worker" }], @@ -141,6 +141,5 @@ export const test = base.extend({ await logger.onTestStarted(context); await use(context); await logger.onTestFinished(testInfo); - await mailhogClient.deleteAll(); }, }); diff --git a/playwright/testcontainers/synapse.ts b/playwright/testcontainers/synapse.ts index 22bfd9f665..3469082d10 100644 --- a/playwright/testcontainers/synapse.ts +++ b/playwright/testcontainers/synapse.ts @@ -277,7 +277,7 @@ export class StartedSynapseContainer extends AbstractStartedContainer implements const data = await res.json(); return { - homeServer: data.home_server, + homeServer: data.home_server || data.user_id.split(":").slice(1).join(":"), accessToken: data.access_token, userId: data.user_id, deviceId: data.device_id, @@ -310,7 +310,7 @@ export class StartedSynapseContainer extends AbstractStartedContainer implements accessToken: json.access_token, userId: json.user_id, deviceId: json.device_id, - homeServer: json.home_server, + homeServer: json.home_server || json.user_id.split(":").slice(1).join(":"), username: userId.slice(1).split(":")[0], }; }