Files
baiyue-firstleg/scripts/java-quality-summary.test.mjs
T
2026-10-08 17:07:57 +08:00

98 lines
6.3 KiB
JavaScript

import assert from 'node:assert/strict'
import { mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import path from 'node:path'
import test from 'node:test'
import {
buildQualitySummary,
parseJacocoReport,
parseSpotbugsReport,
requirementFailures,
repositoryRoot
} from './java-quality-summary.mjs'
test('parses JaCoCo line coverage and SpotBugs findings without quality thresholds', () => {
assert.deepEqual(parseJacocoReport('<report><counter type="LINE" missed="3" covered="7"/></report>'), {
missed: 3, covered: 7, percentage: 70
})
assert.deepEqual(parseSpotbugsReport('<BugCollection><BugInstance priority="1" category="CORRECTNESS"/><BugInstance priority="2" category="STYLE"/></BugCollection>'), {
findings: 2,
byPriority: { 1: 1, 2: 1 },
byCategory: { CORRECTNESS: 1, STYLE: 1 }
})
assert.deepEqual(parseSpotbugsReport("<BugCollection><BugInstance priority='2' category='MALICIOUS_CODE'/></BugCollection>"), {
findings: 1,
byPriority: { 2: 1 },
byCategory: { MALICIOUS_CODE: 1 }
})
assert.throws(() => parseJacocoReport('<report/>'), /not a JaCoCo report/)
assert.throws(() => parseSpotbugsReport('<BugCollection/>'), /not a SpotBugs report/)
})
test('aggregates code modules, report presence and the OpenAPI service matrix', async (t) => {
const root = await mkdtemp(path.join(tmpdir(), 'baiyue-quality-summary-'))
t.after(() => rm(root, { recursive: true, force: true }))
await writeFile(path.join(root, 'pom.xml'), '<modules><module>bom</module><module>alpha</module><module>beta</module></modules>', 'utf8')
await mkdir(path.join(root, 'deploy'), { recursive: true })
await writeFile(path.join(root, 'deploy', 'service-map.yml'), 'services:\n alpha:\n port: 1\n beta:\n port: 2\n', 'utf8')
await mkdir(path.join(root, 'alpha', 'src', 'main', 'java'), { recursive: true })
await mkdir(path.join(root, 'beta', 'src', 'main', 'java'), { recursive: true })
await writeFile(path.join(root, 'alpha', 'src', 'main', 'java', 'Alpha.java'), 'class Alpha {}', 'utf8')
await writeFile(path.join(root, 'beta', 'src', 'main', 'java', 'Beta.java'), 'class Beta {}', 'utf8')
await mkdir(path.join(root, 'alpha', 'src', 'main', 'resources', 'openapi'), { recursive: true })
await writeFile(path.join(root, 'alpha', 'src', 'main', 'resources', 'openapi', 'alpha.yaml'), 'openapi: 3.0.3\n', 'utf8')
await mkdir(path.join(root, 'alpha', 'target', 'site', 'jacoco'), { recursive: true })
await writeFile(path.join(root, 'alpha', 'target', 'site', 'jacoco', 'jacoco.xml'), '<report><counter type="LINE" missed="1" covered="9"/></report>', 'utf8')
await mkdir(path.join(root, 'alpha', 'target', 'site'), { recursive: true })
await writeFile(path.join(root, 'alpha', 'target', 'spotbugsXml.xml'), '<BugCollection><BugInstance priority="2" category="STYLE"/></BugCollection>', 'utf8')
await writeFile(path.join(root, 'alpha', 'target', 'site', 'spotbugs.html'), '<html></html>', 'utf8')
const summary = await buildQualitySummary(root)
assert.deepEqual(summary.topology, { modules: 3, codeModules: 2, services: 2 })
assert.equal(summary.openapi.documents, 1)
assert.deepEqual(summary.openapi.coveredServices, ['alpha'])
assert.deepEqual(summary.openapi.codeFirstServices, ['beta'])
assert.deepEqual(summary.jacoco, { present: 1, invalid: 0, missing: 1 })
assert.deepEqual(summary.spotbugs, { present: 1, invalid: 0, missing: 1, findings: 1 })
assert.deepEqual(requirementFailures(summary), [])
assert.deepEqual(requirementFailures(summary, { requireJacoco: true, requireSpotbugs: true }), [
'beta: JaCoCo report is missing', 'beta: SpotBugs report is missing'
])
})
test('repository freezes the current topology and non-blocking aggregate summary wiring', async () => {
const summary = await buildQualitySummary(repositoryRoot)
const baseline = JSON.parse(await readFile(path.join(repositoryRoot, 'scripts', 'java-quality-baseline.json'), 'utf8'))
assert.deepEqual(summary.topology, { modules: 20, codeModules: 19, services: 13 })
assert.equal(summary.openapi.documents, 69)
assert.ok(summary.openapi.files.includes('lastleg-service/src/main/resources/openapi/fleet-trips-v1.yaml'))
assert.ok(summary.openapi.files.includes('lastleg-service/src/main/resources/openapi/fleet-drivers-v1.yaml'))
assert.ok(summary.openapi.files.includes('file/src/main/resources/openapi/fleet-driver-license-v1.yaml'))
assert.ok(summary.modules.every(row => !['gateway-overseas', 'event-bridge-service'].includes(row.module)))
assert.ok(summary.openapi.files.includes('file/src/main/resources/openapi/loading-evidence-v1.yaml'))
assert.ok(summary.openapi.files.includes('file/src/main/resources/openapi/overseas-relabel-document-v1.yaml'))
assert.ok(summary.openapi.files.includes('finance/src/main/resources/openapi/finance-container-settlement-v1.yaml'))
assert.ok(summary.openapi.files.includes('warehouse-overseas-service/src/main/resources/openapi/warehouse-pallet-batch-internal-v1.yaml'))
assert.equal(baseline.openapi.documents, summary.openapi.documents)
assert.equal(summary.openapi.coveredServices.length, 11)
assert.deepEqual(summary.openapi.codeFirstServices, ['audit-service', 'gateway'])
assert.equal(baseline.mode, 'report-only')
assert.deepEqual(baseline.topology, summary.topology)
assert.equal(baseline.modules.length, 19)
assert.deepEqual(baseline.modules.map(row => row.module).sort(), summary.modules.map(row => row.module).sort())
assert.equal(baseline.modules.reduce((total, row) => total + row.spotbugsFindings, 0), baseline.reports.spotbugsFindings)
const gitlab = (await readFile(path.join(repositoryRoot, '.gitlab-ci.yml'), 'utf8')).replaceAll('\r\n', '\n')
const job = gitlab.match(/^质量摘要:\n([\s\S]*?)(?=^[^\s#].*:\n)/m)?.[1] ?? ''
const packageJob = gitlab.match(/^打包服务:\n([\s\S]*)/m)?.[1] ?? ''
assert.match(job, /^ allow_failure: true$/m)
assert.match(job, /java-quality-summary\.test\.mjs/)
assert.match(job, /java-quality-summary\.mjs --output target\/java-quality-summary\.json --require-jacoco --require-spotbugs/)
assert.match(job, /^ - job: 校验与测试$/m)
assert.match(job, /^ - job: 静态分析报告$/m)
assert.match(job, /^ - target\/java-quality-summary\.json$/m)
assert.doesNotMatch(job, /threshold|ratchet/i)
assert.doesNotMatch(packageJob, /^ - 质量摘要$/m)
})