Files
crawler-plugin/frontend-vue/tests/dead-code-cleanup.test.ts
T
huangzd1997 c81ebb7053 fix(前端测试): 修复 npm test 卡死——定时器泄漏 + 去套娃 + 强制退出/超时
- 根因:polling-backoff-recovery 测试断言失败后跳过 loop.dispose(),残留自续期定时器导致 node --test 子进程永不退出
- dead-code-cleanup:移除套娃用例 test_full_vitest_green(再跑一遍全量套件,放大问题),execSync 加 300s 超时;其余静态断言保留
- package.json:node --test --test-force-exit --test-timeout=180000
- CI workflow 前端测试步骤改为 npm test(与 package.json 单一来源)
- 修正 3 处过时期望值(轮询退避/品牌 files+taskType/巡店 delete_conditions)
- 验证:本地 666 用例全过,19-24s,无残留进程
2026-09-13 10:51:19 +08:00

79 lines
3.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { test } from 'node:test'
import assert from 'node:assert/strict'
import { execSync } from 'node:child_process'
import { readFileSync, existsSync, readdirSync } from 'node:fs'
import { fileURLToPath } from 'node:url'
import { resolve, dirname } from 'node:path'
const here = dirname(fileURLToPath(import.meta.url))
const repoRoot = resolve(here, '..')
/** 子命令一律带超时:卡住时快速失败,不再把整个测试进程树拖死 */
const CHILD_TIMEOUT_MS = 300_000
function run(cmd: string): string {
const env = { ...process.env }
delete env.NODE_TEST_CONTEXT
return execSync(cmd, { cwd: repoRoot, encoding: 'utf-8', env, timeout: CHILD_TIMEOUT_MS })
}
test('test_no_unexported_duplicates', () => {
const source = readFileSync(resolve(repoRoot, 'src/shared/api/java-modules.ts'), 'utf-8')
const lines = source.split('\n').filter((line) => line.includes('export * from'))
const targets = lines
.map((line) => line.match(/export \* from "\.\/([^"]+)"/)?.[1])
.filter(Boolean)
assert.equal(new Set(targets).size, targets.length, '不应有重复的 re-export')
})
test('test_build_typecheck', () => {
const output = run('npx vue-tsc --noEmit')
assert.equal(output.trim(), '', `vue-tsc 应零错误,实际: ${output.slice(0, 500)}`)
})
test('test_no_console_debug_left', () => {
const apiDir = resolve(repoRoot, 'src/shared/api')
for (const file of readdirSync(apiDir, { recursive: true }) as string[]) {
if (!file.endsWith('.ts')) continue
const source = readFileSync(resolve(apiDir, file), 'utf-8')
assert.ok(
!/console\.(log|debug)\(/.test(source),
`${file} 不应残留调试日志`,
)
}
})
test('test_no_unused_import', () => {
const source = readFileSync(resolve(repoRoot, 'src/shared/api/java-modules.ts'), 'utf-8')
// 聚合器除 re-export 外不应有其它 import/函数体
const deadMarkers = [
'function postTaskProgressBatch',
'const taskProgressResponseCache',
'function getCurrentUserId',
'function normalizeTaskIds',
'function buildTaskProgressRequestKey',
'async function uploadTempFileToJava',
'function getJavaDownloadUrl',
]
for (const marker of deadMarkers) {
assert.ok(!source.includes(marker), `java-modules.ts 不应残留: ${marker}`)
}
})
test('test_entry_points_compile', () => {
const viteConfig = readFileSync(resolve(repoRoot, 'vite.config.ts'), 'utf-8')
const entries = [...viteConfig.matchAll(/['"]([^'"]+\.html)['"]/g)].map((m) => m[1])
// SPA2026-09-08):单入口 index.html,页面由 vue-router 渲染
assert.deepEqual(entries, ['index.html'], `应仅 index.html 单入口,实际 ${entries.join(', ')}`)
for (const entry of entries) {
assert.ok(existsSync(resolve(repoRoot, entry)), `入口 ${entry} 应存在`)
}
})
test('test_bundle_build', () => {
const outDir = resolve(repoRoot, 'new_web_source')
assert.ok(existsSync(outDir), '构建产物目录应存在')
assert.ok(existsSync(resolve(outDir, 'index.html')), 'SPA 产物应包含 index.html')
assert.ok(existsSync(resolve(outDir, 'assets')), 'SPA 产物应包含 assets/')
})