Skip to main content
Glama
useDoseSpotClinicFormulary.test.tsx11.2 kB
// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors // SPDX-License-Identifier: Apache-2.0 import type { CodeableConcept, Coding } from '@medplum/fhirtypes'; import { MockClient } from '@medplum/mock'; import { MedplumProvider } from '@medplum/react-hooks'; import { act, render, renderHook, screen } from '@testing-library/react'; import type { JSX } from 'react'; import { vi } from 'vitest'; import { DOSESPOT_ADD_FAVORITE_MEDICATION_BOT, DOSESPOT_SEARCH_MEDICATIONS_BOT } from './common'; import { useDoseSpotClinicFormulary } from './useDoseSpotClinicFormulary'; function TestComponent(): JSX.Element { const { state, searchMedications, saveFavoriteMedication, setSelectedMedicationDirections, setSelectedMedication } = useDoseSpotClinicFormulary(); const handleSetMedication = (): void => { const testMedication: CodeableConcept = { text: 'Test Medication', coding: [ { system: 'http://www.nlm.nih.gov/research/umls/rxnorm', code: 'test-med', display: 'Test Medication', }, ], }; setSelectedMedication(testMedication); }; const handleSetCodingMedication = (): void => { const testCoding: Coding = { system: 'http://www.nlm.nih.gov/research/umls/rxnorm', code: '1191', display: 'Aspirin 325 MG Oral Tablet', }; setSelectedMedication(testCoding); }; return ( <div> <div>Selected: {state.selectedMedication?.text || 'none'}</div> <div>Directions: {state.directions || 'none'}</div> <button onClick={() => searchMedications('aspirin')}>Search</button> <button onClick={() => saveFavoriteMedication()}>Add Favorite</button> <button onClick={() => setSelectedMedicationDirections('Take 1 daily')}>Set Directions</button> <button onClick={handleSetMedication}>Set CodeableConcept Medication</button> <button onClick={handleSetCodingMedication}>Set Coding Medication</button> <div>Name: {state.selectedMedication?.text || 'none'}</div> </div> ); } describe('useDoseSpotClinicFormulary', () => { beforeEach(() => { vi.resetAllMocks(); }); test('initializes with default state', async () => { const medplum = new MockClient(); medplum.executeBot = vi.fn(); await act(async () => { render( <MedplumProvider medplum={medplum}> <TestComponent /> </MedplumProvider> ); }); expect(screen.getByText('Selected: none')).toBeDefined(); expect(screen.getByText('Directions: none')).toBeDefined(); }); test('searchMedications returns medications successfully', async () => { const medplum = new MockClient(); const mockMedications: CodeableConcept[] = [ { text: 'Aspirin 325mg', coding: [ { system: 'http://www.nlm.nih.gov/research/umls/rxnorm', code: '1191', display: 'Aspirin 325 MG Oral Tablet', }, ], }, ]; medplum.executeBot = vi.fn().mockResolvedValue(mockMedications); await act(async () => { render( <MedplumProvider medplum={medplum}> <TestComponent /> </MedplumProvider> ); }); await act(async () => { screen.getByText('Search').click(); }); expect(medplum.executeBot).toHaveBeenCalledWith(DOSESPOT_SEARCH_MEDICATIONS_BOT, { name: 'aspirin' }); }); test('searchMedications handles empty results', async () => { const medplum = new MockClient(); const mockMedications: CodeableConcept[] = []; medplum.executeBot = vi.fn().mockResolvedValue(mockMedications); await act(async () => { render( <MedplumProvider medplum={medplum}> <TestComponent /> </MedplumProvider> ); }); await act(async () => { screen.getByText('Search').click(); }); expect(medplum.executeBot).toHaveBeenCalledWith(DOSESPOT_SEARCH_MEDICATIONS_BOT, { name: 'aspirin' }); }); test('saveFavoriteMedication adds medication with directions', async () => { const medplum = new MockClient(); const expectedMedicationWithDirections = { resourceType: 'MedicationKnowledge', code: { text: 'Test Medication', coding: [ { system: 'http://www.nlm.nih.gov/research/umls/rxnorm', code: 'test-med', display: 'Test Medication', }, ], }, administrationGuidelines: [ { dosage: [ { dosage: [ { patientInstruction: 'Take 1 daily', }, ], type: { coding: [ { system: 'https://dosespot.com/patient-instructions', }, ], }, }, ], }, ], }; medplum.executeBot = vi.fn().mockResolvedValue(expectedMedicationWithDirections); await act(async () => { render( <MedplumProvider medplum={medplum}> <TestComponent /> </MedplumProvider> ); }); // Set directions first await act(async () => { screen.getByText('Set Directions').click(); }); // Set medication await act(async () => { screen.getByText('Set CodeableConcept Medication').click(); }); // Add favorite await act(async () => { screen.getByText('Add Favorite').click(); }); expect(medplum.executeBot).toHaveBeenCalledWith( DOSESPOT_ADD_FAVORITE_MEDICATION_BOT, expectedMedicationWithDirections ); }); test('saveFavoriteMedication handles empty directions', async () => { const medplum = new MockClient(); const expectedMedicationWithDirections = { resourceType: 'MedicationKnowledge', code: { text: 'Test Medication', coding: [ { system: 'http://www.nlm.nih.gov/research/umls/rxnorm', code: 'test-med', display: 'Test Medication', }, ], }, administrationGuidelines: [ { dosage: [ { dosage: [ { patientInstruction: '', }, ], type: { coding: [ { system: 'https://dosespot.com/patient-instructions', }, ], }, }, ], }, ], }; medplum.executeBot = vi.fn().mockResolvedValue(expectedMedicationWithDirections); await act(async () => { render( <MedplumProvider medplum={medplum}> <TestComponent /> </MedplumProvider> ); }); // Set medication without directions await act(async () => { screen.getByText('Set CodeableConcept Medication').click(); }); // Add favorite await act(async () => { screen.getByText('Add Favorite').click(); }); expect(medplum.executeBot).toHaveBeenCalledWith( DOSESPOT_ADD_FAVORITE_MEDICATION_BOT, expectedMedicationWithDirections ); }); test('saveFavoriteMedication with Coding object creates proper structure', async () => { const medplum = new MockClient(); const expectedMedicationWithDirections = { resourceType: 'MedicationKnowledge', code: { coding: [ { system: 'http://www.nlm.nih.gov/research/umls/rxnorm', code: '1191', display: 'Aspirin 325 MG Oral Tablet', }, ], text: 'Aspirin 325 MG Oral Tablet', // Add this line to match the new behavior }, administrationGuidelines: [ { dosage: [ { dosage: [ { patientInstruction: 'Take 1 daily', }, ], type: { coding: [ { system: 'https://dosespot.com/patient-instructions', }, ], }, }, ], }, ], }; medplum.executeBot = vi.fn().mockResolvedValue(expectedMedicationWithDirections); await act(async () => { render( <MedplumProvider medplum={medplum}> <TestComponent /> </MedplumProvider> ); }); // Set directions first await act(async () => { screen.getByText('Set Directions').click(); }); // Set Coding medication await act(async () => { screen.getByText('Set Coding Medication').click(); }); // Add favorite await act(async () => { screen.getByText('Add Favorite').click(); }); expect(medplum.executeBot).toHaveBeenCalledWith( DOSESPOT_ADD_FAVORITE_MEDICATION_BOT, expectedMedicationWithDirections ); }); test('setSelectedMedicationDirections updates state', async () => { const medplum = new MockClient(); medplum.executeBot = vi.fn(); await act(async () => { render( <MedplumProvider medplum={medplum}> <TestComponent /> </MedplumProvider> ); }); await act(async () => { screen.getByText('Set Directions').click(); }); expect(screen.getByText('Directions: Take 1 daily')).toBeDefined(); }); test('setSelectedMedication with CodeableConcept updates state', async () => { const medplum = new MockClient(); medplum.executeBot = vi.fn(); await act(async () => { render( <MedplumProvider medplum={medplum}> <TestComponent /> </MedplumProvider> ); }); await act(async () => { screen.getByText('Set CodeableConcept Medication').click(); }); expect(screen.getByText('Selected: Test Medication')).toBeDefined(); }); test('setSelectedMedication with Coding updates state', async () => { const medplum = new MockClient(); medplum.executeBot = vi.fn(); await act(async () => { render( <MedplumProvider medplum={medplum}> <TestComponent /> </MedplumProvider> ); }); await act(async () => { screen.getByText('Set Coding Medication').click(); }); expect(screen.getByText('Selected: Aspirin 325 MG Oral Tablet')).toBeDefined(); }); test('clear resets state', async () => { const medplum = new MockClient(); medplum.executeBot = vi.fn(); const { result } = renderHook(() => useDoseSpotClinicFormulary(), { wrapper: ({ children }) => <MedplumProvider medplum={medplum}>{children}</MedplumProvider>, }); // Set some state first act(() => { result.current.setSelectedMedication({ text: 'Test Medication' }); result.current.setSelectedMedicationDirections('Take 1 daily'); }); // Verify state is set expect(result.current.state.directions).toBe('Take 1 daily'); // Clear state act(() => { result.current.clear(); }); // Verify state is cleared expect(result.current.state.selectedMedication).toBeUndefined(); expect(result.current.state.directions).toBeUndefined(); }); });

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