e248b6e43a
- SPA 化:22 个 MPA html 入口与 *-main.ts 合并为 index.html + vue-router(URL 无 .html 后缀), 页面跳转全部 router-link,/new_web_source/xxx.html 旧路径归一为 /xxx - 任务面板统一:共享 TaskCenterPanel/TaskItemCard/TaskStatCards/HistoryTaskLayer, 16 个工具页右侧统一为统计卡 + 当前任务 + 历史任务弹层(任务ID/开始/结束/状态必展示) - 历史记录支持单条删除 + 批量勾选删除(确认框/全选/失败提示) - Java 7 模块(dedupe/convert/split/productrisk/shopmatch/pricetrack/deletebrand) history 接口补齐任务时间字段(VO+Service,复用 biz_file_task 列) - 图片工作台/API 层(brand/permission/user)既有未提交改动一并提交
106 lines
3.9 KiB
TypeScript
106 lines
3.9 KiB
TypeScript
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 testsDir = resolve(here)
|
||
|
||
function run(cmd: string): string {
|
||
const env = { ...process.env }
|
||
delete env.NODE_TEST_CONTEXT
|
||
return execSync(cmd, { cwd: repoRoot, encoding: 'utf-8', env })
|
||
}
|
||
|
||
function otherTestFiles(): string[] {
|
||
return readdirSync(testsDir)
|
||
.filter((f) => f.endsWith('.test.ts') && f !== 'dead-code-cleanup.test.ts')
|
||
.map((f) => `tests/${f}`)
|
||
}
|
||
|
||
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_full_vitest_green', () => {
|
||
const output = run(`node --test ${otherTestFiles().join(' ')} 2>&1`)
|
||
assert.match(output, /pass \d+/, '应产出通过统计')
|
||
assert.match(output, /fail 0/, '全量测试应零失败')
|
||
})
|
||
|
||
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])
|
||
// SPA(2026-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/')
|
||
})
|
||
|
||
test('test_git_diff_scope', () => {
|
||
const diff = run('git diff --name-only HEAD~1 HEAD')
|
||
const changed = diff.split('\n').filter(Boolean)
|
||
assert.ok(changed.length > 0, '应检出本次提交的变更')
|
||
const frontendTouched = changed.some((file) => file.startsWith('frontend-vue/'))
|
||
if (!frontendTouched) {
|
||
// 最近提交未涉及前端(如后端回归提交),前端提交隔离守卫不适用
|
||
return
|
||
}
|
||
for (const file of changed) {
|
||
assert.ok(
|
||
file.startsWith('frontend-vue/'),
|
||
`前端提交变更应仅限 frontend-vue 目录,越界: ${file}`,
|
||
)
|
||
}
|
||
})
|