Skip to main content
Glama
condition.integration.test.ts11.5 kB
import { Condition, OperationOutcome, Patient, Reference, CodeableConcept, } from '@medplum/fhirtypes'; import { createCondition, getConditionById, searchConditions, updateCondition, CreateConditionArgs, UpdateConditionArgs, ConditionClinicalStatusCodes, ConditionVerificationStatusCodes, } from '../../src/tools/conditionUtils'; import { medplum } from '../../src/config/medplumClient'; import { randomUUID } from 'crypto'; const createdConditionIds: string[] = []; let testPatient: Patient; describe('Condition Utils Integration Tests', () => { beforeAll(async () => { try { // Create a test patient for the conditions to be linked to const patientToCreate: Patient = { resourceType: 'Patient', name: [{ given: ['ConditionTest'], family: `Patient-${randomUUID()}` }], }; testPatient = await medplum.createResource(patientToCreate); console.log('Test patient created for condition tests:', testPatient.id); } catch (error) { console.error('Failed to create test patient for condition tests', error); throw error; // Fail all tests if patient creation fails } }); afterAll(async () => { console.log(`Cleaning up ${createdConditionIds.length} condition(s)...`); for (const id of createdConditionIds) { try { await medplum.deleteResource('Condition', id); } catch (error: any) { console.error(`Error deleting condition ${id}:`, error.message); } } if (testPatient?.id) { try { await medplum.deleteResource('Patient', testPatient.id); console.log(`Test patient ${testPatient.id} deleted.`); } catch (error) { console.error('Failed to delete test patient', error); } } }); describe('createCondition', () => { test('should create a new condition with minimal valid data', async () => { const args: CreateConditionArgs = { subject: { reference: `Patient/${testPatient.id}` }, code: { coding: [ { system: 'http://snomed.info/sct', code: '44054006', display: 'Type 2 diabetes mellitus', }, ], text: 'Type 2 Diabetes', }, // Rely on default clinicalStatus and verificationStatus }; const result = await createCondition(args); console.log('Create condition result:', JSON.stringify(result, null, 2)); expect(result).toBeDefined(); expect(result.resourceType).toBe('Condition'); const condition = result as Condition; expect(condition.id).toBeDefined(); if (condition.id) { createdConditionIds.push(condition.id); } expect(condition.subject?.reference).toBe(`Patient/${testPatient.id}`); expect(condition.code?.coding?.[0]?.code).toBe('44054006'); expect(condition.clinicalStatus?.coding?.[0]?.code).toBe('active'); // Default }); test('should create a new condition with all fields', async () => { const recordedDate = new Date().toISOString(); const args: CreateConditionArgs = { subject: { reference: `Patient/${testPatient.id}` }, code: { coding: [{ system: 'http://snomed.info/sct', code: '38341003', display: 'Hypertension' }], text: 'Hypertension', }, clinicalStatus: { coding: [ConditionClinicalStatusCodes.RESOLVED] }, verificationStatus: { coding: [ConditionVerificationStatusCodes.CONFIRMED] }, category: [{ coding: [{ system: 'http://terminology.hl7.org/CodeSystem/condition-category', code: 'encounter-diagnosis', display: 'Encounter Diagnosis', }] }], onsetString: 'Approximately 2 years ago', recordedDate, }; const result = await createCondition(args); const condition = result as Condition; if (condition.id) createdConditionIds.push(condition.id); expect(condition.resourceType).toBe('Condition'); expect(condition.clinicalStatus?.coding?.[0]?.code).toBe('resolved'); expect(condition.verificationStatus?.coding?.[0]?.code).toBe('confirmed'); expect(condition.category?.[0]?.coding?.[0]?.code).toBe('encounter-diagnosis'); expect(condition.onsetString).toBe('Approximately 2 years ago'); expect(condition.recordedDate).toBe(recordedDate); }); test('should return OperationOutcome if subject is missing', async () => { const args = { code: { text: 'No subject condition' }, } as unknown as CreateConditionArgs; const result = await createCondition(args); expect(result.resourceType).toBe('OperationOutcome'); const outcome = result as OperationOutcome; expect(outcome.issue?.[0]?.diagnostics).toContain('Patient subject reference is required'); }); }); describe('getConditionById', () => { let testCondition: Condition; beforeAll(async () => { const result = await createCondition({ subject: { reference: `Patient/${testPatient.id}` }, code: { coding: [{ system: 'http://test.com', code: 'GET-TEST', display: 'Condition for get test' }], text: 'Condition for get test' }, }); testCondition = result as Condition; if (testCondition.id) { createdConditionIds.push(testCondition.id); } }); test('should retrieve an existing condition by its ID', async () => { const result = await getConditionById(testCondition.id as string); expect(result).toBeDefined(); expect(result!.resourceType).toBe('Condition'); const condition = result as Condition; expect(condition.id).toBe(testCondition.id); expect(condition.code?.text).toBe('Condition for get test'); }); test('should return null for a non-existent condition ID', async () => { const nonExistentId = randomUUID(); const result = await getConditionById(nonExistentId); expect(result).toBeNull(); }); }); describe('updateCondition', () => { let conditionToUpdate: Condition; beforeEach(async () => { // Use beforeEach to get a fresh condition for each update test const result = await createCondition({ subject: { reference: `Patient/${testPatient.id}` }, code: { coding: [{ system: 'http://test.com', code: 'UPDATE-TEST', display: 'Condition to be updated' }], text: 'Condition to be updated' }, clinicalStatus: { coding: [ConditionClinicalStatusCodes.ACTIVE] }, onsetString: "Original onset" }); conditionToUpdate = result as Condition; if (conditionToUpdate.id) { createdConditionIds.push(conditionToUpdate.id); } }); test('should update the clinicalStatus of a condition', async () => { const args: UpdateConditionArgs = { id: conditionToUpdate.id as string, clinicalStatus: { coding: [ConditionClinicalStatusCodes.INACTIVE] }, }; const result = await updateCondition(args); expect(result.resourceType).toBe('Condition'); const updated = result as Condition; expect(updated.id).toBe(conditionToUpdate.id); expect(updated.clinicalStatus?.coding?.[0]?.code).toBe('inactive'); expect(updated.code?.text).toBe('Condition to be updated'); // Ensure other fields are preserved }); test('should remove a field when updated with null', async () => { const args: UpdateConditionArgs = { id: conditionToUpdate.id as string, onsetString: null }; const result = await updateCondition(args); expect(result.resourceType).toBe('Condition'); const updated = result as Condition; expect(updated.id).toBe(conditionToUpdate.id); expect(updated.onsetString).toBeUndefined(); }); }); describe('searchConditions', () => { beforeAll(async () => { // Clean up any conditions from other tests for (const id of createdConditionIds) { await medplum.deleteResource('Condition', id); } createdConditionIds.length = 0; // Reset the array // Create a set of conditions for searching const conditionsToCreate = [ { subject: { reference: `Patient/${testPatient.id}` }, code: { coding: [{ system: 'test', code: 'C-1' }], text: 'Active Test Condition' }, clinicalStatus: { coding: [ConditionClinicalStatusCodes.ACTIVE] } }, { subject: { reference: `Patient/${testPatient.id}` }, code: { coding: [{ system: 'test', code: 'C-2' }], text: 'Inactive Test Condition' }, clinicalStatus: { coding: [ConditionClinicalStatusCodes.INACTIVE] } }, { subject: { reference: `Patient/${testPatient.id}` }, code: { coding: [{ system: 'test', code: 'C-3' }], text: 'Resolved Encounter Diagnosis' }, clinicalStatus: { coding: [ConditionClinicalStatusCodes.RESOLVED] }, category: [{ coding: [{ code: 'encounter-diagnosis' }]}] }, ]; for (const c of conditionsToCreate) { const result = await createCondition(c); if(result.resourceType === 'Condition' && result.id) { createdConditionIds.push(result.id); } } }); test('should find conditions by subject ID', async () => { const result = await searchConditions({ subject: testPatient.id as string }); expect(result).toBeInstanceOf(Array); const conditions = result as Condition[]; expect(conditions.length).toBeGreaterThanOrEqual(3); expect(conditions.every(c => c.subject?.reference === `Patient/${testPatient.id}`)).toBe(true); }); test('should find conditions by clinical-status', async () => { const result = await searchConditions({ subject: testPatient.id, 'clinical-status': 'inactive' }); expect(result).toBeInstanceOf(Array); const conditions = result as Condition[]; expect(conditions.length).toBe(1); expect(conditions[0].clinicalStatus?.coding?.[0]?.code).toBe('inactive'); expect(conditions[0].code?.coding?.[0]?.code).toBe('C-2'); }); test('should find conditions by code', async () => { const result = await searchConditions({ subject: testPatient.id, code: 'test|C-1' }); expect(result).toBeInstanceOf(Array); const conditions = result as Condition[]; expect(conditions.length).toBe(1); expect(conditions[0].code?.coding?.[0]?.code).toBe('C-1'); }); test('should find conditions by category', async () => { const result = await searchConditions({ subject: testPatient.id, category: 'encounter-diagnosis' }); expect(result).toBeInstanceOf(Array); const conditions = result as Condition[]; expect(conditions.length).toBe(1); expect(conditions[0].code?.coding?.[0]?.code).toBe('C-3'); }); test('should return an empty array for non-matching criteria', async () => { const result = await searchConditions({ subject: testPatient.id as string, code: 'non-existent' }); expect(result).toBeInstanceOf(Array); expect((result as Condition[]).length).toBe(0); }); test('should return OperationOutcome if no criteria provided', async () => { const result = await searchConditions({}); expect(result).not.toBeInstanceOf(Array); if (!Array.isArray(result)) { expect(result.resourceType).toBe('OperationOutcome'); } else { fail('Expected OperationOutcome but received an array of conditions.'); } }); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/rkirkendall/medplum-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server