Skip to main content
Glama
project.test.ts8.36 kB
// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors // SPDX-License-Identifier: Apache-2.0 import type { MedplumClient } from '@medplum/core'; import type { Project } from '@medplum/fhirtypes'; import { MockClient } from '@medplum/mock'; import fs from 'node:fs'; import { main } from '.'; import { FileSystemStorage } from './storage'; import { createMedplumClient } from './util/client'; jest.mock('./util/client'); jest.mock('node:child_process'); jest.mock('node:http'); jest.mock('node:fs', () => ({ existsSync: jest.fn(), readFileSync: jest.fn(), writeFileSync: jest.fn(), constants: { O_CREAT: 0, }, promises: { readFile: jest.fn(async () => '{}'), }, })); describe('CLI Project', () => { let medplum: MedplumClient; let processError: jest.SpyInstance; beforeAll(() => { process.exit = jest.fn<never, any>().mockImplementation(function exit(exitCode: number) { throw new Error(`Process exited with exit code ${exitCode}`); }) as unknown as typeof process.exit; processError = jest.spyOn(process.stderr, 'write').mockImplementation(jest.fn()); }); beforeEach(() => { jest.resetModules(); jest.clearAllMocks(); medplum = new MockClient({ storage: new FileSystemStorage('default') }); (createMedplumClient as unknown as jest.Mock).mockImplementation(async () => medplum); console.log = jest.fn(); console.error = jest.fn(); }); test('Project List', async () => { (fs.existsSync as unknown as jest.Mock).mockReturnValue(true); (fs.readFileSync as unknown as jest.Mock).mockReturnValue( JSON.stringify({ logins: JSON.stringify([ { accessToken: 'abc', refreshToken: 'xyz', profile: { reference: 'Practitioner/123', display: 'Alice Smith', }, project: { reference: 'Project/456', display: 'My Project', }, }, ]), }) ); await main(['node', 'index.js', 'project', 'list']); expect(console.log).toHaveBeenCalledWith(expect.stringMatching(`(Project/456)`)); }); test('Project Current', async () => { (fs.existsSync as unknown as jest.Mock).mockReturnValue(true); (fs.readFileSync as unknown as jest.Mock).mockReturnValue( JSON.stringify({ activeLogin: JSON.stringify({ accessToken: 'abc', refreshToken: 'xyz', profile: { reference: 'Practitioner/123', display: 'Alice Smith', }, project: { reference: 'Project/456', display: 'My Project', }, }), }) ); await main(['node', 'index.js', 'project', 'current']); expect(console.log).toHaveBeenCalledWith(expect.stringMatching(`(Project/456)`)); }); test('Project Switch', async () => { (fs.existsSync as unknown as jest.Mock).mockReturnValue(true); (fs.readFileSync as unknown as jest.Mock).mockReturnValue( JSON.stringify({ logins: JSON.stringify([ { accessToken: 'abc', refreshToken: 'xyz', profile: { reference: 'Practitioner/123', display: 'Alice Smith', }, project: { reference: 'Project/456', display: 'My Project', }, }, { accessToken: 'def', refreshToken: '123', profile: { reference: 'Practitioner/789', display: 'Alice Smith', }, project: { reference: 'Project/789', display: 'My Other Project', }, }, ]), }) ); await main(['node', 'index.js', 'project', 'switch', '789']); expect(console.log).toHaveBeenCalledWith(expect.stringMatching(`Switched to project 789`)); }); test('Project Switch invalid id', async () => { (fs.existsSync as unknown as jest.Mock).mockReturnValue(true); (fs.readFileSync as unknown as jest.Mock).mockReturnValue( JSON.stringify({ logins: JSON.stringify([ { accessToken: 'abc', refreshToken: 'xyz', profile: { reference: 'Practitioner/123', display: 'Alice Smith', }, project: { reference: 'Project/456', display: 'My Project', }, }, { accessToken: 'def', refreshToken: '123', profile: { reference: 'Practitioner/789', display: 'Alice Smith', }, project: { reference: 'Project/789', display: 'My Other Project', }, }, ]), }) ); await expect(main(['node', 'index.js', 'project', 'switch', 'bad-projectId'])).rejects.toThrow( 'Process exited with exit code 1' ); expect(processError).toHaveBeenCalledWith(expect.stringContaining('Error: Project bad-projectId not found.')); }); test('Project invite with no login', async () => { await expect( main(['node', 'index.js', 'project', 'invite', 'homer', 'simpon', 'homer@simpson.com']) ).rejects.toThrow('Process exited with exit code 1'); expect(processError).toHaveBeenCalledWith( expect.stringContaining('Error: Unauthenticated: run `npx medplum login` to login') ); }); test('Project invite with no project', async () => { (fs.existsSync as unknown as jest.Mock).mockReturnValue(true); (fs.readFileSync as unknown as jest.Mock).mockReturnValue( JSON.stringify({ activeLogin: JSON.stringify({ accessToken: 'abc', refreshToken: 'xyz', }), }) ); await expect( main(['node', 'index.js', 'project', 'invite', 'homer', 'simpon', 'homer@simpson.com']) ).rejects.toThrow('Process exited with exit code 1'); expect(processError).toHaveBeenCalledWith(expect.stringContaining('Error: No current project to invite user to')); }); test('Project invite with no send-email flag', async () => { const project = await medplum.createResource<Project>({ resourceType: 'Project', name: 'test' }); (fs.existsSync as unknown as jest.Mock).mockReturnValue(true); (fs.readFileSync as unknown as jest.Mock).mockReturnValue( JSON.stringify({ activeLogin: JSON.stringify({ accessToken: 'abc', refreshToken: 'xyz', profile: { reference: 'Practitioner/123', display: 'Alice Smith', }, project: { reference: `Project/${project.id}`, display: 'test', }, }), }) ); await main([ 'node', 'index.js', 'project', 'invite', '--admin', '-r', 'Patient', 'homer', 'simpon', 'homer@simpson.com', ]); expect(console.log).not.toHaveBeenCalledWith(expect.stringMatching(`Email sent`)); expect(console.log).toHaveBeenCalledWith( expect.stringMatching(`See your users at https://app.medplum.com/admin/users`) ); }); test('Project invite with all default role and all flags', async () => { const project = await medplum.createResource<Project>({ resourceType: 'Project', name: 'test' }); (fs.existsSync as unknown as jest.Mock).mockReturnValue(true); (fs.readFileSync as unknown as jest.Mock).mockReturnValue( JSON.stringify({ activeLogin: JSON.stringify({ accessToken: 'abc', refreshToken: 'xyz', profile: { reference: 'Practitioner/123', display: 'Alice Smith', }, project: { reference: `Project/${project.id}`, display: 'test', }, }), }) ); await main([ 'node', 'index.js', 'project', 'invite', '--send-email', '--admin', '-r', 'Patient', 'homer', 'simpon', 'homer@simpson.com', ]); expect(console.log).toHaveBeenCalledWith(expect.stringMatching(`Email sent`)); expect(console.log).toHaveBeenCalledWith( expect.stringMatching(`See your users at https://app.medplum.com/admin/users`) ); }); });

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