/* eslint-env node */ import fs from 'node:fs' import path from 'node:path' import { fileURLToPath } from 'node:url' const currentDir = path.dirname(fileURLToPath(import.meta.url)) const pageFile = path.join(currentDir, '..', 'index.vue') const apiFile = path.resolve(currentDir, '../../../../api/steady/steadyDataView/index.ts') const interfaceFile = path.resolve(currentDir, '../../../../api/steady/steadyDataView/interface/index.ts') const componentDir = path.join(currentDir, '..', 'components') const utilsDir = path.join(currentDir, '..', 'utils') const read = file => fs.readFileSync(file, 'utf8') const pageSource = read(pageFile) const apiSource = read(apiFile) const interfaceSource = read(interfaceFile) const componentSource = fs.existsSync(componentDir) ? fs .readdirSync(componentDir) .filter(file => file.endsWith('.vue')) .map(file => read(path.join(componentDir, file))) .join('\n') : '' const utilitySource = fs.existsSync(utilsDir) ? fs .readdirSync(utilsDir) .filter(file => file.endsWith('.ts')) .map(file => read(path.join(utilsDir, file))) .join('\n') : '' const expectations = [ ['page imports extracted trend workbench', /SteadyTrendWorkbench/], ['trend workbench component exists', fs.existsSync(path.join(componentDir, 'SteadyTrendWorkbench.vue'))], ['floating indicator panel component exists', fs.existsSync(path.join(componentDir, 'SteadyIndicatorFloatingPanel.vue'))], ['components import ledger tree panel', /SteadyLedgerTree/], ['components import indicator tree panel', /SteadyIndicatorTree/], ['components import trend toolbar', /SteadyTrendToolbar/], ['components import trend chart panel', /SteadyTrendChartPanel/], ['page does not import trend summary panel', /SteadyTrendSummaryPanel/], ['page does not import data table panel', /SteadyDataTablePanel/], ['components render floating indicator panel', /indicator-floating-panel/], ['page defaults floating indicator panel expanded', /indicatorPanelCollapsed\s*=\s*ref\(false\)/], ['page restores default harmonic order when harmonic filter becomes visible', /DEFAULT_HARMONIC_ORDERS[\s\S]*showHarmonicOrders\.value[\s\S]*trendForm\.value\.harmonicOrders\.length[\s\S]*DEFAULT_HARMONIC_ORDERS/], ['API exposes ledger tree endpoint', /\/steady\/data-view\/ledger-tree/], ['API exposes indicator tree endpoint', /\/steady\/data-view\/indicator-tree/], ['API exposes trend query endpoint', /\/steady\/data-view\/trend\/query/], ['API exposes trend day endpoint', /\/steady\/data-view\/trend\/day/], ['API disables global loading for trend query', /querySteadyTrend[\s\S]*\/steady\/data-view\/trend\/query[\s\S]*loading:\s*false/], ['API disables global loading for trend day query', /querySteadyTrendDay[\s\S]*\/steady\/data-view\/trend\/day[\s\S]*loading:\s*false/], ['API does not expose trend summary endpoint', /\/steady\/data-view\/trend\/summary/], ['interfaces define trend query params', /interface\s+SteadyTrendQueryParams/], ['interfaces define trend series', /interface\s+SteadyTrendSeries/], ['interfaces do not define trend summary', /interface\s+SteadyTrendSummary/], ['components render ledger checkbox tree', /show-checkbox[\s\S]*@check/], ['components render indicator checkbox tree', /indicator-tree[\s\S]*show-checkbox[\s\S]*@check/], ['components reuse LineChart', / { const matched = typeof pattern === 'boolean' ? pattern : pattern.test(sourceByExpectation[index]) return name.includes('does not') || name.includes('do not') ? matched : !matched }) if (failures.length) { console.error('steadyDataView trend contract failed:') for (const [name] of failures) { console.error(`- ${name}`) } process.exit(1) } console.log('steadyDataView trend contract passed')