From 47684f65c6a0f9f5c341a2bcfddc9d3876eec68b Mon Sep 17 00:00:00 2001 From: Gordon Nicholas Date: Thu, 19 Dec 2024 14:11:30 +0100 Subject: [PATCH] N21-2103 cleanup, use repo-interface, adjust tests --- .../service/vidis-sync.service.spec.ts | 79 +++++++++++++------ .../service/vidis-sync.service.ts | 6 +- .../repo/media-source.repo.spec.ts | 40 +++++++--- .../service/media-source.service.spec.ts | 2 +- .../src/modules/school-license/repo/index.ts | 2 +- .../media-school-license-repo.interface.ts | 11 +++ ...a-school-license.repo.integration.spec.ts} | 32 ++++---- ...e-repo.ts => media-school-license.repo.ts} | 6 +- .../school-license/school-license.module.ts | 8 +- .../media-school-license.service.spec.ts | 6 +- .../service/media-school-license.service.ts | 7 +- .../mikro-orm/school.repo.integration.spec.ts | 8 +- 12 files changed, 138 insertions(+), 69 deletions(-) create mode 100644 apps/server/src/modules/school-license/repo/media-school-license-repo.interface.ts rename apps/server/src/modules/school-license/repo/mikro-orm/{media-school-license.repo.spec.ts => media-school-license.repo.integration.spec.ts} (81%) rename apps/server/src/modules/school-license/repo/mikro-orm/{media-school-license-repo.ts => media-school-license.repo.ts} (86%) diff --git a/apps/server/src/infra/sync/media-licenses/service/vidis-sync.service.spec.ts b/apps/server/src/infra/sync/media-licenses/service/vidis-sync.service.spec.ts index 06fc3539aa..f764342ef3 100644 --- a/apps/server/src/infra/sync/media-licenses/service/vidis-sync.service.spec.ts +++ b/apps/server/src/infra/sync/media-licenses/service/vidis-sync.service.spec.ts @@ -346,36 +346,71 @@ describe(VidisSyncService.name, () => { }); describe('when vidis no longer provides school activations for existing media school licenses in SVS', () => { - const setup = () => { - const mediaSource = mediaSourceFactory.build(); - const items = vidisItemResponseFactory.buildList(2, { schoolActivations: [] }); - const school = schoolFactory.build({ officialSchoolNumber: '00100' }); + describe('when the school has an official school number', () => { + const setup = () => { + const mediaSource = mediaSourceFactory.build(); + const items = vidisItemResponseFactory.buildList(2, { schoolActivations: [] }); + const school = schoolFactory.build({ officialSchoolNumber: '00100' }); + + const existingMediaSchoolLicense = mediaSchoolLicenseFactory.build({ + schoolId: school.id, + mediumId: items[0].offerId, + mediaSource, + }); - const existingMediaSchoolLicense = mediaSchoolLicenseFactory.build({ - schoolId: school.id, - mediumId: items[0].offerId, - mediaSource, + mediaSchoolLicenseService.findMediaSchoolLicensesByMediumId.mockResolvedValueOnce([ + existingMediaSchoolLicense, + ]); + schoolService.getSchoolById.mockResolvedValueOnce(school); + schoolService.getSchoolByOfficialSchoolNumber.mockResolvedValue(school); + + return { + mediaSource, + items, + existingMediaSchoolLicense, + }; + }; + + it('it should delete the unavailable existing media school licenses', async () => { + const { mediaSource, items, existingMediaSchoolLicense } = setup(); + + await vidisSyncService.syncMediaSchoolLicenses(mediaSource, items); + + expect(mediaSchoolLicenseService.deleteSchoolLicense).toHaveBeenCalledWith(existingMediaSchoolLicense); }); + }); - mediaSchoolLicenseService.findMediaSchoolLicensesByMediumId.mockResolvedValueOnce([ - existingMediaSchoolLicense, - ]); - schoolService.getSchoolById.mockResolvedValueOnce(school); - schoolService.getSchoolByOfficialSchoolNumber.mockResolvedValue(school); + describe('when the school does not have an official school number', () => { + const setup = () => { + const mediaSource = mediaSourceFactory.build(); + const items = vidisItemResponseFactory.buildList(2, { schoolActivations: [] }); + const school = schoolFactory.build({ officialSchoolNumber: undefined }); - return { - mediaSource, - items, - existingMediaSchoolLicense, + const existingMediaSchoolLicense = mediaSchoolLicenseFactory.build({ + schoolId: school.id, + mediumId: items[0].offerId, + mediaSource, + }); + + mediaSchoolLicenseService.findMediaSchoolLicensesByMediumId.mockResolvedValueOnce([ + existingMediaSchoolLicense, + ]); + schoolService.getSchoolById.mockResolvedValueOnce(school); + schoolService.getSchoolByOfficialSchoolNumber.mockResolvedValue(null); + + return { + mediaSource, + items, + }; }; - }; - it('it should delete the unavailable existing media school licenses', async () => { - const { mediaSource, items, existingMediaSchoolLicense } = setup(); + it('it should not delete the existing media school licenses', async () => { + const { mediaSource, items } = setup(); - await vidisSyncService.syncMediaSchoolLicenses(mediaSource, items); + await vidisSyncService.syncMediaSchoolLicenses(mediaSource, items); - expect(mediaSchoolLicenseService.deleteSchoolLicense).toHaveBeenCalledWith(existingMediaSchoolLicense); + expect(mediaSchoolLicenseService.deleteSchoolLicense).not.toHaveBeenCalled(); + }); }); }); diff --git a/apps/server/src/infra/sync/media-licenses/service/vidis-sync.service.ts b/apps/server/src/infra/sync/media-licenses/service/vidis-sync.service.ts index ce0331eceb..b5d2aff4f6 100644 --- a/apps/server/src/infra/sync/media-licenses/service/vidis-sync.service.ts +++ b/apps/server/src/infra/sync/media-licenses/service/vidis-sync.service.ts @@ -71,9 +71,9 @@ export class VidisSyncService { if (!school) { this.logger.info(new SchoolForSchoolMediaLicenseSyncNotFoundLoggable(schoolNumber)); } else { - const isExistingLicense: boolean = existingLicenses.some( - (license: MediaSchoolLicense): boolean => license.schoolId === school.id - ); + const isExistingLicense: boolean = existingLicenses.some((license: MediaSchoolLicense): boolean => { + return license.schoolId === school.id; + }); if (!isExistingLicense) { const newLicense: MediaSchoolLicense = new MediaSchoolLicense({ id: new ObjectId().toHexString(), diff --git a/apps/server/src/modules/media-source/repo/media-source.repo.spec.ts b/apps/server/src/modules/media-source/repo/media-source.repo.spec.ts index b37e4ecf96..068c40102d 100644 --- a/apps/server/src/modules/media-source/repo/media-source.repo.spec.ts +++ b/apps/server/src/modules/media-source/repo/media-source.repo.spec.ts @@ -109,25 +109,39 @@ describe(MediaSourceRepo.name, () => { describe('findByFormat', () => { describe('when a media source data format is provided', () => { - const setup = async () => { - const format = MediaSourceDataFormat.VIDIS; - const mediaSourceEntity = mediaSourceEntityFactory.build({ format }); - const otherMediaSourceEntity = mediaSourceEntityFactory.build({ format: MediaSourceDataFormat.BILDUNGSLOGIN }); + describe('when there the media source exists', () => { + const setup = async () => { + const format = MediaSourceDataFormat.VIDIS; + const mediaSourceEntity = mediaSourceEntityFactory.build({ format }); + const otherMediaSourceEntity = mediaSourceEntityFactory.build({ + format: MediaSourceDataFormat.BILDUNGSLOGIN, + }); - await em.persistAndFlush([mediaSourceEntity, otherMediaSourceEntity]); - em.clear(); + await em.persistAndFlush([mediaSourceEntity, otherMediaSourceEntity]); + em.clear(); - const expectedDO = MediaSourceMapper.mapEntityToDo(mediaSourceEntity); + const expectedDO = MediaSourceMapper.mapEntityToDo(mediaSourceEntity); - return { format, expectedDO }; - }; + return { format, expectedDO }; + }; - it('should return the media source', async () => { - const { format, expectedDO } = await setup(); + it('should return the media source', async () => { + const { format, expectedDO } = await setup(); - const result = await repo.findByFormat(format); + const result: MediaSource | null = await repo.findByFormat(format); - expect(result).toEqual(expectedDO); + expect(result).toEqual(expectedDO); + }); + }); + + describe('when there the media source does not exist', () => { + it('should return null', async () => { + const format = MediaSourceDataFormat.VIDIS; + + const result: MediaSource | null = await repo.findByFormat(format); + + expect(result).toBeNull(); + }); }); }); }); diff --git a/apps/server/src/modules/media-source/service/media-source.service.spec.ts b/apps/server/src/modules/media-source/service/media-source.service.spec.ts index 48fcd4e173..e64f089619 100644 --- a/apps/server/src/modules/media-source/service/media-source.service.spec.ts +++ b/apps/server/src/modules/media-source/service/media-source.service.spec.ts @@ -1,9 +1,9 @@ import { createMock, DeepMocked } from '@golevelup/ts-jest'; import { Test, TestingModule } from '@nestjs/testing'; import { MediaSourceRepo } from '../repo'; +import { MediaSourceDataFormat } from '../enum'; import { mediaSourceFactory } from '../testing'; import { MediaSourceService } from './media-source.service'; -import { MediaSourceDataFormat } from '@modules/media-source'; describe(MediaSourceService.name, () => { let module: TestingModule; diff --git a/apps/server/src/modules/school-license/repo/index.ts b/apps/server/src/modules/school-license/repo/index.ts index 159291dac4..19af9c899f 100644 --- a/apps/server/src/modules/school-license/repo/index.ts +++ b/apps/server/src/modules/school-license/repo/index.ts @@ -1 +1 @@ -export { MediaSchoolLicenseRepo } from './mikro-orm/media-school-license-repo'; +export { MEDIA_SCHOOL_LICENSE_REPO, MediaSchoolLicenseRepo } from './media-school-license-repo.interface'; diff --git a/apps/server/src/modules/school-license/repo/media-school-license-repo.interface.ts b/apps/server/src/modules/school-license/repo/media-school-license-repo.interface.ts new file mode 100644 index 0000000000..ef6283d935 --- /dev/null +++ b/apps/server/src/modules/school-license/repo/media-school-license-repo.interface.ts @@ -0,0 +1,11 @@ +import { MediaSchoolLicense } from '../domain'; + +export interface MediaSchoolLicenseRepo { + findMediaSchoolLicensesByMediumId(mediumId: string): Promise; + + save(domainObject: MediaSchoolLicense): Promise; + + delete(domainObjects: MediaSchoolLicense[] | MediaSchoolLicense): Promise; +} + +export const MEDIA_SCHOOL_LICENSE_REPO = 'MEDIA_SCHOOL_LICENSE_REPO'; diff --git a/apps/server/src/modules/school-license/repo/mikro-orm/media-school-license.repo.spec.ts b/apps/server/src/modules/school-license/repo/mikro-orm/media-school-license.repo.integration.spec.ts similarity index 81% rename from apps/server/src/modules/school-license/repo/mikro-orm/media-school-license.repo.spec.ts rename to apps/server/src/modules/school-license/repo/mikro-orm/media-school-license.repo.integration.spec.ts index 13a25c2a1a..912a0ef65d 100644 --- a/apps/server/src/modules/school-license/repo/mikro-orm/media-school-license.repo.spec.ts +++ b/apps/server/src/modules/school-license/repo/mikro-orm/media-school-license.repo.integration.spec.ts @@ -4,24 +4,24 @@ import { Test, TestingModule } from '@nestjs/testing'; import { cleanupCollections } from '@shared/testing'; import { MediaSourceEntity } from '@modules/media-source/entity'; import { mediaSourceEntityFactory } from '@modules/media-source/testing'; -import { MediaSchoolLicenseRepo } from './media-school-license-repo'; +import { MediaSchoolLicenseMikroOrmRepo } from './media-school-license.repo'; import { MediaSchoolLicense } from '../../domain'; import { MediaSchoolLicenseEntity } from '../../entity'; import { mediaSchoolLicenseEntityFactory, mediaSchoolLicenseFactory } from '../../testing'; import { MediaSchoolLicenseEntityMapper } from '../mapper/media-school-license.entity.mapper'; -describe(MediaSchoolLicenseRepo.name, () => { +describe(MediaSchoolLicenseMikroOrmRepo.name, () => { let module: TestingModule; - let repo: MediaSchoolLicenseRepo; + let repo: MediaSchoolLicenseMikroOrmRepo; let em: EntityManager; beforeAll(async () => { module = await Test.createTestingModule({ imports: [MongoMemoryDatabaseModule.forRoot()], - providers: [MediaSchoolLicenseRepo], + providers: [MediaSchoolLicenseMikroOrmRepo], }).compile(); - repo = module.get(MediaSchoolLicenseRepo); + repo = module.get(MediaSchoolLicenseMikroOrmRepo); em = module.get(EntityManager); }); @@ -43,17 +43,12 @@ describe(MediaSchoolLicenseRepo.name, () => { mediumId, }); - const mediaSchoolLicenseWithNoId: MediaSchoolLicenseEntity = mediaSchoolLicenseEntityFactory.buildWithId( - { - mediaSource: mediaSourceEntity, - mediumId, - }, - undefined - ); - - mediaSchoolLicenses.push(mediaSchoolLicenseWithNoId); + const otherMediaSchoolLicense: MediaSchoolLicenseEntity = mediaSchoolLicenseEntityFactory.build({ + mediaSource: mediaSourceEntity, + mediumId: 'test-other-medium-id', + }); - await em.persistAndFlush(mediaSchoolLicenses); + await em.persistAndFlush([otherMediaSchoolLicense, ...mediaSchoolLicenses]); em.clear(); const expectedDOs: MediaSchoolLicense[] = mediaSchoolLicenses.map( @@ -105,8 +100,9 @@ describe(MediaSchoolLicenseRepo.name, () => { {}, mediaSchoolLicenseDO.id ); + const otherEntity: MediaSchoolLicenseEntity = mediaSchoolLicenseEntityFactory.build(); - await em.persistAndFlush([mediaSchoolLicenseEntity]); + await em.persistAndFlush([mediaSchoolLicenseEntity, otherEntity]); em.clear(); return { mediaSchoolLicenseDO }; @@ -117,7 +113,9 @@ describe(MediaSchoolLicenseRepo.name, () => { await repo.delete(mediaSchoolLicenseDO); - const savedMediaSchoolLicense: MediaSchoolLicenseEntity | null = await em.findOne(MediaSchoolLicenseEntity, {}); + const savedMediaSchoolLicense: MediaSchoolLicenseEntity | null = await em.findOne(MediaSchoolLicenseEntity, { + id: mediaSchoolLicenseDO.id, + }); expect(savedMediaSchoolLicense).toBeNull(); }); }); diff --git a/apps/server/src/modules/school-license/repo/mikro-orm/media-school-license-repo.ts b/apps/server/src/modules/school-license/repo/mikro-orm/media-school-license.repo.ts similarity index 86% rename from apps/server/src/modules/school-license/repo/mikro-orm/media-school-license-repo.ts rename to apps/server/src/modules/school-license/repo/mikro-orm/media-school-license.repo.ts index 54ad85eec9..dabf46f4b5 100644 --- a/apps/server/src/modules/school-license/repo/mikro-orm/media-school-license-repo.ts +++ b/apps/server/src/modules/school-license/repo/mikro-orm/media-school-license.repo.ts @@ -5,9 +5,13 @@ import { MediaSchoolLicense } from '../../domain'; import { MediaSchoolLicenseEntity } from '../../entity'; import { SchoolLicenseType } from '../../enum'; import { MediaSchoolLicenseEntityMapper } from '../mapper/media-school-license.entity.mapper'; +import { MediaSchoolLicenseRepo } from '../media-school-license-repo.interface'; @Injectable() -export class MediaSchoolLicenseRepo extends BaseDomainObjectRepo { +export class MediaSchoolLicenseMikroOrmRepo + extends BaseDomainObjectRepo + implements MediaSchoolLicenseRepo +{ protected get entityName(): EntityName { return MediaSchoolLicenseEntity; } diff --git a/apps/server/src/modules/school-license/school-license.module.ts b/apps/server/src/modules/school-license/school-license.module.ts index bc57c7cace..045176eb14 100644 --- a/apps/server/src/modules/school-license/school-license.module.ts +++ b/apps/server/src/modules/school-license/school-license.module.ts @@ -2,12 +2,16 @@ import { Module } from '@nestjs/common'; import { LoggerModule } from '../../core/logger'; import { MediaSourceModule } from '../media-source/media-source.module'; import { SchoolModule } from '../school'; -import { MediaSchoolLicenseRepo } from './repo/mikro-orm/media-school-license-repo'; +import { MEDIA_SCHOOL_LICENSE_REPO } from './repo'; +import { MediaSchoolLicenseMikroOrmRepo } from './repo/mikro-orm/media-school-license.repo'; import { MediaSchoolLicenseService } from './service/media-school-license.service'; @Module({ imports: [MediaSourceModule, SchoolModule, LoggerModule], - providers: [MediaSchoolLicenseRepo, MediaSchoolLicenseService], + providers: [ + MediaSchoolLicenseService, + { provide: MEDIA_SCHOOL_LICENSE_REPO, useClass: MediaSchoolLicenseMikroOrmRepo }, + ], exports: [MediaSchoolLicenseService], }) export class SchoolLicenseModule {} diff --git a/apps/server/src/modules/school-license/service/media-school-license.service.spec.ts b/apps/server/src/modules/school-license/service/media-school-license.service.spec.ts index 912028f923..7c798de9af 100644 --- a/apps/server/src/modules/school-license/service/media-school-license.service.spec.ts +++ b/apps/server/src/modules/school-license/service/media-school-license.service.spec.ts @@ -1,6 +1,6 @@ import { Test, TestingModule } from '@nestjs/testing'; import { createMock, DeepMocked } from '@golevelup/ts-jest'; -import { MediaSchoolLicenseRepo } from '../repo'; +import { MediaSchoolLicenseRepo, MEDIA_SCHOOL_LICENSE_REPO } from '../repo'; import { mediaSchoolLicenseFactory } from '../testing'; import { MediaSchoolLicenseService } from './media-school-license.service'; @@ -14,14 +14,14 @@ describe(MediaSchoolLicenseService.name, () => { providers: [ MediaSchoolLicenseService, { - provide: MediaSchoolLicenseRepo, + provide: MEDIA_SCHOOL_LICENSE_REPO, useValue: createMock(), }, ], }).compile(); mediaSchoolLicenseService = module.get(MediaSchoolLicenseService); - mediaSchoolLicenseRepo = module.get(MediaSchoolLicenseRepo); + mediaSchoolLicenseRepo = module.get(MEDIA_SCHOOL_LICENSE_REPO); }); afterAll(async () => { diff --git a/apps/server/src/modules/school-license/service/media-school-license.service.ts b/apps/server/src/modules/school-license/service/media-school-license.service.ts index 9a96bda6e7..3ea1bf8e22 100644 --- a/apps/server/src/modules/school-license/service/media-school-license.service.ts +++ b/apps/server/src/modules/school-license/service/media-school-license.service.ts @@ -1,10 +1,9 @@ -import { Injectable } from '@nestjs/common'; +import { Inject } from '@nestjs/common'; import { MediaSchoolLicense } from '../domain'; -import { MediaSchoolLicenseRepo } from '../repo'; +import { MEDIA_SCHOOL_LICENSE_REPO, MediaSchoolLicenseRepo } from '../repo'; -@Injectable() export class MediaSchoolLicenseService { - constructor(private readonly mediaSchoolLicenseRepo: MediaSchoolLicenseRepo) {} + constructor(@Inject(MEDIA_SCHOOL_LICENSE_REPO) private readonly mediaSchoolLicenseRepo: MediaSchoolLicenseRepo) {} public async findMediaSchoolLicensesByMediumId(mediumId: string): Promise { const mediaSchoolLicenses: MediaSchoolLicense[] = diff --git a/apps/server/src/modules/school/repo/mikro-orm/school.repo.integration.spec.ts b/apps/server/src/modules/school/repo/mikro-orm/school.repo.integration.spec.ts index 2aa4b1446e..342ef28ef7 100644 --- a/apps/server/src/modules/school/repo/mikro-orm/school.repo.integration.spec.ts +++ b/apps/server/src/modules/school/repo/mikro-orm/school.repo.integration.spec.ts @@ -14,7 +14,7 @@ import { } from '@shared/testing'; import { countyEmbeddableFactory } from '@shared/testing/factory/county.embeddable.factory'; import { MongoMemoryDatabaseModule } from '@src/infra/database'; -import { FileStorageType, School, SCHOOL_REPO } from '../../domain'; +import { FileStorageType, SCHOOL_REPO } from '../../domain'; import { federalStateFactory, schoolFactory } from '../../testing'; import { countyFactory } from '../../testing/county.factory'; import { FederalStateEntityMapper, SchoolEntityMapper, SchoolYearEntityMapper } from './mapper'; @@ -324,7 +324,11 @@ describe('SchoolMikroOrmRepo', () => { officialSchoolNumber, }); - await em.persistAndFlush([schoolEntity]); + const otherSchoolEntity = schoolEntityFactory.build({ + officialSchoolNumber: '11011', + }); + + await em.persistAndFlush([schoolEntity, otherSchoolEntity]); em.clear(); const expectedSchoolDO = SchoolEntityMapper.mapToDo(schoolEntity);