// 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"; import { SOCKET_SHAPES, formatValue, getSocketItemName, setItemCategory } from "../website/src/features/toolboxes/modules/equipmentPlannerOptions.js"; import { applyDueResets, getTaskParentMap, getTaskTreeIds, isTaskResetSoon, moveTask } from "../website/src/features/toolboxes/modules/taskPlannerUtils.js"; import { createInput, getInputLabel, normalizeCustomKey, parseHoldSeconds } from "../website/src/features/toolboxes/modules/combosUtils.js"; import { getBoundsFromStartAndSize, getSelectionBounds, moveSelectionCells, parseTsvBlock, pasteCellBlock } from "../website/src/features/toolboxes/modules/tableUtils.js"; import { canToggleAutoRefresh, getCountdownValidationError, isAlertGuarded } from "../website/src/features/toolboxes/modules/timerOptions.js"; import { getCalendarOccurrences, getCurrentCalendarOccurrence, getMonthEnd, getMonthStart, getNextCalendarAlertTime, getWeekStart } from "../website/src/features/toolboxes/modules/calendarUtils.js"; import { exportModuleText, importModuleText } from "../website/src/features/toolboxes/modules/textImport.js"; import { compactCalendarDataForStorage, normalizeCalendarData } from "../website/src/features/toolboxes/storage/modules/calendar.js"; function countLines(source) { return source.trimEnd().split("\n").length; } 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 storageCompactorRegistry = await readFile("website/src/features/toolboxes/storage/modules/index.js", "utf8"); const checklistStorage = await readFile("website/src/features/toolboxes/storage/modules/checklist.js", "utf8"); const timerStorage = await readFile("website/src/features/toolboxes/storage/modules/timer.js", "utf8"); const calendarStorage = await readFile("website/src/features/toolboxes/storage/modules/calendar.js", "utf8"); const equipmentStorage = await readFile("website/src/features/toolboxes/storage/modules/equipmentPlanner.js", "utf8"); const indexedToolboxesHook = await readFile("website/src/features/toolboxes/storage/useIndexedToolboxes.js", "utf8"); const optimisticModuleData = await readFile("website/src/features/toolboxes/storage/optimisticModuleData.js", "utf8"); const storageQuota = await readFile("website/src/components/StorageQuota.jsx", "utf8"); const importButton = await readFile("website/src/components/ImportButton.jsx", "utf8"); const guidedTooltipTour = await readFile("website/src/components/GuidedTooltipTour.jsx", "utf8"); const reorderHook = await readFile("website/src/hooks/usePointerReorder.js", "utf8"); const groupedReorderHook = await readFile("website/src/hooks/useGroupedReorder.js", "utf8"); const inlineEditHook = await readFile("website/src/hooks/useInlineEdit.js", "utf8"); const draftFormHook = await readFile("website/src/hooks/useDraftForm.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(indexedToolboxesHook, /moduleDataByKey/); assert.match(indexedToolboxesHook, /rollbackModuleDataCheckpoints/); assert.match(optimisticModuleData, /export function createModuleDataCheckpoint/); assert.match(optimisticModuleData, /export function rollbackModuleDataCheckpoints/); assert.match(toolboxActions, /export function useToolboxActions/); assert.match(toolboxActions, /importAllToolboxesPayload/); assert.match(toolboxActions, /async function addImageFiles/); assert.match(toolboxActions, /creationTemplate/); assert.match(toolboxActions, /type: "notepad"/); assert.match(toolboxActions, /type: "links"/); assert.match(toolboxActions, /#\/library/); 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(checklistStorage, /qtyTarget/); assert.match(checklistStorage, /qtyCurrent/); assert.match(checklistStorage, /hideCompletedSections/); assert.match(checklistStorage, /hideCompletedSectionsFully/); assert.match(checklistStorage, /hideWhenComplete/); assert.match(equipmentStorage, /collapsed/); assert.match(toolboxStorage, /module\.scrollable/); assert.match(toolboxStorage, /normalizeLinksData/); assert.match(toolboxStorage, /normalizeCountersData/); assert.match(toolboxStorage, /normalizeCombosData/); assert.match(toolboxStorage, /normalizeCalculatorData/); assert.match(toolboxStorage, /normalizeTableData/); assert.match(toolboxStorage, /normalizeTimerData/); assert.match(toolboxStorage, /normalizeCalendarData/); assert.match(toolboxStorage, /normalizeTaskPlannerData/); assert.match(toolboxStorage, /normalizeGoalTreeData/); assert.match(toolboxStorage, /normalizeEquipmentPlannerData/); assert.match(toolboxStorage, /summarizeEquipmentPlannerData/); assert.match(toolboxStorage, /normalizeImageAnnotationData/); assert.match(toolboxStorage, /export function compactModuleDataForStorage\(type, value\)/); assert.match(storageCompactorRegistry, /export const MODULE_DATA_COMPACTORS/); assert.match(storageCompactorRegistry, /timer: compactTimerDataForStorage/); assert.match(storageCompactorRegistry, /calendar: compactCalendarDataForStorage/); assert.match(storageCompactorRegistry, /goalTree: compactGoalTreeDataForStorage/); assert.match(timerStorage, /scrollResults/); assert.match(calendarStorage, /normalizeCalendarData/); assert.match(toolboxStorage, /nextId\("calendar"\)/); 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, /reorder\.getItemProps/); 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, /useGroupedReorder/); assert.match(toolboxPages, /useInlineEdit/); assert.match(toolboxPages, /getContentEditableProps/); assert.match(toolboxPages, /orientation: "horizontal"/); 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, /normalizeCombosData/); assert.match(toolboxPages, /function ToolboxView/); assert.match(toolboxPages, /GuidedTooltipTour/); assert.match(toolboxPages, /data-toolbox-tutorial-target/); assert.match(guidedTooltipTour, /document\.querySelector/); assert.match(guidedTooltipTour, /--tutorial-arrow-left/); assert.match(guidedTooltipTour, /--tutorial-arrow-top/); assert.match(guidedTooltipTour, /data-placement/); assert.match(toolboxPages, /toolbox\.tutorial === true/); assert.match(toolboxPages, /tutorial: false/); assert.doesNotMatch(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, /elementsFromPoint/); assert.match(reorderHook, /elementFromPoint/); 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, /operation\.sourceParentId === operation\.targetParentId/); assert.match(inlineEditHook, /export function useInlineEdit/); assert.match(inlineEditHook, /skipCommitRef/); assert.match(inlineEditHook, /blurOnEscape/); assert.match(inlineEditHook, /commitOnEnter/); assert.match(inlineEditHook, /getContentEditableProps/); assert.match(draftFormHook, /export function useDraftForm/); assert.match(draftFormHook, /getFieldProps/); assert.match(draftFormHook, /handleSubmit/); assert.match(draftFormHook, /preventDefault/); }); 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 moduleComponents = await readFile("website/src/features/toolboxes/modules/toolboxModuleComponents.jsx", "utf8"); const addToolControls = await readFile("website/src/features/toolboxes/modules/AddToolControls.jsx", "utf8"); const toolboxModules = await readFile("website/src/features/toolboxes/modules/ToolboxModules.jsx", "utf8"); const moduleRegistryBundle = `${moduleRegistry}\n${moduleComponents}\n${addToolControls}\n${toolboxModules}`; const moduleMetadataRegistry = await readFile("website/src/features/toolboxes/toolboxModuleRegistry.js", "utf8"); const notepadModule = await readFile("website/src/features/toolboxes/modules/NotepadModule.jsx", "utf8"); const notepadToolbar = await readFile("website/src/features/toolboxes/modules/NotepadToolbar.jsx", "utf8"); const notepadUtils = await readFile("website/src/features/toolboxes/modules/notepadUtils.js", "utf8"); const combosModule = await readFile("website/src/features/toolboxes/modules/CombosModule.jsx", "utf8"); const combosEditor = await readFile("website/src/features/toolboxes/modules/CombosEditor.jsx", "utf8"); const combosParts = await readFile("website/src/features/toolboxes/modules/CombosParts.jsx", "utf8"); const combosList = await readFile("website/src/features/toolboxes/modules/CombosList.jsx", "utf8"); const combosEditorState = await readFile("website/src/features/toolboxes/modules/useCombosEditorState.js", "utf8"); const combosReorder = await readFile("website/src/features/toolboxes/modules/useCombosReorder.js", "utf8"); const combosBundle = `${combosModule}\n${combosEditor}\n${combosParts}\n${combosList}\n${combosEditorState}\n${combosReorder}`; const combosUtils = await readFile("website/src/features/toolboxes/modules/combosUtils.js", "utf8"); const calculatorModule = await readFile("website/src/features/toolboxes/modules/CalculatorModule.jsx", "utf8"); const calculatorEntries = await readFile("website/src/features/toolboxes/modules/CalculatorEntries.jsx", "utf8"); const calculatorUtils = await readFile("website/src/features/toolboxes/modules/calculatorUtils.js", "utf8"); const calculatorBundle = `${calculatorModule}\n${calculatorEntries}\n${calculatorUtils}`; const tableModule = await readFile("website/src/features/toolboxes/modules/TableModule.jsx", "utf8"); const tableGrid = await readFile("website/src/features/toolboxes/modules/TableGrid.jsx", "utf8"); const tableGridParts = await readFile("website/src/features/toolboxes/modules/TableGridParts.jsx", "utf8"); const tableToolbar = await readFile("website/src/features/toolboxes/modules/TableToolbar.jsx", "utf8"); const tableInteractions = await readFile("website/src/features/toolboxes/modules/useTableInteractions.js", "utf8"); const tableClipboard = await readFile("website/src/features/toolboxes/modules/useTableClipboard.js", "utf8"); const tableBundle = `${tableModule}\n${tableGrid}\n${tableGridParts}\n${tableToolbar}\n${tableInteractions}\n${tableClipboard}`; const tableUtils = await readFile("website/src/features/toolboxes/modules/tableUtils.js", "utf8"); const tableFormulaEngine = await readFile("website/src/features/toolboxes/modules/tableFormulaEngine.js", "utf8"); const timerModule = await readFile("website/src/features/toolboxes/modules/TimerModule.jsx", "utf8"); const timerParts = await readFile("website/src/features/toolboxes/modules/TimerParts.jsx", "utf8"); const timerCountdown = await readFile("website/src/features/toolboxes/modules/TimerCountdown.jsx", "utf8"); const timerSharedControls = await readFile("website/src/features/toolboxes/modules/TimerSharedControls.jsx", "utf8"); const timerStopwatch = await readFile("website/src/features/toolboxes/modules/TimerStopwatch.jsx", "utf8"); const timerBundle = `${timerModule}\n${timerParts}\n${timerCountdown}\n${timerSharedControls}\n${timerStopwatch}`; const timerOptions = await readFile("website/src/features/toolboxes/modules/timerOptions.js", "utf8"); const calendarModule = await readFile("website/src/features/toolboxes/modules/CalendarModule.jsx", "utf8"); const calendarController = await readFile("website/src/features/toolboxes/modules/useCalendarController.js", "utf8"); const calendarDraftControls = await readFile("website/src/features/toolboxes/modules/useCalendarDraftControls.js", "utf8"); const calendarEventActions = await readFile("website/src/features/toolboxes/modules/calendarEventActions.js", "utf8"); const calendarLifecycle = await readFile("website/src/features/toolboxes/modules/useCalendarLifecycle.js", "utf8"); const calendarModeChoice = await readFile("website/src/features/toolboxes/modules/CalendarModeChoice.jsx", "utf8"); const calendarContent = await readFile("website/src/features/toolboxes/modules/CalendarContent.jsx", "utf8"); const calendarDraft = await readFile("website/src/features/toolboxes/modules/calendarDraft.js", "utf8"); const calendarEventForm = await readFile("website/src/features/toolboxes/modules/CalendarEventForm.jsx", "utf8"); const calendarEventControls = await readFile("website/src/features/toolboxes/modules/CalendarEventControls.jsx", "utf8"); const calendarMonthDatePicker = await readFile("website/src/features/toolboxes/modules/CalendarMonthDatePicker.jsx", "utf8"); const calendarViews = await readFile("website/src/features/toolboxes/modules/CalendarViews.jsx", "utf8"); const calendarBundle = `${calendarModule}\n${calendarController}\n${calendarDraftControls}\n${calendarEventActions}\n${calendarLifecycle}\n${calendarModeChoice}\n${calendarContent}\n${calendarDraft}\n${calendarEventForm}\n${calendarEventControls}\n${calendarMonthDatePicker}\n${calendarViews}`; const calendarUtils = await readFile("website/src/features/toolboxes/modules/calendarUtils.js", "utf8"); const taskPlannerModule = await readFile("website/src/features/toolboxes/modules/TaskPlannerModule.jsx", "utf8"); const taskPlannerItems = await readFile("website/src/features/toolboxes/modules/TaskPlannerItems.jsx", "utf8"); const taskPlannerBranch = await readFile("website/src/features/toolboxes/modules/TaskPlannerBranch.jsx", "utf8"); const taskPlannerItem = await readFile("website/src/features/toolboxes/modules/TaskPlannerItem.jsx", "utf8"); const taskPlannerItemPanels = await readFile("website/src/features/toolboxes/modules/TaskPlannerItemPanels.jsx", "utf8"); const taskPlannerReorder = await readFile("website/src/features/toolboxes/modules/useTaskPlannerReorder.js", "utf8"); const taskPlannerTopbar = await readFile("website/src/features/toolboxes/modules/TaskPlannerTopbar.jsx", "utf8"); const taskPlannerSettings = await readFile("website/src/features/toolboxes/modules/TaskPlannerSettings.jsx", "utf8"); const taskPlannerBundle = `${taskPlannerItems}\n${taskPlannerBranch}\n${taskPlannerItem}\n${taskPlannerItemPanels}\n${taskPlannerReorder}\n${taskPlannerTopbar}\n${taskPlannerSettings}`; const taskPlannerUtils = await readFile("website/src/features/toolboxes/modules/taskPlannerUtils.js", "utf8"); const goalTreeModule = await readFile("website/src/features/toolboxes/modules/GoalTreeModule.jsx", "utf8"); const goalTreeEditor = await readFile("website/src/features/toolboxes/modules/GoalTreeEditor.jsx", "utf8"); const goalTreeParts = await readFile("website/src/features/toolboxes/modules/GoalTreeParts.jsx", "utf8"); const goalTreeBranch = await readFile("website/src/features/toolboxes/modules/GoalTreeBranch.jsx", "utf8"); const goalTreeEditorFields = await readFile("website/src/features/toolboxes/modules/GoalTreeEditorFields.jsx", "utf8"); const goalTreeNodeContent = await readFile("website/src/features/toolboxes/modules/GoalTreeNodeContent.jsx", "utf8"); const goalTreeController = await readFile("website/src/features/toolboxes/modules/useGoalTreeController.js", "utf8"); const goalTreeView = await readFile("website/src/features/toolboxes/modules/GoalTreeView.jsx", "utf8"); const goalTreeBundle = `${goalTreeModule}\n${goalTreeEditor}\n${goalTreeParts}\n${goalTreeBranch}\n${goalTreeEditorFields}\n${goalTreeNodeContent}\n${goalTreeController}\n${goalTreeView}`; const goalTreeDisplay = await readFile("website/src/features/toolboxes/modules/goalTreeDisplay.js", "utf8"); const goalTreeUtils = await readFile("website/src/features/toolboxes/modules/goalTreeUtils.js", "utf8"); const equipmentPlannerModule = await readFile("website/src/features/toolboxes/modules/EquipmentPlannerModule.jsx", "utf8"); const equipmentPlannerEditors = await readFile("website/src/features/toolboxes/modules/EquipmentPlannerEditors.jsx", "utf8"); const equipmentPlannerCharacteristics = await readFile("website/src/features/toolboxes/modules/EquipmentPlannerCharacteristics.jsx", "utf8"); const equipmentPlannerMaterials = await readFile("website/src/features/toolboxes/modules/EquipmentPlannerMaterials.jsx", "utf8"); const equipmentPlannerSockets = await readFile("website/src/features/toolboxes/modules/EquipmentPlannerSockets.jsx", "utf8"); const equipmentPlannerBundle = `${equipmentPlannerEditors}\n${equipmentPlannerCharacteristics}\n${equipmentPlannerMaterials}\n${equipmentPlannerSockets}`; const equipmentPlannerItem = await readFile("website/src/features/toolboxes/modules/EquipmentPlannerItem.jsx", "utf8"); const equipmentPlannerPickers = await readFile("website/src/features/toolboxes/modules/EquipmentPlannerPickers.jsx", "utf8"); const equipmentPlannerSummary = await readFile("website/src/features/toolboxes/modules/EquipmentPlannerSummary.jsx", "utf8"); const equipmentPlannerOptions = await readFile("website/src/features/toolboxes/modules/equipmentPlannerOptions.js", "utf8"); const checklistModule = await readFile("website/src/features/toolboxes/modules/ChecklistModule.jsx", "utf8"); const checklistParts = await readFile("website/src/features/toolboxes/modules/ChecklistParts.jsx", "utf8"); const checklistUtils = await readFile("website/src/features/toolboxes/modules/checklistUtils.js", "utf8"); const checklistBundle = `${checklistModule}\n${checklistParts}\n${checklistUtils}`; 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 textExchangeActions = await readFile("website/src/features/toolboxes/modules/TextExchangeActions.jsx", "utf8"); const textExchangeHook = await readFile("website/src/features/toolboxes/modules/useTextExchange.js", "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 textImportShared = await readFile("website/src/features/toolboxes/modules/textImport/shared.js", "utf8"); const textImportPlanning = await readFile("website/src/features/toolboxes/modules/textImport/planning.js", "utf8"); const textImportTime = await readFile("website/src/features/toolboxes/modules/textImport/time.js", "utf8"); const imageViewer = await readFile("website/src/components/ImageViewer.jsx", "utf8"); [ ["CalendarModule.jsx", calendarModule], ["modules/index.jsx", moduleRegistry], ["GoalTreeParts.jsx", goalTreeParts], ["TimerParts.jsx", timerParts], ["TaskPlannerItems.jsx", taskPlannerItems] ].forEach(([fileName, fileSource]) => { assert.ok(countLines(fileSource) <= 220, `${fileName} must remain a short orchestrator/barrel`); }); [ ["AddToolControls.jsx", addToolControls], ["ToolboxModules.jsx", toolboxModules], ["useCalendarController.js", calendarController], ["useCalendarDraftControls.js", calendarDraftControls], ["calendarEventActions.js", calendarEventActions], ["useCalendarLifecycle.js", calendarLifecycle], ["CalendarModeChoice.jsx", calendarModeChoice], ["GoalTreeBranch.jsx", goalTreeBranch], ["GoalTreeEditorFields.jsx", goalTreeEditorFields], ["GoalTreeNodeContent.jsx", goalTreeNodeContent], ["TimerCountdown.jsx", timerCountdown], ["TimerSharedControls.jsx", timerSharedControls], ["TimerStopwatch.jsx", timerStopwatch], ["TaskPlannerBranch.jsx", taskPlannerBranch], ["TaskPlannerItem.jsx", taskPlannerItem] ].forEach(([fileName, fileSource]) => { assert.ok(countLines(fileSource) <= 300, `${fileName} must stay focused; split by responsibility before growing further`); }); assert.match(moduleMetadataRegistry, /export const TOOLBOX_MODULES/); assert.match(moduleMetadataRegistry, /export const TOOLBOX_MODULE_DEFINITIONS/); assert.match(moduleMetadataRegistry, /export function getDefaultModuleTitle/); assert.match(moduleRegistry, /export \{ AddToolControls \}/); assert.match(moduleRegistry, /export \{ ToolboxModules \}/); assert.match(moduleComponents, /MODULE_COMPONENTS/); assert.match(moduleComponents, /lazy\(\(\) => import\("\.\/CombosModule\.jsx"\)/); assert.match(moduleComponents, /lazy\(\(\) => import\("\.\/CalendarModule\.jsx"\)/); assert.match(moduleComponents, /lazy\(\(\) => import\("\.\/GoalTreeModule\.jsx"\)/); assert.match(moduleComponents, /lazy\(\(\) => import\("\.\/EquipmentPlannerModule\.jsx"\)/); assert.match(toolboxModules, /Suspense fallback=\{\}/); assert.match(moduleComponents, /LAZY_MODULE_TYPES/); assert.match(moduleComponents, /notepad:/); assert.match(moduleComponents, /checklist:/); assert.match(moduleComponents, /images:/); assert.match(moduleComponents, /links:/); assert.match(moduleComponents, /counters:/); assert.match(moduleComponents, /combos:/); assert.match(moduleComponents, /CombosModule/); assert.match(moduleComponents, /calculator:/); assert.match(moduleComponents, /table:/); assert.match(moduleComponents, /table: \{ \.\.\.TOOLBOX_MODULE_DEFINITIONS\.table, Component: TableModule \}/); assert.match(moduleComponents, /timer:/); assert.match(moduleComponents, /calendar:/); assert.match(moduleComponents, /taskPlanner:/); assert.match(moduleComponents, /goalTree:/); assert.match(moduleComponents, /equipmentPlanner:/); assert.match(moduleMetadataRegistry, /Planificateur d'équipements/); assert.match(moduleComponents, /imageAnnotation:/); assert.match(moduleMetadataRegistry, /Annotation d'images/); assert.match(moduleComponents, /notepad: \{ \.\.\.TOOLBOX_MODULE_DEFINITIONS\.notepad, Component: NotepadModule \}/); assert.match(toolboxModules, /module-edit-button/); assert.match(toolboxModules, /itemReorder\.startDrag/); assert.match(moduleRegistryBundle, /onPointerDown/); assert.match(toolboxModules, /useGroupedReorder/); assert.match(toolboxModules, /useInlineEdit/); assert.match(toolboxModules, /getContentEditableProps/); assert.match(addToolControls, /tool-add-card/); assert.match(addToolControls, /tool-quick-add-button/); assert.match(addToolControls, /tool-add-quick-toggle/); assert.match(moduleMetadataRegistry, /scrollable: true/); assert.match(toolboxModules, /module-content/); assert.match(toolboxModules, /module-scroll-button/); assert.match(addToolControls, /Icon name="dropdown"/); assert.match(addToolControls, /CompactDropdown/); assert.doesNotMatch(source, /