Untitled

 avatar
unknown
plain_text
9 months ago
27 kB
12
Indexable
import React from 'react';
import userEvent from '@testing-library/user-event';
import ClosedWorkOrders from '../../components/ClosedWorkOrders';
import { render, screen, createTestStore, within } from '../test-utils';

// Mock MUI X License to avoid license check errors in tests
jest.mock('@mui/x-license', () => ({
  LicenseInfo: {
    setLicenseKey: jest.fn(),
  },
}));

// Mock MUI X DataGrid Pro to avoid license check
jest.mock('@mui/x-data-grid-pro', () => ({
  DataGridPro: jest.fn(() => <div data-testid="data-grid-pro">DataGridPro</div>),
  DataGrid: jest.fn(() => <div data-testid="data-grid">DataGrid</div>),
  useGridApiRef: () => ({
    current: {
      updateRows: jest.fn(),
      setFilterModel: jest.fn(),
      setSortModel: jest.fn(),
      setColumns: jest.fn(),
      getColumns: jest.fn(() => []),
      updateColumns: jest.fn(),
      updateRow: jest.fn(),
      getRow: jest.fn(),
      getAllColumns: jest.fn(() => []),
    },
  }),
  getGridDateOperators: jest.fn(() => []),
  GridColDef: {},
  GridRenderCellParams: {},
  GridClasses: {},
  gridClasses: {
    cell: 'MuiDataGrid-cell',
    row: 'MuiDataGrid-row',
    'row--editing': 'MuiDataGrid-row--editing',
    actionsCell: 'MuiDataGrid-actionsCell',
    columnHeader: 'MuiDataGrid-columnHeader',
    footerContainer: 'MuiDataGrid-footerContainer',
    toolbarContainer: 'MuiDataGrid-toolbarContainer',
  },
}));

// Mock Apollo Client useQuery
const mockUseQuery = jest.fn();
jest.mock('@apollo/client', () => ({
  ...jest.requireActual('@apollo/client'),
  useQuery: (query: any, options: any) => mockUseQuery(query, options),
  gql: jest.requireActual('@apollo/client').gql,
}));

// Mock Redux dispatch
const mockDispatch = jest.fn();
jest.mock('react-redux', () => ({
  ...jest.requireActual('react-redux'),
  useDispatch: () => mockDispatch,
}));

// Mock hooks
jest.mock('../../hooks/useDropZone', () => ({
  useDropZone: jest.fn(() => ({
    isDraggingOver: false,
    dropZoneHandlers: {},
    dropZoneRef: { current: null },
  })),
}));

jest.mock('../../hooks/useDragAndDrop', () => ({
  useDragAndDrop: () => ({
    draggedWorkOrder: null,
    dragHandlers: {
      onDragStart: jest.fn(),
      onDragEnd: jest.fn(),
    },
  }),
}));

// Mock ConfirmDialog
jest.mock('../../components/ConfirmDialog', () => {
  return function MockConfirmDialog({ open, title, message, confirmText, cancelText, onConfirm, onCancel }: any) {
    if (!open) return null;
    
    return (
      <div data-testid="confirm-dialog" role="dialog">
        <h2>{title}</h2>
        <div>{typeof message === 'string' ? message : 'Dialog message'}</div>
        <button onClick={onConfirm} data-testid="confirm-button">
          {confirmText}
        </button>
        <button onClick={onCancel} data-testid="cancel-button">
          {cancelText}
        </button>
      </div>
    );
  };
});

