import { describe, expect, it } from 'vitest';
|
|
import {
|
createInputTableRowClickHandler,
|
getInputTableCellInteractionAttrs,
|
isInputTableCellEditable,
|
isInputTableInteractiveTarget,
|
toggleInputTableRowSelection,
|
} from '../helpers/rowSelection';
|
|
interface TestRow {
|
id?: string;
|
}
|
|
const row1: TestRow = { id: 'row-1' };
|
const row2: TestRow = { id: 'row-2' };
|
|
describe('toggleInputTableRowSelection', () => {
|
it('adds an unselected row without replacing other selections', () => {
|
expect(toggleInputTableRowSelection(['row-1'], [row1], row2, (row) => row.id as string)).toEqual({
|
selectedRowKeys: ['row-1', 'row-2'],
|
selectedRows: [row1, row2],
|
});
|
});
|
|
it('removes only the clicked row when it is already selected', () => {
|
expect(toggleInputTableRowSelection(['row-1', 'row-2'], [row1, row2], row1, (row) => row.id as string)).toEqual({
|
selectedRowKeys: ['row-2'],
|
selectedRows: [row2],
|
});
|
});
|
|
it('does not mutate the existing selection arrays', () => {
|
const selectedRowKeys = ['row-1'];
|
const selectedRows = [row1];
|
|
toggleInputTableRowSelection(selectedRowKeys, selectedRows, row2, (row) => row.id as string);
|
|
expect(selectedRowKeys).toEqual(['row-1']);
|
expect(selectedRows).toEqual([row1]);
|
});
|
});
|
|
describe('createInputTableRowClickHandler', () => {
|
function createHarness(options: { enabled?: boolean; readonly?: boolean } = {}) {
|
let selection = { selectedRowKeys: ['row-1'], selectedRows: [row1] };
|
let updateCount = 0;
|
const customRow = createInputTableRowClickHandler<TestRow, string>({
|
getRowKey: (row) => row.id,
|
getSelectedRowKeys: () => selection.selectedRowKeys,
|
getSelectedRows: () => selection.selectedRows,
|
isEnabled: () => options.enabled !== false,
|
isRowReadonly: () => options.readonly === true,
|
updateSelection: (nextSelection) => {
|
selection = nextSelection;
|
updateCount++;
|
},
|
});
|
|
return {
|
click: (row: TestRow, target: EventTarget | null) => customRow(row).onClick({ target }),
|
getSelection: () => selection,
|
getUpdateCount: () => updateCount,
|
};
|
}
|
|
it('publishes a toggled selection for an ordinary row click', () => {
|
const harness = createHarness();
|
const target = document.createElement('td');
|
|
harness.click(row2, target);
|
|
expect(harness.getSelection()).toEqual({
|
selectedRowKeys: ['row-1', 'row-2'],
|
selectedRows: [row1, row2],
|
});
|
expect(harness.getUpdateCount()).toBe(1);
|
});
|
|
it('ignores clicks from interactive row content', () => {
|
const harness = createHarness();
|
const control = document.createElement('div');
|
const target = document.createElement('input');
|
control.dataset.inputTableInteractive = '';
|
control.append(target);
|
|
harness.click(row2, target);
|
|
expect(harness.getSelection()).toEqual({ selectedRowKeys: ['row-1'], selectedRows: [row1] });
|
expect(harness.getUpdateCount()).toBe(0);
|
});
|
|
it.each([
|
['batch selection is disabled', { enabled: false }],
|
['the clicked row is read-only', { readonly: true }],
|
])('ignores the click when %s', (_label, options) => {
|
const harness = createHarness(options);
|
|
harness.click(row2, document.createElement('td'));
|
|
expect(harness.getUpdateCount()).toBe(0);
|
});
|
|
it('ignores rows without a key', () => {
|
const harness = createHarness();
|
|
harness.click({}, document.createElement('td'));
|
|
expect(harness.getUpdateCount()).toBe(0);
|
});
|
});
|
|
describe('isInputTableInteractiveTarget', () => {
|
it.each(['a', 'button'])('recognizes row action %s elements', (tagName) => {
|
expect(isInputTableInteractiveTarget(document.createElement(tagName))).toBe(true);
|
});
|
|
it('recognizes nested content inside a field marked editable', () => {
|
const control = document.createElement('div');
|
const target = document.createElement('span');
|
control.dataset.inputTableInteractive = '';
|
control.append(target);
|
|
expect(isInputTableInteractiveTarget(target)).toBe(true);
|
});
|
|
it.each(['input', 'select', 'textarea'])('allows row selection from unmarked %s content', (tagName) => {
|
expect(isInputTableInteractiveTarget(document.createElement(tagName))).toBe(false);
|
});
|
|
it('recognizes the complete Ant Design selection cell', () => {
|
const selectionCell = document.createElement('td');
|
const target = document.createElement('span');
|
selectionCell.className = 'ant-table-selection-column';
|
selectionCell.append(target);
|
|
expect(isInputTableInteractiveTarget(target)).toBe(true);
|
});
|
|
it('allows clicks on ordinary table-cell content', () => {
|
const cell = document.createElement('td');
|
const target = document.createElement('span');
|
cell.append(target);
|
|
expect(isInputTableInteractiveTarget(target)).toBe(false);
|
expect(isInputTableInteractiveTarget(null)).toBe(false);
|
});
|
});
|
|
describe('isInputTableCellEditable', () => {
|
it('marks an enabled generated field as editable', () => {
|
expect(isInputTableCellEditable({})).toBe(true);
|
});
|
|
it.each([
|
['disabled', { disabled: true }],
|
['readonly', { readonly: true }],
|
['detailed', { detailed: true }],
|
])('treats a %s generated field as row-clickable content', (_label, controlProps) => {
|
expect(isInputTableCellEditable(controlProps)).toBe(false);
|
});
|
});
|
|
describe('getInputTableCellInteractionAttrs', () => {
|
it('marks an enabled field as interactive', () => {
|
expect(getInputTableCellInteractionAttrs({})).toEqual({ 'data-input-table-interactive': '' });
|
});
|
|
it('makes a disabled field pass pointer events through to the table row', () => {
|
expect(getInputTableCellInteractionAttrs({ disabled: true })).toEqual({ 'data-input-table-click-through': '' });
|
});
|
|
it('keeps a disabled detail field interactive', () => {
|
expect(getInputTableCellInteractionAttrs({ disabled: true, disabledButClickable: true })).toEqual({ 'data-input-table-interactive': '' });
|
});
|
|
it.each([
|
['readonly', { readonly: true }],
|
['detailed', { detailed: true }],
|
])('leaves a %s field unmarked so its click bubbles normally', (_label, controlProps) => {
|
expect(getInputTableCellInteractionAttrs(controlProps)).toEqual({});
|
});
|
});
|