104 lines
3.0 KiB
TypeScript
104 lines
3.0 KiB
TypeScript
import { vi } from 'vitest';
|
|
import type { FastifyInstance } from 'fastify';
|
|
import type { NodePgDatabase } from 'drizzle-orm/node-postgres';
|
|
import type * as schema from '../src/db/schema/index.js';
|
|
|
|
export type MockDb = {
|
|
select: ReturnType<NodePgDatabase<typeof schema>['select']>;
|
|
insert: ReturnType<NodePgDatabase<typeof schema>['insert']>;
|
|
update: ReturnType<NodePgDatabase<typeof schema>['update']>;
|
|
delete: ReturnType<NodePgDatabase<typeof schema>['delete']>;
|
|
};
|
|
|
|
/** Build a select chain that resolves to the given rows at .limit(n) */
|
|
export function selectChain(resolveAtLimit: unknown[] = []) {
|
|
const limitFn = vi.fn().mockResolvedValue(resolveAtLimit);
|
|
return {
|
|
from: vi.fn().mockReturnValue({
|
|
where: vi.fn().mockReturnValue({
|
|
limit: limitFn,
|
|
orderBy: vi.fn().mockReturnValue({ limit: limitFn }),
|
|
}),
|
|
limit: limitFn,
|
|
}),
|
|
};
|
|
}
|
|
|
|
/** Build an insert chain that resolves at .returning() or .values() */
|
|
export function insertChain(resolveAtReturning: unknown[] = []) {
|
|
const returningFn = vi.fn().mockResolvedValue(resolveAtReturning);
|
|
const chainFromValues = {
|
|
returning: returningFn,
|
|
then: (resolve: (v?: unknown) => void) => resolve(undefined),
|
|
};
|
|
return {
|
|
values: vi.fn().mockReturnValue(chainFromValues),
|
|
returning: returningFn,
|
|
};
|
|
}
|
|
|
|
/** Build an update chain that resolves at .where() */
|
|
export function updateChain(resolveAtWhere: unknown[] = []) {
|
|
return {
|
|
set: vi.fn().mockReturnValue({
|
|
where: vi.fn().mockResolvedValue(resolveAtWhere),
|
|
}),
|
|
};
|
|
}
|
|
|
|
/** Build a delete chain that resolves at .where() */
|
|
export function deleteChain() {
|
|
return {
|
|
where: vi.fn().mockResolvedValue(undefined),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Create a chainable mock for Drizzle DB operations.
|
|
* Use mockReturnValue with selectChain/insertChain/updateChain/deleteChain.
|
|
*/
|
|
export function createMockDb(): MockDb {
|
|
const chain = {
|
|
from: vi.fn().mockReturnThis(),
|
|
where: vi.fn().mockReturnThis(),
|
|
values: vi.fn().mockReturnThis(),
|
|
set: vi.fn().mockReturnThis(),
|
|
orderBy: vi.fn().mockReturnThis(),
|
|
limit: vi.fn().mockReturnThis(),
|
|
returning: vi.fn().mockReturnThis(),
|
|
};
|
|
|
|
return {
|
|
select: vi.fn().mockReturnValue(chain),
|
|
insert: vi.fn().mockReturnValue(chain),
|
|
update: vi.fn().mockReturnValue(chain),
|
|
delete: vi.fn().mockReturnValue(chain),
|
|
} as unknown as MockDb;
|
|
}
|
|
|
|
/**
|
|
* Create a minimal mock Fastify app with db for route/integration tests.
|
|
* Use buildApp() from app.ts for full integration tests.
|
|
*/
|
|
export function createMockApp(): FastifyInstance & { db: MockDb } {
|
|
return {
|
|
db: createMockDb(),
|
|
log: {
|
|
child: () => ({
|
|
debug: () => {},
|
|
info: () => {},
|
|
warn: () => {},
|
|
error: () => {},
|
|
trace: () => {},
|
|
fatal: () => {},
|
|
}),
|
|
debug: () => {},
|
|
info: () => {},
|
|
warn: () => {},
|
|
error: () => {},
|
|
trace: () => {},
|
|
fatal: () => {},
|
|
},
|
|
} as FastifyInstance & { db: MockDb };
|
|
}
|