diff --git a/cypress/e2e/permalinks/permalinks.spec.ts b/cypress/e2e/permalinks/permalinks.spec.ts deleted file mode 100644 index 2a61df26a0..0000000000 --- a/cypress/e2e/permalinks/permalinks.spec.ts +++ /dev/null @@ -1,139 +0,0 @@ -/* -Copyright 2023 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -import { ISendEventResponse } from "matrix-js-sdk/src/matrix"; - -import { HomeserverInstance } from "../../plugins/utils/homeserver"; -import type { CypressBot } from "../../support/bot"; - -const room1Name = "Room 1"; -const room2Name = "Room 2"; -const unknownRoomAlias = "#unknownroom:example.com"; -const permalinkPrefix = "https://matrix.to/#/"; - -const getPill = (label: string) => { - return cy.contains(".mx_Pill_text", new RegExp("^" + label + "$", "g")); -}; - -describe("permalinks", () => { - beforeEach(() => { - cy.startHomeserver("default") - .as("homeserver") - .then((homeserver: HomeserverInstance) => { - cy.initTestUser(homeserver, "Alice"); - - cy.createRoom({ name: room1Name }).as("room1Id"); - cy.createRoom({ name: room2Name }).as("room2Id"); - - cy.getBot(homeserver, { displayName: "Bob" }).as("bob"); - cy.getBot(homeserver, { displayName: "Charlotte" }).as("charlotte"); - cy.getBot(homeserver, { displayName: "Danielle" }).as("danielle"); - }); - }); - - afterEach(() => { - cy.get("@homeserver").then((homeserver: HomeserverInstance) => { - cy.stopHomeserver(homeserver); - }); - }); - - it("shoud render permalinks as expected", () => { - let danielle: CypressBot; - - cy.get("@danielle").then((d) => { - danielle = d; - }); - - cy.viewRoomByName(room1Name); - - cy.all([ - cy.getClient(), - cy.get("@room1Id"), - cy.get("@room2Id"), - cy.get("@bob"), - cy.get("@charlotte"), - ]).then(([client, room1Id, room2Id, bob, charlotte]) => { - cy.inviteUser(room1Id, bob.getUserId()); - cy.botJoinRoom(bob, room1Id); - cy.inviteUser(room2Id, charlotte.getUserId()); - cy.botJoinRoom(charlotte, room2Id); - - cy.botSendMessage(client, room1Id, "At room mention: @room"); - - cy.botSendMessage(client, room1Id, `Permalink to Room 2: ${permalinkPrefix}${room2Id}`); - cy.botSendMessage( - client, - room1Id, - `Permalink to an unknown room alias: ${permalinkPrefix}${unknownRoomAlias}`, - ); - - cy.botSendMessage(bob, room1Id, "Hello").then((result: ISendEventResponse) => { - cy.botSendMessage( - client, - room1Id, - `Permalink to a message in the same room: ${permalinkPrefix}${room1Id}/${result.event_id}`, - ); - }); - cy.botSendMessage(charlotte, room2Id, "Hello").then((result: ISendEventResponse) => { - cy.botSendMessage( - client, - room1Id, - `Permalink to a message in another room: ${permalinkPrefix}${room2Id}/${result.event_id}`, - ); - }); - cy.botSendMessage(client, room1Id, `Permalink to an uknonwn message: ${permalinkPrefix}${room1Id}/$abc123`); - - cy.botSendMessage(client, room1Id, `Permalink to a user in the room: ${permalinkPrefix}${bob.getUserId()}`); - cy.botSendMessage( - client, - room1Id, - `Permalink to a user in another room: ${permalinkPrefix}${charlotte.getUserId()}`, - ); - cy.botSendMessage( - client, - room1Id, - `Permalink to a user with whom alice doesn't share a room: ${permalinkPrefix}${danielle.getUserId()}`, - ); - }); - - cy.get(".mx_RoomView_timeline").within(() => { - getPill("@room"); - - getPill(room2Name); - getPill(unknownRoomAlias); - - getPill("Message from Bob"); - getPill(`Message in ${room2Name}`); - getPill("Message"); - - getPill("Bob"); - getPill("Charlotte"); - // This is the permalink to Danielle's profile. It should only display the MXID - // because the profile is unknown (not sharing any room with Danielle). - getPill(danielle.getSafeUserId()); - }); - - // Exclude various components from the snapshot, for consistency - const percyCSS = - ".mx_cryptoEvent, " + - ".mx_NewRoomIntro, " + - ".mx_MessageTimestamp, " + - ".mx_RoomView_myReadMarker, " + - ".mx_GenericEventListSummary { visibility: hidden !important; }"; - - cy.get(".mx_RoomView_timeline").percySnapshotElement("Permalink rendering", { percyCSS }); - }); -}); diff --git a/playwright/e2e/permalinks/permalinks.spec.ts b/playwright/e2e/permalinks/permalinks.spec.ts new file mode 100644 index 0000000000..6b3a10a4d6 --- /dev/null +++ b/playwright/e2e/permalinks/permalinks.spec.ts @@ -0,0 +1,110 @@ +/* +Copyright 2023 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import type { Locator } from "@playwright/test"; +import { test, expect } from "../../element-web-test"; +import { Bot } from "../../pages/bot"; + +const room1Name = "Room 1"; +const room2Name = "Room 2"; +const unknownRoomAlias = "#unknownroom:example.com"; +const permalinkPrefix = "https://matrix.to/#/"; + +const getPill = (locator: Locator, label: string) => { + return locator.locator(".mx_Pill_text", { hasText: new RegExp("^" + label + "$", "g") }); +}; + +test.describe("permalinks", () => { + test.use({ + displayName: "Alice", + }); + + test("shoud render permalinks as expected", async ({ page, app, user, homeserver }) => { + const bob = new Bot(page, homeserver, { displayName: "Bob" }); + const charlotte = new Bot(page, homeserver, { displayName: "Charlotte" }); + await bob.prepareClient(); + await charlotte.prepareClient(); + + // We don't use a bot for danielle as we want a stable MXID. + const danielleId = "@danielle:localhost"; + + const room1Id = await app.client.createRoom({ name: room1Name }); + const room2Id = await app.client.createRoom({ name: room2Name }); + + await app.viewRoomByName(room1Name); + + await app.client.inviteUser(room1Id, bob.credentials.userId); + await app.client.inviteUser(room2Id, charlotte.credentials.userId); + + await app.client.sendMessage(room1Id, "At room mention: @room"); + + await app.client.sendMessage(room1Id, `Permalink to Room 2: ${permalinkPrefix}${room2Id}`); + await app.client.sendMessage( + room1Id, + `Permalink to an unknown room alias: ${permalinkPrefix}${unknownRoomAlias}`, + ); + + const event1Response = await bob.sendMessage(room1Id, "Hello"); + await app.client.sendMessage( + room1Id, + `Permalink to a message in the same room: ${permalinkPrefix}${room1Id}/${event1Response.event_id}`, + ); + + const event2Response = await charlotte.sendMessage(room2Id, "Hello"); + await app.client.sendMessage( + room1Id, + `Permalink to a message in another room: ${permalinkPrefix}${room2Id}/${event2Response.event_id}`, + ); + + await app.client.sendMessage(room1Id, `Permalink to an unknown message: ${permalinkPrefix}${room1Id}/$abc123`); + + await app.client.sendMessage( + room1Id, + `Permalink to a user in the room: ${permalinkPrefix}${bob.credentials.userId}`, + ); + await app.client.sendMessage( + room1Id, + `Permalink to a user in another room: ${permalinkPrefix}${charlotte.credentials.userId}`, + ); + await app.client.sendMessage( + room1Id, + `Permalink to a user with whom alice doesn't share a room: ${permalinkPrefix}${danielleId}`, + ); + + const timeline = page.locator(".mx_RoomView_timeline"); + getPill(timeline, "@room"); + + getPill(timeline, room2Name); + getPill(timeline, unknownRoomAlias); + + getPill(timeline, "Message from Bob"); + getPill(timeline, `Message in ${room2Name}`); + getPill(timeline, "Message"); + + getPill(timeline, "Bob"); + getPill(timeline, "Charlotte"); + // This is the permalink to Danielle's profile. It should only display the MXID + // because the profile is unknown (not sharing any room with Danielle). + getPill(timeline, danielleId); + + await expect(timeline).toMatchScreenshot("permalink-rendering.png", { + mask: [ + // Exclude timestamps from the snapshot, for consistency. + page.locator(".mx_MessageTimestamp"), + ], + }); + }); +}); diff --git a/playwright/pages/client.ts b/playwright/pages/client.ts index 1b893fc970..b3a6cdcaed 100644 --- a/playwright/pages/client.ts +++ b/playwright/pages/client.ts @@ -104,8 +104,8 @@ export class Client { public async sendMessage(roomId: string, content: IContent | string): Promise { if (typeof content === "string") { content = { - body: content, msgtype: "m.text", + body: content, }; } diff --git a/playwright/plugins/homeserver/synapse/templates/default/homeserver.yaml b/playwright/plugins/homeserver/synapse/templates/default/homeserver.yaml index e51ac1918f..a7f40ab402 100644 --- a/playwright/plugins/homeserver/synapse/templates/default/homeserver.yaml +++ b/playwright/plugins/homeserver/synapse/templates/default/homeserver.yaml @@ -92,3 +92,8 @@ oidc_providers: user_mapping_provider: config: display_name_template: "{{ user.name }}" + +# Inhibit background updates as this Synapse isn't long-lived +background_updates: + min_batch_size: 100000 + sleep_duration_ms: 100000 diff --git a/playwright/snapshots/permalinks/permalinks.spec.ts/permalink-rendering-linux.png b/playwright/snapshots/permalinks/permalinks.spec.ts/permalink-rendering-linux.png new file mode 100644 index 0000000000..f32be24fb4 Binary files /dev/null and b/playwright/snapshots/permalinks/permalinks.spec.ts/permalink-rendering-linux.png differ