import { test } from 'node:test' import assert from 'node:assert/strict' import fs from 'node:fs' import path from 'node:path' import { fileURLToPath } from 'node:url' /** task-216:CI 接入测试阶段契约。.gitea/workflows/build.yml 含 Java 测试与前端测试,失败即红。 */ const YML = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..', '.gitea', 'workflows', 'build.yml') function text(): string { return fs.readFileSync(YML, 'utf8') } test('CI 工作流存在', () => { assert.ok(fs.existsSync(YML), 'build.yml 应存在') }) test('含 Java 测试阶段(mvn test 跑单元+契约+ArchUnit)', () => { const t = text() assert.ok(/Test \(Java: unit \+ contract \+ ArchUnit\)/.test(t), t) assert.ok(/mvn test/.test(t), t) assert.ok(!/mvn clean package -DskipTests.*\n\s*run: mvn test/.test(t), '测试应先于打包') }) test('测试在打包之前执行(失败即红,阻断产物上传)', () => { const t = text() const testIdx = t.indexOf('mvn test') const packageIdx = t.indexOf('mvn clean package -DskipTests') assert.ok(testIdx !== -1 && packageIdx !== -1 && testIdx < packageIdx, 'mvn test 必须先于 package') }) test('含前端测试 job(node --test 契约测试)', () => { const t = text() assert.ok(/frontend-test/.test(t), t) assert.ok(/node --test tests\/\*\.test\.ts/.test(t), t) assert.ok(/npm ci/.test(t), t) }) test('前端含类型检查(vue-tsc)', () => { const t = text() assert.ok(/npm run build/.test(t), '应执行 npm run build(vue-tsc + vite)') }) test('有超时与容器环境配置', () => { const t = text() assert.ok(/timeout-minutes:\s*\d+/.test(t), '应有超时配置') assert.ok(/maven:3\.9-eclipse-temurin-21/.test(t), 'Java 容器应存在') assert.ok(/node:24-alpine/.test(t), '前端容器应存在') }) test('产物上传保留且路径指向 backend-java', () => { const t = text() assert.ok(/backend-java\/target\/\*\.jar/.test(t), 'jar 产物路径应对') assert.ok(/Upload artifact/.test(t)) }) test('可重复、内容稳定(两次读取一致)', () => { assert.equal(text(), text()) })