import { Test, TestingModule } from '@nestjs/testing'; import { AppVersionMapper } from '../../../../src/infrastructure/persistence/mappers/app-version.mapper'; import { AppVersion } from '../../../../src/domain/entities/app-version.entity'; import { Platform } from '../../../../src/domain/enums/platform.enum'; import { Platform as PrismaPlatform } from '@prisma/client'; import { VersionCode } from '../../../../src/domain/value-objects/version-code.vo'; import { VersionName } from '../../../../src/domain/value-objects/version-name.vo'; import { BuildNumber } from '../../../../src/domain/value-objects/build-number.vo'; import { DownloadUrl } from '../../../../src/domain/value-objects/download-url.vo'; import { FileSize } from '../../../../src/domain/value-objects/file-size.vo'; import { FileSha256 } from '../../../../src/domain/value-objects/file-sha256.vo'; import { Changelog } from '../../../../src/domain/value-objects/changelog.vo'; describe('AppVersionMapper', () => { let mapper: AppVersionMapper; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [AppVersionMapper], }).compile(); mapper = module.get(AppVersionMapper); }); const createDomainVersion = () => { return AppVersion.create({ platform: Platform.ANDROID, versionCode: VersionCode.create(100), versionName: VersionName.create('1.0.0'), buildNumber: BuildNumber.create('100'), downloadUrl: DownloadUrl.create('https://example.com/app.apk'), fileSize: FileSize.create(10485760n), fileSha256: FileSha256.create('e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'), changelog: Changelog.create('Initial release'), isForceUpdate: false, createdBy: 'admin', }); }; const createPrismaVersion = () => ({ id: 'test-id', platform: PrismaPlatform.ANDROID, versionCode: 100, versionName: '1.0.0', buildNumber: '100', downloadUrl: 'https://example.com/app.apk', fileSize: 10485760n, fileSha256: 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', changelog: 'Initial release', minOsVersion: null, isEnabled: true, isForceUpdate: false, releaseDate: null, createdAt: new Date('2024-01-01'), updatedAt: new Date('2024-01-01'), createdBy: 'admin', updatedBy: null, }); describe('toDomain', () => { it('should map Prisma model to domain entity', () => { const prismaVersion = createPrismaVersion(); const domainVersion = mapper.toDomain(prismaVersion); expect(domainVersion).toBeInstanceOf(AppVersion); expect(domainVersion.id).toBe(prismaVersion.id); expect(domainVersion.platform).toBe(Platform.ANDROID); expect(domainVersion.versionCode.value).toBe(100); expect(domainVersion.versionName.value).toBe('1.0.0'); expect(domainVersion.buildNumber.value).toBe('100'); expect(domainVersion.downloadUrl.value).toBe('https://example.com/app.apk'); expect(domainVersion.fileSize.bytes).toBe(10485760n); expect(domainVersion.fileSha256.value).toBe('e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'); expect(domainVersion.changelog.value).toBe('Initial release'); expect(domainVersion.isEnabled).toBe(true); expect(domainVersion.isForceUpdate).toBe(false); }); it('should map iOS platform correctly', () => { const prismaVersion = { ...createPrismaVersion(), platform: PrismaPlatform.IOS }; const domainVersion = mapper.toDomain(prismaVersion); expect(domainVersion.platform).toBe(Platform.IOS); }); it('should handle null minOsVersion', () => { const prismaVersion = { ...createPrismaVersion(), minOsVersion: null }; const domainVersion = mapper.toDomain(prismaVersion); expect(domainVersion.minOsVersion).toBeNull(); }); it('should handle null releaseDate', () => { const prismaVersion = { ...createPrismaVersion(), releaseDate: null }; const domainVersion = mapper.toDomain(prismaVersion); expect(domainVersion.releaseDate).toBeNull(); }); }); describe('toPersistence', () => { it('should map domain entity to Prisma model', () => { const domainVersion = createDomainVersion(); const persistenceModel = mapper.toPersistence(domainVersion); expect(persistenceModel.id).toBe(domainVersion.id); expect(persistenceModel.platform).toBe(Platform.ANDROID); expect(persistenceModel.versionCode).toBe(100); expect(persistenceModel.versionName).toBe('1.0.0'); expect(persistenceModel.buildNumber).toBe('100'); expect(persistenceModel.downloadUrl).toBe('https://example.com/app.apk'); expect(persistenceModel.fileSize).toBe(10485760n); expect(persistenceModel.fileSha256).toBe('e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'); expect(persistenceModel.changelog).toBe('Initial release'); expect(persistenceModel.isEnabled).toBe(true); expect(persistenceModel.isForceUpdate).toBe(false); }); it('should exclude createdAt and updatedAt from output', () => { const domainVersion = createDomainVersion(); const persistenceModel = mapper.toPersistence(domainVersion); expect(persistenceModel).not.toHaveProperty('createdAt'); expect(persistenceModel).not.toHaveProperty('updatedAt'); }); }); describe('round-trip conversion', () => { it('should maintain data integrity through round-trip conversion', () => { const originalPrisma = createPrismaVersion(); const domain = mapper.toDomain(originalPrisma); const backToPersistence = mapper.toPersistence(domain); expect(backToPersistence.id).toBe(originalPrisma.id); expect(backToPersistence.versionCode).toBe(originalPrisma.versionCode); expect(backToPersistence.versionName).toBe(originalPrisma.versionName); expect(backToPersistence.platform).toBe(originalPrisma.platform); }); }); });