patch tests for refining remote cell edit

This commit is contained in:
AllenFang 2018-01-04 23:21:17 +08:00
parent a50a12426a
commit beafef9661
10 changed files with 351 additions and 444 deletions

View File

@ -1,75 +0,0 @@
/* eslint no-unused-vars: 0 */
/* eslint arrow-body-style: 0 */
import React, { Component } from 'react';
import BootstrapTable from 'react-bootstrap-table2';
import Code from 'components/common/code-block';
import { productsGenerator, sleep } from 'utils/common';
const products = productsGenerator();
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const sourceCode = `\
class CellEditWithPromise extends Component {
handleCellEditing = (rowId, dataField, newValue) => {
return sleep(1000).then(() => {
if (dataField === 'price' && (newValue < 2000 || isNaN(newValue))) {
throw new Error('Product Price should bigger than $2000');
}
});
}
render() {
const cellEdit = {
mode: 'click',
blurToSave: true,
onUpdate: this.handleCellEditing
};
return (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } cellEdit={ cellEdit } />
<Code>{ sourceCode }</Code>
</div>
);
}
}
`;
class CellEditWithPromise extends Component {
handleCellEditing = (rowId, dataField, newValue) => {
return sleep(1000).then(() => {
if (dataField === 'price' && (newValue < 2000 || isNaN(newValue))) {
throw new Error('Product Price should bigger than $2000');
}
});
}
render() {
const cellEdit = {
mode: 'click',
blurToSave: true,
onUpdate: this.handleCellEditing
};
return (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } cellEdit={ cellEdit } />
<Code>{ sourceCode }</Code>
</div>
);
}
}
export default CellEditWithPromise;

View File

