Actualizados los tests de bus-gateway!

This commit is contained in:
Alejandro Gomez Auad 2026-04-30 21:18:12 +00:00
parent ca4db597cc
commit b1cf91d992
5 changed files with 100 additions and 163 deletions

View File

@ -20,5 +20,9 @@
}, },
"devDependencies": { "devDependencies": {
"jest": "^30.3.0" "jest": "^30.3.0"
},
"jest": {
"testEnvironment": "node",
"setupFiles": ["./tests/setup.js"]
} }
} }

View File

@ -3,16 +3,14 @@ const axios = require('axios');
const { getBusToken } = require('../../utils/busAuth'); const { getBusToken } = require('../../utils/busAuth');
const { const {
createDocumentReference, createDocumentReference,
postDocumentReference, findDocumentReferenceBySubject,
searchDocumentReferenceBySubject, findDocumentReferenceByPatient,
searchDocumentReferenceByPatient,
searchDocumentReference, searchDocumentReference,
} = require('../../services/documentReference'); } = require('../../services/documentReference');
jest.mock('axios'); jest.mock('axios');
const BUS_URL = process.env.BUS_URL; 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_JWT_SECRET = process.env.BUS_JWT_SECRET;
const BUS_ISSUER = process.env.BUS_ISSUER; const BUS_ISSUER = process.env.BUS_ISSUER;
const BUS_SCOPE = process.env.DOCUMENT_REGISTRY_SCOPE; const BUS_SCOPE = process.env.DOCUMENT_REGISTRY_SCOPE;
@ -29,128 +27,66 @@ async function acquireToken() {
return getBusToken(BUS_URL, BUS_JWT_SECRET, BUS_ISSUER, BUS_SCOPE); return getBusToken(BUS_URL, BUS_JWT_SECRET, BUS_ISSUER, BUS_SCOPE);
} }
const CUSTODIAN_ID = 'efector-001'; // Internal URL used by the document registry (replaced by maskPrivateURL)
const BUNDLE_URL = 'http://hapi-fhir-host:8080/fhir/Bundle/abc123'; const INTERNAL_REGISTRY_BASE = 'https://federador.qa-bus-interoperabilidad.svc.cluster.local:8080/fhir/DocumentReference';
const IPS_BUNDLE = { const DOCUMENT_REFERENCE = {
resourceType: 'Bundle', resourceType: 'DocumentReference',
id: 'bundle-001', status: 'current',
entry: [ subject: {
{ identifier: { system: 'https://federador.msal.gob.ar/patient-id', value: '5037097' },
resource: { },
resourceType: 'Patient',
identifier: [
{ system: 'https://federador.msal.gob.ar/patient-id', value: '5037097' },
],
},
},
],
}; };
describe('createDocumentReference', () => { describe('createDocumentReference', () => {
it('builds a DocumentReference from IPS bundle using the first patient identifier', () => { it('POSTs a DocumentReference to the registry and returns the created resource', async () => {
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 token = await acquireToken();
const responseData = { resourceType: 'DocumentReference', id: 'dr-001' }; const responseData = { resourceType: 'DocumentReference', id: 'dr-001' };
mockRequest.post.mockResolvedValue({ data: responseData }); mockRequest.post.mockResolvedValue({
data: {},
const result = await postDocumentReference(REGISTRY_URL, token, IPS_BUNDLE, CUSTODIAN_ID, BUNDLE_URL); headers: { location: `${INTERNAL_REGISTRY_BASE}/dr-001` },
expect(axios.create).toHaveBeenCalledWith({
baseURL: REGISTRY_URL,
headers: {
'Content-Type': 'application/fhir+json',
'Authorization': `Bearer ${token}`,
},
}); });
expect(mockRequest.post).toHaveBeenCalledWith( mockRequest.get.mockResolvedValue({ data: responseData });
'/fhir/DocumentReference',
expect.objectContaining({ resourceType: 'DocumentReference' }) const result = await createDocumentReference(token, DOCUMENT_REFERENCE);
);
expect(mockRequest.post).toHaveBeenCalledWith(expect.anything(), DOCUMENT_REFERENCE);
expect(result).toEqual(responseData); expect(result).toEqual(responseData);
}); });
}); });
describe('searchDocumentReferenceBySubject', () => { describe('findDocumentReferenceBySubject', () => {
it('GETs /fhir/DocumentReference with subject param as system|value', async () => { it('GETs /fhir/DocumentReference with subject param as system|value', async () => {
const token = await acquireToken(); const token = await acquireToken();
const bundle = { resourceType: 'Bundle', entry: [] }; const bundle = { resourceType: 'Bundle', entry: [] };
mockRequest.get.mockResolvedValue({ data: bundle }); mockRequest.get.mockResolvedValue({ data: bundle });
const result = await searchDocumentReferenceBySubject( const result = await findDocumentReferenceBySubject(
REGISTRY_URL, token, token,
'https://federador.msal.gob.ar/patient-id', 'https://federador.msal.gob.ar/patient-id',
'5037097' '5037097'
); );
expect(mockRequest.get).toHaveBeenCalledWith('/fhir/DocumentReference', { expect(mockRequest.get).toHaveBeenCalledWith(
params: { subject: 'https://federador.msal.gob.ar/patient-id|5037097' }, expect.anything(),
}); { params: { subject: 'https://federador.msal.gob.ar/patient-id|5037097' } }
);
expect(result).toEqual(bundle); expect(result).toEqual(bundle);
}); });
}); });
describe('searchDocumentReferenceByPatient', () => { describe('findDocumentReferenceByPatient', () => {
it('GETs /fhir/DocumentReference with patient param', async () => { it('GETs /fhir/DocumentReference with patient ID as subject param', async () => {
const token = await acquireToken(); const token = await acquireToken();
const bundle = { resourceType: 'Bundle', entry: [] }; const bundle = { resourceType: 'Bundle', entry: [] };
mockRequest.get.mockResolvedValue({ data: bundle }); mockRequest.get.mockResolvedValue({ data: bundle });
const result = await searchDocumentReferenceByPatient(REGISTRY_URL, token, '5037097'); const result = await findDocumentReferenceByPatient(token, 'http://mpi/fhir/Patient/123');
expect(mockRequest.get).toHaveBeenCalledWith('/fhir/DocumentReference', { expect(mockRequest.get).toHaveBeenCalledWith(
params: { patient: '5037097' }, expect.anything(),
}); { params: { subject: 'http://mpi/fhir/Patient/123' } }
);
expect(result).toEqual(bundle); expect(result).toEqual(bundle);
}); });
}); });
@ -165,15 +101,18 @@ describe('searchDocumentReference', () => {
const custodian = { system: 'https://federador.msal.gob.ar/uri', value: 'efector-001' }; const custodian = { system: 'https://federador.msal.gob.ar/uri', value: 'efector-001' };
const type = { system: 'http://loinc.org', value: '60591-5' }; const type = { system: 'http://loinc.org', value: '60591-5' };
const result = await searchDocumentReference(REGISTRY_URL, token, subject, custodian, type); const result = await searchDocumentReference(token, subject, custodian, type);
expect(mockRequest.get).toHaveBeenCalledWith('/fhir/DocumentReference', { expect(mockRequest.get).toHaveBeenCalledWith(
params: { expect.anything(),
subject: 'https://federador.msal.gob.ar/patient-id|5037097', {
custodian: 'https://federador.msal.gob.ar/uri|efector-001', params: {
type: 'http://loinc.org|60591-5', 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); expect(result).toEqual(bundle);
}); });
}); });

