@kadconsulting/dry
Version:
KAD Reusable Component Library
241 lines • 10.9 kB
JavaScript
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import { useEffect, useRef, useState } from 'react';
import { render, screen, waitFor, fireEvent, within, } from '@testing-library/react';
import DataTable from './DataTable';
import { FilterType } from './DataTableTypes';
describe('DataTable', () => {
const sampleColumns = [
{ Header: 'Order #', accessor: 'orderNumber', filterType: FilterType.Text },
{ Header: 'Project', accessor: 'projectId', filterType: FilterType.Text },
{ Header: 'Status', accessor: 'orderState', filterType: FilterType.Text },
{
Header: 'Date Created',
accessor: 'dateCreated',
filterType: FilterType.DateRange,
},
{ Header: 'Amount', accessor: 'amount', filterType: FilterType.Number },
];
const sampleData = [
{
id: 1,
orderNumber: '123',
projectId: '456',
orderState: 'Purchase Order',
dateCreated: '2021-01-01',
amount: 1000,
},
{
id: 2,
orderNumber: '124',
projectId: '457',
orderState: 'Completed',
dateCreated: '2021-01-02',
amount: 2000,
},
{
id: 3,
orderNumber: '125',
projectId: '458',
orderState: 'In Progress',
dateCreated: '2021-01-03',
amount: 3000,
},
];
const defaultProps = {
columns: sampleColumns,
data: sampleData,
pageIndex: 0,
pageSize: 10,
onPageChange: jest.fn(),
filters: {},
columnOrder: sampleColumns.map((col) => col.accessor),
columnWidths: {},
visibleColumns: sampleColumns.map((col) => col.accessor),
pinnedColumns: [],
setColumnOrder: jest.fn(),
setColumnWidths: jest.fn(),
loading: false,
setPageIndex: jest.fn(),
handleRowClick: jest.fn(),
};
beforeEach(() => {
jest.clearAllMocks();
});
it('renders with given data and columns', () => {
render(_jsx(DataTable, { ...defaultProps }));
sampleColumns.forEach((column) => {
expect(screen.getByText(column.Header)).toBeInTheDocument();
});
sampleData.forEach((row) => {
expect(screen.getByText(row.orderNumber)).toBeInTheDocument();
});
});
it('renders loading state', () => {
render(_jsx(DataTable, { ...defaultProps, loading: true, loadingRowCount: 3 }));
expect(screen.getAllByRole('row')).toHaveLength(4); // Header + 3 loading rows
});
it('handles row click', () => {
render(_jsx(DataTable, { ...defaultProps }));
fireEvent.click(screen.getByText('123'));
expect(defaultProps.handleRowClick).toHaveBeenCalledWith(sampleData[0]);
});
it('handles sorting when column header is clicked', async () => {
render(_jsx(DataTable, { ...defaultProps }));
const orderHeader = screen.getByText('Order #');
fireEvent.click(orderHeader);
await waitFor(() => {
expect(screen.getAllByRole('row')[1]).toHaveTextContent('123');
expect(screen.getAllByRole('row')[3]).toHaveTextContent('125');
});
fireEvent.click(orderHeader);
await waitFor(() => {
expect(screen.getAllByRole('row')[1]).toHaveTextContent('125');
expect(screen.getAllByRole('row')[3]).toHaveTextContent('123');
});
});
it('handles default sorting', () => {
const columnsWithDefaultSort = [
...sampleColumns,
{ Header: 'Default Sort', accessor: 'defaultSort', defaultSort: true },
];
const dataWithDefaultSort = sampleData.map((item, index) => ({
...item,
defaultSort: index,
}));
render(_jsx(DataTable, { ...defaultProps, columns: columnsWithDefaultSort, data: dataWithDefaultSort }));
const rows = screen.getAllByRole('row');
expect(within(rows[1]).getByText('0')).toBeInTheDocument();
expect(within(rows[3]).getByText('2')).toBeInTheDocument();
});
it('handles text filtering', async () => {
const { rerender } = render(_jsx(DataTable, { ...defaultProps }));
rerender(_jsx(DataTable, { ...defaultProps, filters: { orderNumber: ['123'] } }));
await waitFor(() => {
expect(screen.getAllByRole('row')).toHaveLength(2); // Header + 1 data row
expect(screen.getByText('123')).toBeInTheDocument();
expect(screen.queryByText('124')).not.toBeInTheDocument();
});
});
it('handles number filtering', async () => {
const { rerender } = render(_jsx(DataTable, { ...defaultProps }));
rerender(_jsx(DataTable, { ...defaultProps, filters: { amount: 2000 } }));
await waitFor(() => {
expect(screen.getAllByRole('row')).toHaveLength(2); // Header + 1 data row
expect(screen.getByText('124')).toBeInTheDocument();
expect(screen.queryByText('123')).not.toBeInTheDocument();
});
});
it('handles date range filtering', async () => {
const { rerender } = render(_jsx(DataTable, { ...defaultProps }));
rerender(_jsx(DataTable, { ...defaultProps, filters: {
dateCreated: { startDate: '2021-01-02', endDate: '2021-01-03' },
} }));
await waitFor(() => {
expect(screen.getAllByRole('row')).toHaveLength(3); // Header + 2 data rows
expect(screen.getByText('124')).toBeInTheDocument();
expect(screen.getByText('125')).toBeInTheDocument();
expect(screen.queryByText('123')).not.toBeInTheDocument();
});
});
it('handles column reordering', async () => {
render(_jsx(DataTable, { ...defaultProps, isDraggable: true }));
const headers = screen.getAllByRole('columnheader');
fireEvent.dragStart(headers[0]);
fireEvent.dragOver(headers[1]);
fireEvent.drop(headers[1]);
expect(defaultProps.setColumnOrder).toHaveBeenCalled();
});
it('handles column resizing', async () => {
render(_jsx(DataTable, { ...defaultProps, hasResize: true }));
const resizeHandle = screen.getAllByText('─')[0];
fireEvent.mouseDown(resizeHandle, { clientX: 0 });
fireEvent.mouseMove(document, { clientX: 100 });
fireEvent.mouseUp(document);
expect(defaultProps.setColumnWidths).toHaveBeenCalled();
});
it('renders with accordion when hasAccordion is true', () => {
render(_jsx(DataTable, { ...defaultProps, hasAccordion: true }));
expect(screen.getAllByText('Purchase Order')).toHaveLength(sampleData.length);
});
it('handles pagination correctly', async () => {
const onPageChange = jest.fn();
render(_jsx(DataTable, { ...defaultProps, pageSize: 2, onPageChange: onPageChange }));
const nextButton = screen.getByText('Next');
fireEvent.click(nextButton);
expect(onPageChange).toHaveBeenCalledWith(1, 2);
const previousButton = screen.getByText('Previous');
fireEvent.click(previousButton);
expect(onPageChange).toHaveBeenCalledWith(0, 2);
});
it('renders custom cell content when provided', () => {
const customColumns = [
...sampleColumns,
{
Header: 'Custom',
accessor: 'custom',
Cell: ({ value }) => _jsx("span", { children: `Custom: ${value}` }),
},
];
const customData = sampleData.map((item) => ({ ...item, custom: 'test' }));
render(_jsx(DataTable, { ...defaultProps, columns: customColumns, data: customData }));
expect(screen.getAllByText('Custom: test')).toHaveLength(customData.length);
expect(screen.getByText('Custom: test')).toBeInTheDocument();
});
it('handles empty data set', () => {
render(_jsx(DataTable, { ...defaultProps, data: [] }));
expect(screen.getByText('No data available')).toBeInTheDocument();
});
it('applies badge styling when badgeColumnConfig is provided', () => {
const badgeColumnConfig = {
orderState: {
'Purchase Order': { color: 'blue', variant: 'solid' },
Completed: { color: 'green', variant: 'outline' },
},
};
render(_jsx(DataTable, { ...defaultProps, badgeColumnConfig: badgeColumnConfig }));
expect(screen.getByText('Purchase Order').parentElement).toHaveClass('badge-blue-solid');
expect(screen.getByText('Completed').parentElement).toHaveClass('badge-green-outline');
});
it('renders with a dry-prepended className', () => {
const { container } = render(_jsx(DataTable, { ...defaultProps }));
expect(container.firstChild).toHaveClass('dry-data-table');
});
it('passes a ref to its outermost element', async () => {
const Wrapper = () => {
const ref = useRef(null);
const [refWasPassed, setRefWasPassed] = useState(false);
useEffect(() => {
setRefWasPassed(!!ref.current);
}, []);
return (_jsxs(_Fragment, { children: [_jsx(DataTable, { ref: ref, ...defaultProps }), refWasPassed && _jsx("div", { children: "Ref was passed!" })] }));
};
render(_jsx(Wrapper, {}));
await waitFor(() => screen.getByText('Ref was passed!'));
});
it('passes a downstream id', () => {
const id = 'test-id';
render(_jsx(DataTable, { ...defaultProps, id: id }));
expect(document.getElementById(id)).toBeInTheDocument();
});
it('passes any downstream className(s)', () => {
const className = 'first second third';
render(_jsx(DataTable, { ...defaultProps, className: className }));
const parentElement = screen.getByRole('table').parentElement;
expect(parentElement).toHaveClass('first');
expect(parentElement).toHaveClass('second');
expect(parentElement).toHaveClass('third');
});
it('passes any downstream data-* attribute(s)', () => {
const testValue = 'product-1234-abcd-5678-efgh';
render(_jsx(DataTable, { ...defaultProps, "data-product": testValue }));
const parentElement = screen.getByRole('table').parentElement;
expect(parentElement).toHaveAttribute('data-product', testValue);
});
it('supports downstream @testing-library `screen.getByTestId`', () => {
const testId = 'test-subject';
render(_jsx(DataTable, { ...defaultProps, "data-testid": testId }));
const parentElement = screen.getByRole('table').parentElement;
expect(parentElement).toHaveAttribute('data-testid', testId);
});
});
//# sourceMappingURL=DataTable.test.js.map