patch tests for react-bootstrap-table-next

This commit is contained in:
AllenFang 2018-05-28 18:05:33 +08:00
parent 74bf885d47
commit fc0b99e8a0
18 changed files with 1472 additions and 946 deletions

View File

@ -11,7 +11,7 @@
"pretest": "yarn lint --cache",
"test": "jest",
"test:coverage": "jest --coverage",
"test:watch": "jest --watch",
"test:watch": "jest --coverage --watch",
"storybook": "cd ./packages/react-bootstrap-table2-example && yarn storybook",
"gh-pages:clean": "cd ./packages/react-bootstrap-table2-example && yarn gh-pages:clean",
"gh-pages:build": "cd ./packages/react-bootstrap-table2-example && yarn gh-pages:build",
@ -86,7 +86,7 @@
},
"jest": {
"collectCoverageFrom": [
"packages/*/src/*.js",
"packages/*/src/**/*.js",
"packages/*/index.js"
],
"roots": [

View File

@ -0,0 +1,430 @@
import 'jsdom-global/register';
import React from 'react';
import { shallow } from 'enzyme';
import _ from 'react-bootstrap-table-next/src/utils';
import dataOperator from 'react-bootstrap-table-next/src/store/operators';
import BootstrapTable from 'react-bootstrap-table-next/src/bootstrap-table';
import {
CLICK_TO_CELL_EDIT,
DBCLICK_TO_CELL_EDIT,
DELAY_FOR_DBCLICK
} from '../src/const';
import createCellEditContext from '../src/context';
import cellEditFactory from '../index';
describe('CellEditContext', () => {
let wrapper;
let cellEdit;
let CellEditContext;
const data = [{
id: 1,
name: 'A'
}, {
id: 2,
name: 'B'
}];
const keyField = 'id';
const columns = [{
dataField: 'id',
text: 'ID'
}, {
dataField: 'name',
text: 'Name'
}];
const defaultCellEdit = {
mode: CLICK_TO_CELL_EDIT
};
const defaultSelectRow = undefined;
const mockBase = jest.fn((props => (
<BootstrapTable
data={ data }
columns={ columns }
keyField={ keyField }
{ ...props }
/>
)));
const handleCellChange = jest.fn();
function shallowContext(
customCellEdit = defaultCellEdit,
enableRemote = false,
selectRow = defaultSelectRow
) {
mockBase.mockReset();
handleCellChange.mockReset();
CellEditContext = createCellEditContext(
_,
dataOperator,
jest.fn().mockReturnValue(enableRemote),
handleCellChange
);
cellEdit = cellEditFactory(customCellEdit);
return (
<CellEditContext.Provider
cellEdit={ cellEdit }
keyField={ keyField }
columns={ columns }
selectRow={ selectRow }
data={ data }
>
<CellEditContext.Consumer>
{
cellEditProps => mockBase(cellEditProps)
}
</CellEditContext.Consumer>
</CellEditContext.Provider>
);
}
describe('default render', () => {
beforeEach(() => {
wrapper = shallow(shallowContext());
wrapper.render();
});
it('should have correct Provider property after calling createCellEditContext', () => {
expect(CellEditContext.Provider).toBeDefined();
});
it('should have correct Consumer property after calling createCellEditContext', () => {
expect(CellEditContext.Consumer).toBeDefined();
});
it('should have correct state.ridx', () => {
expect(wrapper.state().ridx).toBeNull();
});
it('should have correct state.cidx', () => {
expect(wrapper.state().cidx).toBeNull();
});
it('should have correct state.message', () => {
expect(wrapper.state().message).toBeNull();
});
it('should pass correct cell editing props to children element', () => {
expect(wrapper.length).toBe(1);
expect(JSON.stringify(mockBase.mock.calls[0])).toEqual(JSON.stringify([{
cellEdit: {
...defaultCellEdit,
CLICK_TO_CELL_EDIT,
DBCLICK_TO_CELL_EDIT,
DELAY_FOR_DBCLICK,
...wrapper.state(),
nonEditableRows: []
}
}]));
});
});
describe('componentWillReceiveProps', () => {
const initialState = { ridx: 1, cidx: 1, message: 'test' };
describe('if nextProps.cellEdit is not existing', () => {
beforeEach(() => {
wrapper = shallow(shallowContext());
wrapper.setState(initialState);
wrapper.render();
wrapper.instance().componentWillReceiveProps({});
});
it('should not set state.message', () => {
expect(wrapper.state().message).toBe(initialState.message);
});
it('should not set state.ridx', () => {
expect(wrapper.state().ridx).toBe(initialState.ridx);
});
it('should not set state.cidx', () => {
expect(wrapper.state().cidx).toBe(initialState.cidx);
});
});
describe('if nextProps.cellEdit is existing but remote cell editing is disable', () => {
beforeEach(() => {
wrapper = shallow(shallowContext());
wrapper.setState(initialState);
wrapper.render();
wrapper.instance().componentWillReceiveProps({
cellEdit: cellEditFactory(defaultCellEdit)
});
});
it('should not set state.message', () => {
expect(wrapper.state().message).toBe(initialState.message);
});
it('should not set state.ridx', () => {
expect(wrapper.state().ridx).toBe(initialState.ridx);
});
it('should not set state.cidx', () => {
expect(wrapper.state().cidx).toBe(initialState.cidx);
});
});
describe('if nextProps.cellEdit is existing and remote cell editing is enable', () => {
describe('if nextProps.cellEdit.options.errorMessage is defined', () => {
let message;
beforeEach(() => {
message = 'validation fail';
wrapper = shallow(shallowContext(defaultCellEdit, true));
wrapper.setState(initialState);
wrapper.render();
wrapper.instance().componentWillReceiveProps({
cellEdit: cellEditFactory({
...defaultCellEdit,
errorMessage: message
})
});
wrapper.update();
});
it('should set state.message', () => {
expect(wrapper.state('message')).toBe(message);
});
it('should not set state.ridx', () => {
expect(wrapper.state().ridx).toBe(initialState.ridx);
});
it('should not set state.cidx', () => {
expect(wrapper.state().cidx).toBe(initialState.cidx);
});
});
describe('if nextProps.cellEdit.options.errorMessage is not defined', () => {
beforeEach(() => {
wrapper = shallow(shallowContext(defaultCellEdit, true));
wrapper.setState(initialState);
wrapper.instance().componentWillReceiveProps({
cellEdit: cellEditFactory({ ...defaultCellEdit })
});
wrapper.update();
});
it('should not set state.message', () => {
expect(wrapper.state('message')).toBe(initialState.message);
});
it('should set correct state.ridx', () => {
expect(wrapper.state().ridx).toBeNull();
});
it('should set correct state.cidx', () => {
expect(wrapper.state().cidx).toBeNull();
});
});
});
});
describe('handleCellUpdate', () => {
const row = data[1];
const column = columns[1];
const newValue = 'This is new value';
const oldValue = row[column.dataField];
describe('if cellEdit.beforeSaveCell prop is defined', () => {
const beforeSaveCell = jest.fn();
beforeEach(() => {
beforeSaveCell.mockReset();
wrapper = shallow(shallowContext({
...defaultCellEdit,
beforeSaveCell
}));
wrapper.instance().handleCellUpdate(
row,
column,
newValue
);
});
it('should call cellEdit.beforeSaveCell correctly', () => {
expect(beforeSaveCell).toHaveBeenCalledTimes(1);
expect(beforeSaveCell).toHaveBeenCalledWith(oldValue, newValue, row, column);
});
});
describe('when remote cell editing is enable', () => {
const afterSaveCell = jest.fn();
beforeEach(() => {
afterSaveCell.mockReset();
wrapper = shallow(shallowContext({
...defaultCellEdit,
afterSaveCell
}, true));
wrapper.instance().handleCellUpdate(
row,
column,
newValue
);
});
it('should call handleCellChange correctly', () => {
expect(handleCellChange).toHaveBeenCalledTimes(1);
expect(handleCellChange).toHaveBeenCalledWith(row[keyField], column.dataField, newValue);
});
it('should not call cellEdit.afterSaveCell even if it is defined', () => {
expect(afterSaveCell).toHaveBeenCalledTimes(0);
});
});
describe('when remote cell editing is disable', () => {
const afterSaveCell = jest.fn();
beforeEach(() => {
afterSaveCell.mockReset();
wrapper = shallow(shallowContext({
...defaultCellEdit,
afterSaveCell
}));
wrapper.setState({
ridx: 1,
cidx: 1
});
wrapper.instance().handleCellUpdate(
row,
column,
newValue
);
});
it('should not call handleCellChange correctly', () => {
expect(handleCellChange).toHaveBeenCalledTimes(0);
});
it('should set state correctly', () => {
expect(wrapper.state('ridx')).toBeNull();
expect(wrapper.state('cidx')).toBeNull();
expect(wrapper.state('message')).toBeNull();
});
it('should call cellEdit.afterSaveCell if it is defined', () => {
expect(afterSaveCell).toHaveBeenCalledTimes(1);
});
});
});
describe('completeEditing', () => {
const initialState = { ridx: 1, cidx: 1, message: 'test' };
beforeEach(() => {
wrapper = shallow(shallowContext());
wrapper.setState(initialState);
wrapper.render();
wrapper.instance().completeEditing();
});
it('should set state correctly', () => {
expect(wrapper.state().ridx).toBeNull();
expect(wrapper.state().cidx).toBeNull();
expect(wrapper.state().message).toBeNull();
});
});
describe('startEditing', () => {
const ridx = 0;
const cidx = 1;
describe('if selectRow prop is not defined', () => {
beforeEach(() => {
wrapper = shallow(shallowContext());
wrapper.render();
wrapper.instance().startEditing(ridx, cidx);
});
it('should set state correctly', () => {
expect(wrapper.state().ridx).toEqual(ridx);
expect(wrapper.state().cidx).toEqual(cidx);
});
});
describe('if selectRow prop is defined', () => {
describe('and selectRow.clickToEdit is enable', () => {
beforeEach(() => {
wrapper = shallow(shallowContext(
defaultCellEdit,
false,
{
...defaultSelectRow,
clickToEdit: true
}
));
wrapper.render();
wrapper.instance().startEditing(ridx, cidx);
});
it('should set state correctly', () => {
expect(wrapper.state().ridx).toEqual(ridx);
expect(wrapper.state().cidx).toEqual(cidx);
});
});
describe('and selectRow.clickToSelect is disable', () => {
beforeEach(() => {
wrapper = shallow(shallowContext(
defaultCellEdit,
false,
{
...defaultSelectRow,
clickToSelect: false
}
));
wrapper.render();
wrapper.instance().startEditing(ridx, cidx);
});
it('should set state correctly', () => {
expect(wrapper.state().ridx).toEqual(ridx);
expect(wrapper.state().cidx).toEqual(cidx);
});
});
describe('and selectRow.clickToEdit & selectRow.clickToSelect is enable', () => {
beforeEach(() => {
wrapper = shallow(shallowContext(
defaultCellEdit,
false,
{
...defaultSelectRow,
clickToEdit: false,
clickToSelect: true
}
));
wrapper.render();
wrapper.instance().startEditing(ridx, cidx);
});
it('should not set state', () => {
expect(wrapper.state().ridx).toBeNull();
expect(wrapper.state().cidx).toBeNull();
});
});
});
});
describe('escapeEditing', () => {
const initialState = { ridx: 1, cidx: 1 };
beforeEach(() => {
wrapper = shallow(shallowContext());
wrapper.setState(initialState);
wrapper.instance().escapeEditing();
});
it('should set state correctly', () => {
expect(wrapper.state().ridx).toBeNull();
expect(wrapper.state().cidx).toBeNull();
});
});
});

View File

@ -2,7 +2,6 @@ import React from 'react';
import { shallow } from 'enzyme';
import Caption from '../src/caption';
import Store from '../src/store';
import Header from '../src/header';
import Body from '../src/body';
import BootstrapTable from '../src/bootstrap-table';
@ -25,13 +24,10 @@ describe('BootstrapTable', () => {
name: 'B'
}];
const store = new Store('id');
store.data = data;
describe('simplest table', () => {
beforeEach(() => {
wrapper = shallow(
<BootstrapTable keyField="id" columns={ columns } data={ data } store={ store } />);
<BootstrapTable keyField="id" columns={ columns } data={ data } />);
});
it('should render successfully', () => {
@ -41,11 +37,6 @@ describe('BootstrapTable', () => {
expect(wrapper.find(Body).length).toBe(1);
});
it('should have correct default state', () => {
expect(wrapper.state().data).toBeDefined();
expect(wrapper.state().data).toEqual(store.data);
});
it("should only have classes 'table' and 'table-bordered' as default", () => {
expect(wrapper.find('table').prop('className')).toBe('table table-bordered');
});
@ -64,7 +55,6 @@ describe('BootstrapTable', () => {
keyField="id"
columns={ columns }
data={ data }
store={ store }
classes={ classes }
/>);
});
@ -83,7 +73,6 @@ describe('BootstrapTable', () => {
keyField="id"
columns={ columns }
data={ data }
store={ store }
wrapperClasses={ classes }
/>);
});
@ -102,7 +91,6 @@ describe('BootstrapTable', () => {
keyField="id"
columns={ columns }
data={ data }
store={ store }
id={ id }
/>);
});
@ -115,7 +103,7 @@ describe('BootstrapTable', () => {
describe('when hover props is true', () => {
beforeEach(() => {
wrapper = shallow(
<BootstrapTable keyField="id" columns={ columns } data={ data } store={ store } hover />);
<BootstrapTable keyField="id" columns={ columns } data={ data } hover />);
});
it('should have table-hover class on table', () => {
@ -126,7 +114,7 @@ describe('BootstrapTable', () => {
describe('when striped props is true', () => {
beforeEach(() => {
wrapper = shallow(
<BootstrapTable keyField="id" columns={ columns } data={ data } store={ store } striped />);
<BootstrapTable keyField="id" columns={ columns } data={ data } striped />);
});
it('should have table-striped class on table', () => {
@ -137,7 +125,7 @@ describe('BootstrapTable', () => {
describe('when condensed props is true', () => {
beforeEach(() => {
wrapper = shallow(
<BootstrapTable keyField="id" columns={ columns } data={ data } store={ store } condensed />);
<BootstrapTable keyField="id" columns={ columns } data={ data } condensed />);
});
it('should have table-condensed class on table', () => {
@ -148,7 +136,7 @@ describe('BootstrapTable', () => {
describe('when bordered props is false', () => {
beforeEach(() => {
wrapper = shallow(
<BootstrapTable keyField="id" columns={ columns } data={ data } store={ store } bordered={ false } />);
<BootstrapTable keyField="id" columns={ columns } data={ data } bordered={ false } />);
});
it('should not have table-condensed class on table', () => {
@ -160,7 +148,6 @@ describe('BootstrapTable', () => {
beforeEach(() => {
wrapper = shallow(
<BootstrapTable
store={ store }
caption={ <span className="table-caption">test</span> }
keyField="id"
columns={ columns }

View File

@ -1,209 +0,0 @@
/* eslint react/prefer-stateless-function: 0 */
/* eslint react/no-multi-comp: 0 */
import React from 'react';
import { shallow } from 'enzyme';
import BootstrapTable from '../src/bootstrap-table';
import Container from '../index.js';
describe('container', () => {
let wrapper;
const keyField = 'id';
const columns = [{
dataField: keyField,
text: 'ID'
}, {
dataField: 'name',
text: 'Name'
}];
const data = [{
id: 1,
name: 'A'
}, {
id: 2,
name: 'B'
}];
describe('initialization', () => {
beforeEach(() => {
wrapper = shallow(
<Container keyField={ keyField } data={ data } columns={ columns } />
);
});
it('should initialize BaseComponent', () => {
expect(wrapper.instance().BaseComponent.name).toBe('BootstrapTable');
});
it('should render BootstrapTable successfully', () => {
expect(wrapper.find(BootstrapTable)).toHaveLength(1);
});
it('should creating store successfully', () => {
const store = wrapper.instance().store;
expect(store).toBeDefined();
expect(store.data).toEqual(data);
expect(store.keyField).toEqual(keyField);
});
});
describe('when cellEdit prop is defined', () => {
const wrapperFactory = Base => class CellEditWrapper extends React.Component {
render() { return <Base { ...this.props } />; }
};
const cellEdit = {
wrapperFactory,
options: {
mode: 'click'
}
};
beforeEach(() => {
wrapper = shallow(
<Container
keyField={ keyField }
data={ data }
columns={ columns }
cellEdit={ cellEdit }
/>
);
});
it('should initialize BaseComponent correctly', () => {
expect(wrapper.instance().BaseComponent.name).toBe('CellEditWrapper');
});
it('should render CellEditWrapper component successfully', () => {
expect(wrapper.find('CellEditWrapper')).toHaveLength(1);
});
it('should render BootstrapTable component successfully', () => {
expect(wrapper.dive().find(BootstrapTable)).toHaveLength(1);
});
});
describe('when selectRow prop is defined', () => {
const selectRow = {
mode: 'checkbox'
};
beforeEach(() => {
wrapper = shallow(
<Container
keyField={ keyField }
data={ data }
columns={ columns }
selectRow={ selectRow }
/>
);
});
it('should initialize BaseComponent correctly', () => {
expect(wrapper.instance().BaseComponent.name).toBe('RowSelectionWrapper');
});
it('should render BootstrapTable component successfully', () => {
expect(wrapper.dive().find(BootstrapTable)).toHaveLength(1);
});
it('should render RowSelectionWrapper component successfully', () => {
expect(wrapper.find('RowSelectionWrapper').length).toBe(1);
});
});
describe('when pagination prop is defined', () => {
const wrapperFactory = Base => class PaginationWrapper extends React.Component {
render() { return <Base { ...this.props } />; }
};
const pagination = {
wrapperFactory
};
beforeEach(() => {
wrapper = shallow(
<Container
keyField={ keyField }
data={ data }
columns={ columns }
pagination={ pagination }
/>
);
});
it('should initialize BaseComponent correctly', () => {
expect(wrapper.instance().BaseComponent.name).toBe('PaginationWrapper');
});
it('should render BootstrapTable component successfully', () => {
expect(wrapper.dive().find(BootstrapTable)).toHaveLength(1);
});
it('should render PaginationWrapper component successfully', () => {
expect(wrapper.find('PaginationWrapper').length).toBe(1);
});
});
describe('when filter prop is defined', () => {
const wrapperFactory = Base => class FilterWrapper extends React.Component {
render() { return <Base { ...this.props } />; }
};
const filter = { wrapperFactory };
beforeEach(() => {
wrapper = shallow(
<Container
keyField={ keyField }
data={ data }
columns={ columns }
filter={ filter }
/>
);
});
it('should initialize BaseComponent correctly', () => {
expect(wrapper.instance().BaseComponent.name).toBe('FilterWrapper');
});
it('should render BootstrapTable component successfully', () => {
expect(wrapper.dive().find(BootstrapTable)).toHaveLength(1);
});
it('should render FilterWrapper component successfully', () => {
expect(wrapper.find('FilterWrapper').length).toBe(1);
});
});
describe('when any column.sort is defined', () => {
beforeEach(() => {
const columnsWithSort = [{
dataField: keyField,
text: 'ID',
sort: true
}];
wrapper = shallow(
<Container
keyField={ keyField }
data={ data }
columns={ columnsWithSort }
/>
);
});
it('should initialize BaseComponent correctly', () => {
expect(wrapper.instance().BaseComponent.name).toBe('SortWrapper');
});
it('should render BootstrapTable component successfully', () => {
expect(wrapper.dive().find(BootstrapTable)).toHaveLength(1);
});
it('should render SortWrapper component successfully', () => {
expect(wrapper.find('SortWrapper').length).toBe(1);
});
});
});

View File

@ -0,0 +1,130 @@
import 'jsdom-global/register';
import React from 'react';
import { shallow } from 'enzyme';
import BootstrapTable from '../../src/bootstrap-table';
import createDataContext from '../../src/contexts/data-context';
describe('DataContext', () => {
let wrapper;
const data = [{
id: 1,
name: 'A'
}, {
id: 2,
name: 'B'
}];
const columns = [{
dataField: 'id',
text: 'ID'
}, {
dataField: 'name',
text: 'Name'
}];
const mockBase = jest.fn((props => (
<BootstrapTable
data={ data }
columns={ columns }
keyField="id"
{ ...props }
/>
)));
const DataContext = createDataContext();
function shallowContext() {
return (
<DataContext.Provider
data={ data }
>
<DataContext.Consumer>
{
dataProps => mockBase(dataProps)
}
</DataContext.Consumer>
</DataContext.Provider>
);
}
describe('default render', () => {
beforeEach(() => {
wrapper = shallow(shallowContext());
wrapper.render();
});
it('should have correct Provider property after calling createDataContext', () => {
expect(DataContext.Provider).toBeDefined();
});
it('should have correct Consumer property after calling createDataContext', () => {
expect(DataContext.Consumer).toBeDefined();
});
it('should have correct state.data', () => {
expect(wrapper.state().data).toEqual(data);
});
it('should pass correct sort props to children element', () => {
expect(wrapper.length).toBe(1);
expect(mockBase).toHaveBeenCalledWith({
data,
getData: wrapper.instance().getData
});
});
});
describe('componentWillReceiveProps', () => {
const newData = [...data, { id: 3, name: 'test' }];
beforeEach(() => {
wrapper = shallow(shallowContext());
wrapper.instance().componentWillReceiveProps({
data: newData
});
});
it('should have correct state.data', () => {
expect(wrapper.state().data).toEqual(newData);
});
});
describe('getData', () => {
let result;
const fakeData = [...data, { id: 3, name: 'test' }];
beforeEach(() => {
wrapper = shallow(shallowContext());
});
describe('if third argument is give', () => {
it('should return the data property from third argument', () => {
result = wrapper.instance().getData(null, null, { data: fakeData });
expect(result).toEqual(fakeData);
});
});
describe('if second argument is give', () => {
it('should return the data property from second argument', () => {
result = wrapper.instance().getData(null, { data: fakeData });
expect(result).toEqual(fakeData);
});
});
describe('if first argument is give', () => {
it('should return the data property from first argument', () => {
result = wrapper.instance().getData({ data: fakeData });
expect(result).toEqual(fakeData);
});
});
describe('if no argument is give', () => {
it('should return default props.data', () => {
result = wrapper.instance().getData();
expect(result).toEqual(data);
});
});
});
});

View File

@ -0,0 +1,196 @@
/* eslint no-param-reassign: 0 */
import React from 'react';
import { shallow } from 'enzyme';
import Base from '../../src/bootstrap-table';
import withContext from '../../src/contexts';
describe('Context', () => {
let wrapper;
const keyField = 'id';
let columns;
const data = [{
id: 1,
name: 'A'
}, {
id: 2,
name: 'B'
}];
const BootstrapTable = withContext(Base);
beforeEach(() => {
columns = [{
dataField: keyField,
text: 'ID'
}, {
dataField: 'name',
text: 'Name'
}];
});
describe('basic render', () => {
beforeEach(() => {
wrapper = shallow(
<BootstrapTable keyField={ keyField } data={ data } columns={ columns } />
);
wrapper.render();
});
it('should create contexts correctly', () => {
expect(wrapper.instance().DataContext).toBeDefined();
expect(wrapper.instance().SortContext).not.toBeDefined();
expect(wrapper.instance().SelectionContext).not.toBeDefined();
expect(wrapper.instance().CellEditContext).not.toBeDefined();
expect(wrapper.instance().FilterContext).not.toBeDefined();
expect(wrapper.instance().PaginationContext).not.toBeDefined();
});
it('should render correctly', () => {
const dataProvider = wrapper.find(wrapper.instance().DataContext.Provider);
expect(dataProvider).toHaveLength(1);
expect(dataProvider.props().data).toEqual(data);
expect(dataProvider.props().keyField).toEqual(keyField);
expect(dataProvider.props().columns).toEqual(columns);
});
});
describe('if there\'s sort is enable', () => {
beforeEach(() => {
const columnsWithSort = columns.map((c) => {
c.sort = true;
return c;
});
wrapper = shallow(
<BootstrapTable keyField={ keyField } data={ data } columns={ columnsWithSort } />
);
wrapper.render();
});
it('should create contexts correctly', () => {
expect(wrapper.instance().DataContext).toBeDefined();
expect(wrapper.instance().SortContext).toBeDefined();
expect(wrapper.instance().SelectionContext).not.toBeDefined();
expect(wrapper.instance().CellEditContext).not.toBeDefined();
expect(wrapper.instance().FilterContext).not.toBeDefined();
expect(wrapper.instance().PaginationContext).not.toBeDefined();
});
});
describe('if row selection is enable', () => {
beforeEach(() => {
const selectRow = { mode: 'radio' };
wrapper = shallow(
<BootstrapTable
keyField={ keyField }
data={ data }
columns={ columns }
selectRow={ selectRow }
/>
);
wrapper.render();
});
it('should create contexts correctly', () => {
expect(wrapper.instance().DataContext).toBeDefined();
expect(wrapper.instance().SortContext).not.toBeDefined();
expect(wrapper.instance().SelectionContext).toBeDefined();
expect(wrapper.instance().CellEditContext).not.toBeDefined();
expect(wrapper.instance().FilterContext).not.toBeDefined();
expect(wrapper.instance().PaginationContext).not.toBeDefined();
});
});
describe('if cell editing is enable', () => {
beforeEach(() => {
const CellEditContext = React.createContext();
const cellEdit = {
createContext: jest.fn().mockReturnValue({
Provider: CellEditContext.Provider,
Consumer: CellEditContext.Consumer
})
};
wrapper = shallow(
<BootstrapTable
keyField={ keyField }
data={ data }
columns={ columns }
cellEdit={ cellEdit }
/>
);
wrapper.render();
});
it('should create contexts correctly', () => {
expect(wrapper.instance().DataContext).toBeDefined();
expect(wrapper.instance().SortContext).not.toBeDefined();
expect(wrapper.instance().SelectionContext).not.toBeDefined();
expect(wrapper.instance().CellEditContext).toBeDefined();
expect(wrapper.instance().FilterContext).not.toBeDefined();
expect(wrapper.instance().PaginationContext).not.toBeDefined();
});
});
describe('if column filter is enable', () => {
beforeEach(() => {
const FilterContext = React.createContext();
const filter = {
createContext: jest.fn().mockReturnValue({
Provider: FilterContext.Provider,
Consumer: FilterContext.Consumer
})
};
wrapper = shallow(
<BootstrapTable
keyField={ keyField }
data={ data }
columns={ columns }
filter={ filter }
/>
);
wrapper.render();
});
it('should create contexts correctly', () => {
expect(wrapper.instance().DataContext).toBeDefined();
expect(wrapper.instance().SortContext).not.toBeDefined();
expect(wrapper.instance().SelectionContext).not.toBeDefined();
expect(wrapper.instance().CellEditContext).not.toBeDefined();
expect(wrapper.instance().FilterContext).toBeDefined();
expect(wrapper.instance().PaginationContext).not.toBeDefined();
});
});
describe('if pagination is enable', () => {
beforeEach(() => {
const PaginationContext = React.createContext();
const paginator = {
createContext: jest.fn().mockReturnValue({
Provider: PaginationContext.Provider,
Consumer: PaginationContext.Consumer
})
};
wrapper = shallow(
<BootstrapTable
keyField={ keyField }
data={ data }
columns={ columns }
pagination={ paginator }
/>
);
wrapper.render();
});
it('should create contexts correctly', () => {
expect(wrapper.instance().DataContext).toBeDefined();
expect(wrapper.instance().SortContext).not.toBeDefined();
expect(wrapper.instance().SelectionContext).not.toBeDefined();
expect(wrapper.instance().CellEditContext).not.toBeDefined();
expect(wrapper.instance().FilterContext).not.toBeDefined();
expect(wrapper.instance().PaginationContext).toBeDefined();
});
});
});

View File

@ -0,0 +1,258 @@
import 'jsdom-global/register';
import React from 'react';
import { shallow } from 'enzyme';
import dataOperator from '../../src/store/operators';
import BootstrapTable from '../../src/bootstrap-table';
import createSelectionContext from '../../src/contexts/selection-context';
describe('DataContext', () => {
let wrapper;
const data = [{
id: 1,
name: 'A'
}, {
id: 2,
name: 'B'
}, {
id: 3,
name: 'B'
}];
const keyField = 'id';
const columns = [{
dataField: 'id',
text: 'ID'
}, {
dataField: 'name',
text: 'Name'
}];
const mockBase = jest.fn((props => (
<BootstrapTable
data={ data }
columns={ columns }
keyField={ keyField }
{ ...props }
/>
)));
const defaultSelectRow = {
mode: 'checkbox'
};
const SelectionContext = createSelectionContext(dataOperator);
function shallowContext(selectRow = defaultSelectRow) {
return (
<SelectionContext.Provider
data={ data }
keyField={ keyField }
selectRow={ selectRow }
>
<SelectionContext.Consumer>
{
selectionProps => mockBase(selectionProps)
}
</SelectionContext.Consumer>
</SelectionContext.Provider>
);
}
describe('default render', () => {
beforeEach(() => {
wrapper = shallow(shallowContext());
wrapper.render();
});
it('should have correct Provider property after calling createSelectionContext', () => {
expect(SelectionContext.Provider).toBeDefined();
});
it('should have correct Consumer property after calling createSelectionContext', () => {
expect(SelectionContext.Consumer).toBeDefined();
});
it('should have correct state.data', () => {
expect(wrapper.state().selected).toEqual([]);
});
it('should pass correct sort props to children element', () => {
expect(wrapper.length).toBe(1);
expect(mockBase).toHaveBeenCalledWith({
selected: wrapper.state().selected,
onRowSelect: wrapper.instance().handleRowSelect,
onAllRowsSelect: wrapper.instance().handleAllRowsSelect
});
});
});
describe('componentWillReceiveProps', () => {
const newSelectRow = {
...defaultSelectRow,
selected: [1]
};
beforeEach(() => {
wrapper = shallow(shallowContext());
wrapper.instance().componentWillReceiveProps({
selectRow: newSelectRow
});
});
it('should have correct state.selected', () => {
expect(wrapper.state().selected).toEqual(newSelectRow.selected);
});
describe('if nextProps.selectRow is not existing', () => {
const defaultSelected = [1];
beforeEach(() => {
wrapper = shallow(shallowContext({
...defaultSelectRow,
selected: defaultSelected
}));
wrapper.instance().componentWillReceiveProps({
selectRow: defaultSelectRow
});
});
it('should keep origin state.selected', () => {
expect(wrapper.state().selected).toEqual(defaultSelected);
});
});
describe('if nextProps.selectRow is not existing', () => {
beforeEach(() => {
wrapper = shallow(shallowContext());
wrapper.instance().componentWillReceiveProps({});
});
it('should not set state.selected', () => {
expect(wrapper.state().selected).toEqual([]);
});
});
});
describe('when selectRow.selected prop is defined', () => {
let selectRow;
beforeEach(() => {
selectRow = {
...defaultSelectRow,
selected: [1]
};
wrapper = shallow(shallowContext(selectRow));
});
it('should have correct state.data', () => {
expect(wrapper.state().selected).toEqual(selectRow.selected);
});
});
describe('handleRowSelect', () => {
const rowIndex = 1;
const firstSelectedRow = data[0][keyField];
const secondSelectedRow = data[1][keyField];
describe('when selectRow.mode is \'radio\'', () => {
beforeEach(() => {
const selectRow = { mode: 'radio' };
wrapper = shallow(shallowContext(selectRow));
});
it('should set state.selected correctly', () => {
wrapper.instance().handleRowSelect(firstSelectedRow, true, rowIndex);
expect(wrapper.state('selected')).toEqual([firstSelectedRow]);
wrapper.instance().handleRowSelect(secondSelectedRow, true, rowIndex);
expect(wrapper.state('selected')).toEqual([secondSelectedRow]);
});
});
describe('when selectRow.mode is \'checkbox\'', () => {
beforeEach(() => {
wrapper = shallow(shallowContext());
});
it('should set state.selected correctly', () => {
wrapper.instance().handleRowSelect(firstSelectedRow, true, rowIndex);
expect(wrapper.state('selected')).toEqual(expect.arrayContaining([firstSelectedRow]));
wrapper.instance().handleRowSelect(secondSelectedRow, true, rowIndex);
expect(wrapper.state('selected')).toEqual(expect.arrayContaining([firstSelectedRow, secondSelectedRow]));
wrapper.instance().handleRowSelect(firstSelectedRow, false, rowIndex);
expect(wrapper.state('selected')).toEqual(expect.arrayContaining([secondSelectedRow]));
wrapper.instance().handleRowSelect(secondSelectedRow, false, rowIndex);
expect(wrapper.state('selected')).toEqual([]);
});
});
describe('when selectRow.onSelect is defined', () => {
const onSelect = jest.fn();
beforeEach(() => {
wrapper = shallow(shallowContext({
...defaultSelectRow,
onSelect
}));
});
it('call selectRow.onSelect correctly', () => {
const e = { target: {} };
const row = dataOperator.getRowByRowId(data, keyField, firstSelectedRow);
wrapper.instance().handleRowSelect(firstSelectedRow, true, rowIndex, e);
expect(onSelect).toHaveBeenCalledWith(row, true, rowIndex, e);
});
});
});
describe('handleAllRowsSelect', () => {
const e = { target: {} };
describe('when isUnSelect argument is false', () => {
beforeEach(() => {
wrapper = shallow(shallowContext());
wrapper.instance().handleAllRowsSelect(e, false);
});
it('should set state.selected correctly', () => {
expect(wrapper.state('selected')).toEqual(data.map(d => d[keyField]));
});
});
describe('when isUnSelect argument is true', () => {
beforeEach(() => {
wrapper = shallow(shallowContext({
...defaultSelectRow,
selected: data.map(d => d[keyField])
}));
wrapper.instance().handleAllRowsSelect(e, true);
});
it('should set state.selected correctly', () => {
expect(wrapper.state('selected')).toEqual([]);
});
});
describe('when selectRow.onSelectAll is defined', () => {
const onSelectAll = jest.fn();
beforeEach(() => {
wrapper = shallow(shallowContext({
...defaultSelectRow,
onSelectAll
}));
wrapper.instance().handleAllRowsSelect(e, false);
});
it('should call selectRow.onSelectAll correctly', () => {
expect(onSelectAll).toHaveBeenCalledWith(
true,
dataOperator.getSelectedRows(data, keyField, wrapper.state('selected')),
e
);
});
});
});
});

View File

@ -0,0 +1,255 @@
import 'jsdom-global/register';
import React from 'react';
import { shallow } from 'enzyme';
import Const from '../../src/const';
import dataOperator from '../../src/store/operators';
import BootstrapTable from '../../src/bootstrap-table';
import createSortContext from '../../src/contexts/sort-context';
describe('SortContext', () => {
let wrapper;
let columns;
let SortContext;
let data;
const mockBase = jest.fn((props => (
<BootstrapTable
data={ data }
columns={ columns }
keyField="id"
{ ...props }
/>
)));
beforeEach(() => {
data = [{
id: 1,
name: 'A'
}, {
id: 2,
name: 'B'
}];
columns = [{
dataField: 'id',
text: 'ID',
sort: true
}, {
dataField: 'name',
text: 'Name',
sort: true
}];
});
const handleRemoteSortChange = jest.fn();
function shallowContext(enableRemote = false, providerProps = {}) {
handleRemoteSortChange.mockReset();
mockBase.mockReset();
SortContext = createSortContext(
dataOperator,
jest.fn().mockReturnValue(enableRemote),
handleRemoteSortChange
);
return (
<SortContext.Provider
columns={ columns }
data={ data }
{ ...providerProps }
>
<SortContext.Consumer>
{
sortProps => mockBase(sortProps)
}
</SortContext.Consumer>
</SortContext.Provider>
);
}
describe('default render', () => {
beforeEach(() => {
wrapper = shallow(shallowContext());
wrapper.render();
});
it('should have correct Provider property after calling createSortContext', () => {
expect(SortContext.Provider).toBeDefined();
});
it('should have correct Consumer property after calling createSortContext', () => {
expect(SortContext.Consumer).toBeDefined();
});
it('should have correct state.sortOrder', () => {
expect(wrapper.state().sortOrder).toBe(undefined);
});
it('should have correct state.sortColumn', () => {
expect(wrapper.state().sortColumn).toBe(undefined);
});
it('should pass correct sort props to children element', () => {
expect(wrapper.length).toBe(1);
expect(mockBase).toHaveBeenCalledWith({
data,
sortOrder: undefined,
onSort: wrapper.instance().handleSort,
sortField: null
});
});
});
describe('handleSort function', () => {
let sortColumn;
let nextOrderSpy;
beforeEach(() => {
sortColumn = columns[0];
nextOrderSpy = jest.spyOn(dataOperator, 'nextOrder');
});
afterEach(() => {
nextOrderSpy.mockRestore();
});
describe('when remote.sort is false', () => {
beforeEach(() => {
wrapper = shallow(shallowContext());
wrapper.render();
wrapper.instance().handleSort(sortColumn);
wrapper.update();
wrapper.render();
});
it('should set state correctly', () => {
expect(wrapper.state().sortColumn).toEqual(sortColumn);
expect(wrapper.state().sortOrder).toEqual(Const.SORT_DESC);
});
it('should call dataOperator.nextOrder correctly', () => {
expect(nextOrderSpy).toHaveBeenCalledTimes(1);
expect(nextOrderSpy).toHaveBeenCalledWith(
sortColumn,
{ sortColumn: undefined, sortOrder: undefined },
wrapper.props().defaultSortDirection
);
});
it('should pass correct sort props to children element', () => {
expect(wrapper.length).toBe(1);
expect(mockBase).toHaveBeenLastCalledWith({
data: data.reverse(),
sortOrder: wrapper.state().sortOrder,
onSort: wrapper.instance().handleSort,
sortField: wrapper.state().sortColumn.dataField
});
});
});
describe('when remote.sort is true', () => {
beforeEach(() => {
wrapper = shallow(shallowContext(true));
wrapper.render();
nextOrderSpy = jest.spyOn(dataOperator, 'nextOrder');
wrapper.instance().handleSort(sortColumn);
});
it('should set state correctly', () => {
expect(wrapper.state().sortColumn).toEqual(sortColumn);
expect(wrapper.state().sortOrder).toEqual(Const.SORT_DESC);
});
it('should call dataOperator.nextOrder correctly', () => {
expect(nextOrderSpy).toHaveBeenCalledTimes(1);
expect(nextOrderSpy).toHaveBeenCalledWith(
sortColumn,
{ sortColumn: undefined, sortOrder: undefined },
wrapper.props().defaultSortDirection
);
});
it('should calling handleRemoteSortChange correctly', () => {
expect(handleRemoteSortChange).toHaveBeenCalledTimes(1);
expect(handleRemoteSortChange).toHaveBeenCalledWith(sortColumn.dataField, Const.SORT_DESC);
});
});
describe('when column.onSort prop is defined', () => {
const onSortCB = jest.fn();
beforeEach(() => {
columns[0].onSort = onSortCB;
wrapper = shallow(shallowContext());
wrapper.instance().handleSort(sortColumn);
});
it('should calling column.onSort function correctly', () => {
expect(onSortCB).toHaveBeenCalledTimes(1);
expect(onSortCB).toHaveBeenCalledWith(columns[0].dataField, Const.SORT_DESC);
wrapper.instance().handleSort(sortColumn);
expect(onSortCB).toHaveBeenCalledTimes(2);
expect(onSortCB).toHaveBeenCalledWith(columns[0].dataField, Const.SORT_ASC);
});
});
});
describe('when defaultSorted prop is defined', () => {
const defaultSorted = [{
dataField: 'name',
order: Const.SORT_DESC
}];
beforeEach(() => {
wrapper = shallow(shallowContext(false, { defaultSorted }));
wrapper.render();
});
it('should pass correct sort props to children element', () => {
expect(wrapper.length).toBe(1);
expect(mockBase).toHaveBeenLastCalledWith({
data: data.reverse(),
sortOrder: wrapper.state().sortOrder,
onSort: wrapper.instance().handleSort,
sortField: wrapper.state().sortColumn.dataField
});
});
it('should have correct state.sortOrder', () => {
expect(wrapper.state().sortOrder).toBe(defaultSorted[0].order);
});
it('should have correct state.sortColumn', () => {
expect(wrapper.state().sortColumn).toBe(columns[1]);
});
describe('when column.onSort prop is defined', () => {
const onSortCB = jest.fn();
beforeEach(() => {
columns[1].onSort = onSortCB;
wrapper = shallow(shallowContext(false, { defaultSorted }));
});
it('should calling column.onSort function correctly', () => {
expect(onSortCB).toHaveBeenCalledTimes(1);
expect(onSortCB).toHaveBeenCalledWith(defaultSorted[0].dataField, defaultSorted[0].order);
});
});
describe('when remote.sort is true', () => {
beforeEach(() => {
wrapper = shallow(shallowContext(true, { defaultSorted }));
wrapper.render();
});
it('should calling handleRemoteSortChange correctly', () => {
expect(handleRemoteSortChange).toHaveBeenCalledTimes(1);
expect(handleRemoteSortChange)
.toHaveBeenCalledWith(defaultSorted[0].dataField, defaultSorted[0].order);
});
});
});
});

View File

@ -225,17 +225,9 @@ describe('TableResolver', () => {
bar: expect.any(Function)
}));
});
it('should return object which can not contain allRowsSelected option', () => {
expect(headerCellSelectionInfo.allRowsSelected).not.toBeDefined();
});
it('should return object which can not contain allRowsSelected option', () => {
expect(headerCellSelectionInfo.selected).not.toBeDefined();
});
});
describe('if all rows were selected', () => {
describe('if options.allRowsSelected is true', () => {
beforeEach(() => {
selectRow = {};
const selectedRowKeys = [1, 2];
@ -258,7 +250,7 @@ describe('TableResolver', () => {
});
});
describe('if part of rows were selected', () => {
describe('if options.allRowsSelected and options.allRowsNotSelected both are false', () => {
beforeEach(() => {
selectRow = {};
const selectedRowKeys = [1];
@ -269,6 +261,7 @@ describe('TableResolver', () => {
wrapper = shallow(mockElement);
headerCellSelectionInfo = wrapper.instance().resolveSelectRowPropsForHeader({
allRowsSelected: false,
allRowsNotSelected: false,
selected: selectedRowKeys
});
});
@ -280,7 +273,7 @@ describe('TableResolver', () => {
});
});
describe('if none of row was selected', () => {
describe('if options.allRowsNotSelected is true', () => {
beforeEach(() => {
selectRow = {};
const selectedRowKeys = [];
@ -292,6 +285,7 @@ describe('TableResolver', () => {
headerCellSelectionInfo = wrapper.instance().resolveSelectRowPropsForHeader({
allRowsSelected: false,
allRowsNotSelected: true,
selected: selectedRowKeys
});
});

View File

@ -3,7 +3,7 @@ import React from 'react';
import sinon from 'sinon';
import { shallow } from 'enzyme';
import Container from '../../';
import Container from '../../index';
// import remoteResolver from '../../src/props-resolver/remote-resolver';
describe('remoteResolver', () => {
@ -100,6 +100,16 @@ describe('remoteResolver', () => {
expect(wrapper.instance().isRemoteFiltering()).toBeTruthy();
});
});
describe('when this.isRemotePagination return true', () => {
beforeEach(() => {
shallowContainer({ remote: { pagination: true } });
});
it('should return true', () => {
expect(wrapper.instance().isRemoteFiltering()).toBeTruthy();
});
});
});
describe('isRemoteSort', () => {
@ -132,6 +142,16 @@ describe('remoteResolver', () => {
expect(wrapper.instance().isRemoteSort()).toBeTruthy();
});
});
describe('when this.isRemotePagination return true', () => {
beforeEach(() => {
shallowContainer({ remote: { pagination: true } });
});
it('should return true', () => {
expect(wrapper.instance().isRemoteSort()).toBeTruthy();
});
});
});
describe('isRemoteCellEdit', () => {
@ -166,7 +186,7 @@ describe('remoteResolver', () => {
});
});
describe('handleCellChange', () => {
describe('handleRemoteCellChange', () => {
const onTableChangeCB = sinon.stub();
const rowId = 1;
const dataField = 'name';
@ -175,7 +195,7 @@ describe('remoteResolver', () => {
beforeEach(() => {
onTableChangeCB.reset();
shallowContainer({ onTableChange: onTableChangeCB });
wrapper.instance().handleCellChange(rowId, dataField, newValue);
wrapper.instance().handleRemoteCellChange(rowId, dataField, newValue);
});
it('should calling props.onTableChange correctly', () => {
@ -188,35 +208,45 @@ describe('remoteResolver', () => {
describe('handleSortChange', () => {
const onTableChangeCB = sinon.stub();
const newSortFiled = 'name';
const newSortOrder = 'asc';
beforeEach(() => {
onTableChangeCB.reset();
shallowContainer({ onTableChange: onTableChangeCB });
wrapper.instance().handleSortChange();
wrapper.instance().handleRemoteSortChange(newSortFiled, newSortOrder);
});
it('should calling props.onTableChange correctly', () => {
expect(onTableChangeCB.calledOnce).toBeTruthy();
expect(onTableChangeCB.calledWith('sort', wrapper.instance().getNewestState())).toBeTruthy();
expect(onTableChangeCB.calledWith('sort', wrapper.instance().getNewestState({
sortField: newSortFiled,
sortOrder: newSortOrder
}))).toBeTruthy();
});
});
describe('handleRemotePageChange', () => {
const onTableChangeCB = sinon.stub();
const newPage = 2;
const newSizePerPage = 10;
beforeEach(() => {
onTableChangeCB.reset();
shallowContainer({ onTableChange: onTableChangeCB });
wrapper.instance().handleRemotePageChange();
wrapper.instance().handleRemotePageChange(newPage, newSizePerPage);
});
it('should calling props.onTableChange correctly', () => {
expect(onTableChangeCB.calledOnce).toBeTruthy();
expect(onTableChangeCB.calledWith('pagination', wrapper.instance().getNewestState())).toBeTruthy();
expect(onTableChangeCB.calledWith('pagination', wrapper.instance().getNewestState({
page: newPage,
sizePerPage: newSizePerPage
}))).toBeTruthy();
});
});
describe('handleRemoteFilterChange', () => {
const onTableChangeCB = sinon.stub();
const filters = { price: { filterVal: 20, filterType: 'TEXT' } };
beforeEach(() => {
onTableChangeCB.reset();
shallowContainer({ onTableChange: onTableChangeCB });
@ -224,16 +254,16 @@ describe('remoteResolver', () => {
describe('when remote pagination is disabled', () => {
it('should calling props.onTableChange correctly', () => {
wrapper.instance().handleRemoteFilterChange();
wrapper.instance().handleRemoteFilterChange(filters);
expect(onTableChangeCB.calledOnce).toBeTruthy();
expect(onTableChangeCB.calledWith('filter', wrapper.instance().getNewestState())).toBeTruthy();
expect(onTableChangeCB.calledWith('filter', wrapper.instance().getNewestState({
filters
}))).toBeTruthy();
});
});
describe('when remote pagination is enabled', () => {
const wrapperFactory = Base => class FilterWrapper extends React.Component {
render() { return <Base { ...this.props } />; }
};
const createContext = () => {};
describe('and pagination.options.pageStartIndex is defined', () => {
const options = { pageStartIndex: 0 };
@ -241,16 +271,16 @@ describe('remoteResolver', () => {
shallowContainer({
remote: true,
onTableChange: onTableChangeCB,
pagination: { options, wrapperFactory }
pagination: { options, createContext }
});
wrapper.instance().store.page = 1;
wrapper.instance().store.sizePerPage = 10;
wrapper.instance().handleRemoteFilterChange();
wrapper.instance().handleRemoteFilterChange(filters);
});
it('should calling onTableChange correctly', () => {
it('should calling onTableChange with page property by pageStartIndex', () => {
expect(onTableChangeCB.calledOnce).toBeTruthy();
const newState = wrapper.instance().getNewestState();
const newState = wrapper.instance().getNewestState({
filters
});
newState.page = options.pageStartIndex;
expect(onTableChangeCB.calledWith('filter', newState)).toBeTruthy();
});
@ -261,14 +291,14 @@ describe('remoteResolver', () => {
shallowContainer({
remote: true,
onTableChange: onTableChangeCB,
pagination: { wrapperFactory }
pagination: { createContext }
});
wrapper.instance().handleRemoteFilterChange();
wrapper.instance().handleRemoteFilterChange(filters);
});
it('should calling onTableChange correctly', () => {
it('should calling onTableChange with page property by default 1', () => {
expect(onTableChangeCB.calledOnce).toBeTruthy();
const newState = wrapper.instance().getNewestState();
const newState = wrapper.instance().getNewestState({ filters });
newState.page = 1;
expect(onTableChangeCB.calledWith('filter', newState)).toBeTruthy();
});

View File

@ -1,224 +0,0 @@
import React from 'react';
import sinon from 'sinon';
import { shallow } from 'enzyme';
import Store from '../../src/store';
import BootstrapTable from '../../src/bootstrap-table';
import wrapperFactory from '../../src/row-selection/wrapper';
describe('RowSelectionWrapper', () => {
let wrapper;
let selectRow;
const columns = [{
dataField: 'id',
text: 'ID'
}, {
dataField: 'name',
text: 'Name'
}];
const data = [{
id: 1,
name: 'A'
}, {
id: 2,
name: 'B'
}];
const rowIndex = 1;
const keyField = 'id';
const store = new Store(keyField);
store.data = data;
const RowSelectionWrapper = wrapperFactory(BootstrapTable);
beforeEach(() => {
selectRow = {
mode: 'radio'
};
wrapper = shallow(
<RowSelectionWrapper
keyField={ keyField }
data={ data }
columns={ columns }
selectRow={ selectRow }
store={ store }
/>
);
});
it('should render RowSelectionWrapper correctly', () => {
expect(wrapper.length).toBe(1);
expect(wrapper.find(BootstrapTable)).toBeDefined();
});
it('should have correct store.selected value', () => {
expect(store.selected).toEqual([]);
});
it('should have correct state', () => {
expect(wrapper.state().selectedRowKeys).toBeDefined();
expect(wrapper.state().selectedRowKeys.length).toEqual(0);
});
it('should inject correct props to base component', () => {
expect(wrapper.props().onRowSelect).toBeDefined();
expect(wrapper.props().onAllRowsSelect).toBeDefined();
});
describe('componentWillReceiveProps', () => {
const nextSelected = [0];
const nextProps = {
store: {
selected: nextSelected
},
selectRow: {
mode: 'checkbox',
selected: nextSelected
}
};
it('should update state.selectedRowKeys with next selected rows', () => {
wrapper.instance().componentWillReceiveProps(nextProps);
expect(nextProps.store.selected).toEqual(nextSelected);
expect(wrapper.state('selectedRowKeys')).toEqual(nextSelected);
});
});
describe('when selectRow.selected is defined', () => {
beforeEach(() => {
selectRow.mode = 'checkbox';
selectRow.selected = [1, 3];
wrapper = shallow(
<RowSelectionWrapper
keyField={ keyField }
data={ data }
columns={ columns }
selectRow={ selectRow }
store={ store }
/>
);
});
it('should have correct store.selected value', () => {
expect(store.selected).toEqual(selectRow.selected);
});
it('should have correct state', () => {
expect(wrapper.state().selectedRowKeys).toEqual(selectRow.selected);
});
});
describe('when selectRow.mode is \'radio\'', () => {
const firstSelectedRow = data[0][keyField];
const secondSelectedRow = data[1][keyField];
it('call handleRowSelect function should setting correct state.selectedRowKeys', () => {
wrapper.instance().handleRowSelect(firstSelectedRow, rowIndex);
expect(wrapper.state('selectedRowKeys')).toEqual([firstSelectedRow]);
wrapper.instance().handleRowSelect(secondSelectedRow, rowIndex);
expect(wrapper.state('selectedRowKeys')).toEqual([secondSelectedRow]);
});
});
describe('when selectRow.mode is \'checkbox\'', () => {
const firstSelectedRow = data[0][keyField];
const secondSelectedRow = data[1][keyField];
beforeEach(() => {
selectRow.mode = 'checkbox';
wrapper = shallow(
<RowSelectionWrapper
keyField={ keyField }
data={ data }
columns={ columns }
selectRow={ selectRow }
store={ store }
/>
);
});
it('call handleRowSelect function should setting correct state.selectedRowKeys', () => {
wrapper.instance().handleRowSelect(firstSelectedRow, true, rowIndex);
expect(wrapper.state('selectedRowKeys')).toEqual(expect.arrayContaining([firstSelectedRow]));
wrapper.instance().handleRowSelect(secondSelectedRow, true, rowIndex);
expect(wrapper.state('selectedRowKeys')).toEqual(expect.arrayContaining([firstSelectedRow, secondSelectedRow]));
wrapper.instance().handleRowSelect(firstSelectedRow, false, rowIndex);
expect(wrapper.state('selectedRowKeys')).toEqual(expect.arrayContaining([secondSelectedRow]));
wrapper.instance().handleRowSelect(secondSelectedRow, false, rowIndex);
expect(wrapper.state('selectedRowKeys')).toEqual([]);
});
it('call handleAllRowsSelect function should setting correct state.selectedRowKeys', () => {
wrapper.instance().handleAllRowsSelect();
expect(wrapper.state('selectedRowKeys')).toEqual(expect.arrayContaining([firstSelectedRow, secondSelectedRow]));
wrapper.instance().handleAllRowsSelect();
expect(wrapper.state('selectedRowKeys')).toEqual([]);
});
});
describe('when selectRow.onSelect is defined', () => {
const selectedRow = data[0][keyField];
const onSelectCallBack = sinon.stub();
beforeEach(() => {
selectRow.mode = 'checkbox';
selectRow.onSelect = onSelectCallBack;
wrapper = shallow(
<RowSelectionWrapper
keyField={ keyField }
data={ data }
columns={ columns }
selectRow={ selectRow }
store={ store }
/>
);
});
it('selectRow.onSelect callback should be called correctly when calling handleRowSelect function', () => {
wrapper.instance().handleRowSelect(selectedRow, true, rowIndex);
expect(onSelectCallBack.callCount).toEqual(1);
expect(onSelectCallBack.calledWith(data[0], true, rowIndex)).toBeTruthy();
wrapper.instance().handleRowSelect(selectedRow, false, rowIndex);
expect(onSelectCallBack.callCount).toEqual(2);
expect(onSelectCallBack.calledWith(data[0], false, rowIndex)).toBeTruthy();
});
});
describe('when selectRow.onSelectAll is defined', () => {
const onSelectAllCallBack = sinon.stub();
beforeEach(() => {
selectRow.mode = 'checkbox';
selectRow.onSelectAll = onSelectAllCallBack;
wrapper = shallow(
<RowSelectionWrapper
keyField={ keyField }
data={ data }
columns={ columns }
selectRow={ selectRow }
store={ store }
/>
);
});
it('selectRow.onSelect callback should be called correctly when calling handleRowSelect function', () => {
const e = {};
wrapper.instance().handleAllRowsSelect(e);
expect(onSelectAllCallBack.callCount).toEqual(1);
expect(onSelectAllCallBack.calledWith(true, data, e)).toBeTruthy();
wrapper.instance().handleAllRowsSelect(e);
expect(onSelectAllCallBack.callCount).toEqual(2);
expect(onSelectAllCallBack.calledWith(false, [], e)).toBeTruthy();
});
});
});

View File

@ -1,230 +0,0 @@
import 'jsdom-global/register';
import React from 'react';
import sinon from 'sinon';
import { shallow } from 'enzyme';
import Const from '../../src/const';
import Store from '../../src/store';
import BootstrapTable from '../../src/bootstrap-table';
import wrapperFactory from '../../src/sort/wrapper';
describe('SortWrapper', () => {
let wrapper;
let columns;
const data = [{
id: 1,
name: 'A'
}, {
id: 2,
name: 'B'
}];
const keyField = 'id';
let store = new Store(keyField);
store.data = data;
const SortWrapper = wrapperFactory(BootstrapTable);
beforeEach(() => {
columns = [{
dataField: 'id',
text: 'ID',
sort: true
}, {
dataField: 'name',
text: 'Name',
sort: true
}];
wrapper = shallow(
<SortWrapper
keyField={ keyField }
data={ data }
columns={ columns }
store={ store }
/>
);
});
it('should render SortWrapper correctly', () => {
expect(wrapper.length).toBe(1);
expect(wrapper.find(BootstrapTable)).toBeDefined();
});
it('should inject correct props to base component', () => {
expect(wrapper.props().onSort).toBeDefined();
});
describe('call handleSort function', () => {
let sortBySpy;
let sortColumn;
beforeEach(() => {
sortColumn = columns[0];
store = new Store(keyField);
store.data = data;
sortBySpy = sinon.spy(store, 'sortBy');
});
describe('when remote.sort is false', () => {
beforeEach(() => {
wrapper = shallow(
<SortWrapper
keyField={ keyField }
data={ data }
columns={ columns }
store={ store }
/>
);
wrapper.instance().handleSort(sortColumn);
});
it('should operating on store correctly', () => {
expect(store.sortOrder).toEqual(Const.SORT_DESC);
expect(store.sortField).toEqual(sortColumn.dataField);
wrapper.instance().handleSort(sortColumn); // sort same column again
expect(store.sortOrder).toEqual(Const.SORT_ASC);
expect(store.sortField).toEqual(sortColumn.dataField);
});
it('should calling store.sortBy correctly', () => {
expect(sortBySpy.calledOnce).toBeTruthy();
expect(sortBySpy.calledWith(sortColumn)).toBeTruthy();
});
});
describe('when remote.sort is true', () => {
let onTableChangeCB;
beforeEach(() => {
onTableChangeCB = sinon.stub();
wrapper = shallow(
<SortWrapper
remote
keyField={ keyField }
data={ data }
columns={ columns }
store={ store }
onTableChange={ onTableChangeCB }
/>
);
wrapper.instance().handleSort(sortColumn);
});
it('should operating on store correctly', () => {
expect(store.sortOrder).toEqual(Const.SORT_DESC);
expect(store.sortField).toEqual(sortColumn.dataField);
wrapper.instance().handleSort(sortColumn); // sort same column again
expect(store.sortOrder).toEqual(Const.SORT_ASC);
expect(store.sortField).toEqual(sortColumn.dataField);
});
it('should not calling store.sortBy', () => {
expect(sortBySpy.calledOnce).toBeFalsy();
});
it('should calling props.onTableChange', () => {
expect(onTableChangeCB.calledOnce).toBeTruthy();
});
});
describe('when column.onSort prop is defined', () => {
const onSortCB = jest.fn();
beforeEach(() => {
columns[0].onSort = onSortCB;
wrapper = shallow(
<SortWrapper
keyField={ keyField }
data={ data }
columns={ columns }
store={ store }
/>
);
wrapper.instance().handleSort(sortColumn);
});
it('should calling column.onSort function correctly', () => {
expect(onSortCB).toHaveBeenCalledTimes(1);
expect(onSortCB).toHaveBeenCalledWith(columns[0].dataField, Const.SORT_DESC);
wrapper.instance().handleSort(sortColumn);
expect(onSortCB).toHaveBeenCalledTimes(2);
expect(onSortCB).toHaveBeenCalledWith(columns[0].dataField, Const.SORT_ASC);
});
});
});
describe('when defaultSorted prop is defined', () => {
const defaultSorted = [{
dataField: 'name',
order: Const.SORT_DESC
}];
beforeEach(() => {
wrapper = shallow(
<SortWrapper
keyField={ keyField }
data={ data }
columns={ columns }
store={ store }
defaultSorted={ defaultSorted }
/>
);
});
it('should render table with correct default sorted', () => {
expect(wrapper.props().data).toEqual(store.data);
});
it('should update store.sortField correctly', () => {
expect(store.sortField).toEqual(defaultSorted[0].dataField);
});
it('should update store.sortOrder correctly', () => {
expect(store.sortOrder).toEqual(defaultSorted[0].order);
});
describe('when column.onSort prop is defined', () => {
const onSortCB = jest.fn();
beforeEach(() => {
columns[1].onSort = onSortCB;
wrapper = shallow(
<SortWrapper
keyField={ keyField }
data={ data }
columns={ columns }
store={ store }
defaultSorted={ defaultSorted }
/>
);
});
it('should calling column.onSort function correctly', () => {
expect(onSortCB).toHaveBeenCalledTimes(1);
expect(onSortCB).toHaveBeenCalledWith(defaultSorted[0].dataField, defaultSorted[0].order);
});
});
});
describe('componentWillReceiveProps', () => {
let nextProps;
beforeEach(() => {
nextProps = { columns, store };
store.sortField = columns[1].dataField;
store.sortOrder = Const.SORT_DESC;
store.sortBy = sinon.stub();
});
it('should sorting again', () => {
wrapper.instance().componentWillReceiveProps(nextProps);
expect(store.sortBy.calledOnce).toBeTruthy();
});
});
});

View File

@ -1,109 +0,0 @@
import Store from '../../src/store';
import Const from '../../src/const';
describe('Store Base', () => {
let store;
let data;
beforeEach(() => {
data = [
{ id: 3, name: 'name2' },
{ id: 2, name: 'ABC' },
{ id: 4, name: '123tester' },
{ id: 1, name: '!@#' }
];
store = new Store('id');
store.data = data;
});
describe('initialize', () => {
it('should have correct initialize data', () => {
expect(store.sortOrder).toBeUndefined();
expect(store.sortField).toBeUndefined();
expect(store.data.length).toEqual(data.length);
});
});
describe('setSort', () => {
let dataField;
beforeEach(() => {
dataField = 'name';
});
it('should change sortField by dataField param', () => {
store.setSort({ dataField });
expect(store.sortField).toEqual(dataField);
});
it('should change sortOrder correctly when sortBy same dataField', () => {
store.setSort({ dataField });
expect(store.sortOrder).toEqual(Const.SORT_DESC);
store.setSort({ dataField });
expect(store.sortOrder).toEqual(Const.SORT_ASC);
});
it('should change sortOrder correctly when sortBy different dataField', () => {
store.setSort({ dataField });
expect(store.sortOrder).toEqual(Const.SORT_DESC);
dataField = 'id';
store.setSort({ dataField });
expect(store.sortOrder).toEqual(Const.SORT_DESC);
dataField = 'name';
store.setSort({ dataField });
expect(store.sortOrder).toEqual(Const.SORT_DESC);
});
it('should force assign sortOrder correctly if second argument is given', () => {
store.setSort({ dataField }, Const.SORT_DESC);
expect(store.sortOrder).toEqual(Const.SORT_DESC);
});
it('should force assign sortOrder correctly if third argument is given', () => {
store.setSort({ dataField }, undefined, Const.SORT_ASC);
expect(store.sortOrder).toEqual(Const.SORT_ASC);
});
});
describe('sortBy', () => {
let dataField;
beforeEach(() => {
dataField = 'name';
});
it('should have correct result after sortBy', () => {
store.sortBy({ dataField });
const result = store.data.map(e => e[dataField]).sort((a, b) => b - a);
store.data.forEach((e, i) => {
expect(e[dataField]).toEqual(result[i]);
});
});
});
describe('edit', () => {
it('should update a specified field correctly', () => {
const newValue = 'newValue';
const dataField = 'name';
const rowId = 2;
store.edit(rowId, dataField, newValue);
const row = store.data.find(d => d[store.keyField] === rowId);
expect(row[dataField]).toEqual(newValue);
});
it('should not throw any error even if rowId is not existing', () => {
expect(() => {
store.edit('123', 'name', 'value');
}).not.toThrow();
});
it('should throwing error if dataField is not existing', () => {
expect(() => {
store.edit(2, 'non_exist_field', 'value');
}).toThrow();
});
});
});

View File

@ -0,0 +1,32 @@
import { editCell } from '../../src/store/mutate';
describe('Mutate Function', () => {
const data = [
{ id: 3, name: 'name2' },
{ id: 2, name: 'ABC' },
{ id: 4, name: '123tester' },
{ id: 1, name: '!@#' }
];
const keyField = 'id';
describe('editCell', () => {
let rowId;
const editField = 'name';
const newValue = 'tester';
it('should edit successfully if row is existing', () => {
rowId = data[0][keyField];
editCell(data, keyField, rowId, editField, newValue);
expect(data[0][editField]).toEqual(newValue);
});
it('should not mutate cell if row is not existing', () => {
rowId = 100;
editCell(data, keyField, rowId, editField, newValue);
expect(data).toEqual(data);
});
});
});

View File

@ -1,5 +1,4 @@
import Store from '../../src/store';
import { getRowByRowId } from '../../src/store/rows';
import { getRowByRowId, matchRow } from '../../src/store/rows';
describe('Rows Function', () => {
const data = [
@ -9,22 +8,28 @@ describe('Rows Function', () => {
{ id: 1, name: '!@#' }
];
const keyField = 'id';
let store;
let fn;
beforeEach(() => {
store = new Store(keyField);
store.data = data;
fn = getRowByRowId(store);
});
describe('getRowByRowId', () => {
it('should returning correct row', () => {
expect(fn(2)).toEqual(data[1]);
expect(getRowByRowId(data, keyField, 2)).toEqual(data[1]);
});
it('should returning undefined if not existing', () => {
expect(fn(20)).not.toBeDefined();
expect(getRowByRowId(data, keyField, 20)).not.toBeDefined();
});
});
describe('matchRow', () => {
it('should return true if keyField and id is match', () => {
const row = data[0];
const fn = matchRow(keyField, row[keyField]);
expect(fn(row)).toBeTruthy();
});
it('should return false if keyField and id is not match', () => {
const row = data[0];
const fn = matchRow(keyField, 0);
expect(fn(row)).toBeFalsy();
});
});
});

View File

@ -1,10 +1,8 @@
import Store from '../../src/store';
import {
isSelectedAll,
isAnySelectedRow,
selectableKeys,
unSelectableKeys,
getSelectedRows
getSelectedRows,
getSelectionSummary
} from '../../src/store/selection';
describe('Selection Function', () => {
@ -15,90 +13,73 @@ describe('Selection Function', () => {
{ id: 1, name: '!@#' }
];
const keyField = 'id';
let store;
let skip;
let fn;
beforeEach(() => {
store = new Store(keyField);
store.data = data;
});
describe('isSelectedAll', () => {
it('should returning false when store.selected is not cover all rows', () => {
expect(isSelectedAll(store)).toBeFalsy();
store.selected = [data[0][keyField]];
expect(isSelectedAll(store)).toBeFalsy();
});
it('should returning true when store.selected is cover all rows', () => {
store.selected = data.map(d => d[keyField]);
expect(isSelectedAll(store)).toBeTruthy();
});
});
describe('isAnySelectedRow', () => {
it('should returning false if any store.selected is empty', () => {
fn = isAnySelectedRow(store);
expect(fn()).toBeFalsy();
});
it('should returning false if store.selected is have same key as skips', () => {
fn = isAnySelectedRow(store);
skip = [data[0][keyField]];
store.selected = [data[0][keyField]];
expect(fn(skip)).toBeFalsy();
});
it('should returning true if store.selected is not empty', () => {
store.selected = [data[0][keyField]];
fn = isAnySelectedRow(store);
expect(fn()).toBeTruthy();
});
it('should returning true if length of store.selected is bigger than skips', () => {
store.selected = [data[0][keyField], data[2][keyField]];
skip = [data[0][keyField]];
fn = isAnySelectedRow(store);
expect(fn(skip)).toBeTruthy();
});
});
describe('selectableKeys', () => {
beforeEach(() => {
fn = selectableKeys(store);
});
it('should returning all row keys if skip is empty', () => {
expect(fn()).toEqual(data.map(d => d[keyField]));
expect(selectableKeys(data, keyField)).toEqual(data.map(d => d[keyField]));
});
it('should returngin row keys expect the skip', () => {
skip = [data[1][keyField]];
expect(fn(skip)).toHaveLength(data.length - skip.length);
expect(selectableKeys(data, keyField, skip)).toHaveLength(data.length - skip.length);
});
});
describe('unSelectableKeys', () => {
it('should returning empty array if skip is empty', () => {
fn = unSelectableKeys(store);
expect(fn()).toHaveLength(0);
expect(unSelectableKeys()).toHaveLength(0);
});
it('should returning array which must contain skip', () => {
skip = [data[1][keyField]];
store.selected = data.map(d => d[keyField]);
fn = unSelectableKeys(store);
expect(fn(skip)).toHaveLength(skip.length);
const selected = data.map(d => d[keyField]);
expect(unSelectableKeys(selected, skip)).toHaveLength(skip.length);
});
});
describe('getSelectedRows', () => {
it('should returning rows object correctly', () => {
store.selected = data.map(d => d[keyField]);
const result = getSelectedRows(store);
expect(result).toHaveLength(store.selected.length);
expect(result).toEqual(store.data);
const selected = data.map(d => d[keyField]);
const result = getSelectedRows(data, keyField, selected);
expect(result).toHaveLength(selected.length);
expect(result).toEqual(data);
});
});
describe('getSelectionSummary', () => {
let result;
describe('if selected argument is able to cover all the data argument', () => {
it('should return an obj which allRowsSelected is true and allRowsNotSelected is false', () => {
const selected = data.map(d => d[keyField]);
result = getSelectionSummary(data, keyField, selected);
expect(result).toEqual({
allRowsSelected: true,
allRowsNotSelected: false
});
});
});
describe('if selected argument empty', () => {
it('should return an obj which allRowsSelected is false but allRowsNotSelected is true', () => {
result = getSelectionSummary(data, keyField);
expect(result).toEqual({
allRowsSelected: false,
allRowsNotSelected: true
});
});
});
describe('if selected argument is only cover partial data', () => {
it('should return an obj which allRowsSelected and allRowsNotSelected both are false', () => {
const selected = [1, 2];
result = getSelectionSummary(data, keyField, selected);
expect(result).toEqual({
allRowsSelected: false,
allRowsNotSelected: false
});
});
});
});
});

View File

@ -1,6 +1,5 @@
import sinon from 'sinon';
import Store from '../../src/store';
import { sort, nextOrder } from '../../src/store/sort';
import Const from '../../src/const';
@ -12,18 +11,17 @@ describe('Sort Function', () => {
{ id: 1, name: '!@#' }
];
let store;
describe('sort', () => {
beforeEach(() => {
store = new Store('id');
store.data = data;
});
const sortColumn = {
dataField: 'id',
text: 'ID'
};
let sortOrder;
let result;
it('should sort array with ASC order correctly', () => {
store.sortField = 'id';
store.sortOrder = Const.SORT_ASC;
const result = sort(store)();
sortOrder = Const.SORT_ASC;
result = sort(data, sortOrder, sortColumn);
expect(result.length).toEqual(data.length);
const sortedArray = data.map(e => e.id).sort((a, b) => a - b);
@ -33,9 +31,8 @@ describe('Sort Function', () => {
});
it('should sort array with DESC order correctly', () => {
store.sortField = 'id';
store.sortOrder = Const.SORT_DESC;
const result = sort(store)();
sortOrder = Const.SORT_DESC;
result = sort(data, sortOrder, sortColumn);
expect(result.length).toEqual(data.length);
const sortedArray = data.map(e => e.id).sort((a, b) => b - a);
@ -46,35 +43,49 @@ describe('Sort Function', () => {
it('should call custom sort function when sortFunc given', () => {
const sortFunc = sinon.stub().returns(1);
store.sortField = 'id';
store.sortOrder = Const.SORT_DESC;
sort(store)(sortFunc);
sortOrder = Const.SORT_DESC;
sort(data, sortOrder, { ...sortColumn, sortFunc });
expect(sortFunc.callCount).toBe(6);
});
});
describe('nextOrder', () => {
beforeEach(() => {
store = new Store('id');
store.data = data;
const currentSortColumn = {
dataField: 'name',
text: 'Product Name'
};
it('should return correcly order when current sortField is not eq next sort field', () => {
const nextSort = {
sortColumn: {
dataField: 'id',
text: 'ID'
},
sortOrder: Const.SORT_DESC
};
expect(nextOrder(currentSortColumn, nextSort)).toBe(Const.SORT_DESC);
});
it('should return correcly order when store.sortField is not eq next sort field', () => {
expect(nextOrder(store)('name')).toBe(Const.SORT_DESC);
it('should return correcly order if even next sort column is undefined', () => {
expect(nextOrder(currentSortColumn, {})).toBe(Const.SORT_DESC);
});
it('should return correcly order when store.sortField is not eq next sort field and default sort direction is given', () => {
expect(nextOrder(store)('name', undefined, Const.SORT_ASC)).toBe(Const.SORT_ASC);
it('should return correcly order when current sortField is not eq next sort field and default sort direction is given', () => {
const nextSort = {
sortColumn: {
dataField: 'id',
text: 'ID'
},
sortOrder: Const.SORT_DESC
};
expect(nextOrder(currentSortColumn, nextSort, Const.SORT_ASC)).toBe(Const.SORT_ASC);
});
it('should return correcly order when store.sortField is eq next sort field', () => {
store.sortField = 'name';
store.sortOrder = Const.SORT_DESC;
expect(nextOrder(store)('name')).toBe(Const.SORT_ASC);
});
it('should return correcly order when order is specified', () => {
expect(nextOrder(store)('name', Const.SORT_ASC)).toBe(Const.SORT_ASC);
it('should return correcly order when current sortField is eq next sort field', () => {
const nextSort = {
sortColumn: currentSortColumn,
sortOrder: Const.SORT_ASC
};
expect(nextOrder(currentSortColumn, nextSort)).toBe(Const.SORT_DESC);
});
});
});

View File

@ -1,16 +1,5 @@
import Store from '../../src/store';
export const extendTo = Base =>
class MockComponent extends Base {
constructor(props) {
super(props);
const { data } = props;
this.store = new Store(props.keyField);
this.store.data = data;
this.state = { data };
}
render() { return null; }
};