40 lines
2.4 KiB
JavaScript
40 lines
2.4 KiB
JavaScript
import {test} from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import {readFile,mkdtemp,mkdir,writeFile,rm} from 'node:fs/promises';
|
|
import {tmpdir} from 'node:os';
|
|
import path from 'node:path';
|
|
import {managedMedia,readRepositoryMedia} from '../scripts/managed-media.mjs';
|
|
test('media registry uses immutable objects and consistent identities',()=>{
|
|
const byKey=new Map();
|
|
assert.equal(Object.keys(managedMedia).length,603);
|
|
for(const [name,asset] of Object.entries(managedMedia)){
|
|
assert.ok(!name.includes('..')&&!name.startsWith('/'));
|
|
assert.match(asset.sha256,/^[a-f0-9]{64}$/);
|
|
assert.equal(asset.key,`repository-media/sha256/${asset.sha256}.png`);
|
|
assert.match(asset.id,/^[a-f0-9-]{36}$/);
|
|
assert.ok(asset.bytes>0&&asset.width>0&&asset.height>0);
|
|
if(byKey.has(asset.key))assert.deepEqual(byKey.get(asset.key),asset);
|
|
byKey.set(asset.key,asset);
|
|
}
|
|
assert.equal(byKey.size,572);
|
|
});
|
|
test('external cache preserves all bytes and detects corruption',async()=>{
|
|
if(!process.env.MEDIA_SOURCE_ROOT)return;
|
|
for(const name of Object.keys(managedMedia))assert.equal((await readRepositoryMedia(name)).length,managedMedia[name].bytes);
|
|
await assert.rejects(()=>readRepositoryMedia('../unregistered.png'),/Unregistered/);
|
|
const previous=process.env.MEDIA_SOURCE_ROOT;const temporary=await mkdtemp(path.join(tmpdir(),'media-corruption-'));
|
|
try{
|
|
const name=Object.keys(managedMedia)[0];const file=path.join(temporary,name);await mkdir(path.dirname(file),{recursive:true});await writeFile(file,'corrupt');
|
|
process.env.MEDIA_SOURCE_ROOT=temporary;await assert.rejects(()=>readRepositoryMedia(name),/checksum mismatch/);
|
|
}finally{process.env.MEDIA_SOURCE_ROOT=previous;await rm(temporary,{recursive:true,force:true});}
|
|
});
|
|
test('every public raster path has an S3 mapping and runtime importer has no directory reads',async()=>{
|
|
const publicImages=Object.keys(managedMedia).filter(name=>name.startsWith('apps/waterfall-wiki/public/'));
|
|
assert.equal(publicImages.length,5);
|
|
const importer=await readFile(new URL('../apps/waterfall-wiki/scripts/import-character-packs.mjs',import.meta.url),'utf8');
|
|
assert.ok(importer.includes('/api/media/'));assert.ok(!importer.includes('readdir'));
|
|
for(const pack of JSON.parse(await readFile(new URL('../apps/waterfall-wiki/seed/characters/packs.json',import.meta.url)))){
|
|
assert.equal(Object.keys(managedMedia).filter(name=>name.startsWith(`apps/waterfall-wiki/seed/characters/${pack.directory}/`)).length,pack.count);
|
|
}
|
|
});
|