import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import { createRequire } from "node:module"; import { resolve } from "node:path"; import { fileURLToPath } from "node:url"; const webuiRoot = resolve(fileURLToPath(new URL("..", import.meta.url))); const read = (path) => readFileSync(resolve(webuiRoot, path), "utf8"); const require = createRequire(import.meta.url); const settings = read("src/features/settings/SettingsPage.tsx"); const retention = read("src/features/privacy/RetentionPolicyManagement.tsx"); const confirmDialog = read("src/components/ConfirmDialog.tsx"); const credentials = read("src/components/CredentialEnvelopeManager.tsx"); const passwordField = read("src/components/PasswordField.tsx"); assert.match(passwordField, /lazy\(\(\) => import\("\.\/PasswordGeneratorDialog"\)\)/, "ordinary password fields must not eagerly load optional generator controls or randomness helpers"); assert.doesNotMatch(passwordField, /import PasswordGeneratorDialog from/, "the optional generator has no static import through the password field"); assert.match(passwordField, /generatorOpen && canGenerate &&[\s\S]* 0[\s\S]*optional_module_load_failed/, "an import failure is not silently presented as an uninstalled optional module"); assert.match(application, /function WebModuleLoadFailureNotice[\s\S]*useUnsavedChanges\(\)[\s\S]*requestNavigation\(\(\) => window\.location\.reload\(\)\)/, "module recovery reload uses the shared unsaved-draft navigation guard"); const wysiwygEditor = read("src/components/WysiwygEditor.tsx"); const titlebar = read("src/layout/Titlebar.tsx"); const temporalDataMenu = read("src/layout/TemporalDataMenu.tsx"); const helpMenu = read("src/layout/HelpMenu.tsx"); const helpContext = read("src/utils/helpContext.ts"); const pageLayout = read("src/components/PageLayout.tsx"); const workspaceLayout = read("src/components/WorkspaceLayout.tsx"); const actionToolbar = read("src/components/ActionToolbar.tsx"); const pageActionBar = read("src/components/PageActionBar.tsx"); const workspaceActionBar = read("src/components/WorkspaceActionBar.tsx"); const contentGrid = read("src/components/ContentGrid.tsx"); const formSection = read("src/components/FormSection.tsx"); const dialogAnatomy = read("src/components/DialogAnatomy.tsx"); const adminPageLayout = read("src/components/admin/AdminPageLayout.tsx"); const layoutStyles = read("src/styles/layout.css"); const authGateStyles = read("src/styles/auth-gate.css"); const viteConfig = read("vite.config.ts"); const packageManifest = JSON.parse(read("package.json")); const defaultModulePackages = [...(viteConfig.match(/const defaultWebModulePackages = \[([\s\S]*?)\];/)?.[1] ?? "") .matchAll(/"([^"]+)"/g)].map((match) => match[1]); const declaredModulePackages = Object.keys(packageManifest.dependencies) .filter((name) => name.startsWith("@govoplan/")).sort(); assert.deepEqual([...defaultModulePackages].sort(), declaredModulePackages, "every declared module must be discoverable in the default build, including Tasks; explicit permutations cannot hide an omitted descriptor"); assert.match(viteConfig, /if \(configured === undefined\) return defaultWebModulePackages;/, "only an absent override selects the full default composition"); assert.match(viteConfig, /return configured\.split\(","\)\.map\([\s\S]*?\.filter\(Boolean\)/, "an explicit empty override still supports a core-only build"); assert.match(viteConfig, /return configuredWebModulePackages\(\)\.filter\(packageInstalled\)/, "declared modules remain optional when their package is not installed"); // Component presence alone cannot detect a collection toolbar in a left pane. await import("./test-workspace-collection-actions.mjs"); const listSelectionFilter = read("src/components/ListSelectionFilter.tsx"); const dataGrid = read("src/components/table/DataGrid.tsx"); const multiSelectFilter = read("src/components/MultiSelectFilter.tsx"); assert.match(dataGrid, / match[1]); for (const specifier of [ "@xyflow/react", "read-excel-file/browser", "read-excel-file/universal", "@tiptap/core", "@tiptap/extension-image", "@tiptap/react", "@tiptap/starter-kit" ]) { assert.ok(optimizedVendors.includes(specifier), `${specifier} is prebundled before lazy routes open`); const packageName = specifier.startsWith("@") ? specifier.split("/").slice(0, 2).join("/") : specifier.split("/")[0]; assert.ok(packageManifest.dependencies[packageName] ?? packageManifest.devDependencies[packageName], `${specifier} is a direct dependency of the development shell`); assert.doesNotThrow(() => require.resolve(specifier), `${specifier} has an installed resolvable entry point`); } assert.match(optimization, /exclude:\s*availableWebModuleSpecifiers\(\)/, "optional module packages stay outside dependency prebundling"); assert.ok(!optimizedVendors.some((specifier) => specifier.startsWith("@govoplan/")), "vendor prebundling must not eagerly import optional module packages"); assert.match(settings, /contextId: "core\.settings"/, "settings expose stable contextual documentation"); assert.match(settings, /archetype=\{editorSection \? "editor" : "workspace"\}/, "settings declare editor intent only for draft-owning sections"); assert.match(settings, //, "page action bars keep reload in a named stable slot"); assert.match(pageActionBar, /data-page-action-group="trailing"[\s\S]*/, "Reload belongs to the trailing group beside primary actions"); assert.doesNotMatch(pageActionBar, /data-page-action-group="leading"(?:(?!<\/ToolbarGroup>)[\s\S])*name="reload"/, "module-independent reload placement must not drift back to the leading group"); assert.match(pageActionBar, /data-page-action-separation="destructive"/, "destructive page actions expose a separate semantic group"); assert.match(pageActionBar, /[\s\S]*/, "editor save follows discard in the trailing group"); assert.match(workspaceActionBar, /actionScope=\{scope\}/, "workspace and pane action bars project their semantic scope centrally"); assert.match(workspaceActionBar, /WorkspaceActionBarProps = PageActionBarProps/, "workspace editor panes reuse the page persistence contract"); assert.match(contentGrid, /content-grid-collapse-\$\{collapseAt\}/, "shared grids make their collapse point explicit"); assert.match(formSection, /form-section-header/, "shared form sections own heading and action placement"); assert.match(dialogAnatomy, /dialog-actions-\$\{align\}/, "shared dialog anatomy owns footer action placement"); assert.match(iconRail, /
\s*