import { stateReducer, SelectionMode, EmptySelectionAction, HoverState, } from './HudCanvasState'; const initialState = { width: 5000, emptySelectionAction: EmptySelectionAction.SelectNothing, hoverX: 0, selection: { start: 0, end: 0 }, origSelection: { start: 0, end: 0 }, mousedownX: 0, mode: SelectionMode.Normal, prevMode: SelectionMode.Normal, cursorClass: 'cursor-auto', hoverState: HoverState.Normal, shouldPublish: false, }; describe('stateReducer', () => { describe('setselection', () => { it('sets the selection', () => { const state = stateReducer( { ...initialState }, { type: 'setselection', x: 0, selection: { start: 100, end: 200 } } ); expect(state.selection).toEqual({ start: 100, end: 200 }); expect(state.shouldPublish).toBeFalsy(); }); }); describe.each([ { name: 'entering resizing start', x: 995, selection: { start: 1000, end: 2000 }, wantMode: SelectionMode.ResizingStart, wantSelection: { start: 1000, end: 2000 }, }, { name: 'entering resizing end', x: 2003, selection: { start: 1000, end: 2000 }, wantMode: SelectionMode.ResizingEnd, wantSelection: { start: 1000, end: 2000 }, }, { name: 'entering dragging', x: 1500, selection: { start: 1000, end: 2000 }, wantMode: SelectionMode.Dragging, wantSelection: { start: 1000, end: 2000 }, }, { name: 'entering selecting', x: 10, selection: { start: 1000, end: 2000 }, wantMode: SelectionMode.Selecting, wantSelection: { start: 10, end: 10 }, }, ])('mousedown', ({ name, x, selection, wantMode, wantSelection }) => { test(`${name} generates the expected state`, () => { const state = stateReducer( { ...initialState, selection: selection }, { type: 'mousedown', x: x } ); expect(state.mode).toEqual(wantMode); expect(state.selection).toEqual(wantSelection); expect(state.mousedownX).toEqual(x); expect(state.shouldPublish).toBeTruthy(); }); }); describe.each([ { name: 're-entering normal mode', x: 1200, selection: { start: 1000, end: 2000 }, emptySelectionAction: EmptySelectionAction.SelectNothing, wantSelection: { start: 1000, end: 2000 }, }, { name: 'when nothing is selected and emptySelectionAction is SelectNothing', x: 1200, selection: { start: 1000, end: 1000 }, emptySelectionAction: EmptySelectionAction.SelectNothing, wantSelection: { start: 1200, end: 1200 }, }, { // TODO: broken name: 'when nothing is selected and emptySelectionAction is SelectPrevious', x: 1200, selection: { start: 1000, end: 2000 }, emptySelectionAction: EmptySelectionAction.SelectPrevious, wantSelection: { start: 1000, end: 2000 }, }, ])( 'mouseup', ({ name, x, selection, emptySelectionAction, wantSelection }) => { test(`${name} generates the expected state`, () => { const state = stateReducer( { ...initialState, selection: selection, mode: SelectionMode.Selecting, emptySelectionAction: emptySelectionAction, }, { type: 'mouseup', x: x } ); expect(state.mode).toEqual(SelectionMode.Normal); expect(state.prevMode).toEqual(SelectionMode.Selecting); expect(state.selection).toEqual(wantSelection); expect(state.shouldPublish).toBeTruthy(); }); } ); describe('mouseleave', () => { it('sets the state', () => { const state = stateReducer( { ...initialState, selection: { start: 2000, end: 3000 }, mode: SelectionMode.Dragging, mousedownX: 475, }, { type: 'mouseleave', x: 500 } ); expect(state.mode).toEqual(SelectionMode.Dragging); expect(state.selection).toEqual({ start: 2000, end: 3000 }); expect(state.mousedownX).toEqual(475); expect(state.shouldPublish).toBeFalsy(); }); }); describe('mousemove', () => { describe.each([ // Normal mode { name: 'hovering over selection start', mode: SelectionMode.Normal, x: 997, selection: { start: 1000, end: 3000 }, wantHoverState: HoverState.OverSelectionStart, shouldPublish: false, }, { name: 'hovering over selection end', mode: SelectionMode.Normal, x: 3009, selection: { start: 1000, end: 3000 }, wantHoverState: HoverState.OverSelectionEnd, shouldPublish: false, }, { name: 'hovering over selection', mode: SelectionMode.Normal, x: 1200, selection: { start: 1000, end: 3000 }, wantHoverState: HoverState.OverSelection, shouldPublish: false, }, { name: 'hovering elsewhere', mode: SelectionMode.Normal, x: 300, selection: { start: 1000, end: 3000 }, wantHoverState: HoverState.Normal, shouldPublish: false, }, // Selecting mode { name: 'when not crossing over', mode: SelectionMode.Selecting, x: 3005, mousedownX: 2000, selection: { start: 2000, end: 3000 }, wantSelection: { start: 2000, end: 3005 }, shouldPublish: true, }, { name: 'when crossing over', mode: SelectionMode.Selecting, x: 1995, mousedownX: 2000, selection: { start: 2000, end: 2002 }, wantSelection: { start: 1995, end: 2000 }, shouldPublish: true, }, // Dragging mode { name: 'in the middle of the canvas', mode: SelectionMode.Dragging, x: 1220, mousedownX: 1200, selection: { start: 1000, end: 1500 }, origSelection: { start: 1000, end: 1500 }, wantSelection: { start: 1020, end: 1520 }, shouldPublish: true, }, { name: 'at the start of the canvas', mode: SelectionMode.Dragging, x: 30, mousedownX: 50, selection: { start: 10, end: 210 }, origSelection: { start: 10, end: 210 }, wantSelection: { start: 0, end: 200 }, shouldPublish: true, }, { name: 'at the end of the canvas', mode: SelectionMode.Dragging, x: 1400, mousedownX: 1250, selection: { start: 4800, end: 4900 }, origSelection: { start: 4800, end: 4900 }, wantSelection: { start: 4900, end: 5000 }, shouldPublish: true, }, // ResizingStart mode { name: 'when not crossing over', mode: SelectionMode.ResizingStart, x: 2020, selection: { start: 2000, end: 3000 }, origSelection: { start: 2000, end: 3000 }, wantSelection: { start: 2020, end: 3000 }, shouldPublish: true, }, { name: 'when crossing over', mode: SelectionMode.ResizingStart, x: 2010, selection: { start: 2000, end: 2002 }, origSelection: { start: 2000, end: 2002 }, wantSelection: { start: 2002, end: 2010 }, shouldPublish: true, }, // ResizingEnd mode { name: 'when not crossing over', mode: SelectionMode.ResizingEnd, x: 2007, selection: { start: 1000, end: 2000 }, origSelection: { start: 1000, end: 2000 }, wantSelection: { start: 1000, end: 2007 }, shouldPublish: true, }, { name: 'when crossing over', mode: SelectionMode.ResizingEnd, x: 1995, selection: { start: 2000, end: 2002 }, origSelection: { start: 2000, end: 2002 }, wantSelection: { start: 1995, end: 2000 }, shouldPublish: true, }, ])( 'mousemove', ({ name, mode, x, mousedownX = 0, selection, origSelection = { start: 0, end: 0 }, wantSelection = selection, wantHoverState = HoverState.Normal, shouldPublish, }) => { test(`${SelectionMode[mode]} mode: ${name} generates the expected state`, () => { const state = stateReducer( { ...initialState, selection: selection, origSelection: origSelection, mode: mode, mousedownX: mousedownX, }, { type: 'mousemove', x: x } ); expect(state.mode).toEqual(mode); expect(state.selection).toEqual(wantSelection); expect(state.hoverState).toEqual(wantHoverState); expect(state.shouldPublish).toEqual(shouldPublish); }); } ); }); });