mirror of
https://git.openapi.site/https://github.com/desirecore/config-center.git
synced 2026-10-21 05:24:25 +08:00
68 lines
4.3 KiB
JavaScript
68 lines
4.3 KiB
JavaScript
import { test } from 'node:test'
|
|
import assert from 'node:assert/strict'
|
|
import { cpSync, mkdtempSync, readFileSync, writeFileSync, rmSync } from 'node:fs'
|
|
import { tmpdir } from 'node:os'
|
|
import { join } from 'node:path'
|
|
import { fileURLToPath } from 'node:url'
|
|
import { spawnSync } from 'node:child_process'
|
|
import { validateDataSources } from '../scripts/validate-data-sources.mjs'
|
|
|
|
const repo = fileURLToPath(new URL('../', import.meta.url))
|
|
function fixture(run) {
|
|
const root = mkdtempSync(join(tmpdir(), 'data-contract-'))
|
|
for (const path of ['docs/data-sources', 'api-providers', 'compute/providers']) cpSync(join(repo, path), join(root, path), { recursive: true })
|
|
for (const file of ['pricing.json', 'service-map.json']) cpSync(join(repo, 'compute', file), join(root, 'compute', file))
|
|
try { run(root) } finally { rmSync(root, { recursive: true, force: true }) }
|
|
}
|
|
function change(root, path, mutate) {
|
|
const file = join(root, path), data = JSON.parse(readFileSync(file, 'utf8'))
|
|
mutate(data)
|
|
writeFileSync(file, JSON.stringify(data))
|
|
}
|
|
test('non-model source records cover current policy and API configuration', () => {
|
|
assert.deepEqual(validateDataSources(repo), { errors: [], records: 8 })
|
|
})
|
|
test('API authentication and result mapping changes require contract review', () => fixture(root => {
|
|
change(root, 'api-providers/web-search/tavily.json', data => { data.auth.type = 'none'; data.response.resultsPath = 'wrong' })
|
|
assert.match(validateDataSources(root).errors.join('\n'), /contract drift: auth/)
|
|
}))
|
|
test('new API provider must have its own source record', () => fixture(root => {
|
|
cpSync(join(root, 'api-providers/web-search/tavily.json'), join(root, 'api-providers/web-search/new.json'))
|
|
assert.match(validateDataSources(root).errors.join('\n'), /missing source record: api-providers\/web-search\/new.json/)
|
|
}))
|
|
test('pricing assumptions cannot drift without policy record update', () => fixture(root => {
|
|
change(root, 'compute/pricing.json', data => { data.usdToCny = 8 })
|
|
assert.match(validateDataSources(root).errors.join('\n'), /contract drift: usdToCny/)
|
|
}))
|
|
test('default mappings cannot reference absent models', () => fixture(root => {
|
|
change(root, 'compute/service-map.json', data => { data.chat.modelName = 'nonexistent' })
|
|
assert.match(validateDataSources(root).errors.join('\n'), /unresolved route chat/)
|
|
}))
|
|
test('changing a default to an existing model still requires a policy record update', () => fixture(root => {
|
|
change(root, 'compute/service-map.json', data => { data.chat.modelName = 'gpt-5.5' })
|
|
assert.match(validateDataSources(root).errors.join('\n'), /routing policy drift/)
|
|
}))
|
|
test('third-party hosts cannot be presented as official evidence', () => fixture(root => {
|
|
const path = join(root, 'docs/data-sources/api-providers/tavily.md')
|
|
writeFileSync(path, readFileSync(path, 'utf8').replace('https://docs.tavily.com/', 'https://third-party.example/'))
|
|
assert.match(validateDataSources(root).errors.join('\n'), /unapproved source URL/)
|
|
}))
|
|
test('an official entry cannot redirect verification to a third-party site', () => fixture(root => {
|
|
const path = join(root, 'docs/data-sources/api-providers/tavily.md')
|
|
writeFileSync(path, readFileSync(path, 'utf8').replace('"resolvedUrl": "https://docs.tavily.com/', '"resolvedUrl": "https://third-party.example/'))
|
|
assert.match(validateDataSources(root).errors.join('\n'), /unapproved resolved source URL/)
|
|
}))
|
|
test('a page shell cannot prove verified API fields', () => fixture(root => {
|
|
const path = join(root, 'docs/data-sources/api-providers/tavily.md')
|
|
writeFileSync(path, readFileSync(path, 'utf8').replace('"retrieval": "fetched"', '"retrieval": "shell"'))
|
|
assert.match(validateDataSources(root).errors.join('\n'), /verified field without fetched source/)
|
|
}))
|
|
test('retired ZenMux tools fail before reading or writing data', () => {
|
|
for (const entry of ['batch_update_model_jsons', 'apply_all_updates_and_build_diff_report', 'generate_current_audit_artifacts', 'generate_field_tables_per_json']) {
|
|
const result = spawnSync(process.execPath, [join(repo, 'tools', `${entry}.mjs`)], { encoding: 'utf8', env: { ...process.env, CONFIG_CENTER_ROOT: '/nonexistent-root', ZENMUX_FILE: '/nonexistent-snapshot' } })
|
|
assert.equal(result.status, 1)
|
|
assert.match(result.stderr, /retired/)
|
|
assert.doesNotMatch(result.stderr, /ENOENT/)
|
|
}
|
|
})
|