import { ACTIONS_COLUMN_ID, SELECTION_COLUMN_ID } from '../../constants' import type { GridRangeSelection } from '../../types' import type { GridRangeSelectionState } from './range-selection' import reducerConfig, { selectRangeSelection, selectRangeSelectionPreview, selectIsSpreadsheet, selectIsRangeSelectionControlled, } from './range-selection' const { reducer: rangeSelectionReducer } = reducerConfig const getStateMock = ( state: Partial = {} ): GridRangeSelectionState => ({ ...reducerConfig.initialState, ...state, }) const mockRangeSelection: GridRangeSelection = { from: { columnId: 'col1', rowId: 'row1' }, to: { columnId: 'col2', rowId: 'row2' }, } describe('rangeSelectionReducer', () => { describe('unknown action', () => { it('should not modify the state', () => { const state = getStateMock() const newState = rangeSelectionReducer(state, { type: 'nope', } as any) expect(state).toBe(newState) }) }) describe('applyProps', () => { it('should enable range selection when spreadsheet is true', () => { const state = rangeSelectionReducer(getStateMock(), { type: 'applyProps', payload: { columns: [], rows: [], spreadsheet: true, }, }) expect(selectIsSpreadsheet(state)).toBe(true) }) it('should disable range selection when spreadsheet is false', () => { const state = rangeSelectionReducer(getStateMock(), { type: 'applyProps', payload: { columns: [], rows: [], spreadsheet: false, }, }) expect(selectIsSpreadsheet(state)).toBe(false) }) it('should mark as controlled when rangeSelection is provided', () => { const state = rangeSelectionReducer(getStateMock(), { type: 'applyProps', payload: { columns: [], rows: [], rangeSelection: mockRangeSelection, }, }) expect(selectIsRangeSelectionControlled(state)).toBe(true) expect(selectRangeSelection(state)).toEqual(mockRangeSelection) }) it('should mark as controlled when rangeSelection is null', () => { const state = rangeSelectionReducer(getStateMock(), { type: 'applyProps', payload: { columns: [], rows: [], rangeSelection: null, }, }) expect(selectIsRangeSelectionControlled(state)).toBe(true) expect(selectRangeSelection(state)).toBe(null) }) it('should mark as not controlled when rangeSelection is undefined (and should not clear existing rangeSelection)', () => { const state = rangeSelectionReducer( getStateMock({ rangeSelection: mockRangeSelection, }), { type: 'applyProps', payload: { columns: [], rows: [], }, } ) expect(selectIsRangeSelectionControlled(state)).toBe(false) expect(selectRangeSelection(state)).toBe(mockRangeSelection) }) it('should handle multiple props at once', () => { const state = rangeSelectionReducer(getStateMock(), { type: 'applyProps', payload: { columns: [], rows: [], spreadsheet: true, rangeSelection: mockRangeSelection, }, }) expect(selectIsSpreadsheet(state)).toBe(true) expect(selectIsRangeSelectionControlled(state)).toBe(true) expect(selectRangeSelection(state)).toEqual(mockRangeSelection) }) }) describe('updateRangeSelection', () => { it('should update range selection with new value', () => { const initialState = getStateMock({ rangeSelection: null }) const state = rangeSelectionReducer(initialState, { type: 'updateRangeSelection', payload: mockRangeSelection, }) expect(selectRangeSelection(state)).toEqual(mockRangeSelection) }) it('should clear range selection when payload is null', () => { const initialState = getStateMock({ rangeSelection: mockRangeSelection, }) const state = rangeSelectionReducer(initialState, { type: 'updateRangeSelection', payload: null, }) expect(selectRangeSelection(state)).toBe(null) }) it('should preserve other state properties', () => { const initialState = getStateMock({ enabled: true, controlled: true, rangeSelectionPreview: mockRangeSelection, }) const state = rangeSelectionReducer(initialState, { type: 'updateRangeSelection', payload: null, }) expect(selectIsSpreadsheet(state)).toBe(true) expect(selectIsRangeSelectionControlled(state)).toBe(true) expect(selectRangeSelectionPreview(state)).toEqual( mockRangeSelection ) }) }) describe('updateRangeSelectionPreview', () => { it('should update range selection preview with new value', () => { const initialState = getStateMock({ rangeSelectionPreview: null }) const state = rangeSelectionReducer(initialState, { type: 'updateRangeSelectionPreview', payload: mockRangeSelection, }) expect(selectRangeSelectionPreview(state)).toEqual( mockRangeSelection ) }) it('should clear range selection preview when payload is null', () => { const initialState = getStateMock({ rangeSelectionPreview: mockRangeSelection, }) const state = rangeSelectionReducer(initialState, { type: 'updateRangeSelectionPreview', payload: null, }) expect(selectRangeSelectionPreview(state)).toBe(null) }) it('should preserve other state properties', () => { const initialState = getStateMock({ enabled: true, controlled: true, rangeSelection: mockRangeSelection, }) const state = rangeSelectionReducer(initialState, { type: 'updateRangeSelectionPreview', payload: null, }) expect(selectIsSpreadsheet(state)).toBe(true) expect(selectIsRangeSelectionControlled(state)).toBe(true) expect(selectRangeSelection(state)).toEqual(mockRangeSelection) }) }) describe('updateFocus', () => { describe('when range selection is disabled', () => { it('should return the same state', () => { const initialState = getStateMock({ enabled: false }) const state = rangeSelectionReducer(initialState, { type: 'updateFocus', payload: { area: 'body', columnId: 'col1', rowId: 'row1', }, }) expect(state).toBe(initialState) }) }) describe('when range selection is enabled', () => { it('should clear range selection when focus area is not body', () => { const initialState = getStateMock({ enabled: true, rangeSelection: mockRangeSelection, }) const state = rangeSelectionReducer(initialState, { type: 'updateFocus', payload: { area: 'header', columnId: 'col1', rowId: 'row1', }, }) expect(selectRangeSelection(state)).toBe(null) }) it('should clear range selection when columnId is SELECTION_COLUMN_ID', () => { const initialState = getStateMock({ enabled: true, rangeSelection: mockRangeSelection, }) const state = rangeSelectionReducer(initialState, { type: 'updateFocus', payload: { area: 'body', columnId: SELECTION_COLUMN_ID, rowId: 'row1', }, }) expect(selectRangeSelection(state)).toBe(null) }) it('should clear range selection when columnId is ACTIONS_COLUMN_ID', () => { const initialState = getStateMock({ enabled: true, rangeSelection: mockRangeSelection, }) const state = rangeSelectionReducer(initialState, { type: 'updateFocus', payload: { area: 'body', columnId: ACTIONS_COLUMN_ID, rowId: 'row1', }, }) expect(selectRangeSelection(state)).toBe(null) }) it('should create single-cell range selection for valid body focus', () => { const initialState = getStateMock({ enabled: true }) const state = rangeSelectionReducer(initialState, { type: 'updateFocus', payload: { area: 'body', columnId: 'col1', rowId: 'row1', }, }) expect(selectRangeSelection(state)).toEqual({ from: { columnId: 'col1', rowId: 'row1' }, to: { columnId: 'col1', rowId: 'row1' }, }) }) it('should preserve other state properties when creating range selection', () => { const initialState = getStateMock({ enabled: true, controlled: true, rangeSelectionPreview: mockRangeSelection, }) const state = rangeSelectionReducer(initialState, { type: 'updateFocus', payload: { area: 'body', columnId: 'col1', rowId: 'row1', }, }) expect(selectIsSpreadsheet(state)).toBe(true) expect(selectIsRangeSelectionControlled(state)).toBe(true) expect(selectRangeSelectionPreview(state)).toEqual( mockRangeSelection ) }) }) }) }) describe('selectors', () => { describe('selectRangeSelection', () => { it('should return range selection when present', () => { const state = getStateMock({ rangeSelection: mockRangeSelection }) expect(selectRangeSelection(state)).toEqual(mockRangeSelection) }) it('should return null when range selection is null', () => { const state = getStateMock({ rangeSelection: null }) expect(selectRangeSelection(state)).toBe(null) }) }) describe('selectRangeSelectionPreview', () => { it('should return range selection preview when present', () => { const state = getStateMock({ rangeSelectionPreview: mockRangeSelection, }) expect(selectRangeSelectionPreview(state)).toEqual( mockRangeSelection ) }) it('should return null when range selection preview is null', () => { const state = getStateMock({ rangeSelectionPreview: null }) expect(selectRangeSelectionPreview(state)).toBe(null) }) }) describe('selectIsSpreadsheet', () => { it('should return true when range selection is enabled', () => { const state = getStateMock({ enabled: true }) expect(selectIsSpreadsheet(state)).toBe(true) }) it('should return false when range selection is disabled', () => { const state = getStateMock({ enabled: false }) expect(selectIsSpreadsheet(state)).toBe(false) }) }) describe('selectIsRangeSelectionControlled', () => { it('should return true when range selection is controlled', () => { const state = getStateMock({ controlled: true }) expect(selectIsRangeSelectionControlled(state)).toBe(true) }) it('should return false when range selection is not controlled', () => { const state = getStateMock({ controlled: false }) expect(selectIsRangeSelectionControlled(state)).toBe(false) }) }) })