import { Test, TestingModule } from '@nestjs/testing' import { datatype, random } from 'faker' import { sample } from 'lodash' import { Competition, CompetitionCategories, CompetitionCompetitor, Patient } from '../../models' import { CompetitionRepository, PatientRepository } from '../../repositories' import { MockedModule } from '../../../test/types' import { RankingNotificationService } from '../notification' import { CompetitionService } from './competition.service' import { AcceptInviteCompetitionService, CreateCompetitionService, FinishCompetitionService, SortCompetitorsByScoreService, UpdatePatientCompetitionsService, } from './services' describe('CompetitionService', () => { let subject: CompetitionService let acceptInviteCompetitionService: MockedModule let createCompetitionService: MockedModule let finishCompetitionService: MockedModule let sortCompetitorsByScoreService: MockedModule let updatePatientCompetitionsService: MockedModule let rankingNotificationService: MockedModule let competitionRepository: MockedModule let patientRepository: MockedModule beforeAll(async () => { acceptInviteCompetitionService = { accept: jest.fn(), } createCompetitionService = { create: jest.fn(), } finishCompetitionService = { finish: jest.fn(), } sortCompetitorsByScoreService = { sort: jest.fn(), } updatePatientCompetitionsService = { update: jest.fn(), } rankingNotificationService = { send: jest.fn(), } competitionRepository = { getAllUnfinished: jest.fn(), get: jest.fn(), } patientRepository = { get: jest.fn(), } const app: TestingModule = await Test.createTestingModule({ providers: [ { provide: AcceptInviteCompetitionService, useValue: acceptInviteCompetitionService, }, { provide: CreateCompetitionService, useValue: createCompetitionService, }, { provide: FinishCompetitionService, useValue: finishCompetitionService, }, { provide: SortCompetitorsByScoreService, useValue: sortCompetitorsByScoreService, }, { provide: UpdatePatientCompetitionsService, useValue: updatePatientCompetitionsService, }, { provide: RankingNotificationService, useValue: rankingNotificationService, }, { provide: CompetitionRepository, useValue: competitionRepository, }, { provide: PatientRepository, useValue: patientRepository, }, CompetitionService, ], }).compile() subject = app.get(CompetitionService) }) afterEach(() => { jest.clearAllMocks() }) afterAll(() => { jest.restoreAllMocks() }) describe('#create', () => { const title = random.words() const category = sample(Object.values(CompetitionCategories)) const patientId = datatype.uuid() const willEndAt = new Date() const competition = Competition.toInstance({}) beforeEach(() => { createCompetitionService.create.mockResolvedValue(competition) }) it('calls creation service', async () => { await subject.create({ title, category, patientId, willEndAt }) expect(createCompetitionService.create).toBeCalledWith({ title, category, patientId, willEndAt }) }) }) describe('#acceptInvite', () => { const competitionId = datatype.uuid() const patientId = datatype.uuid() const competitor = CompetitionCompetitor.toInstance({}) beforeEach(() => { acceptInviteCompetitionService.accept.mockResolvedValue(competitor) }) it('calls accept invite service', async () => { await subject.acceptInvite({ competitionId, patientId }) expect(acceptInviteCompetitionService.accept).toBeCalledWith({ competitionId, patientId }) }) }) describe('#notifyAcceptInvite', () => { const competitionId = datatype.uuid() const competition = Competition.toInstance({ competitors: [CompetitionCompetitor.toInstance({}), CompetitionCompetitor.toInstance({})], }) const competitor = CompetitionCompetitor.toInstance({ competition_id: competitionId, patient_id: datatype.uuid() }) const patient = Patient.toInstance({ id: datatype.uuid() }) beforeEach(() => { competitionRepository.get.mockResolvedValue(competition) patientRepository.get.mockResolvedValue(patient) }) it('calls accept invite service', async () => { await subject.notifyAcceptInvite(competitor) expect(rankingNotificationService.send).toBeCalledWith(patient, 'ranking_invite_accepted_push', competition) }) }) describe('#finish', () => { const willEndAt = new Date() it('calls creation service', async () => { await subject.finish(willEndAt) expect(finishCompetitionService.finish).toBeCalledWith(willEndAt) }) }) describe('#generateNewScoreForAllCompetitions', () => { const patientId = datatype.uuid() const anthropometryId = datatype.uuid() it('calls update service', async () => { await subject.generateNewScoreForAllCompetitions({ patientId, anthropometryId }) expect(updatePatientCompetitionsService.update).toBeCalledWith({ patientId, anthropometryId }) }) }) describe('#generatePositionsAndSort', () => { const competitionId = datatype.uuid() let competitions: Competition[] beforeEach(() => { competitionRepository.getAllUnfinished.mockResolvedValue(competitions) }) describe('when has not unfinished competitions', () => { beforeAll(() => { competitions = [] }) it('does not call sort service', async () => { await subject.generatePositionsAndSort(competitionId) expect(sortCompetitorsByScoreService.sort).not.toBeCalled() }) }) describe('when has unfinished competitions', () => { beforeAll(() => { competitions = [...Array(datatype.number({ min: 1, max: 10 }))].map(() => Competition.toInstance({})) }) it('calls sort service for each competition', async () => { await subject.generatePositionsAndSort(competitionId) expect(sortCompetitorsByScoreService.sort).toBeCalledTimes(competitions.length) }) }) }) })