// Rôle : vérifie les brouillons de formulaire et le cycle de déplacement par pointeur sans assertions de code source. /* global window, document */ import { test, expect } from "@playwright/test"; import { fileURLToPath, URL } from "node:url"; const probeUrl = `/@fs/${fileURLToPath(new URL("./fixtures/form-reorder-probe.js", import.meta.url))}`; async function setup(page, kind) { await page.goto("/"); await page.evaluate(async ({ url, kind }) => { const { mountFormReorderProbe } = await import(url); document.getElementById("app").style.display = "none"; const element = document.createElement("div"); document.body.prepend(element); window.interactionProbe = mountFormReorderProbe(element, kind); }, { url: probeUrl, kind }); } test("draft forms retain edits, report validation, prevent navigation and reset after success", async ({ page }) => { await setup(page, "form"); const title = page.getByRole("textbox", { name: "Title", exact: true }); const detail = page.getByRole("textbox", { name: "Detail", exact: true }); await title.fill(""); await page.getByRole("button", { name: "Submit", exact: true }).click(); await expect(page.getByRole("alert")).toHaveText("Required"); await title.fill("Draft"); await expect(page.getByRole("alert")).toBeEmpty(); await page.evaluate(() => window.interactionProbe.update(1)); await expect(title).toHaveValue("Draft"); await expect(detail).toHaveValue("Kept"); await page.getByRole("button", { name: "Patch", exact: true }).click(); await expect(title).toHaveValue("Patched"); await expect(detail).toHaveValue("Kept"); await page.getByRole("button", { name: "Replace", exact: true }).click(); await expect(title).toHaveValue("Replacement"); await expect(detail).toHaveValue("New"); await title.press("Enter"); await expect(title).toHaveValue("Initial"); await expect(detail).toHaveValue("Kept"); expect(await page.evaluate(() => window.interactionProbe.events)).toEqual([ "changed", { title: "", detail: "Kept" }, { prevented: true }, "changed", { title: "Replacement", detail: "New" }, { prevented: true } ]); }); async function start(page) { await page.getByRole("button", { name: "a", exact: true }).hover(); await page.mouse.down(); await expect(page.getByLabel("Dragging")).toHaveText("a"); } test("pointer drops resolve before and after using the latest callback and reject invalid targets", async ({ page }) => { await setup(page, "reorder"); await page.getByRole("button", { name: "a", exact: true }).hover(); await page.mouse.down({ button: "right" }); await expect(page.getByLabel("Dragging")).toBeEmpty(); await page.mouse.up({ button: "right" }); const target = await page.locator('[data-probe-item="b"]').boundingBox(); for (const [offset, placement] of [[10, "before"], [90, "after"]]) { await start(page); await page.evaluate(() => window.interactionProbe.update(1)); await page.mouse.move(target.x + 200, target.y + offset); await page.mouse.up(); await expect(page.getByLabel("Dragging")).toBeEmpty(); expect(await page.evaluate(() => window.interactionProbe.events.at(-1))).toEqual({ source: "a", target: "b", placement, revision: 1 }); } await start(page); await page.locator('[data-probe-item="blocked"]').hover(); await page.mouse.up(); await start(page); await page.mouse.up(); expect(await page.evaluate(() => window.interactionProbe.events.length)).toBe(2); }); test("pointer cancellation never commits a drop and unmount removes active listeners", async ({ page }) => { await setup(page, "reorder"); const target = await page.locator('[data-probe-item="b"]').boundingBox(); await start(page); await page.mouse.move(target.x + 200, target.y + 50); await page.getByRole("button", { name: "a", exact: true }).dispatchEvent("pointercancel", { clientX: target.x + 200, clientY: target.y + 50, pointerId: 1 }); await expect(page.getByLabel("Dragging")).toBeEmpty(); await page.mouse.up(); expect(await page.evaluate(() => window.interactionProbe.events)).toEqual([]); await start(page); await page.evaluate(() => { const remainingTarget = document.querySelector('[data-probe-item="b"]').cloneNode(true); window.interactionProbe.unmount(); document.body.prepend(remainingTarget); }); await page.locator('[data-probe-item="b"]').hover(); await page.mouse.up(); expect(await page.evaluate(() => window.interactionProbe.events)).toEqual([]); });