39 lines
3.9 KiB
TypeScript
39 lines
3.9 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import {readFile} from 'node:fs/promises';
|
|
import {randomUUID} from 'node:crypto';
|
|
import {db} from '../src/lib/db';
|
|
export async function verifyFlatNoteMigration(){
|
|
const client=await db().connect();const schema='migration_'+randomUUID().replaceAll('-','');
|
|
try{
|
|
await client.query(`CREATE SCHEMA ${schema}`);await client.query(`SET search_path TO ${schema}`);
|
|
for(const name of ['001_library','002_page_snapshots','003_note_descriptions'])await client.query(await readFile(`db/${name}.sql`,'utf8'));
|
|
const [video,picture,post,tag,duplicate,parent]=Array.from({length:6},()=>randomUUID());
|
|
await client.query(`INSERT INTO assets(id,kind,storage_key,mime_type,byte_size) VALUES($1,'video','original','video/mp4',100),($2,'image','snapshot','image/png',50)`,[video,picture]);
|
|
await client.query(`INSERT INTO posts(id,slug,kind,title,page_key) VALUES($1,'old-note','article','保留的笔记','old-code')`,[post]);
|
|
await client.query(`INSERT INTO post_assets(post_id,asset_id,position) VALUES($1,$2,0)`,[post,video]);
|
|
await client.query(`INSERT INTO page_snapshots(post_id,page_index,asset_id,revision) VALUES($1,1,$2,'old-revision')`,[post,picture]);
|
|
await client.query(`INSERT INTO render_jobs(post_id,status,revision) VALUES($1,'pending','old-revision')`,[post]);
|
|
await client.query(`INSERT INTO asset_variants(asset_id,role,storage_key,mime_type,byte_size) VALUES($1,'poster','old-poster','image/jpeg',20)`,[video]);
|
|
await client.query(`INSERT INTO media_jobs(id,asset_id) VALUES($1,$2)`,[randomUUID(),video]);
|
|
await client.query(`INSERT INTO tags(id,slug,name) VALUES($1,'parent','上级'),($2,'same','重复')`,[parent,tag]);
|
|
await client.query(`INSERT INTO tags(id,parent_id,slug,name) VALUES($1,$2,'same','重复')`,[duplicate,parent]);
|
|
await client.query(`INSERT INTO post_tags(post_id,tag_id) VALUES($1,$2),($1,$3)`,[post,tag,duplicate]);
|
|
await client.query(`INSERT INTO asset_tags(asset_id,tag_id) VALUES($1,$2)`,[video,duplicate]);
|
|
await client.query(await readFile('db/004_flat_notes.sql','utf8'));
|
|
assert.equal((await client.query('SELECT count(*)::integer n FROM post_assets WHERE post_id=$1 AND asset_id=$2',[post,picture])).rows[0].n,1,'Previously generated image remains linked');
|
|
const processed=(await client.query(`SELECT a.storage_key,pa.role FROM post_assets pa JOIN assets a ON a.id=pa.asset_id WHERE pa.post_id=$1 AND a.derivation='poster'`,[post])).rows;
|
|
assert.deepEqual(processed,[{storage_key:'old-poster',role:'poster'}],'Processed file uses its existing object and a normal resource link');
|
|
assert.equal((await client.query('SELECT count(*)::integer n FROM post_tags WHERE post_id=$1',[post])).rows[0].n,1);
|
|
assert.equal((await client.query('SELECT count(*)::integer n FROM asset_tags WHERE asset_id=$1',[video])).rows[0].n,1,'Merging equal tags retains asset associations');
|
|
assert.equal((await client.query('SELECT count(*)::integer n FROM media_jobs')).rows[0].n,1,'Video processing queue survives');
|
|
assert.equal((await client.query(`SELECT count(*)::integer n FROM information_schema.columns WHERE table_schema=$1 AND column_name IN ('parent_id','page_key')`,[schema])).rows[0].n,0);
|
|
await client.query(await readFile('db/008_system_tags.sql','utf8'));
|
|
assert.equal((await client.query("SELECT count(*)::integer n FROM tags WHERE kind='system'")).rows[0].n,2);
|
|
assert.ok((await client.query("SELECT 1 FROM tags WHERE kind='normal'")).rowCount);
|
|
assert.equal((await client.query('SELECT count(*)::integer n FROM post_tags WHERE post_id=$1',[post])).rows[0].n,1,'System tag migration retains ordinary associations');
|
|
await assert.rejects(client.query("INSERT INTO tags(id,slug,name,kind) VALUES($1,'invalid-system','Invalid system','system')",[randomUUID()]));
|
|
}finally{
|
|
await client.query('ROLLBACK');await client.query('SET search_path TO public');await client.query(`DROP SCHEMA IF EXISTS ${schema} CASCADE`);client.release();
|
|
}
|
|
}
|