Files
landing-builder/lib/exporter/assets.integrity.index.test.ts
T
jaybe 92aa4f19c7
Auto PR / open-pr (push) Successful in 17s
Auto Label PR / add-automerge-label (pull_request) Successful in 6s
CI / test (pull_request) Successful in 1m18s
Option2 무결성 강화: integrity index 추가, 인덱스 정렬/교차 검증, referencedAt 매트릭스, README 문서화 (TDD)
2025-11-16 12:30:41 +09:00

38 lines
2.5 KiB
TypeScript

import { describe, it, expect } from 'vitest'
import { AssetManager } from '@/lib/assets/assetManager'
import { buildAssetsIntegrityIndex } from '@/lib/exporter/assets.integrity.index'
import { buildAssetsMetadata } from '@/lib/exporter/assets.meta'
function u8(n: number): Uint8Array { const a = new Uint8Array(n); for (let i=0;i<n;i++) a[i]=i&0xff; return a }
describe('assets.integrity.index.json', () => {
it('emits path->integrity mapping consistent with assets.json and deterministically across modes and insertion order', async () => {
for (const mode of ['flat','grouped'] as const) {
// case1: insertion order A,B,C
const am1 = new AssetManager({ maxBytes: 1024*1024, allowedExts: ['png','woff2','txt'], pathStrategy: mode })
await am1.add({ name: 'a.png', type: 'image/png', bytes: u8(3) })
await am1.add({ name: 'b.woff2', type: 'font/woff2', bytes: u8(4) })
await am1.add({ name: 'c.txt', type: 'text/plain', bytes: u8(5) })
const idx1 = JSON.parse(new TextDecoder().decode(buildAssetsIntegrityIndex(am1))) as { entries: Array<{path:string; integrity:string}>; bundleHash: string }
const meta1 = JSON.parse(new TextDecoder().decode(buildAssetsMetadata(am1))) as { assets: Array<{ zipPath: string; integrity: string }> }
const metaMap1 = new Map(meta1.assets.map(a => [a.zipPath, a.integrity]))
const paths1 = idx1.entries.map(e => e.path)
const sorted1 = [...paths1].sort()
expect(paths1).toEqual(sorted1)
for (const e of idx1.entries) expect(metaMap1.get(e.path)).toBe(e.integrity)
// case2: insertion order shuffled C,A,B -> determinism of output
const am2 = new AssetManager({ maxBytes: 1024*1024, allowedExts: ['png','woff2','txt'], pathStrategy: mode })
await am2.add({ name: 'c.txt', type: 'text/plain', bytes: u8(5) })
await am2.add({ name: 'a.png', type: 'image/png', bytes: u8(3) })
await am2.add({ name: 'b.woff2', type: 'font/woff2', bytes: u8(4) })
const idx2 = JSON.parse(new TextDecoder().decode(buildAssetsIntegrityIndex(am2))) as { entries: Array<{path:string; integrity:string}>; bundleHash: string }
// same entries set and order (sorted by path) -> equality
expect(idx2.entries.map(e => e.path)).toEqual(idx1.entries.map(e => e.path))
expect(idx2.entries.map(e => e.integrity)).toEqual(idx1.entries.map(e => e.integrity))
// bundle hash depends on entries -> equal as well
expect(idx2.bundleHash).toBe(idx1.bundleHash)
}
})
})