119 lines
4.1 KiB
TypeScript
119 lines
4.1 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
|
|
|
|
// db.ts imports none of these directly, but the mocks keep the test isolated
|
|
// from real database clients if that ever changes.
|
|
vi.mock('@/lib/prisma', () => ({}));
|
|
vi.mock('@/lib/clickhouse', () => ({}));
|
|
vi.mock('@/lib/kafka', () => ({}));
|
|
|
|
let db!: typeof import('./db');
|
|
|
|
beforeEach(async () => {
|
|
vi.resetModules();
|
|
db = await import('./db');
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.unstubAllEnvs();
|
|
});
|
|
|
|
describe('getDatabaseType', () => {
|
|
test('maps a postgres:// url to postgresql', () => {
|
|
expect(db.getDatabaseType('postgres://user:pass@localhost:5432/umami')).toBe('postgresql');
|
|
});
|
|
|
|
test('returns postgresql for a postgresql:// url', () => {
|
|
expect(db.getDatabaseType('postgresql://user:pass@localhost:5432/umami')).toBe('postgresql');
|
|
});
|
|
|
|
test('returns the raw scheme for other databases', () => {
|
|
expect(db.getDatabaseType('mysql://user:pass@localhost:3306/umami')).toBe('mysql');
|
|
});
|
|
|
|
test('reads process.env.DATABASE_URL by default', () => {
|
|
vi.stubEnv('DATABASE_URL', 'postgres://user:pass@localhost:5432/umami');
|
|
expect(db.getDatabaseType()).toBe('postgresql');
|
|
});
|
|
|
|
test('falls back to the DATABASE_URL default when called with undefined', () => {
|
|
vi.stubEnv('DATABASE_URL', 'postgres://user:pass@localhost:5432/umami');
|
|
expect(db.getDatabaseType(undefined)).toBe('postgresql');
|
|
});
|
|
});
|
|
|
|
describe('runQuery', () => {
|
|
test('runs the clickhouse query when CLICKHOUSE_URL is set', async () => {
|
|
vi.stubEnv('CLICKHOUSE_URL', 'http://localhost:8123');
|
|
const clickhouse = vi.fn().mockResolvedValue('clickhouse-result');
|
|
const prisma = vi.fn();
|
|
|
|
await expect(db.runQuery({ clickhouse, prisma })).resolves.toBe('clickhouse-result');
|
|
expect(clickhouse).toHaveBeenCalledTimes(1);
|
|
expect(prisma).not.toHaveBeenCalled();
|
|
});
|
|
|
|
test('prefers the kafka query over clickhouse when both are provided', async () => {
|
|
vi.stubEnv('CLICKHOUSE_URL', 'http://localhost:8123');
|
|
const kafka = vi.fn().mockResolvedValue('kafka-result');
|
|
const clickhouse = vi.fn();
|
|
|
|
await expect(db.runQuery({ kafka, clickhouse })).resolves.toBe('kafka-result');
|
|
expect(kafka).toHaveBeenCalledTimes(1);
|
|
expect(clickhouse).not.toHaveBeenCalled();
|
|
});
|
|
|
|
test('runs the prisma query for a postgresql database', async () => {
|
|
vi.stubEnv('CLICKHOUSE_URL', '');
|
|
vi.stubEnv('DATABASE_URL', 'postgresql://user:pass@localhost:5432/umami');
|
|
const prisma = vi.fn().mockResolvedValue('prisma-result');
|
|
|
|
await expect(db.runQuery({ prisma })).resolves.toBe('prisma-result');
|
|
expect(prisma).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
test('returns undefined for an unsupported database with no clickhouse', async () => {
|
|
vi.stubEnv('CLICKHOUSE_URL', '');
|
|
vi.stubEnv('DATABASE_URL', 'mysql://user:pass@localhost:3306/umami');
|
|
const prisma = vi.fn();
|
|
|
|
await expect(db.runQuery({ prisma })).resolves.toBeUndefined();
|
|
expect(prisma).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('isRelationalOnly', () => {
|
|
test('returns true for a postgresql database without clickhouse', () => {
|
|
vi.stubEnv('CLICKHOUSE_URL', '');
|
|
vi.stubEnv('DATABASE_URL', 'postgresql://user:pass@localhost:5432/umami');
|
|
|
|
expect(db.isRelationalOnly()).toBe(true);
|
|
});
|
|
|
|
test('returns false when clickhouse is enabled', () => {
|
|
vi.stubEnv('CLICKHOUSE_URL', 'http://localhost:8123');
|
|
vi.stubEnv('DATABASE_URL', 'postgresql://user:pass@localhost:5432/umami');
|
|
|
|
expect(db.isRelationalOnly()).toBe(false);
|
|
});
|
|
|
|
test('returns false for unsupported non-relational databases', () => {
|
|
vi.stubEnv('CLICKHOUSE_URL', '');
|
|
vi.stubEnv('DATABASE_URL', 'mysql://user:pass@localhost:3306/umami');
|
|
|
|
expect(db.isRelationalOnly()).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('BigInt.prototype.toJSON', () => {
|
|
test('serializes bigint values as numbers', () => {
|
|
expect((BigInt(123) as any).toJSON()).toBe(123);
|
|
expect(JSON.stringify({ count: BigInt(42) })).toBe('{"count":42}');
|
|
});
|
|
});
|
|
|
|
describe('notImplemented', () => {
|
|
test('throws a Not implemented error', () => {
|
|
expect(() => db.notImplemented()).toThrow('Not implemented.');
|
|
});
|
|
});
|