Files

88 lines
3.4 KiB
TypeScript

import type { Page } from "@playwright/test";
import { expect } from "../fixtures/test-base";
import {
openInstallDialog,
PACKAGE_PATH,
PLUGIN_ID,
uploadPackage,
} from "../tests/plugins/plugin-test-helpers";
import { waitForHttp } from "./causal-waits";
export const TOAST_THEME_CASES = [
{ name: "saved dark", theme: "dark", colorScheme: "light", expected: "dark" },
{ name: "system dark", theme: "system", colorScheme: "dark", expected: "dark" },
{ name: "saved light", theme: "light", colorScheme: "dark", expected: "light" },
] as const;
type ToastThemeCase = (typeof TOAST_THEME_CASES)[number];
export async function verifyPluginToastTheme(page: Page, scenario: ToastThemeCase, mobile = false) {
await page.emulateMedia({ colorScheme: scenario.colorScheme });
await page.addInitScript((theme) => localStorage.setItem("theme", theme), scenario.theme);
if (mobile) {
await page.goto("/settings/plugins");
await page.getByTestId("install-plugin-trigger").tap();
await expect(page.getByTestId("install-plugin-dialog")).toBeVisible();
} else {
await openInstallDialog(page);
}
await expect(page.locator("html")).toHaveClass(new RegExp(`(^|\\s)${scenario.expected}(\\s|$)`));
const installed = waitForHttp(page, "POST", /\/api\/plugins\/install$/);
await uploadPackage(page, PACKAGE_PATH);
expect((await installed).ok()).toBe(true);
const notification = page.locator('[data-sonner-toast][data-type="success"]', {
hasText: "Kandev E2E Fixture Plugin installed",
});
await expect(notification).toBeVisible();
expect(await page.locator("[data-sonner-toaster]").getAttribute("data-sonner-theme")).toBe(
scenario.expected,
);
const colors = await notification.evaluate((element) => {
const style = getComputedStyle(element);
const probe = document.createElement("div");
probe.style.display = "none";
probe.style.backgroundColor = style.getPropertyValue("--success-bg");
probe.style.color = style.getPropertyValue("--success-text");
probe.style.borderColor = style.getPropertyValue("--success-border");
document.body.append(probe);
try {
const palette = getComputedStyle(probe);
return {
background: palette.backgroundColor,
text: palette.color,
border: palette.borderTopColor,
};
} finally {
probe.remove();
}
});
await expect(notification).toHaveCSS("background-color", colors.background);
await expect(notification).toHaveCSS("color", colors.text);
await expect(notification).toHaveCSS("border-top-color", colors.border);
await expect(page.getByTestId(`plugin-row-${PLUGIN_ID}`)).toBeVisible();
await notification.evaluate(async (element) => {
await Promise.all(
element
.getAnimations()
.filter((animation) => Number.isFinite(animation.effect?.getComputedTiming().iterations))
.map((animation) => animation.finished.catch(() => undefined)),
);
});
const box = await notification.boundingBox();
const viewport = page.viewportSize();
expect(box).not.toBeNull();
expect(viewport).not.toBeNull();
expect(box!.x).toBeGreaterThanOrEqual(0);
expect(box!.y).toBeGreaterThanOrEqual(0);
expect(box!.x + box!.width).toBeLessThanOrEqual(viewport!.width);
expect(box!.y + box!.height).toBeLessThanOrEqual(viewport!.height);
expect(await page.evaluate(() => document.documentElement.scrollWidth <= window.innerWidth)).toBe(
true,
);
}