mirror of
				https://github.com/immich-app/immich.git
				synced 2025-10-26 08:12:33 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			170 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			170 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import { Insertable, Kysely } from 'kysely';
 | |
| import { randomBytes, randomUUID } from 'node:crypto';
 | |
| import { Writable } from 'node:stream';
 | |
| import { Assets, DB, Sessions, Users } from 'src/db';
 | |
| import { AuthDto } from 'src/dtos/auth.dto';
 | |
| import { AssetType } from 'src/enum';
 | |
| import { AlbumRepository } from 'src/repositories/album.repository';
 | |
| import { AssetRepository } from 'src/repositories/asset.repository';
 | |
| import { SessionRepository } from 'src/repositories/session.repository';
 | |
| import { SyncRepository } from 'src/repositories/sync.repository';
 | |
| import { UserRepository } from 'src/repositories/user.repository';
 | |
| 
 | |
| class CustomWritable extends Writable {
 | |
|   private data = '';
 | |
| 
 | |
|   _write(chunk: any, encoding: string, callback: () => void) {
 | |
|     this.data += chunk.toString();
 | |
|     callback();
 | |
|   }
 | |
| 
 | |
|   getResponse() {
 | |
|     const result = this.data;
 | |
|     return result
 | |
|       .split('\n')
 | |
|       .filter((x) => x.length > 0)
 | |
|       .map((x) => JSON.parse(x));
 | |
|   }
 | |
| }
 | |
| 
 | |
| type Asset = Insertable<Assets>;
 | |
| type User = Partial<Insertable<Users>>;
 | |
| type Session = Omit<Insertable<Sessions>, 'token'> & { token?: string };
 | |
| 
 | |
| export const newUuid = () => randomUUID() as string;
 | |
| 
 | |
| export class TestFactory {
 | |
|   private assets: Asset[] = [];
 | |
|   private sessions: Session[] = [];
 | |
|   private users: User[] = [];
 | |
| 
 | |
|   private constructor(private context: TestContext) {}
 | |
| 
 | |
|   static create(context: TestContext) {
 | |
|     return new TestFactory(context);
 | |
|   }
 | |
| 
 | |
|   static stream() {
 | |
|     return new CustomWritable();
 | |
|   }
 | |
| 
 | |
|   static asset(asset: Asset) {
 | |
|     const assetId = asset.id || newUuid();
 | |
|     const defaults: Insertable<Assets> = {
 | |
|       deviceAssetId: '',
 | |
|       deviceId: '',
 | |
|       originalFileName: '',
 | |
|       checksum: randomBytes(32),
 | |
|       type: AssetType.IMAGE,
 | |
|       originalPath: '/path/to/something.jpg',
 | |
|       ownerId: '@immich.cloud',
 | |
|       isVisible: true,
 | |
|     };
 | |
| 
 | |
|     return {
 | |
|       ...defaults,
 | |
|       ...asset,
 | |
|       id: assetId,
 | |
|     };
 | |
|   }
 | |
| 
 | |
|   static auth(auth: { user: User; session?: Session }) {
 | |
|     return auth as AuthDto;
 | |
|   }
 | |
| 
 | |
|   static user(user: User = {}) {
 | |
|     const userId = user.id || newUuid();
 | |
|     const defaults: Insertable<Users> = {
 | |
|       email: `${userId}@immich.cloud`,
 | |
|       name: `User ${userId}`,
 | |
|       deletedAt: null,
 | |
|     };
 | |
| 
 | |
|     return {
 | |
|       ...defaults,
 | |
|       ...user,
 | |
|       id: userId,
 | |
|     };
 | |
|   }
 | |
| 
 | |
|   static session(session: Session) {
 | |
|     const id = session.id || newUuid();
 | |
|     const defaults = {
 | |
|       token: randomBytes(36).toString('base64url'),
 | |
|     };
 | |
| 
 | |
|     return {
 | |
|       ...defaults,
 | |
|       ...session,
 | |
|       id,
 | |
|     };
 | |
|   }
 | |
| 
 | |
|   withAsset(asset: Asset) {
 | |
|     this.assets.push(asset);
 | |
|     return this;
 | |
|   }
 | |
| 
 | |
|   withSession(session: Session) {
 | |
|     this.sessions.push(session);
 | |
|     return this;
 | |
|   }
 | |
| 
 | |
|   withUser(user: User = {}) {
 | |
|     this.users.push(user);
 | |
|     return this;
 | |
|   }
 | |
| 
 | |
|   async create() {
 | |
|     for (const asset of this.assets) {
 | |
|       await this.context.createAsset(asset);
 | |
|     }
 | |
| 
 | |
|     for (const user of this.users) {
 | |
|       await this.context.createUser(user);
 | |
|     }
 | |
| 
 | |
|     for (const session of this.sessions) {
 | |
|       await this.context.createSession(session);
 | |
|     }
 | |
| 
 | |
|     return this.context;
 | |
|   }
 | |
| }
 | |
| 
 | |
| export class TestContext {
 | |
|   userRepository: UserRepository;
 | |
|   assetRepository: AssetRepository;
 | |
|   albumRepository: AlbumRepository;
 | |
|   sessionRepository: SessionRepository;
 | |
|   syncRepository: SyncRepository;
 | |
| 
 | |
|   private constructor(private db: Kysely<DB>) {
 | |
|     this.userRepository = new UserRepository(this.db);
 | |
|     this.assetRepository = new AssetRepository(this.db);
 | |
|     this.albumRepository = new AlbumRepository(this.db);
 | |
|     this.sessionRepository = new SessionRepository(this.db);
 | |
|     this.syncRepository = new SyncRepository(this.db);
 | |
|   }
 | |
| 
 | |
|   static from(db: Kysely<DB>) {
 | |
|     return new TestContext(db).getFactory();
 | |
|   }
 | |
| 
 | |
|   getFactory() {
 | |
|     return TestFactory.create(this);
 | |
|   }
 | |
| 
 | |
|   createUser(user: User = {}) {
 | |
|     return this.userRepository.create(TestFactory.user(user));
 | |
|   }
 | |
| 
 | |
|   createAsset(asset: Asset) {
 | |
|     return this.assetRepository.create(TestFactory.asset(asset));
 | |
|   }
 | |
| 
 | |
|   createSession(session: Session) {
 | |
|     return this.sessionRepository.create(TestFactory.session(session));
 | |
|   }
 | |
| }
 |