Skip to main content
Glama
patienteverything.test.ts9.19 kB
// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors // SPDX-License-Identifier: Apache-2.0 import { ContentType, LOINC, createReference, getReferenceString } from '@medplum/core'; import type { Bundle, BundleEntry, Condition, Observation, Organization, Patient, Practitioner, Resource, } from '@medplum/fhirtypes'; import express from 'express'; import request from 'supertest'; import { initApp, shutdownApp } from '../../app'; import { loadTestConfig } from '../../config/loader'; import { createTestProject, initTestAuth } from '../../test.setup'; import { searchPatientCompartment } from './patienteverything'; const app = express(); let accessToken: string; describe('Patient Everything Operation', () => { beforeAll(async () => { const config = await loadTestConfig(); await initApp(app, config); accessToken = await initTestAuth(); }); afterAll(async () => { await shutdownApp(); }); test('Success', async () => { // Create organization const orgRes = await request(app) .post(`/fhir/R4/Organization`) .set('Authorization', 'Bearer ' + accessToken) .set('Content-Type', ContentType.FHIR_JSON) .send({ resourceType: 'Organization' }); expect(orgRes.status).toBe(201); const organization = orgRes.body as Organization; // Create practitioner const practRes = await request(app) .post(`/fhir/R4/Practitioner`) .set('Authorization', 'Bearer ' + accessToken) .set('Content-Type', ContentType.FHIR_JSON) .send({ resourceType: 'Practitioner', qualification: [{ code: { text: 'MD' }, issuer: createReference(organization) }], }); expect(practRes.status).toBe(201); const practitioner = practRes.body as Practitioner; // Create patient const res1 = await request(app) .post(`/fhir/R4/Patient`) .set('Authorization', 'Bearer ' + accessToken) .set('Content-Type', ContentType.FHIR_JSON) .send({ resourceType: 'Patient', name: [{ given: ['Alice'], family: 'Smith' }], address: [{ use: 'home', line: ['123 Main St'], city: 'Anywhere', state: 'CA', postalCode: '90210' }], telecom: [ { system: 'phone', value: '555-555-5555' }, { system: 'email', value: 'alice@example.com' }, ], managingOrganization: createReference(organization), } satisfies Patient); expect(res1.status).toBe(201); const patient = res1.body as Patient; // Create observation const res2 = await request(app) .post(`/fhir/R4/Observation`) .set('Authorization', 'Bearer ' + accessToken) .set('Content-Type', ContentType.FHIR_JSON) .send({ resourceType: 'Observation', status: 'final', code: { coding: [{ system: LOINC, code: '12345-6' }] }, subject: createReference(patient), performer: [createReference(practitioner), createReference(organization)], } satisfies Observation); expect(res2.status).toBe(201); const observation = res2.body as Observation; // Create condition // This condition references the patient twice, once as subject and once as asserter // This is to test that the condition is only returned once const res3 = await request(app) .post(`/fhir/R4/Condition`) .set('Authorization', 'Bearer ' + accessToken) .set('Content-Type', ContentType.FHIR_JSON) .send({ resourceType: 'Condition', code: { coding: [{ system: LOINC, code: '12345-6' }] }, asserter: createReference(patient), subject: createReference(patient), recorder: createReference(practitioner), } satisfies Condition); expect(res3.status).toBe(201); const condition = res3.body as Condition; // Execute the operation const res4 = await request(app) .get(`/fhir/R4/Patient/${patient.id}/$everything`) .set('Authorization', 'Bearer ' + accessToken); expect(res4.status).toBe(200); const result = res4.body as Bundle; expect(result.entry?.length).toStrictEqual(5); expect( result.entry?.map((e) => `${e.search?.mode}:${getReferenceString(e.resource as Resource)}`).sort() ).toStrictEqual([ 'include:' + getReferenceString(organization), 'include:' + getReferenceString(practitioner), 'match:' + getReferenceString(condition), 'match:' + getReferenceString(observation), 'match:' + getReferenceString(patient), ]); // Create another observation const res5 = await request(app) .post(`/fhir/R4/Observation`) .set('Authorization', 'Bearer ' + accessToken) .set('Content-Type', ContentType.FHIR_JSON) .send({ resourceType: 'Observation', status: 'final', code: { coding: [{ system: LOINC, code: '12345-6' }] }, subject: createReference(patient), performer: [createReference(practitioner), createReference(organization)], } satisfies Observation); expect(res5.status).toBe(201); const newObservation = res5.body as Observation; // Execute the operation with _since const res6 = await request(app) .get(`/fhir/R4/Patient/${patient.id}/$everything?_since=${newObservation.meta?.lastUpdated}`) .set('Authorization', 'Bearer ' + accessToken); expect(res6.status).toBe(200); const sinceResult = res6.body as Bundle; expect( sinceResult.entry?.map((e) => `${e.search?.mode}:${getReferenceString(e.resource as Resource)}`).sort() ).toStrictEqual([ 'include:' + getReferenceString(organization), 'include:' + getReferenceString(practitioner), 'match:' + getReferenceString(newObservation), ]); // Execute the operation with _count and _offset const res7 = await request(app) .get(`/fhir/R4/Patient/${patient.id}/$everything?_count=1&_offset=1`) .set('Authorization', 'Bearer ' + accessToken); expect(res7.status).toBe(200); // Bundle should have pagination links const bundle = res7.body as Bundle; expect(bundle.link).toBeDefined(); expect(bundle.link?.some((link) => link.relation === 'next')).toBeTruthy(); expect(bundle.link?.some((link) => link.relation === 'first')).toBeTruthy(); expect(bundle.link?.some((link) => link.relation === 'previous')).toBeTruthy(); // Execute the operation with "start" and "end" parameters const res8 = await request(app) .get(`/fhir/R4/Patient/${patient.id}/$everything?start=2020-01-01&end=2040-01-01`) .set('Authorization', 'Bearer ' + accessToken); expect(res8.status).toBe(200); }); }); describe('searchPatientCompartment', () => { beforeEach(async () => { const config = await loadTestConfig(); await initApp(app, config); }); afterEach(async () => { await shutdownApp(); }); test('Successfully paginates through resource types', async () => { const { repo } = await createTestProject({ withRepo: true }); const organization = await repo.createResource<Organization>({ resourceType: 'Organization' }); const practitioner = await repo.createResource<Practitioner>({ resourceType: 'Practitioner' }); const patient = await repo.createResource<Patient>({ resourceType: 'Patient', name: [{ given: ['Alice'], family: 'Smith' }], address: [{ use: 'home', line: ['123 Main St'], city: 'Anywhere', state: 'CA', postalCode: '90210' }], telecom: [ { system: 'phone', value: '555-555-5555' }, { system: 'email', value: 'alice@example.com' }, ], managingOrganization: createReference(organization), }); const observation = await repo.createResource<Observation>({ resourceType: 'Observation', status: 'final', code: { coding: [{ system: LOINC, code: '12345-6' }] }, subject: createReference(patient), performer: [createReference(practitioner), createReference(organization)], }); // This condition references the patient twice, once as subject and once as asserter // This is to test that the condition is only returned once const condition = await repo.createResource({ resourceType: 'Condition', code: { coding: [{ system: LOINC, code: '12345-6' }] }, asserter: createReference(patient), subject: createReference(patient), recorder: createReference(practitioner), }); // Force search to paginate to ensure that it's handled correctly const results: BundleEntry[] = []; let offset = 0; while (offset < 100) { const bundle = await searchPatientCompartment(repo, patient, { count: 1, offset }); if (bundle.entry?.length) { results.push(...bundle.entry); offset += bundle.entry.length; } else { break; } } expect(results).toHaveLength(3); expect(results).toStrictEqual( expect.arrayContaining<BundleEntry>([ expect.objectContaining({ resource: patient, search: { mode: 'match' } }), expect.objectContaining({ resource: observation, search: { mode: 'match' } }), expect.objectContaining({ resource: condition, search: { mode: 'match' } }), ]) ); }); });

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/medplum/medplum'

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