/** * @vitest-environment jsdom * * The form-submit flow under test does not fire its callback under happy-dom * (likely a DOM-event-dispatch divergence). Run this file under jsdom. */ import React from 'react'; import { vi, describe, expect, test, beforeEach } from 'vitest'; import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { getDefaultsFromConfigSchema, useConfig } from '@openmrs/esm-framework'; import { useOrderConceptsByUuids, useLabEncounter, useObservation, type LabOrderConcept, updateOrderResult, type Datatype, useCompletedLabResultsArray, } from './lab-results.resource'; import LabResultsForm, { type LabResultsFormProps } from './lab-results-form.workspace'; import ExportedLabResultsForm, { type LabResultsFormProps as ExportedLabResultsFormProps, } from './exported-lab-results-form.workspace'; import { type PatientWorkspace2DefinitionProps, type Order, type TestOrderBasketItem, useOrderBasket, } from '@openmrs/esm-patient-common-lib'; import { configSchema, type ConfigObject } from '../config-schema'; import { type Encounter } from '../types/encounter'; import { mockPatient } from 'tools'; const mockUseOrderConceptByUuids = vi.mocked(useOrderConceptsByUuids); const mockUseLabEncounter = vi.mocked(useLabEncounter); const mockUseObservation = vi.mocked(useObservation); const mockUseCompletedLabResultsArray = vi.mocked(useCompletedLabResultsArray); const mockUseConfig = vi.mocked(useConfig); const mockUseOrderBasket = vi.mocked(useOrderBasket); vi.mock('./lab-results.resource', async () => ({ ...((await vi.importActual('./lab-results.resource')) as object), useOrderConceptByUuid: vi.fn(), useOrderConceptsByUuids: vi.fn(), useLabEncounter: vi.fn(), useObservation: vi.fn(), updateOrderResult: vi.fn().mockResolvedValue({}), useCompletedLabResultsArray: vi.fn(), })); vi.mock('@openmrs/esm-patient-common-lib', async () => ({ ...((await vi.importActual('@openmrs/esm-patient-common-lib')) as object), useOrderBasket: vi.fn(), })); const mockOrder = { uuid: 'order-uuid', concept: { uuid: 'concept-uuid' }, encounter: { uuid: 'encounter-uuid' }, patient: { uuid: 'patient-uuid' }, orderNumber: 'ORD-1', careSetting: { uuid: 'care-setting-uuid' }, orderer: { uuid: 'orderer-uuid' }, }; const mockCloseWorkspace = vi.fn(); const testProps: PatientWorkspace2DefinitionProps = { closeWorkspace: mockCloseWorkspace, workspaceProps: { order: mockOrder as Order, }, windowProps: {}, groupProps: { patientUuid: mockPatient.id, patient: mockPatient, visitContext: null, mutateVisitContext: null, }, launchChildWorkspace: vi.fn(), workspaceName: '', windowName: '', isRootWorkspace: false, showActionMenu: true, }; const exportedTestProps = { closeWorkspace: mockCloseWorkspace, workspaceProps: { patient: mockPatient, order: mockOrder as Order, } satisfies ExportedLabResultsFormProps, windowProps: {}, groupProps: {}, launchChildWorkspace: vi.fn(), workspaceName: '', windowName: '', isRootWorkspace: false, showActionMenu: true, }; describe('LabResultsForm', () => { beforeEach(() => { mockUseConfig.mockReturnValue({ ...getDefaultsFromConfigSchema(configSchema), enableAddTestsDuringResultEntry: false, }); mockUseOrderBasket.mockReturnValue({ orders: [], setOrders: vi.fn(), clearOrders: vi.fn(), }); mockUseOrderConceptByUuids.mockReturnValue({ concepts: [ { uuid: 'concept-uuid', display: 'Test Concept', setMembers: [], datatype: { display: 'Numeric', hl7Abbreviation: 'NM' }, hiAbsolute: 100, hiCritical: 80, hiNormal: 70, lowAbsolute: 0, lowCritical: 40, lowNormal: 50, units: 'mg/dL', allowDecimal: false, }, ] as LabOrderConcept[], isLoading: false, error: null, isValidating: false, mutate: vi.fn(), }); mockUseLabEncounter.mockReturnValue({ encounter: { obs: [] } as Encounter, isLoading: false, error: null, isValidating: false, mutate: vi.fn(), }); mockUseObservation.mockReturnValue({ data: null, isLoading: false, error: null, isValidating: false, mutate: vi.fn(), }); mockUseCompletedLabResultsArray.mockReturnValue({ completeLabResults: [], isLoading: false, error: null, mutate: vi.fn(), }); }); test('hides the add tests basket in patient chart context by default', () => { render(); expect(screen.queryByText('Add Tests to this order')).not.toBeInTheDocument(); }); test('hides the add tests basket in exported context without a launch callback', () => { render(); expect(screen.queryByText('Add Tests to this order')).not.toBeInTheDocument(); }); test('shows the add tests basket in patient chart context when enabled', () => { mockUseConfig.mockReturnValue({ ...getDefaultsFromConfigSchema(configSchema), enableAddTestsDuringResultEntry: true, }); render(); expect(screen.getByText('Add Tests to this order')).toBeInTheDocument(); }); test('hides the add tests basket in exported context with a child workspace name when disabled', () => { render( , ); expect(screen.queryByText('Add Tests to this order')).not.toBeInTheDocument(); }); test('shows the add tests basket in exported context when enabled and a child workspace name is supplied', () => { mockUseConfig.mockReturnValue({ ...getDefaultsFromConfigSchema(configSchema), enableAddTestsDuringResultEntry: true, }); render( , ); expect(screen.getByText('Add Tests to this order')).toBeInTheDocument(); }); test('hides staged add-tests actions when disabled even if the basket has orders', () => { mockUseOrderBasket.mockReturnValue({ orders: [ { action: 'NEW', display: 'Extra Test', testType: { label: 'Extra Test', conceptUuid: 'extra-concept-uuid' }, visit: null as any, isOrderIncomplete: false, }, ] as Array, setOrders: vi.fn(), clearOrders: vi.fn(), }); render(); expect(screen.queryByRole('button', { name: /Cancel order/i })).not.toBeInTheDocument(); expect(screen.queryByRole('button', { name: /Save Tests/i })).not.toBeInTheDocument(); }); test('hides the add tests basket in edit mode even when enabled', () => { mockUseConfig.mockReturnValue({ ...getDefaultsFromConfigSchema(configSchema), enableAddTestsDuringResultEntry: true, }); render( , ); expect(screen.queryByText('Add Tests to this order')).not.toBeInTheDocument(); }); test('validates numeric input correctly', async () => { const user = userEvent.setup(); render(); const input = await screen.findByLabelText(`Test Concept (0 - 100 mg/dL)`); await user.type(input, '150'); const saveButton = screen.getByRole('button', { name: /Save and close/i }); await user.click(saveButton); await waitFor(() => { expect(screen.getByText('Test Concept must be between 0 and 100')).toBeInTheDocument(); }); }); test('validate when we have a concept with allowDecimal set to true', async () => { const user = userEvent.setup(); // if allowDecimal is true, we should allow decimal values mockUseOrderConceptByUuids.mockReturnValue({ concepts: [ { uuid: 'concept-uuid', display: 'Test Concept', setMembers: [], datatype: { display: 'Numeric', hl7Abbreviation: 'NM' }, hiAbsolute: 100, lowAbsolute: null, lowCritical: null, lowNormal: null, hiCritical: null, hiNormal: null, units: 'mg/dL', allowDecimal: true, }, ] as LabOrderConcept[], isLoading: false, error: null, isValidating: false, mutate: vi.fn(), }); render(); const input = screen.getByRole('spinbutton', { name: /Test Concept/i, }); await user.type(input, '50.5'); const saveButton = screen.getByRole('button', { name: /Save and close/i }); await user.click(saveButton); await waitFor(() => { expect(screen.queryByText('Test Concept must be a whole number')).not.toBeInTheDocument(); }); }); test('validate when we have a concept with allowDecimal set to null', async () => { const user = userEvent.setup(); render(); const input = await screen.findByLabelText(`Test Concept (0 - 100 mg/dL)`); await user.type(input, '50.5'); const saveButton = screen.getByRole('button', { name: /Save and close/i }); await user.click(saveButton); // if allowDecimal is null or false, we should not allow decimal values await waitFor(() => { expect(screen.getByText('Test Concept must be a whole number')).toBeInTheDocument(); }); }); test('validate numeric input with negative value', async () => { const user = userEvent.setup(); render(); const input = await screen.findByLabelText(`Test Concept (0 - 100 mg/dL)`); await user.type(input, '-50'); const saveButton = screen.getByRole('button', { name: /Save and close/i }); await user.click(saveButton); await waitFor(() => { expect(screen.getByText('Test Concept must be between 0 and 100')).toBeInTheDocument(); }); }); test('validate numeric input with zero value', async () => { const user = userEvent.setup(); render(); const input = await screen.findByLabelText('Test Concept (0 - 100 mg/dL)'); await user.type(input, '0'); await waitFor(() => { expect(screen.queryByText('Test Concept must be between 0 and 100')).not.toBeInTheDocument(); }); }); test('validate numeric input with concept having only hiAbsolute', async () => { const user = userEvent.setup(); mockUseOrderConceptByUuids.mockReturnValue({ concepts: [ { uuid: 'concept-uuid', display: 'Test Concept', setMembers: [], datatype: { display: 'Numeric', hl7Abbreviation: 'NM' }, hiAbsolute: 100, lowAbsolute: null, lowCritical: null, lowNormal: null, hiCritical: null, hiNormal: null, units: 'mg/dL', }, ] as LabOrderConcept[], isLoading: false, error: null, isValidating: false, mutate: vi.fn(), }); render(); const input = screen.getByRole('spinbutton', { name: /Test Concept/i, }); await user.type(input, '150'); const saveButton = screen.getByRole('button', { name: /Save and close/i }); await user.click(saveButton); await waitFor(() => { expect(screen.getByText('Test Concept must be less than or equal to 100')).toBeInTheDocument(); }); }); test('validate numeric input with concept having only lowAbsolute', async () => { const user = userEvent.setup(); mockUseOrderConceptByUuids.mockReturnValue({ concepts: [ { uuid: 'concept-uuid', display: 'Test Concept', setMembers: [], datatype: { display: 'Numeric', hl7Abbreviation: 'NM' }, lowAbsolute: 0, lowCritical: null, lowNormal: null, hiCritical: null, hiNormal: null, hiAbsolute: null, units: 'mg/dL', }, ] as LabOrderConcept[], isLoading: false, error: null, isValidating: false, mutate: vi.fn(), }); render(); const input = screen.getByRole('spinbutton', { name: /Test Concept/i, }); await user.type(input, '-50'); const saveButton = screen.getByRole('button', { name: /Save and close/i }); await user.click(saveButton); await waitFor(() => { expect(screen.getByText('Test Concept must be greater than or equal to 0')).toBeInTheDocument(); }); }); test('validate numeric input for multiple fields', async () => { const user = userEvent.setup(); mockUseOrderConceptByUuids.mockReturnValue({ concepts: [ { uuid: 'concept-uuid', display: 'Test Concept', setMembers: [], datatype: { display: 'Numeric', hl7Abbreviation: 'NM' }, hiAbsolute: 60, lowAbsolute: 0, lowCritical: null, lowNormal: null, hiCritical: null, hiNormal: null, units: 'mg/dL', allowDecimal: true, }, { uuid: 'concept-uuid2', display: 'Test Concept Percentage', setMembers: [], datatype: { display: 'Numeric', hl7Abbreviation: 'NM' }, hiAbsolute: 100, lowAbsolute: 0, lowCritical: null, lowNormal: null, hiCritical: null, hiNormal: null, units: '%', allowDecimal: true, }, ] as LabOrderConcept[], isLoading: false, error: null, isValidating: false, mutate: vi.fn(), }); render(); const input = await screen.findByLabelText(`Test Concept (0 - 60 mg/dL)`); await user.type(input, '80'); const input2 = await screen.findByLabelText(`Test Concept Percentage (0 - 100 %)`); await user.type(input2, '120'); const saveButton = screen.getByRole('button', { name: /Save and close/i }); await user.click(saveButton); await waitFor(() => { expect(screen.getByText('Test Concept must be between 0 and 60')).toBeInTheDocument(); }); await waitFor(() => { expect(screen.getByText('Test Concept Percentage must be between 0 and 100')).toBeInTheDocument(); }); }); test('submits form with valid data', async () => { const user = userEvent.setup(); render(); const input = await screen.findByLabelText(`Test Concept (0 - 100 mg/dL)`); await user.type(input, '50'); const saveButton = screen.getByRole('button', { name: /Save and close/i }); await user.click(saveButton); await waitFor(() => { expect(mockCloseWorkspace).toHaveBeenCalled(); }); }); test('submits form with valid data for multiple Results', async () => { const user = userEvent.setup(); mockUseOrderConceptByUuids.mockReturnValue({ concepts: [ { uuid: 'concept-uuid', display: 'Test Concept', setMembers: [], datatype: { display: 'Numeric', hl7Abbreviation: 'NM' }, hiAbsolute: 60, lowAbsolute: 0, lowCritical: null, lowNormal: null, hiCritical: null, hiNormal: null, units: 'mg/dL', allowDecimal: true, }, { uuid: 'concept-uuid2', display: 'Test Concept Percentage', setMembers: [], datatype: { display: 'Numeric', hl7Abbreviation: 'NM' }, hiAbsolute: 100, lowAbsolute: 0, lowCritical: null, lowNormal: null, hiCritical: null, hiNormal: null, units: '%', allowDecimal: true, }, ] as LabOrderConcept[], isLoading: false, error: null, isValidating: false, mutate: vi.fn(), }); const mockCloseWorkspace = vi.fn(); const mockCloseWorkspaceWithSavedChanges = vi.fn(); render(); const input = await screen.findByLabelText(`Test Concept (0 - 60 mg/dL)`); await user.type(input, '50'); const input2 = await screen.findByLabelText(`Test Concept Percentage (0 - 100 %)`); await user.type(input2, '90'); const saveButton = screen.getByRole('button', { name: /Save and close/i }); await user.click(saveButton); await waitFor(() => { expect(mockCloseWorkspace).toHaveBeenCalled(); }); }); test('validate numeric input where concept is a set', async () => { const user = userEvent.setup(); mockUseOrderConceptByUuids.mockReturnValue({ concepts: [ { uuid: 'concept-uuid', display: 'Test Concept', datatype: { display: 'Numeric', hl7Abbreviation: 'NM' }, lowAbsolute: 0, lowCritical: null, lowNormal: null, hiCritical: null, hiNormal: null, hiAbsolute: null, units: 'mg/dL', setMembers: [ { uuid: 'set-member-uuid', display: 'Set Member', setMembers: [], datatype: { display: 'Numeric', hl7Abbreviation: 'NM' }, lowAbsolute: 50, lowCritical: 70, lowNormal: 80, hiCritical: 140, hiNormal: 120, hiAbsolute: 150, units: 'mg/dL', }, { uuid: 'set-member-uuid-2', display: 'Set Member 2', setMembers: [], datatype: { display: 'Numeric', hl7Abbreviation: 'NM' }, lowAbsolute: 5, lowCritical: 10, lowNormal: 15, hiCritical: 20, hiNormal: 25, hiAbsolute: 30, units: 'mg/dL', }, ], }, ] as LabOrderConcept[], isLoading: false, error: null, isValidating: false, mutate: vi.fn(), }); render(); // Normal input range const setMember1Input = screen.getByLabelText('Set Member (50 - 150 mg/dL)'); await user.type(setMember1Input, '50'); expect(screen.queryByText('Set Member must be between 50 and 150')).not.toBeInTheDocument(); const setMember2Input = screen.getByLabelText('Set Member 2 (5 - 30 mg/dL)'); await user.type(setMember2Input, '10'); expect(screen.queryByText('Set Member must be between 5 and 30')).not.toBeInTheDocument(); // Out of range input, upper limit await user.type(setMember1Input, '151'); expect(await screen.findByText('Set Member must be between 50 and 150')).toBeInTheDocument(); await user.type(setMember2Input, '31'); expect(await screen.findByText('Set Member 2 must be between 5 and 30')).toBeInTheDocument(); // Out of range input, lower limit await user.type(setMember1Input, '49'); expect(await screen.findByText('Set Member must be between 50 and 150')).toBeInTheDocument(); await user.type(setMember2Input, '4'); expect(await screen.findByText('Set Member 2 must be between 5 and 30')).toBeInTheDocument(); }); test('lab results form submits the correct lab result payload when the concept is not a set', async () => { const user = userEvent.setup(); mockUseOrderConceptByUuids.mockReturnValue({ concepts: [ { uuid: 'concept-uuid', display: 'Test Concept', setMembers: [], datatype: { display: 'Text', hl7Abbreviation: 'ST' } as Datatype, hiAbsolute: 100, lowAbsolute: 0, lowCritical: null, lowNormal: null, hiCritical: null, hiNormal: null, units: 'mg/dL', }, ] as LabOrderConcept[], isLoading: false, error: null, isValidating: false, mutate: vi.fn(), }); render(); const input = await screen.findByRole('textbox', { name: /Test Concept/i }); await user.type(input, '100'); const submitButton = screen.getByRole('button', { name: 'Save and close' }); await user.click(submitButton); expect(updateOrderResult).toHaveBeenCalledWith( 'order-uuid', 'encounter-uuid', { obs: [{ concept: { uuid: 'concept-uuid' }, order: { uuid: 'order-uuid' }, status: 'FINAL', value: '100' }] }, { fulfillerComment: 'Test Results Entered', fulfillerStatus: 'COMPLETED' }, { action: 'DISCONTINUE', careSetting: 'care-setting-uuid', concept: 'concept-uuid', encounter: 'encounter-uuid', orderer: mockOrder.orderer, patient: 'patient-uuid', previousOrder: 'order-uuid', type: 'testorder', }, expect.anything(), ); }); test('lab results forms submits correct payload when the concept is a set and one set member is keyed', async () => { const user = userEvent.setup(); mockUseOrderConceptByUuids.mockReturnValue({ concepts: [ { uuid: 'concept-uuid', display: 'Test Concept', set: true, setMembers: [ { uuid: 'set-member-uuid-1', display: 'Set Member 1', concept: { uuid: 'concept-uuid-1', display: 'Concept 1' }, datatype: { display: 'Numeric', hl7Abbreviation: 'NM' } as Datatype, hiAbsolute: 100, lowAbsolute: 0, lowCritical: null, lowNormal: null, hiCritical: null, hiNormal: null, units: 'mg/dL', }, { uuid: 'set-member-uuid-2', display: 'Set Member 2', concept: { uuid: 'concept-uuid-2', display: 'Concept 2' }, datatype: { display: 'Numeric', hl7Abbreviation: 'NM' } as Datatype, hiAbsolute: 80, lowAbsolute: 0, lowCritical: null, lowNormal: null, hiCritical: null, hiNormal: null, units: 'mmol/L', }, ], datatype: { display: 'Numeric', hl7Abbreviation: 'NM' }, hiAbsolute: 100, lowAbsolute: 0, lowCritical: null, lowNormal: null, hiCritical: null, hiNormal: null, units: 'mg/dL', }, ] as unknown as LabOrderConcept[], isLoading: false, error: null, isValidating: false, mutate: vi.fn(), }); render(); const concept1Input = await screen.findByLabelText('Set Member 1 (0 - 100 mg/dL)'); await user.type(concept1Input, '100'); const submitButton = screen.getByRole('button', { name: 'Save and close' }); await user.click(submitButton); // Expect the observation payload to include only the set member that was keyed expect(updateOrderResult).toHaveBeenCalledWith( 'order-uuid', 'encounter-uuid', { obs: [ { concept: { uuid: 'concept-uuid', }, status: 'FINAL', order: { uuid: 'order-uuid', }, groupMembers: [ { concept: { uuid: 'set-member-uuid-1', }, value: 100, status: 'FINAL', order: { uuid: 'order-uuid', }, }, ], }, ], }, { fulfillerStatus: 'COMPLETED', fulfillerComment: 'Test Results Entered', }, { previousOrder: 'order-uuid', type: 'testorder', action: 'DISCONTINUE', careSetting: 'care-setting-uuid', encounter: 'encounter-uuid', patient: 'patient-uuid', concept: 'concept-uuid', orderer: { uuid: 'orderer-uuid' }, }, expect.anything(), ); }); test('lab results form submits correct payload when the concept is a set and both set members are keyed', async () => { const user = userEvent.setup(); mockUseOrderConceptByUuids.mockReturnValue({ concepts: [ { uuid: 'concept-uuid', display: 'Test Concept', set: true, setMembers: [ { uuid: 'set-member-uuid-1', display: 'Set Member 1', concept: { uuid: 'concept-uuid-1', display: 'Concept 1' }, datatype: { display: 'Numeric', hl7Abbreviation: 'NM' }, hiAbsolute: 100, lowAbsolute: 0, lowCritical: null, lowNormal: null, hiCritical: null, hiNormal: null, units: 'mg/dL', }, { uuid: 'set-member-uuid-2', display: 'Set Member 2', concept: { uuid: 'concept-uuid-2', display: 'Concept 2' }, datatype: { display: 'Numeric', hl7Abbreviation: 'NM' }, hiAbsolute: 80, lowAbsolute: 0, lowCritical: null, lowNormal: null, hiCritical: null, hiNormal: null, units: 'mmol/L', }, ], datatype: { display: 'Numeric' }, hiAbsolute: 100, lowAbsolute: 0, lowCritical: null, lowNormal: null, hiCritical: null, hiNormal: null, units: 'mg/dL', }, ] as unknown as LabOrderConcept[], isLoading: false, error: null, isValidating: false, mutate: vi.fn(), }); render(); const concept1Input = await screen.findByLabelText('Set Member 1 (0 - 100 mg/dL)'); await user.type(concept1Input, '100'); const concept2Input = await screen.findByLabelText('Set Member 2 (0 - 80 mmol/L)'); await user.type(concept2Input, '60'); const submitButton = screen.getByRole('button', { name: 'Save and close' }); await user.click(submitButton); // Expect the observation payload to include both set members with their respective values expect(updateOrderResult).toHaveBeenCalledWith( 'order-uuid', 'encounter-uuid', { obs: [ { concept: { uuid: 'concept-uuid', }, status: 'FINAL', order: { uuid: 'order-uuid', }, groupMembers: [ { concept: { uuid: 'set-member-uuid-1', }, value: 100, status: 'FINAL', order: { uuid: 'order-uuid', }, }, { concept: { uuid: 'set-member-uuid-2', }, value: 60, status: 'FINAL', order: { uuid: 'order-uuid', }, }, ], }, ], }, { fulfillerStatus: 'COMPLETED', fulfillerComment: 'Test Results Entered', }, { previousOrder: 'order-uuid', type: 'testorder', action: 'DISCONTINUE', careSetting: 'care-setting-uuid', encounter: 'encounter-uuid', patient: 'patient-uuid', concept: 'concept-uuid', orderer: { uuid: 'orderer-uuid' }, }, expect.anything(), ); }); test('display error notification when the concept datatype is N/A', async () => { mockUseOrderConceptByUuids.mockReturnValue({ concepts: [ { uuid: 'concept-uuid', display: 'Test Concept', setMembers: [], datatype: { display: 'N/A' }, }, ] as LabOrderConcept[], isLoading: false, error: null, isValidating: false, mutate: vi.fn(), }); render(); const label = screen.getByText('Test Concept'); expect(label).toBeInTheDocument(); const errorNotification = screen.getByText( 'This test needs to be configured with a specific type (like number, text, or choice list) to record results properly. Please contact your system administrator to fix this.', ); expect(errorNotification).toBeInTheDocument(); }); test('should display second level of set members for a given concept, if present', () => { mockUseOrderConceptByUuids.mockReturnValue({ concepts: [ { uuid: 'concept-uuid', display: 'Test Concept', set: true, setMembers: [ { uuid: 'set-member-uuid-1', display: 'Set Member 1', concept: { uuid: 'concept-uuid-1', display: 'Concept 1' }, datatype: { display: 'Numeric', hl7Abbreviation: 'NM' }, hiAbsolute: 100, lowAbsolute: 0, lowCritical: null, lowNormal: null, hiCritical: null, hiNormal: null, units: 'mg/dL', }, { uuid: 'set-member-uuid-2', display: 'Set Member 2', concept: { uuid: 'concept-uuid-2', display: 'Concept 2' }, datatype: { display: 'Numeric', hl7Abbreviation: 'NM' }, hiAbsolute: 80, lowAbsolute: 0, lowCritical: null, lowNormal: null, hiCritical: null, hiNormal: null, units: 'mmol/L', }, { uuid: 'set-member-uuid-3', display: 'Set Member 3', concept: { uuid: 'concept-uuid-3', display: 'Concept 3' }, datatype: { display: 'N/A', hl7Abbreviation: 'ZZ' }, set: true, setMembers: [ { uuid: 'set-member-uuid-3.1', display: 'Set Member 3.1', concept: { uuid: 'concept-uuid-3.1', display: 'Concept 3.1' }, datatype: { display: 'Numeric', hl7Abbreviation: 'NM' }, hiAbsolute: 80, lowAbsolute: 0, lowCritical: null, lowNormal: null, units: 'mg/dL', }, { uuid: 'set-member-uuid-3.2', display: 'Set Member 3.2', concept: { uuid: 'concept-uuid-3.2', display: 'Concept 3.2' }, datatype: { display: 'Numeric', hl7Abbreviation: 'NM' }, hiAbsolute: 80, lowAbsolute: 0, lowCritical: null, units: 'mg/dL', }, ], }, ], datatype: { display: 'Numeric' }, hiAbsolute: 100, lowAbsolute: 0, lowCritical: null, lowNormal: null, hiCritical: null, hiNormal: null, units: 'mg/dL', }, ] as unknown as LabOrderConcept[], isLoading: false, error: null, isValidating: false, mutate: vi.fn(), }); render(); expect(screen.getByText('Set Member 3')).toBeInTheDocument(); expect(screen.getByLabelText('Set Member 3.1 (0 - 80 mg/dL)')).toBeInTheDocument(); expect(screen.getByLabelText('Set Member 3.2 (0 - 80 mg/dL)')).toBeInTheDocument(); }); test('should handle empty form submission', async () => { const user = userEvent.setup(); render(); const saveButton = screen.getByRole('button', { name: /Save and close/i }); await user.click(saveButton); expect(screen.getByText('Please fill at least one field.')).toBeInTheDocument(); expect(updateOrderResult).not.toHaveBeenCalled(); }); test('should disable save button when form has validation errors', async () => { const user = userEvent.setup(); render(); const input = await screen.findByLabelText(`Test Concept (0 - 100 mg/dL)`); await user.type(input, '150'); const saveButton = screen.getByRole('button', { name: /Save and close/i }); expect(saveButton).toBeDisabled(); }); });