Files
samreshu_backend/tests/test-utils.ts
2026-03-04 15:44:28 +03:00

150 lines
4.4 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 a select chain for .from().where().orderBy() - orderBy is terminal */
export function selectChainOrdered(resolveAtOrderBy: unknown[] = []) {
const orderByThenable = {
then: (resolve: (v: unknown) => void) => resolve(resolveAtOrderBy),
};
return {
from: vi.fn().mockReturnValue({
where: vi.fn().mockReturnValue({
orderBy: vi.fn().mockReturnValue(orderByThenable),
}),
}),
};
}
/** Build a select chain for .from().where() with no orderBy - used by select({...}).from() */
export function selectChainSimple(resolveRows: unknown[] = []) {
const thenable = { then: (resolve: (v: unknown) => void) => resolve(resolveRows) };
return {
from: vi.fn().mockReturnValue({
where: vi.fn().mockReturnValue(thenable),
}),
};
}
/** Build a select chain for .from().where() - where is terminal (no orderBy/limit) */
export function selectChainWhere(resolveAtWhere: unknown[] = []) {
const thenable = { then: (resolve: (v: unknown) => void) => resolve(resolveAtWhere) };
return {
from: vi.fn().mockReturnValue({
where: vi.fn().mockReturnValue(thenable),
}),
};
}
/** 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 an update chain with .where().returning() */
export function updateChainReturning(resolveAtReturning: unknown[] = []) {
const returningFn = vi.fn().mockResolvedValue(resolveAtReturning);
return {
set: vi.fn().mockReturnValue({
where: vi.fn().mockReturnValue({
returning: returningFn,
}),
}),
};
}
/** 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 };
}