Improve compact desktop usability and action guidance
All checks were successful
Deploy Sokko G / deploy (push) Successful in 19s

This commit is contained in:
Shinuwa 2026-10-05 21:47:16 +02:00
parent 0ac1a0974e
commit 0fc18cd8b9
24 changed files with 325 additions and 90 deletions

View file

@ -1,12 +1,14 @@
// Rôle : couvre les parcours navigateur principaux des toolboxes locales.
/* global window, document, navigator, CustomEvent, FileSystemDirectoryHandle */
import { expect, test } from "@playwright/test";
import { readFileSync } from "node:fs";
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");
const site = JSON.parse(readFileSync(path.join(__dirname, "..", "website", "public", "data", "site.json"), "utf8"));
async function collectBrowserErrors(page) {
const errors = [];
@ -63,6 +65,65 @@ test("creates a toolbox and lazy-loads an added tool", async ({ page }) => {
await expect(page.locator("[data-module-type='goalTree']")).toBeVisible();
});
test("add-tool modal explains every tool without overflowing compact desktop widths", async ({ page }) => {
await page.setViewportSize({ width: 1280, height: 720 });
await createToolbox(page, "Catalogue des outils");
await page.getByRole("button", { name: "Ajouter un outil", exact: true }).click();
const dialog = page.getByRole("dialog", { name: "Ajouter un outil", exact: true });
const cards = dialog.locator(".tool-add-card");
const descriptions = Object.entries(site.toolboxes.addToolDescriptions);
await expect(cards).toHaveCount(descriptions.length);
for (const [index, [, description]] of descriptions.entries()) {
await expect(dialog.getByText(description, { exact: true })).toBeVisible();
await expect(cards.nth(index).locator("strong")).not.toHaveCSS("text-overflow", "ellipsis");
}
for (const [width, expectedColumns] of [[768, 4], [960, 5], [1024, 5], [1280, 5]]) {
await page.setViewportSize({ width, height: 720 });
await expect(dialog).toBeVisible();
const layout = await dialog.evaluate((element) => {
const rect = element.getBoundingClientRect();
const grid = element.querySelector(".tool-add-grid");
return {
left: rect.left,
right: rect.right,
height: rect.height,
viewportWidth: window.innerWidth,
viewportHeight: window.innerHeight,
columns: window.getComputedStyle(grid).gridTemplateColumns.split(" ").length,
overflowY: window.getComputedStyle(element).overflowY,
scrollbarColor: window.getComputedStyle(element).scrollbarColor,
scrollbarWidth: window.getComputedStyle(element).scrollbarWidth,
webkitScrollbarWidth: window.getComputedStyle(element, "::-webkit-scrollbar").width,
scrolls: element.scrollHeight > element.clientHeight,
pageFits: document.documentElement.scrollWidth <= window.innerWidth
};
});
expect(layout.left).toBeGreaterThanOrEqual(0);
expect(layout.right).toBeLessThanOrEqual(layout.viewportWidth);
expect(layout.right - layout.left).toBeGreaterThanOrEqual(Math.min(900, width - 32) - 2);
expect(layout.height).toBeLessThanOrEqual(layout.viewportHeight);
expect(layout.columns).toBe(expectedColumns);
expect(layout.overflowY).toBe("auto");
expect(layout.scrollbarColor).toContain("88, 55, 174");
expect(layout.scrollbarWidth).toBe("thin");
expect(layout.webkitScrollbarWidth).toBe("6px");
expect(layout.scrolls).toBe(true);
expect(layout.pageFits).toBe(true);
}
const categorySections = dialog.locator(".tool-add-category-section");
await expect(categorySections).toHaveCount(5);
await expect(categorySections.locator("h3")).toHaveText(Object.values(site.library.categories));
await expect(dialog.locator("[aria-pressed]")).toHaveCount(0);
await dialog.getByRole("button", { name: "Fermer", exact: true }).click();
await page.getByRole("button", { name: "Afficher l'ajout rapide", exact: true }).click();
const quickImage = page.getByRole("button", { name: "Ajouter Images", exact: true });
await quickImage.focus();
await expect(page.getByRole("tooltip", { name: "Images", exact: true })).toBeVisible();
});
test("keeps an uncommitted memo through unrelated app updates and saves multiline text", async ({ page }) => {
await createToolbox(page, "Memo draft toolbox");
const memos = moduleByType(page, "memos");