Files
X-Financial/web/tests/code-size-limits.test.mjs
2026-06-22 11:58:53 +08:00

80 lines
2.0 KiB
JavaScript

import assert from 'node:assert/strict'
import { readdirSync, readFileSync } from 'node:fs'
import { join, relative } from 'node:path'
import test from 'node:test'
const MAX_SOURCE_UNIT_LINES = 800
const REPO_ROOT = new URL('../..', import.meta.url).pathname
const FRONTEND_SOURCE_ROOTS = [
'web/src/components',
'web/src/composables',
'web/src/utils',
'web/src/views',
]
const FRONTEND_EXTENSIONS = new Set(['.html', '.js', '.mjs', '.ts', '.tsx', '.vue'])
function extensionOf(path) {
const index = path.lastIndexOf('.')
return index === -1 ? '' : path.slice(index)
}
function countLines(source) {
return source.length === 0 ? 0 : source.split('\n').length
}
function walkFiles(root, shouldInclude) {
const result = []
const stack = [root]
while (stack.length > 0) {
const current = stack.pop()
const entries = readdirSync(current, { withFileTypes: true })
for (const entry of entries) {
const path = join(current, entry.name)
if (entry.isDirectory()) {
if (!['node_modules', 'dist', 'build', 'coverage'].includes(entry.name)) {
stack.push(path)
}
continue
}
if (shouldInclude(path)) {
result.push(path)
}
}
}
return result
}
function listOversizedFrontendUnits() {
return FRONTEND_SOURCE_ROOTS.flatMap((root) => {
const absoluteRoot = join(REPO_ROOT, root)
return walkFiles(
absoluteRoot,
(path) => FRONTEND_EXTENSIONS.has(extensionOf(path))
)
})
.map((path) => ({
path: relative(REPO_ROOT, path),
lines: countLines(readFileSync(path, 'utf8')),
}))
.filter((item) => item.lines > MAX_SOURCE_UNIT_LINES)
.sort((left, right) => right.lines - left.lines)
}
test('前端核心组件和模块不超过 800 行', () => {
const oversized = listOversizedFrontendUnits()
assert.deepEqual(
oversized,
[],
`以下前端核心源文件超过 ${MAX_SOURCE_UNIT_LINES} 行:\n${
oversized.map((item) => `- ${item.path}: ${item.lines}`).join('\n')
}`
)
})