Repository: gregnb/mui-datatables
Pull request #818 (2019-08-07 07:49:02)

Bugfix/issue 817 fix rows selected
- Fix https://github.com/gregnb/mui-datatables/issues/817 issue with `rowsSelected` when `selectableRows` option is not specified
- Add tests
- Add deprecation warning

coveralls: 
[![Coverage Status](https://coveralls.io/builds/25029743/badge)](https://coveralls.io/builds/25029743)

Coverage increased (+0.4%) to 75.407% when pulling **39f13d92ea2b896fbc6f94f2fc7806c419021769 on bugfix/issue-817-fix-rows-selected** into **6740f71c14fcbda2e20ef0a358aca3e81d19e1b3 on master**.


Patch:
diff --git a/README.md b/README.md
index 4bc6098..fc29dce 100644
--- a/README.md
+++ b/README.md
@@ -153,6 +153,7 @@ The component accepts the following props:
 |**`customRowRender `**|function||Override default row rendering with custom function. `customRowRender(data, dataIndex, rowIndex) => React Component`
 |**`customSort`**|function||Override default sorting with custom function. `function(data: array, colIndex: number, order: string) => array`
 |**`customSearch `**|function||Override default search with custom function. `customSearch(searchQuery: string, currentRow: array, columns: array) => boolean`
+|**`customSearchRender `**|function||Render a custom table search. `customSearchRender(searchText: string, handleSearch, hideSearch, options) => React Component`
 |**`elevation`**|number|4|Shadow depth applied to Paper component
 |**`caseSensitive `**|boolean|false|Enable/disable case sensitivity for search
 |**`responsive`**|string|'stacked'|Enable/disable responsive table views. Options: 'stacked', 'scroll'
diff --git a/examples/customize-search-render/CustomSearchRender.js b/examples/customize-search-render/CustomSearchRender.js
new file mode 100644
index 0000000..0fa6589
--- /dev/null
+++ b/examples/customize-search-render/CustomSearchRender.js
@@ -0,0 +1,74 @@
+import React from 'react';
+import Grow from '@material-ui/core/Grow';
+import TextField from '@material-ui/core/TextField';
+import IconButton from '@material-ui/core/IconButton';
+import ClearIcon from '@material-ui/icons/Clear';
+import { withStyles } from '@material-ui/core/styles';
+
+const defaultSearchStyles = theme => ({
+  main: {
+    display: 'flex',
+    flex: '1 0 auto',
+  },
+  searchText: {
+    flex: '0.8 0',
+  },
+  clearIcon: {
+    '&:hover': {
+      color: theme.palette.error.main,
+    },
+  },
+});
+
+class CustomSearchRender extends React.Component {
+  handleTextChange = event => {
+    const { onSearchChange } = this.props.options;
+
+    if (onSearchChange) {
+      onSearchChange(event.target.value);
+    }
+
+    this.props.onSearch(event.target.value);
+  };
+
+  componentDidMount() {
+    document.addEventListener('keydown', this.onKeyDown, false);
+  }
+
+  componentWillUnmount() {
+    document.removeEventListener('keydown', this.onKeyDown, false);
+  }
+
+  onKeyDown = event => {
+    if (event.keyCode === 27) {
+      this.props.onHide();
+    }
+  };
+
+  render() {
+    const { classes, options, onHide, searchText } = this.props;
+
+    return (
+      <Grow appear in={true} timeout={300}>
+        <div className={classes.main} ref={el => (this.rootRef = el)}>
+          <TextField
+            placeholder={'Custom TableSearch without search icon'}
+            className={classes.searchText}
+            InputProps={{
+              'aria-label': options.textLabels.toolbar.search,
+            }}
+            value={searchText || ''}
+            onChange={this.handleTextChange}
+            fullWidth={true}
+            inputRef={el => (this.searchField = el)}
+          />
+          <IconButton className={classes.clearIcon} onClick={onHide}>
+            <ClearIcon />
+          </IconButton>
+        </div>
+      </Grow>
+    );
+  }
+}
+
+export default withStyles(defaultSearchStyles, { name: 'CustomSearchRender' })(CustomSearchRender);
diff --git a/examples/customize-search-render/index.js b/examples/customize-search-render/index.js
new file mode 100644
index 0000000..db816c1
--- /dev/null
+++ b/examples/customize-search-render/index.js
@@ -0,0 +1,70 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import MUIDataTable from '../../src/';
+import CustomSearchRender from './CustomSearchRender';
+
+class Example extends React.Component {
+
+  render () {
+
+    const columns = ['Name', 'Title', 'Location', 'Age', 'Salary'];
+
+    let data = [
+      ['Gabby George', 'Business Analyst', 'Minneapolis', 30, 100000],
+      ['Aiden Lloyd', 'Business Consultant', 'Dallas', 55, 200000],
+      ['Jaden Collins', 'Attorney', 'Santa Ana', 27, 500000],
+      ['Franky Rees', 'Business Analyst', 'St. Petersburg', 22, 50000],
+      ['Aaren Rose', 'Business Consultant', 'Toledo', 28, 75000],
+      ['Blake Duncan', 'Business Management Analyst', 'San Diego', 65, 94000],
+      ['Frankie Parry', 'Agency Legal Counsel', 'Jacksonville', 71, 210000],
+      ['Lane Wilson', 'Commercial Specialist', 'Omaha', 19, 65000],
+      ['Robin Duncan', 'Business Analyst', 'Los Angeles', 20, 77000],
+      ['Mel Brooks', 'Business Consultant', 'Oklahoma City', 37, 135000],
+      ['Harper White', 'Attorney', 'Pittsburgh', 52, 420000],
+      ['Kris Humphrey', 'Agency Legal Counsel', 'Laredo', 30, 150000],
+      ['Frankie Long', 'Industrial Analyst', 'Austin', 31, 170000],
+      ['Brynn Robbins', 'Business Analyst', 'Norfolk', 22, 90000],
+      ['Justice Mann', 'Business Consultant', 'Chicago', 24, 133000],
+      ['Addison Navarro', 'Business Management Analyst', 'New York', 50, 295000],
+      ['Jesse Welch', 'Agency Legal Counsel', 'Seattle', 28, 200000],
+      ['Eli Mejia', 'Commercial Specialist', 'Long Beach', 65, 400000],
+      ['Gene Leblanc', 'Industrial Analyst', 'Hartford', 34, 110000],
+      ['Danny Leon', 'Computer Scientist', 'Newark', 60, 220000],
+      ['Lane Lee', 'Corporate Counselor', 'Cincinnati', 52, 180000],
+      ['Jesse Hall', 'Business Analyst', 'Baltimore', 44, 99000],
+      ['Danni Hudson', 'Agency Legal Counsel', 'Tampa', 37, 90000],
+      ['Terry Macdonald', 'Commercial Specialist', 'Miami', 39, 140000],
+      ['Justice Mccarthy', 'Attorney', 'Tucson', 26, 330000],
+      ['Silver Carey', 'Computer Scientist', 'Memphis', 47, 250000],
+      ['Franky Miles', 'Industrial Analyst', 'Buffalo', 49, 190000],
+      ['Glen Nixon', 'Corporate Counselor', 'Arlington', 44, 80000],
+      ['Gabby Strickland', 'Business Process Consultant', 'Scottsdale', 26, 45000],
+      ['Mason Ray', 'Computer Scientist', 'San Francisco', 39, 142000]
+    ];
+
+    const options = {
+      filter: true,
+      selectableRows: true,
+      filterType: 'dropdown',
+      responsive: 'stacked',
+      rowsPerPage: 10,
+      customSearchRender: (searchText, handleSearch, hideSearch, options) => {
+        return (
+          <CustomSearchRender
+            searchText={searchText}
+            onSearch={handleSearch}
+            onHide={hideSearch}
+            options={options}
+          />
+        );
+      }
+    };
+
+    return (
+      <MUIDataTable title={'ACME Employee list'} data={data} columns={columns} options={options} />
+    );
+
+  }
+}
+
+ReactDOM.render(<Example />, document.getElementById('app-root'));
diff --git a/src/MUIDataTable.js b/src/MUIDataTable.js
index 1a6b4f7..bcb1c67 100644
--- a/src/MUIDataTable.js
+++ b/src/MUIDataTable.js
@@ -126,6 +126,7 @@ class MUIDataTable extends React.Component {
       customToolbar: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
       customToolbarSelect: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
       customFooter: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
+      customSearchRender: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
       customRowRender: PropTypes.func,
       onRowClick: PropTypes.func,
       resizableColumns: PropTypes.bool,
@@ -213,8 +214,8 @@ class MUIDataTable extends React.Component {
   componentDidMount() {
     this.setHeadResizeable(this.headCellRefs, this.tableRef);
 
-    // When we have a search, we must reset page to view it
-    if (this.props.options.searchText) this.setState({ page: 0 });
+    // When we have a search, we must reset page to view it unless on serverSide since paging is handled by the user.
+    if (this.props.options.searchText && !this.props.options.serverSide) this.setState({ page: 0 });
   }
 
   componentDidUpdate(prevProps) {
@@ -225,8 +226,8 @@ class MUIDataTable extends React.Component {
       this.updateOptions(this.props);
     }
 
-    if (this.props.options.searchText !== prevProps.options.searchText) {
-      // When we have a search, we must reset page to view it
+    if (this.props.options.searchText !== prevProps.options.searchText && !this.props.options.serverSide) {
+      // When we have a search, we must reset page to view it unless on serverSide since paging is handled by the user.
       this.setState({ page: 0 });
     }
 
@@ -284,6 +285,7 @@ class MUIDataTable extends React.Component {
 
     const extra = {};
     if (typeof props.options.selectableRows === 'boolean') {
+      console.error('Using a boolean for selectableRows has been deprecated. Please use string option: multiple | single | none');
       extra.selectableRows = props.options.selectableRows ? 'multiple' : 'none';
     }
     this.options = merge(defaultOptions, props.options, extra);
@@ -363,6 +365,7 @@ class MUIDataTable extends React.Component {
     let columnData = [];
     let filterData = [];
     let filterList = [];
+    let sortDirectionSet = false;
 
     newColumns.forEach((column, colIndex) => {
       let columnOptions = {
@@ -378,8 +381,19 @@ class MUIDataTable extends React.Component {
       };
 
       if (typeof column === 'object') {
-        if (column.options && column.options.display !== undefined) {
-          column.options.display = column.options.display.toString();
+        if (column.options) {
+          if (column.options.display !== undefined) {
+            column.options.display = column.options.display.toString();
+          }
+
+          if (column.options.sortDirection !== undefined) {
+            if (sortDirectionSet) {
+              console.error('sortDirection is set for more than one column. Only the first column will be considered.');
+              column.options.sortDirection = null;
+            } else {
+              sortDirectionSet = true;
+            }
+          }
         }
 
         columnOptions = {
@@ -417,15 +431,13 @@ class MUIDataTable extends React.Component {
   };
 
   setTableData(props, status, callback = () => {}) {
-    const { options } = props;
-
     let tableData = [];
     let { columns, filterData, filterList } = this.buildColumns(props.columns);
     let sortIndex = null;
     let sortDirection = null;
 
     const data = status === TABLE_LOAD.INITIAL ? this.transformData(columns, props.data) : props.data;
-    const searchText = status === TABLE_LOAD.INITIAL ? options.searchText : null;
+    const searchText = status === TABLE_LOAD.INITIAL ? this.options.searchText : null;
 
     columns.forEach((column, colIndex) => {
       for (let rowIndex = 0; rowIndex < data.length; rowIndex++) {
@@ -498,8 +510,8 @@ class MUIDataTable extends React.Component {
 
     if (TABLE_LOAD.INITIAL) {
       // Multiple row selection customization
-      if (options.rowsSelected && options.rowsSelected.length && options.selectableRows === 'multiple') {
-        options.rowsSelected.forEach(row => {
+      if (this.options.rowsSelected && this.options.rowsSelected.length && this.options.selectableRows === 'multiple') {
+        this.options.rowsSelected.forEach(row => {
           let rowPos = row;
 
           for (let cIndex = 0; cIndex < this.state.displayData.length; cIndex++) {
@@ -515,26 +527,26 @@ class MUIDataTable extends React.Component {
       }
 
       // Single row selection customization
-      if (options.rowsSelected && options.rowsSelected.length === 1 && options.selectableRows === 'single') {
-        let rowPos = options.rowsSelected[0];
+      if (this.options.rowsSelected && this.options.rowsSelected.length === 1 && this.options.selectableRows === 'single') {
+        let rowPos = this.options.rowsSelected[0];
 
         for (let cIndex = 0; cIndex < this.state.displayData.length; cIndex++) {
-          if (this.state.displayData[cIndex].dataIndex === options.rowsSelected[0]) {
+          if (this.state.displayData[cIndex].dataIndex === this.options.rowsSelected[0]) {
             rowPos = cIndex;
             break;
           }
         }
 
-        selectedRowsData.data.push({ index: rowPos, dataIndex: options.rowsSelected[0] });
-        selectedRowsData.lookup[options.rowsSelected[0]] = true;
-      } else if (options.rowsSelected && options.rowsSelected.length > 1 && options.selectableRows === 'single') {
+        selectedRowsData.data.push({ index: rowPos, dataIndex: this.options.rowsSelected[0] });
+        selectedRowsData.lookup[this.options.rowsSelected[0]] = true;
+      } else if (this.options.rowsSelected && this.options.rowsSelected.length > 1 && this.options.selectableRows === 'single') {
         console.error(
           'Multiple values provided for selectableRows, but selectableRows set to "single". Either supply only a single value or use "multiple".',
         );
       }
 
-      if (options.rowsExpanded && options.rowsExpanded.length && options.expandableRows) {
-        options.rowsExpanded.forEach(row => {
+      if (this.options.rowsExpanded && this.options.rowsExpanded.length && this.options.expandableRows) {
+        this.options.rowsExpanded.forEach(row => {
           let rowPos = row;
 
           for (let cIndex = 0; cIndex < this.state.displayData.length; cIndex++) {
@@ -550,7 +562,7 @@ class MUIDataTable extends React.Component {
       }
     }
 
-    if (!options.serverSide && sortIndex !== null) {
+    if (!this.options.serverSide && sortIndex !== null) {
       const sortedData = this.sortTable(tableData, sortIndex, sortDirection);
       tableData = sortedData.data;
     }
@@ -563,7 +575,7 @@ class MUIDataTable extends React.Component {
         searchText: searchText,
         selectedRows: selectedRowsData,
         expandedRows: expandedRowsData,
-        count: options.count,
+        count: this.options.count,
         data: tableData,
         displayData: this.getDisplayData(columns, tableData, filterList, searchText),
       }),
diff --git a/src/components/TableFilter.js b/src/components/TableFilter.js
index 0ea4c2f..99e3697 100644
--- a/src/components/TableFilter.js
+++ b/src/components/TableFilter.js
@@ -1,4 +1,5 @@
 import { Grid, GridList, GridListTile, TextField } from '@material-ui/core';
+
 import Button from '@material-ui/core/Button';
 import Checkbox from '@material-ui/core/Checkbox';
 import FormControl from '@material-ui/core/FormControl';
@@ -8,12 +9,12 @@ import Input from '@material-ui/core/Input';
 import InputLabel from '@material-ui/core/InputLabel';
 import ListItemText from '@material-ui/core/ListItemText';
 import MenuItem from '@material-ui/core/MenuItem';
+import PropTypes from 'prop-types';
+import React from 'react';
 import Select from '@material-ui/core/Select';
-import { withStyles } from '@material-ui/core/styles';
 import Typography from '@material-ui/core/Typography';
 import classNames from 'classnames';
-import PropTypes from 'prop-types';
-import React from 'react';
+import { withStyles } from '@material-ui/core/styles';
 
 export const defaultFilterStyles = theme => ({
   root: {
@@ -79,29 +80,8 @@ export const defaultFilterStyles = theme => ({
     },
   },
   checked: {},
-  /* selects */
-  selectRoot: {
-    display: 'flex',
-    marginTop: '16px',
-    flexDirection: 'row',
-    flexWrap: 'wrap',
-    width: '100%',
-    height: '80%',
-    justifyContent: 'space-between',
-  },
-  selectFormControl: {
-    flex: '1 1 calc(50% - 24px)',
-  },
-  /* textField */
-  textFieldRoot: {
-    display: 'flex',
+  gridListTile: {
     marginTop: '16px',
-    flexDirection: 'row',
-    flexWrap: 'wrap',
-    width: '100%',
-  },
-  textFieldFormControl: {
-    flex: '1 1 calc(50% - 24px)',
   },
 });
 
@@ -190,26 +170,25 @@ class TableFilter extends React.Component {
     const textLabels = options.textLabels.filter;
 
     return (
-      <GridListTile key={index} cols={1}>
-        <div className={classes.selectRoot}>
-          <FormControl className={classes.selectFormControl} key={index}>
-            <InputLabel htmlFor={column.name}>{column.label}</InputLabel>
-            <Select
-              value={filterList[index].toString() || textLabels.all}
-              name={column.name}
-              onChange={event => this.handleDropdownChange(event, index, column.name)}
-              input={<Input name={column.name} id={column.name} />}>
-              <MenuItem value={textLabels.all} key={0}>
-                {textLabels.all}
+      <GridListTile key={index} cols={1} classes={{ tile: classes.gridListTile }}>
+        <FormControl key={index} fullWidth>
+          <InputLabel htmlFor={column.name}>{column.label}</InputLabel>
+          <Select
+            fullWidth
+            value={filterList[index].toString() || textLabels.all}
+            name={column.name}
+            onChange={event => this.handleDropdownChange(event, index, column.name)}
+            input={<Input name={column.name} id={column.name} />}>
+            <MenuItem value={textLabels.all} key={0}>
+              {textLabels.all}
+            </MenuItem>
+            {filterData[index].map((filterValue, filterIndex) => (
+              <MenuItem value={filterValue} key={filterIndex + 1}>
+                {filterValue != null ? filterValue.toString() : ''}
               </MenuItem>
-              {filterData[index].map((filterValue, filterIndex) => (
-                <MenuItem value={filterValue} key={filterIndex + 1}>
-                  {filterValue != null ? filterValue.toString() : ''}
-                </MenuItem>
-              ))}
-            </Select>
-          </FormControl>
-        </div>
+            ))}
+          </Select>
+        </FormControl>
       </GridListTile>
     );
   }
@@ -218,16 +197,15 @@ class TableFilter extends React.Component {
     const { classes, filterList } = this.props;
 
     return (
-      <GridListTile key={index} cols={1}>
-        <div className={classes.textFieldRoot}>
-          <FormControl className={classes.textFieldFormControl} key={index}>
-            <TextField
-              label={column.label}
-              value={filterList[index].toString() || ''}
-              onChange={event => this.handleTextFieldChange(event, index, column.name)}
-            />
-          </FormControl>
-        </div>
+      <GridListTile key={index} cols={1} classes={{ tile: classes.gridListTile }}>
+        <FormControl key={index} fullWidth>
+          <TextField
+            fullWidth
+            label={column.label}
+            value={filterList[index].toString() || ''}
+            onChange={event => this.handleTextFieldChange(event, index, column.name)}
+          />
+        </FormControl>
       </GridListTile>
     );
   }
@@ -236,34 +214,33 @@ class TableFilter extends React.Component {
     const { classes, filterData, filterList } = this.props;
 
     return (
-      <GridListTile key={index} cols={1}>
-        <div className={classes.selectRoot}>
-          <FormControl className={classes.selectFormControl} key={index}>
-            <InputLabel htmlFor={column.name}>{column.label}</InputLabel>
-            <Select
-              multiple
-              value={filterList[index] || []}
-              renderValue={selected => selected.join(', ')}
-              name={column.name}
-              onChange={event => this.handleMultiselectChange(index, event.target.value, column.name)}
-              input={<Input name={column.name} id={column.name} />}>
-              {filterData[index].map((filterValue, filterIndex) => (
-                <MenuItem value={filterValue} key={filterIndex + 1}>
-                  <Checkbox
-                    checked={filterList[index].indexOf(filterValue) >= 0 ? true : false}
-                    value={filterValue != null ? filterValue.toString() : ''}
-                    className={classes.checkboxIcon}
-                    classes={{
-                      root: classes.checkbox,
-                      checked: classes.checked,
-                    }}
-                  />
-                  <ListItemText primary={filterValue} />
-                </MenuItem>
-              ))}
-            </Select>
-          </FormControl>
-        </div>
+      <GridListTile key={index} cols={1} classes={{ tile: classes.gridListTile }}>
+        <FormControl key={index} fullWidth>
+          <InputLabel htmlFor={column.name}>{column.label}</InputLabel>
+          <Select
+            multiple
+            fullWidth
+            value={filterList[index] || []}
+            renderValue={selected => selected.join(', ')}
+            name={column.name}
+            onChange={event => this.handleMultiselectChange(index, event.target.value, column.name)}
+            input={<Input name={column.name} id={column.name} />}>
+            {filterData[index].map((filterValue, filterIndex) => (
+              <MenuItem value={filterValue} key={filterIndex + 1}>
+                <Checkbox
+                  checked={filterList[index].indexOf(filterValue) >= 0 ? true : false}
+                  value={filterValue != null ? filterValue.toString() : ''}
+                  className={classes.checkboxIcon}
+                  classes={{
+                    root: classes.checkbox,
+                    checked: classes.checked,
+                  }}
+                />
+                <ListItemText primary={filterValue} />
+              </MenuItem>
+            ))}
+          </Select>
+        </FormControl>
       </GridListTile>
     );
   }
@@ -280,10 +257,10 @@ class TableFilter extends React.Component {
     }
 
     return (
-      <GridListTile key={index} cols={1}>
-        <div className={classes.textFieldRoot}>
-          <FormControl key={index}>{display(filterList, this.handleCustomChange, index, column)}</FormControl>
-        </div>
+      <GridListTile key={index} cols={1} classes={{ tile: classes.gridListTile }}>
+        <FormControl key={index} fullWidth>
+          {display(filterList, this.handleCustomChange, index, column)}
+        </FormControl>
       </GridListTile>
     );
   }
diff --git a/src/components/TableToolbar.js b/src/components/TableToolbar.js
index 70d9bc4..41bc119 100644
--- a/src/components/TableToolbar.js
+++ b/src/components/TableToolbar.js
@@ -204,12 +204,16 @@ class TableToolbar extends React.Component {
       <Toolbar className={classes.root} role={'toolbar'} aria-label={'Table Toolbar'}>
         <div className={classes.left}>
           {showSearch === true ? (
-            <TableSearch
-              searchText={searchText}
-              onSearch={this.handleSearch}
-              onHide={this.hideSearch}
-              options={options}
-            />
+            options.customSearchRender ? (
+              options.customSearchRender(searchText, this.handleSearch, this.hideSearch, options)
+            ) : (
+              <TableSearch
+                searchText={searchText}
+                onSearch={this.handleSearch}
+                onHide={this.hideSearch}
+                options={options}
+              />
+            )
           ) : typeof title !== 'string' ? (
             title
           ) : (


Test patch:
diff --git a/test/MUIDataTable.test.js b/test/MUIDataTable.test.js
index 10d9f9f..1fb54de 100644
--- a/test/MUIDataTable.test.js
+++ b/test/MUIDataTable.test.js
@@ -2,6 +2,7 @@ import React from 'react';
 import { spy } from 'sinon';
 import { mount, shallow } from 'enzyme';
 import { assert, expect } from 'chai';
+import cloneDeep from 'lodash.clonedeep';
 import MUIDataTable from '../src/MUIDataTable';
 import TableFilterList from '../src/components/TableFilterList';
 import TablePagination from '../src/components/TablePagination';
@@ -429,6 +430,21 @@ describe('<MUIDataTable />', function() {
     assert.deepEqual(state.filterList, [['Joe James'], [], [], [], []]);
   });
 
+  it('should apply columns prop change for filterList', () => {
+    const mountShallowWrapper = mount(shallow(<MUIDataTable columns={columns} data={data} />).get(0));
+    const instance = mountShallowWrapper.instance();
+    instance.initializeTable(mountShallowWrapper.props());
+    // now use updated columns props
+    const newColumns = cloneDeep(columns);
+    newColumns[0].options.filterList = ['Joe James'];
+    mountShallowWrapper.setProps({ columns: newColumns });
+    mountShallowWrapper.update();
+    instance.setTableData(mountShallowWrapper.props(), 1 /* instance.TABLE_LOAD.INITIAL */);
+
+    const updatedState = mountShallowWrapper.state();
+    assert.deepEqual(updatedState.filterList, [['Joe James'], [], [], [], []]);
+  });
+
   it('should create Chip when filterList is populated', () => {
     const filterList = [['Joe James'], [], [], [], []];
     const filterListRenderers = [
@@ -799,6 +815,34 @@ describe('<MUIDataTable />', function() {
     assert.deepEqual(state.selectedRows.data, expectedResult);
   });
 
+  it('should not update selectedRows when using rowsSelected option with type=none', () => {
+    const options = {
+      selectableRows: 'none',
+      rowsSelected: [0],
+    };
+    const shallowWrapper = shallow(<MUIDataTable columns={columns} data={data} options={options} />).dive();
+    const instance = shallowWrapper.instance();
+
+    const state = shallowWrapper.state();
+    const expectedResult = [];
+
+    assert.deepEqual(state.selectedRows.data, expectedResult);
+  });
+
+  it('should update selectedRows when using rowsSelected option with type=single', () => {
+    const options = {
+      selectableRows: 'single',
+      rowsSelected: [0],
+    };
+    const shallowWrapper = shallow(<MUIDataTable columns={columns} data={data} options={options} />).dive();
+    const instance = shallowWrapper.instance();
+
+    const state = shallowWrapper.state();
+    const expectedResult = [{ index: 0, dataIndex: 0 }];
+
+    assert.deepEqual(state.selectedRows.data, expectedResult);
+  });
+
   it('should update selectedRows when using rowsSelected option with type=multiple', () => {
     const options = {
       selectableRows: 'multiple',
@@ -813,6 +857,19 @@ describe('<MUIDataTable />', function() {
     assert.deepEqual(state.selectedRows.data, expectedResult);
   });
 
+  it('should update selectedRows (with default type=multiple option) when using rowsSelected with no option specified', () => {
+    const options = {
+      rowsSelected: [0, 3],
+    };
+    const shallowWrapper = shallow(<MUIDataTable columns={columns} data={data} options={options} />).dive();
+    const instance = shallowWrapper.instance();
+
+    const state = shallowWrapper.state();
+    const expectedResult = [{ index: 0, dataIndex: 0 }, { index: 3, dataIndex: 3 }];
+
+    assert.deepEqual(state.selectedRows.data, expectedResult);
+  });
+
   it('should update expandedRows when using expandableRows option with default rowsExpanded', () => {
     const options = {
       expandableRows: true,
diff --git a/test/MUIDataTableToolbar.test.js b/test/MUIDataTableToolbar.test.js
index dd9fcce..dd00ccf 100644
--- a/test/MUIDataTableToolbar.test.js
+++ b/test/MUIDataTableToolbar.test.js
@@ -124,6 +124,22 @@ describe('<TableToolbar />', function() {
     assert.strictEqual(actualResult.length, 0);
   });
 
+  it('should render a toolbar with custom search when option.customSearchRender is provided', () => {
+    const CustomSearchRender = () => <h1>customSearchRender</h1>;
+    const newOptions = { ...options, customSearchRender: CustomSearchRender };
+    const shallowWrapper = shallow(
+      <TableToolbar columns={columns} data={data} options={newOptions} setTableAction={setTableAction} />,
+    )
+      .dive()
+      .dive()
+      .dive();
+    const instance = shallowWrapper.instance();
+    instance.setActiveIcon('search');
+    shallowWrapper.update();
+    const actualResult = shallowWrapper.find('h1');
+    assert.strictEqual(actualResult.length, 1);
+  });
+
   it('should render a toolbar with a search clicking search icon', () => {
     const shallowWrapper = shallow(
       <TableToolbar columns={columns} data={data} options={options} setTableAction={setTableAction} />,