@ -1,212 +0,0 @@
/* eslint no-unused-vars: 0 */
/* eslint react/prop-types: 0 */
/* eslint arrow-body-style: 0 */
/* eslint consistent-return: 0 */
/* eslint no-class-assign: 0 */
import React, { Component } from 'react';
import thunk from 'redux-thunk';
import { Provider, connect } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import BootstrapTable from 'react-bootstrap-table2';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const sourceCode = `\
/////////////////////// Action Creator ///////////////////////
const setErrorMessage = (errorMessage = null) => {
return { type: 'SET_ERR_MESSAGE', errorMessage };
};
// Async Action, using redux-thunk
const cellEditingAsync = (rowId, dataField, newValue) => {
return (dispatch) => {
setTimeout(() => {
if (dataField === 'price' && (newValue < 2000 || isNaN(newValue))) {
dispatch(setErrorMessage('Product Price should bigger than $2000'));
} else {
dispatch({ type: 'ADD_SUCCESS', rowId, dataField, newValue });
}
}, 1200);
};
};
/////////////////////// Component ///////////////////////
class CellEditWithRedux extends Component {
// dispatch a async action
handleCellEditing = (rowId, dataField, newValue) => {
this.props.dispatch(cellEditingAsync(rowId, dataField, newValue));
return false;
}
handleErrorMsgDisappear = () => {
this.props.dispatch(setErrorMessage());
}
render() {
const cellEdit = {
mode: 'click',
editing: this.props.cellEditing,
errorMessage: this.props.errorMessage,
onUpdate: this.handleCellEditing,
onErrorMessageDisappear: this.handleErrorMsgDisappear
};
return (
<div>
<BootstrapTable keyField="id" data={ this.props.data } columns={ columns } cellEdit={ cellEdit } />
<Code>{ sourceCode }</Code>
</div>
);
}
}
// connect
CellEditWithRedux = connect(state => state)(CellEditWithRedux);
/////////////////////// Reducer ///////////////////////
// initial state object and simple reducers
const initialState = {
data: productsGenerator(),
cellEditing: false,
errorMessage: null
};
const reducers = (state, action) => {
switch (action.type) {
case 'ADD_SUCCESS': {
const { rowId, dataField, newValue } = action;
const data = [...state.data];
const rowIndex = data.findIndex(r => r.id === rowId);
data[rowIndex][dataField] = newValue;
return {
data,
cellEditing: false,
errorMessage: null
};
}
case 'SET_ERR_MESSAGE': {
const { errorMessage } = action;
return {
...state,
cellEditing: true,
errorMessage
};
}
default: {
return { ...state };
}
}
};
/////////////////////// Index ///////////////////////
const store = createStore(reducers, initialState, applyMiddleware(thunk));
const Index = () => (
<Provider store={store}>
<CellEditWithRedux />
</Provider>
);
`;
const setErrorMessage = (errorMessage = null) => {
return { type: 'SET_ERR_MESSAGE', errorMessage };
};
// Async Action, using redux-thunk
const cellEditingAsync = (rowId, dataField, newValue) => {
return (dispatch) => {
setTimeout(() => {
if (dataField === 'price' && (newValue < 2000 || isNaN(newValue))) {
dispatch(setErrorMessage('Product Price should bigger than $2000'));
} else {
dispatch({ type: 'ADD_SUCCESS', rowId, dataField, newValue });
}
}, 1200);
};
};
class CellEditWithRedux extends Component {
// dispatch a async action
handleCellEditing = (rowId, dataField, newValue) => {
this.props.dispatch(cellEditingAsync(rowId, dataField, newValue));
return false;
}
handleErrorMsgDisappear = () => {
this.props.dispatch(setErrorMessage());
}
render() {
const cellEdit = {
mode: 'click',
editing: this.props.cellEditing,
errorMessage: this.props.errorMessage,
onUpdate: this.handleCellEditing,
onErrorMessageDisappear: this.handleErrorMsgDisappear
};
return (
<div>
<BootstrapTable keyField="id" data={ this.props.data } columns={ columns } cellEdit={ cellEdit } />
<Code>{ sourceCode }</Code>
</div>
);
}
}
// connect
CellEditWithRedux = connect(state => state)(CellEditWithRedux);
// initial state object and simple reducers
const initialState = {
data: productsGenerator(),
cellEditing: false,
errorMessage: null
};
const reducers = (state, action) => {
switch (action.type) {
case 'ADD_SUCCESS': {
const { rowId, dataField, newValue } = action;
const data = JSON.parse(JSON.stringify(state.data));
const rowIndex = data.findIndex(r => r.id === rowId);
data[rowIndex][dataField] = newValue;
return {
data,
cellEditing: false,
errorMessage: null
};
}
case 'SET_ERR_MESSAGE': {
const { errorMessage } = action;
return {
...state,
cellEditing: true,
errorMessage
};
}
default: {
return { ...state };
}
}
};
const store = createStore(reducers, initialState, applyMiddleware(thunk));
const Index = () => (
<Provider store={ store }>
<CellEditWithRedux />
</Provider>
);
export default Index;

View File

