structure refacto & file documentation
All checks were successful
Deploy Sokko G / deploy (push) Successful in 7s
All checks were successful
Deploy Sokko G / deploy (push) Successful in 7s
This commit is contained in:
parent
d7871736c8
commit
895fec2b40
84 changed files with 2629 additions and 2313 deletions
|
|
@ -1,3 +1,4 @@
|
|||
// Rôle : lance les validations structurelles des données publiques du site.
|
||||
import { readFile } from "node:fs/promises";
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
// Rôle : centralise les règles de validation des JSON éditables du projet.
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
const SNAKE_CASE_RE = /^[a-z0-9]+(?:_[a-z0-9]+)*$/;
|
||||
|
|
@ -102,17 +103,17 @@ export function validateSiteContent(site) {
|
|||
"toolboxes.modules.checklist.incrementLabel",
|
||||
"toolboxes.modules.checklist.currentQuantityLabel",
|
||||
"toolboxes.modules.checklist.deleteTitle",
|
||||
"toolboxes.modules.screenshots.addImages",
|
||||
"toolboxes.modules.screenshots.pastePlaceholder",
|
||||
"toolboxes.modules.screenshots.pasteAriaLabel",
|
||||
"toolboxes.modules.screenshots.imageAlt",
|
||||
"toolboxes.modules.screenshots.labelPlaceholder",
|
||||
"toolboxes.modules.screenshots.labelAriaLabel",
|
||||
"toolboxes.modules.screenshots.previewAriaLabel",
|
||||
"toolboxes.modules.screenshots.annotateAriaLabel",
|
||||
"toolboxes.modules.screenshots.annotateTitle",
|
||||
"toolboxes.modules.screenshots.deleteAriaLabel",
|
||||
"toolboxes.modules.screenshots.deleteTitle",
|
||||
"toolboxes.modules.images.addImages",
|
||||
"toolboxes.modules.images.pastePlaceholder",
|
||||
"toolboxes.modules.images.pasteAriaLabel",
|
||||
"toolboxes.modules.images.imageAlt",
|
||||
"toolboxes.modules.images.labelPlaceholder",
|
||||
"toolboxes.modules.images.labelAriaLabel",
|
||||
"toolboxes.modules.images.previewAriaLabel",
|
||||
"toolboxes.modules.images.annotateAriaLabel",
|
||||
"toolboxes.modules.images.annotateTitle",
|
||||
"toolboxes.modules.images.deleteAriaLabel",
|
||||
"toolboxes.modules.images.deleteTitle",
|
||||
"toolboxes.modules.links.titlePlaceholder",
|
||||
"toolboxes.modules.links.urlPlaceholder",
|
||||
"toolboxes.modules.links.addButton",
|
||||
|
|
|
|||
121
tests/static-app.test.mjs
Normal file
121
tests/static-app.test.mjs
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
// Rôle : vérifie les invariants statiques du shell, du routing et des overlays.
|
||||
import { readFile } from "node:fs/promises";
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
test("vite entrypoint and app shell are wired", async () => {
|
||||
const html = await readFile("website/index.html", "utf8");
|
||||
const source = await readFile("website/src/main.jsx", "utf8");
|
||||
const appDataHook = await readFile("website/src/hooks/useAppData.js", "utf8");
|
||||
const gameFiltersHook = await readFile("website/src/hooks/useGameFilters.js", "utf8");
|
||||
const shell = await readFile("website/src/components/Shell.jsx", "utf8");
|
||||
const overlays = await readFile("website/src/components/AppOverlays.jsx", "utf8");
|
||||
const modals = await readFile("website/src/components/ToolboxModals.jsx", "utf8");
|
||||
const imageViewer = await readFile("website/src/components/ImageViewer.jsx", "utf8");
|
||||
const richText = await readFile("website/src/components/RichText.jsx", "utf8");
|
||||
const homePage = await readFile("website/src/pages/HomePage.jsx", "utf8");
|
||||
const aboutPage = await readFile("website/src/pages/AboutPage.jsx", "utf8");
|
||||
const hashRouter = await readFile("website/src/router/hashRouter.js", "utf8");
|
||||
const routeContent = await readFile("website/src/router/RouteContent.jsx", "utf8");
|
||||
const bodyScrollLock = await readFile("website/src/utils/bodyScrollLock.js", "utf8");
|
||||
|
||||
assert.match(html, /<div id="app"><\/div>/);
|
||||
assert.match(html, /\/favicon\.ico/);
|
||||
assert.match(html, /\/src\/main\.jsx/);
|
||||
assert.match(source, /styles\/main\.scss/);
|
||||
assert.match(source, /components\/Shell\.jsx/);
|
||||
assert.match(source, /components\/AppOverlays\.jsx/);
|
||||
assert.match(source, /router\/RouteContent\.jsx/);
|
||||
assert.match(source, /hooks\/useAppData\.js/);
|
||||
assert.match(source, /hooks\/useGameFilters\.js/);
|
||||
assert.doesNotMatch(source, /DEFAULT_SITE_CONTENT/);
|
||||
assert.match(appDataHook, /export function useAppData/);
|
||||
assert.match(appDataHook, /\/data\/site\.json/);
|
||||
assert.match(appDataHook, /setSiteContentError/);
|
||||
assert.match(gameFiltersHook, /export function useGameFilters/);
|
||||
assert.match(hashRouter, /export function useHashRoute/);
|
||||
assert.match(hashRouter, /export function navigate/);
|
||||
assert.match(routeContent, /export function RouteContent/);
|
||||
assert.match(routeContent, /pages\/HomePage\.jsx/);
|
||||
assert.match(routeContent, /pages\/AboutPage\.jsx/);
|
||||
assert.match(routeContent, /features\/games\/GameRoute\.jsx/);
|
||||
assert.match(shell, /export function Shell/);
|
||||
assert.match(shell, /sidebar-about-link/);
|
||||
assert.match(shell, /ImportButton/);
|
||||
assert.match(overlays, /export function AppOverlays/);
|
||||
assert.match(overlays, /\.\/ToolboxModals\.jsx/);
|
||||
assert.match(overlays, /\.\/ImageViewer\.jsx/);
|
||||
assert.match(overlays, /uid\("marker"\)/);
|
||||
assert.match(modals, /export function ConfirmModal/);
|
||||
assert.match(modals, /export function CreateToolboxModal/);
|
||||
assert.match(modals, /export function LinkToolboxModal/);
|
||||
assert.match(modals, /export function NotificationToast/);
|
||||
assert.match(modals, /useModalScrollLock/);
|
||||
assert.match(imageViewer, /export function ImageViewer/);
|
||||
assert.match(imageViewer, /function openImageInNewTab/);
|
||||
assert.match(richText, /value\.split\("\\n"\)/);
|
||||
assert.match(richText, /<br key=/);
|
||||
assert.match(homePage, /export function HomePage/);
|
||||
assert.match(homePage, /dragon\.png/);
|
||||
assert.match(aboutPage, /export function AboutPage/);
|
||||
assert.match(aboutPage, /module-icon-\$\{tool\.icon \|\| "notepad"\}/);
|
||||
assert.match(bodyScrollLock, /modalLocks/);
|
||||
assert.match(bodyScrollLock, /is-modal-open/);
|
||||
});
|
||||
|
||||
test("project documentation tracks storage and feature updates", async () => {
|
||||
const storageSchema = await readFile("docs/STORAGE_SCHEMA.md", "utf8");
|
||||
const featureChecklist = await readFile("docs/FEATURE_CHECKLIST.md", "utf8");
|
||||
|
||||
assert.match(storageSchema, /IndexedDB/);
|
||||
assert.match(storageSchema, /Outil Checklist/);
|
||||
assert.match(storageSchema, /Outil Images/);
|
||||
assert.match(storageSchema, /Outil Annotation d'images/);
|
||||
assert.match(storageSchema, /Outil Calculateur/);
|
||||
assert.match(featureChecklist, /Mettre à jour `docs\/STORAGE_SCHEMA\.md`/);
|
||||
assert.match(featureChecklist, /npm run check/);
|
||||
});
|
||||
|
||||
test("server and vite support local env configuration", async () => {
|
||||
const server = await readFile("server.mjs", "utf8");
|
||||
const viteConfig = await readFile("vite.config.js", "utf8");
|
||||
const envExample = await readFile(".env.example", "utf8");
|
||||
|
||||
assert.match(server, /function loadEnvFile/);
|
||||
assert.match(server, /process\.env\.PORT/);
|
||||
assert.match(viteConfig, /function loadEnvFile/);
|
||||
assert.match(viteConfig, /process\.env\.PORT/);
|
||||
assert.match(envExample, /PORT=5173/);
|
||||
});
|
||||
|
||||
test("legacy icons and primary images are available", async () => {
|
||||
const manifest = JSON.parse(await readFile("website/public/data/toolbox-icons.json", "utf8"));
|
||||
|
||||
assert.ok(manifest.icons.length >= 4);
|
||||
await readFile("website/public/static/icons/home.svg", "utf8");
|
||||
await readFile("website/public/static/icons/add.svg", "utf8");
|
||||
await readFile("website/public/static/icons/checklist.svg", "utf8");
|
||||
await readFile("website/public/static/icons/close.svg", "utf8");
|
||||
await readFile("website/public/static/icons/columns.svg", "utf8");
|
||||
await readFile("website/public/static/icons/copy.svg", "utf8");
|
||||
await readFile("website/public/static/icons/abacus.svg", "utf8");
|
||||
await readFile("website/public/static/icons/calculator.svg", "utf8");
|
||||
await readFile("website/public/static/icons/map.svg", "utf8");
|
||||
await readFile("website/public/static/icons/enter.svg", "utf8");
|
||||
await readFile("website/public/static/icons/export.svg", "utf8");
|
||||
await readFile("website/public/static/icons/hide.svg", "utf8");
|
||||
await readFile("website/public/static/icons/chevron-down.svg", "utf8");
|
||||
await readFile("website/public/static/icons/chevron-up.svg", "utf8");
|
||||
await readFile("website/public/static/icons/scrollable.svg", "utf8");
|
||||
await readFile("website/public/static/icons/notepad.svg", "utf8");
|
||||
await readFile("website/public/static/icons/picture.svg", "utf8");
|
||||
await readFile("website/public/static/icons/rows.svg", "utf8");
|
||||
await readFile("website/public/static/icons/rubber.svg", "utf8");
|
||||
await readFile("website/public/static/icons/trashcan.svg", "utf8");
|
||||
await readFile("website/public/static/icons/zoom.svg", "utf8");
|
||||
await readFile("website/public/favicon.ico");
|
||||
await readFile("website/public/static/img/dragon.png");
|
||||
await readFile("website/public/static/img/toolbox-icons/toolbox.png");
|
||||
await readFile("website/public/static/img/toolbox-icons/sword.png");
|
||||
await readFile("website/public/static/img/toolbox-icons/puzzle.png");
|
||||
});
|
||||
89
tests/static-games.test.mjs
Normal file
89
tests/static-games.test.mjs
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
// Rôle : vérifie les invariants statiques des pages et données de jeux.
|
||||
import { readFile } from "node:fs/promises";
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
test("generic game routes and shared game components are wired", async () => {
|
||||
const routeContent = await readFile("website/src/router/RouteContent.jsx", "utf8");
|
||||
const gamesPage = await readFile("website/src/features/games/GamesPage.jsx", "utf8");
|
||||
const gameRoute = await readFile("website/src/features/games/GameRoute.jsx", "utf8");
|
||||
const gameLoaders = await readFile("website/src/features/games/loaders.js", "utf8");
|
||||
const gameFiltersPanel = await readFile("website/src/features/games/GameFiltersPanel.jsx", "utf8");
|
||||
const checklistCopyButton = await readFile("website/src/features/games/CopyChecklistItemsButton.jsx", "utf8");
|
||||
const gameListsPage = await readFile("website/src/features/games/GameListsPage.jsx", "utf8");
|
||||
|
||||
assert.match(routeContent, /features\/games\/GamesPage\.jsx/);
|
||||
assert.match(routeContent, /features\/games\/GameRoute\.jsx/);
|
||||
assert.match(gamesPage, /export function GamesPage/);
|
||||
assert.match(gamesPage, /siteContent\.gamesPage/);
|
||||
assert.match(gamesPage, /game-card-cover-link/);
|
||||
assert.match(gamesPage, /game-card-placeholder/);
|
||||
assert.match(gameRoute, /export function GameRoute/);
|
||||
assert.match(gameRoute, /MhwildsPage/);
|
||||
assert.match(gameRoute, /Diablo4Page/);
|
||||
assert.match(gameLoaders, /export async function loadMhwildsData/);
|
||||
assert.match(gameLoaders, /\/data\/mhwilds\/lists\/index\.json/);
|
||||
assert.match(gameLoaders, /loadGameLists/);
|
||||
assert.match(gameLoaders, /normalizeGameListFile/);
|
||||
assert.match(gameLoaders, /export async function loadDiablo4Data/);
|
||||
assert.match(gameLoaders, /\/data\/diablo4\/affixes_types\.json/);
|
||||
assert.match(gameLoaders, /filterOptionKeys/);
|
||||
assert.match(gameFiltersPanel, /export function GameFiltersPanel/);
|
||||
assert.match(gameFiltersPanel, /filter-reset-button/);
|
||||
assert.match(checklistCopyButton, /formatChecklistImportItems/);
|
||||
assert.match(checklistCopyButton, /formatChecklistImportSections/);
|
||||
assert.match(checklistCopyButton, /\$\{entry\.label\}:\$\{entry\.quantity\}/);
|
||||
assert.match(checklistCopyButton, /# \$\{title\}/);
|
||||
assert.match(checklistCopyButton, /navigator\.clipboard\.writeText/);
|
||||
assert.match(checklistCopyButton, /results-copy-button/);
|
||||
assert.match(gameListsPage, /export function GameListsPage/);
|
||||
assert.match(gameListsPage, /game-list-selector/);
|
||||
assert.match(gameListsPage, /game-list-create-button/);
|
||||
assert.match(gameListsPage, /module-icon-checklist/);
|
||||
});
|
||||
|
||||
test("mhwilds and diablo pages expose expected route pieces", async () => {
|
||||
const diablo4Page = await readFile("website/src/features/games/diablo4/Diablo4Page.jsx", "utf8");
|
||||
const diablo4Overview = await readFile("website/src/features/games/diablo4/Diablo4Overview.jsx", "utf8");
|
||||
const diablo4Listing = await readFile("website/src/features/games/diablo4/Diablo4Listing.jsx", "utf8");
|
||||
const diablo4Filters = await readFile("website/src/features/games/diablo4/Diablo4Filters.jsx", "utf8");
|
||||
const diablo4AffixCard = await readFile("website/src/features/games/diablo4/Diablo4AffixCard.jsx", "utf8");
|
||||
const diablo4Utils = await readFile("website/src/features/games/diablo4/utils.js", "utf8");
|
||||
const mhwildsPage = await readFile("website/src/features/games/mhwilds/MhwildsPage.jsx", "utf8");
|
||||
const mhwildsOverview = await readFile("website/src/features/games/mhwilds/MhwildsOverview.jsx", "utf8");
|
||||
const mhwildsListing = await readFile("website/src/features/games/mhwilds/MhwildsListing.jsx", "utf8");
|
||||
const mhwildsLists = await readFile("website/src/features/games/mhwilds/MhwildsLists.jsx", "utf8");
|
||||
const mhwildsFilters = await readFile("website/src/features/games/mhwilds/MhwildsFilters.jsx", "utf8");
|
||||
const monsterCard = await readFile("website/src/features/games/mhwilds/cards/MonsterCard.jsx", "utf8");
|
||||
const endemicCard = await readFile("website/src/features/games/mhwilds/cards/EndemicCard.jsx", "utf8");
|
||||
const damageTable = await readFile("website/src/features/games/mhwilds/cards/DamageTable.jsx", "utf8");
|
||||
|
||||
assert.match(diablo4Page, /export function Diablo4Page/);
|
||||
assert.match(diablo4Overview, /export function Diablo4Overview/);
|
||||
assert.match(diablo4Listing, /export function Diablo4Listing/);
|
||||
assert.match(diablo4Listing, /CopyChecklistItemsButton/);
|
||||
assert.match(diablo4Filters, /export function Diablo4Filters/);
|
||||
assert.match(diablo4Filters, /GameFiltersPanel/);
|
||||
assert.match(diablo4AffixCard, /export function Diablo4AffixCard/);
|
||||
assert.match(diablo4AffixCard, /categoryMap/);
|
||||
assert.match(diablo4Utils, /getFilteredDiablo4Affixes/);
|
||||
assert.match(diablo4Utils, /getCategoryIconStyle/);
|
||||
assert.match(mhwildsPage, /export function MhwildsPage/);
|
||||
assert.match(mhwildsPage, /MhwildsLists/);
|
||||
assert.match(mhwildsPage, /linkedToolboxId/);
|
||||
assert.match(mhwildsOverview, /#\/games\/mhwilds\/lists/);
|
||||
assert.match(mhwildsListing, /export function MhwildsListing/);
|
||||
assert.match(mhwildsListing, /GameBreadcrumb/);
|
||||
assert.match(mhwildsListing, /CopyChecklistItemsButton/);
|
||||
assert.match(mhwildsListing, /endemic_life/);
|
||||
assert.match(mhwildsLists, /export function MhwildsLists/);
|
||||
assert.match(mhwildsLists, /GameListsPage/);
|
||||
assert.match(mhwildsLists, /selectedListId/);
|
||||
assert.match(mhwildsFilters, /export function MhwildsFilters/);
|
||||
assert.match(mhwildsFilters, /GameFiltersPanel/);
|
||||
assert.match(monsterCard, /export function MonsterCard/);
|
||||
assert.match(monsterCard, /ui-icon-flip/);
|
||||
assert.match(endemicCard, /export function EndemicCard/);
|
||||
assert.match(damageTable, /rowIndex/);
|
||||
assert.doesNotMatch(`${mhwildsListing}\n${diablo4Listing}\n${diablo4Overview}`, /mhwilds-(home-grid|home-card|heading|title-row|layout|filters|results|grid)/);
|
||||
});
|
||||
|
|
@ -1,394 +0,0 @@
|
|||
import { readFile } from "node:fs/promises";
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
test("vite entrypoint loads the react application", async () => {
|
||||
const html = await readFile("website/index.html", "utf8");
|
||||
|
||||
assert.match(html, /<div id="app"><\/div>/);
|
||||
assert.match(html, /\/favicon\.ico/);
|
||||
assert.match(html, /\/src\/main\.jsx/);
|
||||
});
|
||||
|
||||
test("project documentation tracks storage and feature updates", async () => {
|
||||
const storageSchema = await readFile("docs/STORAGE_SCHEMA.md", "utf8");
|
||||
const featureChecklist = await readFile("docs/FEATURE_CHECKLIST.md", "utf8");
|
||||
|
||||
assert.match(storageSchema, /IndexedDB/);
|
||||
assert.match(storageSchema, /Outil Checklist/);
|
||||
assert.match(storageSchema, /Outil Images/);
|
||||
assert.match(storageSchema, /Outil Annotation d'images/);
|
||||
assert.match(storageSchema, /Outil Calculateur/);
|
||||
assert.match(featureChecklist, /Mettre à jour `docs\/STORAGE_SCHEMA\.md`/);
|
||||
assert.match(featureChecklist, /npm run check/);
|
||||
});
|
||||
|
||||
test("react application defines the expected local toolbox primitives", async () => {
|
||||
const source = await readFile("website/src/main.jsx", "utf8");
|
||||
const styles = await readFile("website/src/styles/main.scss", "utf8");
|
||||
const styleNebula = await readFile("website/src/styles/_nebula.scss", "utf8");
|
||||
const styleTokens = await readFile("website/src/styles/_tokens.scss", "utf8");
|
||||
const styleBase = await readFile("website/src/styles/_base.scss", "utf8");
|
||||
const styleMixins = await readFile("website/src/styles/_mixins.scss", "utf8");
|
||||
const styleShell = await readFile("website/src/styles/_shell.scss", "utf8");
|
||||
const styleCards = await readFile("website/src/styles/_cards.scss", "utf8");
|
||||
const styleHome = await readFile("website/src/styles/_home.scss", "utf8");
|
||||
const styleToolboxes = await readFile("website/src/styles/_toolboxes.scss", "utf8");
|
||||
const styleOverlays = await readFile("website/src/styles/_overlays.scss", "utf8");
|
||||
const styleIcons = await readFile("website/src/styles/_icons.scss", "utf8");
|
||||
const styleGames = await readFile("website/src/styles/_games.scss", "utf8");
|
||||
const styleMhwilds = await readFile("website/src/styles/_mhwilds.scss", "utf8");
|
||||
const styleResponsive = await readFile("website/src/styles/_responsive.scss", "utf8");
|
||||
const iconComponent = await readFile("website/src/components/Icon.jsx", "utf8");
|
||||
const gamesPage = await readFile("website/src/features/games/GamesPage.jsx", "utf8");
|
||||
const gameRoute = await readFile("website/src/features/games/GameRoute.jsx", "utf8");
|
||||
const checklistCopyButton = await readFile("website/src/features/games/CopyChecklistItemsButton.jsx", "utf8");
|
||||
const gameListsPage = await readFile("website/src/features/games/GameListsPage.jsx", "utf8");
|
||||
const gameLoaders = await readFile("website/src/features/games/loaders.js", "utf8");
|
||||
const gameFiltersPanel = await readFile("website/src/features/games/GameFiltersPanel.jsx", "utf8");
|
||||
const diablo4Page = await readFile("website/src/features/games/diablo4/Diablo4Page.jsx", "utf8");
|
||||
const diablo4Overview = await readFile("website/src/features/games/diablo4/Diablo4Overview.jsx", "utf8");
|
||||
const diablo4Listing = await readFile("website/src/features/games/diablo4/Diablo4Listing.jsx", "utf8");
|
||||
const diablo4Filters = await readFile("website/src/features/games/diablo4/Diablo4Filters.jsx", "utf8");
|
||||
const diablo4AffixCard = await readFile("website/src/features/games/diablo4/Diablo4AffixCard.jsx", "utf8");
|
||||
const diablo4Utils = await readFile("website/src/features/games/diablo4/utils.js", "utf8");
|
||||
const mhwildsPage = await readFile("website/src/features/games/mhwilds/MhwildsPage.jsx", "utf8");
|
||||
const mhwildsOverview = await readFile("website/src/features/games/mhwilds/MhwildsOverview.jsx", "utf8");
|
||||
const mhwildsListing = await readFile("website/src/features/games/mhwilds/MhwildsListing.jsx", "utf8");
|
||||
const mhwildsLists = await readFile("website/src/features/games/mhwilds/MhwildsLists.jsx", "utf8");
|
||||
const mhwildsFilters = await readFile("website/src/features/games/mhwilds/MhwildsFilters.jsx", "utf8");
|
||||
const monsterCard = await readFile("website/src/features/games/mhwilds/cards/MonsterCard.jsx", "utf8");
|
||||
const endemicCard = await readFile("website/src/features/games/mhwilds/cards/EndemicCard.jsx", "utf8");
|
||||
const damageTable = await readFile("website/src/features/games/mhwilds/cards/DamageTable.jsx", "utf8");
|
||||
const moduleRegistry = await readFile("website/src/features/toolboxes/modules/index.jsx", "utf8");
|
||||
const notepadModule = await readFile("website/src/features/toolboxes/modules/NotepadModule.jsx", "utf8");
|
||||
const calculatorModule = await readFile("website/src/features/toolboxes/modules/CalculatorModule.jsx", "utf8");
|
||||
const checklistModule = await readFile("website/src/features/toolboxes/modules/ChecklistModule.jsx", "utf8");
|
||||
const screenshotsModule = await readFile("website/src/features/toolboxes/modules/ScreenshotsModule.jsx", "utf8");
|
||||
const imageAnnotationModule = await readFile("website/src/features/toolboxes/modules/ImageAnnotationModule.jsx", "utf8");
|
||||
const linksModule = await readFile("website/src/features/toolboxes/modules/LinksModule.jsx", "utf8");
|
||||
const textImportModal = await readFile("website/src/features/toolboxes/modules/TextImportModal.jsx", "utf8");
|
||||
const countersModule = await readFile("website/src/features/toolboxes/modules/CountersModule.jsx", "utf8");
|
||||
const textImport = await readFile("website/src/features/toolboxes/modules/textImport.js", "utf8");
|
||||
const reorderHook = await readFile("website/src/hooks/usePointerReorder.js", "utf8");
|
||||
const bodyScrollLock = await readFile("website/src/utils/bodyScrollLock.js", "utf8");
|
||||
const indexedDbStorage = await readFile("website/src/utils/indexedDbStorage.js", "utf8");
|
||||
|
||||
assert.match(source, /indexedDbStorage\.js/);
|
||||
assert.match(indexedDbStorage, /const DB_NAME = "sokkog"/);
|
||||
assert.match(indexedDbStorage, /const KV_STORE = "kv"/);
|
||||
assert.match(indexedDbStorage, /const MODULE_STORE = "modules"/);
|
||||
assert.match(source, /styles\/main\.scss/);
|
||||
assert.match(styles, /@use "tokens"/);
|
||||
assert.match(styles, /@use "nebula"/);
|
||||
assert.match(styles, /@use "toolboxes"/);
|
||||
assert.match(styles, /@use "mhwilds"/);
|
||||
assert.match(styles, /@use "diablo4"/);
|
||||
assert.match(styleTokens, /--gradient-brand/);
|
||||
assert.match(styleBase, /:is\(/);
|
||||
assert.match(styleBase, /\.card-icon-button/);
|
||||
assert.match(styleBase, /\.drawer-action-button/);
|
||||
assert.match(styleNebula, /@function star-field/);
|
||||
assert.match(styleNebula, /body::after/);
|
||||
assert.match(styleBase, /\.import-icon-button/);
|
||||
assert.match(styleHome, /\.dialogue-line i/);
|
||||
assert.match(styleHome, /font-style: italic/);
|
||||
assert.match(styleHome, /\.about-page/);
|
||||
assert.match(styleHome, /\.nebula-panel/);
|
||||
assert.match(styleMixins, /@mixin gold-panel-frame/);
|
||||
assert.match(styleHome, /\.about-story-section/);
|
||||
assert.match(styleHome, /\.about-tools-list/);
|
||||
assert.match(styleHome, /\.about-tool-item \.module-icon/);
|
||||
assert.match(styleShell, /\.sidebar-about-link/);
|
||||
assert.match(styleToolboxes, /\.module-icon-abacus/);
|
||||
assert.match(styleToolboxes, /\.module-icon-calculator/);
|
||||
assert.match(styleToolboxes, /\.calculator-module/);
|
||||
assert.match(styleToolboxes, /\.toolbox-icon-picker/);
|
||||
assert.match(styleToolboxes, /\.toolbox-game-icon/);
|
||||
assert.match(styleToolboxes, /\.toolbox-hero-link/);
|
||||
assert.match(styleToolboxes, /\.toolbox-actions-row/);
|
||||
assert.match(styleToolboxes, /\.text-import-actions/);
|
||||
assert.match(styleIcons, /ui-icon-drag/);
|
||||
assert.match(styleIcons, /ui-icon-dropdown/);
|
||||
assert.match(styleIcons, /ui-icon-enter/);
|
||||
assert.match(styleIcons, /ui-icon-calculator/);
|
||||
assert.match(styleIcons, /ui-icon-scrollable/);
|
||||
assert.match(styleIcons, /ui-icon-hide/);
|
||||
assert.match(styleIcons, /ui-icon-eye-open/);
|
||||
assert.match(styleIcons, /ui-icon-eye-closed/);
|
||||
assert.match(styleIcons, /ui-icon-chevron-down/);
|
||||
assert.match(styleIcons, /ui-icon-chevron-up/);
|
||||
assert.match(styleIcons, /ui-icon-flip/);
|
||||
assert.match(styleIcons, /ui-icon-add/);
|
||||
assert.match(styleMhwilds, /\.mhwilds-card/);
|
||||
assert.match(styleMhwilds, /\.mhwilds-flip-indicator/);
|
||||
assert.match(styleGames, /\.game-home-card/);
|
||||
assert.match(styleGames, /\.game-layout/);
|
||||
assert.match(styleGames, /\.game-grid/);
|
||||
assert.match(styleGames, /\.filter-panel/);
|
||||
assert.doesNotMatch(styleMhwilds, /\.game-(home-card|layout|grid)/);
|
||||
assert.match(styleCards, /compact-data-card/);
|
||||
assert.match(styleResponsive, /@media \(max-width: 760px\)/);
|
||||
assert.match(source, /features\/toolboxes\/modules\/index\.jsx/);
|
||||
assert.match(source, /features\/games\/GamesPage\.jsx/);
|
||||
assert.match(source, /features\/games\/GameRoute\.jsx/);
|
||||
assert.match(iconComponent, /export function Icon/);
|
||||
assert.match(gamesPage, /export function GamesPage/);
|
||||
assert.match(gamesPage, /siteContent\.gamesPage/);
|
||||
assert.match(gamesPage, /game-card-cover-link/);
|
||||
assert.match(gamesPage, /game-card-placeholder/);
|
||||
assert.match(gameRoute, /export function GameRoute/);
|
||||
assert.match(gameRoute, /MhwildsPage/);
|
||||
assert.match(gameRoute, /Diablo4Page/);
|
||||
assert.match(checklistCopyButton, /formatChecklistImportItems/);
|
||||
assert.match(checklistCopyButton, /formatChecklistImportSections/);
|
||||
assert.match(checklistCopyButton, /\$\{entry\.label\}:\$\{entry\.quantity\}/);
|
||||
assert.match(checklistCopyButton, /# \$\{title\}/);
|
||||
assert.match(checklistCopyButton, /navigator\.clipboard\.writeText/);
|
||||
assert.match(checklistCopyButton, /results-copy-button/);
|
||||
assert.match(gameListsPage, /export function GameListsPage/);
|
||||
assert.match(gameListsPage, /game-list-selector/);
|
||||
assert.match(gameListsPage, /game-list-create-button/);
|
||||
assert.match(gameListsPage, /module-icon-checklist/);
|
||||
assert.match(gameLoaders, /export async function loadMhwildsData/);
|
||||
assert.match(gameLoaders, /\/data\/mhwilds\/lists\/index\.json/);
|
||||
assert.match(gameLoaders, /loadGameLists/);
|
||||
assert.match(gameLoaders, /normalizeGameListFile/);
|
||||
assert.match(gameLoaders, /export async function loadDiablo4Data/);
|
||||
assert.match(gameLoaders, /\/data\/diablo4\/affixes_types\.json/);
|
||||
assert.match(gameLoaders, /filterOptionKeys/);
|
||||
assert.match(gameFiltersPanel, /export function GameFiltersPanel/);
|
||||
assert.match(gameFiltersPanel, /filter-reset-button/);
|
||||
assert.match(diablo4Page, /export function Diablo4Page/);
|
||||
assert.match(diablo4Overview, /export function Diablo4Overview/);
|
||||
assert.match(diablo4Listing, /export function Diablo4Listing/);
|
||||
assert.match(diablo4Listing, /CopyChecklistItemsButton/);
|
||||
assert.match(diablo4Filters, /export function Diablo4Filters/);
|
||||
assert.match(diablo4Filters, /GameFiltersPanel/);
|
||||
assert.match(diablo4AffixCard, /export function Diablo4AffixCard/);
|
||||
assert.match(diablo4AffixCard, /categoryMap/);
|
||||
assert.match(diablo4Utils, /getFilteredDiablo4Affixes/);
|
||||
assert.match(diablo4Utils, /getCategoryIconStyle/);
|
||||
assert.match(mhwildsPage, /export function MhwildsPage/);
|
||||
assert.match(mhwildsPage, /MhwildsLists/);
|
||||
assert.match(mhwildsPage, /linkedToolboxId/);
|
||||
assert.match(mhwildsOverview, /#\/games\/mhwilds\/lists/);
|
||||
assert.match(mhwildsListing, /export function MhwildsListing/);
|
||||
assert.match(mhwildsListing, /GameBreadcrumb/);
|
||||
assert.match(mhwildsLists, /export function MhwildsLists/);
|
||||
assert.match(mhwildsLists, /GameListsPage/);
|
||||
assert.match(mhwildsLists, /selectedListId/);
|
||||
assert.match(mhwildsListing, /CopyChecklistItemsButton/);
|
||||
assert.match(mhwildsListing, /endemic_life/);
|
||||
assert.match(mhwildsFilters, /export function MhwildsFilters/);
|
||||
assert.match(mhwildsFilters, /GameFiltersPanel/);
|
||||
assert.match(monsterCard, /export function MonsterCard/);
|
||||
assert.match(monsterCard, /ui-icon-flip/);
|
||||
assert.match(endemicCard, /export function EndemicCard/);
|
||||
assert.match(damageTable, /rowIndex/);
|
||||
assert.match(moduleRegistry, /export const TOOLBOX_MODULES/);
|
||||
assert.match(moduleRegistry, /export function AddToolControls/);
|
||||
assert.match(moduleRegistry, /export function ToolboxModules/);
|
||||
assert.match(moduleRegistry, /MODULE_COMPONENTS/);
|
||||
assert.match(moduleRegistry, /notepad:/);
|
||||
assert.match(moduleRegistry, /checklist:/);
|
||||
assert.match(moduleRegistry, /screenshots:/);
|
||||
assert.match(moduleRegistry, /links:/);
|
||||
assert.match(moduleRegistry, /counters:/);
|
||||
assert.match(moduleRegistry, /calculator:/);
|
||||
assert.match(moduleRegistry, /imageAnnotation:/);
|
||||
assert.match(moduleRegistry, /Annotation d'images/);
|
||||
assert.match(moduleRegistry, /editable: false/);
|
||||
assert.match(moduleRegistry, /module-edit-button/);
|
||||
assert.match(notepadModule, /export function NotepadModule/);
|
||||
assert.match(calculatorModule, /export function CalculatorModule/);
|
||||
assert.match(calculatorModule, /calculateExpression/);
|
||||
assert.match(calculatorModule, /activeParentId/);
|
||||
assert.match(calculatorModule, /parentId/);
|
||||
assert.match(calculatorModule, /scrollResults/);
|
||||
assert.match(calculatorModule, /calculator-scroll-toggle/);
|
||||
assert.match(calculatorModule, /EditableCalculatorLabel/);
|
||||
assert.match(calculatorModule, /calculator-entry-label/);
|
||||
assert.match(calculatorModule, /copyChecklistImport/);
|
||||
assert.match(calculatorModule, /resetCalculator/);
|
||||
assert.match(calculatorModule, /Quantité non modifiable/);
|
||||
assert.doesNotMatch(styleToolboxes, /lecture seule/);
|
||||
assert.match(calculatorModule, /entry\.label \|\| formatResult\(entry\.value\)/);
|
||||
assert.match(calculatorModule, /ResizeObserver/);
|
||||
assert.match(calculatorModule, /--calculator-scroll-height/);
|
||||
assert.match(calculatorModule, /CalculatorEntries/);
|
||||
assert.match(checklistModule, /export function ChecklistModule/);
|
||||
assert.match(checklistModule, /TextImportModal/);
|
||||
assert.match(textImportModal, /createPortal/);
|
||||
assert.match(textImportModal, /lockBodyScroll/);
|
||||
assert.match(checklistModule, /Icon name="import"/);
|
||||
assert.match(styleToolboxes, /\.text-import-modal-dialog/);
|
||||
assert.match(linksModule, /TextImportModal/);
|
||||
assert.match(linksModule, /Icon name="import"/);
|
||||
assert.match(screenshotsModule, /export function ScreenshotsModule/);
|
||||
assert.match(imageAnnotationModule, /export function ImageAnnotationModule/);
|
||||
assert.match(linksModule, /export function LinksModule/);
|
||||
assert.match(countersModule, /export function CountersModule/);
|
||||
assert.match(textImport, /export function parseColonImportLines/);
|
||||
assert.match(textImport, /line\.indexOf\(":\"\)/);
|
||||
assert.match(checklistModule, /editing &&/);
|
||||
assert.match(screenshotsModule, /editing &&/);
|
||||
assert.match(linksModule, /editing &&/);
|
||||
assert.match(countersModule, /editing &&/);
|
||||
assert.match(countersModule, /counter-actions/);
|
||||
assert.match(linksModule, /normalizeUrl/);
|
||||
assert.match(linksModule, /copyText/);
|
||||
assert.doesNotMatch(source, /DEFAULT_SITE_CONTENT/);
|
||||
assert.match(source, /\/data\/site\.json/);
|
||||
assert.match(source, /setSiteContentError/);
|
||||
assert.match(source, /useIndexedToolboxes/);
|
||||
assert.match(source, /getStorageEstimate/);
|
||||
assert.match(source, /DEFAULT_TOOLBOX_ICON/);
|
||||
assert.match(source, /TOOLBOX_ICON_FILES/);
|
||||
assert.match(source, /function normalizeToolboxIcon/);
|
||||
assert.match(source, /function ToolboxIconPicker/);
|
||||
assert.match(source, /function ToolboxGameIcon/);
|
||||
assert.match(source, /updateToolboxOrder/);
|
||||
assert.match(source, /draggingToolboxId/);
|
||||
assert.match(source, /toolbox-card-drag-handle/);
|
||||
assert.match(source, /function StorageQuota/);
|
||||
assert.match(source, /function AboutPage/);
|
||||
assert.match(source, /route === "\/about"/);
|
||||
assert.match(source, /sidebar-about-link/);
|
||||
assert.match(source, /module-icon-\$\{tool\.icon \|\| "notepad"\}/);
|
||||
assert.match(source, /role="progressbar"/);
|
||||
assert.match(source, /function createGlobalExportPayload/);
|
||||
assert.match(source, /async function importAllToolboxes/);
|
||||
assert.match(source, /import-icon-button/);
|
||||
assert.match(source, /function LinkToolboxModal/);
|
||||
assert.doesNotMatch(source, /description: _description/);
|
||||
assert.match(source, /function CreateToolboxModal/);
|
||||
assert.match(source, /const getToolboxGameId/);
|
||||
assert.match(source, /dragon\.png/);
|
||||
assert.match(source, /value\.split\("\\n"\)/);
|
||||
assert.match(source, /<br key=/);
|
||||
assert.match(source, /getToolboxGame\(toolbox\)/);
|
||||
assert.match(source, /Vers la page de jeu/);
|
||||
assert.match(source, /Vers la toolbox complète/);
|
||||
assert.match(source, /#\/games\/\$\{toolboxGame\.id\}/);
|
||||
assert.match(source, /#\/toolbox\/\$\{toolbox\.id\}/);
|
||||
assert.match(source, /setDrawerGameId\(""\)/);
|
||||
assert.match(source, /toolbox-card-cover-link/);
|
||||
assert.match(source, /toolbox-icon-cover/);
|
||||
assert.match(source, /moduleColumns/);
|
||||
assert.match(source, /function ToolboxView/);
|
||||
assert.match(source, /usePointerReorder/);
|
||||
assert.match(moduleRegistry, /onDragStart/);
|
||||
assert.match(moduleRegistry, /onPointerDown/);
|
||||
assert.match(moduleRegistry, /usePointerReorder/);
|
||||
assert.match(reorderHook, /export function usePointerReorder/);
|
||||
assert.match(reorderHook, /setPointerCapture/);
|
||||
assert.match(reorderHook, /elementFromPoint/);
|
||||
assert.match(moduleRegistry, /tool-add-card/);
|
||||
assert.match(moduleRegistry, /tool-quick-add-button/);
|
||||
assert.match(moduleRegistry, /tool-add-quick-toggle/);
|
||||
assert.match(moduleRegistry, /scrollable: true/);
|
||||
assert.match(moduleRegistry, /module-content/);
|
||||
assert.match(moduleRegistry, /module-scroll-button/);
|
||||
assert.match(moduleRegistry, /Icon name="dropdown"/);
|
||||
assert.match(moduleRegistry, /aria-expanded=\{quickOpen\}/);
|
||||
assert.doesNotMatch(source, /<select value="" onChange=\{\(event\) => addModule/);
|
||||
assert.match(source, /qtyTarget/);
|
||||
assert.match(source, /qtyCurrent/);
|
||||
assert.match(source, /hideCompletedSections/);
|
||||
assert.match(source, /hideCompletedSectionsFully/);
|
||||
assert.match(source, /hideWhenComplete/);
|
||||
assert.match(source, /collapsed/);
|
||||
assert.match(source, /module\.scrollable/);
|
||||
assert.match(source, /normalizeLinksData/);
|
||||
assert.match(source, /normalizeCountersData/);
|
||||
assert.match(source, /normalizeCalculatorData/);
|
||||
assert.match(source, /normalizeImageAnnotationData/);
|
||||
assert.match(source, /compactModuleDataForStorage\(type, value\)/);
|
||||
assert.match(source, /scrollResults/);
|
||||
assert.match(checklistModule, /ChecklistItem/);
|
||||
assert.match(checklistModule, /ChecklistSection/);
|
||||
assert.match(checklistModule, /parseChecklistImport/);
|
||||
assert.match(checklistModule, /parseColonImportLines/);
|
||||
assert.match(checklistModule, /startsWith\("#"\)/);
|
||||
assert.match(checklistModule, /chevron-down/);
|
||||
assert.match(checklistModule, /chevron-up/);
|
||||
assert.match(checklistModule, /Number\.parseInt/);
|
||||
assert.match(checklistModule, /checklist-qty-current/);
|
||||
assert.match(checklistModule, /checklist-delete-button danger/);
|
||||
assert.match(linksModule, /parseColonImportLines/);
|
||||
assert.match(linksModule, /context\.normalizeUrl/);
|
||||
assert.match(screenshotsModule, /clipboardData/);
|
||||
assert.match(screenshotsModule, /createImageAnnotationModule/);
|
||||
assert.match(screenshotsModule, /shot-annotate-button/);
|
||||
assert.match(imageAnnotationModule, /annotation-marker/);
|
||||
assert.match(imageAnnotationModule, /setImageFromFiles/);
|
||||
assert.match(imageAnnotationModule, /context\.compressImageFile/);
|
||||
assert.match(imageAnnotationModule, /context\.setScreenshot/);
|
||||
assert.match(imageAnnotationModule, /createMarkerId/);
|
||||
assert.match(source, /uid\("marker"\)/);
|
||||
assert.match(source, /async function addScreenshotFiles/);
|
||||
assert.match(source, /function ScreenshotViewer/);
|
||||
assert.match(source, /useModalScrollLock/);
|
||||
assert.match(bodyScrollLock, /modalLocks/);
|
||||
assert.match(bodyScrollLock, /is-modal-open/);
|
||||
assert.match(moduleRegistry, /lockBodyScroll/);
|
||||
assert.match(source, /screenshot-viewer-media/);
|
||||
assert.match(source, /screenshot-viewer-image-frame/);
|
||||
assert.match(source, /screenshot-viewer-marker/);
|
||||
assert.match(source, /function openImageInNewTab/);
|
||||
assert.match(source, /!hasMarkers &&/);
|
||||
assert.match(source, /<Icon name="zoom"/);
|
||||
assert.match(imageAnnotationModule, /<Icon name="zoom"/);
|
||||
assert.match(styleBase, /themed-scrollbar/);
|
||||
assert.match(styleBase, /body\.is-modal-open/);
|
||||
assert.match(styleOverlays, /overscroll-behavior: contain/);
|
||||
assert.match(source, /annotation-marker-list themed-scrollbar/);
|
||||
assert.match(styleIcons, /ui-icon-map/);
|
||||
assert.match(screenshotsModule, /dataTransfer\.files/);
|
||||
assert.doesNotMatch(`${mhwildsListing}\n${diablo4Listing}\n${diablo4Overview}`, /mhwilds-(home-grid|home-card|heading|title-row|layout|filters|results|grid)/);
|
||||
});
|
||||
|
||||
test("server and vite support local env configuration", async () => {
|
||||
const server = await readFile("server.mjs", "utf8");
|
||||
const viteConfig = await readFile("vite.config.js", "utf8");
|
||||
const envExample = await readFile(".env.example", "utf8");
|
||||
|
||||
assert.match(server, /function loadEnvFile/);
|
||||
assert.match(server, /process\.env\.PORT/);
|
||||
assert.match(viteConfig, /function loadEnvFile/);
|
||||
assert.match(viteConfig, /process\.env\.PORT/);
|
||||
assert.match(envExample, /PORT=5173/);
|
||||
});
|
||||
|
||||
test("legacy svg icons are available for reuse", async () => {
|
||||
const manifest = JSON.parse(await readFile("website/public/data/toolbox-icons.json", "utf8"));
|
||||
|
||||
assert.ok(manifest.icons.length >= 4);
|
||||
await readFile("website/public/static/icons/home.svg", "utf8");
|
||||
await readFile("website/public/static/icons/add.svg", "utf8");
|
||||
await readFile("website/public/static/icons/checklist.svg", "utf8");
|
||||
await readFile("website/public/static/icons/close.svg", "utf8");
|
||||
await readFile("website/public/static/icons/columns.svg", "utf8");
|
||||
await readFile("website/public/static/icons/copy.svg", "utf8");
|
||||
await readFile("website/public/static/icons/abacus.svg", "utf8");
|
||||
await readFile("website/public/static/icons/calculator.svg", "utf8");
|
||||
await readFile("website/public/static/icons/map.svg", "utf8");
|
||||
await readFile("website/public/static/icons/enter.svg", "utf8");
|
||||
await readFile("website/public/static/icons/export.svg", "utf8");
|
||||
await readFile("website/public/static/icons/hide.svg", "utf8");
|
||||
await readFile("website/public/static/icons/chevron-down.svg", "utf8");
|
||||
await readFile("website/public/static/icons/chevron-up.svg", "utf8");
|
||||
await readFile("website/public/static/icons/scrollable.svg", "utf8");
|
||||
await readFile("website/public/static/icons/notepad.svg", "utf8");
|
||||
await readFile("website/public/static/icons/picture.svg", "utf8");
|
||||
await readFile("website/public/static/icons/rows.svg", "utf8");
|
||||
await readFile("website/public/static/icons/rubber.svg", "utf8");
|
||||
await readFile("website/public/static/icons/trashcan.svg", "utf8");
|
||||
await readFile("website/public/static/icons/zoom.svg", "utf8");
|
||||
await readFile("website/public/favicon.ico");
|
||||
await readFile("website/public/static/img/dragon.png");
|
||||
await readFile("website/public/static/img/toolbox-icons/toolbox.png");
|
||||
await readFile("website/public/static/img/toolbox-icons/sword.png");
|
||||
await readFile("website/public/static/img/toolbox-icons/puzzle.png");
|
||||
});
|
||||
78
tests/static-styles.test.mjs
Normal file
78
tests/static-styles.test.mjs
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
// Rôle : vérifie les conventions statiques des styles Sass.
|
||||
import { readFile } from "node:fs/promises";
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
test("style entrypoint and theme layers are wired", async () => {
|
||||
const styles = await readFile("website/src/styles/main.scss", "utf8");
|
||||
const styleNebula = await readFile("website/src/styles/_nebula.scss", "utf8");
|
||||
const styleTokens = await readFile("website/src/styles/_tokens.scss", "utf8");
|
||||
const styleBase = await readFile("website/src/styles/_base.scss", "utf8");
|
||||
const styleMixins = await readFile("website/src/styles/_mixins.scss", "utf8");
|
||||
const styleShell = await readFile("website/src/styles/_shell.scss", "utf8");
|
||||
const styleCards = await readFile("website/src/styles/_cards.scss", "utf8");
|
||||
const styleHome = await readFile("website/src/styles/_home.scss", "utf8");
|
||||
const styleToolboxes = await readFile("website/src/styles/_toolboxes.scss", "utf8");
|
||||
const styleOverlays = await readFile("website/src/styles/_overlays.scss", "utf8");
|
||||
const styleIcons = await readFile("website/src/styles/_icons.scss", "utf8");
|
||||
const styleGames = await readFile("website/src/styles/_games.scss", "utf8");
|
||||
const styleMhwilds = await readFile("website/src/styles/_mhwilds.scss", "utf8");
|
||||
const styleResponsive = await readFile("website/src/styles/_responsive.scss", "utf8");
|
||||
|
||||
assert.match(styles, /@use "tokens"/);
|
||||
assert.match(styles, /@use "nebula"/);
|
||||
assert.match(styles, /@use "toolboxes"/);
|
||||
assert.match(styles, /@use "mhwilds"/);
|
||||
assert.match(styles, /@use "diablo4"/);
|
||||
assert.match(styleTokens, /--gradient-brand/);
|
||||
assert.match(styleBase, /:is\(/);
|
||||
assert.match(styleBase, /\.card-icon-button/);
|
||||
assert.match(styleBase, /\.drawer-action-button/);
|
||||
assert.match(styleBase, /\.import-icon-button/);
|
||||
assert.match(styleBase, /themed-scrollbar/);
|
||||
assert.match(styleBase, /body\.is-modal-open/);
|
||||
assert.match(styleNebula, /@function star-field/);
|
||||
assert.match(styleNebula, /body::after/);
|
||||
assert.match(styleHome, /\.dialogue-line i/);
|
||||
assert.match(styleHome, /font-style: italic/);
|
||||
assert.match(styleHome, /\.about-page/);
|
||||
assert.match(styleHome, /\.nebula-panel/);
|
||||
assert.match(styleHome, /\.about-story-section/);
|
||||
assert.match(styleHome, /\.about-tools-list/);
|
||||
assert.match(styleHome, /\.about-tool-item \.module-icon/);
|
||||
assert.match(styleMixins, /@mixin gold-panel-frame/);
|
||||
assert.match(styleShell, /\.sidebar-about-link/);
|
||||
assert.match(styleToolboxes, /\.module-icon-abacus/);
|
||||
assert.match(styleToolboxes, /\.module-icon-calculator/);
|
||||
assert.match(styleToolboxes, /\.calculator-module/);
|
||||
assert.match(styleToolboxes, /\.toolbox-icon-picker/);
|
||||
assert.match(styleToolboxes, /\.toolbox-game-icon/);
|
||||
assert.match(styleToolboxes, /\.toolbox-hero-link/);
|
||||
assert.match(styleToolboxes, /\.toolbox-actions-row/);
|
||||
assert.match(styleToolboxes, /\.text-import-actions/);
|
||||
assert.match(styleToolboxes, /\.text-import-modal-dialog/);
|
||||
assert.doesNotMatch(styleToolboxes, /lecture seule/);
|
||||
assert.match(styleIcons, /ui-icon-drag/);
|
||||
assert.match(styleIcons, /ui-icon-dropdown/);
|
||||
assert.match(styleIcons, /ui-icon-enter/);
|
||||
assert.match(styleIcons, /ui-icon-calculator/);
|
||||
assert.match(styleIcons, /ui-icon-scrollable/);
|
||||
assert.match(styleIcons, /ui-icon-hide/);
|
||||
assert.match(styleIcons, /ui-icon-eye-open/);
|
||||
assert.match(styleIcons, /ui-icon-eye-closed/);
|
||||
assert.match(styleIcons, /ui-icon-chevron-down/);
|
||||
assert.match(styleIcons, /ui-icon-chevron-up/);
|
||||
assert.match(styleIcons, /ui-icon-flip/);
|
||||
assert.match(styleIcons, /ui-icon-add/);
|
||||
assert.match(styleIcons, /ui-icon-map/);
|
||||
assert.match(styleGames, /\.game-home-card/);
|
||||
assert.match(styleGames, /\.game-layout/);
|
||||
assert.match(styleGames, /\.game-grid/);
|
||||
assert.match(styleGames, /\.filter-panel/);
|
||||
assert.match(styleMhwilds, /\.mhwilds-card/);
|
||||
assert.match(styleMhwilds, /\.mhwilds-flip-indicator/);
|
||||
assert.doesNotMatch(styleMhwilds, /\.game-(home-card|layout|grid)/);
|
||||
assert.match(styleCards, /compact-data-card/);
|
||||
assert.match(styleOverlays, /overscroll-behavior: contain/);
|
||||
assert.match(styleResponsive, /@media \(max-width: 760px\)/);
|
||||
});
|
||||
178
tests/static-toolboxes.test.mjs
Normal file
178
tests/static-toolboxes.test.mjs
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
// Rôle : vérifie les invariants statiques des toolboxes et de leurs outils.
|
||||
import { readFile } from "node:fs/promises";
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
test("toolbox storage, cards and pages are wired", async () => {
|
||||
const source = await readFile("website/src/main.jsx", "utf8");
|
||||
const toolboxCard = await readFile("website/src/features/toolboxes/ToolboxCard.jsx", "utf8");
|
||||
const toolboxPages = await readFile("website/src/features/toolboxes/ToolboxPages.jsx", "utf8");
|
||||
const toolboxActions = await readFile("website/src/features/toolboxes/useToolboxActions.js", "utf8");
|
||||
const toolboxStorage = await readFile("website/src/features/toolboxes/storage/toolboxStorage.js", "utf8");
|
||||
const indexedToolboxesHook = await readFile("website/src/features/toolboxes/storage/useIndexedToolboxes.js", "utf8");
|
||||
const storageQuota = await readFile("website/src/components/StorageQuota.jsx", "utf8");
|
||||
const importButton = await readFile("website/src/components/ImportButton.jsx", "utf8");
|
||||
const reorderHook = await readFile("website/src/hooks/usePointerReorder.js", "utf8");
|
||||
|
||||
assert.match(`${indexedToolboxesHook}\n${toolboxPages}`, /indexedDbStorage\.js/);
|
||||
assert.match(source, /features\/toolboxes\/storage\/useIndexedToolboxes\.js/);
|
||||
assert.match(source, /features\/toolboxes\/useToolboxActions\.js/);
|
||||
assert.match(indexedToolboxesHook, /export function useIndexedToolboxes/);
|
||||
assert.match(indexedToolboxesHook, /getStorageEstimate/);
|
||||
assert.match(toolboxActions, /export function useToolboxActions/);
|
||||
assert.match(toolboxActions, /importAllToolboxesPayload/);
|
||||
assert.match(toolboxActions, /async function addImageFiles/);
|
||||
assert.match(`${source}\n${toolboxActions}`, /features\/toolboxes\/storage\/toolboxStorage\.js/);
|
||||
assert.match(toolboxStorage, /TOOLBOX_ICON_FILES/);
|
||||
assert.match(toolboxStorage, /export function normalizeToolboxIcon/);
|
||||
assert.match(toolboxStorage, /export function createGlobalExportPayload/);
|
||||
assert.match(toolboxStorage, /qtyTarget/);
|
||||
assert.match(toolboxStorage, /qtyCurrent/);
|
||||
assert.match(toolboxStorage, /hideCompletedSections/);
|
||||
assert.match(toolboxStorage, /hideCompletedSectionsFully/);
|
||||
assert.match(toolboxStorage, /hideWhenComplete/);
|
||||
assert.match(toolboxStorage, /collapsed/);
|
||||
assert.match(toolboxStorage, /module\.scrollable/);
|
||||
assert.match(toolboxStorage, /export function normalizeLinksData/);
|
||||
assert.match(toolboxStorage, /export function normalizeCountersData/);
|
||||
assert.match(toolboxStorage, /export function normalizeCalculatorData/);
|
||||
assert.match(toolboxStorage, /export function normalizeImageAnnotationData/);
|
||||
assert.match(toolboxStorage, /export function compactModuleDataForStorage\(type, value\)/);
|
||||
assert.match(toolboxStorage, /scrollResults/);
|
||||
assert.match(toolboxCard, /DEFAULT_TOOLBOX_ICON/);
|
||||
assert.match(toolboxCard, /export function ToolboxCard/);
|
||||
assert.match(toolboxCard, /export function ToolboxIconPicker/);
|
||||
assert.match(toolboxCard, /export function ToolboxGameIcon/);
|
||||
assert.match(toolboxCard, /toolbox-card-drag-handle/);
|
||||
assert.match(toolboxCard, /toolbox-card-cover-link/);
|
||||
assert.match(toolboxCard, /toolbox-icon-cover/);
|
||||
assert.match(toolboxPages, /\.\/ToolboxCard\.jsx/);
|
||||
assert.match(toolboxPages, /updateToolboxOrder/);
|
||||
assert.match(toolboxPages, /draggingToolboxId/);
|
||||
assert.match(toolboxPages, /components\/StorageQuota\.jsx/);
|
||||
assert.match(toolboxPages, /components\/ImportButton\.jsx/);
|
||||
assert.match(toolboxPages, /import-icon-button/);
|
||||
assert.match(toolboxPages, /getToolboxGame\(toolbox\)/);
|
||||
assert.match(toolboxPages, /Vers la page de jeu/);
|
||||
assert.match(toolboxPages, /Vers la toolbox complète/);
|
||||
assert.match(toolboxPages, /#\/games\/\$\{toolboxGame\.id\}/);
|
||||
assert.match(toolboxPages, /#\/toolbox\/\$\{toolbox\.id\}/);
|
||||
assert.match(toolboxPages, /setDrawerGameId\(""\)/);
|
||||
assert.match(toolboxPages, /moduleColumns/);
|
||||
assert.match(toolboxPages, /function ToolboxView/);
|
||||
assert.match(toolboxPages, /usePointerReorder/);
|
||||
assert.match(storageQuota, /export function StorageQuota/);
|
||||
assert.match(storageQuota, /role="progressbar"/);
|
||||
assert.match(importButton, /export function ImportButton/);
|
||||
assert.match(importButton, /accept="application\/json"/);
|
||||
assert.match(reorderHook, /export function usePointerReorder/);
|
||||
assert.match(reorderHook, /setPointerCapture/);
|
||||
assert.match(reorderHook, /elementFromPoint/);
|
||||
});
|
||||
|
||||
test("toolbox module registry and modules expose expected behavior", async () => {
|
||||
const source = await readFile("website/src/main.jsx", "utf8");
|
||||
const moduleRegistry = await readFile("website/src/features/toolboxes/modules/index.jsx", "utf8");
|
||||
const notepadModule = await readFile("website/src/features/toolboxes/modules/NotepadModule.jsx", "utf8");
|
||||
const calculatorModule = await readFile("website/src/features/toolboxes/modules/CalculatorModule.jsx", "utf8");
|
||||
const checklistModule = await readFile("website/src/features/toolboxes/modules/ChecklistModule.jsx", "utf8");
|
||||
const imagesModule = await readFile("website/src/features/toolboxes/modules/ImagesModule.jsx", "utf8");
|
||||
const imageAnnotationModule = await readFile("website/src/features/toolboxes/modules/ImageAnnotationModule.jsx", "utf8");
|
||||
const linksModule = await readFile("website/src/features/toolboxes/modules/LinksModule.jsx", "utf8");
|
||||
const textImportModal = await readFile("website/src/features/toolboxes/modules/TextImportModal.jsx", "utf8");
|
||||
const countersModule = await readFile("website/src/features/toolboxes/modules/CountersModule.jsx", "utf8");
|
||||
const textImport = await readFile("website/src/features/toolboxes/modules/textImport.js", "utf8");
|
||||
const imageViewer = await readFile("website/src/components/ImageViewer.jsx", "utf8");
|
||||
|
||||
assert.match(moduleRegistry, /export const TOOLBOX_MODULES/);
|
||||
assert.match(moduleRegistry, /export function AddToolControls/);
|
||||
assert.match(moduleRegistry, /export function ToolboxModules/);
|
||||
assert.match(moduleRegistry, /MODULE_COMPONENTS/);
|
||||
assert.match(moduleRegistry, /notepad:/);
|
||||
assert.match(moduleRegistry, /checklist:/);
|
||||
assert.match(moduleRegistry, /images:/);
|
||||
assert.match(moduleRegistry, /links:/);
|
||||
assert.match(moduleRegistry, /counters:/);
|
||||
assert.match(moduleRegistry, /calculator:/);
|
||||
assert.match(moduleRegistry, /imageAnnotation:/);
|
||||
assert.match(moduleRegistry, /Annotation d'images/);
|
||||
assert.match(moduleRegistry, /editable: false/);
|
||||
assert.match(moduleRegistry, /module-edit-button/);
|
||||
assert.match(moduleRegistry, /onDragStart/);
|
||||
assert.match(moduleRegistry, /onPointerDown/);
|
||||
assert.match(moduleRegistry, /usePointerReorder/);
|
||||
assert.match(moduleRegistry, /tool-add-card/);
|
||||
assert.match(moduleRegistry, /tool-quick-add-button/);
|
||||
assert.match(moduleRegistry, /tool-add-quick-toggle/);
|
||||
assert.match(moduleRegistry, /scrollable: true/);
|
||||
assert.match(moduleRegistry, /module-content/);
|
||||
assert.match(moduleRegistry, /module-scroll-button/);
|
||||
assert.match(moduleRegistry, /Icon name="dropdown"/);
|
||||
assert.match(moduleRegistry, /aria-expanded=\{quickOpen\}/);
|
||||
assert.doesNotMatch(source, /<select value="" onChange=\{\(event\) => addModule/);
|
||||
assert.match(notepadModule, /export function NotepadModule/);
|
||||
assert.match(calculatorModule, /export function CalculatorModule/);
|
||||
assert.match(calculatorModule, /calculateExpression/);
|
||||
assert.match(calculatorModule, /activeParentId/);
|
||||
assert.match(calculatorModule, /parentId/);
|
||||
assert.match(calculatorModule, /scrollResults/);
|
||||
assert.match(calculatorModule, /calculator-scroll-toggle/);
|
||||
assert.match(calculatorModule, /EditableCalculatorLabel/);
|
||||
assert.match(calculatorModule, /calculator-entry-label/);
|
||||
assert.match(calculatorModule, /copyChecklistImport/);
|
||||
assert.match(calculatorModule, /resetCalculator/);
|
||||
assert.match(calculatorModule, /Quantité non modifiable/);
|
||||
assert.match(calculatorModule, /entry\.label \|\| formatResult\(entry\.value\)/);
|
||||
assert.match(calculatorModule, /ResizeObserver/);
|
||||
assert.match(calculatorModule, /--calculator-scroll-height/);
|
||||
assert.match(calculatorModule, /CalculatorEntries/);
|
||||
assert.match(checklistModule, /export function ChecklistModule/);
|
||||
assert.match(checklistModule, /TextImportModal/);
|
||||
assert.match(checklistModule, /Icon name="import"/);
|
||||
assert.match(checklistModule, /editing &&/);
|
||||
assert.match(checklistModule, /ChecklistItem/);
|
||||
assert.match(checklistModule, /ChecklistSection/);
|
||||
assert.match(checklistModule, /parseChecklistImport/);
|
||||
assert.match(checklistModule, /parseColonImportLines/);
|
||||
assert.match(checklistModule, /startsWith\("#"\)/);
|
||||
assert.match(checklistModule, /chevron-down/);
|
||||
assert.match(checklistModule, /chevron-up/);
|
||||
assert.match(checklistModule, /Number\.parseInt/);
|
||||
assert.match(checklistModule, /checklist-qty-current/);
|
||||
assert.match(checklistModule, /checklist-delete-button danger/);
|
||||
assert.match(textImportModal, /createPortal/);
|
||||
assert.match(textImportModal, /lockBodyScroll/);
|
||||
assert.match(imagesModule, /export function ImagesModule/);
|
||||
assert.match(imagesModule, /editing &&/);
|
||||
assert.match(imagesModule, /clipboardData/);
|
||||
assert.match(imagesModule, /createImageAnnotationModule/);
|
||||
assert.match(imagesModule, /image-annotate-button/);
|
||||
assert.match(imagesModule, /dataTransfer\.files/);
|
||||
assert.match(imageAnnotationModule, /export function ImageAnnotationModule/);
|
||||
assert.match(imageAnnotationModule, /annotation-marker/);
|
||||
assert.match(imageAnnotationModule, /setImageFromFiles/);
|
||||
assert.match(imageAnnotationModule, /context\.compressImageFile/);
|
||||
assert.match(imageAnnotationModule, /context\.setImage/);
|
||||
assert.match(imageAnnotationModule, /createMarkerId/);
|
||||
assert.match(imageAnnotationModule, /<Icon name="zoom"/);
|
||||
assert.match(linksModule, /export function LinksModule/);
|
||||
assert.match(linksModule, /TextImportModal/);
|
||||
assert.match(linksModule, /Icon name="import"/);
|
||||
assert.match(linksModule, /editing &&/);
|
||||
assert.match(linksModule, /normalizeUrl/);
|
||||
assert.match(linksModule, /copyText/);
|
||||
assert.match(linksModule, /parseColonImportLines/);
|
||||
assert.match(linksModule, /context\.normalizeUrl/);
|
||||
assert.match(countersModule, /export function CountersModule/);
|
||||
assert.match(countersModule, /editing &&/);
|
||||
assert.match(countersModule, /counter-actions/);
|
||||
assert.match(textImport, /export function parseColonImportLines/);
|
||||
assert.match(textImport, /line\.indexOf\(":\"\)/);
|
||||
assert.match(imageViewer, /image-viewer-media/);
|
||||
assert.match(imageViewer, /image-viewer-image-frame/);
|
||||
assert.match(imageViewer, /image-viewer-marker/);
|
||||
assert.match(imageViewer, /function openImageInNewTab/);
|
||||
assert.match(imageViewer, /!hasMarkers &&/);
|
||||
assert.match(imageViewer, /<Icon name="zoom"/);
|
||||
assert.match(imageViewer, /annotation-marker-list themed-scrollbar/);
|
||||
});
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
// Rôle : teste les parseurs d'import texte utilisés par les outils toolbox.
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { parseColonImportLines } from "../website/src/features/toolboxes/modules/textImport.js";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue