Files
blap/modules/widget-toggles/e2e/widget-toggles.spec.ts
T
2026-06-08 10:32:12 +01:00

171 lines
6.2 KiB
TypeScript

/*
Copyright 2026 Element Creations Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { type Page } from "@playwright/test";
import { type Credentials } from "@element-hq/element-web-playwright-common/lib/utils/api";
import { type StartedHomeserverContainer } from "@element-hq/element-web-playwright-common/lib/testcontainers/HomeserverContainer";
import { type Container } from "@element-hq/element-web-module-api";
import { test as base, expect } from "../../playwright/element-web-test.ts";
const test = base.extend<{
// Resolver for when to respond to the navigation.json request
navigationJsonResolver: PromiseWithResolvers<void>;
}>({
navigationJsonResolver: async ({}, use) => {
await use(Promise.withResolvers<void>());
},
});
const TEST_WIDGET_NAME = "Name of the test widget";
async function makeRoomWithWidgetAndGoTo(
homeserver: StartedHomeserverContainer,
user: Credentials,
page: Page,
avatarUrl?: string,
): Promise<string> {
const { room_id: roomId } = await homeserver.csApi.request<{ room_id: string }>(
"POST",
"/v3/createRoom",
user.accessToken,
{
name: "Come on in we've got widgets",
},
);
await homeserver.csApi.request<{
event_id: string;
}>("PUT", `/v3/rooms/${encodeURIComponent(roomId)}/state/im.vector.modular.widgets/1`, user.accessToken, {
id: "1",
creatorUserId: user.userId,
type: "m.custom",
name: TEST_WIDGET_NAME,
url: `http://localhost:8080/widget.html`,
avatar_url: avatarUrl,
});
await page.goto(`/#/room/${roomId}`);
return roomId;
}
async function moveWidgetToContainer(
homeserver: StartedHomeserverContainer,
user: Credentials,
roomId: string,
container: Container,
): Promise<void> {
await homeserver.csApi.request(
"PUT",
`/v3/user/${encodeURIComponent(user.userId)}/rooms/${encodeURIComponent(roomId)}/account_data/im.vector.web.settings`,
user.accessToken,
{
"Widgets.layout": {
widgets: {
"1": { container },
},
},
},
);
}
test.describe("widget-toggles", () => {
test.use({
displayName: "Timmy",
page: async ({ context, page, moduleDir }, use) => {
await context.route("http://localhost:8080/widget.html*", async (route) => {
await route.fulfill({ path: `${moduleDir}/e2e/fixture/widget.html`, contentType: "text/html" });
});
await context.route("http://localhost:8080/wigeon.png", async (route) => {
await route.fulfill({ path: `${moduleDir}/e2e/fixture/wigeon.png`, contentType: "image/png" });
});
await page.goto("/");
await use(page);
},
});
test("should error if config is missing", async ({ page }) => {
await expect(page.getByText("Your Element is misconfigured")).toBeVisible();
await expect(page.getByText("Errors in module configuration")).toBeVisible();
// We don't take a screenshot as we don't want to assert Element's styling, only our own
});
test.describe("with correct config", () => {
test.use({
config: {
"io.element.element-web-modules.widget-toggles": {
types: ["m.custom"],
},
},
});
test(
"should render 'show' button for widget not in top",
{ tag: ["@screenshot"] },
async ({ homeserver, page, user }) => {
await makeRoomWithWidgetAndGoTo(homeserver, user, page);
await expect(page.getByRole("button", { name: "Show " + TEST_WIDGET_NAME })).toBeVisible();
},
);
test(
"should render 'hide' button for widget in top",
{ tag: ["@screenshot"] },
async ({ homeserver, page, user }) => {
const roomId = await makeRoomWithWidgetAndGoTo(homeserver, user, page);
await moveWidgetToContainer(homeserver, user, roomId, "top");
await expect(page.getByRole("button", { name: "Hide " + TEST_WIDGET_NAME })).toBeVisible();
},
);
test("should move widget to top when 'show' button is clicked", async ({ homeserver, page, user }) => {
await makeRoomWithWidgetAndGoTo(homeserver, user, page);
await page.getByRole("button", { name: "Show " + TEST_WIDGET_NAME }).click();
await expect(page.getByRole("button", { name: "Hide " + TEST_WIDGET_NAME })).toBeVisible();
await expect(page.locator('iframe[title="Name of the test widget"]')).toBeVisible();
});
test("should move widget to left when 'hide' button is clicked", async ({ homeserver, page, user }) => {
const roomId = await makeRoomWithWidgetAndGoTo(homeserver, user, page);
await moveWidgetToContainer(homeserver, user, roomId, "top");
await expect(page.locator('iframe[title="Name of the test widget"]')).toBeVisible();
await page.getByRole("button", { name: "Hide " + TEST_WIDGET_NAME }).click();
await expect(page.locator('iframe[title="Name of the test widget"]')).not.toBeVisible();
});
test("uses widget icon for button image if present", async ({ homeserver, page, user }) => {
await makeRoomWithWidgetAndGoTo(homeserver, user, page, "mxc://fakehomeserver/fake_content_id");
await expect(
page.getByRole("button", { name: "Show " + TEST_WIDGET_NAME }).getByRole("img"),
).toHaveAttribute("src", /\/_matrix\/media\/v3\/download\/fakehomeserver\/fake_content_id$/);
});
test(
"uses built in icon for widgets with no avatar",
{ tag: ["@screenshot"] },
async ({ homeserver, page, user }) => {
await makeRoomWithWidgetAndGoTo(homeserver, user, page);
await expect(page.getByRole("button", { name: "Show " + TEST_WIDGET_NAME })).toMatchScreenshot(
"widget-toggle-button-default-icon.png",
);
},
);
});
});