Files
jiapuapp/design-pipeline/tests/runtime-asset-inventory.test.mjs
T
2026-07-22 17:31:38 +08:00

143 lines
5.6 KiB
JavaScript

import test from 'node:test'
import assert from 'node:assert/strict'
import { mkdtemp, mkdir, rm, writeFile } from 'node:fs/promises'
import os from 'node:os'
import path from 'node:path'
import { expandRuntimeAssetInventory } from '../scripts/runtime-asset-inventory.mjs'
const createWorkspace = async () => {
const workspace = await mkdtemp(path.join(os.tmpdir(), 'jiapu-runtime-assets-'))
await mkdir(path.join(workspace, 'design-pipeline', 'manifests'), { recursive: true })
return workspace
}
const writeManifest = async (workspace, name, value) => {
const filePath = path.join(workspace, 'design-pipeline', 'manifests', name)
await writeFile(filePath, `${JSON.stringify(value, null, 2)}\n`, 'utf8')
return filePath
}
const directAsset = (id, output) => ({
id,
output,
width: 96,
height: 96,
alpha: true,
bytes: 100,
sha256: 'a'.repeat(64),
provenance: 'committed-binary',
rebuildable: false,
})
const runtimeManifest = (imports = [], assets = []) => ({
schemaVersion: 1,
kind: 'runtime-asset-inventory',
scope: 'auth',
imports,
assets,
})
test('展开直接资产与单一导入且不复制物理规格', async (t) => {
const workspace = await createWorkspace()
t.after(() => rm(workspace, { recursive: true, force: true }))
const imported = await writeManifest(
workspace,
'shared.json',
runtimeManifest([], [directAsset('shared', 'static/assets/shared.png')]),
)
const root = await writeManifest(
workspace,
'auth.json',
runtimeManifest(['design-pipeline/manifests/shared.json'], [directAsset('auth', 'static/assets/auth.png')]),
)
const result = await expandRuntimeAssetInventory(root, workspace)
assert.deepEqual(result.assets.map(({ id }) => id).sort(), ['auth', 'shared'])
assert(result.manifests.includes(imported))
})
test('拒绝缺失的导入文件', async (t) => {
const workspace = await createWorkspace()
t.after(() => rm(workspace, { recursive: true, force: true }))
const root = await writeManifest(workspace, 'auth.json', runtimeManifest(['design-pipeline/manifests/missing.json']))
await assert.rejects(() => expandRuntimeAssetInventory(root, workspace), /missing manifest/i)
})
test('拒绝循环导入', async (t) => {
const workspace = await createWorkspace()
t.after(() => rm(workspace, { recursive: true, force: true }))
const first = await writeManifest(workspace, 'first.json', runtimeManifest(['design-pipeline/manifests/second.json']))
await writeManifest(workspace, 'second.json', runtimeManifest(['design-pipeline/manifests/first.json']))
await assert.rejects(() => expandRuntimeAssetInventory(first, workspace), /import cycle/i)
})
test('拒绝同一清单被重复导入', async (t) => {
const workspace = await createWorkspace()
t.after(() => rm(workspace, { recursive: true, force: true }))
await writeManifest(workspace, 'shared.json', runtimeManifest([], [directAsset('shared', 'static/assets/shared.png')]))
const root = await writeManifest(
workspace,
'auth.json',
runtimeManifest([
'design-pipeline/manifests/shared.json',
'design-pipeline/manifests/shared.json',
]),
)
await assert.rejects(() => expandRuntimeAssetInventory(root, workspace), /duplicate import/i)
})
test('拒绝不同清单拥有同一正式输出', async (t) => {
const workspace = await createWorkspace()
t.after(() => rm(workspace, { recursive: true, force: true }))
await writeManifest(workspace, 'shared.json', runtimeManifest([], [directAsset('shared', 'static/assets/same.png')]))
const root = await writeManifest(
workspace,
'auth.json',
runtimeManifest(
['design-pipeline/manifests/shared.json'],
[directAsset('auth', 'static/assets/same.png')],
),
)
await assert.rejects(() => expandRuntimeAssetInventory(root, workspace), /duplicate output/i)
})
test('拒绝展开图中的重复资产 id', async (t) => {
const workspace = await createWorkspace()
t.after(() => rm(workspace, { recursive: true, force: true }))
await writeManifest(workspace, 'shared.json', runtimeManifest([], [directAsset('same-id', 'static/assets/shared.png')]))
const root = await writeManifest(
workspace,
'auth.json',
runtimeManifest(
['design-pipeline/manifests/shared.json'],
[directAsset('same-id', 'static/assets/auth.png')],
),
)
await assert.rejects(() => expandRuntimeAssetInventory(root, workspace), /duplicate asset id/i)
})
test('直接资产只接受 committed-binary 且拒绝未知字段', async (t) => {
const workspace = await createWorkspace()
t.after(() => rm(workspace, { recursive: true, force: true }))
const wrongProvenance = directAsset('wrong-provenance', 'static/assets/wrong.png')
wrongProvenance.provenance = 'manual-copy'
const wrongRoot = await writeManifest(workspace, 'wrong.json', runtimeManifest([], [wrongProvenance]))
await assert.rejects(() => expandRuntimeAssetInventory(wrongRoot, workspace), /committed-binary/i)
const unknownField = directAsset('unknown-field', 'static/assets/unknown.png')
unknownField.runtimeSelector = '.page'
const unknownRoot = await writeManifest(workspace, 'unknown.json', runtimeManifest([], [unknownField]))
await assert.rejects(() => expandRuntimeAssetInventory(unknownRoot, workspace), /unknown field/i)
})
test('运行时清单本身拒绝未知字段', async (t) => {
const workspace = await createWorkspace()
t.after(() => rm(workspace, { recursive: true, force: true }))
const manifest = runtimeManifest()
manifest.consumerList = []
const root = await writeManifest(workspace, 'auth.json', manifest)
await assert.rejects(() => expandRuntimeAssetInventory(root, workspace), /unknown field/i)
})