Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions src/extractors/FHIRAdverseEventExtractor.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const { BaseFHIRExtractor } = require('./BaseFHIRExtractor');
const { getResearchStudiesFromContext } = require('../helpers/contextUtils');
const logger = require('../helpers/logger');

const BASE_STUDY = ''; // No base study specified

Expand All @@ -12,14 +14,28 @@ class FHIRAdverseEventExtractor extends BaseFHIRExtractor {
// In addition to default parametrization, add study if specified
async parametrizeArgsForFHIRModule({ context }) {
const paramsWithID = await super.parametrizeArgsForFHIRModule({ context });
let allResearchStudyResources = [];
try {
allResearchStudyResources = getResearchStudiesFromContext(context);
} catch (e) {
logger.error(e.message);
logger.debug(e.stack);
}

// The patient is referenced in the 'subject' field of an AdverseEvent
paramsWithID.subject = paramsWithID.patient;
delete paramsWithID.patient;
// Only add study to parameters if it has been specified
return {

// If there are research study resources, create a parameters object for each call to be made
const newStudyIds = allResearchStudyResources.map((rs) => rs.id).join(',');
const studyIdsForCurrentPatient = `${this.study}${this.study && newStudyIds ? ',' : ''}${newStudyIds}`;

// Only add study to parameters if it has been specified or was included from context
const obj = {
...paramsWithID,
...(this.study && { study: this.study }),
...(studyIdsForCurrentPatient && { study: studyIdsForCurrentPatient }),
};
return obj;
}
}

Expand Down
11 changes: 11 additions & 0 deletions src/helpers/contextUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,20 @@ function getEncountersFromContext(context) {
return encounterResourcesInContext;
}

function getResearchStudiesFromContext(context) {
logger.debug('Getting ResearchStudy resources from context');
const researchStudyResourcesInContext = getBundleResourcesByType(context, 'ResearchStudy', {}, false);
if (researchStudyResourcesInContext.length === 0) {
throw Error('Could not find any ResearchStudy resources in context; ensure that a ClinicalTrialInformationExtractor or ResearchStudyExtractor is used earlier in your extraction configuration');
}
logger.debug(`ResearchStudy resources found in context. Found ${researchStudyResourcesInContext.length} ResearchStudy resources.`);
return researchStudyResourcesInContext;
}

module.exports = {
getConditionEntriesFromContext,
getConditionsFromContext,
getEncountersFromContext,
getPatientFromContext,
getResearchStudiesFromContext,
};
34 changes: 34 additions & 0 deletions test/extractors/FHIRAdverseEventExtractor.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,28 @@ const MOCK_CONTEXT = {
},
],
};
const researchStudyResource = {
resourceType: 'ResearchStudy',
id: 'ResearchStudyExample01',
};
const MOCK_CONTEXT_WITH_RESEARCH_STUDY = {
resourceType: 'Bundle',
type: 'collection',
entry: [
{
fullUrl: 'context-url-1',
resource: { resourceType: 'Patient', id: MOCK_MRN },
},
{
fullUrl: 'context-url-2',
resource: researchStudyResource,
},
{
fullUrl: 'context-url-3',
resource: { ...researchStudyResource, id: 'ResearchStudyExample02' },
},
],
};

// Construct extractor and create spies for mocking responses
const extractor = new FHIRAdverseEventExtractor({ baseFhirUrl: MOCK_URL, requestHeaders: MOCK_HEADERS });
Expand All @@ -40,6 +62,12 @@ describe('FHIRAdverseEventExtractor', () => {
expect(params).not.toHaveProperty('study');
});

test('should add study id for all ResearchStudy resources that are in context', async () => {
const params = await extractor.parametrizeArgsForFHIRModule({ context: MOCK_CONTEXT_WITH_RESEARCH_STUDY });
expect(params).toHaveProperty('study');
expect(params.study).toEqual(`${researchStudyResource.id},ResearchStudyExample02`);
});

describe('pass in optional study parameter', () => {
test('should add study when set to param values', async () => {
const params = await extractorWithStudy.parametrizeArgsForFHIRModule({ context: MOCK_CONTEXT });
Expand All @@ -51,6 +79,12 @@ describe('FHIRAdverseEventExtractor', () => {
const params = await extractorWithStudy.parametrizeArgsForFHIRModule({ context: MOCK_CONTEXT });
expect(params).not.toHaveProperty('patient');
});

test('should add study from study parameter and from context', async () => {
const params = await extractorWithStudy.parametrizeArgsForFHIRModule({ context: MOCK_CONTEXT_WITH_RESEARCH_STUDY });
expect(params).toHaveProperty('study');
expect(params.study).toEqual(`${extractorWithStudy.study},${researchStudyResource.id},ResearchStudyExample02`);
});
});
});
});
44 changes: 40 additions & 4 deletions test/helpers/contextUtils.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
const { getConditionEntriesFromContext, getConditionsFromContext, getEncountersFromContext, getPatientFromContext } = require('../../src/helpers/contextUtils');

const MOCK_PATIENT_MRN = '123';
const {
getConditionEntriesFromContext,
getConditionsFromContext,
getEncountersFromContext,
getPatientFromContext,
getResearchStudiesFromContext,
} = require('../../src/helpers/contextUtils');

describe('getPatientFromContext', () => {
const patientResource = {
Expand Down Expand Up @@ -124,7 +128,39 @@ describe('getEncountersFromContext', () => {
});

test('Should throw an error if there are no encounters in context', () => {
expect(() => getEncountersFromContext(MOCK_PATIENT_MRN, {}))
expect(() => getEncountersFromContext({}))
.toThrow('Could not find any encounter resources in context; ensure that an EncounterExtractor is used earlier in your extraction configuration');
});
});

describe('getResearchStudyFromContext', () => {
const researchStudyResource = {
resourceType: 'ResearchStudy',
id: 'ResearchStudyExample01',
};
const researchStudyContext = {
resourceType: 'Bundle',
type: 'collection',
entry: [
{
fullUrl: 'context-url-1',
resource: researchStudyResource,
},
{
fullUrl: 'context-url-2',
resource: { ...researchStudyResource, id: 'ResearchStudyExample02' },
},
],
};

test('Should return all ResearchStudy resources in context', () => {
const researchStudyResources = getResearchStudiesFromContext(researchStudyContext);
expect(researchStudyResources).toHaveLength(2);
expect(researchStudyResources[0]).toEqual(researchStudyResource);
});

test('Should throw an error if there are no research studies in context', () => {
expect(() => getResearchStudiesFromContext({}))
.toThrow('Could not find any ResearchStudy resources in context; ensure that a ClinicalTrialInformationExtractor or ResearchStudyExtractor is used earlier in your extraction configuration');
});
});