import { Test, TestingModule } from '@nestjs/testing' import { datatype } from 'faker' import { lowerFirst, sample } from 'lodash' import { BioimpedanceCreditService, TeleconsultationsCreditService } from '../../../services/credits' import { BusinessExceptionError } from '../../../errors/business_exception.error' import { CreditAuthor, Patient, Products } from '../../../models' import { factory } from '../../../../test/factories' import { MockedModule } from '../../../../test/types' import { PatientRepository } from '../../../repositories/patient.repository' import { Credits } from './credits' describe('Credits', () => { let subject: Credits let bioimpedanceCreditService: MockedModule let teleconsultationsCreditService: MockedModule let patientRepository: MockedModule beforeAll(async () => { bioimpedanceCreditService = { createTransaction: jest.fn(), } patientRepository = { findByLogin: jest.fn(), } teleconsultationsCreditService = { createTransaction: jest.fn(), } const app: TestingModule = await Test.createTestingModule({ controllers: [], providers: [ { provide: BioimpedanceCreditService, useValue: bioimpedanceCreditService, }, { provide: TeleconsultationsCreditService, useValue: teleconsultationsCreditService, }, { provide: PatientRepository, useValue: patientRepository, }, Credits, ], }).compile() subject = app.get(Credits) }) afterEach(() => { jest.resetAllMocks() }) describe('#add', () => { let identifier: Partial & { externalId?: string } let product = Products.BIOIMPEDANCE let author: CreditAuthor beforeAll(() => { author = { id: datatype.uuid(), type: sample(['user', 'patient', 'system']) } identifier = { document_number: datatype.uuid(), externalId: datatype.uuid() } }) describe('when the identifier data is from existing patient', () => { let patient: Patient beforeAll(async () => { patient = await factory.build('patient') }) beforeEach(() => { patientRepository.findByLogin.mockResolvedValue(patient) }) it('creates credit with patient id', async () => { await subject.add(identifier, product, author) expect(bioimpedanceCreditService.createTransaction).toBeCalledWith( expect.objectContaining({ patientId: patient.id }), ) }) }) describe('when author is not given', () => { it("creates transactions with 'system' author", async () => { await subject.add(identifier, product) expect(bioimpedanceCreditService.createTransaction).toBeCalledWith( expect.objectContaining({ author: { type: 'system' } }), ) }) }) describe('when the identifier data is not from existing patient', () => { beforeEach(() => { patientRepository.findByLogin.mockResolvedValue(null) }) it('creates credit with no patient id', async () => { await subject.add(identifier, product, author) expect(bioimpedanceCreditService.createTransaction).toBeCalledWith( expect.not.objectContaining({ patientId: expect.anything() }), ) }) }) describe.each` product | service ${Products.BIOIMPEDANCE} | ${BioimpedanceCreditService} ${Products.TELECONSULTATIONS} | ${TeleconsultationsCreditService} `('when the product is "$product"', ({ product, service }) => { it(`creates credit with ${service.name}`, async () => { await subject.add(identifier, product, author) expect(eval(lowerFirst(service.name))['createTransaction']).toBeCalled() }) }) describe('when is an invalid product', () => { beforeAll(() => { product = 'food_plans' as Products }) it('throws an error', async () => { await expect(subject.add(identifier, product, author)).rejects.toThrowError(BusinessExceptionError) }) }) }) })