Files
Reactive-Resume/tests/e2e/specs/preview-direction.spec.ts
T
Amruth Pillai 443897dcb0 test(e2e): drive documents, trash and the new-document dialog
The shared fixture creates its sample resume through the API and opens
it; documents-new covers Start blank (named after the headline) and Copy
for a job (linked and searchable by the application). dashboard-lifecycle
renames inline, duplicates, trashes with undo, restores and deletes now;
the letter, lock, view, import, auth and direction specs follow the new
library and menus.
2026-09-28 20:39:04 +02:00

71 lines
3.3 KiB
TypeScript

import type { Page } from "@playwright/test";
import { Pool } from "pg";
import { expect, test } from "../fixtures/test";
// The page is centered in the canvas beside the panel, not in the viewport. The canvas's scrollbar sits on the
// left in right-to-left layouts, so the center comes from its content box.
async function expectCenteredPreview(page: Page) {
const canvas = page.locator('[aria-hidden="false"] canvas').first();
await expect(canvas).toBeVisible();
await expect
.poll(() =>
canvas.evaluate((element) => {
let scroller = element.parentElement;
while (scroller && getComputedStyle(scroller).overflowY !== "auto") scroller = scroller.parentElement;
if (!scroller) return Number.POSITIVE_INFINITY;
const bounds = element.getBoundingClientRect();
const center = scroller.getBoundingClientRect().left + scroller.clientLeft + scroller.clientWidth / 2;
return Math.abs(bounds.left + bounds.width / 2 - center);
}),
)
.toBeLessThan(1);
}
for (const uiLanguage of ["English", "Arabic"]) {
for (const resumeLocale of ["en-US", "ar-SA"]) {
test(`centers preview with ${uiLanguage} UI and ${resumeLocale} resume`, async ({ authPage: page }, info) => {
test.setTimeout(60_000);
await page.setViewportSize({ width: 1920, height: 950 });
const created = await page.request.post("/api/openapi/resumes", {
data: { name: "Preview direction fixture", tags: [] },
});
expect(created.ok()).toBe(true);
const resumeId = (await created.json()) as string;
await page.goto("/dashboard");
const builderUrl = new URL(`/builder/${resumeId}`, page.url()).toString();
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
try {
await pool.query(
`update resume set data = jsonb_set(jsonb_set(data, '{metadata,page,locale}', $2::jsonb), '{basics,name}', '"Preview direction fixture"'::jsonb) where id = $1`,
[resumeId, JSON.stringify(resumeLocale)],
);
} finally {
await pool.end();
}
// The editor has no account menu; the UI language comes from the same cookie the language picker sets.
if (uiLanguage === "Arabic") {
await page.context().addCookies([{ name: "locale", value: "ar-SA", url: new URL(builderUrl).origin }]);
}
await page.goto(builderUrl);
await expect(page.locator("html")).toHaveAttribute("dir", uiLanguage === "Arabic" ? "rtl" : "ltr");
await expectCenteredPreview(page);
// The zoom bar's middle button shows "Fit" or the zoom level; its name isn't translated yet.
const zoom = page.getByRole("button", { name: "Fit page to width", exact: true });
await expect(zoom).toHaveCSS("direction", uiLanguage === "Arabic" ? "rtl" : "ltr");
await expect(zoom).not.toHaveText(/%/);
await page.getByRole("button", { name: uiLanguage === "Arabic" ? "تصغير" : "Zoom out", exact: true }).click();
await expect(zoom).toHaveText(/^\d+%$/);
await expectCenteredPreview(page);
await zoom.click();
await expect(zoom).not.toHaveText(/%/);
await expectCenteredPreview(page);
const direction = await page
.locator('[aria-hidden="false"] canvas')
.first()
.evaluate((canvas) => canvas.closest("[dir]")?.getAttribute("dir"));
expect(direction).toBe(resumeLocale === "ar-SA" ? "rtl" : "ltr");
await page.screenshot({ path: info.outputPath("centered-preview.png") });
});
}
}