release: v0.5.1 — 存储后端生产级硬化(CRC-32/全库加密/WAL分片/页面化存储/多标签页锁/e2e)+ 深度审查修复(假实现接线/死代码清理)
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
/**
|
||||
* v0.5.1 — CRUD 生命周期钩子真实接线测试
|
||||
*
|
||||
* 此前 beforeInsert/afterInsert/beforeUpdate/afterUpdate/beforeDelete/afterDelete
|
||||
* 六个钩子虽在 HookName 类型与文档中宣称("14 种钩子"),但从未被任何路径触发。
|
||||
* 本次验证 Table API 与 SQL query 两条路径均真实触发全部 14 个钩子。
|
||||
*/
|
||||
import { MetonaSqlark } from '../src/core';
|
||||
import 'fake-indexeddb/auto';
|
||||
|
||||
async function createDb(name: string): Promise<MetonaSqlark> {
|
||||
const db = new MetonaSqlark({ name: `hooks-${name}-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`, mode: 'memory' });
|
||||
await db.init();
|
||||
await db.defineTable('users', {
|
||||
id: { type: 'string', primaryKey: true },
|
||||
name: { type: 'string' },
|
||||
age: { type: 'number' },
|
||||
});
|
||||
return db;
|
||||
}
|
||||
|
||||
describe('v0.5.1 — CRUD hooks 真实接线', () => {
|
||||
it('Table.insert / insertMany 触发 beforeInsert + afterInsert', async () => {
|
||||
const db = await createDb('table-insert');
|
||||
const events: string[] = [];
|
||||
db.on('beforeInsert', (rows) => { events.push(`before:${(rows as unknown[]).length}`); });
|
||||
db.on('afterInsert', (rows, pks) => { events.push(`after:${(rows as unknown[]).length}:${(pks as string[]).length}`); });
|
||||
|
||||
await db.table('users').insert({ id: '1', name: 'A' });
|
||||
await db.table('users').insertMany([{ id: '2', name: 'B' }, { id: '3', name: 'C' }]);
|
||||
|
||||
expect(events).toEqual([
|
||||
'before:1', 'after:1:1',
|
||||
'before:2', 'after:2:2',
|
||||
]);
|
||||
await db.close();
|
||||
});
|
||||
|
||||
it('Table.update().execute() 触发 beforeUpdate + afterUpdate(含影响行数)', async () => {
|
||||
const db = await createDb('table-update');
|
||||
await db.table('users').insertMany([{ id: '1', name: 'A', age: 1 }, { id: '2', name: 'B', age: 2 }]);
|
||||
const events: string[] = [];
|
||||
db.on('beforeUpdate', (query, updates) => { events.push(`before:${(updates as Record<string, unknown>).name}`); });
|
||||
db.on('afterUpdate', (_query, _updates, count) => { events.push(`after:${count}`); });
|
||||
|
||||
await db.table('users').update({ name: 'X' }).where({ age: { $gt: 1 } }).execute();
|
||||
|
||||
expect(events).toEqual(['before:X', 'after:1']);
|
||||
await db.close();
|
||||
});
|
||||
|
||||
it('Table.delete().execute() 触发 beforeDelete + afterDelete(含影响行数)', async () => {
|
||||
const db = await createDb('table-delete');
|
||||
await db.table('users').insertMany([{ id: '1', name: 'A' }, { id: '2', name: 'B' }]);
|
||||
const events: string[] = [];
|
||||
db.on('beforeDelete', (query) => { events.push(`before:${(query as { where: Record<string, unknown> }).where.id}`); });
|
||||
db.on('afterDelete', (_query, count) => { events.push(`after:${count}`); });
|
||||
|
||||
await db.table('users').delete().where({ id: '1' }).execute();
|
||||
|
||||
expect(events).toEqual(['before:1', 'after:1']);
|
||||
await db.close();
|
||||
});
|
||||
|
||||
it('SQL query 路径触发全部 CRUD hooks(INSERT/UPDATE/DELETE)', async () => {
|
||||
const db = await createDb('sql-crud');
|
||||
await db.query("INSERT INTO users VALUES ('1', 'Alice', 30)");
|
||||
const events: string[] = [];
|
||||
db.on('beforeInsert', () => events.push('beforeInsert'));
|
||||
db.on('afterInsert', () => events.push('afterInsert'));
|
||||
db.on('beforeUpdate', () => events.push('beforeUpdate'));
|
||||
db.on('afterUpdate', () => events.push('afterUpdate'));
|
||||
db.on('beforeDelete', () => events.push('beforeDelete'));
|
||||
db.on('afterDelete', () => events.push('afterDelete'));
|
||||
|
||||
await db.query("INSERT INTO users VALUES ('2', 'Bob', 25)");
|
||||
await db.query("UPDATE users SET age = 26 WHERE id = '2'");
|
||||
await db.query("DELETE FROM users WHERE id = '1'");
|
||||
|
||||
expect(events).toEqual([
|
||||
'beforeInsert', 'afterInsert',
|
||||
'beforeUpdate', 'afterUpdate',
|
||||
'beforeDelete', 'afterDelete',
|
||||
]);
|
||||
await db.close();
|
||||
});
|
||||
|
||||
it('SQL INSERT 多行语句按列名映射触发 afterInsert', async () => {
|
||||
const db = await createDb('sql-insert-cols');
|
||||
const seen: unknown[] = [];
|
||||
db.on('afterInsert', (_rows, pks) => seen.push(pks));
|
||||
|
||||
await db.query("INSERT INTO users (id, name) VALUES ('9', 'Zed')");
|
||||
|
||||
expect(seen).toEqual([['9']]);
|
||||
await db.close();
|
||||
});
|
||||
|
||||
it('全部 14 个钩子均可注册并真实触发', async () => {
|
||||
const db = await createDb('all-hooks');
|
||||
const fired = new Set<string>();
|
||||
const hooks = [
|
||||
'beforeCreateTable', 'afterCreateTable',
|
||||
'beforeDropTable', 'afterDropTable',
|
||||
'beforeInsert', 'afterInsert',
|
||||
'beforeUpdate', 'afterUpdate',
|
||||
'beforeDelete', 'afterDelete',
|
||||
'beforeQuery', 'afterQuery',
|
||||
'beforeTransaction', 'afterTransaction',
|
||||
] as const;
|
||||
for (const h of hooks) db.on(h, () => fired.add(h));
|
||||
|
||||
await db.defineTable('t2', { id: { type: 'string', primaryKey: true } }); // createTable hooks
|
||||
await db.table('t2').insert({ id: '1' }); // insert hooks
|
||||
await db.table('t2').update({}).where({ id: '1' }).execute(); // update hooks
|
||||
await db.table('t2').delete().where({ id: '1' }).execute(); // delete hooks
|
||||
await db.query('SELECT * FROM t2'); // query hooks
|
||||
await db.transaction(async () => { /* noop */ }); // transaction hooks
|
||||
await db.dropTable('t2'); // dropTable hooks
|
||||
|
||||
for (const h of hooks) {
|
||||
expect(fired.has(h)).toBe(true);
|
||||
if (!fired.has(h)) throw new Error(`hook ${h} 应被触发`);
|
||||
}
|
||||
await db.close();
|
||||
});
|
||||
|
||||
it('事务路径不触发 CRUD hooks(Table 无 hooks 回调)', async () => {
|
||||
const db = await createDb('tx-hooks');
|
||||
let fired = false;
|
||||
db.on('beforeInsert', () => { fired = true; });
|
||||
|
||||
await db.transaction(async (trx) => {
|
||||
await trx.table('users').insert({ id: '1', name: 'Tx' });
|
||||
});
|
||||
|
||||
expect(fired).toBe(false);
|
||||
await db.close();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user