diff --git a/apps/web/playwright/e2e/links/messages.spec.ts b/apps/web/playwright/e2e/links/messages.spec.ts new file mode 100644 index 0000000000..579a070722 --- /dev/null +++ b/apps/web/playwright/e2e/links/messages.spec.ts @@ -0,0 +1,59 @@ +/* +Copyright 2026 New Vector Ltd. + +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"; + +test.describe("Message links", () => { + test.use({ + displayName: "Alice", + room: async ({ user, app, bot }, use) => { + const roomId = await app.client.createRoom({ name: "Test room" }); + await use({ roomId }); + }, + }); + for (const link of ["https://example.org", "example.org", "ftp://example.org"]) { + test(`should linkify a regular link '${link}'`, async ({ page, user, app, room }) => { + await page.goto(`#/room/${room.roomId}`); + // Needs to be unformatted so we test linkifing + await app.client.sendMessage(room.roomId, `Check out ${link}`); + const linkElement = page.locator(".mx_EventTile_last").getByRole("link", { name: link }); + await app.timeline.scrollToBottom(); + await expect(linkElement).toBeVisible(); + }); + } + test("should linkify a User ID", async ({ page, user, app, room }) => { + await page.goto(`#/room/${room.roomId}`); + // Needs to be unformatted so we test linkifing + await app.client.sendMessage(room.roomId, `Check out @bob:example.org`); + const linkElement = page.locator(".mx_EventTile_last").getByRole("link", { name: "@bob:example.org" }); + await expect(linkElement).toHaveAttribute("href", `https://matrix.to/#/@bob:example.org`); + }); + test("should linkify a Room alias", async ({ page, user, app, room }) => { + await page.goto(`#/room/${room.roomId}`); + // Needs to be unformatted so we test linkifing + await app.client.sendMessage(room.roomId, "Check out #aroom:example.org"); + const linkElement = page.locator(".mx_EventTile_last").getByRole("link", { name: "#aroom:example.org" }); + await expect(linkElement).toHaveAttribute("href", "https://matrix.to/#/#aroom:example.org"); + }); + test("should linkify text inside a URL preview", { tag: "@screenshot" }, async ({ page, user, app, room, axe }) => { + axe.disableRules("color-contrast"); + await page.route(/.*\/_matrix\/(client\/v1\/media|media\/v3)\/preview_url.*/, (route, request) => { + const requestedPage = new URL(request.url()).searchParams.get("url"); + expect(requestedPage).toEqual("https://example.org/"); + return route.fulfill({ + json: { + "og:title": "A simple site", + "og:description": "And with a brief description containing https://example.org/another-link", + }, + }); + }); + await page.goto(`#/room/${room.roomId}`); + await app.client.sendMessage(room.roomId, "Check out https://example.org/"); + await expect( + page.locator(".mx_EventTile_last").getByRole("link", { name: "https://example.org/another-link" }), + ).toBeVisible(); + }); +}); diff --git a/apps/web/playwright/e2e/permalinks/permalinks.spec.ts b/apps/web/playwright/e2e/links/permalinks.spec.ts similarity index 100% rename from apps/web/playwright/e2e/permalinks/permalinks.spec.ts rename to apps/web/playwright/e2e/links/permalinks.spec.ts diff --git a/apps/web/playwright/e2e/links/topic.spec.ts b/apps/web/playwright/e2e/links/topic.spec.ts new file mode 100644 index 0000000000..f6574860cd --- /dev/null +++ b/apps/web/playwright/e2e/links/topic.spec.ts @@ -0,0 +1,48 @@ +/* +Copyright 2026 New Vector Ltd. + +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"; + +test.describe("Topic links", () => { + test.use({ + displayName: "Alice", + room: async ({ user, app, bot }, use) => { + const roomId = await app.client.createRoom({ name: "Test room" }); + await use({ roomId }); + }, + }); + for (const link of [ + "https://example.org", + "example.org", + "ftp://example.org", + "#aroom:example.org", + "@alice:example.org", + ]) { + // Playwright treats '@' as a tag, so replace it to be safe + test(`should linkify plaintext '${link.replace("@", "_@")}'`, async ({ page, user, app, room }) => { + await app.client.sendStateEvent( + room.roomId, + "m.room.topic", + { + "m.topic": { + // Deliberately no HTML version. + "m.text": [ + { + body: `An interesting room topic containing ${link}`, + }, + ], + }, + "topic": `An interesting room topic containing ${link}`, + }, + "", + ); + await page.goto(`#/room/${room.roomId}`); + await expect(page.getByTestId("topic").getByRole("link", { name: link })).toBeVisible(); + const locator = await app.toggleRoomInfoPanel(); + await expect(locator.getByRole("link", { name: link })).toBeVisible(); + }); + } +}); diff --git a/apps/web/playwright/snapshots/permalinks/permalinks.spec.ts/permalink-rendering-linux.png b/apps/web/playwright/snapshots/links/permalinks.spec.ts/permalink-rendering-linux.png similarity index 100% rename from apps/web/playwright/snapshots/permalinks/permalinks.spec.ts/permalink-rendering-linux.png rename to apps/web/playwright/snapshots/links/permalinks.spec.ts/permalink-rendering-linux.png