require('dotenv').config(); const axios = require('axios'); const { getBusToken } = require('../../utils/busAuth'); const { createDocumentReference, postDocumentReference, searchDocumentReferenceBySubject, searchDocumentReferenceByPatient, searchDocumentReference, } = require('../../services/documentReference'); jest.mock('axios'); const BUS_URL = process.env.BUS_URL; const REGISTRY_URL = process.env.DOCUMENT_REGISTRY_URL || process.env.BUS_URL; const BUS_JWT_SECRET = process.env.BUS_JWT_SECRET; const BUS_ISSUER = process.env.BUS_ISSUER; const BUS_SCOPE = process.env.DOCUMENT_REGISTRY_SCOPE; const mockRequest = { get: jest.fn(), post: jest.fn() }; beforeEach(() => { jest.clearAllMocks(); axios.create.mockReturnValue(mockRequest); }); async function acquireToken() { axios.post.mockResolvedValueOnce({ data: { accessToken: 'acquired-token' } }); return getBusToken(BUS_URL, BUS_JWT_SECRET, BUS_ISSUER, BUS_SCOPE); } const CUSTODIAN_ID = 'efector-001'; const BUNDLE_URL = 'http://hapi-fhir-host:8080/fhir/Bundle/abc123'; const IPS_BUNDLE = { resourceType: 'Bundle', id: 'bundle-001', entry: [ { resource: { resourceType: 'Patient', identifier: [ { system: 'https://federador.msal.gob.ar/patient-id', value: '5037097' }, ], }, }, ], }; describe('createDocumentReference', () => { it('builds a DocumentReference from IPS bundle using the first patient identifier', () => { const dr = createDocumentReference(IPS_BUNDLE, CUSTODIAN_ID, BUNDLE_URL); expect(dr.resourceType).toBe('DocumentReference'); expect(dr.status).toBe('current'); expect(dr.type.coding[0].code).toBe('60591-5'); expect(dr.subject.identifier).toEqual({ system: 'https://federador.msal.gob.ar/patient-id', value: '5037097', }); expect(dr.custodian.identifier).toEqual({ system: 'https://federador.msal.gob.ar/uri', value: CUSTODIAN_ID, }); expect(dr.content[0].attachment.url).toBe(BUNDLE_URL); }); it('uses subjectIdentifier when provided instead of patient identifier', () => { const subjectIdentifier = { system: 'http://www.renaper.gob.ar/dni', value: '30945027' }; const dr = createDocumentReference(IPS_BUNDLE, CUSTODIAN_ID, BUNDLE_URL, subjectIdentifier); expect(dr.subject.identifier).toEqual(subjectIdentifier); }); it('falls back to Bundle/{id} when bundleUrl is not provided', () => { const dr = createDocumentReference(IPS_BUNDLE, CUSTODIAN_ID); expect(dr.content[0].attachment.url).toBe(`Bundle/${IPS_BUNDLE.id}`); }); it('throws when the bundle has no Patient entry', () => { const bundleWithoutPatient = { ...IPS_BUNDLE, entry: [] }; expect(() => createDocumentReference(bundleWithoutPatient, CUSTODIAN_ID)).toThrow( 'IPS Bundle does not contain a Patient resource' ); }); it('throws when the patient has no identifier', () => { const bundleNoIdentifier = { ...IPS_BUNDLE, entry: [{ resource: { resourceType: 'Patient', identifier: [] } }], }; expect(() => createDocumentReference(bundleNoIdentifier, CUSTODIAN_ID)).toThrow( 'Patient resource has no identifier' ); }); }); describe('postDocumentReference', () => { it('POSTs a DocumentReference to /fhir/DocumentReference and returns response data', async () => { const token = await acquireToken(); const responseData = { resourceType: 'DocumentReference', id: 'dr-001' }; mockRequest.post.mockResolvedValue({ data: responseData }); const result = await postDocumentReference(REGISTRY_URL, token, IPS_BUNDLE, CUSTODIAN_ID, BUNDLE_URL); expect(axios.create).toHaveBeenCalledWith({ baseURL: REGISTRY_URL, headers: { 'Content-Type': 'application/fhir+json', 'Authorization': `Bearer ${token}`, }, }); expect(mockRequest.post).toHaveBeenCalledWith( '/fhir/DocumentReference', expect.objectContaining({ resourceType: 'DocumentReference' }) ); expect(result).toEqual(responseData); }); }); describe('searchDocumentReferenceBySubject', () => { it('GETs /fhir/DocumentReference with subject param as system|value', async () => { const token = await acquireToken(); const bundle = { resourceType: 'Bundle', entry: [] }; mockRequest.get.mockResolvedValue({ data: bundle }); const result = await searchDocumentReferenceBySubject( REGISTRY_URL, token, 'https://federador.msal.gob.ar/patient-id', '5037097' ); expect(mockRequest.get).toHaveBeenCalledWith('/fhir/DocumentReference', { params: { subject: 'https://federador.msal.gob.ar/patient-id|5037097' }, }); expect(result).toEqual(bundle); }); }); describe('searchDocumentReferenceByPatient', () => { it('GETs /fhir/DocumentReference with patient param', async () => { const token = await acquireToken(); const bundle = { resourceType: 'Bundle', entry: [] }; mockRequest.get.mockResolvedValue({ data: bundle }); const result = await searchDocumentReferenceByPatient(REGISTRY_URL, token, '5037097'); expect(mockRequest.get).toHaveBeenCalledWith('/fhir/DocumentReference', { params: { patient: '5037097' }, }); expect(result).toEqual(bundle); }); }); describe('searchDocumentReference', () => { it('GETs /fhir/DocumentReference with subject, custodian and type params', async () => { const token = await acquireToken(); const bundle = { resourceType: 'Bundle', entry: [] }; mockRequest.get.mockResolvedValue({ data: bundle }); const subject = { system: 'https://federador.msal.gob.ar/patient-id', value: '5037097' }; const custodian = { system: 'https://federador.msal.gob.ar/uri', value: 'efector-001' }; const type = { system: 'http://loinc.org', value: '60591-5' }; const result = await searchDocumentReference(REGISTRY_URL, token, subject, custodian, type); expect(mockRequest.get).toHaveBeenCalledWith('/fhir/DocumentReference', { params: { subject: 'https://federador.msal.gob.ar/patient-id|5037097', custodian: 'https://federador.msal.gob.ar/uri|efector-001', type: 'http://loinc.org|60591-5', }, }); expect(result).toEqual(bundle); }); });