/* eslint-disable testing-library/no-node-access */ import { vi, describe, it, expect, beforeEach, type MockInstance } from 'vitest'; import React from 'react'; import { screen, within } from '@testing-library/react'; import { getDefaultsFromConfigSchema, useConfig, useSession } from '@openmrs/esm-framework'; import { renderWithSwr } from 'tools'; import { type ConfigObject, configSchema } from '../config-schema'; import { mockPriorityNonUrgent, mockPriorityUrgent, mockQueueEntries, mockSession } from '__mocks__'; import QueueTable from './queue-table.component'; const mockUseSession = vi.mocked(useSession); const mockUseConfig = vi.mocked(useConfig); const configDefaults = getDefaultsFromConfigSchema(configSchema); const configWithCustomColumns = { queueTables: { columnDefinitions: [ { id: 'emr-id', columnType: 'patient-identifier' as const, config: { identifierType: '8d793bee-c2cc-11de-8d13-0010c6dffd0f', identifierTypeUuid: 'ee3e7d1d-7f82-4f5a-8d3f-2f1b2d3d1e0e', statusConfigs: [], visitQueueNumberAttributeUuid: 'queue-number-visit-attr-type-uuid', }, header: 'EMR ID', }, { id: 'in-service-time', columnType: 'wait-time', header: 'Time in service', }, { id: 'check-in-date', columnType: 'visit-start-time', header: 'Check-in date', }, ], tableDefinitions: [ { columns: ['patient-name', 'emr-id', 'patient-age', 'check-in-date', 'wait-time', 'actions'], appliedTo: [ { queue: 'triage-queue-uuid', status: 'waiting-status-uuid', }, ], }, { columns: ['patient-name', 'emr-id', 'patient-age', 'in-service-time', 'actions'], appliedTo: [ { queue: 'triage-queue-uuid', status: 'in-service-status-uuid', }, ], }, ], }, }; const defaultProps = { queueEntries: [], statusUuid: null, queueUuid: null, }; describe('QueueTable', () => { let consoleSpy: MockInstance; beforeEach(() => { mockUseSession.mockReturnValue(mockSession.data); mockUseConfig.mockReturnValue(configDefaults); consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {}); }); it('renders an empty table with default columns when there are no queue entries', () => { renderQueueTable(); const rows = screen.queryAllByRole('row'); expect(rows).toHaveLength(1); // should only have the header row const headerRow = rows[0]; const expectedHeaders = [/name/i, /coming from/i, /priority/i, /status/i, /queue/i, /wait time/i, /actions/i]; const headers = within(headerRow).getAllByRole('columnheader'); for (let i = 0; i < headers.length; i++) { expect(headers[i]).toHaveTextContent(expectedHeaders[i]); } expect(screen.getByText(/No patients to display/i)).toBeInTheDocument(); }); it('renders queue entries with default columns', () => { renderQueueTable({ queueEntries: mockQueueEntries }); for (const entry of mockQueueEntries) { const patientName = entry.patient.person.display; const row = screen.getByText(patientName).closest('tr'); expect(within(row).getByText(entry.status.display)).toBeInTheDocument(); expect(within(row).getByText(entry.priority.display)).toBeInTheDocument(); } }); it('allows modifying the columns of the table applied to all queues and statuses', () => { mockUseConfig.mockReturnValue({ ...configDefaults, queueTables: { ...configDefaults.queueTables, tableDefinitions: [ { columns: ['patient-name', 'status', 'wait-time', 'actions'], appliedTo: [{ queue: '', status: '' }], }, ], }, }); renderQueueTable({ queueEntries: mockQueueEntries, statusUuid: 'foo', queueUuid: 'bar' }); const rows = screen.queryAllByRole('row'); const headerRow = rows[0]; const expectedHeaders = [/name/i, /status/i, /wait time/i, /actions/i]; const headers = within(headerRow).getAllByRole('columnheader'); for (let i = 0; i < headers.length; i++) { expect(headers[i]).toHaveTextContent(expectedHeaders[i]); } }); it('will use the correct default table even when not provided explicitly in the config', () => { mockUseConfig.mockReturnValue({ ...configDefaults, ...configWithCustomColumns, } as ConfigObject); renderQueueTable({ queueEntries: mockQueueEntries, statusUuid: 'foo', queueUuid: 'bar' }); const rows = screen.queryAllByRole('row'); const headerRow = rows[0]; const expectedHeaders = [/name/i, /coming from/i, /priority/i, /status/i, /queue/i, /wait time/i, /actions/i]; const headers = within(headerRow).getAllByRole('columnheader'); for (let i = 0; i < headers.length; i++) { expect(headers[i]).toHaveTextContent(expectedHeaders[i]); } }); it('allows modifying the columns of tables by queue and status, including with custom column definitions', () => { mockUseConfig.mockReturnValue({ ...configDefaults, ...configWithCustomColumns, } as ConfigObject); renderQueueTable({ queueEntries: mockQueueEntries, queueUuid: 'triage-queue-uuid', statusUuid: 'in-service-status-uuid', }); const rows = screen.queryAllByRole('row'); const headerRow = rows[0]; const expectedHeaders = [/name/i, /EMR ID/i, /age/i, /time in service/i, /actions/i]; const headers = within(headerRow).getAllByRole('columnheader'); for (let i = 0; i < headers.length; i++) { expect(headers[i]).toHaveTextContent(expectedHeaders[i]); } }); it('supports custom styles for priority tags at column level', () => { mockUseConfig.mockReturnValue({ ...configDefaults, priorityConfigs: [ { conceptUuid: mockPriorityNonUrgent.uuid, color: 'blue', style: 'bold', }, { conceptUuid: mockPriorityUrgent.uuid, color: 'orange', style: null, }, ], queueTables: { columnDefinitions: [ { id: 'priority', config: { actions: { buttons: ['transition'], overflowMenu: ['edit', 'remove', 'undo'], }, identifierTypeUuid: 'ee3e7d1d-7f82-4f5a-8d3f-2f1b2d3d1e0e', statusConfigs: [], visitQueueNumberAttributeUuid: 'queue-number-visit-attr-type-uuid', }, }, ], tableDefinitions: [ { columns: ['patient-name', 'priority'], }, ], }, }); renderQueueTable({ queueEntries: mockQueueEntries, queueUuid: 'triage-queue-uuid', statusUuid: null, }); const rows = screen.queryAllByRole('row'); expect(rows).toHaveLength(5); const briansRow = rows[1]; const alicesRow = rows[3]; const cells = within(briansRow).getAllByRole('cell'); expect(cells[1].childNodes[0]).toHaveClass('bold'); const alicesCells = within(alicesRow).getAllByRole('cell'); expect(alicesCells[1].childNodes[0]).toHaveClass('orange'); }); it('uses the visitQueueNumberAttributeUuid defined at the top level', () => { mockUseConfig.mockReturnValue({ ...configDefaults, visitQueueNumberAttributeUuid: 'queue-number-visit-attr-type-uuid', queueTables: { ...configDefaults.queueTables, tableDefinitions: [ { columns: ['patient-name', 'queue-number'], }, ], }, }); renderQueueTable({ queueEntries: mockQueueEntries, queueUuid: 'triage-queue-uuid', statusUuid: null, }); const aliceRow = screen.getByText('Alice Johnson').closest('tr'); const cells = within(aliceRow).getAllByRole('cell'); expect(cells[1].childNodes[0]).toHaveTextContent('42'); }); }); function renderQueueTable(props = {}) { renderWithSwr(); }