Improve toolbox ordering and persistence test coverage
All checks were successful
Deploy Sokko G / deploy (push) Successful in 19s
All checks were successful
Deploy Sokko G / deploy (push) Successful in 19s
This commit is contained in:
parent
6bcde57e88
commit
62138120ee
5 changed files with 73 additions and 4 deletions
|
|
@ -44,3 +44,4 @@
|
||||||
{"id":"int-4036248c53312cfaafae4ee37bb145bd","kind":"field_change","created_at":"2026-09-12T21:26:40.724321767Z","actor":"Shinuwa","issue_id":"sokko-g-zsd","extra":{"field":"status","new_value":"open","old_value":"in_progress"}}
|
{"id":"int-4036248c53312cfaafae4ee37bb145bd","kind":"field_change","created_at":"2026-09-12T21:26:40.724321767Z","actor":"Shinuwa","issue_id":"sokko-g-zsd","extra":{"field":"status","new_value":"open","old_value":"in_progress"}}
|
||||||
{"id":"int-37bf322d7d6ae9d06e033d9f16b7f057","kind":"field_change","created_at":"2026-09-12T21:33:50.250082802Z","actor":"Shinuwa","issue_id":"sokko-g-zsd","extra":{"field":"status","new_value":"open","old_value":"in_progress"}}
|
{"id":"int-37bf322d7d6ae9d06e033d9f16b7f057","kind":"field_change","created_at":"2026-09-12T21:33:50.250082802Z","actor":"Shinuwa","issue_id":"sokko-g-zsd","extra":{"field":"status","new_value":"open","old_value":"in_progress"}}
|
||||||
{"id":"int-cc87d51843f7ee62beb6445939aa30d5","kind":"field_change","created_at":"2026-09-13T06:35:52.804580049Z","actor":"Shinuwa","issue_id":"sokko-g-zsd","extra":{"field":"status","new_value":"open","old_value":"in_progress"}}
|
{"id":"int-cc87d51843f7ee62beb6445939aa30d5","kind":"field_change","created_at":"2026-09-13T06:35:52.804580049Z","actor":"Shinuwa","issue_id":"sokko-g-zsd","extra":{"field":"status","new_value":"open","old_value":"in_progress"}}
|
||||||
|
{"id":"int-e554bed2958d709f2965a55fea9aa956","kind":"field_change","created_at":"2026-09-13T06:53:17.211928645Z","actor":"Shinuwa","issue_id":"sokko-g-zsd","extra":{"field":"status","new_value":"open","old_value":"in_progress"}}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ Lire le fichier d'instructions le plus proche du code modifié avant d'interveni
|
||||||
- Ne pas lancer automatiquement un serveur sur `5174` si `5173` répond déjà.
|
- Ne pas lancer automatiquement un serveur sur `5174` si `5173` répond déjà.
|
||||||
- Avant de terminer une modification significative, lancer `npm run check`.
|
- Avant de terminer une modification significative, lancer `npm run check`.
|
||||||
- Quand l'utilisateur indique qu'il va push, traiter le message comme une demande implicite de pré-push check : relire le diff, lancer les validations pertinentes et fournir un message de commit. Ne pas exécuter `git commit`, `git push` ou `git sync` sauf demande explicite.
|
- Quand l'utilisateur indique qu'il va push, traiter le message comme une demande implicite de pré-push check : relire le diff, lancer les validations pertinentes et fournir un message de commit. Ne pas exécuter `git commit`, `git push` ou `git sync` sauf demande explicite.
|
||||||
|
- Proposer les messages de commit sous forme de phrase simple en anglais, sans préfixe Conventional Commits (`fix(...)`, `feat:`, etc.).
|
||||||
|
|
||||||
## Beads
|
## Beads
|
||||||
|
|
||||||
|
|
|
||||||
65
e2e/module-order.spec.js
Normal file
65
e2e/module-order.spec.js
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
// Rôle : vérifie les ordres indépendants une/deux colonnes et leur persistance après déplacement réel.
|
||||||
|
import { test, expect } from "@playwright/test";
|
||||||
|
import { resetSokkoStorage } from "./helpers/storage.js";
|
||||||
|
|
||||||
|
async function setup(page, columns) {
|
||||||
|
await resetSokkoStorage(page);
|
||||||
|
await page.evaluate(async (columns) => {
|
||||||
|
const db = await import("/src/utils/indexedDbStorage.js");
|
||||||
|
await db.setToolboxSnapshot([{
|
||||||
|
id: "order", name: "Ordering", moduleColumns: columns,
|
||||||
|
modules: ["a", "b", "c", "d"].map((id) => ({ id, type: "counters", title: id.toUpperCase() })),
|
||||||
|
moduleOrder: { one: ["a", "b", "c", "d"], two: [["a", "b"], ["c", "d"]] }
|
||||||
|
}], {}, {});
|
||||||
|
}, columns);
|
||||||
|
await page.goto("/#/toolbox/order");
|
||||||
|
await page.reload();
|
||||||
|
await expect(page.locator("article.module")).toHaveCount(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function savedOrder(page) {
|
||||||
|
return page.evaluate(async () => {
|
||||||
|
const db = await import("/src/utils/indexedDbStorage.js");
|
||||||
|
return (await db.getToolboxes())[0].moduleOrder;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function drag(page, title, target, after = false) {
|
||||||
|
await page.getByRole("button", { name: `Déplacer ${title}`, exact: true }).hover();
|
||||||
|
await page.mouse.down();
|
||||||
|
await expect(page.locator("article.module.is-dragging")).toHaveCount(1);
|
||||||
|
await target.scrollIntoViewIfNeeded();
|
||||||
|
const box = await target.boundingBox();
|
||||||
|
await page.mouse.move(box.x + box.width / 2, box.y + box.height * (after ? 0.8 : 0.2), { steps: 5 });
|
||||||
|
await page.mouse.up();
|
||||||
|
await expect(page.locator("article.module.is-dragging")).toHaveCount(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
test("one-column ordering survives reload without changing the two-column order", async ({ page }) => {
|
||||||
|
await setup(page, 1);
|
||||||
|
await drag(page, "C", page.locator('article[data-reorder-item-id="a"]'));
|
||||||
|
const expected = { one: ["c", "a", "b", "d"], two: [["a", "b"], ["c", "d"]] };
|
||||||
|
await expect.poll(() => savedOrder(page)).toEqual(expected);
|
||||||
|
await page.reload();
|
||||||
|
await expect(page.locator(".module-title")).toHaveText(["C", "A", "B", "D"]);
|
||||||
|
await page.getByRole("button", { name: "Afficher en colonnes", exact: true }).click();
|
||||||
|
await expect(page.locator(".module-column").first().locator(".module-title")).toHaveText(["A", "B"]);
|
||||||
|
await expect(page.locator(".module-column").last().locator(".module-title")).toHaveText(["C", "D"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("cross-column drops and empty column boundaries preserve every module and the one-column order", async ({ page }) => {
|
||||||
|
await setup(page, 2);
|
||||||
|
const columns = page.locator(".module-column");
|
||||||
|
await drag(page, "A", page.locator('article[data-reorder-item-id="d"]'), true);
|
||||||
|
await expect.poll(() => savedOrder(page)).toEqual({ one: ["a", "b", "c", "d"], two: [["b"], ["c", "d", "a"]] });
|
||||||
|
await drag(page, "B", columns.last().locator(".module-column-boundary-drop-zone").last(), true);
|
||||||
|
await expect.poll(() => savedOrder(page)).toEqual({ one: ["a", "b", "c", "d"], two: [[], ["c", "d", "a", "b"]] });
|
||||||
|
await drag(page, "A", columns.first().locator(".module-column-boundary-drop-zone").first());
|
||||||
|
const expected = { one: ["a", "b", "c", "d"], two: [["a"], ["c", "d", "b"]] };
|
||||||
|
await expect.poll(() => savedOrder(page)).toEqual(expected);
|
||||||
|
await page.reload();
|
||||||
|
await expect(columns.first().locator(".module-title")).toHaveText(["A"]);
|
||||||
|
await expect(columns.last().locator(".module-title")).toHaveText(["C", "D", "B"]);
|
||||||
|
await page.getByRole("button", { name: "Afficher en lignes", exact: true }).click();
|
||||||
|
await expect(page.locator(".module-title")).toHaveText(["A", "B", "C", "D"]);
|
||||||
|
});
|
||||||
|
|
@ -99,10 +99,6 @@ test("toolbox cards and pages retain their public UI conventions", async () => {
|
||||||
assert.match(storageQuota, /role="progressbar"/);
|
assert.match(storageQuota, /role="progressbar"/);
|
||||||
assert.match(importButton, /export function ImportButton/);
|
assert.match(importButton, /export function ImportButton/);
|
||||||
assert.match(importButton, /accept="application\/json"/);
|
assert.match(importButton, /accept="application\/json"/);
|
||||||
assert.match(groupedReorderHook, /export function useGroupedReorder/);
|
|
||||||
assert.match(groupedReorderHook, /usePointerReorder/);
|
|
||||||
assert.match(groupedReorderHook, /export function getGroupedEntries/);
|
|
||||||
assert.match(groupedReorderHook, /export function applyGroupedReorderOperation/);
|
|
||||||
assert.match(groupedReorderHook, /data-reorder-orientation/);
|
assert.match(groupedReorderHook, /data-reorder-orientation/);
|
||||||
assert.match(groupedReorderHook, /operation\.sourceParentId === operation\.targetParentId/);
|
assert.match(groupedReorderHook, /operation\.sourceParentId === operation\.targetParentId/);
|
||||||
assert.match(toolboxCoverEditor, /image\/webp/);
|
assert.match(toolboxCoverEditor, /image\/webp/);
|
||||||
|
|
|
||||||
|
|
@ -1025,6 +1025,7 @@ test("toolbox export remaps randomizer multi-target exclusions", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("grouped reorder helpers group flat items and complete group order", () => {
|
test("grouped reorder helpers group flat items and complete group order", () => {
|
||||||
|
assert.deepEqual(getGroupedEntries([], { getItemGroup: (item) => item.category }), []);
|
||||||
const items = [
|
const items = [
|
||||||
{ id: "a", category: "" },
|
{ id: "a", category: "" },
|
||||||
{ id: "b", category: "Boss" },
|
{ id: "b", category: "Boss" },
|
||||||
|
|
@ -1086,6 +1087,8 @@ test("grouped reorder operation moves items in and out of categories", () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const original = structuredClone(data);
|
||||||
|
|
||||||
const movedIn = applyGroupedReorderOperation(data, {
|
const movedIn = applyGroupedReorderOperation(data, {
|
||||||
...config,
|
...config,
|
||||||
operation: {
|
operation: {
|
||||||
|
|
@ -1120,6 +1123,9 @@ test("grouped reorder operation moves items in and out of categories", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
assert.deepEqual(movedOut.items.map((item) => `${item.id}:${item.category || ""}`), ["b:Boss", "c:Boss", "a:", "d:Farm"]);
|
assert.deepEqual(movedOut.items.map((item) => `${item.id}:${item.category || ""}`), ["b:Boss", "c:Boss", "a:", "d:Farm"]);
|
||||||
|
assert.deepEqual(data, original);
|
||||||
|
assert.deepEqual(movedIn.items.map((item) => `${item.id}:${item.category || ""}`), ["b:Boss", "c:Boss", "a:Farm", "d:Farm"]);
|
||||||
|
assert.equal(applyGroupedReorderOperation(data, { ...config, operation: { type: "unknown" } }), data);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("grouped reorder operation moves whole categories", () => {
|
test("grouped reorder operation moves whole categories", () => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue