rwadurian/backend/services/admin-service/test/integration/repositories/app-version.repository.spec.ts

272 lines
9.4 KiB
TypeScript

import { Test, TestingModule } from '@nestjs/testing';
import { ConfigModule } from '@nestjs/config';
import { PrismaService } from '../../../src/infrastructure/persistence/prisma/prisma.service';
import { AppVersionRepositoryImpl } from '../../../src/infrastructure/persistence/repositories/app-version.repository.impl';
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 { 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('AppVersionRepository Integration Tests', () => {
let repository: AppVersionRepositoryImpl;
let prisma: PrismaService;
beforeAll(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [
ConfigModule.forRoot({
isGlobal: true,
envFilePath: '.env.test',
}),
],
providers: [
PrismaService,
AppVersionMapper,
AppVersionRepositoryImpl,
],
}).compile();
repository = module.get<AppVersionRepositoryImpl>(AppVersionRepositoryImpl);
prisma = module.get<PrismaService>(PrismaService);
// Connect to test database
await prisma.$connect();
});
afterAll(async () => {
await prisma.$disconnect();
});
beforeEach(async () => {
// Clean up test data
await prisma.appVersion.deleteMany({});
});
const createTestVersion = () => {
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('Test version for integration testing'),
isForceUpdate: false,
createdBy: 'test-user',
});
};
describe('save', () => {
it('should save new app version', async () => {
const version = createTestVersion();
const saved = await repository.save(version);
expect(saved.id).toBe(version.id);
expect(saved.versionCode.value).toBe(100);
expect(saved.versionName.value).toBe('1.0.0');
});
it('should save version and retrieve it from database', async () => {
const version = createTestVersion();
await repository.save(version);
const found = await repository.findById(version.id);
expect(found).not.toBeNull();
expect(found!.id).toBe(version.id);
expect(found!.versionCode.value).toBe(version.versionCode.value);
});
});
describe('findById', () => {
it('should find version by id', async () => {
const version = createTestVersion();
await repository.save(version);
const found = await repository.findById(version.id);
expect(found).not.toBeNull();
expect(found!.id).toBe(version.id);
});
it('should return null for non-existent id', async () => {
const found = await repository.findById('non-existent-id');
expect(found).toBeNull();
});
});
describe('findLatestByPlatform', () => {
it('should find latest enabled version by platform', async () => {
const v1 = createTestVersion();
const v2 = AppVersion.create({
platform: Platform.ANDROID,
versionCode: VersionCode.create(200),
versionName: VersionName.create('2.0.0'),
buildNumber: BuildNumber.create('200'),
downloadUrl: DownloadUrl.create('https://example.com/app-v2.apk'),
fileSize: FileSize.create(20971520n),
fileSha256: FileSha256.create('0000000000000000000000000000000000000000000000000000000000000000'),
changelog: Changelog.create('Version 2.0.0 with new features'),
isForceUpdate: false,
createdBy: 'test-user',
});
await repository.save(v1);
await repository.save(v2);
const latest = await repository.findLatestByPlatform(Platform.ANDROID);
expect(latest).not.toBeNull();
expect(latest!.versionCode.value).toBe(200);
});
it('should return null if no enabled versions exist', async () => {
const latest = await repository.findLatestByPlatform(Platform.ANDROID);
expect(latest).toBeNull();
});
it('should not return disabled versions', async () => {
const version = createTestVersion();
version.disable('test-user');
await repository.save(version);
const latest = await repository.findLatestByPlatform(Platform.ANDROID);
expect(latest).toBeNull();
});
});
describe('findByPlatformAndVersionCode', () => {
it('should find version by platform and version code', async () => {
const version = createTestVersion();
await repository.save(version);
const found = await repository.findByPlatformAndVersionCode(
Platform.ANDROID,
VersionCode.create(100),
);
expect(found).not.toBeNull();
expect(found!.versionCode.value).toBe(100);
});
it('should return null if version not found', async () => {
const found = await repository.findByPlatformAndVersionCode(
Platform.ANDROID,
VersionCode.create(999),
);
expect(found).toBeNull();
});
});
describe('findAllByPlatform', () => {
it('should find all enabled versions by default', async () => {
const v1 = createTestVersion();
const v2 = AppVersion.create({
platform: Platform.ANDROID,
versionCode: VersionCode.create(200),
versionName: VersionName.create('2.0.0'),
buildNumber: BuildNumber.create('200'),
downloadUrl: DownloadUrl.create('https://example.com/app-v2.apk'),
fileSize: FileSize.create(20971520n),
fileSha256: FileSha256.create('0000000000000000000000000000000000000000000000000000000000000000'),
changelog: Changelog.create('Version 2.0.0'),
isForceUpdate: false,
createdBy: 'test-user',
});
v2.disable('test-user');
await repository.save(v1);
await repository.save(v2);
const versions = await repository.findAllByPlatform(Platform.ANDROID);
expect(versions).toHaveLength(1);
expect(versions[0].versionCode.value).toBe(100);
});
it('should find all versions including disabled when requested', async () => {
const v1 = createTestVersion();
const v2 = AppVersion.create({
platform: Platform.ANDROID,
versionCode: VersionCode.create(200),
versionName: VersionName.create('2.0.0'),
buildNumber: BuildNumber.create('200'),
downloadUrl: DownloadUrl.create('https://example.com/app-v2.apk'),
fileSize: FileSize.create(20971520n),
fileSha256: FileSha256.create('0000000000000000000000000000000000000000000000000000000000000000'),
changelog: Changelog.create('Version 2.0.0'),
isForceUpdate: false,
createdBy: 'test-user',
});
v2.disable('test-user');
await repository.save(v1);
await repository.save(v2);
const versions = await repository.findAllByPlatform(Platform.ANDROID, true);
expect(versions).toHaveLength(2);
});
});
describe('update', () => {
it('should update existing version', async () => {
const version = createTestVersion();
await repository.save(version);
version.setForceUpdate(true, 'test-user');
await repository.update(version.id, version);
const updated = await repository.findById(version.id);
expect(updated).not.toBeNull();
expect(updated!.isForceUpdate).toBe(true);
});
});
describe('toggleEnabled', () => {
it('should toggle enabled status', async () => {
const version = createTestVersion();
await repository.save(version);
await repository.toggleEnabled(version.id, false);
const disabled = await repository.findById(version.id);
expect(disabled!.isEnabled).toBe(false);
await repository.toggleEnabled(version.id, true);
const enabled = await repository.findById(version.id);
expect(enabled!.isEnabled).toBe(true);
});
});
describe('delete', () => {
it('should delete version', async () => {
const version = createTestVersion();
await repository.save(version);
await repository.delete(version.id);
const found = await repository.findById(version.id);
expect(found).toBeNull();
});
it('should not throw when deleting non-existent version', async () => {
await expect(repository.delete('non-existent-id')).resolves.not.toThrow();
});
});
});