import { readFileSync } from 'node:fs'; import { resolve } from 'node:path'; import { describe, expect, test } from 'vitest'; import appV2Source from './AppV2.tsx?raw'; import indexSource from '../../index.html?raw'; import mainSource from '../main.tsx?raw'; const v2Styles = readFileSync(resolve(process.cwd(), 'src/v2/styles/v2.css'), 'utf8'); const workspaceStyles = readFileSync(resolve(process.cwd(), 'src/v2/styles/workspace.css'), 'utf8'); const corePageSources = Object.fromEntries(['MonitorPage', 'VehiclePage', 'TrackPage', 'HistoryPage', 'StatisticsPage', 'AlertsPage', 'AccessPage', 'UsersPage', 'OperationsPage'].map((name) => [ name, readFileSync(resolve(process.cwd(), `src/v2/pages/${name}.tsx`), 'utf8') ])); const vehicleSearchSource = readFileSync(resolve(process.cwd(), 'src/v2/pages/VehicleSearchWorkspace.tsx'), 'utf8'); const monitorVehicleDetailSource = readFileSync(resolve(process.cwd(), 'src/v2/pages/MonitorVehicleDetailCard.tsx'), 'utf8'); const reconciliationSource = readFileSync(resolve(process.cwd(), 'src/v2/pages/ReconciliationCenter.tsx'), 'utf8'); const profileSyncPanelSource = readFileSync(resolve(process.cwd(), 'src/v2/pages/VehicleProfileSyncPanel.tsx'), 'utf8'); const sourceEvidenceSource = readFileSync(resolve(process.cwd(), 'src/v2/shared/VehicleSourceEvidencePanel.tsx'), 'utf8'); const mobileFilterToggleSource = readFileSync(resolve(process.cwd(), 'src/v2/shared/MobileFilterToggle.tsx'), 'utf8'); const mobileFilterSheetSource = readFileSync(resolve(process.cwd(), 'src/v2/shared/MobileFilterSheet.tsx'), 'utf8'); const passwordInputSource = readFileSync(resolve(process.cwd(), 'src/v2/shared/PasswordInput.tsx'), 'utf8'); const workspaceFilterPanelSource = readFileSync(resolve(process.cwd(), 'src/v2/shared/WorkspaceFilterPanel.tsx'), 'utf8'); const workspaceMetricRailSource = readFileSync(resolve(process.cwd(), 'src/v2/shared/WorkspaceMetricRail.tsx'), 'utf8'); const workspaceDialogSource = readFileSync(resolve(process.cwd(), 'src/v2/shared/WorkspaceDialog.tsx'), 'utf8'); const workspaceSideSheetSource = readFileSync(resolve(process.cwd(), 'src/v2/shared/WorkspaceSideSheet.tsx'), 'utf8'); const workspaceDetailSideSheetSource = readFileSync(resolve(process.cwd(), 'src/v2/shared/WorkspaceDetailSideSheet.tsx'), 'utf8'); const segmentedTabsSource = readFileSync(resolve(process.cwd(), 'src/v2/shared/SegmentedTabs.tsx'), 'utf8'); const metricActionSource = readFileSync(resolve(process.cwd(), 'src/v2/shared/MetricActionButton.tsx'), 'utf8'); const tablePaginationSource = readFileSync(resolve(process.cwd(), 'src/v2/shared/TablePagination.tsx'), 'utf8'); const vehicleOptionErrorSource = readFileSync(resolve(process.cwd(), 'src/v2/shared/VehicleOptionError.tsx'), 'utf8'); const vehicleCandidateListSource = readFileSync(resolve(process.cwd(), 'src/v2/shared/VehicleCandidateList.tsx'), 'utf8'); const recoveryActionsSource = readFileSync(resolve(process.cwd(), 'src/v2/shared/RecoveryActions.tsx'), 'utf8'); const detailTriggerRowSource = readFileSync(resolve(process.cwd(), 'src/v2/shared/detailTriggerRow.ts'), 'utf8'); const appShellSource = readFileSync(resolve(process.cwd(), 'src/v2/layout/AppShell.tsx'), 'utf8'); const vehicleActionsSource = readFileSync(resolve(process.cwd(), 'src/v2/pages/VehicleActions.tsx'), 'utf8'); const authGateSource = readFileSync(resolve(process.cwd(), 'src/v2/auth/AuthGate.tsx'), 'utf8'); const routeBoundarySource = readFileSync(resolve(process.cwd(), 'src/v2/routing/RouteBoundary.tsx'), 'utf8'); const fleetMapSource = readFileSync(resolve(process.cwd(), 'src/v2/map/FleetMap.tsx'), 'utf8'); const trackMapSource = readFileSync(resolve(process.cwd(), 'src/v2/map/TrackMap.tsx'), 'utf8'); describe('V2 production entry', () => { test('loads the scoped production Semi theme without the retired global stylesheet', () => { expect(mainSource).not.toContain("./styles/global.css"); expect(mainSource).toContain("./v2/styles/semi-theme.scss"); expect(mainSource).toContain("./v2/styles/v2.css"); expect(mainSource).toContain("./v2/styles/workspace.css"); expect(mainSource).toContain("window.history.scrollRestoration = 'manual'"); }); test('renders a static boot shell and recovers when the React entry never becomes ready', () => { expect(indexSource).toContain('id="platform-boot"'); expect(indexSource).toContain('rel="icon" type="image/svg+xml" href="/brand-mark.svg"'); expect(indexSource).toContain('羚牛车辆数据中台'); expect(indexSource).toContain('class="platform-boot-logo" src="/brand-logo.svg"'); expect(indexSource).toContain("window.addEventListener('error', fail, true)"); expect(indexSource).toContain("window.addEventListener('unhandledrejection', fail)"); expect(indexSource).toContain('window.setTimeout(fail, 10_000)'); expect(indexSource).toContain("target.searchParams.set('__reload', String(Date.now()))"); expect(appV2Source).toContain("export const PLATFORM_READY_EVENT = 'vehicle-platform:ready'"); expect(appV2Source).toContain('window.dispatchEvent(new Event(PLATFORM_READY_EVENT))'); }); test('keeps core business pages on shared Semi UI controls and page hierarchy', () => { for (const source of Object.values(corePageSources)) { expect(source).toContain("from '@douyinfe/semi-ui'"); expect(source).toContain(' import('./VehicleSearchWorkspace'))"); expect(vehicleSearchSource).toContain("from '../shared/WorkspaceCommandBar'"); expect(vehicleSearchSource).toContain('} title="未找到车辆"'); expect(corePageSources.VehiclePage).not.toContain('
['); expect(corePageSources.VehiclePage).toContain(' import('./VehicleProfileSyncPanel'))"); expect(vehicleSearchSource).toContain(' import('./MonitorVehicleDetailCard'))"); expect(monitorVehicleDetailSource).toContain('车辆'); expect(sourceEvidenceSource).toContain("import { Button, Card, Empty, Input, Spin, Tag } from '@douyinfe/semi-ui'"); expect(sourceEvidenceSource).toContain('
'); expect(corePageSources.HistoryPage).not.toContain('job) => '); expect(corePageSources.AlertsPage).toContain('className="v2-alert-filter-card"'); expect(corePageSources.AlertsPage).not.toContain('

事件信息

'); expect(corePageSources.AlertsPage).not.toContain('
'); expect(corePageSources.AlertsPage).toContain('车辆'); expect(corePageSources.AccessPage).not.toContain('
'); expect(corePageSources.AccessPage).toContain(''); expect(corePageSources.UsersPage).not.toContain('