refactor: test utils (#16588)

This commit is contained in:
Jason Rasmussen 2025-03-04 11:15:41 -05:00 committed by GitHub
parent 1423cfd53c
commit 63c01b78e2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 245 additions and 216 deletions

View File

@ -15,7 +15,7 @@ export class APIKeyService extends BaseService {
throw new BadRequestException('Cannot grant permissions you do not have'); throw new BadRequestException('Cannot grant permissions you do not have');
} }
const entity = await this.keyRepository.create({ const entity = await this.apiKeyRepository.create({
key: this.cryptoRepository.hashSha256(secret), key: this.cryptoRepository.hashSha256(secret),
name: dto.name || 'API Key', name: dto.name || 'API Key',
userId: auth.user.id, userId: auth.user.id,
@ -26,27 +26,27 @@ export class APIKeyService extends BaseService {
} }
async update(auth: AuthDto, id: string, dto: APIKeyUpdateDto): Promise<APIKeyResponseDto> { async update(auth: AuthDto, id: string, dto: APIKeyUpdateDto): Promise<APIKeyResponseDto> {
const exists = await this.keyRepository.getById(auth.user.id, id); const exists = await this.apiKeyRepository.getById(auth.user.id, id);
if (!exists) { if (!exists) {
throw new BadRequestException('API Key not found'); throw new BadRequestException('API Key not found');
} }
const key = await this.keyRepository.update(auth.user.id, id, { name: dto.name }); const key = await this.apiKeyRepository.update(auth.user.id, id, { name: dto.name });
return this.map(key); return this.map(key);
} }
async delete(auth: AuthDto, id: string): Promise<void> { async delete(auth: AuthDto, id: string): Promise<void> {
const exists = await this.keyRepository.getById(auth.user.id, id); const exists = await this.apiKeyRepository.getById(auth.user.id, id);
if (!exists) { if (!exists) {
throw new BadRequestException('API Key not found'); throw new BadRequestException('API Key not found');
} }
await this.keyRepository.delete(auth.user.id, id); await this.apiKeyRepository.delete(auth.user.id, id);
} }
async getById(auth: AuthDto, id: string): Promise<APIKeyResponseDto> { async getById(auth: AuthDto, id: string): Promise<APIKeyResponseDto> {
const key = await this.keyRepository.getById(auth.user.id, id); const key = await this.apiKeyRepository.getById(auth.user.id, id);
if (!key) { if (!key) {
throw new BadRequestException('API Key not found'); throw new BadRequestException('API Key not found');
} }
@ -54,7 +54,7 @@ export class APIKeyService extends BaseService {
} }
async getAll(auth: AuthDto): Promise<APIKeyResponseDto[]> { async getAll(auth: AuthDto): Promise<APIKeyResponseDto[]> {
const keys = await this.keyRepository.getByUserId(auth.user.id); const keys = await this.apiKeyRepository.getByUserId(auth.user.id);
return keys.map((key) => this.map(key)); return keys.map((key) => this.map(key));
} }

View File

@ -307,7 +307,7 @@ export class AuthService extends BaseService {
private async validateApiKey(key: string): Promise<AuthDto> { private async validateApiKey(key: string): Promise<AuthDto> {
const hashedKey = this.cryptoRepository.hashSha256(key); const hashedKey = this.cryptoRepository.hashSha256(key);
const apiKey = await this.keyRepository.getKey(hashedKey); const apiKey = await this.apiKeyRepository.getKey(hashedKey);
if (apiKey?.user) { if (apiKey?.user) {
return { return {
user: apiKey.user, user: apiKey.user,

View File

@ -57,17 +57,17 @@ export class BaseService {
protected logger: LoggingRepository, protected logger: LoggingRepository,
protected accessRepository: AccessRepository, protected accessRepository: AccessRepository,
protected activityRepository: ActivityRepository, protected activityRepository: ActivityRepository,
protected auditRepository: AuditRepository,
protected albumRepository: AlbumRepository, protected albumRepository: AlbumRepository,
protected albumUserRepository: AlbumUserRepository, protected albumUserRepository: AlbumUserRepository,
protected apiKeyRepository: ApiKeyRepository,
protected assetRepository: AssetRepository, protected assetRepository: AssetRepository,
protected auditRepository: AuditRepository,
protected configRepository: ConfigRepository, protected configRepository: ConfigRepository,
protected cronRepository: CronRepository, protected cronRepository: CronRepository,
protected cryptoRepository: CryptoRepository, protected cryptoRepository: CryptoRepository,
protected databaseRepository: DatabaseRepository, protected databaseRepository: DatabaseRepository,
protected eventRepository: EventRepository, protected eventRepository: EventRepository,
protected jobRepository: JobRepository, protected jobRepository: JobRepository,
protected keyRepository: ApiKeyRepository,
protected libraryRepository: LibraryRepository, protected libraryRepository: LibraryRepository,
protected machineLearningRepository: MachineLearningRepository, protected machineLearningRepository: MachineLearningRepository,
protected mapRepository: MapRepository, protected mapRepository: MapRepository,

View File

@ -4,13 +4,38 @@ import { Writable } from 'node:stream';
import { Assets, DB, Partners, Sessions, Users } from 'src/db'; import { Assets, DB, Partners, Sessions, Users } from 'src/db';
import { AuthDto } from 'src/dtos/auth.dto'; import { AuthDto } from 'src/dtos/auth.dto';
import { AssetType } from 'src/enum'; import { AssetType } from 'src/enum';
import { AccessRepository } from 'src/repositories/access.repository';
import { ActivityRepository } from 'src/repositories/activity.repository';
import { AlbumRepository } from 'src/repositories/album.repository'; import { AlbumRepository } from 'src/repositories/album.repository';
import { ApiKeyRepository } from 'src/repositories/api-key.repository';
import { AssetRepository } from 'src/repositories/asset.repository'; import { AssetRepository } from 'src/repositories/asset.repository';
import { AuditRepository } from 'src/repositories/audit.repository';
import { ConfigRepository } from 'src/repositories/config.repository';
import { LibraryRepository } from 'src/repositories/library.repository';
import { LoggingRepository } from 'src/repositories/logging.repository';
import { MachineLearningRepository } from 'src/repositories/machine-learning.repository';
import { MediaRepository } from 'src/repositories/media.repository';
import { MetadataRepository } from 'src/repositories/metadata.repository';
import { MoveRepository } from 'src/repositories/move.repository';
import { NotificationRepository } from 'src/repositories/notification.repository';
import { OAuthRepository } from 'src/repositories/oauth.repository';
import { PartnerRepository } from 'src/repositories/partner.repository'; import { PartnerRepository } from 'src/repositories/partner.repository';
import { PersonRepository } from 'src/repositories/person.repository';
import { ProcessRepository } from 'src/repositories/process.repository';
import { SearchRepository } from 'src/repositories/search.repository';
import { ServerInfoRepository } from 'src/repositories/server-info.repository';
import { SessionRepository } from 'src/repositories/session.repository'; import { SessionRepository } from 'src/repositories/session.repository';
import { SharedLinkRepository } from 'src/repositories/shared-link.repository';
import { StackRepository } from 'src/repositories/stack.repository';
import { StorageRepository } from 'src/repositories/storage.repository';
import { SyncRepository } from 'src/repositories/sync.repository'; import { SyncRepository } from 'src/repositories/sync.repository';
import { TelemetryRepository } from 'src/repositories/telemetry.repository';
import { TrashRepository } from 'src/repositories/trash.repository';
import { UserRepository } from 'src/repositories/user.repository'; import { UserRepository } from 'src/repositories/user.repository';
import { VersionHistoryRepository } from 'src/repositories/version-history.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';
class CustomWritable extends Writable { class CustomWritable extends Writable {
private data = ''; private data = '';
@ -157,22 +182,71 @@ export class TestFactory {
} }
export class TestContext { export class TestContext {
userRepository: UserRepository; access: AccessRepository;
assetRepository: AssetRepository; logger: LoggingRepository;
albumRepository: AlbumRepository; activity: ActivityRepository;
sessionRepository: SessionRepository; album: AlbumRepository;
syncRepository: SyncRepository; apiKey: ApiKeyRepository;
partnerRepository: PartnerRepository; asset: AssetRepository;
versionHistoryRepository: VersionHistoryRepository; audit: AuditRepository;
config: ConfigRepository;
library: LibraryRepository;
machineLearning: MachineLearningRepository;
media: MediaRepository;
metadata: MetadataRepository;
move: MoveRepository;
notification: NotificationRepository;
oauth: OAuthRepository;
partner: PartnerRepository;
person: PersonRepository;
process: ProcessRepository;
search: SearchRepository;
serverInfo: ServerInfoRepository;
session: SessionRepository;
sharedLink: SharedLinkRepository;
stack: StackRepository;
storage: StorageRepository;
sync: SyncRepository;
telemetry: TelemetryRepository;
trash: TrashRepository;
user: UserRepository;
versionHistory: VersionHistoryRepository;
view: ViewRepository;
private constructor(private db: Kysely<DB>) { private constructor(private db: Kysely<DB>) {
this.userRepository = new UserRepository(this.db); const logger = newLoggingRepositoryMock() as unknown as LoggingRepository;
this.assetRepository = new AssetRepository(this.db); const config = new ConfigRepository();
this.albumRepository = new AlbumRepository(this.db);
this.sessionRepository = new SessionRepository(this.db); this.access = new AccessRepository(this.db);
this.syncRepository = new SyncRepository(this.db); this.logger = logger;
this.partnerRepository = new PartnerRepository(this.db); this.activity = new ActivityRepository(this.db);
this.versionHistoryRepository = new VersionHistoryRepository(this.db); this.album = new AlbumRepository(this.db);
this.apiKey = new ApiKeyRepository(this.db);
this.asset = new AssetRepository(this.db);
this.audit = new AuditRepository(this.db);
this.config = config;
this.library = new LibraryRepository(this.db);
this.machineLearning = new MachineLearningRepository(logger);
this.media = new MediaRepository(logger);
this.metadata = new MetadataRepository(logger);
this.move = new MoveRepository(this.db);
this.notification = new NotificationRepository(logger);
this.oauth = new OAuthRepository(logger);
this.partner = new PartnerRepository(this.db);
this.person = new PersonRepository(this.db);
this.process = new ProcessRepository(logger);
this.search = new SearchRepository(logger, this.db);
this.serverInfo = new ServerInfoRepository(config, logger);
this.session = new SessionRepository(this.db);
this.sharedLink = new SharedLinkRepository(this.db);
this.stack = new StackRepository(this.db);
this.storage = new StorageRepository(logger);
this.sync = new SyncRepository(this.db);
this.telemetry = newTelemetryRepositoryMock() as unknown as TelemetryRepository;
this.trash = new TrashRepository(this.db);
this.user = new UserRepository(this.db);
this.versionHistory = new VersionHistoryRepository(this.db);
this.view = new ViewRepository(this.db);
} }
static from(db: Kysely<DB>) { static from(db: Kysely<DB>) {
@ -184,18 +258,18 @@ export class TestContext {
} }
createUser(user: User = {}) { createUser(user: User = {}) {
return this.userRepository.create(TestFactory.user(user)); return this.user.create(TestFactory.user(user));
} }
createPartner(partner: Partner) { createPartner(partner: Partner) {
return this.partnerRepository.create(TestFactory.partner(partner)); return this.partner.create(TestFactory.partner(partner));
} }
createAsset(asset: Asset) { createAsset(asset: Asset) {
return this.assetRepository.create(TestFactory.asset(asset)); return this.asset.create(TestFactory.asset(asset));
} }
createSession(session: Session) { createSession(session: Session) {
return this.sessionRepository.create(TestFactory.session(session)); return this.session.create(TestFactory.session(session));
} }
} }

View File

@ -34,7 +34,7 @@ describe(MetadataService.name, () => {
let mocks: ServiceMocks; let mocks: ServiceMocks;
beforeEach(() => { beforeEach(() => {
({ sut, mocks } = newTestService(MetadataService, { metadataRepository })); ({ sut, mocks } = newTestService(MetadataService, { metadata: metadataRepository }));
mocks.storage.stat.mockResolvedValue({ size: 123_456 } as Stats); mocks.storage.stat.mockResolvedValue({ size: 123_456 } as Stats);

View File

@ -37,7 +37,7 @@ describe(SyncService.name, () => {
it('should detect and sync the first user', async () => { it('should detect and sync the first user', async () => {
const { context, auth, sut, testSync } = await setup(); const { context, auth, sut, testSync } = await setup();
const user = await context.userRepository.get(auth.user.id, { withDeleted: false }); const user = await context.user.get(auth.user.id, { withDeleted: false });
if (!user) { if (!user) {
expect.fail('First user should exist'); expect.fail('First user should exist');
} }
@ -109,7 +109,7 @@ describe(SyncService.name, () => {
const { auth, context, sut, testSync } = await setup(); const { auth, context, sut, testSync } = await setup();
const user = await context.createUser(); const user = await context.createUser();
await context.userRepository.delete({ id: user.id }, true); await context.user.delete({ id: user.id }, true);
const response = await testSync(auth, [SyncRequestType.UsersV1]); const response = await testSync(auth, [SyncRequestType.UsersV1]);
@ -167,7 +167,7 @@ describe(SyncService.name, () => {
const acks = [initialSyncResponse[0].ack]; const acks = [initialSyncResponse[0].ack];
await sut.setAcks(auth, { acks }); await sut.setAcks(auth, { acks });
const updated = await context.userRepository.update(auth.user.id, { name: 'new name' }); const updated = await context.user.update(auth.user.id, { name: 'new name' });
const updatedSyncResponse = await testSync(auth, [SyncRequestType.UsersV1]); const updatedSyncResponse = await testSync(auth, [SyncRequestType.UsersV1]);
@ -230,7 +230,7 @@ describe(SyncService.name, () => {
const user2 = await context.createUser(); const user2 = await context.createUser();
const partner = await context.createPartner({ sharedById: user2.id, sharedWithId: user1.id }); const partner = await context.createPartner({ sharedById: user2.id, sharedWithId: user1.id });
await context.partnerRepository.remove(partner); await context.partner.remove(partner);
const response = await testSync(auth, [SyncRequestType.PartnersV1]); const response = await testSync(auth, [SyncRequestType.PartnersV1]);
@ -326,7 +326,7 @@ describe(SyncService.name, () => {
const acks = [initialSyncResponse[0].ack]; const acks = [initialSyncResponse[0].ack];
await sut.setAcks(auth, { acks }); await sut.setAcks(auth, { acks });
const updated = await context.partnerRepository.update( const updated = await context.partner.update(
{ sharedById: partner.sharedById, sharedWithId: partner.sharedWithId }, { sharedById: partner.sharedById, sharedWithId: partner.sharedWithId },
{ inTimeline: true }, { inTimeline: true },
); );

View File

@ -21,12 +21,12 @@ describe(VersionService.name, () => {
it('record the current version on startup', async () => { it('record the current version on startup', async () => {
const { context, sut } = await setup(); const { context, sut } = await setup();
const itemsBefore = await context.versionHistoryRepository.getAll(); const itemsBefore = await context.versionHistory.getAll();
expect(itemsBefore).toHaveLength(0); expect(itemsBefore).toHaveLength(0);
await sut.onBootstrap(); await sut.onBootstrap();
const itemsAfter = await context.versionHistoryRepository.getAll(); const itemsAfter = await context.versionHistory.getAll();
expect(itemsAfter).toHaveLength(1); expect(itemsAfter).toHaveLength(1);
expect(itemsAfter[0]).toEqual({ expect(itemsAfter[0]).toEqual({
createdAt: expect.any(Date), createdAt: expect.any(Date),
@ -38,7 +38,7 @@ describe(VersionService.name, () => {
it('should queue memory creation when upgrading from 1.128.0', async () => { it('should queue memory creation when upgrading from 1.128.0', async () => {
const { context, jobMock, sut } = await setup(); const { context, jobMock, sut } = await setup();
await context.versionHistoryRepository.create({ version: 'v1.128.0' }); await context.versionHistory.create({ version: 'v1.128.0' });
await sut.onBootstrap(); await sut.onBootstrap();
expect(jobMock.queue).toHaveBeenCalledWith({ name: JobName.MEMORIES_CREATE }); expect(jobMock.queue).toHaveBeenCalledWith({ name: JobName.MEMORIES_CREATE });
@ -47,7 +47,7 @@ describe(VersionService.name, () => {
it('should not queue memory creation when upgrading from 1.129.0', async () => { it('should not queue memory creation when upgrading from 1.129.0', async () => {
const { context, jobMock, sut } = await setup(); const { context, jobMock, sut } = await setup();
await context.versionHistoryRepository.create({ version: 'v1.129.0' }); await context.versionHistory.create({ version: 'v1.129.0' });
await sut.onBootstrap(); await sut.onBootstrap();
expect(jobMock.queue).not.toHaveBeenCalled(); expect(jobMock.queue).not.toHaveBeenCalled();

View File

@ -6,7 +6,6 @@ import { parse } from 'pg-connection-string';
import { PNG } from 'pngjs'; import { PNG } from 'pngjs';
import postgres, { Notice } from 'postgres'; import postgres, { Notice } from 'postgres';
import { DB } from 'src/db'; import { DB } from 'src/db';
import { ImmichWorker } from 'src/enum';
import { AccessRepository } from 'src/repositories/access.repository'; import { AccessRepository } from 'src/repositories/access.repository';
import { ActivityRepository } from 'src/repositories/activity.repository'; import { ActivityRepository } from 'src/repositories/activity.repository';
import { AlbumUserRepository } from 'src/repositories/album-user.repository'; import { AlbumUserRepository } from 'src/repositories/album-user.repository';
@ -92,198 +91,154 @@ import { newViewRepositoryMock } from 'test/repositories/view.repository.mock';
import { Readable } from 'typeorm/platform/PlatformTools'; import { Readable } from 'typeorm/platform/PlatformTools';
import { Mocked, vitest } from 'vitest'; import { Mocked, vitest } from 'vitest';
type Overrides = { export type ServiceOverrides = {
worker?: ImmichWorker; access: AccessRepository;
metadataRepository?: MetadataRepository; activity: ActivityRepository;
syncRepository?: SyncRepository; album: AlbumRepository;
userRepository?: UserRepository; albumUser: AlbumUserRepository;
versionHistoryRepository?: VersionHistoryRepository; apiKey: ApiKeyRepository;
audit: AuditRepository;
asset: AssetRepository;
config: ConfigRepository;
cron: CronRepository;
crypto: CryptoRepository;
database: DatabaseRepository;
event: EventRepository;
job: JobRepository;
library: LibraryRepository;
logger: LoggingRepository;
machineLearning: MachineLearningRepository;
map: MapRepository;
media: MediaRepository;
memory: MemoryRepository;
metadata: MetadataRepository;
move: MoveRepository;
notification: NotificationRepository;
oauth: OAuthRepository;
partner: PartnerRepository;
person: PersonRepository;
process: ProcessRepository;
search: SearchRepository;
serverInfo: ServerInfoRepository;
session: SessionRepository;
sharedLink: SharedLinkRepository;
stack: StackRepository;
storage: StorageRepository;
sync: SyncRepository;
systemMetadata: SystemMetadataRepository;
tag: TagRepository;
telemetry: TelemetryRepository;
trash: TrashRepository;
user: UserRepository;
versionHistory: VersionHistoryRepository;
view: ViewRepository;
}; };
type As<T> = T extends RepositoryInterface<infer U> ? U : never;
type IAccessRepository = { [K in keyof AccessRepository]: RepositoryInterface<AccessRepository[K]> };
export type ServiceMocks = {
[K in keyof Omit<ServiceOverrides, 'access' | 'telemetry'>]: Mocked<RepositoryInterface<ServiceOverrides[K]>>;
} & { access: IAccessRepositoryMock; telemetry: ITelemetryRepositoryMock };
type BaseServiceArgs = ConstructorParameters<typeof BaseService>; type BaseServiceArgs = ConstructorParameters<typeof BaseService>;
type Constructor<Type, Args extends Array<any>> = { type Constructor<Type, Args extends Array<any>> = {
new (...deps: Args): Type; new (...deps: Args): Type;
}; };
type IAccessRepository = { [K in keyof AccessRepository]: RepositoryInterface<AccessRepository[K]> };
export type ServiceMocks = {
access: IAccessRepositoryMock;
activity: Mocked<RepositoryInterface<ActivityRepository>>;
album: Mocked<RepositoryInterface<AlbumRepository>>;
albumUser: Mocked<RepositoryInterface<AlbumUserRepository>>;
apiKey: Mocked<RepositoryInterface<ApiKeyRepository>>;
audit: Mocked<RepositoryInterface<AuditRepository>>;
asset: Mocked<RepositoryInterface<AssetRepository>>;
config: Mocked<RepositoryInterface<ConfigRepository>>;
cron: Mocked<RepositoryInterface<CronRepository>>;
crypto: Mocked<RepositoryInterface<CryptoRepository>>;
database: Mocked<RepositoryInterface<DatabaseRepository>>;
event: Mocked<RepositoryInterface<EventRepository>>;
job: Mocked<RepositoryInterface<JobRepository>>;
library: Mocked<RepositoryInterface<LibraryRepository>>;
logger: Mocked<RepositoryInterface<LoggingRepository>>;
machineLearning: Mocked<RepositoryInterface<MachineLearningRepository>>;
map: Mocked<RepositoryInterface<MapRepository>>;
media: Mocked<RepositoryInterface<MediaRepository>>;
memory: Mocked<RepositoryInterface<MemoryRepository>>;
metadata: Mocked<RepositoryInterface<MetadataRepository>>;
move: Mocked<RepositoryInterface<MoveRepository>>;
notification: Mocked<RepositoryInterface<NotificationRepository>>;
oauth: Mocked<RepositoryInterface<OAuthRepository>>;
partner: Mocked<RepositoryInterface<PartnerRepository>>;
person: Mocked<RepositoryInterface<PersonRepository>>;
process: Mocked<RepositoryInterface<ProcessRepository>>;
search: Mocked<RepositoryInterface<SearchRepository>>;
serverInfo: Mocked<RepositoryInterface<ServerInfoRepository>>;
session: Mocked<RepositoryInterface<SessionRepository>>;
sharedLink: Mocked<RepositoryInterface<SharedLinkRepository>>;
stack: Mocked<RepositoryInterface<StackRepository>>;
storage: Mocked<RepositoryInterface<StorageRepository>>;
systemMetadata: Mocked<RepositoryInterface<SystemMetadataRepository>>;
tag: Mocked<RepositoryInterface<TagRepository>>;
telemetry: ITelemetryRepositoryMock;
trash: Mocked<RepositoryInterface<TrashRepository>>;
user: Mocked<RepositoryInterface<UserRepository>>;
versionHistory: Mocked<RepositoryInterface<VersionHistoryRepository>>;
view: Mocked<RepositoryInterface<ViewRepository>>;
};
export const newTestService = <T extends BaseService>( export const newTestService = <T extends BaseService>(
Service: Constructor<T, BaseServiceArgs>, Service: Constructor<T, BaseServiceArgs>,
overrides?: Overrides, overrides: Partial<ServiceOverrides> = {},
) => { ) => {
const { metadataRepository, userRepository, syncRepository, versionHistoryRepository } = overrides || {}; const mocks: ServiceMocks = {
access: newAccessRepositoryMock(),
const accessMock = newAccessRepositoryMock(); logger: newLoggingRepositoryMock(),
const loggerMock = newLoggingRepositoryMock(); cron: newCronRepositoryMock(),
const cronMock = newCronRepositoryMock(); crypto: newCryptoRepositoryMock(),
const cryptoMock = newCryptoRepositoryMock(); activity: newActivityRepositoryMock(),
const activityMock = newActivityRepositoryMock(); audit: newAuditRepositoryMock(),
const auditMock = newAuditRepositoryMock(); album: newAlbumRepositoryMock(),
const albumMock = newAlbumRepositoryMock(); albumUser: newAlbumUserRepositoryMock(),
const albumUserMock = newAlbumUserRepositoryMock(); asset: newAssetRepositoryMock(),
const assetMock = newAssetRepositoryMock(); config: newConfigRepositoryMock(),
const configMock = newConfigRepositoryMock(); database: newDatabaseRepositoryMock(),
const databaseMock = newDatabaseRepositoryMock(); event: newEventRepositoryMock(),
const eventMock = newEventRepositoryMock(); job: newJobRepositoryMock(),
const jobMock = newJobRepositoryMock(); apiKey: newKeyRepositoryMock(),
const apiKeyMock = newKeyRepositoryMock(); library: newLibraryRepositoryMock(),
const libraryMock = newLibraryRepositoryMock(); machineLearning: newMachineLearningRepositoryMock(),
const machineLearningMock = newMachineLearningRepositoryMock(); map: newMapRepositoryMock(),
const mapMock = newMapRepositoryMock(); media: newMediaRepositoryMock(),
const mediaMock = newMediaRepositoryMock(); memory: newMemoryRepositoryMock(),
const memoryMock = newMemoryRepositoryMock(); metadata: newMetadataRepositoryMock(),
const metadataMock = (metadataRepository || newMetadataRepositoryMock()) as Mocked< move: newMoveRepositoryMock(),
RepositoryInterface<MetadataRepository> notification: newNotificationRepositoryMock(),
>; oauth: newOAuthRepositoryMock(),
const moveMock = newMoveRepositoryMock(); partner: newPartnerRepositoryMock(),
const notificationMock = newNotificationRepositoryMock(); person: newPersonRepositoryMock(),
const oauthMock = newOAuthRepositoryMock(); process: newProcessRepositoryMock(),
const partnerMock = newPartnerRepositoryMock(); search: newSearchRepositoryMock(),
const personMock = newPersonRepositoryMock(); serverInfo: newServerInfoRepositoryMock(),
const processMock = newProcessRepositoryMock(); session: newSessionRepositoryMock(),
const searchMock = newSearchRepositoryMock(); sharedLink: newSharedLinkRepositoryMock(),
const serverInfoMock = newServerInfoRepositoryMock(); stack: newStackRepositoryMock(),
const sessionMock = newSessionRepositoryMock(); storage: newStorageRepositoryMock(),
const sharedLinkMock = newSharedLinkRepositoryMock(); sync: newSyncRepositoryMock(),
const stackMock = newStackRepositoryMock(); systemMetadata: newSystemMetadataRepositoryMock(),
const storageMock = newStorageRepositoryMock(); tag: newTagRepositoryMock(),
const syncMock = (syncRepository || newSyncRepositoryMock()) as Mocked<RepositoryInterface<SyncRepository>>; telemetry: newTelemetryRepositoryMock(),
const systemMock = newSystemMetadataRepositoryMock(); trash: newTrashRepositoryMock(),
const tagMock = newTagRepositoryMock(); user: newUserRepositoryMock(),
const telemetryMock = newTelemetryRepositoryMock(); versionHistory: newVersionHistoryRepositoryMock(),
const trashMock = newTrashRepositoryMock(); view: newViewRepositoryMock(),
const userMock = (userRepository || newUserRepositoryMock()) as Mocked<RepositoryInterface<UserRepository>>; };
const versionHistoryMock = newVersionHistoryRepositoryMock();
const viewMock = newViewRepositoryMock();
const sut = new Service( const sut = new Service(
loggerMock as RepositoryInterface<LoggingRepository> as LoggingRepository, overrides.logger || (mocks.logger as As<LoggingRepository>),
accessMock as IAccessRepository as AccessRepository, overrides.access || (mocks.access as IAccessRepository as AccessRepository),
activityMock as RepositoryInterface<ActivityRepository> as ActivityRepository, overrides.activity || (mocks.activity as As<ActivityRepository>),
auditMock as RepositoryInterface<AuditRepository> as AuditRepository, overrides.album || (mocks.album as As<AlbumRepository>),
albumMock as RepositoryInterface<AlbumRepository> as AlbumRepository, overrides.albumUser || (mocks.albumUser as As<AlbumUserRepository>),
albumUserMock as RepositoryInterface<AlbumUserRepository> as AlbumUserRepository, overrides.apiKey || (mocks.apiKey as As<ApiKeyRepository>),
assetMock as RepositoryInterface<AssetRepository> as AssetRepository, overrides.asset || (mocks.asset as As<AssetRepository>),
configMock as RepositoryInterface<ConfigRepository> as ConfigRepository, overrides.audit || (mocks.audit as As<AuditRepository>),
cronMock as RepositoryInterface<CronRepository> as CronRepository, overrides.config || (mocks.config as As<ConfigRepository> as ConfigRepository),
cryptoMock as RepositoryInterface<CryptoRepository> as CryptoRepository, overrides.cron || (mocks.cron as As<CronRepository>),
databaseMock as RepositoryInterface<DatabaseRepository> as DatabaseRepository, overrides.crypto || (mocks.crypto as As<CryptoRepository>),
eventMock as RepositoryInterface<EventRepository> as EventRepository, overrides.database || (mocks.database as As<DatabaseRepository>),
jobMock as RepositoryInterface<JobRepository> as JobRepository, overrides.event || (mocks.event as As<EventRepository>),
apiKeyMock as RepositoryInterface<ApiKeyRepository> as ApiKeyRepository, overrides.job || (mocks.job as As<JobRepository>),
libraryMock as RepositoryInterface<LibraryRepository> as LibraryRepository, overrides.library || (mocks.library as As<LibraryRepository>),
machineLearningMock as RepositoryInterface<MachineLearningRepository> as MachineLearningRepository, overrides.machineLearning || (mocks.machineLearning as As<MachineLearningRepository>),
mapMock as RepositoryInterface<MapRepository> as MapRepository, overrides.map || (mocks.map as As<MapRepository>),
mediaMock as RepositoryInterface<MediaRepository> as MediaRepository, overrides.media || (mocks.media as As<MediaRepository>),
memoryMock as RepositoryInterface<MemoryRepository> as MemoryRepository, overrides.memory || (mocks.memory as As<MemoryRepository>),
metadataMock as RepositoryInterface<MetadataRepository> as MetadataRepository, overrides.metadata || (mocks.metadata as As<MetadataRepository>),
moveMock as RepositoryInterface<MoveRepository> as MoveRepository, overrides.move || (mocks.move as As<MoveRepository>),
notificationMock as RepositoryInterface<NotificationRepository> as NotificationRepository, overrides.notification || (mocks.notification as As<NotificationRepository>),
oauthMock as RepositoryInterface<OAuthRepository> as OAuthRepository, overrides.oauth || (mocks.oauth as As<OAuthRepository>),
partnerMock as RepositoryInterface<PartnerRepository> as PartnerRepository, overrides.partner || (mocks.partner as As<PartnerRepository>),
personMock as RepositoryInterface<PersonRepository> as PersonRepository, overrides.person || (mocks.person as As<PersonRepository>),
processMock as RepositoryInterface<ProcessRepository> as ProcessRepository, overrides.process || (mocks.process as As<ProcessRepository>),
searchMock as RepositoryInterface<SearchRepository> as SearchRepository, overrides.search || (mocks.search as As<SearchRepository>),
serverInfoMock as RepositoryInterface<ServerInfoRepository> as ServerInfoRepository, overrides.serverInfo || (mocks.serverInfo as As<ServerInfoRepository>),
sessionMock as RepositoryInterface<SessionRepository> as SessionRepository, overrides.session || (mocks.session as As<SessionRepository>),
sharedLinkMock as RepositoryInterface<SharedLinkRepository> as SharedLinkRepository, overrides.sharedLink || (mocks.sharedLink as As<SharedLinkRepository>),
stackMock as RepositoryInterface<StackRepository> as StackRepository, overrides.stack || (mocks.stack as As<StackRepository>),
storageMock as RepositoryInterface<StorageRepository> as StorageRepository, overrides.storage || (mocks.storage as As<StorageRepository>),
syncMock as RepositoryInterface<SyncRepository> as SyncRepository, overrides.sync || (mocks.sync as As<SyncRepository>),
systemMock as RepositoryInterface<SystemMetadataRepository> as SystemMetadataRepository, overrides.systemMetadata || (mocks.systemMetadata as As<SystemMetadataRepository>),
tagMock as RepositoryInterface<TagRepository> as TagRepository, overrides.tag || (mocks.tag as As<TagRepository>),
telemetryMock as unknown as TelemetryRepository, overrides.telemetry || (mocks.telemetry as unknown as TelemetryRepository),
trashMock as RepositoryInterface<TrashRepository> as TrashRepository, overrides.trash || (mocks.trash as As<TrashRepository>),
userMock as RepositoryInterface<UserRepository> as UserRepository, overrides.user || (mocks.user as As<UserRepository>),
versionHistoryRepository || overrides.versionHistory || (mocks.versionHistory as As<VersionHistoryRepository>),
(versionHistoryMock as RepositoryInterface<VersionHistoryRepository> as VersionHistoryRepository), overrides.view || (mocks.view as As<ViewRepository>),
viewMock as RepositoryInterface<ViewRepository> as ViewRepository,
); );
return { return {
sut, sut,
mocks: { mocks,
access: accessMock,
apiKey: apiKeyMock,
cron: cronMock,
crypto: cryptoMock,
activity: activityMock,
audit: auditMock,
album: albumMock,
albumUser: albumUserMock,
asset: assetMock,
config: configMock,
database: databaseMock,
event: eventMock,
job: jobMock,
library: libraryMock,
logger: loggerMock,
machineLearning: machineLearningMock,
map: mapMock,
media: mediaMock,
memory: memoryMock,
metadata: metadataMock,
move: moveMock,
notification: notificationMock,
oauth: oauthMock,
partner: partnerMock,
person: personMock,
process: processMock,
search: searchMock,
serverInfo: serverInfoMock,
session: sessionMock,
sharedLink: sharedLinkMock,
stack: stackMock,
storage: storageMock,
systemMetadata: systemMock,
tag: tagMock,
telemetry: telemetryMock,
trash: trashMock,
user: userMock,
versionHistory: versionHistoryMock,
view: viewMock,
} as ServiceMocks,
}; };
}; };