/** * AriaEngine 最终扩展测试 — 全部 MemoryBackend */ import { AriaEngine } from '../../src/engine/aria/index'; import { createSchema } from '../../src/table/schema'; import { MemoryBackend } from '../../src/engine/aria/store/backend'; import { installOPFSMock } from '../helpers/opfs-mock'; beforeEach(() => { installOPFSMock(new Map()); }); describe('AriaEngine — 批量扩展测试', () => { let engine: AriaEngine; beforeEach(async () => { engine = new AriaEngine({ storageBackend: 'memory' }); await engine.open('bat', 1); }); afterEach(async () => { await engine.close(); }); it('事务 commit', async () => { await engine.createTable(createSchema('t', { id: { type: 'string', primaryKey: true }, n: { type: 'string' } })); await engine.beginTransaction(); await engine.insert('t', [{ id: '1', n: 'a' }, { id: '2', n: 'b' }]); await engine.commitTransaction(); expect(await engine.count('t')).toBe(2); }); it('事务 rollback', async () => { await engine.createTable(createSchema('t', { id: { type: 'string', primaryKey: true }, n: { type: 'string' } })); await engine.insert('t', [{ id: '1', n: 'a' }]); await engine.beginTransaction(); await engine.insert('t', [{ id: '2', n: 'b' }]); await engine.rollbackTransaction(); expect(await engine.count('t')).toBe(1); }); it('insert 空数组', async () => { await engine.createTable(createSchema('t', { id: { type: 'string', primaryKey: true } })); const pks = await engine.insert('t', []); expect(pks).toHaveLength(0); }); it('update 无匹配', async () => { await engine.createTable(createSchema('t', { id: { type: 'string', primaryKey: true }, n: { type: 'string' } })); await engine.insert('t', [{ id: '1', n: 'a' }]); expect(await engine.update('t', { table: 't', where: { id: 'x' } }, { n: 'x' })).toBe(0); }); it('delete 无匹配', async () => { await engine.createTable(createSchema('t', { id: { type: 'string', primaryKey: true } })); await engine.insert('t', [{ id: '1' }]); expect(await engine.delete('t', { table: 't', where: { id: 'x' } })).toBe(0); }); it('count 空表', async () => { await engine.createTable(createSchema('t', { id: { type: 'string', primaryKey: true } })); expect(await engine.count('t')).toBe(0); }); it('find 空表', async () => { await engine.createTable(createSchema('t', { id: { type: 'string', primaryKey: true } })); expect(await engine.find('t', { table: 't' })).toHaveLength(0); }); it('hasTable false', async () => { expect(await engine.hasTable('nope')).toBe(false); }); it('dropTable 后 hasTable false', async () => { await engine.createTable(createSchema('t', { id: { type: 'string', primaryKey: true } })); await engine.dropTable('t'); expect(await engine.hasTable('t')).toBe(false); }); it('清空表保留结构', async () => { await engine.createTable(createSchema('t', { id: { type: 'string', primaryKey: true } })); await engine.insert('t', [{ id: '1' }, { id: '2' }]); await engine.clear('t'); expect(await engine.count('t')).toBe(0); expect(await engine.hasTable('t')).toBe(true); }); it('重复主键抛异常', async () => { await engine.createTable(createSchema('t', { id: { type: 'string', primaryKey: true } })); await engine.insert('t', [{ id: '1' }]); await expect(engine.insert('t', [{ id: '1' }])).rejects.toThrow('Duplicate'); }); it('类型不匹配抛异常', async () => { await engine.createTable(createSchema('t', { id: { type: 'string', primaryKey: true }, age: { type: 'number' } })); await expect(engine.insert('t', [{ id: '1', age: 'x' as any }])).rejects.toThrow('expects number'); }); it('必填字段缺失抛异常', async () => { await engine.createTable(createSchema('t', { id: { type: 'string', primaryKey: true }, name: { type: 'string', required: true } })); await expect(engine.insert('t', [{ id: '1' }])).rejects.toThrow('required'); }); it('MemoryBackend isOpen', async () => { const be = new MemoryBackend(); expect(be.isOpen()).toBe(false); await be.open('x'); expect(be.isOpen()).toBe(true); await be.close(); }); it('引擎名称为 aria', () => { expect(engine.name).toBe('aria'); }); it('默认值 number', async () => { await engine.createTable(createSchema('t', { id: { type: 'string', primaryKey: true }, val: { type: 'number', default: 42 } })); await engine.insert('t', [{ id: '1' }]); expect((await engine.find('t', { table: 't' }))[0].val).toBe(42); }); it('默认值 boolean', async () => { await engine.createTable(createSchema('t', { id: { type: 'string', primaryKey: true }, active: { type: 'boolean', default: true } })); await engine.insert('t', [{ id: '1' }]); expect((await engine.find('t', { table: 't' }))[0].active).toBe(true); }); it('Schema json 往返', async () => { await engine.createTable(createSchema('t', { id: { type: 'string', primaryKey: true }, meta: { type: 'json' } })); await engine.insert('t', [{ id: '1', meta: { a: 1, b: [2, 3] } }]); expect((await engine.find('t', { table: 't' }))[0].meta).toEqual({ a: 1, b: [2, 3] }); }); it('date 类型存储', async () => { await engine.createTable(createSchema('t', { id: { type: 'string', primaryKey: true }, ts: { type: 'date' } })); await engine.insert('t', [{ id: '1', ts: '2026-01-01T00:00:00.000Z' }]); expect((await engine.find('t', { table: 't' }))[0].ts).toBe('2026-01-01T00:00:00.000Z'); }); it('重复 open 不改变状态', async () => { await engine.open('bat', 1); expect(engine.isOpen()).toBe(true); }); it('GC 调用不抛异常', () => { (engine as any).tryGC(); }); it('内存检查不抛异常', () => { (engine as any).checkMemoryBudget(); }); it('引擎状态 getTableNames', async () => { await engine.createTable(createSchema('t', { id: { type: 'string', primaryKey: true } })); expect(await engine.getTableNames()).toContain('t'); }); it('getTableSchema 返回正确结构', async () => { await engine.createTable(createSchema('t', { id: { type: 'string', primaryKey: true }, name: { type: 'string' } })); const s = await engine.getTableSchema('t'); expect(s!.columns.id.primaryKey).toBe(true); }); it('LIMIT 0 返回空', async () => { await engine.createTable(createSchema('t', { id: { type: 'string', primaryKey: true } })); await engine.insert('t', [{ id: '1' }, { id: '2' }]); expect(await engine.find('t', { table: 't', limit: 0 })).toHaveLength(0); }); it('ORDER BY desc', async () => { await engine.createTable(createSchema('t', { id: { type: 'string', primaryKey: true }, v: { type: 'number' } })); await engine.insert('t', [{ id: 'a', v: 1 }, { id: 'b', v: 3 }, { id: 'c', v: 2 }]); const r = await engine.find('t', { table: 't', orderBy: [{ column: 'v', direction: 'desc' }] }); expect(r[0].v).toBe(3); expect(r[2].v).toBe(1); }); it('$eq 直接值', async () => { await engine.createTable(createSchema('t', { id: { type: 'string', primaryKey: true }, n: { type: 'string' } })); await engine.insert('t', [{ id: '1', n: 'Alice' }, { id: '2', n: 'Bob' }]); expect(await engine.find('t', { table: 't', where: { n: 'Alice' } })).toHaveLength(1); }); it('$gte $lte 组合', async () => { await engine.createTable(createSchema('t', { id: { type: 'string', primaryKey: true }, v: { type: 'number' } })); for (let i = 0; i < 10; i++) await engine.insert('t', [{ id: `${i}`, v: i * 10 }]); expect(await engine.count('t', { table: 't', where: { v: { $gte: 20, $lte: 50 } } })).toBe(4); }); });