import type { GridState } from '..' import { jest } from '@jest/globals' import type { StoreSimpleSelectors } from '../selectors' import type { SelectIsInRangeSelection, SelectCellRangeBorders, SelectRangeIds, } from './range-selection' import generateSelectors from './range-selection' import type { GridRowId } from '../../types' import { BORDERS } from '../../constants' import type { SelectColumnSpanByRowId } from './row' const state = {} as GridState describe('compositeSelectors - range-selection', () => { let selectIsInRangeSelection: SelectIsInRangeSelection let selectCellRangeBorders: SelectCellRangeBorders let selectRangeIds: SelectRangeIds let selectRangeSelection: jest.Mock< StoreSimpleSelectors['selectRangeSelection'] > let selectRangeSelectionPreview: jest.Mock< StoreSimpleSelectors['selectRangeSelectionPreview'] > let selectColumnIdsWithHidden: jest.Mock< StoreSimpleSelectors['selectColumnIdsWithHidden'] > let selectHiddenIds: jest.Mock let selectRowIds: jest.Mock<(state: GridState) => GridRowId[]> let selectColumnSpanByRowId: jest.Mock beforeEach(() => { selectRangeSelection = jest .fn() .mockReturnValue(null) selectRangeSelectionPreview = jest .fn() .mockReturnValue(null) selectColumnIdsWithHidden = jest .fn() .mockReturnValue(['col1', 'col2', 'col3', 'col4']) selectHiddenIds = jest .fn() .mockReturnValue([]) selectRowIds = jest .fn<(state: GridState) => GridRowId[]>() .mockReturnValue(['row1', 'row2', 'row3', 'row4']) selectColumnSpanByRowId = jest .fn() .mockReturnValue(null) ;({ selectIsInRangeSelection, selectCellRangeBorders, selectRangeIds } = generateSelectors( { selectRangeSelection, selectRangeSelectionPreview, selectColumnIdsWithHidden, selectHiddenIds, }, selectRowIds as any, selectColumnSpanByRowId )) }) describe('when no range selection exists', () => { beforeEach(() => { selectRangeSelection.mockReturnValue(null) selectRangeSelectionPreview.mockReturnValue(null) }) describe('selectIsInRangeSelection', () => { it('should return false for any cell', () => { expect(selectIsInRangeSelection(state, 'col1', 'row1')).toBe( false ) expect(selectIsInRangeSelection(state, 'col2', 'row2')).toBe( false ) }) }) describe('selectCellRangeBorders', () => { it('should return 0 for any cell', () => { expect(selectCellRangeBorders(state, 'col1', 'row1')).toBe(0) expect(selectCellRangeBorders(state, 'col2', 'row2')).toBe(0) }) }) describe('selectRangeIds', () => { it('should return empty arrays', () => { const result = selectRangeIds(state) expect(result.rowIds).toEqual([]) expect(result.columnIds).toEqual([]) }) }) }) describe('when range selection exists', () => { const rangeSelection = { from: { columnId: 'col1', rowId: 'row1' }, to: { columnId: 'col3', rowId: 'row3' }, } beforeEach(() => { selectRangeSelection.mockReturnValue(rangeSelection) }) describe('selectIsInRangeSelection', () => { it('should return true for cells within the range', () => { expect(selectIsInRangeSelection(state, 'col1', 'row1')).toBe( true ) expect(selectIsInRangeSelection(state, 'col2', 'row2')).toBe( true ) expect(selectIsInRangeSelection(state, 'col3', 'row3')).toBe( true ) expect(selectIsInRangeSelection(state, 'col1', 'row3')).toBe( true ) expect(selectIsInRangeSelection(state, 'col3', 'row1')).toBe( true ) }) it('should return false for cells outside the range', () => { expect(selectIsInRangeSelection(state, 'col4', 'row1')).toBe( false ) expect(selectIsInRangeSelection(state, 'col1', 'row4')).toBe( false ) expect(selectIsInRangeSelection(state, 'col4', 'row4')).toBe( false ) }) }) describe('selectCellRangeBorders', () => { it('should return 0 for cells outside the range', () => { expect(selectCellRangeBorders(state, 'col4', 'row1')).toBe(0) expect(selectCellRangeBorders(state, 'col1', 'row4')).toBe(0) }) it('should return top-left borders for the top-left corner', () => { const borders = selectCellRangeBorders(state, 'col1', 'row1') expect(borders & BORDERS.TOP).toBeTruthy() expect(borders & BORDERS.LEFT).toBeTruthy() expect(borders & BORDERS.RIGHT).toBeFalsy() expect(borders & BORDERS.BOTTOM).toBeFalsy() }) it('should return top-right borders for the top-right corner', () => { const borders = selectCellRangeBorders(state, 'col3', 'row1') expect(borders & BORDERS.TOP).toBeTruthy() expect(borders & BORDERS.RIGHT).toBeTruthy() expect(borders & BORDERS.LEFT).toBeFalsy() expect(borders & BORDERS.BOTTOM).toBeFalsy() }) it('should return bottom-left borders for the bottom-left corner', () => { const borders = selectCellRangeBorders(state, 'col1', 'row3') expect(borders & BORDERS.BOTTOM).toBeTruthy() expect(borders & BORDERS.LEFT).toBeTruthy() expect(borders & BORDERS.TOP).toBeFalsy() expect(borders & BORDERS.RIGHT).toBeFalsy() }) it('should return bottom-right borders for the bottom-right corner', () => { const borders = selectCellRangeBorders(state, 'col3', 'row3') expect(borders & BORDERS.BOTTOM).toBeTruthy() expect(borders & BORDERS.RIGHT).toBeTruthy() expect(borders & BORDERS.TOP).toBeFalsy() expect(borders & BORDERS.LEFT).toBeFalsy() }) it('should return only top border for top edge cells', () => { const borders = selectCellRangeBorders(state, 'col2', 'row1') expect(borders & BORDERS.TOP).toBeTruthy() expect(borders & BORDERS.LEFT).toBeFalsy() expect(borders & BORDERS.RIGHT).toBeFalsy() expect(borders & BORDERS.BOTTOM).toBeFalsy() }) it('should return only bottom border for bottom edge cells', () => { const borders = selectCellRangeBorders(state, 'col2', 'row3') expect(borders & BORDERS.BOTTOM).toBeTruthy() expect(borders & BORDERS.TOP).toBeFalsy() expect(borders & BORDERS.LEFT).toBeFalsy() expect(borders & BORDERS.RIGHT).toBeFalsy() }) it('should return only left border for left edge cells', () => { const borders = selectCellRangeBorders(state, 'col1', 'row2') expect(borders & BORDERS.LEFT).toBeTruthy() expect(borders & BORDERS.TOP).toBeFalsy() expect(borders & BORDERS.RIGHT).toBeFalsy() expect(borders & BORDERS.BOTTOM).toBeFalsy() }) it('should return only right border for right edge cells', () => { const borders = selectCellRangeBorders(state, 'col3', 'row2') expect(borders & BORDERS.RIGHT).toBeTruthy() expect(borders & BORDERS.TOP).toBeFalsy() expect(borders & BORDERS.LEFT).toBeFalsy() expect(borders & BORDERS.BOTTOM).toBeFalsy() }) it('should return no borders for middle cells', () => { const borders = selectCellRangeBorders(state, 'col2', 'row2') expect(borders).toBe(0) }) it('should return right and left borders if a column span covers the entire selection width', () => { selectColumnSpanByRowId.mockReturnValue( new Map([ [ 'col1', { id: 'col1', positionColumnIds: ['col1', 'col2', 'col3'], }, ], ['col2', { id: 'col2', skip: true }], ['col3', { id: 'col3', skip: true }], ]) ) const borders = selectCellRangeBorders(state, 'col1', 'row2') expect(borders & BORDERS.RIGHT).toBeTruthy() expect(borders & BORDERS.LEFT).toBeTruthy() }) it('should return correct borders if a column span covers part of selection width', () => { selectColumnSpanByRowId.mockReturnValue( new Map([ [ 'col1', { id: 'col1', positionColumnIds: ['col1', 'col2'], }, ], ['col2', { id: 'col2', skip: true }], ]) ) const borders = selectCellRangeBorders(state, 'col1', 'row2') expect(borders & BORDERS.RIGHT).toBeFalsy() expect(borders & BORDERS.LEFT).toBeTruthy() const bordersCol3 = selectCellRangeBorders( state, 'col3', 'row2' ) expect(bordersCol3 & BORDERS.RIGHT).toBeTruthy() expect(bordersCol3 & BORDERS.LEFT).toBeFalsy() }) }) describe('selectRangeIds', () => { it('should return the correct row and column IDs in the range', () => { const result = selectRangeIds(state) expect(result.rowIds).toEqual(['row1', 'row2', 'row3']) expect(result.columnIds).toEqual(['col1', 'col2', 'col3']) }) }) }) describe('when range selection preview exists', () => { const rangeSelectionPreview = { from: { columnId: 'col2', rowId: 'row2' }, to: { columnId: 'col4', rowId: 'row4' }, } beforeEach(() => { selectRangeSelection.mockReturnValue({ from: { columnId: 'col1', rowId: 'row1' }, to: { columnId: 'col3', rowId: 'row3' }, }) selectRangeSelectionPreview.mockReturnValue(rangeSelectionPreview) }) it('should prioritize preview over actual selection', () => { expect(selectIsInRangeSelection(state, 'col2', 'row2')).toBe(true) expect(selectIsInRangeSelection(state, 'col4', 'row4')).toBe(true) expect(selectIsInRangeSelection(state, 'col1', 'row1')).toBe(false) }) it('should use preview for range IDs', () => { const result = selectRangeIds(state) expect(result.rowIds).toEqual(['row2', 'row3', 'row4']) expect(result.columnIds).toEqual(['col2', 'col3', 'col4']) }) }) describe('when selection is in reverse order', () => { beforeEach(() => { selectRangeSelection.mockReturnValue({ from: { columnId: 'col3', rowId: 'row3' }, to: { columnId: 'col1', rowId: 'row1' }, }) }) it('should handle reverse order correctly', () => { expect(selectIsInRangeSelection(state, 'col1', 'row1')).toBe(true) expect(selectIsInRangeSelection(state, 'col2', 'row2')).toBe(true) expect(selectIsInRangeSelection(state, 'col3', 'row3')).toBe(true) const result = selectRangeIds(state) expect(result.rowIds).toEqual(['row1', 'row2', 'row3']) expect(result.columnIds).toEqual(['col1', 'col2', 'col3']) }) it('should return correct borders for reverse selection', () => { const topLeftBorders = selectCellRangeBorders(state, 'col1', 'row1') expect(topLeftBorders & BORDERS.TOP).toBeTruthy() expect(topLeftBorders & BORDERS.LEFT).toBeTruthy() const bottomRightBorders = selectCellRangeBorders( state, 'col3', 'row3' ) expect(bottomRightBorders & BORDERS.BOTTOM).toBeTruthy() expect(bottomRightBorders & BORDERS.RIGHT).toBeTruthy() }) }) describe('when dealing with hidden columns', () => { beforeEach(() => { selectColumnIdsWithHidden.mockReturnValue([ 'col1', 'col2', 'col3', 'col4', 'col5', ]) selectHiddenIds.mockReturnValue(['col2']) selectRangeSelection.mockReturnValue({ from: { columnId: 'col1', rowId: 'row1' }, to: { columnId: 'col4', rowId: 'row3' }, }) }) it('should exclude hidden columns from the selection', () => { expect(selectIsInRangeSelection(state, 'col1', 'row1')).toBe(true) expect(selectIsInRangeSelection(state, 'col2', 'row1')).toBe(false) // hidden expect(selectIsInRangeSelection(state, 'col3', 'row1')).toBe(true) expect(selectIsInRangeSelection(state, 'col4', 'row1')).toBe(true) const result = selectRangeIds(state) expect(result.columnIds).toEqual(['col1', 'col3', 'col4']) }) }) describe('when selection is a single cell', () => { beforeEach(() => { selectRangeSelection.mockReturnValue({ from: { columnId: 'col2', rowId: 'row2' }, to: { columnId: 'col2', rowId: 'row2' }, }) }) it('should return true for the selected cell', () => { expect(selectIsInRangeSelection(state, 'col2', 'row2')).toBe(true) }) it('should return 0 borders for single cell selection', () => { const borders = selectCellRangeBorders(state, 'col2', 'row2') expect(borders).toBe(0) }) it('should return the single cell in range IDs', () => { const result = selectRangeIds(state) expect(result.rowIds).toEqual(['row2']) expect(result.columnIds).toEqual(['col2']) }) }) describe('when column or row is not found in the lists', () => { beforeEach(() => { selectRangeSelection.mockReturnValue({ from: { columnId: 'nonexistent-col', rowId: 'nonexistent-row' }, to: { columnId: 'col2', rowId: 'row2' }, }) }) it('should handle missing column IDs gracefully', () => { expect(selectIsInRangeSelection(state, 'col1', 'row1')).toBe(false) expect(selectIsInRangeSelection(state, 'col2', 'row2')).toBe(false) }) it('should return empty arrays when columns/rows are not found', () => { const result = selectRangeIds(state) expect(result.rowIds).toEqual([]) expect(result.columnIds).toEqual([]) }) }) })