@ -0,0 +1,165 @@
import React from 'react';
import PropTypes from 'prop-types';
import BootstrapTable from 'react-bootstrap-table2';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const products = productsGenerator();
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const sourceCode = `\
const RemoteCellEdit = (props) => {
const cellEdit = {
mode: 'click',
errorMessage: props.errorMessage
};
return (
<div>
<BootstrapTable
remote={ { cellEdit: true } }
keyField="id"
data={ props.data }
columns={ columns }
cellEdit={ cellEdit }
onTableChange={ props.onTableChange }
/>
<Code>{ sourceCode }</Code>
</div>
);
};
RemoteCellEdit.propTypes = {
data: PropTypes.array.isRequired,
onTableChange: PropTypes.func.isRequired,
errorMessage: PropTypes.string.isRequired
};
class Container extends React.Component {
constructor(props) {
super(props);
this.state = {
data: products,
errorMessage: null
};
}
handleTableChange = (type, { data, cellEdit: { rowId, dataField, newValue } }) => {
setTimeout(() => {
if (newValue === 'test' && dataField === 'name') {
this.setState(() => ({
data,
errorMessage: 'Oops, product name shouldn't be "test"'
}));
} else {
const result = data.map((row) => {
if (row.id === rowId) {
const newRow = { ...row };
newRow[dataField] = newValue;
return newRow;
}
return row;
});
this.setState(() => ({
data: result,
errorMessage: null
}));
}
}, 2000);
}
render() {
return (
<RemoteCellEdit
data={ this.state.data }
errorMessage={ this.state.errorMessage }
onTableChange={ this.handleTableChange }
/>
);
}
}
`;
const RemoteCellEdit = (props) => {
const cellEdit = {
mode: 'click',
errorMessage: props.errorMessage
};
return (
<div>
<BootstrapTable
remote={ { cellEdit: true } }
keyField="id"
data={ props.data }
columns={ columns }
cellEdit={ cellEdit }
onTableChange={ props.onTableChange }
/>
<Code>{ sourceCode }</Code>
</div>
);
};
RemoteCellEdit.propTypes = {
data: PropTypes.array.isRequired,
onTableChange: PropTypes.func.isRequired,
errorMessage: PropTypes.string.isRequired
};
class Container extends React.Component {
constructor(props) {
super(props);
this.state = {
data: products,
errorMessage: null
};
}
handleTableChange = (type, { data, cellEdit: { rowId, dataField, newValue } }) => {
setTimeout(() => {
if (newValue === 'test' && dataField === 'name') {
this.setState(() => ({
data,
errorMessage: 'Oops, product name shouldn\'t be "test"'
}));
} else {
const result = data.map((row) => {
if (row.id === rowId) {
const newRow = { ...row };
newRow[dataField] = newValue;
return newRow;
}
return row;
});
this.setState(() => ({
data: result,
errorMessage: null
}));
}
}, 2000);
}
render() {
return (
<RemoteCellEdit
data={ this.state.data }
errorMessage={ this.state.errorMessage }
onTableChange={ this.handleTableChange }
/>
);
}
}
export default Container;

View File

@ -63,8 +63,6 @@ import CellEditHooks from 'examples/cell-edit/cell-edit-hooks-table';
import CellEditValidator from 'examples/cell-edit/cell-edit-validator-table';
import CellEditStyleTable from 'examples/cell-edit/cell-edit-style-table';
import CellEditClassTable from 'examples/cell-edit/cell-edit-class-table';
import CellEditWithPromise from 'examples/cell-edit/cell-edit-with-promise-table';
import CellEditWithRedux from 'examples/cell-edit/cell-edit-with-redux-table';
// work on row selection
import SingleSelectionTable from 'examples/row-selection/single-selection';
@ -91,6 +89,7 @@ import TableOverlay from 'examples/loading-overlay/table-overlay';
import RemoteSort from 'examples/remote/remote-sort';
import RemoteFilter from 'examples/remote/remote-filter';
import RemotePaginationTable from 'examples/remote/remote-pagination';
import RemoteCellEdit from 'examples/remote/remote-celledit';
import RemoteAll from 'examples/remote/remote-all';
// css style
@ -165,9 +164,7 @@ storiesOf('Cell Editing', module)
.add('Rich Hook Functions', () => <CellEditHooks />)
.add('Validation', () => <CellEditValidator />)
.add('Custom Cell Style When Editing', () => <CellEditStyleTable />)
.add('Custom Cell Classes When Editing', () => <CellEditClassTable />)
.add('Async Cell Editing(Promise)', () => <CellEditWithPromise />)
.add('Async Cell Editing(Redux)', () => <CellEditWithRedux />);
.add('Custom Cell Classes When Editing', () => <CellEditClassTable />);
storiesOf('Row Selection', module)
.add('Single Selection', () => <SingleSelectionTable />)
@ -194,4 +191,5 @@ storiesOf('Remote', module)
.add('Remote Sort', () => <RemoteSort />)
.add('Remote Filter', () => <RemoteFilter />)
.add('Remote Pagination', () => <RemotePaginationTable />)
.add('Remote Cell Editing', () => <RemoteCellEdit />)
.add('Remote All', () => <RemoteAll />);

View File

