Files
baiyue-firstleg/scripts/admin-test-env-modules/suppliers-contract.test.mjs
2026-10-22 14:37:59 +08:00

77 lines
4.4 KiB
JavaScript

import assert from 'node:assert/strict'
import { readFileSync } from 'node:fs'
import test from 'node:test'
import { run } from './suppliers.mjs'
import { AcceptanceRun } from '../admin-test-env-acceptance.mjs'
const source=readFileSync(new URL('./suppliers.mjs',import.meta.url),'utf8')
const orchestrator=readFileSync(new URL('../admin-test-env-acceptance.mjs',import.meta.url),'utf8')
const openapi=readFileSync(new URL('../../warehouse/src/main/resources/openapi/supplier-v1.yaml',import.meta.url),'utf8')
test('supplier acceptance covers full CRUD-like lifecycle, carrier matrix and boundary failures',()=>{
for(const marker of ['列表分页与订舱筛选','查询四类供应商统计','新增供应商','查询供应商详情','编辑供应商','停用供应商','重复名称返回冲突','tenantId非0被拒绝','非BOOKING携带carrierCodes返回A0400并保留链路ID','客户账号调用平台供应商接口被拒绝','requestId','traceId']) assert.match(source,new RegExp(marker))
assert.match(source,/carrierCodes:\['MATSON','COSCO'\]/)
assert.match(source,/sameCarrierCodes\(detail\?\.carrierCodes,\['MATSON','COSCO'\]\)/)
assert.doesNotMatch(source,/scope\s*:/)
})
test('supplier module is registered in the default full acceptance orchestration',()=>assert.match(orchestrator,/CONFIGURED_MODULES = \[[^\]]*'suppliers'/s))
test('supplier fixture is retained only as inactive because API has no delete contract',()=>{assert.match(source,/finalStatus:inactive\?'INACTIVE'/);assert.doesNotMatch(source,/context\.request\('DELETE'/)})
test('supplier OpenAPI exposes the internal active category validation contract without scope',()=>{
for(const marker of ['/internal/warehouse/v1/suppliers/{supplierId}','X-Internal-Service-Token','requireActive','InternalSnapshot','SupplierPageResponse','platform:supplier:list']) assert.match(openapi,new RegExp(marker.replace(/[{}]/g,'\\$&')))
assert.doesNotMatch(openapi,/\bscope\b/)
assert.doesNotMatch(openapi,/platform:supplier:view/)
})
function existingHarness({ empty = false, wrongDetail = false, failStats = false } = {}) {
const runner = new AcceptanceRun({ environment: 'test', fixedCustomerId: '123', quiet: true })
const calls = []
const categories = ['BOOKING', 'CUSTOMS', 'TRUCKING', 'CERTIFICATE']
runner.request = async (method, path) => {
calls.push({ method, path })
assert.equal(method, 'GET', 'fixed suppliers must never mutate master data')
const url = new URL(path, 'http://offline.invalid')
let data
let code = '200'
if (url.searchParams.get('tenantId') === '1') code = 'A0400'
else if (url.pathname.endsWith('/stats')) {
data = { booking: 1, customs: 1, trucking: 1, certificate: 1 }
if (failStats) code = 'S0500'
} else if (url.searchParams.has('category')) {
const category = url.searchParams.get('category')
data = { records: empty ? [] : [{ id: String(categories.indexOf(category) + 1), category, status: 'ACTIVE' }],
page: 1, size: 20, total: empty ? 0 : 1, pages: empty ? 0 : 1 }
} else {
const id = url.pathname.split('/').at(-1)
data = { id, tenantId: wrongDetail ? '88' : '0', category: categories[Number(id) - 1], status: 'ACTIVE' }
}
return { http: 200, body: { code, data }, requestId: 'request', traceId: 'trace' }
}
return { runner, calls }
}
test('fixed supplier module runs through orchestrator using only existing read-only records', async () => {
const { runner, calls } = existingHarness()
await runner.executeModule('suppliers', () => run(runner))
assert.equal(calls.length, 10)
assert.equal(runner.modules[0].skipped, undefined)
assert.equal(runner.modules[0].success, true)
assert.equal(runner.coverageGaps.length, 1)
assert.equal(runner.coverageGaps[0].scenario, 'fixed-resource-lifecycle')
})
test('empty supplier lists retain detail gaps and never create replacements', async () => {
const { runner, calls } = existingHarness({ empty: true })
await run(runner)
assert.equal(calls.length, 6)
assert.equal(runner.coverageGaps.length, 5)
assert.ok(runner.steps.every(step => step.passed))
})
test('supplier detail scope drift and failed statistics remain failures', async () => {
for (const options of [{ wrongDetail: true }, { failStats: true }]) {
const { runner } = existingHarness(options)
await runner.executeModule('suppliers', () => run(runner))
assert.equal(runner.modules[0].success, false)
assert.ok(runner.steps.some(step => !step.passed))
}
})