Complete risk-based toolbox regression coverage
All checks were successful
Deploy Sokko G / deploy (push) Successful in 20s

This commit is contained in:
Shinuwa 2026-09-17 23:54:46 +02:00
parent a01f605d55
commit f0797ccf14
5 changed files with 166 additions and 10 deletions

90
e2e/basic-tools.spec.js Normal file
View file

@ -0,0 +1,90 @@
// Rôle : couvre les mutations persistantes des liens, compteurs et checklists.
import { expect, test } from "@playwright/test";
import { Buffer } from "node:buffer";
async function setup(page, type, data) {
await page.goto("/#/toolboxes");
await page.getByText("Importer une toolbox", { exact: true }).locator('input[type="file"]').setInputFiles({
name: "basic.json", mimeType: "application/json",
buffer: Buffer.from(JSON.stringify({
toolbox: { id: "basic", name: "Basic workflows", modules: [{ id: "tool", type, title: "Tool" }] },
modules: { tool: data },
})),
});
await page.getByRole("link", { name: "Ouvrir Basic workflows", exact: true }).first().click();
const tool = page.locator(`[data-module-type="${type}"]`);
await tool.getByRole("button", { name: "Afficher l'ajout de Tool", exact: true }).click();
return tool;
}
test("links persist creation and copying; deleting a category preserves its links", async ({ page, context }) => {
await context.grantPermissions(["clipboard-read", "clipboard-write"]);
const tool = await setup(page, "links", { links: [] });
const form = tool.locator(".links-add-form");
await form.getByPlaceholder("Nom du lien", { exact: true }).fill("Guide");
await form.locator('input[type="url"]').fill("https://example.com/guide");
await form.getByPlaceholder("Catégorie", { exact: true }).fill("Reference");
await form.getByRole("button", { name: "Ajouter", exact: true }).click();
const link = tool.getByRole("link", { name: /Guide/ });
await expect(link).toHaveAttribute("href", "https://example.com/guide");
await expect(link).toHaveAttribute("target", "_blank");
await expect(link).toHaveAttribute("rel", /noreferrer/);
await expect(form.locator('input[type="url"]')).toHaveValue("");
await tool.getByRole("button", { name: "Copier Guide", exact: true }).click();
await expect.poll(() => page.evaluate(() => globalThis.navigator.clipboard.readText())).toBe("https://example.com/guide");
await page.reload();
await expect(link).toHaveAttribute("href", "https://example.com/guide");
await tool.getByRole("button", { name: "Supprimer la catégorie Reference", exact: true }).click();
await expect(tool.getByRole("heading", { name: "Reference", exact: true })).toHaveCount(0);
await page.reload();
await expect(link).toBeVisible();
await tool.getByRole("button", { name: "Supprimer Guide", exact: true }).click();
await page.reload();
await expect(link).toHaveCount(0);
});
test("counters persist signed values and reset without affecting other counters", async ({ page }) => {
const tool = await setup(page, "counters", { counters: [{ id: "other", label: "Other", value: 9 }] });
await tool.getByPlaceholder("Nom du compteur", { exact: true }).fill("Attempts");
await tool.locator(".counters-add-form").getByRole("button", { name: "Ajouter", exact: true }).click();
const item = tool.locator(".counter-item").filter({ has: page.getByRole("button", { name: "Supprimer Attempts", exact: true }) });
await tool.getByRole("button", { name: "Incrémenter Attempts", exact: true }).click();
await expect(item.locator("strong")).toHaveText("1");
await tool.getByRole("button", { name: "Décrémenter Attempts", exact: true }).click({ clickCount: 2 });
await expect(item.locator("strong")).toHaveText("-1");
await page.reload();
await expect(item.locator("strong")).toHaveText("-1");
await tool.getByRole("button", { name: "Réinitialiser Attempts", exact: true }).click();
await page.reload();
await expect(item.locator("strong")).toHaveText("0");
await tool.getByRole("button", { name: "Supprimer Attempts", exact: true }).click();
await page.reload();
await expect(tool.locator(".counter-item")).toHaveCount(1);
await expect(tool.locator(".counter-value strong")).toHaveText("9");
await expect(tool.locator(".counter-value span")).toHaveText("Other");
});
test("checklist quantities are clamped and completed categories hide without losing data", async ({ page }) => {
const tool = await setup(page, "checklist", { sections: [] });
await tool.getByPlaceholder("Catégorie", { exact: true }).fill("Craft");
await tool.getByPlaceholder("Nouvel item", { exact: true }).fill("Ore");
await tool.getByRole("spinbutton", { name: "Quantité cible", exact: true }).fill("3");
await tool.getByRole("button", { name: "Ajouter", exact: true }).click();
const quantity = tool.getByRole("spinbutton", { name: "Quantité actuelle Ore", exact: true });
await tool.getByRole("button", { name: "Ajouter une quantité", exact: true }).click();
await expect(quantity).toHaveValue("1");
await quantity.fill("99");
await expect(quantity).toHaveValue("3");
await tool.getByRole("radio", { name: "Cachée quand terminée", exact: true }).click();
await expect(quantity).toHaveCount(0);
await page.reload();
await expect(tool.getByRole("radio", { name: "Cachée quand terminée", exact: true })).toHaveAttribute("aria-checked", "true");
await tool.getByRole("radio", { name: "Visible quand terminée", exact: true }).click();
await expect(quantity).toHaveValue("3");
await tool.getByRole("button", { name: "Retirer une quantité", exact: true }).click();
await page.reload();
await expect(quantity).toHaveValue("2");
await tool.getByRole("button", { name: "Supprimer Ore", exact: true }).click();
await page.reload();
await expect(quantity).toHaveCount(0);
});

View file

@ -106,3 +106,28 @@ test("recurring resets preserve unique completions and cleanup deletes only comp
await expect(tool.getByRole("checkbox", { name: "Marquer effectué Child", exact: true })).toBeVisible();
await expect(tool.getByRole("checkbox", { name: "Marquer effectué Weekly", exact: true })).toBeVisible();
});
test("reordering a parent moves its subtree and rejects detaching a child", async ({ page }) => {
const tool = await setup(page);
await tool.getByRole("button", { name: "Réglages de la tâche Child", exact: true }).click();
await tool.getByRole("combobox", { name: "Définir un parent", exact: true }).selectOption({ label: "Parent" });
await tool.getByRole("button", { name: "Réglages de la tâche Child", exact: true }).click();
async function drag(source, target) {
await tool.getByRole("button", { name: `Déplacer ${source}`, exact: true }).hover();
await page.mouse.down();
const box = await tool.getByRole("button", { name: `Déplacer ${target}`, exact: true }).boundingBox();
await page.mouse.move(box.x + box.width / 2, box.y + box.height * 0.2, { steps: 5 });
await page.mouse.up();
}
const titles = () => tool.locator(".task-planner-title-input").evaluateAll((inputs) => inputs.map((input) => input.value));
await drag("Weekly", "Parent");
await expect.poll(titles).toEqual(["Weekly", "Parent", "Child"]);
await drag("Parent", "Weekly");
await expect.poll(titles).toEqual(["Parent", "Child", "Weekly"]);
await drag("Child", "Weekly");
await expect.poll(titles).toEqual(["Parent", "Child", "Weekly"]);
await page.reload();
await expect.poll(titles).toEqual(["Parent", "Child", "Weekly"]);
await tool.getByRole("button", { name: "Réglages de la tâche Child", exact: true }).click();
await expect(tool.getByRole("button", { name: "Retirer Parent", exact: true })).toBeVisible();
});