Files
blap/modules/widget-toggles/e2e/widget-toggles.spec.ts
T
Michael Telatynski 44c540eca0 Tweak modules to be disabled if config is missing (#33806)
* Consolidate modules vitest coverage

* Use vite-common as base for modules vitest config

* Make knip happier

* Fix coverage paths

* Place modules unit tests alongside src

* Switch to defineProject for better type safety

* Consolidate vitest CI & coverage

Kills off vite-common

* Update comment

* Update lockfile

* Fix shared-components vitest config

* Soften eslint config for tests in modules

* Run eslint on modules/playwright dir too

* Make tsc happy

* Tweak modules to be disabled if config is missing

* Restore blank line

* Improve coverage

* Potential fix for pull request finding 'Unused variable, import, function or class'

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
2026-06-16 08:41:40 +00:00

187 lines
6.8 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 not error if config is missing", async ({ page }) => {
await expect(page.getByText("Your Element is misconfigured")).not.toBeVisible();
await expect(page.getByText("Errors in module configuration")).not.toBeVisible();
// We don't take a screenshot as we don't want to assert Element's styling, only our own
});
test.describe("with invalid config", () => {
test.use({
config: {
"io.element.element-web-modules.widget-toggles": {
foo: "bar",
},
},
});
test("should render error", 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",
);
},
);
});
});