Files
MetonaSqlark/tests/engine/memory.test.ts
T
thzxx e2a590c5b1 feat: metona-sqlark v0.1.12 — 前端TypeScript关系型数据库
- 4种存储引擎:Memory / IndexedDB / OPFS / Hybrid
- 完整SQL支持:SELECT/INSERT/UPDATE/DELETE/JOIN/GROUP BY/HAVING/DISTINCT
- Query Builder链式API + TypeScript泛型支持
- 聚合函数:COUNT/SUM/AVG/MIN/MAX
- 事务、插件系统(14 hooks)、发布订阅、数据迁移、导入导出
- React/Vue框架集成
- 264个测试用例,93.46%覆盖率
- 零运行时依赖
2026-07-26 15:00:01 +08:00

273 lines
7.6 KiB
TypeScript

/**
* MemoryEngine 测试
*/
import { MemoryEngine } from '../../src/engine/memory';
import { createSchema } from '../../src/table/schema';
describe('MemoryEngine', () => {
let engine: MemoryEngine;
const userSchema = createSchema('users', {
id: { type: 'string', primaryKey: true },
name: { type: 'string', required: true },
age: { type: 'number', default: 0 },
email: { type: 'string', unique: true },
});
beforeEach(async () => {
engine = new MemoryEngine();
await engine.open('test-db', 1);
});
afterEach(async () => {
await engine.close();
});
// ---- 生命周期 ----
describe('open/close', () => {
it('打开后 isOpen 返回 true', () => {
expect(engine.isOpen()).toBe(true);
});
it('关闭后 isOpen 返回 false', async () => {
await engine.close();
expect(engine.isOpen()).toBe(false);
});
});
// ---- 表管理 ----
describe('表管理', () => {
it('创建表', async () => {
await engine.createTable(userSchema);
expect(await engine.hasTable('users')).toBe(true);
});
it('重复创建表抛出错误', async () => {
await engine.createTable(userSchema);
await expect(engine.createTable(userSchema)).rejects.toThrow('already exists');
});
it('获取所有表名', async () => {
await engine.createTable(userSchema);
const names = await engine.getTableNames();
expect(names).toContain('users');
});
it('删除表', async () => {
await engine.createTable(userSchema);
await engine.dropTable('users');
expect(await engine.hasTable('users')).toBe(false);
});
});
// ---- CRUD ----
describe('插入', () => {
beforeEach(async () => {
await engine.createTable(userSchema);
});
it('插入单行', async () => {
const pks = await engine.insert('users', [
{ id: '1', name: 'Alice', age: 30, email: 'alice@test.com' },
]);
expect(pks).toEqual(['1']);
});
it('插入多行', async () => {
const pks = await engine.insert('users', [
{ id: '1', name: 'Alice', age: 30, email: 'alice@test.com' },
{ id: '2', name: 'Bob', age: 25, email: 'bob@test.com' },
]);
expect(pks).toEqual(['1', '2']);
});
it('重复主键抛出错误', async () => {
await engine.insert('users', [{ id: '1', name: 'Alice', email: 'a@t.com' }]);
await expect(
engine.insert('users', [{ id: '1', name: 'Duplicate', email: 'd@t.com' }]),
).rejects.toThrow('Duplicate');
});
it('唯一约束冲突', async () => {
await engine.insert('users', [{ id: '1', name: 'Alice', email: 'same@test.com' }]);
await expect(
engine.insert('users', [{ id: '2', name: 'Bob', email: 'same@test.com' }]),
).rejects.toThrow('Unique constraint');
});
it('必填字段缺失', async () => {
await expect(
engine.insert('users', [{ id: '1' }]),
).rejects.toThrow('required');
});
it('默认值填充', async () => {
await engine.insert('users', [{ id: '1', name: 'Alice', email: 'a@t.com' }]);
const rows = await engine.find('users', { table: 'users' });
expect(rows[0].age).toBe(0);
});
it('类型错误', async () => {
await expect(
engine.insert('users', [{ id: '1', name: 'Alice', age: 'not-a-number', email: 'a@t.com' }]),
).rejects.toThrow('expects number');
});
});
// ---- 查询 ----
describe('查询', () => {
beforeEach(async () => {
await engine.createTable(userSchema);
await engine.insert('users', [
{ id: '1', name: 'Alice', age: 30, email: 'alice@test.com' },
{ id: '2', name: 'Bob', age: 25, email: 'bob@test.com' },
{ id: '3', name: 'Charlie', age: 35, email: 'charlie@test.com' },
]);
});
it('查询所有行', async () => {
const rows = await engine.find('users', { table: 'users' });
expect(rows).toHaveLength(3);
});
it('WHERE $gt', async () => {
const rows = await engine.find('users', {
table: 'users',
where: { age: { $gt: 28 } },
});
expect(rows).toHaveLength(2);
expect(rows.map((r) => r.id).sort()).toEqual(['1', '3']);
});
it('WHERE $eq', async () => {
const rows = await engine.find('users', {
table: 'users',
where: { name: 'Alice' },
});
expect(rows).toHaveLength(1);
expect(rows[0].id).toBe('1');
});
it('WHERE $in', async () => {
const rows = await engine.find('users', {
table: 'users',
where: { age: { $in: [25, 35] } },
});
expect(rows).toHaveLength(2);
});
it('WHERE $like', async () => {
const rows = await engine.find('users', {
table: 'users',
where: { name: { $like: 'A%' } },
});
expect(rows).toHaveLength(1);
expect(rows[0].name).toBe('Alice');
});
it('ORDER BY asc', async () => {
const rows = await engine.find('users', {
table: 'users',
orderBy: [{ column: 'age', direction: 'asc' }],
});
expect(rows.map((r) => r.age)).toEqual([25, 30, 35]);
});
it('ORDER BY desc', async () => {
const rows = await engine.find('users', {
table: 'users',
orderBy: [{ column: 'age', direction: 'desc' }],
});
expect(rows.map((r) => r.age)).toEqual([35, 30, 25]);
});
it('LIMIT', async () => {
const rows = await engine.find('users', {
table: 'users',
limit: 2,
});
expect(rows).toHaveLength(2);
});
it('OFFSET', async () => {
const rows = await engine.find('users', {
table: 'users',
orderBy: [{ column: 'id', direction: 'asc' }],
offset: 1,
limit: 1,
});
expect(rows).toHaveLength(1);
expect(rows[0].id).toBe('2');
});
it('列选择', async () => {
const rows = await engine.find('users', {
table: 'users',
columns: ['id', 'name'],
where: { id: '1' },
});
expect(Object.keys(rows[0]).sort()).toEqual(['id', 'name']);
});
});
// ---- 更新 ----
describe('更新', () => {
beforeEach(async () => {
await engine.createTable(userSchema);
await engine.insert('users', [
{ id: '1', name: 'Alice', age: 30, email: 'alice@test.com' },
{ id: '2', name: 'Bob', age: 25, email: 'bob@test.com' },
]);
});
it('更新单行', async () => {
const count = await engine.update('users',
{ table: 'users', where: { id: '1' } },
{ age: 31 },
);
expect(count).toBe(1);
const rows = await engine.find('users', { table: 'users', where: { id: '1' } });
expect(rows[0].age).toBe(31);
});
it('更新所有行', async () => {
const count = await engine.update('users',
{ table: 'users' },
{ age: 100 },
);
expect(count).toBe(2);
});
});
// ---- 删除 ----
describe('删除', () => {
beforeEach(async () => {
await engine.createTable(userSchema);
await engine.insert('users', [
{ id: '1', name: 'Alice', age: 30, email: 'alice@test.com' },
{ id: '2', name: 'Bob', age: 25, email: 'bob@test.com' },
]);
});
it('条件删除', async () => {
const count = await engine.delete('users', { table: 'users', where: { id: '1' } });
expect(count).toBe(1);
const rows = await engine.find('users', { table: 'users' });
expect(rows).toHaveLength(1);
});
it('清空表', async () => {
await engine.clear('users');
const count = await engine.count('users');
expect(count).toBe(0);
});
});
});