View File

@ -1,17 +1,16 @@
require('dotenv').config(); require('dotenv').config();
const axios = require('axios'); const axios = require('axios');
const { getBusToken } = require('../../utils/busAuth'); const { getBusToken } = require('../../utils/busAuth');
const { postPatient, getPatientById, searchPatient, matchPatient } = require('../../services/patient'); const { createPatient, findPatientById, findPatient, findPatientByMatch } = require('../../services/patient');
jest.mock('axios'); jest.mock('axios');
const BUS_URL = process.env.BUS_URL; const BUS_URL = process.env.BUS_URL;
const MPI_URL = process.env.MPI_URL || process.env.BUS_URL;
const BUS_JWT_SECRET = process.env.BUS_JWT_SECRET; const BUS_JWT_SECRET = process.env.BUS_JWT_SECRET;
const BUS_ISSUER = process.env.BUS_ISSUER; const BUS_ISSUER = process.env.BUS_ISSUER;
const BUS_SCOPE = process.env.MPI_SCOPE; const BUS_SCOPE = process.env.MPI_SCOPE;
const mockRequest = { get: jest.fn(), post: jest.fn() }; const mockRequest = { get: jest.fn(), post: jest.fn(), put: jest.fn() };
beforeEach(() => { beforeEach(() => {
jest.clearAllMocks(); jest.clearAllMocks();
@ -23,49 +22,49 @@ async function acquireToken() {
return getBusToken(BUS_URL, BUS_JWT_SECRET, BUS_ISSUER, BUS_SCOPE); return getBusToken(BUS_URL, BUS_JWT_SECRET, BUS_ISSUER, BUS_SCOPE);
} }
describe('postPatient', () => { // Internal URL used by the MPI service (replaced by maskPrivateURL)
it('POSTs the patient to /fhir/Patient and returns response data', async () => { const INTERNAL_MPI_BASE = 'https://federador.qa-bus-interoperabilidad.svc.cluster.local:8080/masterfile-federacion-service/fhir/Patient';
describe('createPatient', () => {
it('POSTs the patient to the MPI and returns the created resource', async () => {
const token = await acquireToken(); const token = await acquireToken();
const patient = { resourceType: 'Patient', id: '1' }; const patient = { resourceType: 'Patient', id: '1' };
const responseData = { resourceType: 'Patient', id: '1', meta: {} }; const responseData = { resourceType: 'Patient', id: '1', meta: {} };
mockRequest.post.mockResolvedValue({ data: responseData }); mockRequest.post.mockResolvedValue({
data: {},
const result = await postPatient(MPI_URL, token, patient); headers: { location: `${INTERNAL_MPI_BASE}/1` },
expect(axios.create).toHaveBeenCalledWith({
baseURL: MPI_URL,
headers: {
'Content-Type': 'application/fhir+json',
'Authorization': `Bearer ${token}`,
},
}); });
expect(mockRequest.post).toHaveBeenCalledWith('/fhir/Patient', patient); mockRequest.get.mockResolvedValue({ data: responseData });
const result = await createPatient(token, patient);
expect(mockRequest.post).toHaveBeenCalledWith(expect.anything(), patient);
expect(result).toEqual(responseData); expect(result).toEqual(responseData);
}); });
}); });
describe('getPatientById', () => { describe('findPatientById', () => {
it('GETs /fhir/Patient/:id and returns response data', async () => { it('GETs the patient by ID and returns response data', async () => {
const token = await acquireToken(); const token = await acquireToken();
const responseData = { resourceType: 'Patient', id: '42' }; const responseData = { resourceType: 'Patient', id: '42' };
mockRequest.get.mockResolvedValue({ data: responseData }); mockRequest.get.mockResolvedValue({ data: responseData });
const result = await getPatientById(MPI_URL, token, '42'); const result = await findPatientById(token, '42');
expect(mockRequest.get).toHaveBeenCalledWith('/fhir/Patient/42'); expect(mockRequest.get).toHaveBeenCalledWith(expect.anything());
expect(result).toEqual(responseData); expect(result).toEqual(responseData);
}); });
}); });
describe('searchPatient', () => { describe('findPatient', () => {
it('GETs /fhir/Patient with no params when criteria is empty', async () => { it('GETs /fhir/Patient with no params when criteria is empty', async () => {
const token = await acquireToken(); const token = await acquireToken();
const bundle = { resourceType: 'Bundle', entry: [] }; const bundle = { resourceType: 'Bundle', entry: [] };
mockRequest.get.mockResolvedValue({ data: bundle }); mockRequest.get.mockResolvedValue({ data: bundle });
const result = await searchPatient(MPI_URL, token, {}); const result = await findPatient(token, {});
expect(mockRequest.get).toHaveBeenCalledWith('/fhir/Patient', { params: {} }); expect(mockRequest.get).toHaveBeenCalledWith(expect.anything(), { params: {} });
expect(result).toEqual(bundle); expect(result).toEqual(bundle);
}); });
@ -73,7 +72,7 @@ describe('searchPatient', () => {
const token = await acquireToken(); const token = await acquireToken();
mockRequest.get.mockResolvedValue({ data: {} }); mockRequest.get.mockResolvedValue({ data: {} });
await searchPatient(MPI_URL, token, { await findPatient(token, {
name: 'Juan', name: 'Juan',
family: 'Perez', family: 'Perez',
birthdate: '1983-04-17', birthdate: '1983-04-17',
@ -81,7 +80,7 @@ describe('searchPatient', () => {
phone: '1141233100', phone: '1141233100',
}); });
expect(mockRequest.get).toHaveBeenCalledWith('/fhir/Patient', { expect(mockRequest.get).toHaveBeenCalledWith(expect.anything(), {
params: { params: {
name: 'Juan', name: 'Juan',
family: 'Perez', family: 'Perez',
@ -92,42 +91,28 @@ describe('searchPatient', () => {
}); });
}); });
it('combines identifierSystem and identifierValue into identifier param', async () => { it('passes the identifier param directly when provided as system|value string', async () => {
const token = await acquireToken(); const token = await acquireToken();
mockRequest.get.mockResolvedValue({ data: {} }); mockRequest.get.mockResolvedValue({ data: {} });
await searchPatient(MPI_URL, token, { await findPatient(token, { identifier: 'http://www.renaper.gob.ar/dni|30945027' });
identifierSystem: 'http://www.renaper.gob.ar/dni',
identifierValue: '30945027',
});
expect(mockRequest.get).toHaveBeenCalledWith('/fhir/Patient', { expect(mockRequest.get).toHaveBeenCalledWith(expect.anything(), {
params: { identifier: 'http://www.renaper.gob.ar/dni|30945027' }, params: { identifier: 'http://www.renaper.gob.ar/dni|30945027' },
}); });
}); });
it('uses identifierValue alone when identifierSystem is not provided', async () => {
const token = await acquireToken();
mockRequest.get.mockResolvedValue({ data: {} });
await searchPatient(MPI_URL, token, { identifierValue: '30945027' });
expect(mockRequest.get).toHaveBeenCalledWith('/fhir/Patient', {
params: { identifier: '30945027' },
});
});
}); });
describe('matchPatient', () => { describe('findPatientByMatch', () => {
it('POSTs a Parameters resource to /fhir/Patient/$match', async () => { it('POSTs a Parameters resource to $match', async () => {
const token = await acquireToken(); const token = await acquireToken();
const patient = { resourceType: 'Patient', id: '1' }; const patient = { resourceType: 'Patient', id: '1' };
const bundle = { resourceType: 'Bundle', entry: [] }; const bundle = { resourceType: 'Bundle', entry: [] };
mockRequest.post.mockResolvedValue({ data: bundle }); mockRequest.post.mockResolvedValue({ data: bundle });
const result = await matchPatient(MPI_URL, token, patient); const result = await findPatientByMatch(token, patient);
expect(mockRequest.post).toHaveBeenCalledWith('/fhir/Patient/$match', { expect(mockRequest.post).toHaveBeenCalledWith(expect.anything(), {
resourceType: 'Parameters', resourceType: 'Parameters',
parameter: [{ name: 'resource', resource: patient }], parameter: [{ name: 'resource', resource: patient }],
}); });
@ -139,9 +124,9 @@ describe('matchPatient', () => {
const patient = { resourceType: 'Patient' }; const patient = { resourceType: 'Patient' };
mockRequest.post.mockResolvedValue({ data: {} }); mockRequest.post.mockResolvedValue({ data: {} });
await matchPatient(MPI_URL, token, patient, 3); await findPatientByMatch(token, patient, 3);
expect(mockRequest.post).toHaveBeenCalledWith('/fhir/Patient/$match', { expect(mockRequest.post).toHaveBeenCalledWith(expect.anything(), {
resourceType: 'Parameters', resourceType: 'Parameters',
parameter: [ parameter: [
{ name: 'resource', resource: patient }, { name: 'resource', resource: patient },
@ -155,7 +140,7 @@ describe('matchPatient', () => {
const patient = { resourceType: 'Patient' }; const patient = { resourceType: 'Patient' };
mockRequest.post.mockResolvedValue({ data: {} }); mockRequest.post.mockResolvedValue({ data: {} });
await matchPatient(MPI_URL, token, patient); await findPatientByMatch(token, patient);
const call = mockRequest.post.mock.calls[0]; const call = mockRequest.post.mock.calls[0];
const parameters = call[1]; const parameters = call[1];

View File

@ -0,0 +1,8 @@
process.env.BUS_URL = 'http://bus-host:8080';
process.env.BUS_JWT_SECRET = 'test-secret';
process.env.BUS_ISSUER = 'https://test-repositorio-url';
process.env.MPI_SCOPE = 'Patient/*.read,Patient/*.write';
process.env.DOCUMENT_REGISTRY_SCOPE = 'DocumentReference/*.read,DocumentReference/*.write';
process.env.FHIR_URL = 'http://hapi-fhir-host:8080/fhir';
process.env.MPI_URL = 'http://mpi-host:8080';
process.env.DOCUMENT_REGISTRY_URL = 'http://document-registry-host:8080';

View File

@ -89,19 +89,20 @@ describe('getBusToken', () => {
}); });
describe('createBusRequest', () => { describe('createBusRequest', () => {
it('creates an axios instance with the correct baseURL and headers', () => { it('creates an axios instance with Authorization and Content-Type headers', () => {
const mockInstance = { get: jest.fn(), post: jest.fn() }; const mockInstance = { get: jest.fn(), post: jest.fn() };
axios.create.mockReturnValue(mockInstance); axios.create.mockReturnValue(mockInstance);
const token = 'my-token'; const token = 'my-token';
createBusRequest(BUS_URL, token); createBusRequest(token);
expect(axios.create).toHaveBeenCalledWith({ expect(axios.create).toHaveBeenCalledWith(
baseURL: BUS_URL, expect.objectContaining({
headers: { headers: {
'Content-Type': 'application/fhir+json', 'Content-Type': 'application/fhir+json',
'Authorization': `Bearer ${token}`, 'Authorization': `Bearer ${token}`,
}, },
}); })
);
}); });
}); });