sokko-g/e2e/calculator.spec.js
Shinuwa a4268dac54
All checks were successful
Deploy Sokko G / deploy (push) Successful in 18s
Cover calculator hierarchy and result workflows
2026-09-14 16:19:16 +02:00

112 lines
6.6 KiB
JavaScript

// Rôle : vérifie les calculs hiérarchiques et les actions du calculateur dans une toolbox réelle.
import { expect, test } from "@playwright/test";
async function setup(page) {
await page.goto("/#/toolboxes");
await page.getByRole("button", { name: "Nouvelle toolbox" }).click();
const dialog = page.getByRole("dialog", { name: "Nouvelle toolbox" });
await dialog.getByLabel("Nom").fill("Calculator workflows");
await dialog.getByRole("button", { name: "Créer", exact: true }).click();
await page.getByRole("button", { name: "Ajouter un outil", exact: true }).click();
await page.getByRole("dialog", { name: "Ajouter un outil" }).getByRole("button", { name: "Calculateur", exact: true }).click();
return page.locator('[data-module-type="calculator"]');
}
function entry(tool, label) {
return tool.locator(".calculator-entry").filter({ has: tool.page().getByRole("button", { name: `Supprimer ${label}`, exact: true }) });
}
async function saveRoot(tool, formula, label) {
await tool.getByRole("textbox", { name: "Calcul", exact: true }).fill(formula);
await tool.getByLabel("Libellé", { exact: true }).fill(label);
await tool.getByRole("button", { name: "Enregistrer", exact: true }).click();
await expect(entry(tool, label)).toBeVisible();
}
test("parent edits recalculate descendants and survive reload; deleting a parent removes its subtree", async ({ page }) => {
const tool = await setup(page);
const expression = tool.getByRole("textbox", { name: "Calcul", exact: true });
await expression.fill("2 +");
await expect(tool.getByRole("button", { name: "Enregistrer", exact: true })).toBeDisabled();
await saveRoot(tool, "2 + 3 * 4", "Parent");
await expect(entry(tool, "Parent").locator("strong")).toHaveAttribute("aria-label", "14");
await tool.getByRole("button", { name: "Ajouter un calcul enfant Parent", exact: true }).click();
await expect(expression).toBeFocused();
await expect(expression).toContainText("Valeur du parent");
await expression.press("End");
await expression.pressSequentially(" * 3");
await tool.getByLabel("Libellé", { exact: true }).fill("Child");
await tool.getByRole("button", { name: "Mettre à jour", exact: true }).click();
await expect(entry(tool, "Child").locator("strong")).toHaveAttribute("aria-label", "42");
await entry(tool, "Parent").getByTitle("Modifier", { exact: true }).click();
await expression.fill("20");
await tool.getByRole("button", { name: "Mettre à jour", exact: true }).click();
await expect(entry(tool, "Child").locator("strong")).toHaveAttribute("aria-label", "60");
await page.reload();
await expect(entry(tool, "Parent").locator("strong")).toHaveAttribute("aria-label", "20");
await expect(entry(tool, "Child").locator("strong")).toHaveAttribute("aria-label", "60");
await entry(tool, "Child").getByTitle("Modifier", { exact: true }).click();
await tool.getByRole("button", { name: "Supprimer Parent", exact: true }).click();
await expect(tool.locator(".calculator-entry")).toHaveCount(0);
await expect(expression).toHaveValue("");
await expect(tool.getByRole("button", { name: "Enregistrer", exact: true })).toBeDisabled();
await page.reload();
await expect(tool.getByText("Aucun résultat enregistré.", { exact: true })).toBeVisible();
});
test("reset clears only the draft, new calculation returns to root, and clipboard and scroll preferences persist", async ({ page, context }) => {
await context.grantPermissions(["clipboard-read", "clipboard-write"]);
const tool = await setup(page);
await expect(tool.getByRole("button", { name: "Copier pour checklist", exact: true })).toBeDisabled();
await saveRoot(tool, "10", "Ore");
await tool.getByRole("button", { name: "Ajouter un calcul enfant Ore", exact: true }).click();
await tool.getByRole("textbox", { name: "Calcul", exact: true }).fill("base * 2");
await tool.getByLabel("Libellé", { exact: true }).fill("Bars");
await tool.getByRole("button", { name: "Mettre à jour", exact: true }).click();
await tool.getByRole("button", { name: "Nouveau calcul", exact: true }).click();
await saveRoot(tool, "7", "Spare");
await tool.getByRole("textbox", { name: "Calcul", exact: true }).fill("99");
await tool.getByLabel("Libellé", { exact: true }).fill("Unsaved");
await tool.getByRole("button", { name: "Réinitialiser", exact: true }).click();
await expect(tool.getByRole("textbox", { name: "Calcul", exact: true })).toHaveValue("");
await expect(tool.getByLabel("Libellé", { exact: true })).toHaveValue("");
await expect(tool.locator(".calculator-entry")).toHaveCount(3);
await tool.getByRole("button", { name: "Copier pour checklist", exact: true }).click();
await expect.poll(() => page.evaluate(() => globalThis.navigator.clipboard.readText())).toBe("Ore:10\nBars:20\nSpare:7");
const scroll = tool.getByRole("button", { name: "Liste scrollable", exact: true });
await expect(scroll).toHaveAttribute("aria-pressed", "false");
await scroll.click();
await page.reload();
await expect(scroll).toHaveAttribute("aria-pressed", "true");
await expect(tool.locator(".calculator-tree")).toHaveCSS("overflow-y", "auto");
await scroll.click();
await page.reload();
await expect(scroll).toHaveAttribute("aria-pressed", "false");
await expect(tool.locator(".calculator-entry")).toHaveCount(3);
});
test("reordering roots keeps descendants attached and rejects moving a child to another parent", async ({ page }) => {
const tool = await setup(page);
await saveRoot(tool, "10", "First");
await saveRoot(tool, "20", "Second");
await tool.getByRole("button", { name: "Ajouter un calcul enfant First", exact: true }).click();
await tool.getByLabel("Libellé", { exact: true }).fill("Child");
await tool.getByRole("button", { name: "Mettre à jour", exact: true }).click();
async function drag(label, targetLabel) {
await tool.getByRole("button", { name: `Déplacer ${label}`, exact: true }).hover();
await page.mouse.down();
const target = entry(tool, targetLabel);
await target.scrollIntoViewIfNeeded();
const box = await target.boundingBox();
await page.mouse.move(box.x + box.width / 2, box.y + box.height * 0.2, { steps: 5 });
await page.mouse.up();
}
await drag("Second", "First");
await expect(tool.locator(".calculator-entry em")).toHaveText(["Second", "First", "Child"]);
await drag("Child", "Second");
await expect(tool.locator(".calculator-entry em")).toHaveText(["Second", "First", "Child"]);
await page.reload();
await expect(tool.locator(".calculator-entry em")).toHaveText(["Second", "First", "Child"]);
await tool.getByRole("button", { name: "Supprimer First", exact: true }).click();
await expect(tool.locator(".calculator-entry em")).toHaveText(["Second"]);
});