test(db): isolate default sqlite path under vitest
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { resolve } from 'node:path';
|
||||
|
||||
type DbModule = typeof import('./index.js');
|
||||
|
||||
describe('sqlite default path resolution', () => {
|
||||
let dbModule: DbModule | null = null;
|
||||
|
||||
afterEach(async () => {
|
||||
if (dbModule) {
|
||||
await dbModule.closeDbConnections();
|
||||
dbModule = null;
|
||||
}
|
||||
delete process.env.DATA_DIR;
|
||||
delete process.env.DB_URL;
|
||||
vi.resetModules();
|
||||
});
|
||||
|
||||
it('uses an isolated temp sqlite path under vitest when no db env is configured', async () => {
|
||||
delete process.env.DATA_DIR;
|
||||
delete process.env.DB_URL;
|
||||
vi.resetModules();
|
||||
|
||||
dbModule = await import('./index.js');
|
||||
const sqlitePath = dbModule.__dbProxyTestUtils.resolveSqlitePath();
|
||||
const sharedRepoPath = resolve('./data/hub.db');
|
||||
|
||||
expect(sqlitePath).not.toBe(sharedRepoPath);
|
||||
expect(sqlitePath).toContain(tmpdir());
|
||||
expect(sqlitePath).toContain('metapi-vitest');
|
||||
});
|
||||
|
||||
it('still honors explicit DATA_DIR when provided', async () => {
|
||||
process.env.DATA_DIR = resolve(tmpdir(), 'metapi-explicit-data-dir');
|
||||
delete process.env.DB_URL;
|
||||
vi.resetModules();
|
||||
|
||||
dbModule = await import('./index.js');
|
||||
const sqlitePath = dbModule.__dbProxyTestUtils.resolveSqlitePath();
|
||||
|
||||
expect(sqlitePath).toBe(resolve(process.env.DATA_DIR, 'hub.db'));
|
||||
});
|
||||
});
|
||||
+40
-1
@@ -12,7 +12,9 @@ import { ensureSharedIndexSchemaCompatibility } from './sharedIndexSchemaCompati
|
||||
import { config } from '../config.js';
|
||||
import { ensureRuntimeDatabaseReady } from '../runtimeDatabaseBootstrap.js';
|
||||
import { mkdirSync } from 'fs';
|
||||
import { tmpdir } from 'os';
|
||||
import { dirname, resolve } from 'path';
|
||||
import { threadId } from 'worker_threads';
|
||||
|
||||
export type RuntimeDbDialect = 'sqlite' | 'mysql' | 'postgres';
|
||||
type SqlMethod = 'all' | 'get' | 'run' | 'values' | 'execute';
|
||||
@@ -42,7 +44,13 @@ let proxyLogBillingDetailsColumnAvailable: boolean | null = null;
|
||||
|
||||
function resolveSqlitePath(): string {
|
||||
const raw = (config.dbUrl || '').trim();
|
||||
if (!raw) return resolve(`${config.dataDir}/hub.db`);
|
||||
if (!raw) {
|
||||
const isolatedVitestPath = resolveVitestSqlitePath();
|
||||
if (isolatedVitestPath) {
|
||||
return isolatedVitestPath;
|
||||
}
|
||||
return resolve(`${config.dataDir}/hub.db`);
|
||||
}
|
||||
if (raw === ':memory:') return raw;
|
||||
if (raw.startsWith('file://')) {
|
||||
const parsed = new URL(raw);
|
||||
@@ -54,6 +62,35 @@ function resolveSqlitePath(): string {
|
||||
return resolve(raw);
|
||||
}
|
||||
|
||||
function isVitestRuntime(): boolean {
|
||||
if ((process.env.VITEST_POOL_ID || '').trim()) {
|
||||
return true;
|
||||
}
|
||||
if ((process.env.VITEST_WORKER_ID || '').trim()) {
|
||||
return true;
|
||||
}
|
||||
const runtimeArgs = [...process.argv, ...process.execArgv]
|
||||
.map((value) => String(value || '').toLowerCase());
|
||||
return runtimeArgs.some((value) => value.includes('vitest'));
|
||||
}
|
||||
|
||||
function resolveVitestSqlitePath(): string | null {
|
||||
if (!isVitestRuntime()) {
|
||||
return null;
|
||||
}
|
||||
if ((process.env.DB_URL || '').trim()) {
|
||||
return null;
|
||||
}
|
||||
if ((process.env.DATA_DIR || '').trim()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const workerTag = process.env.VITEST_POOL_ID
|
||||
|| process.env.VITEST_WORKER_ID
|
||||
|| `${process.pid}-${threadId}`;
|
||||
return resolve(tmpdir(), `metapi-vitest-${workerTag}`, 'hub.db');
|
||||
}
|
||||
|
||||
function requireSqliteConnection(): Database.Database {
|
||||
if (!sqliteConnection) {
|
||||
throw new Error('SQLite connection is not initialized');
|
||||
@@ -993,4 +1030,6 @@ export async function switchRuntimeDatabase(nextDialect: RuntimeDbDialect, nextD
|
||||
export const __dbProxyTestUtils = {
|
||||
wrapQueryLike,
|
||||
shouldWrapObject,
|
||||
resolveSqlitePath,
|
||||
resolveVitestSqlitePath,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user