From 985a1713ae4ff294dbf5cc8da674adaae66e07c2 Mon Sep 17 00:00:00 2001 From: Allen Date: Thu, 26 Oct 2017 01:35:09 -0500 Subject: [PATCH] fix #111 * implement selectRow.clickToSelect and selectRow.clickToEdit * add selectRow.clickToSelect and selectRow.clickToEdit stories * add clickToSelect to row selection examples for easier to select row * refine selectRow.nonSelectable * patch tests for selectRow.clickToSelect and selectRow.clickToEdit * patch docs for selectRow.clickToSelect and selectRow.clickToEdit --- docs/row-selection.md | 26 +++ .../click-to-select-with-cell-edit.js | 65 ++++++ .../examples/row-selection/click-to-select.js | 55 +++++ .../row-selection/multiple-selection.js | 14 +- .../row-selection/non-selectable-rows.js | 2 + .../row-selection/selection-bgcolor.js | 4 + .../examples/row-selection/selection-class.js | 4 + .../examples/row-selection/selection-style.js | 4 + .../row-selection/single-selection.js | 14 +- .../stories/index.js | 4 + packages/react-bootstrap-table2/src/body.js | 6 +- .../src/bootstrap-table.js | 2 + .../src/cell-edit/editing-cell.js | 13 ++ .../src/cell-edit/wrapper.js | 19 +- packages/react-bootstrap-table2/src/const.js | 3 +- packages/react-bootstrap-table2/src/row.js | 192 +++++++++++------- packages/react-bootstrap-table2/src/utils.js | 27 ++- .../react-bootstrap-table2/test/body.test.js | 24 +++ .../test/cell-edit/wrapper.test.js | 51 ++++- .../react-bootstrap-table2/test/row.test.js | 162 ++++++++++++++- 20 files changed, 588 insertions(+), 103 deletions(-) create mode 100644 packages/react-bootstrap-table2-example/examples/row-selection/click-to-select-with-cell-edit.js create mode 100644 packages/react-bootstrap-table2-example/examples/row-selection/click-to-select.js diff --git a/docs/row-selection.md b/docs/row-selection.md index 9726ce2..832ef1d 100644 --- a/docs/row-selection.md +++ b/docs/row-selection.md @@ -13,6 +13,8 @@ The following are available properties in `selectRow`: * [classes)](#classes) * [bgColor](#bgColor) * [nonSelectable)](#nonSelectable) +* [clickToSelect)](#clickToSelect) +* [clickToEdit](#clickToEdit) #### Optional @@ -118,4 +120,28 @@ const selectRow = { mode: 'checkbox', nonSelectable: [1, 3 ,5] }; +``` + +## selectRow.clickToSelect - [Bool] +Able to select row when clicking on row. + +```js +const selectRow = { + mode: 'checkbox', + clickToSelect: true +}; +``` + +> Note: if you also enable [cellEdit](./cell-edit.md), the `selectRow.clickToSelect` will deactivate the functionality of cell editing +> If you want to click on row to select row and edit cell simultaneously, you are suppose to enable [`selectRow.clickToEdit`](#clickToEdit) + +## selectRow.clickToEdit - [Bool] +Able to click to edit cell and select row + +```js +const selectRow = { + mode: 'checkbox', + clickToSelect: true + clickToEdit: true +}; ``` \ No newline at end of file diff --git a/packages/react-bootstrap-table2-example/examples/row-selection/click-to-select-with-cell-edit.js b/packages/react-bootstrap-table2-example/examples/row-selection/click-to-select-with-cell-edit.js new file mode 100644 index 0000000..cc0c1fe --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/row-selection/click-to-select-with-cell-edit.js @@ -0,0 +1,65 @@ +import React from 'react'; + +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 selectRow = { + mode: 'checkbox', + clickToSelect: true, + clickToEdit: true +}; + +const cellEdit = { + mode: 'click' +}; + +const sourceCode = `\ +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'price', + text: 'Product Price' +}]; + +const selectRow = { + mode: 'checkbox', + clickToSelect: true, + clickToEdit: true // Click to edit cell also +}; + +const cellEdit = { + mode: 'click' +}; + + +`; + +export default () => ( +
+ + { sourceCode } +
+); diff --git a/packages/react-bootstrap-table2-example/examples/row-selection/click-to-select.js b/packages/react-bootstrap-table2-example/examples/row-selection/click-to-select.js new file mode 100644 index 0000000..b792b43 --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/row-selection/click-to-select.js @@ -0,0 +1,55 @@ +import React from 'react'; + +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 selectRow = { + mode: 'checkbox', + clickToSelect: true +}; + +const sourceCode = `\ +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'price', + text: 'Product Price' +}]; + +const selectRow = { + mode: 'checkbox', + clickToSelect: true +}; + + +`; + +export default () => ( +
+ + { sourceCode } +
+); diff --git a/packages/react-bootstrap-table2-example/examples/row-selection/multiple-selection.js b/packages/react-bootstrap-table2-example/examples/row-selection/multiple-selection.js index 8228902..b792b43 100644 --- a/packages/react-bootstrap-table2-example/examples/row-selection/multiple-selection.js +++ b/packages/react-bootstrap-table2-example/examples/row-selection/multiple-selection.js @@ -17,8 +17,9 @@ const columns = [{ text: 'Product Price' }]; -const selectRowProp = { - mode: 'checkbox' +const selectRow = { + mode: 'checkbox', + clickToSelect: true }; const sourceCode = `\ @@ -33,21 +34,22 @@ const columns = [{ text: 'Product Price' }]; -const selectRowProp = { - mode: 'checkbox' +const selectRow = { + mode: 'checkbox', + clickToSelect: true }; `; export default () => (
- + { sourceCode }
); diff --git a/packages/react-bootstrap-table2-example/examples/row-selection/non-selectable-rows.js b/packages/react-bootstrap-table2-example/examples/row-selection/non-selectable-rows.js index d74d785..69fbf0a 100644 --- a/packages/react-bootstrap-table2-example/examples/row-selection/non-selectable-rows.js +++ b/packages/react-bootstrap-table2-example/examples/row-selection/non-selectable-rows.js @@ -19,6 +19,7 @@ const columns = [{ const selectRow = { mode: 'checkbox', + clickToSelect: true, nonSelectable: [0, 2, 4] }; @@ -36,6 +37,7 @@ const columns = [{ const selectRow = { mode: 'checkbox', + clickToSelect: true, nonSelectable: [0, 2, 4] }; diff --git a/packages/react-bootstrap-table2-example/examples/row-selection/selection-bgcolor.js b/packages/react-bootstrap-table2-example/examples/row-selection/selection-bgcolor.js index a1dc2db..ede13e0 100644 --- a/packages/react-bootstrap-table2-example/examples/row-selection/selection-bgcolor.js +++ b/packages/react-bootstrap-table2-example/examples/row-selection/selection-bgcolor.js @@ -20,11 +20,13 @@ const columns = [{ const selectRow1 = { mode: 'checkbox', + clickToSelect: true, bgColor: '#00BFFF' }; const selectRow2 = { mode: 'checkbox', + clickToSelect: true, bgColor: (row, rowIndex) => (rowIndex > 1 ? '#00BFFF' : '#00FFFF') }; @@ -42,6 +44,7 @@ const columns = [{ const selectRow = { mode: 'checkbox', + clickToSelect: true, bgColor: '#00BFFF' }; @@ -67,6 +70,7 @@ const columns = [{ const selectRow = { mode: 'checkbox', + clickToSelect: true, bgColor: (row, rowIndex) => (rowIndex > 1 ? '#00BFFF' : '#00FFFF') }; diff --git a/packages/react-bootstrap-table2-example/examples/row-selection/selection-class.js b/packages/react-bootstrap-table2-example/examples/row-selection/selection-class.js index ffce5b8..4c6b794 100644 --- a/packages/react-bootstrap-table2-example/examples/row-selection/selection-class.js +++ b/packages/react-bootstrap-table2-example/examples/row-selection/selection-class.js @@ -20,11 +20,13 @@ const columns = [{ const selectRow1 = { mode: 'checkbox', + clickToSelect: true, classes: 'selection-row' }; const selectRow2 = { mode: 'checkbox', + clickToSelect: true, classes: (row, rowIndex) => (rowIndex > 1 ? 'row-index-bigger-than-2101' : 'row-index-small-than-2101') }; @@ -43,6 +45,7 @@ const columns = [{ const selectRow = { mode: 'checkbox', + clickToSelect: true, classes: 'selection-row' }; @@ -68,6 +71,7 @@ const columns = [{ const selectRow = { mode: 'checkbox', + clickToSelect: true, classes: (row, rowIndex) => (rowIndex > 1 ? 'row-index-bigger-than-2101' : 'row-index-small-than-2101') }; diff --git a/packages/react-bootstrap-table2-example/examples/row-selection/selection-style.js b/packages/react-bootstrap-table2-example/examples/row-selection/selection-style.js index 1608fdf..e347c1e 100644 --- a/packages/react-bootstrap-table2-example/examples/row-selection/selection-style.js +++ b/packages/react-bootstrap-table2-example/examples/row-selection/selection-style.js @@ -20,11 +20,13 @@ const columns = [{ const selectRow1 = { mode: 'checkbox', + clickToSelect: true, style: { backgroundColor: '#c8e6c9' } }; const selectRow2 = { mode: 'checkbox', + clickToSelect: true, style: (row, rowIndex) => { const backgroundColor = rowIndex > 1 ? '#00BFFF' : '#00FFFF'; return { backgroundColor }; @@ -45,6 +47,7 @@ const columns = [{ const selectRow = { mode: 'checkbox', + clickToSelect: true, style: { backgroundColor: '#c8e6c9' } }; @@ -70,6 +73,7 @@ const columns = [{ const selectRow = { mode: 'checkbox', + clickToSelect: true, style: (row, rowIndex) => { const backgroundColor = rowIndex > 1 ? '#00BFFF' : '#00FFFF'; return { backgroundColor }; diff --git a/packages/react-bootstrap-table2-example/examples/row-selection/single-selection.js b/packages/react-bootstrap-table2-example/examples/row-selection/single-selection.js index 15827b9..936dde4 100644 --- a/packages/react-bootstrap-table2-example/examples/row-selection/single-selection.js +++ b/packages/react-bootstrap-table2-example/examples/row-selection/single-selection.js @@ -17,8 +17,9 @@ const columns = [{ text: 'Product Price' }]; -const selectRowProp = { - mode: 'radio' +const selectRow = { + mode: 'radio', + clickToSelect: true }; const sourceCode = `\ @@ -33,21 +34,22 @@ const columns = [{ text: 'Product Price' }]; -const selectRowProp = { - mode: 'radio' +const selectRow = { + mode: 'radio', + clickToSelect: true }; `; export default () => (
- + { sourceCode }
); diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js index 7be418f..6598dd6 100644 --- a/packages/react-bootstrap-table2-example/stories/index.js +++ b/packages/react-bootstrap-table2-example/stories/index.js @@ -53,6 +53,8 @@ import CellEditWithRedux from 'examples/cell-edit/cell-edit-with-redux-table'; // work on row selection import SingleSelectionTable from 'examples/row-selection/single-selection'; import MultipleSelectionTable from 'examples/row-selection/multiple-selection'; +import ClickToSelectTable from 'examples/row-selection/click-to-select'; +import ClickToSelectWithCellEditTable from 'examples/row-selection/click-to-select-with-cell-edit'; import SelectionStyleTable from 'examples/row-selection/selection-style'; import SelectionClassTable from 'examples/row-selection/selection-class'; import NonSelectableRowsTable from 'examples/row-selection/non-selectable-rows'; @@ -119,6 +121,8 @@ storiesOf('Cell Editing', module) storiesOf('Row Selection', module) .add('Single Selection', () => ) .add('Multiple Selection', () => ) + .add('Click to Select', () => ) + .add('Click to Select and Edit Cell', () => ) .add('Selection Style', () => ) .add('Selection Class', () => ) .add('Selection Background Color', () => ) diff --git a/packages/react-bootstrap-table2/src/body.js b/packages/react-bootstrap-table2/src/body.js index 18ccef8..453ab0d 100644 --- a/packages/react-bootstrap-table2/src/body.js +++ b/packages/react-bootstrap-table2/src/body.js @@ -25,7 +25,8 @@ const Body = (props) => { const { style: selectedStyle, classes: selectedClasses, - bgColor + bgColor, + nonSelectable } = selectRow; let content; @@ -55,6 +56,8 @@ const Body = (props) => { } } + const selectable = !nonSelectable || !nonSelectable.includes(key); + return ( { columns={ columns } cellEdit={ cellEdit } editable={ editable } + selectable={ selectable } selected={ selected } selectRow={ selectRow } style={ style } diff --git a/packages/react-bootstrap-table2/src/bootstrap-table.js b/packages/react-bootstrap-table2/src/bootstrap-table.js index c90823a..11530c8 100644 --- a/packages/react-bootstrap-table2/src/bootstrap-table.js +++ b/packages/react-bootstrap-table2/src/bootstrap-table.js @@ -128,6 +128,8 @@ BootstrapTable.propTypes = { }), selectRow: PropTypes.shape({ mode: PropTypes.oneOf([Const.ROW_SELECT_SINGLE, Const.ROW_SELECT_MULTIPLE]).isRequired, + clickToSelect: PropTypes.bool, + clickToEdit: PropTypes.bool, style: PropTypes.oneOfType([PropTypes.object, PropTypes.func]), classes: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), nonSelectable: PropTypes.array, diff --git a/packages/react-bootstrap-table2/src/cell-edit/editing-cell.js b/packages/react-bootstrap-table2/src/cell-edit/editing-cell.js index ee432dd..48a7299 100644 --- a/packages/react-bootstrap-table2/src/cell-edit/editing-cell.js +++ b/packages/react-bootstrap-table2/src/cell-edit/editing-cell.js @@ -1,6 +1,8 @@ /* eslint arrow-body-style: 0 */ /* eslint react/prop-types: 0 */ /* eslint no-return-assign: 0 */ +/* eslint class-methods-use-this: 0 */ +/* eslint jsx-a11y/no-noninteractive-element-interactions: 0 */ import React, { Component } from 'react'; import cs from 'classnames'; import PropTypes from 'prop-types'; @@ -16,6 +18,7 @@ class EditingCell extends Component { this.indicatorTimer = null; this.clearTimer = this.clearTimer.bind(this); this.handleBlur = this.handleBlur.bind(this); + this.handleClick = this.handleClick.bind(this); this.handleKeyDown = this.handleKeyDown.bind(this); this.beforeComplete = this.beforeComplete.bind(this); this.state = { @@ -94,6 +97,15 @@ class EditingCell extends Component { } } + handleClick(e) { + if (e.target.tagName !== 'TD') { + // To avoid the row selection event be triggered, + // When user define selectRow.clickToSelect and selectRow.clickToEdit + // We shouldn't trigger selection event even if user click on the cell editor(input) + e.stopPropagation(); + } + } + render() { const { invalidMessage } = this.state; const { row, column, className, style } = this.props; @@ -111,6 +123,7 @@ class EditingCell extends Component { this.editor = node } diff --git a/packages/react-bootstrap-table2/src/cell-edit/wrapper.js b/packages/react-bootstrap-table2/src/cell-edit/wrapper.js index da6963f..60e3134 100644 --- a/packages/react-bootstrap-table2/src/cell-edit/wrapper.js +++ b/packages/react-bootstrap-table2/src/cell-edit/wrapper.js @@ -61,13 +61,18 @@ class CellEditWrapper extends Component { } startEditing(ridx, cidx) { - this.setState(() => { - return { - ridx, - cidx, - editing: true - }; - }); + const editing = () => { + this.setState(() => { + return { + ridx, + cidx, + editing: true + }; + }); + }; + + const { selectRow } = this.props; + if (!selectRow || (selectRow.clickToEdit || !selectRow.clickToSelect)) editing(); } escapeEditing() { diff --git a/packages/react-bootstrap-table2/src/const.js b/packages/react-bootstrap-table2/src/const.js index 4e10028..e9ebaa6 100644 --- a/packages/react-bootstrap-table2/src/const.js +++ b/packages/react-bootstrap-table2/src/const.js @@ -10,5 +10,6 @@ export default { ROW_SELECT_DISABLED: 'ROW_SELECT_DISABLED', CHECKBOX_STATUS_CHECKED: 'checked', CHECKBOX_STATUS_INDETERMINATE: 'indeterminate', - CHECKBOX_STATUS_UNCHECKED: 'unchecked' + CHECKBOX_STATUS_UNCHECKED: 'unchecked', + DELAY_FOR_DBCLICK: 200 }; diff --git a/packages/react-bootstrap-table2/src/row.js b/packages/react-bootstrap-table2/src/row.js index d93f384..23a8cf2 100644 --- a/packages/react-bootstrap-table2/src/row.js +++ b/packages/react-bootstrap-table2/src/row.js @@ -1,5 +1,5 @@ /* eslint react/prop-types: 0 */ -import React from 'react'; +import React, { Component } from 'react'; import PropTypes from 'prop-types'; import _ from './utils'; @@ -8,91 +8,133 @@ import SelectionCell from './row-selection/selection-cell'; import EditingCell from './cell-edit/editing-cell'; import Const from './const'; -const Row = (props) => { - const { - row, - columns, - keyField, - rowIndex, - className, - style, - cellEdit, - selected, - selectRow, - editable: editableRow - } = props; +class Row extends Component { + constructor(props) { + super(props); + this.clickNum = 0; + this.handleRowClick = this.handleRowClick.bind(this); + } - const { - mode, - onStart, - ridx: editingRowIdx, - cidx: editingColIdx, - ...rest - } = cellEdit; - - const key = _.get(row, keyField); - const { nonSelectable } = selectRow; - - return ( - - { - selectRow.mode === Const.ROW_SELECT_DISABLED - ? null - : ( - - ) + handleRowClick() { + const { + row, + selected, + keyField, + selectable, + selectRow: { + onRowSelect, + clickToEdit } - { - columns.map((column, index) => { - const { dataField } = column; - const content = _.get(row, dataField); - let editable = _.isDefined(column.editable) ? column.editable : true; - if (dataField === keyField || !editableRow) editable = false; - if (_.isFunction(column.editable)) { - editable = column.editable(content, row, rowIndex, index); + } = this.props; + const key = _.get(row, keyField); + if (selectable) { + const { cellEdit: { mode } } = this.props; + if (mode === Const.DBCLICK_TO_CELL_EDIT && clickToEdit) { + this.clickNum += 1; + _.debounce(() => { + if (this.clickNum === 1) { + onRowSelect(key, !selected); } - if (rowIndex === editingRowIdx && index === editingColIdx) { - let editCellstyle = column.editCellStyle || {}; - let editCellclasses = column.editCellClasses; - if (_.isFunction(column.editCellStyle)) { - editCellstyle = column.editCellStyle(content, row, rowIndex, index); + this.clickNum = 0; + }, Const.DELAY_FOR_DBCLICK)(); + } else { + onRowSelect(key, !selected); + } + } + } + + render() { + const { + row, + columns, + keyField, + rowIndex, + className, + style, + cellEdit, + selected, + selectRow, + selectable, + editable: editableRow + } = this.props; + + const { + mode, + onStart, + ridx: editingRowIdx, + cidx: editingColIdx, + ...rest + } = cellEdit; + + const key = _.get(row, keyField); + const { clickToSelect } = selectRow; + + const trAttrs = {}; + if (clickToSelect) { + trAttrs.onClick = this.handleRowClick; + } + + return ( + + { + selectRow.mode === Const.ROW_SELECT_DISABLED + ? null + : ( + + ) + } + { + columns.map((column, index) => { + const { dataField } = column; + const content = _.get(row, dataField); + let editable = _.isDefined(column.editable) ? column.editable : true; + if (dataField === keyField || !editableRow) editable = false; + if (_.isFunction(column.editable)) { + editable = column.editable(content, row, rowIndex, index); } - if (_.isFunction(column.editCellClasses)) { - editCellclasses = column.editCellClasses(content, row, rowIndex, index); + if (rowIndex === editingRowIdx && index === editingColIdx) { + let editCellstyle = column.editCellStyle || {}; + let editCellclasses = column.editCellClasses; + if (_.isFunction(column.editCellStyle)) { + editCellstyle = column.editCellStyle(content, row, rowIndex, index); + } + if (_.isFunction(column.editCellClasses)) { + editCellclasses = column.editCellClasses(content, row, rowIndex, index); + } + return ( + + ); } return ( - ); - } - return ( - - ); - }) - } - - ); -}; + }) + } + + ); + } +} Row.propTypes = { row: PropTypes.object.isRequired, diff --git a/packages/react-bootstrap-table2/src/utils.js b/packages/react-bootstrap-table2/src/utils.js index 4360d0d..16572b2 100644 --- a/packages/react-bootstrap-table2/src/utils.js +++ b/packages/react-bootstrap-table2/src/utils.js @@ -1,5 +1,6 @@ /* eslint no-empty: 0 */ /* eslint no-param-reassign: 0 */ +/* eslint prefer-rest-params: 0 */ function splitNested(str) { return [str] @@ -72,6 +73,29 @@ function sleep(fn, ms) { return setTimeout(() => fn(), ms); } +function debounce(func, wait, immediate) { + let timeout; + + return () => { + const later = () => { + timeout = null; + + if (!immediate) { + func.apply(this, arguments); + } + }; + + const callNow = immediate && !timeout; + + clearTimeout(timeout); + timeout = setTimeout(later, wait || 0); + + if (callNow) { + func.appy(this, arguments); + } + }; +} + export default { get, set, @@ -79,5 +103,6 @@ export default { isObject, isEmptyObject, isDefined, - sleep + sleep, + debounce }; diff --git a/packages/react-bootstrap-table2/test/body.test.js b/packages/react-bootstrap-table2/test/body.test.js index fc30b0b..717e34e 100644 --- a/packages/react-bootstrap-table2/test/body.test.js +++ b/packages/react-bootstrap-table2/test/body.test.js @@ -349,6 +349,30 @@ describe('Body', () => { expect(wrapper.find(Row).get(0).props.style.backgroundColor).toBe(bgColor); }); }); + + describe('if selectRow.nonSelectable is defined', () => { + const nonSelectableRowIndex = 1; + const nonSelectable = [data[nonSelectableRowIndex][keyField]]; + + beforeEach(() => { + selectRow.nonSelectable = nonSelectable; + wrapper = shallow( + + ); + }); + + it('should render Row component with correct selectable prop', () => { + expect(wrapper.find(Row).get(0).props.selectable).toBeTruthy(); + expect(wrapper.find(Row).get(nonSelectableRowIndex).props.selectable).toBeFalsy(); + }); + }); }); describe('when selectRow.mode is ROW_SELECT_DISABLED (row was un-selectable)', () => { diff --git a/packages/react-bootstrap-table2/test/cell-edit/wrapper.test.js b/packages/react-bootstrap-table2/test/cell-edit/wrapper.test.js index 49ebd22..c41d336 100644 --- a/packages/react-bootstrap-table2/test/cell-edit/wrapper.test.js +++ b/packages/react-bootstrap-table2/test/cell-edit/wrapper.test.js @@ -146,14 +146,61 @@ describe('CellEditWrapper', () => { }); describe('call startEditing function', () => { + const ridx = 1; + const cidx = 3; it('should set state correctly', () => { - const ridx = 1; - const cidx = 3; wrapper.instance().startEditing(ridx, cidx); expect(wrapper.state().ridx).toEqual(ridx); expect(wrapper.state().cidx).toEqual(cidx); expect(wrapper.state().editing).toBeTruthy(); }); + + describe('if selectRow.clickToSelect is defined', () => { + beforeEach(() => { + const selectRow = { mode: 'checkbox', clickToSelect: true }; + wrapper = shallow( + + ); + }); + + it('should not set state', () => { + wrapper.instance().startEditing(ridx, cidx); + expect(wrapper.state().ridx).toBeNull(); + expect(wrapper.state().cidx).toBeDefined(); + }); + }); + + describe('if selectRow.clickToSelect and selectRow.clickToEdit is defined', () => { + beforeEach(() => { + const selectRow = { mode: 'checkbox', clickToSelect: true, clickToEdit: true }; + wrapper = shallow( + + ); + }); + + it('should set state correctly', () => { + wrapper.instance().startEditing(ridx, cidx); + expect(wrapper.state().ridx).toEqual(ridx); + expect(wrapper.state().cidx).toEqual(cidx); + expect(wrapper.state().editing).toBeTruthy(); + }); + }); }); describe('call completeEditing function', () => { diff --git a/packages/react-bootstrap-table2/test/row.test.js b/packages/react-bootstrap-table2/test/row.test.js index 73d01ea..f720ee7 100644 --- a/packages/react-bootstrap-table2/test/row.test.js +++ b/packages/react-bootstrap-table2/test/row.test.js @@ -37,6 +37,7 @@ describe('Row', () => { wrapper = shallow( { row={ row } selectRow={ selectRow } selected + selectable />); }); @@ -483,9 +485,8 @@ describe('Row', () => { expect(wrapper.find(SelectionCell).props().mode).toEqual(selectRow.mode); }); - describe('if selectRow.nonSelectable is defined and contain a rowkey which is match to current row', () => { + describe('if selectable prop is false', () => { beforeEach(() => { - selectRow = { mode: 'checkbox', nonSelectable: [row.id] }; wrapper = shallow( { row={ row } keyField={ keyField } selectRow={ selectRow } + selectable={ false } />); }); @@ -503,9 +505,8 @@ describe('Row', () => { }); }); - describe('if selectRow.nonSelectable is defined and not contain any rowkey which is match to current row', () => { + describe('if selectable prop is true', () => { beforeEach(() => { - selectRow = { mode: 'checkbox', nonSelectable: [3, 4, 6] }; wrapper = shallow( { row={ row } keyField={ keyField } selectRow={ selectRow } + selectable />); }); @@ -522,5 +524,157 @@ describe('Row', () => { expect(wrapper.find(SelectionCell).prop('disabled')).toBeFalsy(); }); }); + + describe('if selectRow.clickToSelect is true', () => { + beforeEach(() => { + selectRow.clickToSelect = true; + wrapper = shallow( + ); + }); + + it('should render Row component successfully with onClick event', () => { + expect(wrapper.length).toBe(1); + expect(wrapper.find('tr').prop('onClick')).toBeDefined(); + }); + }); + }); + + describe('handleRowClick', () => { + let selectRow; + let onRowSelectCallBack; + + describe('selectable prop is false', () => { + beforeEach(() => { + onRowSelectCallBack = sinon.stub(); + selectRow = { + mode: 'checkbox', + clickToSelect: true, + onRowSelect: onRowSelectCallBack + }; + wrapper = shallow( + ); + wrapper.find('tr').simulate('click'); + }); + + it('should not calling selectRow.onRowSelect callback', () => { + expect(onRowSelectCallBack.callCount).toEqual(0); + }); + }); + + describe('selectable prop is true', () => { + describe('and selected prop is true', () => { + beforeEach(() => { + onRowSelectCallBack = sinon.stub(); + selectRow = { + mode: 'checkbox', + clickToSelect: true, + onRowSelect: onRowSelectCallBack + }; + wrapper = shallow( + ); + wrapper.find('tr').simulate('click'); + }); + + it('should calling selectRow.onRowSelect callback', () => { + expect(onRowSelectCallBack.callCount).toEqual(1); + }); + + it('should calling selectRow.onRowSelect with correct argument', () => { + expect(onRowSelectCallBack.calledWith(row[keyField], false)).toBeTruthy(); + }); + }); + + describe('and selected prop is false', () => { + beforeEach(() => { + onRowSelectCallBack = sinon.stub(); + selectRow = { + mode: 'checkbox', + clickToSelect: true, + onRowSelect: onRowSelectCallBack + }; + wrapper = shallow( + ); + wrapper.find('tr').simulate('click'); + }); + + it('should calling selectRow.onRowSelect callback', () => { + expect(onRowSelectCallBack.callCount).toEqual(1); + }); + + it('should calling selectRow.onRowSelect with correct argument', () => { + expect(onRowSelectCallBack.calledWith(row[keyField], true)).toBeTruthy(); + }); + }); + }); + + describe('if cellEdit.mode is dbclick and selectRow.clickToEdit is true', () => { + beforeEach(() => { + onRowSelectCallBack = sinon.stub(); + const cellEdit = { + mode: Const.DBCLICK_TO_CELL_EDIT, + ridx: undefined, + cidx: undefined, + onStart: sinon.stub() + }; + selectRow = { + mode: 'checkbox', + clickToSelect: true, + clickToEdit: true, + onRowSelect: onRowSelectCallBack + }; + wrapper = shallow( + ); + wrapper.instance().handleRowClick(); + wrapper.instance().handleRowClick(); + }); + + it('should increase clickNum as 2', () => { + expect(wrapper.instance().clickNum).toEqual(2); + }); + }); }); });