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>/); assert.match(html, /\/favicon\.ico/); assert.match(html, /\/src\/main\.jsx/); }); 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 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 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 mhwildsListing = await readFile("website/src/features/games/mhwilds/MhwildsListing.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 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"); assert.match(source, /sokkog:toolboxes/); assert.match(source, /sokkog:game-toolbox-links/); 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(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-form/); 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-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, /\$\{label\}:1/); assert.match(checklistCopyButton, /navigator\.clipboard\.writeText/); assert.match(checklistCopyButton, /results-copy-button/); assert.match(gameLoaders, /export async function loadMhwildsData/); 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(mhwildsListing, /export function MhwildsListing/); 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(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.match(source, /DEFAULT_SITE_CONTENT/); assert.match(source, /\/data\/site\.json/); assert.match(source, /APP_STORAGE_LIMIT_BYTES/); 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 writeStorageValue/); 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, /
addModule/); assert.match(source, /qtyTarget/); assert.match(source, /qtyCurrent/); 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, /parseColonImportLines/); 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, / { 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/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"); });