{
return {
...row,
className: classNames({
- 'is-selected': this.state.selectedRows.indexOf(rowKey) > -1
+ 'is-selected': (this.props.selectedRows || this.state.selectedRows).indexOf(rowKey) > -1
}, row.className)
};
})
diff --git a/src/DataTable/Sortable.js b/src/DataTable/Sortable.js
index 2de8340..d36b91f 100644
--- a/src/DataTable/Sortable.js
+++ b/src/DataTable/Sortable.js
@@ -1,6 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
+import isEqual from 'lodash.isequal';
import TableHeader from './TableHeader';
function initState(props) {
@@ -26,6 +27,7 @@ const propTypes = {
export default Component => {
class Sortable extends React.Component {
+ // eslint-disable-next-line react/sort-comp
constructor(props) {
super(props);
@@ -33,20 +35,28 @@ export default Component => {
if (props.sortable) {
this.state = initState(props);
+ } else {
+ this.state = {
+ rows: undefined,
+ sortHeader: undefined,
+ isAsc: undefined,
+ };
}
}
- componentWillReceiveProps(nextProps) {
+ // eslint-disable-next-line react/sort-comp
+ static getDerivedStateFromProps(nextProps, state) {
if (nextProps.sortable) {
const realRows = nextProps.rows || nextProps.data;
- const rows = this.state.sortHeader
- ? this.getSortedRowsForColumn(this.state.isAsc, this.state.sortHeader, realRows)
+ const rows = state.sortHeader
+ ? Sortable.getSortedRowsForColumn(nextProps, state.isAsc, state.sortHeader, realRows)
: realRows;
- this.setState({
- rows
- });
+ if (!isEqual(rows, state.rows)) {
+ return { rows };
+ }
}
+ return null;
}
getColumnClass(column) {
@@ -58,18 +68,18 @@ export default Component => {
});
}
- getDefaultSortFn(a, b, isAsc) {
+ static getDefaultSortFn(a, b, isAsc) {
return isAsc
? a.localeCompare(b)
: b.localeCompare(a);
}
- getSortedRowsForColumn(isAsc, columnName, rows) {
- const columns = !!this.props.children
- ? React.Children.map(this.props.children, child => child.props)
- : this.props.columns;
+ static getSortedRowsForColumn(props, isAsc, columnName, rows) {
+ const columns = !!props.children
+ ? React.Children.map(props.children, child => child.props)
+ : props.columns;
- let sortFn = this.getDefaultSortFn;
+ let sortFn = Sortable.getDefaultSortFn;
for (let i = 0; i < columns.length; i++) {
if (columns[i].name === columnName && columns[i].sortFn) {
sortFn = columns[i].sortFn;
@@ -88,7 +98,7 @@ export default Component => {
handleClickColumn(e, columnName) {
const isAsc = this.state.sortHeader === columnName ? !this.state.isAsc : true;
- const rows = this.getSortedRowsForColumn(isAsc, columnName, this.state.rows);
+ const rows = Sortable.getSortedRowsForColumn(this.props, isAsc, columnName, this.state.rows);
this.setState({
sortHeader: columnName,
isAsc,
diff --git a/src/DataTable/Table.js b/src/DataTable/Table.js
index c8b4763..591ec09 100644
--- a/src/DataTable/Table.js
+++ b/src/DataTable/Table.js
@@ -25,9 +25,10 @@ const propTypes = {
class Table extends React.Component {
renderCell(column, row, idx) {
const className = !column.numeric ? 'mdl-data-table__cell--non-numeric' : '';
+ const field = column.field || column.name;
return (
|
- {column.cellFormatter ? column.cellFormatter(row[column.name], row, idx) : row[column.name]}
+ {column.cellFormatter ? column.cellFormatter(row[field], row, idx) : row[field]}
|
);
}
diff --git a/src/DataTable/TableHeader.js b/src/DataTable/TableHeader.js
index 409f4ea..a9e60bc 100644
--- a/src/DataTable/TableHeader.js
+++ b/src/DataTable/TableHeader.js
@@ -7,6 +7,7 @@ const propTypes = {
cellFormatter: PropTypes.func, // Used by the Table component to format the cell content for this "column"
className: PropTypes.string,
name: PropTypes.string.isRequired,
+ field: PropTypes.string,
numeric: PropTypes.bool,
onClick: PropTypes.func,
nosort: PropTypes.bool,
@@ -22,6 +23,7 @@ const TableHeader = props => {
// see https://github.com/Hacker0x01/react-datepicker/issues/517#issuecomment-230171426
delete otherProps.cellFormatter;
delete otherProps.sortFn;
+ delete otherProps.field;
const classes = classNames({
'mdl-data-table__cell--non-numeric': !numeric
diff --git a/src/DataTable/__tests__/Selectable-test.js b/src/DataTable/__tests__/Selectable-test.js
index 3a9afba..2cb04b3 100644
--- a/src/DataTable/__tests__/Selectable-test.js
+++ b/src/DataTable/__tests__/Selectable-test.js
@@ -34,7 +34,7 @@ describe('Selectable Table', () => {
}
function getElementByRowId(wrapper, id) {
- const elts = wrapper.find('[data-reactmdl]');
+ const elts = wrapper.find('[data-reactmdl]').hostNodes();
for (let i = 0; i < elts.length; i++) {
if (elts.at(i).prop('data-reactmdl') === JSON.stringify({ id })) {
return elts.at(i);
diff --git a/src/DataTable/__tests__/Table-test.js b/src/DataTable/__tests__/Table-test.js
index 6b2637f..cdd026a 100644
--- a/src/DataTable/__tests__/Table-test.js
+++ b/src/DataTable/__tests__/Table-test.js
@@ -27,6 +27,9 @@ describe('Table', () => {
Material
Quantity
Price
+ Material
+ Quantity
+ Price
);
}
@@ -50,7 +53,7 @@ describe('Table', () => {
it('should contain the specific columns', () => {
const wrapper = mount(getDataTable());
- expect(wrapper.find(TableHeader)).to.have.length(3);
+ expect(wrapper.find(TableHeader)).to.have.length(6);
});
it('should contain the specific data', () => {
@@ -61,11 +64,14 @@ describe('Table', () => {
bodyTr.forEach((row, i) => {
const tds = row.find('td');
- expect(tds).to.have.length(3);
+ expect(tds).to.have.length(6);
expect(tds.at(0)).to.have.text(rows[i].material);
expect(tds.at(1)).to.have.text(rows[i].quantity);
expect(tds.at(2)).to.have.text(`\$${rows[i].price.toFixed(2)}`);
+ expect(tds.at(3)).to.have.text(rows[i].material);
+ expect(tds.at(4)).to.have.text(rows[i].quantity);
+ expect(tds.at(5)).to.have.text(`\$${rows[i].price.toFixed(2)}`);
});
});
@@ -79,6 +85,9 @@ describe('Table', () => {
expect(tds.at(0)).to.have.className('mdl-data-table__cell--non-numeric');
expect(tds.at(1)).to.not.have.className('mdl-data-table__cell--non-numeric');
expect(tds.at(2)).to.not.have.className('mdl-data-table__cell--non-numeric');
+ expect(tds.at(3)).to.have.className('mdl-data-table__cell--non-numeric');
+ expect(tds.at(4)).to.not.have.className('mdl-data-table__cell--non-numeric');
+ expect(tds.at(5)).to.not.have.className('mdl-data-table__cell--non-numeric');
});
});
diff --git a/src/Dialog/DialogTitle.js b/src/Dialog/DialogTitle.js
index 11e0203..1296fe8 100644
--- a/src/Dialog/DialogTitle.js
+++ b/src/Dialog/DialogTitle.js
@@ -15,7 +15,7 @@ DialogTitle.propTypes = {
className: PropTypes.string,
component: PropTypes.oneOfType([
PropTypes.string,
- PropTypes.element,
+ PropTypes.elementType,
PropTypes.func
])
};
diff --git a/src/Grid/Cell.js b/src/Grid/Cell.js
index 803bffa..0bd2c87 100644
--- a/src/Grid/Cell.js
+++ b/src/Grid/Cell.js
@@ -10,7 +10,7 @@ const propTypes = {
col: PropTypes.number,
component: PropTypes.oneOfType([
PropTypes.string,
- PropTypes.element,
+ PropTypes.elementType,
PropTypes.func
]),
phone: PropTypes.number,
diff --git a/src/Grid/Grid.js b/src/Grid/Grid.js
index 76b99b1..fbbd234 100644
--- a/src/Grid/Grid.js
+++ b/src/Grid/Grid.js
@@ -8,7 +8,7 @@ const propTypes = {
className: PropTypes.string,
component: PropTypes.oneOfType([
PropTypes.string,
- PropTypes.element,
+ PropTypes.elementType,
PropTypes.func
]),
noSpacing: PropTypes.bool,
diff --git a/src/Layout/Content.js b/src/Layout/Content.js
index 68eeb88..1fc8786 100644
--- a/src/Layout/Content.js
+++ b/src/Layout/Content.js
@@ -17,7 +17,7 @@ Content.propTypes = {
className: PropTypes.string,
component: PropTypes.oneOfType([
PropTypes.string,
- PropTypes.element,
+ PropTypes.elementType,
PropTypes.func
])
};
diff --git a/src/Layout/__tests__/HeaderTabs-test.js b/src/Layout/__tests__/HeaderTabs-test.js
index 4cfd2d5..e6ed150 100644
--- a/src/Layout/__tests__/HeaderTabs-test.js
+++ b/src/Layout/__tests__/HeaderTabs-test.js
@@ -1,7 +1,7 @@
/* eslint-env mocha */
import expect from 'expect';
import React from 'react';
-import TestUtils from 'react-addons-test-utils';
+import TestUtils from 'react-dom/test-utils';
import { render, renderDOM } from '../../__tests__/render';
import { HeaderTabs } from '../';
import { Tab, TabBar } from '../../Tabs/';
diff --git a/src/Snackbar/index.js b/src/Snackbar/index.js
index 4781fe1..397bba9 100644
--- a/src/Snackbar/index.js
+++ b/src/Snackbar/index.js
@@ -21,6 +21,7 @@ const defaultProps = {
};
class Snackbar extends React.Component {
+ // eslint-disable-next-line react/sort-comp
constructor(props) {
super(props);
this.clearTimer = this.clearTimer.bind(this);
@@ -31,10 +32,13 @@ class Snackbar extends React.Component {
};
}
- componentWillReceiveProps(nextProps) {
- this.setState({
- open: nextProps.active
- });
+ static getDerivedStateFromProps(nextProps, state) {
+ if (state.open !== nextProps.active) {
+ return {
+ open: nextProps.active
+ };
+ }
+ return null;
}
componentDidUpdate() {
diff --git a/src/Tabs/Tab.js b/src/Tabs/Tab.js
index b77316d..b4ba48f 100644
--- a/src/Tabs/Tab.js
+++ b/src/Tabs/Tab.js
@@ -7,7 +7,7 @@ const propTypes = {
className: PropTypes.string,
component: PropTypes.oneOfType([
PropTypes.string,
- PropTypes.element,
+ PropTypes.elementType,
PropTypes.func
]),
cssPrefix: PropTypes.string,
diff --git a/src/Tabs/__tests__/Tabs-test.js b/src/Tabs/__tests__/Tabs-test.js
index c7fd4b8..425daec 100644
--- a/src/Tabs/__tests__/Tabs-test.js
+++ b/src/Tabs/__tests__/Tabs-test.js
@@ -1,7 +1,7 @@
/* eslint-env mocha */
import expect from 'expect';
import React from 'react';
-import TestUtils from 'react-addons-test-utils';
+import TestUtils from 'react-dom/test-utils';
import { render, renderDOM } from '../../__tests__/render';
import { Tabs, Tab, TabBar } from '../';
diff --git a/src/__tests__/Slider-test.js b/src/__tests__/Slider-test.js
index 474070b..bee1a7b 100644
--- a/src/__tests__/Slider-test.js
+++ b/src/__tests__/Slider-test.js
@@ -23,7 +23,7 @@ describe('Slider', () => {
expect(output.props.className).toInclude('my-slider');
});
- describe('should have the backgrund aligned with the thumb', () => {
+ it('should have the backgrund aligned with the thumb', () => {
const onChange = expect.createSpy();
const el = renderDOM();
@@ -31,13 +31,14 @@ describe('Slider', () => {
expect(el.parentElement.querySelector('.mdl-slider__background-upper').style.flex).toMatch(/^0.75 .*/);
});
- describe('should update with the new value', () => {
+ it('should update with the new value', () => {
const onChange = expect.createSpy();
const el = renderDOM();
+ const parent = el.parentNode;
- ReactDOM.render(, el.parentNode);
+ ReactDOM.render(, parent);
- expect(el.parentElement.querySelector('.mdl-slider__background-lower').style.flex).toMatch(/^0.5 .*/);
- expect(el.parentElement.querySelector('.mdl-slider__background-upper').style.flex).toMatch(/^0.5 .*/);
+ expect(parent.querySelector('.mdl-slider__background-lower').style.flex).toMatch(/^0.5 .*/);
+ expect(parent.querySelector('.mdl-slider__background-upper').style.flex).toMatch(/^0.5 .*/);
});
});
diff --git a/src/__tests__/render.js b/src/__tests__/render.js
index cf089d2..63eb6fa 100644
--- a/src/__tests__/render.js
+++ b/src/__tests__/render.js
@@ -1,4 +1,5 @@
-import { createRenderer, renderIntoDocument } from 'react-addons-test-utils';
+import { createRenderer } from 'react-test-renderer/shallow';
+import { renderIntoDocument } from 'react-dom/test-utils';
import { findDOMNode } from 'react-dom';
import MDLComponent from '../utils/MDLComponent';
diff --git a/src/utils/MDLComponent.js b/src/utils/MDLComponent.js
index 3b831e5..d1e8bd7 100644
--- a/src/utils/MDLComponent.js
+++ b/src/utils/MDLComponent.js
@@ -12,7 +12,12 @@ export default class MDLComponent extends Component {
}
componentWillUnmount() {
- window.componentHandler.downgradeElements(findDOMNode(this));
+ const node = findDOMNode(this);
+ if (node) {
+ // Not sure what causes this but sometimes there is no node here, which
+ // causes componentHandler to throw up
+ window.componentHandler.downgradeElements(node);
+ }
}
render() {
diff --git a/tests.setup.js b/tests.setup.js
new file mode 100644
index 0000000..800a0e0
--- /dev/null
+++ b/tests.setup.js
@@ -0,0 +1,3 @@
+const Enzyme = require('enzyme');
+const Adapter = require('enzyme-adapter-react-16');
+Enzyme.configure({ adapter: new Adapter() });
diff --git a/tests.webpack.js b/tests.webpack.js
index e0d564e..f88e2b0 100644
--- a/tests.webpack.js
+++ b/tests.webpack.js
@@ -1,3 +1,5 @@
+require('./tests.setup');
+
// see https://github.com/webpack/karma-webpack#alternative-usage
const context = require.context('./src', true, /-test\.js$/);
diff --git a/wallaby.js b/wallaby.js
new file mode 100644
index 0000000..7a95e35
--- /dev/null
+++ b/wallaby.js
@@ -0,0 +1,68 @@
+const wallabyWebpack = require('wallaby-webpack');
+const webpack = require('webpack');
+
+module.exports = (wallaby) => ({
+ files: [
+ { pattern: 'extra/material.js', instrument: false },
+ { pattern: 'node_modules/chai/chai.js', instrument: false },
+ { pattern: 'node_modules/sinon/pkg/sinon.js', instrument: false },
+ { pattern: 'node_modules/react/umd/react.development.js', instrument: false },
+ { pattern: 'node_modules/react-dom/umd/react-dom.development.js', instrument: false },
+ { pattern: 'tests.setup.js', load: false },
+ { pattern: 'src/**/*.js', load: false },
+ { pattern: 'src/**/*-test.js', ignore: true },
+ ],
+ tests: [
+ { pattern: 'src/**/*-test.js', load: false },
+ ],
+ env: {
+ kind: 'chrome',
+ },
+ testFramework: 'mocha',
+ compilers: {
+ '**/*.js': wallaby.compilers.babel({}),
+ },
+ postprocessor: wallabyWebpack({
+ entryPatterns: [
+ 'tests.setup.js',
+ 'src/**/*-test.js',
+ ],
+ module: {
+ preLoaders: [
+ {
+ test: /\.js$/,
+ exclude: /(__tests__|node_modules)\//,
+ loader: 'isparta'
+ }
+ ],
+ loaders: [
+ {
+ test: /\.js$/,
+ exclude: /(node_modules)/,
+ loader: 'babel'
+ },
+ { test: /\.json$/, loader: 'json' }
+ ]
+ },
+ plugins: [
+ new webpack.DefinePlugin({
+ 'process.env.NODE_ENV': JSON.stringify('test')
+ })
+ ],
+ externals: {
+ sinon: 'sinon',
+ 'react/addons': true,
+ 'react/lib/ExecutionEnvironment': true,
+ 'react/lib/ReactContext': true,
+ react: 'React',
+ 'react-dom': 'ReactDOM',
+ },
+ }),
+ setup: () => {
+ window.should = window.chai.should();
+ window.expect = window.chai.expect;
+ window.assert = window.chai.assert;
+ // eslint-disable-next-line no-underscore-dangle
+ window.__moduleBundler.loadTests();
+ },
+});
diff --git a/webpack.config.js b/webpack.config.js
index c9a33dd..ae537e3 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -13,7 +13,7 @@ module.exports = {
amd: 'react-dom'
}
},
- devtool: 'sourcemap',
+ devtool: 'source-map',
module: {
loaders: [
{ test: /\.js$/, loader: 'babel-loader', exclude: /(node_modules)/ }