import { Test, TestingModule } from '@nestjs/testing' import { datatype } from 'faker' import { factory } from '../../../../test/factories' import { LanguageCountryCode } from '../../../utils/countries/language-country-code.enum' import { MessagingService } from '../../../services/messaging' import { MockedModule } from '../../../../test/types' import { Patient } from '../../../models/patient.model' import { PatientRepository } from '../../../repositories/patient.repository' import { TranslatePatientsHelper } from '../i18n' import { AppointmentRepository, MessageRepository } from '../../../repositories' import { Appointment } from '../../../models/appointment.model' import { Messaging } from './messaging' describe('Messaging', () => { let subject: Messaging let patientRepository: MockedModule let appointmentRepository: MockedModule let messageRepository: MockedModule let messagingService: MockedModule let translator: TranslatePatientsHelper beforeAll(async () => { patientRepository = { get: jest.fn(), } appointmentRepository = { findThatStartsAtHour: jest.fn(), } messageRepository = { create: jest.fn(), } messagingService = { sendPushNotification: jest.fn(), } translator = new TranslatePatientsHelper() const app: TestingModule = await Test.createTestingModule({ controllers: [], providers: [ { provide: PatientRepository, useValue: patientRepository, }, { provide: AppointmentRepository, useValue: appointmentRepository, }, { provide: MessageRepository, useValue: messageRepository, }, { provide: MessagingService, useValue: messagingService, }, { provide: TranslatePatientsHelper, useValue: translator, }, Messaging, ], }).compile() subject = app.get(Messaging) }) afterEach(() => { jest.resetAllMocks() }) describe('#nutriReplyNotification()', () => { let patient: Patient let patientId: string beforeAll(() => { patientId = datatype.uuid() }) beforeEach(() => { patientRepository.get.mockResolvedValue(patient) }) describe('when there is not patient', () => { it('does not send notification', async () => { await subject.nutriReplyNotification(patientId) expect(messagingService.sendPushNotification).not.toBeCalled() }) }) describe('when there is patient', () => { beforeAll(async () => { patient = await factory.build('patient') }) it('sends notification', async () => { await subject.nutriReplyNotification(patientId) expect(messagingService.sendPushNotification).toBeCalled() }) describe('when patient is BR', () => { beforeAll(() => { patient.country_code = LanguageCountryCode.PT_BR }) it('sends portuguese text', async () => { await subject.nutriReplyNotification(patientId) expect(messagingService.sendPushNotification).toBeCalledWith( patient.device_id, expect.objectContaining({ notification: { title: translator.get(LanguageCountryCode.PT_BR, translator.keys.NEW_MESSAGE), body: translator.get(LanguageCountryCode.PT_BR, translator.keys.NUTRI_REPLIED), }, data: { click_action: 'FLUTTER_NOTIFICATION_CLICK', page: '/chat', }, }), ) }) }) describe('when patient is MX', () => { beforeAll(() => { patient.country_code = LanguageCountryCode.ES_MX }) it('sends spanish text', async () => { await subject.nutriReplyNotification(patientId) expect(messagingService.sendPushNotification).toBeCalledWith( patient.device_id, expect.objectContaining({ notification: { title: translator.get(LanguageCountryCode.ES_MX, translator.keys.NEW_MESSAGE), body: translator.get(LanguageCountryCode.ES_MX, translator.keys.NUTRI_REPLIED), }, data: { click_action: 'FLUTTER_NOTIFICATION_CLICK', page: '/chat', }, }), ) }) }) }) }) describe('#mealRatedNotification()', () => { let patient: Patient let patientId: string beforeAll(() => { patientId = datatype.uuid() }) beforeEach(() => { patientRepository.get.mockResolvedValue(patient) }) describe('when there is not patient', () => { it('does not send notification', async () => { await subject.mealRatedNotification(patientId) expect(messagingService.sendPushNotification).not.toBeCalled() }) }) describe('when there is patient', () => { beforeAll(async () => { patient = await factory.build('patient') }) it('sends notification', async () => { await subject.mealRatedNotification(patientId) expect(messagingService.sendPushNotification).toBeCalled() }) describe('when patient is BR', () => { beforeAll(() => { patient.country_code = LanguageCountryCode.PT_BR }) it('sends portuguese text', async () => { await subject.mealRatedNotification(patientId) expect(messagingService.sendPushNotification).toBeCalledWith( patient.device_id, expect.objectContaining({ notification: { title: translator.get(LanguageCountryCode.PT_BR, translator.keys.MEAL_RATED), body: translator.get(LanguageCountryCode.PT_BR, translator.keys.MEAL_MESSAGE), }, data: { click_action: 'FLUTTER_NOTIFICATION_CLICK', page: '/home/diary', }, }), ) }) }) describe('when patient is MX', () => { beforeAll(() => { patient.country_code = LanguageCountryCode.ES_MX }) it('sends spanish text', async () => { await subject.mealRatedNotification(patientId) expect(messagingService.sendPushNotification).toBeCalledWith( patient.device_id, expect.objectContaining({ notification: { title: translator.get(LanguageCountryCode.ES_MX, translator.keys.MEAL_RATED), body: translator.get(LanguageCountryCode.ES_MX, translator.keys.MEAL_MESSAGE), }, data: { click_action: 'FLUTTER_NOTIFICATION_CLICK', page: '/home/diary', }, }), ) }) }) }) }) describe('#foodPlanReadyNotification()', () => { let patient: Patient let patientId: string beforeAll(() => { patientId = datatype.uuid() }) beforeEach(() => { patientRepository.get.mockResolvedValue(patient) }) describe('when there is not patient', () => { it('does not send notification', async () => { await subject.foodPlanReadyNotification(patientId) expect(messageRepository.create).not.toBeCalled() }) }) describe('when there is patient', () => { beforeAll(async () => { patient = await factory.build('patient') }) it('sends notification', async () => { await subject.foodPlanReadyNotification(patientId) expect(messageRepository.create).toBeCalled() }) describe('when patient is BR', () => { beforeAll(() => { patient.country_code = LanguageCountryCode.PT_BR }) it('sends portuguese text', async () => { await subject.foodPlanReadyNotification(patientId) expect(messageRepository.create).toBeCalledWith( expect.objectContaining({ patient_id: patient.id, user_id: patient.user_id, replied_by_user_id: patient.user_id, tags: { tags: ['FOOD_PLAN_ACTIVATED'] }, text: translator.get(LanguageCountryCode.PT_BR, translator.keys.FOOD_PLAN_ACTIVATED), }), ) }) }) describe('when patient is MX', () => { beforeAll(() => { patient.country_code = LanguageCountryCode.ES_MX }) it('sends spanish text', async () => { await subject.foodPlanReadyNotification(patientId) expect(messageRepository.create).toBeCalledWith( expect.objectContaining({ patient_id: patient.id, user_id: patient.user_id, replied_by_user_id: patient.user_id, tags: { tags: ['FOOD_PLAN_ACTIVATED'] }, text: translator.get(LanguageCountryCode.ES_MX, translator.keys.FOOD_PLAN_ACTIVATED), }), ) }) }) }) }) describe('#incomingAppointmentsChatNofitication()', () => { describe('when there are no appointments', () => { beforeEach(() => { appointmentRepository.findThatStartsAtHour.mockResolvedValue([]) }) it('does not create message', async () => { await subject.incomingAppointmentsChatNofitication() expect(messageRepository.create).not.toBeCalled() }) }) describe('when there are appointments', () => { let appointmentsPt: Array let appointmentsEs: Array beforeEach(async () => { appointmentsPt = await Promise.all( Array(5) .fill(null) .map(async () => factory.build('appointment:patient')), ) appointmentsEs = await Promise.all( Array(5) .fill(null) .map(async () => factory.build('appointment', { patient: await factory.build('patient:es_MX') })), ) appointmentRepository.findThatStartsAtHour.mockResolvedValueOnce(appointmentsPt) appointmentRepository.findThatStartsAtHour.mockResolvedValueOnce(appointmentsEs) }) it('creates message for each appointment', async () => { await subject.incomingAppointmentsChatNofitication() expect(messageRepository.create).toBeCalledTimes(10) }) it('creates message with correct text', async () => { await subject.incomingAppointmentsChatNofitication() const appointments = appointmentsPt.concat(appointmentsEs) appointments.forEach(appointment => { expect(messageRepository.create).toHaveBeenNthCalledWith( appointments.indexOf(appointment) + 1, expect.objectContaining({ patient_id: appointment.patient_id, user_id: appointment.user_id, replied_by_user_id: appointment.user_id, }), ) }) }) }) }) })