Files
Recordly/tests/ui/editor-layout.spec.ts

164 lines
6.9 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { expect, test } from "@playwright/test";
import { installDesktopBridge } from "./bridge";
test("advanced controls preserve values and remember each section's view", async ({ page }) => {
await installDesktopBridge(page);
await page.goto("/?windowType=editor");
const advanced = page.getByRole("switch", { name: "Advanced settings" });
await expect(advanced).toBeVisible({ timeout: 20000 });
await expect(page.getByRole("switch", { name: "Link padding sides" })).toHaveCount(0);
const blur = page.getByRole("slider", { name: "Blur", exact: true });
await blur.focus();
await page.keyboard.press("ArrowRight");
const value = await blur.inputValue();
await page.locator("aside").getByText("Advanced", { exact: true }).click();
await expect(page.getByRole("switch", { name: "Link padding sides" })).toBeVisible();
await page.getByRole("radio", { name: "Webcam", exact: true }).click();
await expect(advanced).not.toBeChecked();
await expect(page.getByRole("slider", { name: "Webcam Height" })).toHaveCount(0);
await page.locator("aside").getByText("Advanced", { exact: true }).click();
await expect(page.getByRole("slider", { name: "Webcam Height" })).toBeAttached();
await page.screenshot({
path: "test-results/editor-webcam-advanced.png",
animations: "disabled",
});
await page.getByRole("radio", { name: "Scene", exact: true }).click();
await expect(advanced).toBeChecked();
await expect(blur).toHaveValue(value);
await page.locator("aside").getByText("Advanced", { exact: true }).click();
await expect(blur).toHaveValue(value);
await page.getByRole("row", { name: "Color", exact: true }).click();
await page.getByRole("button", { name: "Custom color", exact: true }).click();
await page.getByRole("textbox", { name: "Hex color", exact: true }).fill("#27AE60");
await page.keyboard.press("Tab");
await expect(page.getByRole("textbox", { name: "Hex color", exact: true })).toHaveValue(
"#27AE60",
);
await page.keyboard.press("Escape");
await page.getByRole("button", { name: "Custom color", exact: true }).click();
await expect(page.getByRole("textbox", { name: "Hex color", exact: true })).toHaveValue(
"#27AE60",
);
await page.screenshot({ path: "test-results/editor-color-picker.png", animations: "disabled" });
});
test("header breadcrumb fits long names, native chrome and compact windows", async ({ page }) => {
await installDesktopBridge(page);
await page.goto("/?windowType=editor");
await expect(page.getByRole("button", { name: "Rename project" })).toBeVisible({
timeout: 20000,
});
await page.getByRole("button", { name: "Rename project" }).click();
await page
.getByRole("textbox", { name: "Project name" })
.fill("A very long project title that should truncate and never cover the toolbar");
// Validate the editing state as well as the display state.
for (const width of [1440, 1280, 800]) {
await page.setViewportSize({ width, height: 800 });
for (const trafficLightsVisible of [true, false]) {
await page.evaluate(
(visible) =>
window.dispatchEvent(
new CustomEvent("test-window-chrome", {
detail: { trafficLightsVisible: visible },
}),
),
trafficLightsVisible,
);
await expect(page.locator(".editor-header-start")).toHaveCSS(
"padding-left",
trafficLightsVisible ? "76px" : "0px",
);
const header = await page.locator(".editor-header").boundingBox();
const dividers = await page.locator(".editor-header").getByRole("separator").all();
expect(dividers).toHaveLength(2);
for (const divider of dividers) {
const box = await divider.boundingBox();
expect(box!.height).toBe(20);
expect(
Math.abs(box!.y + box!.height / 2 - (header!.y + header!.height / 2)),
).toBeLessThanOrEqual(1);
}
const stage = await page.locator(".editor-preview-stage").boundingBox();
const frame = await page.locator(".editor-preview-frame").boundingBox();
expect(
Math.abs(stage!.x + stage!.width / 2 - frame!.x - frame!.width / 2),
).toBeLessThan(1);
expect(
Math.abs(stage!.y + stage!.height / 2 - frame!.y - frame!.height / 2),
).toBeLessThan(1);
const boxes = await Promise.all(
[".editor-header-start", ".editor-header-title", ".editor-header-end"].map(
(selector) => page.locator(selector).boundingBox(),
),
);
const [left, center, right] = boxes;
expect(center!.x).toBeGreaterThan(left!.x);
expect(left!.x + left!.width).toBeLessThanOrEqual(right!.x);
expect(center!.x + center!.width).toBeLessThanOrEqual(right!.x);
const buttons = await page.locator(".editor-playback button").evaluateAll((nodes) =>
nodes
.filter((n) => n.getBoundingClientRect().width > 0)
.map((n) => {
const r = n.getBoundingClientRect();
return { x: r.x, y: r.y, right: r.right, bottom: r.bottom };
}),
);
for (let i = 0; i < buttons.length; i++)
for (let j = i + 1; j < buttons.length; j++) {
const a = buttons[i],
b = buttons[j];
expect(
a.right <= b.x || b.right <= a.x || a.bottom <= b.y || b.bottom <= a.y,
).toBe(true);
}
await expect(
page.getByRole("button", { name: "Export", exact: true }),
).toBeInViewport();
await expect(page.getByRole("button", { name: "Play", exact: true })).toBeInViewport();
}
await page.screenshot({
path: `test-results/editor-layout-${width}.png`,
animations: "disabled",
});
}
await page.keyboard.press("Escape");
await expect(page.getByRole("button", { name: "Rename project" })).toBeVisible();
});
test("header name edits in place and saves on blur without a boxed input", async ({ page }) => {
await installDesktopBridge(page);
await page.addInitScript(() => {
window.electronAPI.saveProjectFileNamed = async (_data, name) => ({
success: true,
path: `/projects/${name}.recordly`,
});
});
await page.goto("/?windowType=editor");
await expect(page.getByRole("button", { name: "Rename project" })).toContainText(
"Untitled Project",
);
await page.getByRole("button", { name: "Rename project" }).click();
const input = page.getByRole("textbox", { name: "Project name" });
await expect(input).toHaveCSS("box-shadow", "none");
await expect(input).toHaveCSS("border-top-width", "0px");
await input.fill("Launch demo");
await input.press("Tab");
await expect(page.getByRole("button", { name: "Rename project" })).toContainText("Launch demo");
await page.getByRole("button", { name: "Rename project" }).click();
await input.fill("Discard this");
await input.press("Escape");
await expect(page.getByRole("button", { name: "Rename project" })).toContainText("Launch demo");
});
test("new zoom blocks default to 1.8x", async ({ page }) => {
await installDesktopBridge(page);
await page.goto("/?windowType=editor");
await page.getByRole("button", { name: "Add Zoom (Z)", exact: true }).click();
await page.locator('[data-variant="zoom"] .timeline-block').first().click();
await expect(page.getByRole("row", { name: "1.8×", exact: true })).toHaveAttribute(
"aria-selected",
"true",
);
});