import assert from 'node:assert/strict' import { readFileSync } from 'node:fs' import test from 'node:test' import { fileURLToPath } from 'node:url' const shell = readFileSync( fileURLToPath(new URL('../src/views/AppShellRouteView.vue', import.meta.url)), 'utf8' ) const router = readFileSync(fileURLToPath(new URL('../src/router/index.js', import.meta.url)), 'utf8') const sidebarRail = readFileSync( fileURLToPath(new URL('../src/components/layout/SidebarRail.vue', import.meta.url)), 'utf8' ) const aiSidebarRail = readFileSync( fileURLToPath(new URL('../src/components/layout/AiSidebarRail.vue', import.meta.url)), 'utf8' ) test('app shell lazily loads heavy business views with an in-workarea loading state', () => { assert.match(shell, /defineAsyncRouteView\('audit'\)/) assert.match(shell, /defineAsyncRouteView\('documents'\)/) assert.match(shell, /defineAsyncRouteView\('workbench'\)/) assert.match(shell, /defineAsyncModalView\('travelCreate'\)/) assert.match(shell, /function prefetchAppView\(viewId\)/) assert.match(shell, /@prefetch-view="prefetchAppView"/) assert.doesNotMatch(shell, /import AuditView from '\.\/AuditView\.vue'/) assert.doesNotMatch(shell, /import DigitalEmployeesView from '\.\/DigitalEmployeesView\.vue'/) assert.doesNotMatch(shell, /import EmployeeManagementView from '\.\/EmployeeManagementView\.vue'/) assert.doesNotMatch(shell, /import DocumentsCenterView from '\.\/DocumentsCenterView\.vue'/) assert.doesNotMatch(shell, /import BudgetCenterView from '\.\/BudgetCenterView\.vue'/) }) test('app view preloading is triggered from both standard and AI sidebars', () => { assert.match(sidebarRail, /'prefetch-view'/) assert.match(sidebarRail, /@mouseenter="emit\('prefetch-view', item\.id\)"/) assert.match(sidebarRail, /@focus="emit\('prefetch-view', item\.id\)"/) assert.match(aiSidebarRail, /'prefetch-view'/) assert.match(aiSidebarRail, /@mouseenter="emit\('prefetch-view', item\.id\)"/) assert.match(aiSidebarRail, /@focus="emit\('prefetch-view', item\.id\)"/) }) test('async app view loader keeps transitions nonblocking and visible', () => { const asyncViews = readFileSync( fileURLToPath(new URL('../src/views/scripts/appShellAsyncViews.js', import.meta.url)), 'utf8' ) const loadingState = readFileSync( fileURLToPath(new URL('../src/components/shared/AppViewLoadingState.vue', import.meta.url)), 'utf8' ) const modalLoadingState = readFileSync( fileURLToPath(new URL('../src/components/shared/AppModalLoadingState.vue', import.meta.url)), 'utf8' ) assert.match(asyncViews, /defineAsyncComponent/) assert.match(asyncViews, /loadingComponent:\s*options\.loadingComponent \|\| AppViewLoadingState/) assert.match(asyncViews, /loadingComponent:\s*AppModalLoadingState/) assert.match(asyncViews, /suspensible:\s*false/) assert.match(asyncViews, /requestIdleCallback/) assert.match(loadingState, /正在加载页面内容/) assert.match(loadingState, /app-view-loading-skeleton/) assert.match(modalLoadingState, /Teleport to="body"/) assert.match(modalLoadingState, /正在打开智能工作台/) }) test('top-level shell routes stay eager so the layout does not blank during navigation', () => { assert.doesNotMatch(router, /component:\s*\(\)\s*=>\s*import\(\s*'\.\.\/views\/AppShellRouteView\.vue'/) assert.match(router, /import AppShellRouteView from '\.\.\/views\/AppShellRouteView\.vue'/) assert.match(router, /import LoginRouteView from '\.\.\/views\/LoginRouteView\.vue'/) assert.match(router, /import SetupRouteView from '\.\.\/views\/SetupRouteView\.vue'/) })