Files
iofficeai--aionui/tests/unit/bootstrap/configMigrationIntegration.test.ts
2026-07-13 13:20:22 +08:00

121 lines
3.7 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(),
}));
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: [{ table: 'teams', column: 'session_mode' }],
skippedTables: [],
})),
}));
import { existsSync } from 'fs';
import { runLegacyDatabaseMigrations } from '@process/services/database/runLegacyDatabaseMigrations';
import { getDatabaseVersion, setDatabaseVersion } from '@process/services/database/schema';
import { runMigrations } from '@process/services/database/migrations';
import { repairLegacyHandoffSchema } from '@process/services/database/repairLegacyHandoffSchema';
describe('configMigrationIntegration', () => {
beforeEach(() => {
vi.clearAllMocks();
(existsSync as any).mockReturnValue(true);
(getDatabaseVersion as any).mockReturnValue(20);
});
it('runs migrations when database version is outdated', async () => {
const result = await runLegacyDatabaseMigrations('/test/aionui.db');
expect(result.migrated).toBe(true);
expect(result.fromVersion).toBe(20);
expect(result.toVersion).toBe(26);
expect(runMigrations).toHaveBeenCalledWith(mockDriver, 20, 26);
expect(setDatabaseVersion).toHaveBeenCalledWith(mockDriver, 26);
});
it('skips migrations when database does not exist', async () => {
(existsSync as any).mockReturnValue(false);
const result = await runLegacyDatabaseMigrations('/test/aionui.db');
expect(result.skipped).toBe(true);
expect(result.migrated).toBe(false);
expect(result.handoffRepair).toEqual({ repairedColumns: [], skippedTables: [] });
expect(runMigrations).not.toHaveBeenCalled();
});
it('runs handoff repair even when database version is current', async () => {
(getDatabaseVersion as any).mockReturnValue(26);
const result = await runLegacyDatabaseMigrations('/test/aionui.db');
expect(runMigrations).not.toHaveBeenCalled();
expect(setDatabaseVersion).not.toHaveBeenCalled();
expect(repairLegacyHandoffSchema).toHaveBeenCalledWith(mockDriver);
expect(result.migrated).toBe(false);
expect(result.handoffRepair.repairedColumns).toEqual([{ table: 'teams', column: 'session_mode' }]);
});
it('closes driver after migration completes', async () => {
await runLegacyDatabaseMigrations('/test/aionui.db');
expect(mockDriver.close).toHaveBeenCalled();
});
it('ensures system user exists after migration', async () => {
await runLegacyDatabaseMigrations('/test/aionui.db');
expect(mockDriver.prepare).toHaveBeenCalledWith(expect.stringContaining('INSERT OR IGNORE INTO users'));
});
it('closes driver even if migration throws', async () => {
(runMigrations as any).mockImplementation(() => {
throw new Error('Migration failed');
});
await expect(runLegacyDatabaseMigrations('/test/aionui.db')).rejects.toThrow('Migration failed');
expect(mockDriver.close).toHaveBeenCalled();
});
});