Files
EpicNext-Cms/e2e/ui/furniture-jobs.spec.ts
T
Simo 13bd3695cb
CI / check (push) Successful in 2m5s
CI / deploy (push) Successful in 1m8s
CI / publish-container (push) Successful in 1m4s
feat(studio): recover matching Nitro sources and persist import phases
2026-09-11 10:22:06 +02:00

146 lines
4.7 KiB
TypeScript

import { expect, test } from "@playwright/test";
import {
furnitureCursorFixture,
furnitureJobFixture,
} from "../../src/test/furniture-jobs-fixtures";
test("history hook deduplicates refreshes, pages and reports completion once", async ({
page,
}) => {
let requests = 0;
let completed = false;
await page.route("**/api/admin/studio/import-jobs?*", async (route) => {
requests++;
const secondPage = new URL(route.request().url()).searchParams.has(
"before",
);
await new Promise((resolve) => setTimeout(resolve, 100));
await route.fulfill({
json: {
ok: true,
jobs: [
{
...furnitureJobFixture,
id: secondPage
? "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb"
: furnitureJobFixture.id,
state: completed ? "completed" : "queued",
},
],
nextCursor: secondPage ? null : furnitureCursorFixture,
},
});
});
await page.goto("/admin/jobs-harness");
await expect(page.getByLabel("Jobs", { exact: true })).toContainText(
furnitureJobFixture.id,
);
await expect(page.getByLabel("Loading", { exact: true })).toHaveText("false");
const initial = requests;
await page.getByRole("button", { name: "Refresh twice" }).click();
await expect(page.getByLabel("Loading", { exact: true })).toHaveText("true");
await expect(page.getByLabel("Loading", { exact: true })).toHaveText("false");
expect(requests).toBe(initial + 1);
await page.getByRole("button", { name: "Next page" }).click();
await expect(page.getByLabel("Page", { exact: true })).toHaveText("2");
await expect(page.getByLabel("Jobs", { exact: true })).toContainText(
"bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
);
await page.getByRole("button", { name: "Previous page" }).click();
await expect(page.getByLabel("Page", { exact: true })).toHaveText("1");
await expect(page.getByLabel("Jobs", { exact: true })).toContainText(
furnitureJobFixture.id,
);
await expect(page.getByLabel("Loading", { exact: true })).toHaveText("false");
completed = true;
await page.getByRole("button", { name: "Refresh twice" }).click();
await expect(page.getByLabel("Loading", { exact: true })).toHaveText("true");
await expect(page.getByLabel("Completions", { exact: true })).toHaveText("1");
await expect(page.getByLabel("Loading", { exact: true })).toHaveText("false");
await page.getByRole("button", { name: "Refresh twice" }).click();
await expect(page.getByLabel("Loading", { exact: true })).toHaveText("true");
await expect(page.getByLabel("Loading", { exact: true })).toHaveText("false");
await expect(page.getByLabel("Completions", { exact: true })).toHaveText("1");
});
test("history polling pauses while hidden and refreshes on visibility return", async ({
page,
}) => {
let requests = 0;
await page.clock.install();
await page.route("**/api/admin/studio/import-jobs?*", (route) => {
requests++;
return route.fulfill({
json: { ok: true, jobs: [furnitureJobFixture], nextCursor: null },
});
});
await page.goto("/admin/jobs-harness");
await expect(page.getByLabel("Jobs", { exact: true })).toContainText(
furnitureJobFixture.id,
);
await expect(page.getByLabel("Loading", { exact: true })).toHaveText("false");
await page.evaluate(() => {
Object.defineProperty(document, "visibilityState", {
configurable: true,
get: () => "hidden",
});
document.dispatchEvent(new Event("visibilitychange"));
});
const hiddenCount = requests;
await page.clock.fastForward(60000);
expect(requests).toBe(hiddenCount);
await page.evaluate(() => {
Object.defineProperty(document, "visibilityState", {
configurable: true,
get: () => "visible",
});
document.dispatchEvent(new Event("visibilitychange"));
});
await expect.poll(() => requests).toBe(hiddenCount + 1);
});
test("history shows the current phase and validated recovery source", async ({
page,
}) => {
await page.route("**/api/admin/studio/import-jobs?*", (route) =>
route.fulfill({
json: {
ok: true,
jobs: [
{
...furnitureJobFixture,
state: "running",
items: [
{
...furnitureJobFixture.items[0],
state: "running",
phase: "writing_db",
phaseStartedAt: new Date().toISOString(),
recoveredSource: {
sourceId: "configured",
sourceName: "Configured source",
revision: 42,
},
},
],
},
],
nextCursor: null,
},
}),
);
await page.goto("/admin/jobs-harness?progress");
await page.locator("details details summary").click();
await expect(
page.getByText("Current phase: Saving SQL and catalog"),
).toBeVisible();
await expect(
page.getByText(/Bundle recovered from Configured source/),
).toBeVisible();
expect(
await page.evaluate(
() => document.documentElement.scrollWidth > innerWidth,
),
).toBe(false);
});