@ -28,7 +28,7 @@ describe('Wrapper', () => {
onTableChangeCB.reset();
});
const createTableProps = () => {
const createTableProps = (props) => {
const tableProps = {
keyField: 'id',
columns: [{
@ -47,7 +47,8 @@ describe('Wrapper', () => {
filter: filter(),
_,
store: new Store('id'),
onTableChange: onTableChangeCB
onTableChange: onTableChangeCB,
...props
};
tableProps.store.data = data;
return tableProps;
@ -105,6 +106,17 @@ describe('Wrapper', () => {
});
});
describe('when props.isDataChanged is true and remote is enable', () => {
beforeEach(() => {
nextProps = createTableProps({ isDataChanged: true });
instance.componentWillReceiveProps(nextProps);
});
it('should setting isDataChanged as true', () => {
expect(instance.state.isDataChanged).toBeTruthy();
});
});
describe('when props.store.filters is different from current state.currFilters', () => {
beforeEach(() => {
nextProps = createTableProps();

View File

@ -31,13 +31,10 @@ describe('CellEditWrapper', () => {
};
const keyField = 'id';
let onUpdateCellCB = sinon.stub();
const store = new Store(keyField);
store.data = data;
const CellEditWrapper = wrapperFactory(Container, {
onUpdateCell: onUpdateCellCB
});
const CellEditWrapper = wrapperFactory(Container);
beforeEach(() => {
wrapper = shallow(
@ -60,24 +57,24 @@ describe('CellEditWrapper', () => {
expect(wrapper.state().ridx).toBeNull();
expect(wrapper.state().cidx).toBeNull();
expect(wrapper.state().message).toBeNull();
expect(wrapper.state().editing).toBeFalsy();
expect(wrapper.state().isDataChanged).toBeFalsy();
});
it('should inject correct props to base component', () => {
expect(wrapper.props().onCellUpdate).toBeDefined();
expect(wrapper.props().onStartEditing).toBeDefined();
expect(wrapper.props().onEscapeEditing).toBeDefined();
expect(wrapper.props().isDataChanged).toBe(wrapper.state().isDataChanged);
expect(wrapper.props().currEditCell).toBeDefined();
expect(wrapper.props().currEditCell.ridx).toBeNull();
expect(wrapper.props().currEditCell.cidx).toBeNull();
expect(wrapper.props().currEditCell.message).toBeNull();
expect(wrapper.props().currEditCell.editing).toBeFalsy();
});
describe('when receive new cellEdit prop', () => {
const spy = jest.spyOn(CellEditWrapper.prototype, 'escapeEditing');
describe('and cellEdit.editing is false', () => {
describe('and cellEdit is not work on remote', () => {
beforeEach(() => {
wrapper = shallow(
<CellEditWrapper
@ -88,54 +85,69 @@ describe('CellEditWrapper', () => {
store={ store }
/>
);
wrapper.setProps({ cellEdit: { ...cellEdit, editing: false } });
wrapper.setProps({ cellEdit: { ...cellEdit } });
});
it('should call escapeEditing', () => {
expect(spy).toHaveBeenCalled();
});
it('should have correct state', () => {
expect(wrapper.state().ridx).toBeNull();
expect(wrapper.state().cidx).toBeNull();
expect(wrapper.state().message).toBeNull();
expect(wrapper.state().editing).toBeFalsy();
it('should always setting state.isDataChanged as false', () => {
expect(wrapper.state().isDataChanged).toBeFalsy();
});
});
describe('and cellEdit.editing is true', () => {
const errorMessage = 'test';
describe('and cellEdit is work on remote', () => {
let errorMessage;
const ridx = 1;
const cidx = 2;
beforeEach(() => {
wrapper = shallow(
<CellEditWrapper
keyField={ keyField }
data={ data }
columns={ columns }
cellEdit={ cellEdit }
store={ store }
/>
);
wrapper.setState({ ridx, cidx, editing: true });
wrapper.setProps({ cellEdit: { ...cellEdit, editing: true, errorMessage } });
describe('and cellEdit.errorMessage is defined', () => {
beforeEach(() => {
wrapper = shallow(
<CellEditWrapper
remote={ { cellEdit: true } }
keyField={ keyField }
data={ data }
columns={ columns }
cellEdit={ cellEdit }
store={ store }
/>
);
errorMessage = 'test';
wrapper.setState({ ridx, cidx });
wrapper.setProps({ cellEdit: { ...cellEdit, errorMessage } });
});
it('should setting correct state', () => {
expect(wrapper.state().ridx).toEqual(ridx);
expect(wrapper.state().cidx).toEqual(cidx);
expect(wrapper.state().isDataChanged).toBeFalsy();
expect(wrapper.state().message).toEqual(errorMessage);
});
});
it('should have correct state', () => {
expect(wrapper.state().ridx).toEqual(ridx);
expect(wrapper.state().cidx).toEqual(cidx);
expect(wrapper.state().editing).toBeTruthy();
expect(wrapper.state().message).toEqual(errorMessage);
});
});
});
describe('and cellEdit.errorMessage is undefined', () => {
beforeEach(() => {
wrapper = shallow(
<CellEditWrapper
remote={ { cellEdit: true } }
keyField={ keyField }
data={ data }
columns={ columns }
cellEdit={ cellEdit }
store={ store }
/>
);
errorMessage = null;
wrapper.setState({ ridx, cidx });
wrapper.setProps({ cellEdit: { ...cellEdit, errorMessage } });
});
describe('call updateEditingWithErr function', () => {
it('should set state.message correctly', () => {
const message = 'test';
wrapper.instance().updateEditingWithErr(message);
expect(wrapper.state().message).toEqual(message);
it('should setting correct state', () => {
expect(wrapper.state().isDataChanged).toBeTruthy();
});
it('should escape current editing', () => {
expect(spy).toHaveBeenCalled();
});
});
});
});
@ -144,7 +156,6 @@ describe('CellEditWrapper', () => {
wrapper.instance().escapeEditing();
expect(wrapper.state().ridx).toBeNull();
expect(wrapper.state().cidx).toBeNull();
expect(wrapper.state().editing).toBeFalsy();
});
});
@ -155,7 +166,7 @@ describe('CellEditWrapper', () => {
wrapper.instance().startEditing(ridx, cidx);
expect(wrapper.state().ridx).toEqual(ridx);
expect(wrapper.state().cidx).toEqual(cidx);
expect(wrapper.state().editing).toBeTruthy();
expect(wrapper.state().isDataChanged).toBeFalsy();
});
describe('if selectRow.clickToSelect is defined', () => {
@ -199,7 +210,6 @@ describe('CellEditWrapper', () => {
wrapper.instance().startEditing(ridx, cidx);
expect(wrapper.state().ridx).toEqual(ridx);
expect(wrapper.state().cidx).toEqual(cidx);
expect(wrapper.state().editing).toBeTruthy();
});
});
});
@ -210,7 +220,7 @@ describe('CellEditWrapper', () => {
expect(wrapper.state().ridx).toBeNull();
expect(wrapper.state().cidx).toBeNull();
expect(wrapper.state().message).toBeNull();
expect(wrapper.state().editing).toBeFalsy();
expect(wrapper.state().isDataChanged).toBeTruthy();
});
});
@ -219,35 +229,75 @@ describe('CellEditWrapper', () => {
const column = columns[1];
const newValue = 'new name';
beforeEach(() => {
wrapper = shallow(
<CellEditWrapper
keyField={ keyField }
data={ data }
columns={ columns }
cellEdit={ cellEdit }
store={ store }
/>
);
wrapper.instance().handleCellUpdate(row, column, newValue);
describe('when cell edit is work on remote', () => {
const spy = jest.spyOn(CellEditWrapper.prototype, 'handleCellChange');
const onTableChangeCB = jest.fn();
beforeEach(() => {
wrapper = shallow(
<CellEditWrapper
remote={ { cellEdit: true } }
keyField={ keyField }
data={ data }
columns={ columns }
cellEdit={ cellEdit }
onTableChange={ onTableChangeCB }
store={ store }
/>
);
wrapper.instance().handleCellUpdate(row, column, newValue);
});
it('should calling handleCellChange correctly', () => {
expect(spy).toHaveBeenCalled();
expect(spy.mock.calls).toHaveLength(1);
expect(spy.mock.calls[0]).toHaveLength(3);
expect(spy.mock.calls[0][0]).toEqual(row[keyField]);
expect(spy.mock.calls[0][1]).toEqual(column.dataField);
expect(spy.mock.calls[0][2]).toEqual(newValue);
});
});
it('should calling onUpdateCell callback correctly', () => {
expect(onUpdateCellCB.callCount).toBe(1);
expect(onUpdateCellCB.calledWith(row.id, column.dataField, newValue)).toBe(true);
});
describe('when cell edit is not work on remote', () => {
const spyOnCompleteEditing = jest.spyOn(CellEditWrapper.prototype, 'completeEditing');
const spyOnStoreEdit = jest.spyOn(Store.prototype, 'edit');
describe('when onUpdateCell function return true', () => {
const spy = jest.spyOn(CellEditWrapper.prototype, 'completeEditing');
beforeEach(() => {
wrapper = shallow(
<CellEditWrapper
keyField={ keyField }
data={ data }
columns={ columns }
cellEdit={ cellEdit }
store={ store }
/>
);
wrapper.instance().handleCellUpdate(row, column, newValue);
});
afterEach(() => {
spyOnStoreEdit.mockReset();
spyOnCompleteEditing.mockReset();
});
it('should calling props.store.edit', () => {
expect(spyOnStoreEdit).toHaveBeenCalled();
expect(spyOnStoreEdit.mock.calls).toHaveLength(1);
expect(spyOnStoreEdit.mock.calls[0]).toHaveLength(3);
expect(spyOnStoreEdit.mock.calls[0][0]).toEqual(row[keyField]);
expect(spyOnStoreEdit.mock.calls[0][1]).toEqual(column.dataField);
expect(spyOnStoreEdit.mock.calls[0][2]).toEqual(newValue);
});
it('should calling completeEditing function', () => {
expect(spy).toHaveBeenCalled();
expect(spyOnCompleteEditing).toHaveBeenCalled();
});
describe('if cellEdit.afterSaveCell prop defined', () => {
const aftereSaveCellCallBack = sinon.stub();
beforeEach(() => {
cellEdit.beforeSaveCell = aftereSaveCellCallBack;
cellEdit.afterSaveCell = aftereSaveCellCallBack;
wrapper = shallow(
<CellEditWrapper
keyField={ keyField }
@ -269,28 +319,6 @@ describe('CellEditWrapper', () => {
});
});
describe('when onUpdateCell function return false', () => {
const spy = jest.spyOn(CellEditWrapper.prototype, 'completeEditing');
beforeEach(() => {
onUpdateCellCB = sinon.stub().returns(false);
wrapper = shallow(
<CellEditWrapper
keyField={ keyField }
data={ data }
columns={ columns }
cellEdit={ cellEdit }
store={ store }
/>
);
wrapper.instance().handleCellUpdate(row, column, newValue);
});
it('shouldn\'t calling completeEditing function', () => {
expect(spy).toHaveBeenCalled();
});
});
describe('if cellEdit.beforeSaveCell prop defined', () => {
const beforeSaveCellCallBack = sinon.stub();
beforeEach(() => {

View File

@ -1,12 +1,10 @@
/* eslint react/prefer-stateless-function: 0 */
/* eslint react/no-multi-comp: 0 */
import React from 'react';
import sinon from 'sinon';
import { shallow } from 'enzyme';
import BootstrapTable from '../src/bootstrap-table';
import Container from '../src';
import { getRowByRowId } from '../src/store/rows';
describe('container', () => {
let wrapper;
@ -79,63 +77,6 @@ describe('container', () => {
it('should render BootstrapTable component successfully', () => {
expect(wrapper.dive().find(BootstrapTable)).toHaveLength(1);
});
describe('for handleUpdateCell function', () => {
const rowId = data[1].id;
const dataField = columns[1].dataField;
const newValue = 'tester';
let result;
describe('when cellEdit.onUpdate callback is not defined', () => {
beforeEach(() => {
result = wrapper.instance().handleUpdateCell(rowId, dataField, newValue);
});
it('should return true', () => {
expect(result).toBeTruthy();
});
it('should update store data directly', () => {
const store = wrapper.instance().store;
const row = getRowByRowId(store)(rowId);
expect(row[dataField]).toEqual(newValue);
});
});
describe('when cellEdit.onUpdate callback is define and which return false', () => {
beforeEach(() => {
cellEdit.onUpdate = sinon.stub().returns(false);
wrapper = shallow(
<Container
keyField={ keyField }
data={ data }
columns={ columns }
cellEdit={ cellEdit }
/>
);
result = wrapper.instance().handleUpdateCell(rowId, dataField, newValue);
});
it('should calling cellEdit.onUpdate callback correctly', () => {
expect(cellEdit.onUpdate.callCount).toBe(1);
expect(cellEdit.onUpdate.calledWith(rowId, dataField, newValue)).toBe(true);
});
it('should return false', () => {
expect(result).toBeFalsy();
});
it('shouldn\'t update store data', () => {
const store = wrapper.instance().store;
const row = getRowByRowId(store)(rowId);
expect(row[dataField]).not.toEqual(newValue);
});
});
// We need refactoring handleUpdateCell function for handling promise firstly
// then it will be much easier to test
describe.skip('when cellEdit.onUpdate callback is define and which return a Promise', () => {});
});
});
describe('when selectRow prop is defined', () => {

View File

@ -93,7 +93,6 @@ describe('TableResolver', () => {
const expectNonEditableRows = [1, 2];
const cellEdit = {
mode: Const.DBCLICK_TO_CELL_EDIT,
onUpdate: sinon.stub(),
blurToSave: true,
beforeSaveCell: sinon.stub(),
afterSaveCell: sinon.stub(),

View File

@ -134,6 +134,58 @@ describe('remoteResolver', () => {
});
});
describe('isRemoteCellEdit', () => {
describe('when remote is false', () => {
beforeEach(() => {
shallowContainer();
});
it('should return false', () => {
expect(wrapper.instance().isRemoteCellEdit()).toBeFalsy();
});
});
describe('when remote is true', () => {
beforeEach(() => {
shallowContainer({ remote: true });
});
it('should return true', () => {
expect(wrapper.instance().isRemoteCellEdit()).toBeTruthy();
});
});
describe('when remote.cellEdit is true', () => {
beforeEach(() => {
shallowContainer({ remote: { cellEdit: true } });
});
it('should return true', () => {
expect(wrapper.instance().isRemoteCellEdit()).toBeTruthy();
});
});
});
describe('handleCellChange', () => {
const onTableChangeCB = sinon.stub();
const rowId = 1;
const dataField = 'name';
const newValue = 'test';
beforeEach(() => {
onTableChangeCB.reset();
shallowContainer({ onTableChange: onTableChangeCB });
wrapper.instance().handleCellChange(rowId, dataField, newValue);
});
it('should calling props.onTableChange correctly', () => {
const cellEdit = { rowId, dataField, newValue };
expect(onTableChangeCB.calledOnce).toBeTruthy();
expect(onTableChangeCB.calledWith(
'cellEdit', wrapper.instance().getNewestState({ cellEdit }))).toBeTruthy();
});
});
describe('handleSortChange', () => {
const onTableChangeCB = sinon.stub();
beforeEach(() => {

View File

@ -273,7 +273,6 @@ describe('Row', () => {
cellEdit.cidx = editingColIndex;
cellEdit.onUpdate = sinon.stub();
cellEdit.onEscape = sinon.stub();
cellEdit.onUpdate = sinon.stub();
wrapper = shallow(
<Row
{ ...mockBodyResolvedProps }