Improve toolbox persistence and goal tree coverage
All checks were successful
Deploy Sokko G / deploy (push) Successful in 15s

This commit is contained in:
Shinuwa 2026-08-24 16:11:22 +02:00
parent 50029b45a2
commit 7348969ac4
10 changed files with 801 additions and 591 deletions

View file

@ -0,0 +1,33 @@
{
"toolbox": {
"id": "fixture-toolbox",
"name": "Fixture Toolbox",
"updatedAt": "2026-08-24T10:00:00.000Z",
"modules": [
{
"id": "fixture-note",
"type": "notepad",
"title": "Fixture Notes"
}
],
"moduleColumns": 1,
"moduleOrder": {
"one": [
"fixture-note"
],
"two": [
[
"fixture-note"
],
[]
]
}
},
"modules": {
"fixture-note": {
"html": "<p>Imported fixture note</p>",
"text": "Imported fixture note",
"updatedAt": "2026-08-24T10:00:00.000Z"
}
}
}

30
e2e/helpers/storage.js Normal file
View file

@ -0,0 +1,30 @@
// Rôle : isole les scénarios Playwright en vidant le stockage local Sokko G.
/* global window */
export async function resetSokkoStorage(page) {
await page.goto("/");
await page.evaluate(async () => {
window.localStorage.clear();
window.sessionStorage.clear();
await new Promise((resolve, reject) => {
const request = window.indexedDB.open("sokkog", 1);
request.onupgradeneeded = () => {
const db = request.result;
if (!db.objectStoreNames.contains("kv")) db.createObjectStore("kv");
if (!db.objectStoreNames.contains("modules")) db.createObjectStore("modules", { keyPath: "key" });
};
request.onerror = () => reject(request.error);
request.onsuccess = () => {
const db = request.result;
const transaction = db.transaction(["kv", "modules"], "readwrite");
transaction.objectStore("kv").clear();
transaction.objectStore("modules").clear();
transaction.oncomplete = () => {
db.close();
resolve();
};
transaction.onerror = () => reject(transaction.error);
transaction.onabort = () => reject(transaction.error);
};
});
});
}

65
e2e/toolbox.spec.js Normal file
View file

@ -0,0 +1,65 @@
// Rôle : couvre les parcours navigateur principaux des toolboxes locales.
import { expect, test } from "@playwright/test";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { resetSokkoStorage } from "./helpers/storage.js";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const fixturePath = path.join(__dirname, "fixtures", "toolbox-export.json");
async function createToolbox(page, name) {
await page.goto("/#/toolboxes");
await expect(page.getByRole("main")).toBeVisible();
await page.getByRole("button", { name: "Nouvelle toolbox" }).click();
const dialog = page.getByRole("dialog", { name: "Nouvelle toolbox" });
await expect(dialog).toBeVisible();
await dialog.getByLabel("Nom").fill(name);
await dialog.getByRole("button", { name: "Créer" }).click();
await expect(page.getByRole("heading", { name })).toBeVisible();
}
test.beforeEach(async ({ page }) => {
await resetSokkoStorage(page);
});
test("creates a toolbox and lazy-loads an added tool", async ({ page }) => {
await createToolbox(page, "E2E Toolbox");
await expect(page.getByRole("heading", { name: "E2E Toolbox" })).toBeVisible();
await expect(page.locator("[data-module-type='notepad']")).toBeVisible();
await expect(page.locator("[data-module-type='links']")).toBeVisible();
await page.getByRole("button", { name: "Ajouter un outil", exact: true }).click();
const addDialog = page.getByRole("dialog", { name: "Ajouter un outil" });
await addDialog.getByRole("button", { name: "Arbre d'objectifs" }).click();
await expect(page.locator("[data-module-type='goalTree']")).toBeVisible();
});
test("creates a game-linked toolbox from the drawer", async ({ page }) => {
await page.goto("/#/games/mhwilds");
await expect(page.getByRole("heading", { name: /Monster Hunter.*Wilds/ })).toBeVisible();
await page.getByRole("button", { name: "Associer une toolbox" }).click();
const drawer = page.locator("#toolbox-drawer .drawer-panel");
await expect(drawer).toBeVisible();
await drawer.getByRole("button", { name: "Créer et associer" }).click();
const dialog = page.getByRole("dialog", { name: "Créer et associer une toolbox" });
await expect(dialog.getByLabel("Nom")).toHaveValue(/Monster Hunter.*Wilds/);
await dialog.getByRole("button", { name: "Créer" }).click();
await expect(drawer.getByRole("heading", { name: /Monster Hunter.*Wilds/ })).toBeVisible();
await expect(drawer.locator("[data-module-type='notepad']")).toBeVisible();
await expect(page.getByRole("button", { name: /Ouvrir la toolbox Monster Hunter.*Wilds/ })).toBeVisible();
});
test("imports and exports a toolbox payload", async ({ page }) => {
await page.goto("/#/toolboxes");
await expect(page.getByRole("main")).toBeVisible();
await page.getByText("Importer une toolbox").locator("input[type='file']").setInputFiles(fixturePath);
await expect(page.getByRole("link", { name: "Ouvrir Fixture Toolbox" }).first()).toBeVisible();
const downloadPromise = page.waitForEvent("download");
await page.getByRole("button", { name: "Exporter Fixture Toolbox" }).click();
const download = await downloadPromise;
expect(download.suggestedFilename()).toBe("fixture-toolbox.sokkog.json");
});