Skip to main content
Glama
LabsPage.test.tsx14.1 kB
// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors // SPDX-License-Identifier: Apache-2.0 import { MantineProvider } from '@mantine/core'; import { Notifications } from '@mantine/notifications'; import type { ServiceRequest } from '@medplum/fhirtypes'; import { HomerSimpson, MockClient } from '@medplum/mock'; import { MedplumProvider } from '@medplum/react'; import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { MemoryRouter, Routes, Route } from 'react-router'; import { describe, expect, test, vi, beforeEach } from 'vitest'; import { LabsPage } from './LabsPage'; describe('LabsPage', () => { let medplum: MockClient; beforeEach(async () => { medplum = new MockClient(); vi.clearAllMocks(); await medplum.createResource(HomerSimpson); }); const setup = (initialPath = `/Patient/${HomerSimpson.id}/ServiceRequest`): ReturnType<typeof render> => { return render( <MemoryRouter initialEntries={[initialPath]}> <MedplumProvider medplum={medplum}> <MantineProvider> <Notifications /> <Routes> <Route path="/Patient/:patientId/ServiceRequest/:serviceRequestId" element={<LabsPage />} /> <Route path="/Patient/:patientId/ServiceRequest" element={<LabsPage />} /> </Routes> </MantineProvider> </MedplumProvider> </MemoryRouter> ); }; test('renders tabs and new order button', async () => { setup(); await waitFor(() => { expect(screen.getByText('Completed')).toBeInTheDocument(); expect(screen.getByText('Open')).toBeInTheDocument(); }); // Find the plus button by its icon (ActionIcon with IconPlus) const plusButtons = screen.getAllByRole('button', { name: '' }); const plusButton = plusButtons.find((btn) => btn.querySelector('.tabler-icon-plus')); expect(plusButton).toBeInTheDocument(); }); test('shows loading skeleton when loading', async () => { // Mock searchResources to return a promise that never resolves medplum.searchResources = vi.fn().mockImplementation(() => new Promise(() => {})); setup(); await waitFor(() => { const skeletons = document.querySelectorAll('.mantine-Skeleton-root'); expect(skeletons.length).toBeGreaterThan(0); }); }); test('shows empty state when no orders are found', async () => { medplum.searchResources = vi.fn().mockResolvedValue([]); setup(); await waitFor(() => { expect(screen.getByText(/No completed labs to display/i)).toBeInTheDocument(); }); }); test('displays completed orders in completed tab', async () => { const completedOrder: ServiceRequest = { resourceType: 'ServiceRequest', id: 'completed-1', status: 'completed', intent: 'order', code: { text: 'Complete Blood Count' }, subject: { reference: `Patient/${HomerSimpson.id}` }, requisition: { value: 'REQ-001' }, meta: { lastUpdated: '2024-01-01T10:00:00Z', }, }; await medplum.createResource(completedOrder); medplum.searchResources = vi.fn().mockResolvedValue([completedOrder]); setup(); await waitFor(() => { expect(screen.getByText('Complete Blood Count')).toBeInTheDocument(); }); }); test('displays open orders in open tab', async () => { const openOrder: ServiceRequest = { resourceType: 'ServiceRequest', id: 'open-1', status: 'active', intent: 'order', code: { text: 'Metabolic Panel' }, subject: { reference: `Patient/${HomerSimpson.id}` }, requisition: { value: 'REQ-002' }, meta: { lastUpdated: '2024-01-02T10:00:00Z', }, }; await medplum.createResource(openOrder); medplum.searchResources = vi.fn().mockResolvedValue([openOrder]); setup(); // Switch to open tab const openTab = screen.getByText('Open'); await userEvent.click(openTab); await waitFor(() => { expect(screen.getByText('Metabolic Panel')).toBeInTheDocument(); }); }); test('switches between tabs', async () => { const completedOrder: ServiceRequest = { resourceType: 'ServiceRequest', id: 'completed-1', status: 'completed', intent: 'order', code: { text: 'Completed Test' }, subject: { reference: `Patient/${HomerSimpson.id}` }, requisition: { value: 'REQ-001' }, meta: { lastUpdated: '2024-01-01T10:00:00Z', }, }; const openOrder: ServiceRequest = { resourceType: 'ServiceRequest', id: 'open-1', status: 'active', intent: 'order', code: { text: 'Open Test' }, subject: { reference: `Patient/${HomerSimpson.id}` }, requisition: { value: 'REQ-002' }, meta: { lastUpdated: '2024-01-02T10:00:00Z', }, }; await medplum.createResource(completedOrder); await medplum.createResource(openOrder); medplum.searchResources = vi.fn().mockResolvedValue([completedOrder, openOrder]); setup(); // Initially shows completed tab await waitFor(() => { expect(screen.getByText('Completed Test')).toBeInTheDocument(); }); // Switch to open tab const openTab = screen.getByText('Open'); await userEvent.click(openTab); await waitFor(() => { expect(screen.getByText('Open Test')).toBeInTheDocument(); expect(screen.queryByText('Completed Test')).not.toBeInTheDocument(); }); // Switch back to completed tab const completedTab = screen.getByText('Completed'); await userEvent.click(completedTab); await waitFor(() => { expect(screen.getByText('Completed Test')).toBeInTheDocument(); expect(screen.queryByText('Open Test')).not.toBeInTheDocument(); }); }); test('opens new order modal when plus button is clicked', async () => { medplum.searchResources = vi.fn().mockResolvedValue([]); setup(); // Find the plus button by its icon (ActionIcon with IconPlus) const plusButtons = screen.getAllByRole('button', { name: '' }); const plusButton = plusButtons.find((btn) => btn.querySelector('.tabler-icon-plus')); expect(plusButton).toBeDefined(); if (plusButton) { await userEvent.click(plusButton); } await waitFor(() => { expect(screen.getByText('Order Labs')).toBeInTheDocument(); }); }); test('closes new order modal when onClose is called', async () => { medplum.searchResources = vi.fn().mockResolvedValue([]); setup(); // Find the plus button by its icon (ActionIcon with IconPlus) const plusButtons = screen.getAllByRole('button', { name: '' }); const plusButton = plusButtons.find((btn) => btn.querySelector('.tabler-icon-plus')); expect(plusButton).toBeDefined(); if (plusButton) { await userEvent.click(plusButton); } await waitFor(() => { expect(screen.getByText('Order Labs')).toBeInTheDocument(); }); const closeButton = document.querySelector('.mantine-Modal-close'); if (closeButton) { await userEvent.click(closeButton); } await waitFor(() => { expect(screen.queryByText('Order Labs')).not.toBeInTheDocument(); }); }); test('filters out draft and entered-in-error orders from open tab', async () => { const activeOrder: ServiceRequest = { resourceType: 'ServiceRequest', id: 'active-1', status: 'active', intent: 'order', code: { text: 'Active Order' }, subject: { reference: `Patient/${HomerSimpson.id}` }, meta: { lastUpdated: '2024-01-02T10:00:00Z', }, }; const draftOrder: ServiceRequest = { resourceType: 'ServiceRequest', id: 'draft-1', status: 'draft', intent: 'order', code: { text: 'Draft Order' }, subject: { reference: `Patient/${HomerSimpson.id}` }, meta: { lastUpdated: '2024-01-01T10:00:00Z', }, }; const errorOrder: ServiceRequest = { resourceType: 'ServiceRequest', id: 'error-1', status: 'entered-in-error', intent: 'order', code: { text: 'Error Order' }, subject: { reference: `Patient/${HomerSimpson.id}` }, meta: { lastUpdated: '2024-01-01T09:00:00Z', }, }; await medplum.createResource(activeOrder); await medplum.createResource(draftOrder); await medplum.createResource(errorOrder); medplum.searchResources = vi.fn().mockResolvedValue([activeOrder, draftOrder, errorOrder]); setup(); // Switch to open tab const openTab = screen.getByText('Open'); await userEvent.click(openTab); await waitFor(() => { expect(screen.getByText('Active Order')).toBeInTheDocument(); expect(screen.queryByText('Draft Order')).not.toBeInTheDocument(); expect(screen.queryByText('Error Order')).not.toBeInTheDocument(); }); }); test('displays order details when order is selected', async () => { const completedOrder: ServiceRequest = { resourceType: 'ServiceRequest', id: 'completed-1', status: 'completed', intent: 'order', code: { text: 'Complete Blood Count' }, subject: { reference: `Patient/${HomerSimpson.id}` }, requisition: { value: 'REQ-001' }, meta: { lastUpdated: '2024-01-01T10:00:00Z', }, }; await medplum.createResource(completedOrder); medplum.searchResources = vi.fn().mockResolvedValue([completedOrder]); setup(`/Patient/${HomerSimpson.id}/ServiceRequest/${completedOrder.id}`); await waitFor(() => { // The order should be found in the search results and displayed (may appear multiple times) const elements = screen.getAllByText('Complete Blood Count'); expect(elements.length).toBeGreaterThan(0); }); }); test('fetches order when serviceRequestId is not in current items', async () => { const completedOrder: ServiceRequest = { resourceType: 'ServiceRequest', id: 'completed-1', status: 'completed', intent: 'order', code: { text: 'Complete Blood Count' }, subject: { reference: `Patient/${HomerSimpson.id}` }, requisition: { value: 'REQ-001' }, meta: { lastUpdated: '2024-01-01T10:00:00Z', }, }; await medplum.createResource(completedOrder); // Return empty results so the order is not in currentItems medplum.searchResources = vi.fn().mockResolvedValue([]); const readResourceSpy = vi.spyOn(medplum, 'readResource').mockResolvedValue(completedOrder as any); setup(`/Patient/${HomerSimpson.id}/ServiceRequest/${completedOrder.id}`); // Wait for search to complete first await waitFor(() => { expect(medplum.searchResources).toHaveBeenCalled(); }); // Then wait for readResource to be called await waitFor( () => { expect(readResourceSpy).toHaveBeenCalledWith('ServiceRequest', completedOrder.id); }, { timeout: 3000 } ); }); test('shows empty state message for open tab when no open orders', async () => { medplum.searchResources = vi.fn().mockResolvedValue([]); setup(); const openTab = screen.getByText('Open'); await userEvent.click(openTab); await waitFor(() => { expect(screen.getByText(/No open labs to display/i)).toBeInTheDocument(); }); }); test('filters orders based on requisition numbers', async () => { const order1: ServiceRequest = { resourceType: 'ServiceRequest', id: 'order-1', status: 'completed', intent: 'order', code: { text: 'Test 1' }, subject: { reference: `Patient/${HomerSimpson.id}` }, requisition: { value: 'REQ-001' }, meta: { lastUpdated: '2024-01-01T10:00:00Z', }, }; const order2: ServiceRequest = { resourceType: 'ServiceRequest', id: 'order-2', status: 'completed', intent: 'order', code: { text: 'Test 2' }, subject: { reference: `Patient/${HomerSimpson.id}` }, requisition: { value: 'REQ-001' }, // Same requisition number meta: { lastUpdated: '2024-01-01T11:00:00Z', }, }; await medplum.createResource(order1); await medplum.createResource(order2); medplum.searchResources = vi.fn().mockResolvedValue([order1, order2]); setup(); // Only one order with the same requisition number should be shown await waitFor(() => { const test1Elements = screen.queryAllByText('Test 1'); const test2Elements = screen.queryAllByText('Test 2'); // One should be shown, the other filtered out expect(test1Elements.length + test2Elements.length).toBe(1); }); }); test('filters out orders based on completed basedOn references', async () => { const completedOrder: ServiceRequest = { resourceType: 'ServiceRequest', id: 'completed-base', status: 'completed', intent: 'order', code: { text: 'Base Order' }, subject: { reference: `Patient/${HomerSimpson.id}` }, requisition: { value: 'REQ-BASE' }, meta: { lastUpdated: '2024-01-01T10:00:00Z', }, }; const basedOnOrder: ServiceRequest = { resourceType: 'ServiceRequest', id: 'based-on-order', status: 'active', intent: 'order', code: { text: 'Based On Order' }, subject: { reference: `Patient/${HomerSimpson.id}` }, basedOn: [{ reference: 'ServiceRequest/completed-base' }], meta: { lastUpdated: '2024-01-02T10:00:00Z', }, }; await medplum.createResource(completedOrder); await medplum.createResource(basedOnOrder); medplum.searchResources = vi.fn().mockResolvedValue([completedOrder, basedOnOrder]); setup(); // Switch to open tab const openTab = screen.getByText('Open'); await userEvent.click(openTab); await waitFor(() => { // The basedOn order should be filtered out because its base order is completed expect(screen.queryByText('Based On Order')).not.toBeInTheDocument(); }); }); });

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