refactor: repository mocks (#16785)

This commit is contained in:
Jason Rasmussen
2025-03-10 16:52:44 -04:00
committed by GitHub
parent 1b35400043
commit 1382b27349
59 changed files with 320 additions and 550 deletions
+2 -2
View File
@@ -34,9 +34,9 @@ import { TrashRepository } from 'src/repositories/trash.repository';
import { UserRepository } from 'src/repositories/user.repository';
import { VersionHistoryRepository } from 'src/repositories/version-history.repository';
import { ViewRepository } from 'src/repositories/view-repository';
import { newLoggingRepositoryMock } from 'test/repositories/logger.repository.mock';
import { newTelemetryRepositoryMock } from 'test/repositories/telemetry.repository.mock';
import { newUuid } from 'test/small.factory';
import { automock } from 'test/utils';
class CustomWritable extends Writable {
private data = '';
@@ -213,7 +213,7 @@ export class TestContext {
view: ViewRepository;
private constructor(public db: Kysely<DB>) {
const logger = newLoggingRepositoryMock() as unknown as LoggingRepository;
const logger = automock(LoggingRepository, { args: [, { getEnv: () => ({}) }], strict: false });
const config = new ConfigRepository();
this.access = new AccessRepository(this.db);
@@ -3,12 +3,14 @@ import { writeFile } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { AssetEntity } from 'src/entities/asset.entity';
import { LoggingRepository } from 'src/repositories/logging.repository';
import { MetadataRepository } from 'src/repositories/metadata.repository';
import { MetadataService } from 'src/services/metadata.service';
import { newFakeLoggingRepository } from 'test/repositories/logger.repository.mock';
import { newRandomImage, newTestService, ServiceMocks } from 'test/utils';
import { automock, newRandomImage, newTestService, ServiceMocks } from 'test/utils';
const metadataRepository = new MetadataRepository(newFakeLoggingRepository());
const metadataRepository = new MetadataRepository(
automock(LoggingRepository, { args: [, { getEnv: () => ({}) }], strict: false }),
);
const createTestFile = async (exifData: Record<string, any>) => {
const data = newRandomImage();
@@ -1,12 +0,0 @@
import { ActivityRepository } from 'src/repositories/activity.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newActivityRepositoryMock = (): Mocked<RepositoryInterface<ActivityRepository>> => {
return {
search: vitest.fn(),
create: vitest.fn(),
delete: vitest.fn(),
getStatistics: vitest.fn(),
};
};
@@ -1,11 +0,0 @@
import { AlbumUserRepository } from 'src/repositories/album-user.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked } from 'vitest';
export const newAlbumUserRepositoryMock = (): Mocked<RepositoryInterface<AlbumUserRepository>> => {
return {
create: vitest.fn(),
delete: vitest.fn(),
update: vitest.fn(),
};
};
@@ -1,25 +0,0 @@
import { AlbumRepository } from 'src/repositories/album.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newAlbumRepositoryMock = (): Mocked<RepositoryInterface<AlbumRepository>> => {
return {
getById: vitest.fn(),
getByAssetId: vitest.fn(),
getMetadataForIds: vitest.fn(),
getOwned: vitest.fn(),
getShared: vitest.fn(),
getNotShared: vitest.fn(),
restoreAll: vitest.fn(),
softDeleteAll: vitest.fn(),
deleteAll: vitest.fn(),
addAssetIds: vitest.fn(),
removeAsset: vitest.fn(),
removeAssetIds: vitest.fn(),
getAssetIds: vitest.fn(),
create: vitest.fn(),
update: vitest.fn(),
delete: vitest.fn(),
updateThumbnails: vitest.fn(),
};
};
@@ -1,14 +0,0 @@
import { ApiKeyRepository } from 'src/repositories/api-key.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newKeyRepositoryMock = (): Mocked<RepositoryInterface<ApiKeyRepository>> => {
return {
create: vitest.fn(),
update: vitest.fn(),
delete: vitest.fn(),
getKey: vitest.fn(),
getById: vitest.fn(),
getByUserId: vitest.fn(),
};
};
@@ -1,10 +0,0 @@
import { AuditRepository } from 'src/repositories/audit.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newAuditRepositoryMock = (): Mocked<RepositoryInterface<AuditRepository>> => {
return {
getAfter: vitest.fn(),
removeBefore: vitest.fn(),
};
};
@@ -1,10 +0,0 @@
import { CronRepository } from 'src/repositories/cron.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newCronRepositoryMock = (): Mocked<RepositoryInterface<CronRepository>> => {
return {
create: vitest.fn(),
update: vitest.fn(),
};
};
@@ -1,12 +0,0 @@
import { DownloadRepository } from 'src/repositories/download.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newDownloadRepositoryMock = (): Mocked<RepositoryInterface<DownloadRepository>> => {
return {
downloadAssetIds: vitest.fn(),
downloadMotionAssetIds: vitest.fn(),
downloadAlbumId: vitest.fn(),
downloadUserId: vitest.fn(),
};
};
@@ -1,17 +0,0 @@
import { EventRepository } from 'src/repositories/event.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newEventRepositoryMock = (): Mocked<RepositoryInterface<EventRepository>> => {
return {
setup: vitest.fn(),
emit: vitest.fn() as any,
clientSend: vitest.fn() as any,
clientBroadcast: vitest.fn() as any,
serverSend: vitest.fn(),
afterInit: vitest.fn(),
handleConnection: vitest.fn(),
handleDisconnect: vitest.fn(),
setAuthFn: vitest.fn(),
};
};
@@ -1,17 +0,0 @@
import { LibraryRepository } from 'src/repositories/library.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newLibraryRepositoryMock = (): Mocked<RepositoryInterface<LibraryRepository>> => {
return {
get: vitest.fn(),
create: vitest.fn(),
delete: vitest.fn(),
softDelete: vitest.fn(),
update: vitest.fn(),
getStatistics: vitest.fn(),
getAllDeleted: vitest.fn(),
getAll: vitest.fn(),
streamAssetIds: vitest.fn(),
};
};
@@ -1,23 +0,0 @@
import { LoggingRepository } from 'src/repositories/logging.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newLoggingRepositoryMock = (): Mocked<RepositoryInterface<LoggingRepository>> => {
return {
setLogLevel: vitest.fn(),
setContext: vitest.fn(),
setAppName: vitest.fn(),
isLevelEnabled: vitest.fn(),
verbose: vitest.fn(),
verboseFn: vitest.fn(),
debug: vitest.fn(),
debugFn: vitest.fn(),
log: vitest.fn(),
warn: vitest.fn(),
error: vitest.fn(),
fatal: vitest.fn(),
};
};
export const newFakeLoggingRepository = () =>
newLoggingRepositoryMock() as RepositoryInterface<LoggingRepository> as LoggingRepository;
@@ -1,11 +0,0 @@
import { MachineLearningRepository } from 'src/repositories/machine-learning.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newMachineLearningRepositoryMock = (): Mocked<RepositoryInterface<MachineLearningRepository>> => {
return {
encodeImage: vitest.fn(),
encodeText: vitest.fn(),
detectFaces: vitest.fn(),
};
};
@@ -1,11 +0,0 @@
import { MapRepository } from 'src/repositories/map.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked } from 'vitest';
export const newMapRepositoryMock = (): Mocked<RepositoryInterface<MapRepository>> => {
return {
init: vitest.fn(),
reverseGeocode: vitest.fn(),
getMapMarkers: vitest.fn(),
};
};
@@ -1,17 +0,0 @@
import { MemoryRepository } from 'src/repositories/memory.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newMemoryRepositoryMock = (): Mocked<RepositoryInterface<MemoryRepository>> => {
return {
search: vitest.fn().mockResolvedValue([]),
get: vitest.fn(),
create: vitest.fn(),
update: vitest.fn(),
delete: vitest.fn(),
getAssetIds: vitest.fn().mockResolvedValue(new Set()),
addAssetIds: vitest.fn(),
removeAssetIds: vitest.fn(),
cleanup: vitest.fn(),
};
};
@@ -1,14 +0,0 @@
import { MoveRepository } from 'src/repositories/move.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newMoveRepositoryMock = (): Mocked<RepositoryInterface<MoveRepository>> => {
return {
create: vitest.fn(),
getByEntity: vitest.fn(),
update: vitest.fn(),
delete: vitest.fn(),
cleanMoveHistory: vitest.fn(),
cleanMoveHistorySingle: vitest.fn(),
};
};
@@ -1,11 +0,0 @@
import { NotificationRepository } from 'src/repositories/notification.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked } from 'vitest';
export const newNotificationRepositoryMock = (): Mocked<RepositoryInterface<NotificationRepository>> => {
return {
renderEmail: vitest.fn(),
sendEmail: vitest.fn().mockResolvedValue({ messageId: 'message-1' }),
verifySmtp: vitest.fn(),
};
};
@@ -1,12 +0,0 @@
import { OAuthRepository } from 'src/repositories/oauth.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked } from 'vitest';
export const newOAuthRepositoryMock = (): Mocked<RepositoryInterface<OAuthRepository>> => {
return {
init: vitest.fn(),
authorize: vitest.fn(),
getLogoutEndpoint: vitest.fn(),
getProfile: vitest.fn(),
};
};
@@ -1,13 +0,0 @@
import { PartnerRepository } from 'src/repositories/partner.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newPartnerRepositoryMock = (): Mocked<RepositoryInterface<PartnerRepository>> => {
return {
create: vitest.fn(),
remove: vitest.fn(),
getAll: vitest.fn().mockResolvedValue([]),
get: vitest.fn(),
update: vitest.fn(),
};
};
@@ -1,41 +0,0 @@
import { PersonRepository } from 'src/repositories/person.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newPersonRepositoryMock = (): Mocked<RepositoryInterface<PersonRepository>> => {
return {
getById: vitest.fn(),
getAll: vitest.fn(),
getAllForUser: vitest.fn(),
getAllWithoutFaces: vitest.fn(),
getByName: vitest.fn(),
getDistinctNames: vitest.fn(),
create: vitest.fn(),
createAll: vitest.fn(),
update: vitest.fn(),
updateAll: vitest.fn(),
delete: vitest.fn(),
deleteFaces: vitest.fn(),
getStatistics: vitest.fn(),
getAllFaces: vitest.fn(),
getFacesByIds: vitest.fn(),
getRandomFace: vitest.fn(),
reassignFaces: vitest.fn(),
unassignFaces: vitest.fn(),
refreshFaces: vitest.fn(),
getFaces: vitest.fn(),
reassignFace: vitest.fn(),
getFaceById: vitest.fn(),
getFaceByIdWithAssets: vitest.fn(),
getNumberOfPeople: vitest.fn(),
getLatestFaceDate: vitest.fn(),
createAssetFace: vitest.fn(),
deleteAssetFace: vitest.fn(),
softDeleteAssetFaces: vitest.fn(),
};
};
@@ -1,9 +0,0 @@
import { ProcessRepository } from 'src/repositories/process.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newProcessRepositoryMock = (): Mocked<RepositoryInterface<ProcessRepository>> => {
return {
spawn: vitest.fn(),
};
};
@@ -1,24 +0,0 @@
import { SearchRepository } from 'src/repositories/search.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newSearchRepositoryMock = (): Mocked<RepositoryInterface<SearchRepository>> => {
return {
searchMetadata: vitest.fn(),
searchSmart: vitest.fn(),
searchDuplicates: vitest.fn(),
searchFaces: vitest.fn(),
searchRandom: vitest.fn(),
upsert: vitest.fn(),
searchPlaces: vitest.fn(),
getAssetsByCity: vitest.fn(),
deleteAllSearchEmbeddings: vitest.fn(),
getDimensionSize: vitest.fn(),
setDimensionSize: vitest.fn(),
getCameraMakes: vitest.fn(),
getCameraModels: vitest.fn(),
getCities: vitest.fn(),
getCountries: vitest.fn(),
getStates: vitest.fn(),
};
};
@@ -1,10 +0,0 @@
import { ServerInfoRepository } from 'src/repositories/server-info.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newServerInfoRepositoryMock = (): Mocked<RepositoryInterface<ServerInfoRepository>> => {
return {
getGitHubRelease: vitest.fn(),
getBuildVersions: vitest.fn(),
};
};
@@ -1,14 +0,0 @@
import { SessionRepository } from 'src/repositories/session.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newSessionRepositoryMock = (): Mocked<RepositoryInterface<SessionRepository>> => {
return {
search: vitest.fn(),
create: vitest.fn() as any,
update: vitest.fn() as any,
delete: vitest.fn(),
getByToken: vitest.fn(),
getByUserId: vitest.fn(),
};
};
@@ -1,14 +0,0 @@
import { SharedLinkRepository } from 'src/repositories/shared-link.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newSharedLinkRepositoryMock = (): Mocked<RepositoryInterface<SharedLinkRepository>> => {
return {
getAll: vitest.fn(),
get: vitest.fn(),
getByKey: vitest.fn(),
create: vitest.fn(),
remove: vitest.fn(),
update: vitest.fn(),
};
};
@@ -1,14 +0,0 @@
import { StackRepository } from 'src/repositories/stack.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newStackRepositoryMock = (): Mocked<RepositoryInterface<StackRepository>> => {
return {
search: vitest.fn(),
create: vitest.fn(),
update: vitest.fn(),
delete: vitest.fn(),
getById: vitest.fn(),
deleteAll: vitest.fn(),
};
};
@@ -1,21 +0,0 @@
import { SyncRepository } from 'src/repositories/sync.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newSyncRepositoryMock = (): Mocked<RepositoryInterface<SyncRepository>> => {
return {
getCheckpoints: vitest.fn(),
upsertCheckpoints: vitest.fn(),
deleteCheckpoints: vitest.fn(),
getUserUpserts: vitest.fn(),
getUserDeletes: vitest.fn(),
getPartnerUpserts: vitest.fn(),
getPartnerDeletes: vitest.fn(),
getPartnerAssetsUpserts: vitest.fn(),
getPartnerAssetDeletes: vitest.fn(),
getAssetDeletes: vitest.fn(),
getAssetUpserts: vitest.fn(),
getAssetExifsUpserts: vitest.fn(),
getPartnerAssetExifsUpserts: vitest.fn(),
};
};
@@ -1,23 +0,0 @@
import { TagRepository } from 'src/repositories/tag.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newTagRepositoryMock = (): Mocked<RepositoryInterface<TagRepository>> => {
return {
getAll: vitest.fn(),
getByValue: vitest.fn(),
upsertValue: vitest.fn(),
replaceAssetTags: vitest.fn(),
get: vitest.fn(),
create: vitest.fn(),
update: vitest.fn(),
delete: vitest.fn(),
getAssetIds: vitest.fn(),
addAssetIds: vitest.fn(),
removeAssetIds: vitest.fn(),
upsertAssetIds: vitest.fn(),
deleteEmptyTags: vitest.fn(),
};
};
@@ -1,12 +0,0 @@
import { TrashRepository } from 'src/repositories/trash.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newTrashRepositoryMock = (): Mocked<RepositoryInterface<TrashRepository>> => {
return {
empty: vitest.fn(),
restore: vitest.fn(),
restoreAll: vitest.fn(),
getDeletedIds: vitest.fn(),
};
};
@@ -1,26 +0,0 @@
import { UserRepository } from 'src/repositories/user.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newUserRepositoryMock = (): Mocked<RepositoryInterface<UserRepository>> => {
return {
get: vitest.fn(),
getMetadata: vitest.fn().mockResolvedValue([]),
getAdmin: vitest.fn(),
getByEmail: vitest.fn(),
getByStorageLabel: vitest.fn(),
getByOAuthId: vitest.fn(),
getUserStats: vitest.fn(),
getList: vitest.fn(),
create: vitest.fn(),
update: vitest.fn(),
delete: vitest.fn(),
restore: vitest.fn(),
getDeletedUsers: vitest.fn(),
hasAdmin: vitest.fn(),
updateUsage: vitest.fn(),
syncUsage: vitest.fn(),
upsertMetadata: vitest.fn(),
deleteMetadata: vitest.fn(),
};
};
@@ -1,11 +0,0 @@
import { VersionHistoryRepository } from 'src/repositories/version-history.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newVersionHistoryRepositoryMock = (): Mocked<RepositoryInterface<VersionHistoryRepository>> => {
return {
getAll: vitest.fn().mockResolvedValue([]),
getLatest: vitest.fn(),
create: vitest.fn(),
};
};
@@ -1,10 +0,0 @@
import { ViewRepository } from 'src/repositories/view-repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newViewRepositoryMock = (): Mocked<RepositoryInterface<ViewRepository>> => {
return {
getAssetsByOriginalPath: vitest.fn(),
getUniqueOriginalPaths: vitest.fn(),
};
};
+26
View File
@@ -42,6 +42,23 @@ const authUserFactory = (authUser: Partial<AuthUser> = {}) => ({
...authUser,
});
const sessionFactory = () => ({
id: newUuid(),
createdAt: newDate(),
updatedAt: newDate(),
updateId: newUpdateId(),
deviceOS: 'android',
deviceType: 'mobile',
token: 'abc123',
userId: newUuid(),
});
const stackFactory = () => ({
id: newUuid(),
ownerId: newUuid(),
primaryAssetId: newUuid(),
});
const userFactory = (user: Partial<User> = {}) => ({
id: newUuid(),
name: 'Test User',
@@ -145,6 +162,12 @@ const memoryFactory = (memory: Partial<MemoryItem> = {}) => ({
...memory,
});
const versionHistoryFactory = () => ({
id: newUuid(),
createdAt: newDate(),
version: '1.123.45',
});
export const factory = {
activity: activityFactory,
apiKey: apiKeyFactory,
@@ -154,5 +177,8 @@ export const factory = {
authUser: authUserFactory,
library: libraryFactory,
memory: memoryFactory,
session: sessionFactory,
stack: stackFactory,
user: userFactory,
versionHistory: versionHistoryFactory,
};
+77 -61
View File
@@ -1,3 +1,4 @@
import { ClassConstructor } from 'class-transformer';
import { Kysely, sql } from 'kysely';
import { PostgresJSDialect } from 'kysely-postgres-js';
import { ChildProcessWithoutNullStreams } from 'node:child_process';
@@ -50,48 +51,59 @@ import { ViewRepository } from 'src/repositories/view-repository';
import { BaseService } from 'src/services/base.service';
import { RepositoryInterface } from 'src/types';
import { IAccessRepositoryMock, newAccessRepositoryMock } from 'test/repositories/access.repository.mock';
import { newActivityRepositoryMock } from 'test/repositories/activity.repository.mock';
import { newAlbumUserRepositoryMock } from 'test/repositories/album-user.repository.mock';
import { newAlbumRepositoryMock } from 'test/repositories/album.repository.mock';
import { newKeyRepositoryMock } from 'test/repositories/api-key.repository.mock';
import { newAssetRepositoryMock } from 'test/repositories/asset.repository.mock';
import { newAuditRepositoryMock } from 'test/repositories/audit.repository.mock';
import { newConfigRepositoryMock } from 'test/repositories/config.repository.mock';
import { newCronRepositoryMock } from 'test/repositories/cron.repository.mock';
import { newCryptoRepositoryMock } from 'test/repositories/crypto.repository.mock';
import { newDatabaseRepositoryMock } from 'test/repositories/database.repository.mock';
import { newDownloadRepositoryMock } from 'test/repositories/download.repository.mock';
import { newEventRepositoryMock } from 'test/repositories/event.repository.mock';
import { newJobRepositoryMock } from 'test/repositories/job.repository.mock';
import { newLibraryRepositoryMock } from 'test/repositories/library.repository.mock';
import { newLoggingRepositoryMock } from 'test/repositories/logger.repository.mock';
import { newMachineLearningRepositoryMock } from 'test/repositories/machine-learning.repository.mock';
import { newMapRepositoryMock } from 'test/repositories/map.repository.mock';
import { newMediaRepositoryMock } from 'test/repositories/media.repository.mock';
import { newMemoryRepositoryMock } from 'test/repositories/memory.repository.mock';
import { newMetadataRepositoryMock } from 'test/repositories/metadata.repository.mock';
import { newMoveRepositoryMock } from 'test/repositories/move.repository.mock';
import { newNotificationRepositoryMock } from 'test/repositories/notification.repository.mock';
import { newOAuthRepositoryMock } from 'test/repositories/oauth.repository.mock';
import { newPartnerRepositoryMock } from 'test/repositories/partner.repository.mock';
import { newPersonRepositoryMock } from 'test/repositories/person.repository.mock';
import { newProcessRepositoryMock } from 'test/repositories/process.repository.mock';
import { newSearchRepositoryMock } from 'test/repositories/search.repository.mock';
import { newServerInfoRepositoryMock } from 'test/repositories/server-info.repository.mock';
import { newSessionRepositoryMock } from 'test/repositories/session.repository.mock';
import { newSharedLinkRepositoryMock } from 'test/repositories/shared-link.repository.mock';
import { newStackRepositoryMock } from 'test/repositories/stack.repository.mock';
import { newStorageRepositoryMock } from 'test/repositories/storage.repository.mock';
import { newSyncRepositoryMock } from 'test/repositories/sync.repository.mock';
import { newSystemMetadataRepositoryMock } from 'test/repositories/system-metadata.repository.mock';
import { newTagRepositoryMock } from 'test/repositories/tag.repository.mock';
import { ITelemetryRepositoryMock, newTelemetryRepositoryMock } from 'test/repositories/telemetry.repository.mock';
import { newTrashRepositoryMock } from 'test/repositories/trash.repository.mock';
import { newUserRepositoryMock } from 'test/repositories/user.repository.mock';
import { newVersionHistoryRepositoryMock } from 'test/repositories/version-history.repository.mock';
import { newViewRepositoryMock } from 'test/repositories/view.repository.mock';
import { Readable } from 'typeorm/platform/PlatformTools';
import { Mocked, vitest } from 'vitest';
import { assert, Mocked, vitest } from 'vitest';
const mockFn = (label: string, { strict }: { strict: boolean }) => {
const message = `Called a mock function without a mock implementation (${label})`;
return vitest.fn().mockImplementation(() => {
if (strict) {
assert.fail(message);
} else {
// console.warn(message);
}
});
};
export const automock = <T>(
Dependency: ClassConstructor<T>,
options?: {
args?: ConstructorParameters<ClassConstructor<T>>;
strict?: boolean;
},
): Mocked<T> => {
const mock: Record<string, unknown> = {};
const strict = options?.strict ?? true;
const args = options?.args ?? [];
const instance = new Dependency(...args);
for (const property of Object.getOwnPropertyNames(Dependency.prototype)) {
if (property === 'constructor') {
continue;
}
const label = `${Dependency.name}.${property}`;
// console.log(`Automocking ${label}`);
const target = instance[property as keyof T];
if (typeof target === 'function') {
mock[property] = mockFn(label, { strict });
continue;
}
}
return mock as Mocked<T>;
};
export type ServiceOverrides = {
access: AccessRepository;
@@ -153,48 +165,52 @@ export const newTestService = <T extends BaseService>(
Service: Constructor<T, BaseServiceArgs>,
overrides: Partial<ServiceOverrides> = {},
) => {
const loggerMock = { setContext: () => {} };
const configMock = { getEnv: () => ({}) };
const mocks: ServiceMocks = {
access: newAccessRepositoryMock(),
logger: newLoggingRepositoryMock(),
cron: newCronRepositoryMock(),
logger: automock(LoggingRepository, { args: [, configMock], strict: false }),
cron: automock(CronRepository, { args: [, loggerMock] }),
crypto: newCryptoRepositoryMock(),
activity: newActivityRepositoryMock(),
audit: newAuditRepositoryMock(),
album: newAlbumRepositoryMock(),
albumUser: newAlbumUserRepositoryMock(),
activity: automock(ActivityRepository),
audit: automock(AuditRepository),
album: automock(AlbumRepository, { strict: false }),
albumUser: automock(AlbumUserRepository),
asset: newAssetRepositoryMock(),
config: newConfigRepositoryMock(),
database: newDatabaseRepositoryMock(),
downloadRepository: newDownloadRepositoryMock(),
event: newEventRepositoryMock(),
downloadRepository: automock(DownloadRepository, { strict: false }),
event: automock(EventRepository, { args: [, , loggerMock], strict: false }),
job: newJobRepositoryMock(),
apiKey: newKeyRepositoryMock(),
library: newLibraryRepositoryMock(),
machineLearning: newMachineLearningRepositoryMock(),
map: newMapRepositoryMock(),
apiKey: automock(ApiKeyRepository),
library: automock(LibraryRepository, { strict: false }),
machineLearning: automock(MachineLearningRepository, { args: [loggerMock], strict: false }),
map: automock(MapRepository, { args: [undefined, undefined, { setContext: () => {} }] }),
media: newMediaRepositoryMock(),
memory: newMemoryRepositoryMock(),
memory: automock(MemoryRepository),
metadata: newMetadataRepositoryMock(),
move: newMoveRepositoryMock(),
notification: newNotificationRepositoryMock(),
oauth: newOAuthRepositoryMock(),
partner: newPartnerRepositoryMock(),
person: newPersonRepositoryMock(),
process: newProcessRepositoryMock(),
search: newSearchRepositoryMock(),
serverInfo: newServerInfoRepositoryMock(),
session: newSessionRepositoryMock(),
sharedLink: newSharedLinkRepositoryMock(),
stack: newStackRepositoryMock(),
move: automock(MoveRepository, { strict: false }),
notification: automock(NotificationRepository, { args: [loggerMock] }),
oauth: automock(OAuthRepository, { args: [loggerMock] }),
partner: automock(PartnerRepository, { strict: false }),
person: automock(PersonRepository, { strict: false }),
process: automock(ProcessRepository, { args: [loggerMock] }),
search: automock(SearchRepository, { args: [loggerMock], strict: false }),
serverInfo: automock(ServerInfoRepository, { args: [, loggerMock], strict: false }),
session: automock(SessionRepository),
sharedLink: automock(SharedLinkRepository),
stack: automock(StackRepository),
storage: newStorageRepositoryMock(),
sync: newSyncRepositoryMock(),
sync: automock(SyncRepository),
systemMetadata: newSystemMetadataRepositoryMock(),
tag: newTagRepositoryMock(),
// systemMetadata: automock(SystemMetadataRepository, { strict: false }),
tag: automock(TagRepository, { args: [, loggerMock], strict: false }),
telemetry: newTelemetryRepositoryMock(),
trash: newTrashRepositoryMock(),
user: newUserRepositoryMock(),
versionHistory: newVersionHistoryRepositoryMock(),
view: newViewRepositoryMock(),
trash: automock(TrashRepository),
user: automock(UserRepository, { strict: false }),
versionHistory: automock(VersionHistoryRepository),
view: automock(ViewRepository),
};
const sut = new Service(