From bce4188ffa1b7cc8541eb21b8af4bcdb390458d2 Mon Sep 17 00:00:00 2001 From: Kevin Van Cott Date: Tue, 24 Dec 2024 13:39:01 -0600 Subject: [PATCH] filterFns unit tests and rearrange some fixtures --- packages/table-core/src/fns/filterFns.ts | 45 +++- .../tests/fixtures/data/generateColumns.ts | 17 -- .../fixtures/data/generateTestColumnDefs.ts | 20 ++ .../data/{makeData.ts => generateTestData.ts} | 34 ++- .../table-core/tests/fixtures/data/types.ts | 8 +- .../tests/helpers/createTestTable.ts | 54 ----- .../tests/helpers/generateTestRows.ts | 59 +++++ .../tests/helpers/generateTestTable.ts | 108 +++++++++ .../tests/helpers/rowPinningHelpers.ts | 12 +- .../row-pinning/rowSelectionFeature.test.ts | 28 +-- .../columnGroupingFeature.test.ts | 4 +- .../rowPinningFeature.utils.test.ts | 44 ++-- .../tests/unit/fns/filterFns.test.ts | 207 ++++++++++++++++++ tsconfig.json | 7 +- vitest.workspace.js | 14 ++ 15 files changed, 537 insertions(+), 124 deletions(-) delete mode 100644 packages/table-core/tests/fixtures/data/generateColumns.ts create mode 100644 packages/table-core/tests/fixtures/data/generateTestColumnDefs.ts rename packages/table-core/tests/fixtures/data/{makeData.ts => generateTestData.ts} (65%) delete mode 100644 packages/table-core/tests/helpers/createTestTable.ts create mode 100644 packages/table-core/tests/helpers/generateTestRows.ts create mode 100644 packages/table-core/tests/helpers/generateTestTable.ts create mode 100644 packages/table-core/tests/unit/fns/filterFns.test.ts create mode 100644 vitest.workspace.js diff --git a/packages/table-core/src/fns/filterFns.ts b/packages/table-core/src/fns/filterFns.ts index 271a65c43c..3cdcb89d95 100644 --- a/packages/table-core/src/fns/filterFns.ts +++ b/packages/table-core/src/fns/filterFns.ts @@ -50,7 +50,9 @@ export const filterFn_includesStringSensitive: FilterFn = < columnId: string, filterValue: string, ) => { - return Boolean(row.getValue(columnId)?.toString().includes(filterValue)) + return Boolean( + row.getValue(columnId)?.toString().includes(filterValue.toString()), + ) } filterFn_includesStringSensitive.autoRemove = (val: any) => testFalsy(val) @@ -96,6 +98,22 @@ export const filterFn_equalsString: FilterFn = < filterFn_equalsString.autoRemove = (val: any) => testFalsy(val) +/** + * Filter function for checking if a string is exactly equal to a given string. (Case-sensitive) + */ +export const filterFn_equalsStringSensitive: FilterFn = < + TFeatures extends TableFeatures, + TData extends RowData, +>( + row: Row, + columnId: string, + filterValue: string, +) => { + return row.getValue(columnId)?.toString() === filterValue +} + +filterFn_equalsStringSensitive.autoRemove = (val: any) => testFalsy(val) + // Number filters /** @@ -277,6 +295,20 @@ filterFn_inNumberRange.autoRemove = (val: any) => // Array filters +/** + * Filter function for checking if an array has a given value. + */ +export const filterFn_arrHas: FilterFn = < + TFeatures extends TableFeatures, + TData extends RowData, +>( + row: Row, + columnId: string, + filterValue: Array, +) => { + return filterValue.some((val) => row.getValue(columnId) === val) +} + /** * Filter function for checking if an array includes a given value. */ @@ -286,11 +318,13 @@ export const filterFn_arrIncludes: FilterFn = < >( row: Row, columnId: string, - filterValue: unknown, + filterValue: Array, ) => { - const value = row.getValue>(columnId) - if (!Array.isArray(value)) return false - return value.includes(filterValue) + return filterValue.some((val) => + (row.getValue(columnId) as Array | string).includes( + val as any, + ), + ) } filterFn_arrIncludes.autoRemove = (val: any) => testFalsy(val) || !val?.length @@ -338,6 +372,7 @@ filterFn_arrIncludesSome.autoRemove = (val: any) => export const filterFns = { arrIncludes: filterFn_arrIncludes, arrIncludesAll: filterFn_arrIncludesAll, + arrHas: filterFn_arrHas, arrIncludesSome: filterFn_arrIncludesSome, between: filterFn_between, betweenInclusive: filterFn_betweenInclusive, diff --git a/packages/table-core/tests/fixtures/data/generateColumns.ts b/packages/table-core/tests/fixtures/data/generateColumns.ts deleted file mode 100644 index 591c53592a..0000000000 --- a/packages/table-core/tests/fixtures/data/generateColumns.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { createColumnHelper } from '../../../src' -import type { Person, PersonColumn, PersonKeys } from './types' - -export function generateColumns(people: Array): Array { - const columnHelper = createColumnHelper() - const person = people[0] - - if (!person) { - return [] - } - - return Object.keys(person).map((key) => { - const typedKey = key as PersonKeys - - return columnHelper.accessor(typedKey, { id: typedKey }) - }) -} diff --git a/packages/table-core/tests/fixtures/data/generateTestColumnDefs.ts b/packages/table-core/tests/fixtures/data/generateTestColumnDefs.ts new file mode 100644 index 0000000000..ca3b639a72 --- /dev/null +++ b/packages/table-core/tests/fixtures/data/generateTestColumnDefs.ts @@ -0,0 +1,20 @@ +import { createColumnHelper } from '../../../src' +import type { Person, PersonColumn, PersonKeys } from './types' +import type { TableFeatures } from '../../../src' + +export function generateTestColumnDefs( + people: Array, +): Array> { + const columnHelper = createColumnHelper() + const person = people[0] + + if (!person) { + return [] + } + + return Object.keys(person).map((key) => { + const typedKey = key as PersonKeys + + return columnHelper.accessor(typedKey, { id: typedKey } as any) + }) +} diff --git a/packages/table-core/tests/fixtures/data/makeData.ts b/packages/table-core/tests/fixtures/data/generateTestData.ts similarity index 65% rename from packages/table-core/tests/fixtures/data/makeData.ts rename to packages/table-core/tests/fixtures/data/generateTestData.ts index 7663cb056a..6fe7f7d680 100644 --- a/packages/table-core/tests/fixtures/data/makeData.ts +++ b/packages/table-core/tests/fixtures/data/generateTestData.ts @@ -24,7 +24,7 @@ function createPerson(): Person { * e.g. makeData(3, 2) creates 3 parent rows with 2 sub-rows each * @returns An array of Person objects with optional nested subRows based on the provided lengths */ -export function makeData(...lengths: Array) { +export function generateTestData(...lengths: Array) { const makeDataLevel = (depth = 0): Array => { const len = lengths[depth] @@ -40,3 +40,35 @@ export function makeData(...lengths: Array) { return makeDataLevel() } + +export function getStaticTestData() { + return [ + { + id: '1', + firstName: 'John', + lastName: 'Doe', + age: 30, + visits: 100, + progress: 50, + status: 'relationship', + }, + { + id: '2', + firstName: 'Jane', + lastName: 'Smith', + age: 25, + visits: 200, + progress: 75, + status: 'complicated', + }, + { + id: '3', + firstName: 'Alice', + lastName: 'Johnson', + age: 35, + visits: 150, + progress: 60, + status: 'single', + }, + ] as const satisfies Array +} diff --git a/packages/table-core/tests/fixtures/data/types.ts b/packages/table-core/tests/fixtures/data/types.ts index 3ba761eba4..99cc27501d 100644 --- a/packages/table-core/tests/fixtures/data/types.ts +++ b/packages/table-core/tests/fixtures/data/types.ts @@ -1,7 +1,11 @@ -import type { ColumnDef } from '../../../src' +import type { ColumnDef, TableFeatures } from '../../../src' export type PersonKeys = keyof Person -export type PersonColumn = ColumnDef +export type PersonColumn = ColumnDef< + TFeatures, + Person, + any +> export type Person = { id: string diff --git a/packages/table-core/tests/helpers/createTestTable.ts b/packages/table-core/tests/helpers/createTestTable.ts deleted file mode 100644 index 3dd046c1ed..0000000000 --- a/packages/table-core/tests/helpers/createTestTable.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { constructTable, coreFeatures } from '../../src' -import { makeData } from '../fixtures/data/makeData' -import { generateColumns } from '../fixtures/data/generateColumns' -import type { TableOptions, TableState } from '../../src' -import type { Person } from '../fixtures/data/types' - -export function createTestTableWithData( - lengths: Array | number = 10, - options?: Omit, 'data' | 'columns'>, -) { - const lengthsArray = Array.isArray(lengths) ? lengths : [lengths] - const data = makeData(...lengthsArray) - const columns = generateColumns(data) - - return constructTable({ - data, - columns, - getSubRows: (row) => row.subRows, - ...options, - _features: { - ...options?._features, - ...coreFeatures, - }, - }) -} - -export function createTestTableWithDataAndState( - lengths: Array | number = 10, - options?: Omit< - TableOptions, - 'data' | 'columns' | 'onStateChange' - >, -) { - let state = { ...options?.initialState } as TableState - - const table = createTestTableWithData(lengths, { - ...options, - _features: { - ...options?._features, - }, - state, - onStateChange: (updater) => { - if (typeof updater === 'function') { - state = updater(state) - } else { - state = updater - } - - table.options.state = state - }, - }) - - return table -} diff --git a/packages/table-core/tests/helpers/generateTestRows.ts b/packages/table-core/tests/helpers/generateTestRows.ts new file mode 100644 index 0000000000..d9fe908d16 --- /dev/null +++ b/packages/table-core/tests/helpers/generateTestRows.ts @@ -0,0 +1,59 @@ +import { + generateTestTableFromData, + generateTestTableWithData, + generateTestTableWithDataAndState, + generateTestTableWithStateFromData, +} from './generateTestTable' +import type { TableFeatures, TableOptions } from '../../src' +import type { Person } from '../fixtures/data/types' + +export function generateTestRowsWithData( + lengths: Array | number = 10, + options?: Omit, 'data' | 'columns'> & { + _features?: TFeatures + }, +) { + const testTable = generateTestTableWithData(lengths, options) + return testTable.getRowModel().rows +} + +export function generateTestRowsFromData( + data: Array, + options?: Omit, 'data' | 'columns'> & { + _features?: TFeatures + }, +) { + const testTable = generateTestTableFromData(data, options) + return testTable.getRowModel().rows +} + +export function generateTestRowsWithState( + lengths: Array | number = 10, + options?: Omit< + TableOptions, + 'data' | 'columns' | 'onStateChange' + > & { + _features?: TFeatures + }, +) { + const testTable = generateTestTableWithDataAndState( + lengths, + options, + ) + return testTable.getRowModel().rows +} + +export function generateTestRowsWithStateFromData< + TFeatures extends TableFeatures, +>( + data: Array, + options?: Omit< + TableOptions, + 'data' | 'columns' | 'onStateChange' + > & { + _features?: TFeatures + }, +) { + const testTable = generateTestTableWithStateFromData(data, options) + return testTable.getRowModel().rows +} diff --git a/packages/table-core/tests/helpers/generateTestTable.ts b/packages/table-core/tests/helpers/generateTestTable.ts new file mode 100644 index 0000000000..942ba68f02 --- /dev/null +++ b/packages/table-core/tests/helpers/generateTestTable.ts @@ -0,0 +1,108 @@ +import { constructTable, coreFeatures } from '../../src' +import { generateTestColumnDefs } from '../fixtures/data/generateTestColumnDefs' +import { generateTestData } from '../fixtures/data/generateTestData' +import type { Row, TableFeatures, TableOptions, TableState } from '../../src' +import type { Person } from '../fixtures/data/types' + +export function generateTestTableWithData( + lengths: Array | number = 10, + options?: Omit, 'data' | 'columns'>, +) { + const lengthsArray = Array.isArray(lengths) ? lengths : [lengths] + const data = generateTestData(...lengthsArray) + const columns = generateTestColumnDefs(data) + + return constructTable({ + data, + columns, + getSubRows: (row: Row) => row.subRows, + ...options, + _features: { + ...coreFeatures, + ...options?._features, + }, + } as any) +} + +export function generateTestTableFromData( + data: Array, + options?: Omit, 'data' | 'columns'>, +) { + const columns = generateTestColumnDefs(data) + return constructTable({ + data, + columns, + ...options, + _features: { + ...coreFeatures, + ...options?._features, + }, + } as any) +} + +export function generateTestTableWithDataAndState< + TFeatures extends TableFeatures, +>( + lengths: Array | number = 10, + options?: Omit< + TableOptions, + 'data' | 'columns' | 'onStateChange' + >, +) { + const lengthsArray = Array.isArray(lengths) ? lengths : [lengths] + const data = generateTestData(...lengthsArray) + const columns = generateTestColumnDefs(data) + let state = { ...options?.initialState } as TableState + + const table = generateTestTableWithData(lengths, { + data, + columns, + ...options, + _features: { + ...options?._features, + }, + state, + onStateChange: (updater: any) => { + if (typeof updater === 'function') { + state = updater(state) + } else { + state = updater + } + + table.options.state = state + }, + } as any) + + return table +} + +export function generateTestTableWithStateFromData< + TFeatures extends TableFeatures, +>( + data: Array, + options?: Omit< + TableOptions, + 'data' | 'columns' | 'onStateChange' + >, +) { + const columns = generateTestColumnDefs(data) + let state = { ...options?.initialState } as TableState + + const table = generateTestTableFromData(data, { + columns, + ...options, + _features: { + ...options?._features, + }, + state, + onStateChange: (updater: any) => { + if (typeof updater === 'function') { + state = updater(state) + } else { + state = updater + } + }, + } as any) + + return table +} diff --git a/packages/table-core/tests/helpers/rowPinningHelpers.ts b/packages/table-core/tests/helpers/rowPinningHelpers.ts index 3fd8ad65b3..2ebdb93842 100644 --- a/packages/table-core/tests/helpers/rowPinningHelpers.ts +++ b/packages/table-core/tests/helpers/rowPinningHelpers.ts @@ -3,9 +3,9 @@ import { getDefaultRowPinningState } from '../../src/features/row-pinning/rowPin import { rowPinningFeature } from '../../src' import { - createTestTableWithData, - createTestTableWithDataAndState, -} from './createTestTable' + generateTestTableWithData, + generateTestTableWithDataAndState, +} from './generateTestTable' import type { RowPinningState, TableOptions } from '../../src' import type { Person } from '../fixtures/data/types' @@ -13,7 +13,7 @@ export function createTableWithPinningState( rowCount = 10, pinningState?: RowPinningState, ) { - const table = createTestTableWithData(rowCount) + const table = generateTestTableWithData(rowCount) if (pinningState) { table.options.state = { rowPinning: pinningState, @@ -28,7 +28,7 @@ export function createTableWithPinningState( export function createTableWithMockOnPinningChange(rowCount = 10) { const onRowPinningChangeMock = vi.fn() - const table = createTestTableWithData(rowCount) + const table = generateTestTableWithData(rowCount) table.options.onRowPinningChange = onRowPinningChangeMock return { table, onRowPinningChangeMock } } @@ -40,7 +40,7 @@ export function createRowPinningTable( >, lengths: Array | number = 10, ) { - const table = createTestTableWithDataAndState(lengths, { + const table = generateTestTableWithDataAndState(lengths, { enableRowPinning: true, initialState: { rowPinning: { diff --git a/packages/table-core/tests/implementation/features/row-pinning/rowSelectionFeature.test.ts b/packages/table-core/tests/implementation/features/row-pinning/rowSelectionFeature.test.ts index 55994c39b2..812402a85f 100644 --- a/packages/table-core/tests/implementation/features/row-pinning/rowSelectionFeature.test.ts +++ b/packages/table-core/tests/implementation/features/row-pinning/rowSelectionFeature.test.ts @@ -6,7 +6,7 @@ import { rowSelectionFeature, } from '../../../../src' import * as RowSelectionUtils from '../../../../src/features/row-selection/rowSelectionFeature.utils' -import { makeData } from '../../../fixtures/data/makeData' +import { generateTestData } from '../../../fixtures/data/generateTestData' import type { Person } from '../../../fixtures/data/types' import type { ColumnDef } from '../../../../src' @@ -32,7 +32,7 @@ function generateColumns(people: Array): Array { describe('rowSelectionFeature', () => { describe('selectRowsFn', () => { it('should only return rows that are selected', () => { - const data = makeData(5) + const data = generateTestData(5) const columns = generateColumns(data) const table = constructTable({ @@ -62,7 +62,7 @@ describe('rowSelectionFeature', () => { }) it('should recurse into subRows and only return selected subRows', () => { - const data = makeData(3, 2) // assuming 3 parent rows with 2 sub-rows each + const data = generateTestData(3, 2) // assuming 3 parent rows with 2 sub-rows each const columns = generateColumns(data) const table = constructTable({ @@ -92,7 +92,7 @@ describe('rowSelectionFeature', () => { }) it('should return an empty list if no rows are selected', () => { - const data = makeData(5) + const data = generateTestData(5) const columns = generateColumns(data) const table = constructTable({ @@ -119,7 +119,7 @@ describe('rowSelectionFeature', () => { }) describe('isRowSelected', () => { it('should return true if the row id exists in selection and is set to true', () => { - const data = makeData(3) + const data = generateTestData(3) const columns = generateColumns(data) const table = constructTable({ @@ -145,7 +145,7 @@ describe('rowSelectionFeature', () => { }) it('should return false if the row id exists in selection and is set to false', () => { - const data = makeData(3) + const data = generateTestData(3) const columns = generateColumns(data) const table = constructTable({ @@ -171,7 +171,7 @@ describe('rowSelectionFeature', () => { }) it('should return false if the row id does not exist in selection', () => { - const data = makeData(3) + const data = generateTestData(3) const columns = generateColumns(data) const table = constructTable({ @@ -197,7 +197,7 @@ describe('rowSelectionFeature', () => { }) it('should return false if selection is an empty object', () => { - const data = makeData(3) + const data = generateTestData(3) const columns = generateColumns(data) const table = constructTable({ @@ -219,7 +219,7 @@ describe('rowSelectionFeature', () => { }) describe('isSubRowSelected', () => { it('should return false if there are no sub-rows', () => { - const data = makeData(3) + const data = generateTestData(3) const columns = generateColumns(data) const table = constructTable({ @@ -241,7 +241,7 @@ describe('rowSelectionFeature', () => { }) it('should return false if no sub-rows are selected', () => { - const data = makeData(3, 2) + const data = generateTestData(3, 2) const columns = generateColumns(data) const table = constructTable({ @@ -266,7 +266,7 @@ describe('rowSelectionFeature', () => { }) it('should return some if some sub-rows are selected', () => { - const data = makeData(3, 2) + const data = generateTestData(3, 2) const columns = generateColumns(data) const table = constructTable({ @@ -293,7 +293,7 @@ describe('rowSelectionFeature', () => { }) it('should return all if all sub-rows are selected', () => { - const data = makeData(3, 2) + const data = generateTestData(3, 2) const columns = generateColumns(data) const table = constructTable({ @@ -320,7 +320,7 @@ describe('rowSelectionFeature', () => { expect(result).toEqual('all') }) it('should return all if all selectable sub-rows are selected', () => { - const data = makeData(3, 2) + const data = generateTestData(3, 2) const columns = generateColumns(data) const table = constructTable({ @@ -346,7 +346,7 @@ describe('rowSelectionFeature', () => { expect(result).toEqual('all') }) it('should return some when some nested sub-rows are selected', () => { - const data = makeData(3, 2, 2) + const data = generateTestData(3, 2, 2) const columns = generateColumns(data) const table = constructTable({ diff --git a/packages/table-core/tests/performance/features/column-grouping/columnGroupingFeature.test.ts b/packages/table-core/tests/performance/features/column-grouping/columnGroupingFeature.test.ts index 4cc7cb50eb..6916cf4c24 100644 --- a/packages/table-core/tests/performance/features/column-grouping/columnGroupingFeature.test.ts +++ b/packages/table-core/tests/performance/features/column-grouping/columnGroupingFeature.test.ts @@ -7,7 +7,7 @@ import { createGroupedRowModel, } from '../../../../src' import { createColumnHelper } from '../../../../src/helpers/columnHelper' -import { makeData } from '../../../fixtures/data/makeData' +import { generateTestData } from '../../../fixtures/data/generateTestData' import type { Person } from '../../../fixtures/data/types' import type { ColumnDef } from '../../../../src' @@ -32,7 +32,7 @@ function generateColumns(people: Array): Array { describe('#getGroupedRowModel', () => { it('groups 50k rows and 3 grouped columns with clustered data in less than 5 seconds', () => { - const data = makeData(50000) + const data = generateTestData(50000) const columns = generateColumns(data) const grouping = ['firstName', 'lastName', 'age'] const start = new Date() diff --git a/packages/table-core/tests/unit/features/row-pinning/rowPinningFeature.utils.test.ts b/packages/table-core/tests/unit/features/row-pinning/rowPinningFeature.utils.test.ts index 57b79040c0..db16411f54 100644 --- a/packages/table-core/tests/unit/features/row-pinning/rowPinningFeature.utils.test.ts +++ b/packages/table-core/tests/unit/features/row-pinning/rowPinningFeature.utils.test.ts @@ -12,7 +12,7 @@ import { table_resetRowPinning, table_setRowPinning, } from '../../../../src/features/row-pinning/rowPinningFeature.utils' -import { createTestTableWithData } from '../../../helpers/createTestTable' +import { generateTestTableWithData } from '../../../helpers/generateTestTable' import { getUpdaterResult } from '../../../helpers/testUtils' import { createTableWithMockOnPinningChange, @@ -79,7 +79,7 @@ describe('table_setRowPinning', () => { }) it('should handle undefined onRowPinningChange without error', () => { - const table = createTestTableWithData(DEFAULT_ROW_COUNT) + const table = generateTestTableWithData(DEFAULT_ROW_COUNT) expect(() => { table_setRowPinning(table, EMPTY_PINNING_STATE) @@ -171,7 +171,7 @@ describe('table_getIsSomeRowsPinned', () => { describe('table_getTopRows and table_getBottomRows', () => { it('should return empty arrays when no rows are pinned', () => { - const table = createTestTableWithData(10) + const table = generateTestTableWithData(10) table.options.state = { rowPinning: getDefaultRowPinningState(), } @@ -181,7 +181,7 @@ describe('table_getTopRows and table_getBottomRows', () => { }) it('should return pinned rows with position property', () => { - const table = createTestTableWithData(10) + const table = generateTestTableWithData(10) const row0 = table.getRow('0', true) const row1 = table.getRow('1', true) @@ -203,7 +203,7 @@ describe('table_getTopRows and table_getBottomRows', () => { }) it('should handle keepPinnedRows=false by only returning visible rows', () => { - const table = createTestTableWithData(10) + const table = generateTestTableWithData(10) table.options.keepPinnedRows = false // Setup a row model with only some rows visible @@ -232,7 +232,7 @@ describe('table_getTopRows and table_getBottomRows', () => { }) it('should handle keepPinnedRows=true by returning all pinned rows regardless of visibility', () => { - const table = createTestTableWithData(10) + const table = generateTestTableWithData(10) table.options.keepPinnedRows = true // Setup a row model with only some rows visible @@ -261,7 +261,7 @@ describe('table_getTopRows and table_getBottomRows', () => { }) it('should handle undefined state', () => { - const table = createTestTableWithData(10) + const table = generateTestTableWithData(10) table.options.state = undefined expect(table_getTopRows(table)).toEqual([]) @@ -271,7 +271,7 @@ describe('table_getTopRows and table_getBottomRows', () => { describe('table_getCenterRows', () => { it('should return all rows when no rows are pinned', () => { - const table = createTestTableWithData(10) + const table = generateTestTableWithData(10) table.options.state = { rowPinning: getDefaultRowPinningState(), } @@ -283,7 +283,7 @@ describe('table_getCenterRows', () => { }) it('should return only unpinned rows when some rows are pinned', () => { - const table = createTestTableWithData(10) + const table = generateTestTableWithData(10) const allRows = table.getRowModel().rows table.options.state = { @@ -302,7 +302,7 @@ describe('table_getCenterRows', () => { }) it('should handle undefined state', () => { - const table = createTestTableWithData(10) + const table = generateTestTableWithData(10) const allRows = table.getRowModel().rows table.options.state = undefined @@ -314,14 +314,14 @@ describe('table_getCenterRows', () => { describe('row_getCanPin', () => { it('should return true when enableRowPinning is undefined', () => { - const table = createTestTableWithData(10) + const table = generateTestTableWithData(10) const row = table.getRow('0') expect(row_getCanPin(row)).toBe(true) }) it('should return false when enableRowPinning is false', () => { - const table = createTestTableWithData(10) + const table = generateTestTableWithData(10) table.options.enableRowPinning = false const row = table.getRow('0') @@ -330,7 +330,7 @@ describe('row_getCanPin', () => { }) it('should return true when enableRowPinning is true', () => { - const table = createTestTableWithData(10) + const table = generateTestTableWithData(10) table.options.enableRowPinning = true const row = table.getRow('0') @@ -340,7 +340,7 @@ describe('row_getCanPin', () => { it('should use enableRowPinning function when provided', () => { const enableRowPinning = vi.fn((row) => row.id === '1') - const table = createTestTableWithData(10) + const table = generateTestTableWithData(10) table.options.enableRowPinning = enableRowPinning @@ -355,7 +355,7 @@ describe('row_getCanPin', () => { describe('row_getIsPinned', () => { it('should return false when no rows are pinned', () => { - const table = createTestTableWithData(10) + const table = generateTestTableWithData(10) table.options.state = { rowPinning: getDefaultRowPinningState(), } @@ -365,7 +365,7 @@ describe('row_getIsPinned', () => { }) it('should return "top" when row is pinned to top', () => { - const table = createTestTableWithData(10) + const table = generateTestTableWithData(10) table.options.state = { rowPinning: { top: [ROW[0]], @@ -378,7 +378,7 @@ describe('row_getIsPinned', () => { }) it('should return "bottom" when row is pinned to bottom', () => { - const table = createTestTableWithData(10) + const table = generateTestTableWithData(10) table.options.state = { rowPinning: { top: [], @@ -391,7 +391,7 @@ describe('row_getIsPinned', () => { }) it('should handle undefined state', () => { - const table = createTestTableWithData(10) + const table = generateTestTableWithData(10) table.options.state = undefined const row = table.getRow('0') @@ -401,7 +401,7 @@ describe('row_getIsPinned', () => { describe('row_getPinnedIndex', () => { it('should return -1 when row is not pinned', () => { - const table = createTestTableWithData(10) + const table = generateTestTableWithData(10) table.options.state = { rowPinning: getDefaultRowPinningState(), } @@ -411,7 +411,7 @@ describe('row_getPinnedIndex', () => { }) it('should return correct index for top pinned rows', () => { - const table = createTestTableWithData(10) + const table = generateTestTableWithData(10) table.options.state = { rowPinning: { top: [ROW[0], ROW[1], ROW[2]], @@ -425,7 +425,7 @@ describe('row_getPinnedIndex', () => { }) it('should return correct index for bottom pinned rows', () => { - const table = createTestTableWithData(10) + const table = generateTestTableWithData(10) table.options.state = { rowPinning: { top: [], @@ -439,7 +439,7 @@ describe('row_getPinnedIndex', () => { }) it('should handle undefined state', () => { - const table = createTestTableWithData(10) + const table = generateTestTableWithData(10) table.options.state = undefined const row = table.getRow('0') diff --git a/packages/table-core/tests/unit/fns/filterFns.test.ts b/packages/table-core/tests/unit/fns/filterFns.test.ts new file mode 100644 index 0000000000..c808d6750d --- /dev/null +++ b/packages/table-core/tests/unit/fns/filterFns.test.ts @@ -0,0 +1,207 @@ +import { describe, expect, it } from 'vitest' +import { generateTestRowsWithStateFromData } from '../../helpers/generateTestRows' +import { + columnFilteringFeature, + filterFn_equals, + filterFn_equalsString, + filterFn_equalsStringSensitive, + filterFn_includesString, + filterFn_includesStringSensitive, + filterFn_weakEquals, +} from '../../../src' +import { getStaticTestData } from '../../fixtures/data/generateTestData' + +// TODO - fix _features not being inferred correctly +const mockRows = generateTestRowsWithStateFromData(getStaticTestData(), { + _features: { + columnFilteringFeature, + }, +}) + +describe('Filter Functions', () => { + describe('Basic Filters', () => { + describe('filterFn_equals', () => { + it('should match exact values', () => { + const row = mockRows[0]! + const columnId = 'firstName' + const filterValue = 'John' + const result = filterFn_equals(row as any, columnId, filterValue) + expect(result).toBe(true) + }) + it('should not match values with type coercion (e.g., "1" == 1)', () => { + const row = mockRows[0]! + const columnId = 'id' + const filterValue = 1 // number instead of string + const result = filterFn_equals(row as any, columnId, filterValue) + expect(result).toBe(false) + }) + it('should handle null/undefined values', () => { + const row = mockRows[0]! + const columnId = 'firstName' + const filterValue = null + const result = filterFn_equals(row as any, columnId, filterValue) + expect(result).toBe(false) + }) + it('should correctly identify non-matches', () => { + const row = mockRows[0]! + const columnId = 'firstName' + const filterValue = 'Jane' + const result = filterFn_equals(row as any, columnId, filterValue) + expect(result).toBe(false) + }) + }) + + describe('filterFn_weakEquals', () => { + it('should match exact values', () => { + const row = mockRows[0]! + const columnId = 'firstName' + const filterValue = 'John' + const result = filterFn_weakEquals(row as any, columnId, filterValue) + expect(result).toBe(true) + }) + it('should match values with type coercion (e.g., "1" == 1)', () => { + const row = mockRows[0]! + const columnId = 'id' + const filterValue = 1 // number instead of string + const result = filterFn_weakEquals(row as any, columnId, filterValue) + expect(result).toBe(true) + }) + it('should handle null/undefined values', () => { + const row = mockRows[0]! + const columnId = 'firstName' + const filterValue = null + const result = filterFn_weakEquals(row as any, columnId, filterValue) + expect(result).toBe(false) + }) + it('should correctly identify non-matches', () => { + const row = mockRows[0]! + const columnId = 'firstName' + const filterValue = 'Jane' + const result = filterFn_weakEquals(row as any, columnId, filterValue) + expect(result).toBe(false) + }) + }) + }) + + describe('String Filters', () => { + describe('filterFn_includesStringSensitive', () => { + it('should match case-sensitive substrings', () => { + const row = mockRows[0]! + const columnId = 'firstName' + const filterValue = 'John' + const result = filterFn_includesStringSensitive( + row as any, + columnId, + filterValue, + ) + expect(result).toBe(true) + }) + it('should not match different case substrings', () => { + const row = mockRows[0]! + const columnId = 'firstName' + const filterValue = 'john' + const result = filterFn_includesStringSensitive( + row as any, + columnId, + filterValue, + ) + expect(result).toBe(false) + }) + it('should handle partial matches', () => { + const row = mockRows[0]! + const columnId = 'firstName' + const filterValue = 'ohn' + const result = filterFn_includesStringSensitive( + row as any, + columnId, + filterValue, + ) + expect(result).toBe(true) + }) + }) + + describe('filterFn_includesString', () => { + it('should match case-insensitive substrings', () => { + const row = mockRows[0]! + const columnId = 'firstName' + const filterValue = 'john' + const result = filterFn_includesString( + row as any, + columnId, + filterValue, + ) + expect(result).toBe(true) + }) + it('should match different case substrings', () => { + const row = mockRows[0]! + const columnId = 'firstName' + const filterValue = 'john' + const result = filterFn_includesString( + row as any, + columnId, + filterValue, + ) + expect(result).toBe(true) + }) + it('should handle partial matches', () => { + const row = mockRows[0]! + const columnId = 'firstName' + const filterValue = 'ohn' + const result = filterFn_includesString( + row as any, + columnId, + filterValue, + ) + expect(result).toBe(true) + }) + }) + + describe('filterFn_equalsString', () => { + it('should match exact strings', () => { + const row = mockRows[0]! + const columnId = 'firstName' + const filterValue = 'John' + const result = filterFn_equalsString(row as any, columnId, filterValue) + expect(result).toBe(true) + }) + it('should match case-insensitive exact strings', () => { + const row = mockRows[0]! + const columnId = 'firstName' + const filterValue = 'john' + const result = filterFn_equalsString(row as any, columnId, filterValue) + expect(result).toBe(true) + }) + it('should not match partial strings', () => { + const row = mockRows[0]! + const columnId = 'firstName' + const filterValue = 'ohn' + const result = filterFn_equalsString(row as any, columnId, filterValue) + expect(result).toBe(false) + }) + }) + + describe('filterFn_equalsStringSensitive', () => { + it('should match case-sensitive exact strings', () => { + const row = mockRows[0]! + const columnId = 'firstName' + const filterValue = 'John' + const result = filterFn_equalsStringSensitive(row as any, columnId, filterValue) + expect(result).toBe(true) + }) + it('should not match case-insensitive exact strings', () => { + const row = mockRows[0]! + const columnId = 'firstName' + const filterValue = 'john' + const result = filterFn_equalsStringSensitive(row as any, columnId, filterValue) + expect(result).toBe(false) + }) + it('should not match partial strings', () => { + const row = mockRows[0]! + const columnId = 'firstName' + const filterValue = 'ohn' + const result = filterFn_equalsStringSensitive(row as any, columnId, filterValue) + expect(result).toBe(false) + }) + }) + }) +}) diff --git a/tsconfig.json b/tsconfig.json index 5a22056363..a7999981fe 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -23,5 +23,10 @@ "strict": true, "target": "ES2020" }, - "include": ["prettier.config.cjs", "scripts", "eslint.config.js"] + "include": [ + "prettier.config.cjs", + "scripts", + "eslint.config.js", + "vitest.workspace.js" + ] } diff --git a/vitest.workspace.js b/vitest.workspace.js new file mode 100644 index 0000000000..4103534a26 --- /dev/null +++ b/vitest.workspace.js @@ -0,0 +1,14 @@ +import { defineWorkspace } from 'vitest/config' + +export default defineWorkspace([ + './packages/react-table-devtools/vite.config.ts', + './packages/svelte-table/vite.config.ts', + './packages/qwik-table/vite.config.ts', + './packages/lit-table/vite.config.ts', + './packages/vue-table/vite.config.ts', + './packages/solid-table/vite.config.ts', + './packages/react-table/vite.config.ts', + './packages/table-core/vite.config.ts', + './packages/angular-table/vite.config.ts', + './packages/match-sorter-utils/vite.config.ts', +])