// Mock WorkOrderColumns
jest.mock('../../components/WorkOrderColumns', () => {
  return {
    __esModule: true,
    default: [
      { field: 'workOrderNo', headerName: 'Work Order No', width: 150 },
      { field: 'assignedTo', headerName: 'Assigned', width: 120 },
      { field: 'shift', headerName: 'Shift', width: 100 },
      { field: 'notes', headerName: 'Notes', width: 200 },
    ],
    applyConfigurations: jest.fn((currentApi, columns, _restoreDefault) => {
      // Handle case where currentApi might be undefined
      if (!currentApi) {
        return Promise.resolve(columns || []);
      }
      return Promise.resolve(columns || [
        { field: 'workOrderNo', headerName: 'Work Order No', width: 150 },
        { field: 'assignedTo', headerName: 'Assigned', width: 120 },
        { field: 'shift', headerName: 'Shift', width: 100 },
        { field: 'notes', headerName: 'Notes', width: 200 },
      ]);
    }),
    getWorkOrderColumns: jest.fn(() => [
      { field: 'workOrderNo', headerName: 'Work Order No', width: 150 },
      { field: 'assignedTo', headerName: 'Assigned', width: 120 },
      { field: 'shift', headerName: 'Shift', width: 100 },
      { field: 'notes', headerName: 'Notes', width: 200 },
    ]),
  };
});

// Mock DraggableTableRow
jest.mock('../../components/DraggableTableRow', () => ({
  DraggableTableRow: ({ order, handleCommitChange, handleDeleteRow, editingId, editValue, editingShiftId, shiftValue, editingNotesId, notesValue, setEditingId, setEditValue, setEditingShiftId, setShiftValue, setEditingNotesId, setNotesValue, handleSave, handleSaveShift, handleSaveNotes }: any) => (
    <tr data-testid={`work-order-row-${order.workOrderNo}`}>
      <td>
        <input
          type="checkbox"
          checked={order.committed}
          onChange={(e) => handleCommitChange(order, e.target.checked)}
          data-testid={`commit-checkbox-${order.workOrderNo}`}
        />
      </td>
      <td data-testid={`work-order-no-${order.workOrderNo}`}>{order.workOrderNo}</td>
      <td>{order.ncOpenCount}</td>
      <td>{order.defaultWoDescription}</td>
      <td>
        {editingId === order.workOrderNo ? (
          <input
            value={editValue}
            onChange={(e) => setEditValue(e.target.value)}
            onBlur={() => handleSave(order.workOrderNo, editValue)}
            data-testid={`assigned-input-${order.workOrderNo}`}
          />
        ) : (
          <span 
            onClick={() => {
              setEditingId(order.workOrderNo);
              setEditValue(order.assignedTo);
            }}
            data-testid={`assigned-text-${order.workOrderNo}`}
          >
            {order.assignedTo}
          </span>
        )}
      </td>
      <td>
        {editingShiftId === order.workOrderNo ? (
          <input
            value={shiftValue}
            onChange={(e) => setShiftValue(e.target.value)}
            onBlur={() => handleSaveShift(order.workOrderNo, shiftValue)}
            data-testid={`shift-input-${order.workOrderNo}`}
          />
        ) : (
          <span 
            onClick={() => {
              setEditingShiftId(order.workOrderNo);
              setShiftValue(order.shift);
            }}
            data-testid={`shift-text-${order.workOrderNo}`}
          >
            {order.shift}
          </span>
        )}
      </td>
      <td>
        {editingNotesId === order.workOrderNo ? (
          <input
            value={notesValue}
            onChange={(e) => setNotesValue(e.target.value)}
            onBlur={() => handleSaveNotes(order.workOrderNo, notesValue)}
            data-testid={`notes-input-${order.workOrderNo}`}
          />
        ) : (
          <span 
            onClick={() => {
              setEditingNotesId(order.workOrderNo);
              setNotesValue(order.notes);
            }}
            data-testid={`notes-text-${order.workOrderNo}`}
          >
            {order.notes}
          </span>
        )}
      </td>
      <td>
        <button 
          onClick={() => handleDeleteRow(order.workOrderNo)}
          data-testid={`delete-button-${order.workOrderNo}`}
        >
          Delete
        </button>
      </td>
    </tr>
  ),
}));

