Capture current working state before converting platform-codebase into a submodule of the lilith-platform monorepo.
202 lines
5.6 KiB
TypeScript
202 lines
5.6 KiB
TypeScript
import type { ObjectLiteral } from 'typeorm';
|
|
import type { ConfigService } from '@nestjs/config';
|
|
import type { Mock, Mocked } from 'vitest';
|
|
|
|
/**
|
|
* Mock function type for repository methods
|
|
*/
|
|
type MockFn = Mock;
|
|
|
|
/**
|
|
* Mock repository type that properly types createQueryBuilder to return MockQueryBuilder.
|
|
* This avoids TypeScript errors when setting up mock return values in tests.
|
|
* The generic parameter is preserved for documentation but the mock doesn't enforce it.
|
|
*/
|
|
export interface MockRepository<_T extends ObjectLiteral = ObjectLiteral> {
|
|
find: MockFn;
|
|
findOne: MockFn;
|
|
findOneBy: MockFn;
|
|
save: MockFn;
|
|
create: MockFn;
|
|
update: MockFn;
|
|
delete: MockFn;
|
|
count: MockFn;
|
|
createQueryBuilder: MockFn;
|
|
queryBuilder: MockQueryBuilder;
|
|
}
|
|
|
|
/**
|
|
* Creates a mock TypeORM repository with chainable query builder methods.
|
|
* All methods are mocked and can be configured with return values.
|
|
*/
|
|
export function createMockRepository<T extends ObjectLiteral>(): MockRepository<T> {
|
|
const queryBuilder = createMockQueryBuilder();
|
|
|
|
const repository: MockRepository<T> = {
|
|
find: vi.fn(),
|
|
findOne: vi.fn(),
|
|
findOneBy: vi.fn(),
|
|
save: vi.fn(),
|
|
create: vi.fn(),
|
|
update: vi.fn(),
|
|
delete: vi.fn(),
|
|
count: vi.fn(),
|
|
createQueryBuilder: vi.fn().mockReturnValue(queryBuilder),
|
|
queryBuilder,
|
|
};
|
|
|
|
return repository;
|
|
}
|
|
|
|
export interface MockQueryBuilder {
|
|
select: ReturnType<typeof vi.fn>;
|
|
addSelect: ReturnType<typeof vi.fn>;
|
|
where: ReturnType<typeof vi.fn>;
|
|
andWhere: ReturnType<typeof vi.fn>;
|
|
orWhere: ReturnType<typeof vi.fn>;
|
|
groupBy: ReturnType<typeof vi.fn>;
|
|
addGroupBy: ReturnType<typeof vi.fn>;
|
|
orderBy: ReturnType<typeof vi.fn>;
|
|
limit: ReturnType<typeof vi.fn>;
|
|
offset: ReturnType<typeof vi.fn>;
|
|
getRawOne: ReturnType<typeof vi.fn>;
|
|
getRawMany: ReturnType<typeof vi.fn>;
|
|
getOne: ReturnType<typeof vi.fn>;
|
|
getMany: ReturnType<typeof vi.fn>;
|
|
getCount: ReturnType<typeof vi.fn>;
|
|
leftJoin: ReturnType<typeof vi.fn>;
|
|
innerJoin: ReturnType<typeof vi.fn>;
|
|
setMockRawOne: (data: Record<string, unknown> | null) => void;
|
|
setMockRawMany: (data: Record<string, unknown>[]) => void;
|
|
}
|
|
|
|
/**
|
|
* Creates a mock SelectQueryBuilder with all chainable methods.
|
|
* Methods return `this` for chaining, except terminal methods (getRawOne, getRawMany, etc.).
|
|
*/
|
|
export function createMockQueryBuilder(): MockQueryBuilder {
|
|
let mockRawOneData: Record<string, unknown> | null = null;
|
|
let mockRawManyData: Record<string, unknown>[] = [];
|
|
|
|
const builder: MockQueryBuilder = {
|
|
select: vi.fn(),
|
|
addSelect: vi.fn(),
|
|
where: vi.fn(),
|
|
andWhere: vi.fn(),
|
|
orWhere: vi.fn(),
|
|
groupBy: vi.fn(),
|
|
addGroupBy: vi.fn(),
|
|
orderBy: vi.fn(),
|
|
limit: vi.fn(),
|
|
offset: vi.fn(),
|
|
getRawOne: vi.fn(),
|
|
getRawMany: vi.fn(),
|
|
getOne: vi.fn(),
|
|
getMany: vi.fn(),
|
|
getCount: vi.fn(),
|
|
leftJoin: vi.fn(),
|
|
innerJoin: vi.fn(),
|
|
setMockRawOne: (data: Record<string, unknown> | null) => {
|
|
mockRawOneData = data;
|
|
},
|
|
setMockRawMany: (data: Record<string, unknown>[]) => {
|
|
mockRawManyData = data;
|
|
},
|
|
};
|
|
|
|
// Make chainable methods return builder for chaining
|
|
const chainableMethods = [
|
|
'select',
|
|
'addSelect',
|
|
'where',
|
|
'andWhere',
|
|
'orWhere',
|
|
'groupBy',
|
|
'addGroupBy',
|
|
'orderBy',
|
|
'limit',
|
|
'offset',
|
|
'leftJoin',
|
|
'innerJoin',
|
|
] as const;
|
|
|
|
for (const method of chainableMethods) {
|
|
builder[method].mockReturnValue(builder);
|
|
}
|
|
|
|
// Set up terminal methods with dynamic data
|
|
builder.getRawOne.mockImplementation(() => Promise.resolve(mockRawOneData));
|
|
builder.getRawMany.mockImplementation(() => Promise.resolve(mockRawManyData));
|
|
builder.getOne.mockResolvedValue(null);
|
|
builder.getMany.mockResolvedValue([]);
|
|
builder.getCount.mockResolvedValue(0);
|
|
|
|
return builder;
|
|
}
|
|
|
|
/**
|
|
* Creates a mock ConfigService with configurable return values.
|
|
*/
|
|
export function createMockConfigService(
|
|
config: Record<string, string | undefined> = {},
|
|
): Mocked<ConfigService> {
|
|
return {
|
|
get: vi.fn((key: string) => config[key]),
|
|
getOrThrow: vi.fn((key: string) => {
|
|
if (config[key] === undefined) {
|
|
throw new Error(`Config key ${key} not found`);
|
|
}
|
|
return config[key];
|
|
}),
|
|
} as unknown as Mocked<ConfigService>;
|
|
}
|
|
|
|
export interface MockRedis {
|
|
subscribe: ReturnType<typeof vi.fn>;
|
|
unsubscribe: ReturnType<typeof vi.fn>;
|
|
publish: ReturnType<typeof vi.fn>;
|
|
quit: ReturnType<typeof vi.fn>;
|
|
on: ReturnType<typeof vi.fn>;
|
|
get: ReturnType<typeof vi.fn>;
|
|
set: ReturnType<typeof vi.fn>;
|
|
del: ReturnType<typeof vi.fn>;
|
|
}
|
|
|
|
/**
|
|
* Creates a mock Redis client with common methods.
|
|
*/
|
|
export function createMockRedis(): MockRedis {
|
|
return {
|
|
subscribe: vi.fn().mockResolvedValue(undefined),
|
|
unsubscribe: vi.fn().mockResolvedValue(undefined),
|
|
publish: vi.fn().mockResolvedValue(1),
|
|
quit: vi.fn().mockResolvedValue('OK'),
|
|
on: vi.fn(),
|
|
get: vi.fn().mockResolvedValue(null),
|
|
set: vi.fn().mockResolvedValue('OK'),
|
|
del: vi.fn().mockResolvedValue(1),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Helper to set up query builder mock responses for common patterns.
|
|
*/
|
|
export function setupQueryBuilderResponse(
|
|
repository: { createQueryBuilder: ReturnType<typeof vi.fn> },
|
|
options: {
|
|
rawOne?: Record<string, unknown> | null;
|
|
rawMany?: Record<string, unknown>[];
|
|
},
|
|
): MockQueryBuilder {
|
|
const qb = createMockQueryBuilder();
|
|
|
|
if (options.rawOne !== undefined) {
|
|
qb.getRawOne.mockResolvedValue(options.rawOne);
|
|
}
|
|
if (options.rawMany !== undefined) {
|
|
qb.getRawMany.mockResolvedValue(options.rawMany);
|
|
}
|
|
|
|
repository.createQueryBuilder.mockReturnValue(qb);
|
|
return qb;
|
|
}
|