UNPKG

bucket-duck

Version:

A redux module containing a reducer and actions for a bucket widget.

309 lines (296 loc) 12.3 kB
import {expect} from 'chai' import {State, StatePartial} from '../src/types' import reducer from '../src/reducer' import * as actions from '../src/actions' import { stateFactory, DummyType, stateDefaults, generateDummyItems } from './test-helpers' import * as _ from 'lodash' declare const describe:(desc:string, it:(desc:string, done?:() => void) => void) => void declare const it:(desc:string, done?:() => void) => void declare const beforeEach:(cb:() => void) => void const createState = stateFactory<DummyType>(stateDefaults) describe('Double click action', function () { it('moves a non-selected item to the list of selected items', function () { const initialState = createState({ selectedItems: generateDummyItems(1, 1), nonSelectedItems: generateDummyItems(2, 1) }) expect(reducer(initialState, actions.doubleClickItem(false, 0))).to.be.eql(createState({ nonSelectedItems: [], selectedItems:[ {title:'Item 1' , subtitle: '', id:'item1'}, {title:'Item 2' , subtitle: '', id:'item2'} ] })) }) it('moves a selected item to the list of non-selected items', function () { const initialState = createState({ selectedItems: generateDummyItems(1, 1), nonSelectedItems: generateDummyItems(2, 1) }) expect(reducer(initialState, actions.doubleClickItem(true, 0))).to.be.eql(createState({ nonSelectedItems: [ {title:'Item 2' , subtitle: '', id:'item2'}, {title:'Item 1' , subtitle: '', id:'item1'} ], selectedItems:[] })) }) }) describe('Click action', function () { it('sets a hovered item in the non-selected item list', function () { const index = 2 const initialState = createState({ nonSelectedItems: generateDummyItems(1, 3) }) const expectedHoveredItem = {index, isSelected: false} const state = reducer(initialState, actions.clickItem(index, false)) expect(state.hoveredItem).to.be.eql(expectedHoveredItem) }) it('works on the selected item list as well', function () { const index = 2 const initialState = createState({ selectedItems: generateDummyItems(1, 3) }) const expectedHoveredItem = {index, isSelected: true} const state = reducer(initialState, actions.clickItem(index, true)) expect(state.hoveredItem).to.be.eql(expectedHoveredItem) }) }) describe('Hover next action', function () { describe('selects the next item in', function () { let initialState:State<DummyType> let items:DummyType[] beforeEach(function () { items = generateDummyItems(1, 3) initialState = createState({ hoveredItem: {index: 1, isSelected: true} }) }) it('the non-selected list', function () { initialState.nonSelectedItems = items if (initialState.hoveredItem !== null) { initialState.hoveredItem.isSelected = false } const state = reducer(initialState, actions.hoverNextItem()) expect(state.hoveredItem).to.eql({index: 2, isSelected: false}) }) it('the selected list', function () { initialState.selectedItems = items const state = reducer(initialState, actions.hoverNextItem()) expect(state.hoveredItem).to.eql({index: 2, isSelected: true}) }) }) it('does not select past the end of the list', function () { const items = generateDummyItems(1, 3) const initialState = createState({ hoveredItem: {index: 2, isSelected: true}, selectedItems: items }) const state = reducer(initialState, actions.hoverNextItem()) expect(state.hoveredItem).to.eql({index: 2, isSelected: true}) }) }) describe('Hover previous action', function () { describe('selects the previous item in', function () { let initialState:State<DummyType> let items:DummyType[] beforeEach(function () { items = generateDummyItems(1, 3) initialState = createState({ hoveredItem: {index: 2, isSelected: true} }) }) it('the non-selected list', function () { initialState.nonSelectedItems = items if (initialState.hoveredItem !== null) { initialState.hoveredItem.isSelected = false } const state = reducer(initialState, actions.hoverPrevItem()) expect(state.hoveredItem).to.eql({index: 1, isSelected: false}) }) it('the selected list', function () { initialState.selectedItems = items const state = reducer(initialState, actions.hoverPrevItem()) expect(state.hoveredItem).to.eql({index: 1, isSelected: true}) }) }) it('does not select past the beginning of the list', function () { const items = generateDummyItems(1, 3) const initialState = createState({ hoveredItem: {index: 0, isSelected: true}, selectedItems: items }) const state = reducer(initialState, actions.hoverPrevItem()) expect(state.hoveredItem).to.eql({index: 0, isSelected: true}) }) }) describe('Clear hover action', function () { it('sets the hovered item to null', function () { const initialState = createState({ hoveredItem: {index: 0, isSelected: true}, selectedItems: generateDummyItems(1, 3) }) const state = reducer(initialState, actions.clearHover()) expect(state.hoveredItem).to.be.null }) }) describe('Select item action', function () { it('moves the item at specified index selected items list', function () { const items = generateDummyItems(1, 3) const initialState = createState({ hoveredItem: {index: 0, isSelected: false}, nonSelectedItems: items }) const state = reducer(initialState, actions.selectItem(1)) const expectedSelected = [items[1]] const expectedNotSelected = [items[0], items[2]] expect(state.selectedItems).to.be.eql(expectedSelected) expect(state.nonSelectedItems).to.be.eql(expectedNotSelected) }) }) describe('Deselect item action', function () { it('moves the hovered item from the selected item list to the non-selected items list', function () { const items = generateDummyItems(1, 3) const initialState = createState({ selectedItems: items }) const state = reducer(initialState, actions.deselectItem(1)) const expectedNotSelected = [items[1]] const expectedSelected = [items[0], items[2]] expect(state.selectedItems).to.be.eql(expectedSelected) expect(state.nonSelectedItems).to.be.eql(expectedNotSelected) }) }) describe('Select hover action', function () { it('selects the hovered item if it is not selected', function () { const items = generateDummyItems(1, 3) const initialState = createState({ hoveredItem: {index: 1, isSelected: false}, nonSelectedItems: _.clone(items) }) const state = reducer(initialState, actions.selectHover()) const expectedSelected = [items[1]] const expectedNotSelected = [items[0], items[2]] expect(state.selectedItems).to.be.eql(expectedSelected) expect(state.nonSelectedItems).to.be.eql(expectedNotSelected) }) it('deselects the hovered item if it is selected', function () { const items = generateDummyItems(1, 3) const initialState = createState({ hoveredItem: {index: 1, isSelected: true}, selectedItems: _.clone(items) }) const state = reducer(initialState, actions.selectHover()) const expectedNotSelected = [items[1]] const expectedSelected = [items[0], items[2]] expect(state.selectedItems).to.be.eql(expectedSelected) expect(state.nonSelectedItems).to.be.eql(expectedNotSelected) }) it('clears the hovered item', function () { const items = generateDummyItems(1, 3) const initialState = createState({ hoveredItem: {index: 1, isSelected: true}, selectedItems: _.clone(items) }) const state = reducer(initialState, actions.selectHover()) const expectedNotSelected = [items[1]] const expectedSelected = [items[0], items[2]] expect(state.hoveredItem).to.be.null }) it('does nothing if no item is hovered', function () { const items = generateDummyItems(1, 3) const initialState = createState({ selectedItems: items }) const state = reducer(initialState, actions.selectHover()) const expectedNotSelected = [items[1]] const expectedSelected = [items[0], items[2]] expect(state).to.be.eql(initialState) }) }) describe('received state action', function () { interface OtherDummy extends DummyType { 'not-label'?:string 'not-subtitle'?:string 'not-id'?:string } let initialState:State<DummyType> beforeEach(function () { initialState = createState({ nonSelectedItems: generateDummyItems(1, 3) }) }) it('updates selected state properties', function () { const newStateProps:StatePartial<OtherDummy> = { hoveredItem: {index: 0, isSelected: false}, nonSelectedItems: generateDummyItems(3, 3), selectedItems: generateDummyItems(1, 2), titleAttr: 'not-label', subtitleAttr: 'not-subtitle', valueAttr: 'not-id', selectedChanged: true } const state = reducer(initialState, actions.receivedState(newStateProps)) expect(state.hoveredItem).to.be.eql(newStateProps.hoveredItem) expect(state.nonSelectedItems).to.be.eql(newStateProps.nonSelectedItems) expect(state.selectedItems).to.be.eql(newStateProps.selectedItems) expect(state.titleAttr).to.be.eql(newStateProps.titleAttr) expect(state.subtitleAttr).to.be.eql(newStateProps.subtitleAttr) expect(state.valueAttr).to.be.eql(newStateProps.valueAttr) }) it('does not indicate change in selected items', function () { const newStateProps:StatePartial<OtherDummy> = { hoveredItem: {index: 0, isSelected: false}, nonSelectedItems: generateDummyItems(3, 3), selectedItems: generateDummyItems(1, 2), titleAttr: 'not-label', subtitleAttr: 'not-subtitle', valueAttr: 'not-id' } const state = reducer(initialState, actions.receivedState(newStateProps)) expect(state.selectedChanged).to.be.equal(false) }) it('unsets the hovered item if the one provided is out of range', function () { const newStateProps:StatePartial<OtherDummy> = { hoveredItem: {index: 10, isSelected: false} } const state = reducer(initialState, actions.receivedState(newStateProps)) expect(state.hoveredItem).to.be.equal(null) }) }) describe('reorder items action', function () { let initialState let selectedItems let newOrder:DummyType[] let movedItem let state:State<DummyType> beforeEach(function () { selectedItems = generateDummyItems(1, 4) initialState = createState({ selectedItems }) // reorder 3rd and 2nd items newOrder = [ selectedItems[0], selectedItems[2], selectedItems[1], selectedItems[3] ] movedItem = selectedItems[2] state = reducer(initialState, actions.reorderItems(newOrder, movedItem)) }) it('reorders the selected items', function () { expect(state.selectedItems).to.be.eql(newOrder) }) it('sets the hovered item to the dragged item', function () { expect(state.hoveredItem).to.be.eql({ index: 1, isSelected: true }) }) })