/** * @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, it, expect, beforeEach, type Mock } from 'vitest'; import userEvent from '@testing-library/user-event'; import { render, screen } from '@testing-library/react'; import { useLayoutType, type Workspace2DefinitionProps } from '@openmrs/esm-framework'; import { useSWRConfig } from 'swr'; import QueueRoomForm from './queue-room-form.workspace'; vi.mock('swr', () => ({ useSWRConfig: vi.fn(), })); const mockUseLayoutType = vi.mocked(useLayoutType); const mockMutate = vi.fn(); vi.mock('../../create-queue-entry/hooks/useQueueLocations', async () => ({ ...((await vi.importActual('../../create-queue-entry/hooks/useQueueLocations')) as object), useQueueLocations: vi.fn(() => ({ queueLocations: [{ id: 'e7786d9a-ab62-11ec-b909-0242ac120002', name: 'Location Test' }], })), })); vi.mock('../../hooks/useQueues', () => ({ useQueues: vi.fn(() => ({ queues: [ { uuid: 'queue-uuid-1', display: 'Queue 1', service: { uuid: 'service-uuid-1' } }, { uuid: 'queue-uuid-2', display: 'Queue 2', service: { uuid: 'service-uuid-2' } }, ], })), })); const workspaceProps = { closeWorkspace: vi.fn(), setTitle: vi.fn(), launchChildWorkspace: vi.fn(), }; vi.mock('./queue-room.resource', () => ({ saveQueueRoom: vi.fn().mockResolvedValue({ status: 201 }), useServices: vi.fn(() => ({ services: [ { uuid: 'service-uuid-1', display: 'Service 1' }, { uuid: 'service-uuid-2', display: 'Service 2' }, ], })), })); describe('QueueRoomForm', () => { beforeEach(() => { mockUseLayoutType.mockReturnValue('tablet'); (useSWRConfig as Mock).mockReturnValue({ mutate: mockMutate }); }); it('renders the form with queue room elements', () => { render(); expect(screen.getByLabelText(/queue room name/i)).toBeInTheDocument(); expect(screen.getByLabelText(/^queue$/i)).toBeInTheDocument(); expect(screen.getByLabelText(/queue location/i)).toBeInTheDocument(); expect(screen.getByText('Cancel')).toBeInTheDocument(); expect(screen.getByText('Save')).toBeInTheDocument(); }); it('displays error notification if queue room name is missing on submission', async () => { const user = userEvent.setup(); render(); await user.click(screen.getByText('Save')); expect(screen.getByText('Queue is required')).toBeInTheDocument(); }); it('displays error notification if queue room service is missing on submission', async () => { const user = userEvent.setup(); render(); const queueRoomNameInput = screen.getByLabelText('Queue room name'); await user.type(queueRoomNameInput, 'Room 123'); await user.click(screen.getByText('Save')); expect(screen.getByText('Queue is required')).toBeInTheDocument(); }); it('calls closePanel when Cancel button is clicked', async () => { const user = userEvent.setup(); const closeWorkspace = vi.fn(); render(); await user.click(screen.getByText('Cancel')); expect(closeWorkspace).toHaveBeenCalledTimes(1); }); it('updates queue room name state when a value is entered', async () => { const user = userEvent.setup(); render(); const queueRoomNameInput = screen.getByLabelText('Queue room name'); await user.type(queueRoomNameInput, 'Room 123'); expect(queueRoomNameInput).toHaveValue('Room 123'); }); it('invalidates the correct cache keys with query parameter pattern on successful creation', async () => { const user = userEvent.setup(); render(); const queueRoomNameInput = screen.getByLabelText('Queue room name'); const queueRoomServiceSelect = screen.getByLabelText('Queue'); const queueLocationSelect = screen.getByLabelText('Queue location'); const saveButton = screen.getByText('Save'); await user.type(queueRoomNameInput, 'Room 123'); await user.selectOptions(queueLocationSelect, 'e7786d9a-ab62-11ec-b909-0242ac120002'); await user.selectOptions(queueRoomServiceSelect, 'queue-uuid-1'); await user.click(saveButton); expect(mockMutate).toHaveBeenCalledWith(expect.any(Function)); const mutateCallback = mockMutate.mock.calls[0][0] as (key: unknown) => boolean; // Should match queue-room endpoints with query parameters expect(mutateCallback('/ws/rest/v1/queue-room?v=full')).toBe(true); expect(mutateCallback('/ws/rest/v1/queue-room?status=active')).toBe(true); // Should NOT match other endpoints that start with 'queue-room' expect(mutateCallback('/ws/rest/v1/queue-room-audit')).toBe(false); expect(mutateCallback('/ws/rest/v1/queue-roomtype')).toBe(false); }); });