diff --git a/web/packages/common/src/components/DataView/useRowClick.test.tsx b/web/packages/common/src/components/DataView/useRowClick.test.tsx new file mode 100644 index 0000000000..631f762acc --- /dev/null +++ b/web/packages/common/src/components/DataView/useRowClick.test.tsx @@ -0,0 +1,260 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { useRowClick } from '@nemo/common/src/components/DataView/useRowClick'; +import { render, screen, fireEvent } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { FC } from 'react'; + +// Mock internal DataView module – useRowClick imports it only for TypeScript types +// but the module would still be loaded at runtime. Mocking avoids loading its full +// dependency tree (tanstack-table, KUI components, etc.) in this isolated test. +vi.mock('@nemo/common/src/components/DataView/internal', () => ({ + TanstackTable: {}, + Root: {}, +})); + +// ────────────────────────────────────────────────────────────────────────── +// Minimal test helpers +// ────────────────────────────────────────────────────────────────────────── + +type Item = { id: string; name: string }; + +// Helper used by Harness to invoke the wrapped makeColumns function and render +// the resulting cell content for each row. +const HELPER = { + accessor: (field: string, opts: Record = {}) => ({ + id: field, + accessorKey: field, + ...opts, + }), +}; +const PREBUILT = { + rowSelectionColumn: (opts: Record = {}) => ({ + id: 'row-selection', + ...opts, + }), + rowActionsColumn: (opts: Record = {}) => ({ + id: 'row-actions', + ...opts, + }), + rowExpansionColumn: (opts: Record = {}) => ({ + id: 'row-expansion', + ...opts, + }), +}; + +// Minimal test harness that exercises useRowClick without the full DataView stack. +// It renders a with one row per data item. Inside the first cell it places +// the keyboard target injected by wrapColumns, and the onClick handler is attached +// to the table element (same event-delegation pattern as the real TableContent). +interface HarnessProps { + data: Item[]; + onRowClick?: (row: Item, index: number) => void; +} + +const Harness: FC = ({ data, onRowClick }) => { + const { wrapColumns, onClick, className } = useRowClick(onRowClick, data); + + // Build a single accessor column. + const baseMakeColumns = (helper: typeof HELPER) => [ + helper.accessor('name', { header: 'Name' }), + ]; + + // wrapColumns(baseMakeColumns) returns a new MakeColumns function. + // Invoke it immediately with the test helper/prebuilt to get the column array. + const wrappedMakeColumns = wrapColumns( + baseMakeColumns as Parameters[0] + ); + const columns = wrappedMakeColumns( + HELPER as Parameters[0], + PREBUILT as Parameters[1] + ); + + return ( + // eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-noninteractive-element-interactions +
}> + + {data.map((item, index) => { + const cellContent = + typeof columns[0]?.cell === 'function' + ? (columns[0].cell as (ctx: Record) => React.ReactNode)({ + row: { + original: item, + index, + depth: 0, + getParentRow: () => undefined, + }, + getValue: () => item.name, + renderValue: () => item.name, + }) + : item.name; + + return ( + + + + ); + })} + +
{cellContent}
+ ); +}; + +const testData: Item[] = [ + { id: '1', name: 'Alice' }, + { id: '2', name: 'Bob' }, +]; + +// ────────────────────────────────────────────────────────────────────────── +// Tests +// ────────────────────────────────────────────────────────────────────────── + +describe('useRowClick – RowKeyboardTarget', () => { + it('renders a native