Files
CN_Tool_client/frontend/src/views/steady/steadyDataView/contracts/check-trend-contract.mjs

136 lines
6.2 KiB
JavaScript
Raw Normal View History

2026-05-15 16:36:50 +08:00
/* 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')
2026-05-15 16:36:50 +08:00
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/],
2026-05-15 16:36:50 +08:00
['page does not import trend summary panel', /SteadyTrendSummaryPanel/],
['page does not import data table panel', /SteadyDataTablePanel/],
['components render floating indicator panel', /indicator-floating-panel/],
2026-05-15 16:36:50 +08:00
['page defaults floating indicator panel expanded', /indicatorPanelCollapsed\s*=\s*ref\(false\)/],
['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/],
2026-05-15 16:36:50 +08:00
['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', /<LineChart/],
['toolbar uses shared time period search', /TimePeriodSearch/],
['toolbar labels stat quality filters', /toolbar-field__label[\s\S]*统计:[\s\S]*toolbar-field__label[\s\S]*数据:/],
['toolbar does not render bucket selector', /modelValue\.bucket|bucketOptions|粒度:|选择时间粒度/],
['toolbar does not render phase selector', /modelValue\.phases|phaseOptions|resolvePhaseLabel/],
2026-05-15 16:36:50 +08:00
['toolbar labels quality options descriptively', /仅有效数据[\s\S]*仅无效数据/],
['toolbar binds valid quality flag to zero', /<el-option\s+label="仅有效数据"\s+:value="0"\s*\/>/],
['utilities default to valid quality flag zero', /qualityFlag:\s*0/],
2026-05-15 16:36:50 +08:00
['utilities collect selected line ids', /export const collectSelectedLineIds/],
['utilities validate selection limits', /export const validateTrendSelection[\s\S]*24/],
['utilities do not require phase selection', /if\s*\(!phases\.length\)/],
2026-05-15 16:36:50 +08:00
['utilities validate harmonic orders', /export const validateHarmonicOrders[\s\S]*6/],
['utilities build trend query payload', /export const buildSteadyTrendQueryPayload/],
['utilities strip milliseconds from trend query time', /formatSteadyTrendQueryTime[\s\S]*replace\(\s*\/\\\.\[\^.\]\+\$\//],
['utilities do not send bucket in trend query payload', /bucket:\s*formState\.bucket/],
['utilities do not send phases in trend query payload', /phases:\s*formState\.phases/],
['trend query params do not include bucket', /interface\s+SteadyTrendQueryParams\s*{[^}]*bucket\??:\s*string/],
['trend query params do not include phases', /phases:\s*string\[\]/],
2026-05-15 16:36:50 +08:00
['utilities build chart options', /export const buildSteadyTrendChartOptions/]
]
const sourceByExpectation = [
pageSource,
componentSource,
componentSource,
componentSource,
componentSource,
componentSource,
componentSource,
componentSource,
2026-05-15 16:36:50 +08:00
pageSource,
componentSource,
2026-05-15 16:36:50 +08:00
pageSource,
apiSource,
apiSource,
apiSource,
apiSource,
apiSource,
2026-05-15 16:36:50 +08:00
apiSource,
apiSource,
interfaceSource,
interfaceSource,
interfaceSource,
componentSource,
componentSource,
componentSource,
componentSource,
componentSource,
componentSource,
componentSource,
componentSource,
componentSource,
2026-05-15 16:36:50 +08:00
utilitySource,
utilitySource,
utilitySource,
utilitySource,
utilitySource,
utilitySource,
utilitySource,
utilitySource,
utilitySource,
interfaceSource,
interfaceSource,
2026-05-15 16:36:50 +08:00
utilitySource
]
const failures = expectations.filter(([name, pattern], index) => {
const matched = typeof pattern === 'boolean' ? pattern : pattern.test(sourceByExpectation[index])
2026-05-15 16:36:50 +08:00
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')