Skip to main content
Glama
codesystemlookup.test.ts16.6 kB
// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors // SPDX-License-Identifier: Apache-2.0 import { ContentType } from '@medplum/core'; import type { CodeSystem, OperationOutcome, Parameters } 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(); const testCodeSystem: CodeSystem = { resourceType: 'CodeSystem', url: 'http://example.com/test-code-system-' + randomUUID(), name: 'testCodeSystem', title: 'Test Code System', status: 'active', hierarchyMeaning: 'is-a', content: 'complete', property: [ { code: 'parent', uri: 'http://hl7.org/fhir/concept-properties#parent', description: 'Test parent property', type: 'code', }, { code: 'abstract', uri: 'http://hl7.org/fhir/concept-properties#notSelectable', description: 'Code is not a real thing', type: 'boolean', }, { code: 'publishedOn', type: 'dateTime', }, { code: 'rank', type: 'integer', }, ], concept: [ { code: '4', display: 'Procedure', concept: [ { code: '3', display: 'Procedure on head', concept: [ { code: '2', display: 'Biopsy of head', concept: [{ code: '1', display: 'Biopsy of brain' }], property: [ { code: 'abstract', valueBoolean: true, }, ], }, ], }, ], }, ], }; describe('CodeSystem lookup', () => { let codeSystem: CodeSystem; let accessToken: string; beforeAll(async () => { const config = await loadTestConfig(); await initApp(app, config); accessToken = await initTestAuth({ membership: { admin: true } }); expect(accessToken).toBeDefined(); const res = await request(app) .post('/fhir/R4/CodeSystem') .set('Authorization', 'Bearer ' + accessToken) .set('Content-Type', ContentType.FHIR_JSON) .send(testCodeSystem); expect(res.status).toStrictEqual(201); codeSystem = res.body as CodeSystem; }); afterAll(async () => { await shutdownApp(); }); test('Success', async () => { const res = await request(app) .post('/fhir/R4/CodeSystem/$lookup') .set('Authorization', 'Bearer ' + accessToken) .set('Content-Type', 'application/fhir+json') .send({ resourceType: 'Parameters', parameter: [ { name: 'system', valueUri: codeSystem.url }, { name: 'code', valueCode: '1' }, ], } as Parameters); expect(res.status).toStrictEqual(200); expect(res.body).toMatchObject<Parameters>({ resourceType: 'Parameters', parameter: [ { name: 'name', valueString: 'Test Code System' }, { name: 'display', valueString: 'Biopsy of brain' }, { name: 'property', part: [ { name: 'code', valueCode: 'parent' }, { name: 'value', valueCode: '2' }, { name: 'description', valueString: 'Biopsy of head' }, ], }, ], }); }); test('Renders description for relationship and simple properties', async () => { const res = await request(app) .post('/fhir/R4/CodeSystem/$lookup') .set('Authorization', 'Bearer ' + accessToken) .set('Content-Type', 'application/fhir+json') .send({ resourceType: 'Parameters', parameter: [ { name: 'system', valueUri: codeSystem.url }, { name: 'code', valueCode: '2' }, ], } as Parameters); expect(res.status).toStrictEqual(200); expect(res.body).toMatchObject<Parameters>({ resourceType: 'Parameters', parameter: expect.arrayContaining([ { name: 'name', valueString: 'Test Code System' }, { name: 'display', valueString: 'Biopsy of head' }, { name: 'property', part: [ { name: 'code', valueCode: 'parent' }, { name: 'value', valueCode: '3' }, { name: 'description', valueString: 'Procedure on head' }, ], }, { name: 'property', part: [ { name: 'code', valueCode: 'abstract' }, { name: 'value', valueBoolean: true }, { name: 'description', valueString: 'Code is not a real thing' }, ], }, ]), }); }); test('Coding parameter', async () => { const res = await request(app) .post('/fhir/R4/CodeSystem/$lookup') .set('Authorization', 'Bearer ' + accessToken) .set('Content-Type', 'application/fhir+json') .send({ resourceType: 'Parameters', parameter: [{ name: 'coding', valueCoding: { system: codeSystem.url, code: '1' } }], } as Parameters); expect(res.status).toStrictEqual(200); expect(res.body).toMatchObject<Parameters>({ resourceType: 'Parameters', parameter: [ { name: 'name', valueString: 'Test Code System' }, { name: 'display', valueString: 'Biopsy of brain' }, { name: 'property', part: [ { name: 'code', valueCode: 'parent' }, { name: 'value', valueCode: '2' }, { name: 'description', valueString: 'Biopsy of head' }, ], }, ], }); }); test('Not found', async () => { const res = await request(app) .post('/fhir/R4/CodeSystem/$lookup') .set('Authorization', 'Bearer ' + accessToken) .set('Content-Type', 'application/fhir+json') .send({ resourceType: 'Parameters', parameter: [ { name: 'system', valueUri: codeSystem.url }, { name: 'code', valueCode: 'wrong code' }, ], } as Parameters); expect(res.status).toStrictEqual(404); expect(res.body).toMatchObject<OperationOutcome>({ resourceType: 'OperationOutcome', issue: [{ severity: 'error', code: 'not-found', details: { text: 'Not found' } }], }); }); test('No full coding specified', async () => { const res = await request(app) .post('/fhir/R4/CodeSystem/$lookup') .set('Authorization', 'Bearer ' + accessToken) .set('Content-Type', 'application/fhir+json') .send({ resourceType: 'Parameters', parameter: [{ name: 'code', valueCode: '1' }], } as Parameters); expect(res.status).toStrictEqual(400); expect(res.body).toMatchObject<OperationOutcome>({ resourceType: 'OperationOutcome', issue: [{ severity: 'error', code: 'invalid', details: { text: 'No code system specified' } }], }); }); test('Checks project', async () => { const otherAccessToken = await initTestAuth(); const res = await request(app) .post('/fhir/R4/CodeSystem/$lookup') .set('Authorization', 'Bearer ' + otherAccessToken) .set('Content-Type', 'application/fhir+json') .send({ resourceType: 'Parameters', parameter: [{ name: 'coding', valueCoding: { system: codeSystem.url, code: '1' } }], } as Parameters); expect(res.status).toStrictEqual(400); expect(res.body).toMatchObject<OperationOutcome>({ resourceType: 'OperationOutcome', issue: [{ severity: 'error', code: 'invalid', details: { text: `CodeSystem ${codeSystem.url} not found` } }], }); }); test('Lookup using specific CodeSystem version', async () => { const updatedCodeSystem: CodeSystem = { ...testCodeSystem, version: '3.1.4', concept: [{ code: '5', display: 'Neologism' }], }; const res = await request(app) .post('/fhir/R4/CodeSystem') .set('Authorization', 'Bearer ' + accessToken) .set('Content-Type', ContentType.FHIR_JSON) .send(updatedCodeSystem); expect(res.status).toStrictEqual(201); const codeSystem = res.body as CodeSystem; const res2 = await request(app) .post('/fhir/R4/CodeSystem/$lookup') .set('Authorization', 'Bearer ' + accessToken) .set('Content-Type', 'application/fhir+json') .send({ resourceType: 'Parameters', parameter: [ { name: 'coding', valueCoding: { system: codeSystem.url, code: '5' } }, { name: 'version', valueString: '3.1.4' }, ], } as Parameters); expect(res2.status).toStrictEqual(200); expect(res2.body).toMatchObject<Parameters>({ resourceType: 'Parameters', parameter: [ { name: 'name', valueString: 'Test Code System' }, { name: 'display', valueString: 'Neologism' }, ], }); }); test('GET endpoint', async () => { const res = await request(app) .get(`/fhir/R4/CodeSystem/$lookup?system=${testCodeSystem.url}&code=1`) .set('Authorization', 'Bearer ' + accessToken) .set('Content-Type', 'application/fhir+json') .send(); expect(res.status).toStrictEqual(200); expect(res.body).toMatchObject<Parameters>({ resourceType: 'Parameters', parameter: [ { name: 'name', valueString: 'Test Code System' }, { name: 'display', valueString: 'Biopsy of brain' }, { name: 'property', part: [ { name: 'code', valueCode: 'parent' }, { name: 'value', valueCode: '2' }, { name: 'description', valueString: 'Biopsy of head' }, ], }, ], }); }); test('GET instance endpoint', async () => { const res = await request(app) .get(`/fhir/R4/CodeSystem/${codeSystem.id}/$lookup?code=1`) .set('Authorization', 'Bearer ' + accessToken) .set('Content-Type', 'application/fhir+json') .send(); expect(res.status).toStrictEqual(200); expect(res.body).toMatchObject<Parameters>({ resourceType: 'Parameters', parameter: [ { name: 'name', valueString: 'Test Code System' }, { name: 'display', valueString: 'Biopsy of brain' }, { name: 'property', part: [ { name: 'code', valueCode: 'parent' }, { name: 'value', valueCode: '2' }, { name: 'description', valueString: 'Biopsy of head' }, ], }, ], }); }); test('Error on instance system URL mismatch', async () => { const res = await request(app) .get(`/fhir/R4/CodeSystem/${codeSystem.id}/$lookup?system=incorrect&code=1`) .set('Authorization', 'Bearer ' + accessToken) .set('Content-Type', 'application/fhir+json') .send(); expect(res.status).toStrictEqual(404); expect(res.body).toMatchObject<OperationOutcome>({ resourceType: 'OperationOutcome', issue: [{ severity: 'error', code: 'not-found', details: { text: 'Not found' } }], }); }); test('Instance endpoint with coding', async () => { const res = await request(app) .post(`/fhir/R4/CodeSystem/${codeSystem.id}/$lookup`) .set('Authorization', 'Bearer ' + accessToken) .set('Content-Type', 'application/fhir+json') .send({ resourceType: 'Parameters', parameter: [{ name: 'coding', valueCoding: { code: '1' } }], } as Parameters); expect(res.status).toStrictEqual(200); expect(res.body).toMatchObject<Parameters>({ resourceType: 'Parameters', parameter: [ { name: 'name', valueString: 'Test Code System' }, { name: 'display', valueString: 'Biopsy of brain' }, { name: 'property', part: [ { name: 'code', valueCode: 'parent' }, { name: 'value', valueCode: '2' }, { name: 'description', valueString: 'Biopsy of head' }, ], }, ], }); }); test('Error on instance coding system mismatch', async () => { const res = await request(app) .post(`/fhir/R4/CodeSystem/${codeSystem.id}/$lookup`) .set('Authorization', 'Bearer ' + accessToken) .set('Content-Type', 'application/fhir+json') .send({ resourceType: 'Parameters', parameter: [{ name: 'coding', valueCoding: { system: 'incorrect', code: '1' } }], } as Parameters); expect(res.status).toStrictEqual(404); expect(res.body).toMatchObject<OperationOutcome>({ resourceType: 'OperationOutcome', issue: [{ severity: 'error', code: 'not-found', details: { text: 'Not found' } }], }); }); test('Correctly renders imported properties of different types', async () => { const res = await request(app) .post(`/fhir/R4/CodeSystem/${codeSystem.id}/$import`) .set('Authorization', 'Bearer ' + accessToken) .set('Content-Type', 'application/fhir+json') .send({ resourceType: 'Parameters', parameter: [ { name: 'property', part: [ { name: 'code', valueCode: '1' }, { name: 'property', valueCode: 'abstract' }, { name: 'value', valueString: 'false' }, ], }, { name: 'property', part: [ { name: 'code', valueCode: '1' }, { name: 'property', valueCode: 'publishedOn' }, { name: 'value', valueString: '2020-01-01' }, ], }, { name: 'property', part: [ { name: 'code', valueCode: '1' }, { name: 'property', valueCode: 'rank' }, { name: 'value', valueString: '418' }, ], }, ], } as Parameters); expect(res.status).toBe(200); const res2 = await request(app) .post(`/fhir/R4/CodeSystem/${codeSystem.id}/$lookup`) .set('Authorization', 'Bearer ' + accessToken) .set('Content-Type', 'application/fhir+json') .send({ resourceType: 'Parameters', parameter: [{ name: 'code', valueCode: '1' }], } as Parameters); expect(res2.status).toStrictEqual(200); expect(res2.body).toMatchObject<Parameters>({ resourceType: 'Parameters', parameter: expect.arrayContaining([ { name: 'name', valueString: 'Test Code System' }, { name: 'display', valueString: 'Biopsy of brain' }, { name: 'property', part: [ { name: 'code', valueCode: 'parent' }, { name: 'value', valueCode: '2' }, { name: 'description', valueString: 'Biopsy of head' }, ], }, { name: 'property', part: [ { name: 'code', valueCode: 'abstract' }, { name: 'value', valueBoolean: false }, { name: 'description', valueString: 'Code is not a real thing' }, ], }, { name: 'property', part: [ { name: 'code', valueCode: 'publishedOn' }, { name: 'value', valueDateTime: '2020-01-01' }, ], }, { name: 'property', part: [ { name: 'code', valueCode: 'rank' }, { name: 'value', valueInteger: 418 }, ], }, ]), }); }); test('Outputs translated designations', async () => { const res = await request(app) .get( '/fhir/R4/CodeSystem/$lookup?system=http://terminology.hl7.org/CodeSystem/operation-outcome&code=MSG_INVALID_ID' ) .set('Authorization', 'Bearer ' + accessToken) .set('Content-Type', 'application/fhir+json') .send(); expect(res.status).toStrictEqual(200); expect(res.body).toMatchObject<Parameters>({ resourceType: 'Parameters', parameter: expect.arrayContaining([ { name: 'name', valueString: 'Operation Outcome Codes' }, { name: 'display', valueString: 'Id not accepted' }, { name: 'designation', part: [ { name: 'language', valueCode: 'pl' }, { name: 'value', valueString: 'Identyfikator nie zaakceptowany' }, ], }, { name: 'designation', part: [ { name: 'language', valueCode: 'fr' }, { name: 'value', valueString: 'Id non accepté' }, ], }, { name: 'designation', part: [ { name: 'language', valueCode: 'zh' }, { name: 'value', valueString: 'Id不被接受' }, ], }, ]), }); }); });

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