125 lines
3.9 KiB
TypeScript
125 lines
3.9 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2025 AionUi (aionui.com)
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
|
|
const mockDriver = {
|
|
prepare: vi.fn(() => ({
|
|
run: vi.fn(),
|
|
get: vi.fn(),
|
|
all: vi.fn(),
|
|
})),
|
|
close: vi.fn(),
|
|
exec: vi.fn(),
|
|
};
|
|
|
|
vi.mock('@process/services/database/drivers/BetterSqlite3Driver', () => ({
|
|
BetterSqlite3Driver: class {
|
|
constructor() {
|
|
return mockDriver;
|
|
}
|
|
},
|
|
}));
|
|
|
|
vi.mock('fs', () => ({
|
|
existsSync: vi.fn(() => true),
|
|
}));
|
|
|
|
vi.mock('@process/utils', () => ({
|
|
ensureDirectory: vi.fn(),
|
|
getDataPath: () => '/data',
|
|
}));
|
|
|
|
vi.mock('@process/services/database/schema', () => ({
|
|
CURRENT_DB_VERSION: 26,
|
|
getDatabaseVersion: vi.fn(() => 20),
|
|
initSchema: vi.fn(),
|
|
setDatabaseVersion: vi.fn(),
|
|
}));
|
|
|
|
vi.mock('@process/services/database/migrations', () => ({
|
|
runMigrations: vi.fn(),
|
|
}));
|
|
|
|
vi.mock('@process/services/database/repairLegacyHandoffSchema', () => ({
|
|
repairLegacyHandoffSchema: vi.fn(() => ({ repairedColumns: [], skippedTables: [] })),
|
|
}));
|
|
|
|
import { runLegacyDatabaseMigrations } from '@process/services/database/runLegacyDatabaseMigrations';
|
|
import { runMigrations } from '@process/services/database/migrations';
|
|
import { repairLegacyHandoffSchema } from '@process/services/database/repairLegacyHandoffSchema';
|
|
import { initSchema, setDatabaseVersion } from '@process/services/database/schema';
|
|
|
|
describe('migrationErrorRecovery', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
(initSchema as any).mockImplementation(() => {});
|
|
(runMigrations as any).mockImplementation(() => {});
|
|
(repairLegacyHandoffSchema as any).mockImplementation(() => ({ repairedColumns: [], skippedTables: [] }));
|
|
(setDatabaseVersion as any).mockImplementation(() => {});
|
|
mockDriver.prepare.mockImplementation(() => ({
|
|
run: vi.fn(),
|
|
get: vi.fn(),
|
|
all: vi.fn(),
|
|
}));
|
|
});
|
|
|
|
it('closes driver when initSchema throws', async () => {
|
|
(initSchema as any).mockImplementation(() => {
|
|
throw new Error('Schema init failed');
|
|
});
|
|
|
|
await expect(runLegacyDatabaseMigrations('/test/aionui.db')).rejects.toThrow('Schema init failed');
|
|
expect(mockDriver.close).toHaveBeenCalled();
|
|
});
|
|
|
|
it('closes driver when runMigrations throws', async () => {
|
|
(runMigrations as any).mockImplementation(() => {
|
|
throw new Error('Migration step failed');
|
|
});
|
|
|
|
await expect(runLegacyDatabaseMigrations('/test/aionui.db')).rejects.toThrow('Migration step failed');
|
|
expect(mockDriver.close).toHaveBeenCalled();
|
|
});
|
|
|
|
it('closes driver when setDatabaseVersion throws', async () => {
|
|
(setDatabaseVersion as any).mockImplementation(() => {
|
|
throw new Error('Set version failed');
|
|
});
|
|
|
|
await expect(runLegacyDatabaseMigrations('/test/aionui.db')).rejects.toThrow('Set version failed');
|
|
expect(mockDriver.close).toHaveBeenCalled();
|
|
});
|
|
|
|
it('closes driver when handoff repair throws', async () => {
|
|
(repairLegacyHandoffSchema as any).mockImplementation(() => {
|
|
throw new Error('Handoff repair failed');
|
|
});
|
|
|
|
await expect(runLegacyDatabaseMigrations('/test/aionui.db')).rejects.toThrow('Handoff repair failed');
|
|
expect(mockDriver.close).toHaveBeenCalled();
|
|
});
|
|
|
|
it('closes driver when system user insert throws', async () => {
|
|
mockDriver.prepare.mockImplementation(() => {
|
|
throw new Error('User insert failed');
|
|
});
|
|
|
|
await expect(runLegacyDatabaseMigrations('/test/aionui.db')).rejects.toThrow('User insert failed');
|
|
expect(mockDriver.close).toHaveBeenCalled();
|
|
});
|
|
|
|
it('skips migration gracefully when database path is invalid', async () => {
|
|
const { existsSync } = await import('fs');
|
|
(existsSync as any).mockReturnValue(false);
|
|
|
|
const result = await runLegacyDatabaseMigrations('/invalid/path.db');
|
|
|
|
expect(result.skipped).toBe(true);
|
|
expect(mockDriver.close).not.toHaveBeenCalled();
|
|
});
|
|
});
|