describe('ClosedWorkOrders', () => {
  const mockWorkOrders = [
    {
      workOrderNo: 'WO001',
      tailNumber: 'TAIL001',
      committed: false,
      committedOn: null,
      assignedTo: 'John Doe',
      shift: 'Day',
      notes: 'Test notes',
      ncOpenCount: 2,
      defaultWoDescription: 'Test Description',
      workType: 'REP',
      category: 'electrical',
      planDate: '2024-01-15',
      budgetHours: 8,
      createdOn: '2024-01-15T08:00:00Z',
      estimatedCompletedOn: null,
    },
    {
      workOrderNo: 'WO002',
      tailNumber: 'TAIL001',
      committed: true,
      committedOn: '2024-01-15T10:00:00Z',
      assignedTo: 'Jane Smith',
      shift: 'Night',
      notes: 'Urgent repair',
      ncOpenCount: 1,
      defaultWoDescription: 'Critical Fix',
      workType: 'DIS',
      category: 'mechanical',
      planDate: '2024-01-15',
      budgetHours: 4,
      createdOn: '2024-01-15T09:00:00Z',
      estimatedCompletedOn: '2024-01-15T14:00:00Z',
    },
  ];

  // Create mock functions for component props
  const mockClosedWorkOrderRow = jest.fn();
  const mockSaveConfigurations = jest.fn();
  const mockApplyConfigurations = jest.fn((currentApi, columns, _restoreDefault) => {
    return Promise.resolve(columns || [
      { field: 'workOrderNo', headerName: 'Work Order No', width: 150 },
      { field: 'assignedTo', headerName: 'Assigned', width: 120 },
      { field: 'shift', headerName: 'Shift', width: 100 },
      { field: 'notes', headerName: 'Notes', width: 200 },
    ]);
  });

  const renderClosedWorkOrders = (initialState: any = {}, queryResult = {}, componentProps: any = {}) => {
    // Set up default useQuery mock
    mockUseQuery.mockReturnValue({
      data: { closedWoList: mockWorkOrders },
      loading: false,
      error: null,
      ...queryResult,
    });
    
    // Use tomorrow's date to ensure whiteboard is not locked by date logic
    const tomorrow = new Date();
    tomorrow.setDate(tomorrow.getDate() + 1);
    
    const store = createTestStore({
      whiteBoard: {
        tailNumber: 'TEST-001',
        planDate: tomorrow.toISOString().split('T')[0], // Future date
        electrical: [],
        structures: [],
        mechanical: [],
        constraints: [],
        closedWorkOrders: mockWorkOrders,
        locked: false,
        isPrevWhiteBoardImported: false,
        constraintBoardStates: {},
        ...initialState.whiteBoard,
      },
    });

    // Render with props that match how component is used in PlanOfTheDayDashboard
    // Using 'as any' because component accepts these props (used in PlanOfTheDayDashboard) 
    // but TypeScript definition may not reflect this
    return render(
      <ClosedWorkOrders
        {...({
          tailNumber: componentProps.tailNumber || 'TEST-001',
          closedWorkOrderRow: componentProps.closedWorkOrderRow || mockClosedWorkOrderRow,
          saveConfigurations: componentProps.saveConfigurations || mockSaveConfigurations,
          applyConfigurations: componentProps.applyConfigurations || mockApplyConfigurations,
        } as any)}
      />,
      { store }
    );
  };

  beforeEach(() => {
    jest.clearAllMocks();
    
    // Reset useQuery mock to default
    mockUseQuery.mockReturnValue({
      data: { closedWoList: mockWorkOrders },
      loading: false,
      error: null,
    });
    
    // Reset prop mocks
    mockClosedWorkOrderRow.mockClear();
    mockSaveConfigurations.mockClear();
    mockApplyConfigurations.mockImplementation((currentApi, columns, _restoreDefault) => {
      return Promise.resolve(columns || [
        { field: 'workOrderNo', headerName: 'Work Order No', width: 150 },
        { field: 'assignedTo', headerName: 'Assigned', width: 120 },
        { field: 'shift', headerName: 'Shift', width: 100 },
        { field: 'notes', headerName: 'Notes', width: 200 },
      ]);
    });
  });

  describe('Basic Rendering', () => {
    // Tests that the component renders with proper structure and title
    it('renders ClosedWorkOrders with correct title and structure', () => {
      renderClosedWorkOrders();
      
      expect(screen.getByText('Closed Work Orders')).toBeInTheDocument();
      expect(screen.getByRole('table')).toBeInTheDocument();
      
      // Check table headers
      expect(screen.getByText('Committed')).toBeInTheDocument();
      expect(screen.getByText('Work Order')).toBeInTheDocument();
      expect(screen.getByText('MC Open')).toBeInTheDocument();
      expect(screen.getByText('EDUC')).toBeInTheDocument();
      expect(screen.getByText('Assigned')).toBeInTheDocument();
      expect(screen.getByText('Shift')).toBeInTheDocument();
      expect(screen.getByText('Notes')).toBeInTheDocument();
      expect(screen.getByText('X')).toBeInTheDocument();
    });

    // Tests that work orders are displayed correctly
    it('displays work orders from Redux state', () => {
      renderClosedWorkOrders();
      
      expect(screen.getByTestId('work-order-row-WO001')).toBeInTheDocument();
      expect(screen.getByTestId('work-order-row-WO002')).toBeInTheDocument();
      expect(screen.getByTestId('work-order-no-WO001')).toHaveTextContent('WO001');
      expect(screen.getByTestId('work-order-no-WO002')).toHaveTextContent('WO002');
    });

    // Tests rendering with empty work orders list
    it('renders empty table when no work orders exist', () => {
      renderClosedWorkOrders({
        whiteBoard: {
          closedWorkOrders: [],
          locked: false,
        },
      });
      
      expect(screen.getByText('Closed Work Orders')).toBeInTheDocument();
      expect(screen.getByRole('table')).toBeInTheDocument();
      expect(screen.queryByTestId('work-order-row-WO001')).not.toBeInTheDocument();
    });

    // Tests that clear table button is present
    it('renders clear table button with correct icon', () => {
      renderClosedWorkOrders();
      
      const clearButton = screen.getByRole('button', { name: /clear table/i });
      expect(clearButton).toBeInTheDocument();
      expect(clearButton).not.toBeDisabled();
    });
  });

  describe('Redux State Management', () => {
    // Tests that committed checkbox updates Redux state
    it('updates work order committed status via Redux', async () => {
      const user = userEvent.setup();
      renderClosedWorkOrders();
      
      const checkbox = screen.getByTestId('commit-checkbox-WO001');
      expect(checkbox).not.toBeChecked();
      
      await user.click(checkbox);
      
      expect(mockDispatch).toHaveBeenCalledWith(
        expect.objectContaining({
          type: expect.stringContaining('updateWorkOrder'),
          payload: expect.objectContaining({
            category: 'closedWorkOrders',
            workOrder: expect.objectContaining({
              workOrderNo: 'WO001',
              committed: true,
            }),
          }),
        })
      );
    });

    // Tests that work order data is properly passed to child components
    it('passes correct work order data to DraggableTableRow components', () => {
      renderClosedWorkOrders();
      
      // Verify work order data is displayed
      expect(screen.getByTestId('assigned-text-WO001')).toHaveTextContent('John Doe');
      expect(screen.getByTestId('assigned-text-WO002')).toHaveTextContent('Jane Smith');
      expect(screen.getByTestId('shift-text-WO001')).toHaveTextContent('Day');
      expect(screen.getByTestId('shift-text-WO002')).toHaveTextContent('Night');
      expect(screen.getByTestId('notes-text-WO001')).toHaveTextContent('Test notes');
      expect(screen.getByTestId('notes-text-WO002')).toHaveTextContent('Urgent repair');
    });

    // Tests behavior when whiteboard is locked
    it('disables clear table button when whiteboard is locked', () => {
      // Use past date to trigger locked state through business logic
      const yesterday = new Date();
      yesterday.setDate(yesterday.getDate() - 1);
      
      renderClosedWorkOrders({
        whiteBoard: {
          closedWorkOrders: mockWorkOrders,
          locked: true,
          planDate: yesterday.toISOString().split('T')[0],
        },
      });
      
      const clearButton = screen.getByRole('button', { name: /clear table/i });
      expect(clearButton).toBeDisabled();
    });
  });

  describe('Inline Editing Functionality', () => {
    // Tests editing assigned field
    it('allows editing assigned field inline', async () => {
      const user = userEvent.setup();
      renderClosedWorkOrders();
      
      const assignedText = screen.getByTestId('assigned-text-WO001');
      await user.click(assignedText);
      
      const assignedInput = screen.getByTestId('assigned-input-WO001');
      expect(assignedInput).toBeInTheDocument();
      expect(assignedInput).toHaveValue('John Doe');
      
      await user.clear(assignedInput);
      await user.type(assignedInput, 'Updated Name');
      await user.tab(); // Trigger blur event
      
      // The mock handles the save, we verify the interaction occurred
      expect(assignedInput).toHaveValue('Updated Name');
    });

    // Tests editing shift field
    it('allows editing shift field inline', async () => {
      const user = userEvent.setup();
      renderClosedWorkOrders();
      
      const shiftText = screen.getByTestId('shift-text-WO001');
      await user.click(shiftText);
      
      const shiftInput = screen.getByTestId('shift-input-WO001');
      expect(shiftInput).toBeInTheDocument();
      expect(shiftInput).toHaveValue('Day');
      
      await user.clear(shiftInput);
      await user.type(shiftInput, 'Night');
      await user.tab(); // Trigger blur event
      
      expect(shiftInput).toHaveValue('Night');
    });

    // Tests editing notes field
    it('allows editing notes field inline', async () => {
      const user = userEvent.setup();
      renderClosedWorkOrders();
      
      const notesText = screen.getByTestId('notes-text-WO001');
      await user.click(notesText);
      
      const notesInput = screen.getByTestId('notes-input-WO001');
      expect(notesInput).toBeInTheDocument();
      expect(notesInput).toHaveValue('Test notes');
      
      await user.clear(notesInput);
      await user.type(notesInput, 'Updated notes');
      await user.tab(); // Trigger blur event
      
      expect(notesInput).toHaveValue('Updated notes');
    });

    // Tests that only one field can be edited at a time
    it('allows editing only one field at a time', async () => {
      const user = userEvent.setup();
      renderClosedWorkOrders();
      
      // Start editing assigned field
      const assignedText = screen.getByTestId('assigned-text-WO001');
      await user.click(assignedText);
      
      expect(screen.getByTestId('assigned-input-WO001')).toBeInTheDocument();
      
      // Try to edit shift field - should not show input since assigned is being edited
      const shiftText = screen.getByTestId('shift-text-WO001');
      await user.click(shiftText);
      
      // Both inputs should not be present simultaneously in a real scenario
      // This test verifies the component structure
      expect(screen.getByTestId('assigned-input-WO001')).toBeInTheDocument();
    });
  });

  describe('Drag and Drop Functionality', () => {
    // Tests drop zone integration
    it('integrates with drop zone for drag and drop', () => {
      renderClosedWorkOrders();
      
      // Should have drop zone attributes
      const dropZone = screen.getByRole('table').closest('[data-droppable="true"]');
      expect(dropZone).toBeInTheDocument();
      expect(dropZone).toHaveAttribute('data-table-type', 'closedWorkOrders');
    });

    // Tests drag over styling
    it('applies drag over styling when dragging', () => {
      renderClosedWorkOrders();
      
      // Should apply drag over styling
      expect(screen.getByRole('table')).toBeInTheDocument();
    });

    // Tests that drop zone handlers are attached
    it('attaches drop zone event handlers correctly', () => {
      renderClosedWorkOrders();
      
      const dropZone = screen.getByRole('table').closest('[data-droppable="true"]');
      expect(dropZone).toBeInTheDocument();
      
      // Verify the drop zone is configured for touch interactions
      expect(dropZone).toHaveStyle('touch-action: none');
    });
  });

  describe('Confirmation Dialogs', () => {
    // Tests clear table confirmation dialog
    it('shows confirmation dialog when clear table button is clicked', async () => {
      const user = userEvent.setup();
      renderClosedWorkOrders();
      
      const clearButton = screen.getByRole('button', { name: /clear table/i });
      await user.click(clearButton);
      
      const dialog = screen.getByTestId('confirm-dialog');
      expect(dialog).toBeInTheDocument();
      expect(within(dialog).getByText('Clear Table')).toBeInTheDocument();
      expect(within(dialog).getByText('Are you sure you want to clear this table?')).toBeInTheDocument();
      expect(within(dialog).getByTestId('confirm-button')).toHaveTextContent('Clear');
      expect(within(dialog).getByTestId('cancel-button')).toHaveTextContent('Cancel');
    });

    // Tests delete row confirmation dialog
    it('shows confirmation dialog when delete button is clicked', async () => {
      const user = userEvent.setup();
      renderClosedWorkOrders();
      
      const deleteButton = screen.getByTestId('delete-button-WO001');
      await user.click(deleteButton);
      
      const dialog = screen.getByTestId('confirm-dialog');
      expect(dialog).toBeInTheDocument();
      expect(within(dialog).getByText('Clear the row')).toBeInTheDocument();
      expect(within(dialog).getByText('Are you sure you want to clear this row?')).toBeInTheDocument();
      expect(within(dialog).getByText('Work Order:')).toBeInTheDocument();
      expect(within(dialog).getByText('WO001')).toBeInTheDocument();
    });

    // Tests canceling clear table dialog
    it('closes clear table dialog when cancel is clicked', async () => {
      const user = userEvent.setup();
      renderClosedWorkOrders();
      
      const clearButton = screen.getByRole('button', { name: /clear table/i });
      await user.click(clearButton);
      
      const dialog = screen.getByTestId('confirm-dialog');
      const cancelButton = within(dialog).getByTestId('cancel-button');
      await user.click(cancelButton);
      
      expect(screen.queryByTestId('confirm-dialog')).not.toBeInTheDocument();
    });

    // Tests confirming clear table action
    it('handles clear table confirmation correctly', async () => {
      const user = userEvent.setup();
      renderClosedWorkOrders();
      
      const clearButton = screen.getByRole('button', { name: /clear table/i });
      await user.click(clearButton);
      
      const dialog = screen.getByTestId('confirm-dialog');
      const confirmButton = within(dialog).getByTestId('confirm-button');
      await user.click(confirmButton);
      
      // Dialog should close after confirmation
      expect(screen.queryByTestId('confirm-dialog')).not.toBeInTheDocument();
    });
  });

  describe('Component Layout and Styling', () => {
    // Tests that component has correct width and layout
    it('renders with correct layout and width', () => {
      renderClosedWorkOrders();
      
      // The component should be wrapped in PaperFrame with 33% width
      const container = screen.getByText('Closed Work Orders').closest('[class*="MuiPaper-root"]');
      expect(container).toBeInTheDocument();
    });

    // Tests table container scrolling behavior
    it('configures table container for proper scrolling', () => {
      renderClosedWorkOrders();
      
      const tableContainer = screen.getByRole('table').closest('[class*="MuiTableContainer-root"]');
      expect(tableContainer).toBeInTheDocument();
      expect(tableContainer).toHaveStyle('touch-action: none');
    });

    // Tests header styling and layout
    it('renders header with correct styling and controls', () => {
      renderClosedWorkOrders();
      
      const header = screen.getByText('Closed Work Orders').parentElement;
      expect(header).toBeInTheDocument();
      
      // Should contain both title and clear button
      expect(within(header!).getByText('Closed Work Orders')).toBeInTheDocument();
      expect(within(header!).getByRole('button', { name: /clear table/i })).toBeInTheDocument();
    });
  });

  describe('Error Handling and Edge Cases', () => {
    // Tests behavior with malformed work order data
    it('handles malformed work order data gracefully', () => {
      const malformedWorkOrders = [
        {
          workOrderNo: 'WO003',
          // Missing some required fields
          committed: false,
          assignedTo: '',
          shift: '',
          notes: '',
        },
      ];
      
      renderClosedWorkOrders({
        whiteBoard: {
          closedWorkOrders: malformedWorkOrders,
          locked: false,
        },
      });
      
      expect(screen.getByText('Closed Work Orders')).toBeInTheDocument();
      expect(screen.getByTestId('work-order-row-WO003')).toBeInTheDocument();
    });

    // Tests behavior when Redux state is undefined
    it('handles undefined Redux state gracefully', () => {
      renderClosedWorkOrders({
        whiteBoard: {
          closedWorkOrders: undefined,
          locked: false,
        },
      });
      
      expect(screen.getByText('Closed Work Orders')).toBeInTheDocument();
      expect(screen.getByRole('table')).toBeInTheDocument();
    });

    // Tests behavior with very long work order numbers
    it('handles long work order numbers correctly', () => {
      const longWorkOrderNumber = 'WO' + '1'.repeat(50);
      const workOrderWithLongNumber = [{
        ...mockWorkOrders[0],
        workOrderNo: longWorkOrderNumber,
      }];
      
      renderClosedWorkOrders({
        whiteBoard: {
          closedWorkOrders: workOrderWithLongNumber,
          locked: false,
        },
      });
      
      expect(screen.getByTestId(`work-order-row-${longWorkOrderNumber}`)).toBeInTheDocument();
      expect(screen.getByTestId(`work-order-no-${longWorkOrderNumber}`)).toHaveTextContent(longWorkOrderNumber);
    });
  });

  describe('Accessibility', () => {
    // Tests that table has proper accessibility structure
    it('provides proper table accessibility structure', () => {
      renderClosedWorkOrders();
      
      const table = screen.getByRole('table');
      expect(table).toBeInTheDocument();
      
      // Should have proper table headers
      const columnHeaders = screen.getAllByRole('columnheader');
      expect(columnHeaders).toHaveLength(8); // 8 columns as defined in the component
    });

    // Tests that interactive elements have proper accessibility
    it('provides proper accessibility for interactive elements', () => {
      renderClosedWorkOrders();
      
      const clearButton = screen.getByRole('button', { name: /clear table/i });
      expect(clearButton).toBeInTheDocument();
      expect(clearButton).toHaveAttribute('title', 'Clear Table');
      
      // Checkboxes should be accessible
      const checkboxes = screen.getAllByRole('checkbox');
      expect(checkboxes.length).toBeGreaterThan(0);
    });

    // Tests keyboard navigation support
    it('supports keyboard navigation for interactive elements', async () => {
      const user = userEvent.setup();
      renderClosedWorkOrders();
      
      const clearButton = screen.getByRole('button', { name: /clear table/i });
      
      // Should be focusable
      await user.tab();
      expect(clearButton).toHaveFocus();
      
      // Should be activatable with Enter
      await user.keyboard('{Enter}');
      expect(screen.getByTestId('confirm-dialog')).toBeInTheDocument();
    });
  });
});
Editor is loading...
Leave a Comment