166 lines
7.9 KiB
JavaScript
166 lines
7.9 KiB
JavaScript
// Rôle : vérifie les brouillons RNG et les changements d'image sans état périmé sous StrictMode.
|
|
/* global window, document */
|
|
import { test, expect } from "@playwright/test";
|
|
import { fileURLToPath, URL } from "node:url";
|
|
|
|
const probeUrl = `/@fs/${fileURLToPath(new URL("./fixtures/editor-lifecycle-probe.js", import.meta.url))}`;
|
|
|
|
async function setup(page, kind, props = {}) {
|
|
await page.goto("/");
|
|
await page.evaluate(async ({ url, kind, props }) => {
|
|
const { mountEditorProbe, controlImageDecoding } = await import(url);
|
|
document.getElementById("app").style.display = "none";
|
|
const element = document.createElement("div");
|
|
element.id = "editor-probe";
|
|
document.body.prepend(element);
|
|
if (kind === "cover" || kind === "viewer") {
|
|
const canvas = document.createElement("canvas");
|
|
canvas.width = 800;
|
|
canvas.height = 400;
|
|
const ctx = canvas.getContext("2d");
|
|
ctx.fillStyle = "#22d3ee";
|
|
ctx.fillRect(0, 0, 800, 400);
|
|
window.probeImage = canvas.toDataURL();
|
|
if (kind === "cover") {
|
|
window.probeFile = await new Promise((resolve) => canvas.toBlob(resolve));
|
|
window.decoding = controlImageDecoding();
|
|
if (props.existingCover) props.existingCover = window.probeImage;
|
|
else props.file = window.probeFile;
|
|
} else {
|
|
window.viewerImage = {
|
|
dataUrl: window.probeImage, canAnnotate: true,
|
|
markers: [{ id: "a", label: "First", x: 30, y: 30 }],
|
|
onChangeMarkers: () => {}, onChangeDrawings: () => {}
|
|
};
|
|
props.image = window.viewerImage;
|
|
}
|
|
}
|
|
window.editorProbe = mountEditorProbe(element, kind, props);
|
|
}, { url: probeUrl, kind, props });
|
|
return page.locator("#editor-probe");
|
|
}
|
|
|
|
test("RNG drafts follow rate and module identity without losing unrelated edits", async ({ page }) => {
|
|
const rates = [
|
|
{ id: "a", label: "First", rate: "10", costPerDraw: "12" },
|
|
{ id: "b", label: "Second", rate: "20", costPerDraw: "34", occurrenceValue: 2, occurrenceUnit: "perDay" }
|
|
];
|
|
const editor = await setup(page, "rng", { data: { rates, activeRateId: "a" } });
|
|
const cost = editor.getByLabel("Coût d'un tirage");
|
|
await cost.fill("999");
|
|
await page.evaluate(() => window.editorProbe.update({}));
|
|
await expect(cost).toHaveValue("999");
|
|
const snapshots = await page.evaluate((rates) => {
|
|
window.editorProbe.update({ data: { rates, activeRateId: "b" } });
|
|
return window.editorProbe.snapshots;
|
|
}, rates);
|
|
expect(snapshots.length).toBeGreaterThan(0);
|
|
for (const values of snapshots) {
|
|
expect(values).toContain("34");
|
|
expect(values).not.toContain("999");
|
|
}
|
|
await editor.getByRole("tab", { name: "Prévisions", exact: true }).click();
|
|
await expect(editor.getByRole("combobox", { name: "Période", exact: true })).toHaveValue("perDay");
|
|
await cost.fill("777");
|
|
await page.evaluate(() => window.editorProbe.update({ moduleId: "other" }));
|
|
await expect(cost).toHaveValue("34");
|
|
await cost.fill("56");
|
|
await cost.press("Tab");
|
|
expect(await page.evaluate(() => window.editorProbe.saves.at(-1).rates[1].costPerDraw)).toBe("56");
|
|
await page.evaluate(() => window.editorProbe.update({ editing: true }));
|
|
const label = editor.locator('.rng-simulator-rate-form input').first();
|
|
await label.fill("Unsubmitted");
|
|
await page.evaluate(() => window.editorProbe.update({ editing: false }));
|
|
await expect(label).toHaveCount(0);
|
|
await page.evaluate(() => window.editorProbe.update({ editing: true }));
|
|
await expect(label).toHaveValue("");
|
|
});
|
|
|
|
test("viewer resets markers and drawing tools before committing a replacement image", async ({ page }) => {
|
|
const editor = await setup(page, "viewer");
|
|
const marker = editor.getByRole("textbox", { name: "Libellé du marqueur 1" });
|
|
await marker.fill("Edited");
|
|
await editor.getByTitle("Dessiner", { exact: true }).click();
|
|
await editor.getByTitle("Gommer", { exact: true }).click();
|
|
await page.evaluate(() => window.editorProbe.update({}));
|
|
await expect(marker).toHaveValue("Edited");
|
|
await expect(editor.getByTitle("Gommer", { exact: true })).toHaveAttribute("aria-pressed", "true");
|
|
const snapshots = await page.evaluate(() => {
|
|
window.editorProbe.update({ image: {
|
|
...window.viewerImage, drawingMode: "temporary",
|
|
markers: [{ id: "b", label: "Second", x: 60, y: 60 }]
|
|
} });
|
|
return window.editorProbe.snapshots;
|
|
});
|
|
expect(snapshots.length).toBeGreaterThan(0);
|
|
for (const values of snapshots) expect(values).toEqual(["Second"]);
|
|
await expect(editor.getByTitle("Dessiner", { exact: true })).toHaveAttribute("aria-pressed", "false");
|
|
await editor.getByTitle("Dessiner", { exact: true }).click();
|
|
await expect(editor.getByTitle("Gommer", { exact: true })).toHaveAttribute("aria-pressed", "false");
|
|
await expect(editor.getByRole("button", { name: "Annotations temporaires" })).toBeVisible();
|
|
await page.evaluate(() => window.editorProbe.unmount());
|
|
});
|
|
|
|
test("cover ignores obsolete decodes and releases every bitmap and object URL", async ({ page }) => {
|
|
const errors = [];
|
|
page.on("pageerror", (error) => errors.push(error.message));
|
|
const editor = await setup(page, "cover");
|
|
const save = editor.getByRole("button", { name: "Valider", exact: true });
|
|
await expect(save).toBeDisabled();
|
|
expect(await page.evaluate(() => window.decoding.pending.length)).toBe(2);
|
|
await page.evaluate(async () => {
|
|
await window.decoding.resolve(0);
|
|
await window.decoding.resolve(1);
|
|
});
|
|
await expect(save).toBeEnabled();
|
|
await expect(editor.locator("img")).toBeVisible();
|
|
await editor.getByLabel("Zoom", { exact: true }).press("End");
|
|
await save.click();
|
|
expect(await page.evaluate(() => window.editorProbe.saves[0])).toMatch(/^data:image\/(webp|jpeg);base64,/);
|
|
await page.evaluate(() => window.editorProbe.update({ file: window.probeFile.slice() }));
|
|
await expect(save).toBeDisabled();
|
|
await expect(editor.locator("img")).toHaveCount(0);
|
|
await page.evaluate(() => window.editorProbe.update({ file: window.probeFile.slice() }));
|
|
await page.evaluate(async () => {
|
|
await window.decoding.resolve(3);
|
|
window.decoding.reject(2);
|
|
});
|
|
await expect(save).toBeEnabled();
|
|
await expect(editor.locator(".toolbox-cover-editor-error")).toHaveCount(0);
|
|
await page.evaluate(() => window.editorProbe.update({ file: window.probeFile.slice() }));
|
|
await page.evaluate(() => window.decoding.reject(4));
|
|
await expect(save).toBeDisabled();
|
|
await expect(editor.locator(".toolbox-cover-editor-error")).toBeVisible();
|
|
await page.evaluate(() => {
|
|
window.editorProbe.update({ file: window.probeFile.slice() });
|
|
window.editorProbe.unmount();
|
|
});
|
|
await page.evaluate(() => window.decoding.resolve(5));
|
|
const resources = await page.evaluate(() => {
|
|
window.decoding.restore();
|
|
return { created: window.decoding.created, revoked: window.decoding.revoked, closed: window.decoding.closed };
|
|
});
|
|
expect(resources.revoked.sort()).toEqual(resources.created.sort());
|
|
expect(resources.closed.sort()).toEqual([0, 1, 3, 5]);
|
|
expect(errors).toEqual([]);
|
|
});
|
|
|
|
test("cover loads an existing image and clears it when the source is removed", async ({ page }) => {
|
|
const editor = await setup(page, "cover", { existingCover: true });
|
|
await expect.poll(() => page.evaluate(() => window.decoding.pending.length)).toBe(2);
|
|
await page.evaluate(async () => {
|
|
await window.decoding.resolve(0);
|
|
await window.decoding.resolve(1);
|
|
});
|
|
await expect(editor.getByRole("button", { name: "Valider", exact: true })).toBeEnabled();
|
|
await page.evaluate(() => window.editorProbe.update({ existingCover: "" }));
|
|
await expect(editor.locator("img")).toHaveCount(0);
|
|
await expect(editor.getByRole("button", { name: "Valider", exact: true })).toBeDisabled();
|
|
const resources = await page.evaluate(() => {
|
|
window.editorProbe.unmount();
|
|
window.decoding.restore();
|
|
return { created: window.decoding.created, closed: window.decoding.closed };
|
|
});
|
|
expect(resources.created).toEqual([]);
|
|
expect(resources.closed.sort()).toEqual([0, 1]);
|
|
});
|