159 lines
9.4 KiB
JavaScript
159 lines
9.4 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" }).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("current values are subtracted from totals and kept during recalculation", async ({ page }) => {
|
|
const tool = await setup(page);
|
|
const expression = tool.getByRole("textbox", { name: "Calcul", exact: true });
|
|
const current = tool.getByLabel("Actuel", { exact: true });
|
|
const totalLabel = tool.getByText("Total", { exact: true });
|
|
await expect(current).toHaveCount(0);
|
|
await expect(totalLabel).toHaveCount(0);
|
|
const subtractCurrent = tool.getByRole("button", { name: "Soustraire l'actuel", exact: true });
|
|
await expect(subtractCurrent).toHaveAttribute("aria-pressed", "false");
|
|
await subtractCurrent.click();
|
|
await expect(subtractCurrent).toHaveAttribute("aria-pressed", "true");
|
|
await expect(current).toBeFocused();
|
|
await expect(totalLabel).toBeVisible();
|
|
await expect(tool.locator(".calculator-result-field")).toHaveClass(/has-current/);
|
|
await expect(tool.locator(".calculator-result").getByText("Résultat", { exact: true })).toHaveCount(0);
|
|
await expect(tool.locator(".calculator-result-field > span")).toHaveText("Résultat");
|
|
const expressionBounds = await expression.boundingBox();
|
|
const currentBounds = await current.boundingBox();
|
|
expect(currentBounds.x).toBeCloseTo(expressionBounds.x, 0);
|
|
expect(currentBounds.width).toBeCloseTo(expressionBounds.width, 0);
|
|
await expression.fill("10");
|
|
await current.fill("2");
|
|
await tool.getByLabel("Libellé", { exact: true }).fill("Parent");
|
|
await expect(tool.locator(".calculator-result strong")).toHaveAttribute("aria-label", "8");
|
|
await tool.getByRole("button", { name: "Enregistrer", exact: true }).click();
|
|
await tool.getByRole("button", { name: "Ajouter un calcul enfant Parent", exact: true }).click();
|
|
await expression.fill("base * 10");
|
|
await subtractCurrent.click();
|
|
await current.fill("20");
|
|
await tool.getByLabel("Libellé", { exact: true }).fill("Child");
|
|
await expect(tool.locator(".calculator-result strong")).toHaveAttribute("aria-label", "60");
|
|
await tool.getByRole("button", { name: "Mettre à jour", exact: true }).click();
|
|
await entry(tool, "Parent").getByTitle("Modifier", { exact: true }).click();
|
|
await expect(current).toHaveValue("2");
|
|
await expression.fill("20");
|
|
await tool.getByRole("button", { name: "Mettre à jour", exact: true }).click();
|
|
await expect(entry(tool, "Child").locator("strong")).toHaveAttribute("aria-label", "160");
|
|
await page.reload();
|
|
await entry(tool, "Child").getByTitle("Modifier", { exact: true }).click();
|
|
await expect(current).toHaveValue("20");
|
|
await expect(tool.locator(".calculator-result strong")).toHaveAttribute("aria-label", "160");
|
|
await subtractCurrent.click();
|
|
await expect(current).toHaveCount(0);
|
|
await expect(tool.locator(".calculator-result-field")).not.toHaveClass(/has-current/);
|
|
await expect(tool.locator(".calculator-result strong")).toHaveAttribute("aria-label", "180");
|
|
});
|
|
|
|
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"]);
|
|
});
|