diff --git a/docs/columns.md b/docs/columns.md
index 5e7a8b0..a517532 100644
--- a/docs/columns.md
+++ b/docs/columns.md
@@ -10,13 +10,15 @@ Available properties in a column object:
* [hidden](#hidden)
* [formatter](#formatter)
* [formatExtraData](#formatExtraData)
-* [headerFormatter](#headerFormatter)
+* [sort](#sort)
+* [sortFunc](#sortFunc)
* [classes](#classes)
* [style](#style)
* [title](#title)
* [events](#events)
* [align](#align)
* [attrs](#attrs)
+* [headerFormatter](#headerFormatter)
* [headerClasses](#headerClasses)
* [headerStyle](#headerStyle)
* [headerTitle](#headerTitle)
@@ -85,6 +87,24 @@ dataField: 'address.city'
## column.formatExtraData - [Any]
It's only used for [`column.formatter`](#formatter), you can define any value for it and will be passed as fourth argument for [`column.formatter`](#formatter) callback function.
+## column.sort - [Bool]
+Enable the column sort via a `true` value given.
+
+## column.sortFunc - [Function]
+`column.sortFunc` only work when `column.sort` is enable. `sortFunc` allow you to define your sorting algorithm. This callback function accept four arguments:
+
+```js
+{
+ // omit...
+ sort: true,
+ sortFunc: (a, b, order, dataField) => {
+ if (order === 'asc') return a - b;
+ else return b - a;
+ }
+}
+```
+> The possible value of `order` argument is **`asc`** and **`desc`**.
+
## column.classes - [String | Function]
It's availabe to have custom class on table column:
diff --git a/packages/react-bootstrap-table2-example/examples/sort/custom-sort-table.js b/packages/react-bootstrap-table2-example/examples/sort/custom-sort-table.js
new file mode 100644
index 0000000..d362e8d
--- /dev/null
+++ b/packages/react-bootstrap-table2-example/examples/sort/custom-sort-table.js
@@ -0,0 +1,60 @@
+/* eslint no-unused-vars: 0 */
+
+import React from 'react';
+
+import { BootstrapTableful } 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',
+ sort: true,
+ // here, we implement a custom sort which perform a reverse sorting
+ sortFunc: (a, b, order, dataField) => {
+ if (order === 'asc') {
+ return b - a;
+ }
+ return a - b; // desc
+ }
+}, {
+ dataField: 'name',
+ text: 'Product Name',
+ sort: true
+}, {
+ dataField: 'price',
+ text: 'Product Price'
+}];
+
+const sourceCode = `\
+const columns = [{
+ dataField: 'id',
+ text: 'Product ID',
+ sort: true,
+ // here, we implement a custom sort which perform a reverse sorting
+ sortFunc: (a, b, order, dataField) => {
+ if (order === 'asc') {
+ return b - a;
+ }
+ return a - b; // desc
+ }
+}, {
+ dataField: 'name',
+ text: 'Product Name',
+ sort: true
+}, {
+ dataField: 'price',
+ text: 'Product Price'
+}];
+
+
+`;
+
+export default () => (
+
+
+ { sourceCode }
+
+);
diff --git a/packages/react-bootstrap-table2-example/examples/sort/enable-sort-table.js b/packages/react-bootstrap-table2-example/examples/sort/enable-sort-table.js
new file mode 100644
index 0000000..255414b
--- /dev/null
+++ b/packages/react-bootstrap-table2-example/examples/sort/enable-sort-table.js
@@ -0,0 +1,44 @@
+import React from 'react';
+
+import { BootstrapTableful } 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',
+ sort: true
+}, {
+ dataField: 'name',
+ text: 'Product Name',
+ sort: true
+}, {
+ dataField: 'price',
+ text: 'Product Price'
+}];
+
+const sourceCode = `\
+const columns = [{
+ dataField: 'id',
+ text: 'Product ID',
+ sort: true
+}, {
+ dataField: 'name',
+ text: 'Product Name',
+ sort: true
+}, {
+ dataField: 'price',
+ text: 'Product Price'
+}];
+
+
+`;
+
+export default () => (
+
+
+ { sourceCode }
+
+);
diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js
index 16c3bae..8e40fcf 100644
--- a/packages/react-bootstrap-table2-example/stories/index.js
+++ b/packages/react-bootstrap-table2-example/stories/index.js
@@ -31,6 +31,10 @@ import HeaderColumnClassTable from 'examples/header-columns/column-class-table';
import HeaderColumnStyleTable from 'examples/header-columns/column-style-table';
import HeaderColumnAttrsTable from 'examples/header-columns/column-attrs-table';
+// table sort
+import EnableSortTable from 'examples/sort/enable-sort-table';
+import CustomSortTable from 'examples/sort/custom-sort-table';
+
// css style
import 'bootstrap/dist/css/bootstrap.min.css';
import 'stories/stylesheet/tomorrow.min.css';
@@ -69,3 +73,7 @@ storiesOf('Work on Header Columns', module)
.add('Customize Column Class', () => )
.add('Customize Column Style', () => )
.add('Customize Column HTML attribute', () => );
+
+storiesOf('Sort Table', module)
+ .add('Enable Sort', () => )
+ .add('Custom Sort Fuction', () => );
diff --git a/packages/react-bootstrap-table2/src/bootstrap-table.js b/packages/react-bootstrap-table2/src/bootstrap-table.js
index f60f519..5acfb2f 100644
--- a/packages/react-bootstrap-table2/src/bootstrap-table.js
+++ b/packages/react-bootstrap-table2/src/bootstrap-table.js
@@ -1,3 +1,4 @@
+/* eslint arrow-body-style: 0 */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import cs from 'classnames';
@@ -13,11 +14,15 @@ class BootstrapTable extends PropsBaseResolver(Component) {
this.validateProps();
const { store } = this.props;
this.store = !store ? new Store(props) : store;
+
+ this.handleSort = this.handleSort.bind(this);
+ this.state = {
+ data: this.store.get()
+ };
}
render() {
const {
- data,
columns,
keyField,
striped,
@@ -37,9 +42,14 @@ class BootstrapTable extends PropsBaseResolver(Component) {
return (
-
+
);
}
+
+ handleSort(column) {
+ this.store.sortBy(column);
+
+ this.setState(() => {
+ return {
+ data: this.store.get()
+ };
+ });
+ }
}
BootstrapTable.propTypes = {
diff --git a/packages/react-bootstrap-table2/src/const.js b/packages/react-bootstrap-table2/src/const.js
new file mode 100644
index 0000000..acc75d2
--- /dev/null
+++ b/packages/react-bootstrap-table2/src/const.js
@@ -0,0 +1,4 @@
+export default {
+ SORT_ASC: 'asc',
+ SORT_DESC: 'desc'
+};
diff --git a/packages/react-bootstrap-table2/src/header-cell.js b/packages/react-bootstrap-table2/src/header-cell.js
index be2e525..d419710 100644
--- a/packages/react-bootstrap-table2/src/header-cell.js
+++ b/packages/react-bootstrap-table2/src/header-cell.js
@@ -1,12 +1,25 @@
+/* eslint react/require-default-props: 0 */
import React from 'react';
+import cs from 'classnames';
import PropTypes from 'prop-types';
+import Const from './const';
+import SortSymbol from './sort-symbol';
+import SortCaret from './sort-caret';
import _ from './utils';
-const HeaderCell = ({ column, index }) => {
+const HeaderCell = (props) => {
+ const {
+ column,
+ index,
+ onSort,
+ sorting,
+ sortOrder
+ } = props;
const {
text,
+ sort,
hidden,
headerTitle,
headerAlign,
@@ -25,6 +38,7 @@ const HeaderCell = ({ column, index }) => {
const cellClasses = _.isFunction(headerClasses) ? headerClasses(column, index) : headerClasses;
let cellStyle = {};
+ let sortSymbol;
if (headerStyle) {
cellStyle = _.isFunction(headerStyle) ? headerStyle(column, index) : headerStyle;
@@ -46,9 +60,24 @@ const HeaderCell = ({ column, index }) => {
if (!_.isEmptyObject(cellStyle)) cellAttrs.style = cellStyle;
+ if (sort) {
+ const customClick = cellAttrs.onClick;
+ cellAttrs.onClick = (e) => {
+ onSort(column);
+ if (_.isFunction(customClick)) customClick(e);
+ };
+ cellAttrs.className = cs(cellAttrs.className, 'sortable');
+
+ if (sorting) {
+ sortSymbol = ;
+ } else {
+ sortSymbol = ;
+ }
+ }
+
return (
|
- { children }
+ { children }{ sortSymbol }
|
);
};
@@ -68,9 +97,14 @@ HeaderCell.propTypes = {
headerEvents: PropTypes.object,
events: PropTypes.object,
headerAlign: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
- align: PropTypes.oneOfType([PropTypes.string, PropTypes.func])
+ align: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
+ sort: PropTypes.bool,
+ sortFunc: PropTypes.func
}).isRequired,
- index: PropTypes.number.isRequired
+ index: PropTypes.number.isRequired,
+ onSort: PropTypes.func,
+ sorting: PropTypes.bool,
+ sortOrder: PropTypes.oneOf([Const.SORT_ASC, Const.SORT_DESC])
};
export default HeaderCell;
diff --git a/packages/react-bootstrap-table2/src/header.js b/packages/react-bootstrap-table2/src/header.js
index eddf6a2..36752f1 100644
--- a/packages/react-bootstrap-table2/src/header.js
+++ b/packages/react-bootstrap-table2/src/header.js
@@ -1,22 +1,44 @@
+/* eslint react/require-default-props: 0 */
import React from 'react';
import PropTypes from 'prop-types';
import HeaderCell from './header-cell';
-const Header = ({ columns }) => (
-
-
- {
- columns.map((column, i) =>
- )
- }
-
-
-);
+const Header = (props) => {
+ const {
+ columns,
+ onSort,
+ sortField,
+ sortOrder
+ } = props;
+ return (
+
+
+ {
+ columns.map((column, i) => {
+ const currSort = column.dataField === sortField;
+ return (
+ );
+ })
+ }
+
+
+ );
+};
Header.propTypes = {
- columns: PropTypes.array.isRequired
+ columns: PropTypes.array.isRequired,
+ onSort: PropTypes.func,
+ sortField: PropTypes.string,
+ sortOrder: PropTypes.string
};
export default Header;
diff --git a/packages/react-bootstrap-table2/src/sort-caret.js b/packages/react-bootstrap-table2/src/sort-caret.js
new file mode 100644
index 0000000..08a918a
--- /dev/null
+++ b/packages/react-bootstrap-table2/src/sort-caret.js
@@ -0,0 +1,21 @@
+import React from 'react';
+import cs from 'classnames';
+import PropTypes from 'prop-types';
+
+import Const from './const';
+
+const SortCaret = ({ order }) => {
+ const orderClass = cs('react-bootstrap-table-sort-order', {
+ dropup: order === Const.SORT_ASC
+ });
+ return (
+
+
+
+ );
+};
+
+SortCaret.propTypes = {
+ order: PropTypes.oneOf([Const.SORT_ASC, Const.SORT_DESC]).isRequired
+};
+export default SortCaret;
diff --git a/packages/react-bootstrap-table2/src/sort-symbol.js b/packages/react-bootstrap-table2/src/sort-symbol.js
new file mode 100644
index 0000000..ecaf324
--- /dev/null
+++ b/packages/react-bootstrap-table2/src/sort-symbol.js
@@ -0,0 +1,13 @@
+import React from 'react';
+
+const SortSymbol = () => (
+
+
+
+
+
+
+
+ );
+
+export default SortSymbol;
diff --git a/packages/react-bootstrap-table2/src/store/base.js b/packages/react-bootstrap-table2/src/store/base.js
index 5805a43..c44a5ef 100644
--- a/packages/react-bootstrap-table2/src/store/base.js
+++ b/packages/react-bootstrap-table2/src/store/base.js
@@ -1,10 +1,31 @@
+import { sort } from './sort';
+import Const from '../const';
+
export default class Store {
constructor(props) {
const { data } = props;
this.data = data ? data.slice() : [];
+
+ this.sortOrder = undefined;
+ this.sortField = undefined;
}
isEmpty() {
return this.data.length === 0;
}
+
+ sortBy({ dataField, sortFunc }) {
+ if (dataField !== this.sortField) {
+ this.sortOrder = Const.SORT_DESC;
+ } else {
+ this.sortOrder = this.sortOrder === Const.SORT_DESC ? Const.SORT_ASC : Const.SORT_DESC;
+ }
+
+ this.data = sort(dataField, this.data, this.sortOrder, sortFunc);
+ this.sortField = dataField;
+ }
+
+ get() {
+ return this.data;
+ }
}
diff --git a/packages/react-bootstrap-table2/src/store/sort.js b/packages/react-bootstrap-table2/src/store/sort.js
new file mode 100644
index 0000000..95271b3
--- /dev/null
+++ b/packages/react-bootstrap-table2/src/store/sort.js
@@ -0,0 +1,40 @@
+/* eslint no-nested-ternary: 0 */
+/* eslint no-lonely-if: 0 */
+/* eslint no-underscore-dangle: 0 */
+import _ from '../utils';
+import Const from '../const';
+
+function comparator(a, b) {
+ let result;
+ if (typeof b === 'string') {
+ result = b.localeCompare(a);
+ } else {
+ result = a > b ? -1 : ((a < b) ? 1 : 0);
+ }
+ return result;
+}
+
+const sort = (dataField, data, order, sortFunc) => {
+ const _data = [...data];
+ _data.sort((a, b) => {
+ let result;
+ let valueA = _.get(a, dataField);
+ let valueB = _.get(b, dataField);
+ valueA = _.isDefined(valueA) ? valueA : '';
+ valueB = _.isDefined(valueB) ? valueB : '';
+
+ if (sortFunc) {
+ result = sortFunc(valueA, valueB, order, dataField);
+ } else {
+ if (order === Const.SORT_DESC) {
+ result = comparator(valueA, valueB);
+ } else {
+ result = comparator(valueB, valueA);
+ }
+ }
+ return result;
+ });
+ return _data;
+};
+
+export { sort };
diff --git a/packages/react-bootstrap-table2/src/utils.js b/packages/react-bootstrap-table2/src/utils.js
index e86be0f..780be47 100644
--- a/packages/react-bootstrap-table2/src/utils.js
+++ b/packages/react-bootstrap-table2/src/utils.js
@@ -40,9 +40,14 @@ function isEmptyObject(obj) {
return true;
}
+function isDefined(value) {
+ return typeof value !== 'undefined' && value !== null;
+}
+
export default {
get,
isFunction,
isObject,
- isEmptyObject
+ isEmptyObject,
+ isDefined
};
diff --git a/packages/react-bootstrap-table2/style/react-bootstrap-table.scss b/packages/react-bootstrap-table2/style/react-bootstrap-table.scss
index 2737023..3a8a126 100644
--- a/packages/react-bootstrap-table2/style/react-bootstrap-table.scss
+++ b/packages/react-bootstrap-table2/style/react-bootstrap-table.scss
@@ -1,5 +1,24 @@
.react-bootstrap-table-container {
+
+ th.sortable {
+ cursor: pointer;
+ }
+
+ th > .order > .dropdown > .caret {
+ margin: 10px 0 10px 5px;
+ color: #cccccc;
+ }
+
+ th > .order > .dropup > .caret {
+ margin: 10px 0;
+ color: #cccccc;
+ }
+
+ th > .react-bootstrap-table-sort-order > .caret {
+ margin: 10px 6.5px;
+ }
+
td.react-bs-table-no-data {
- text-align: center
- }
+ text-align: center;
+ }
}
\ No newline at end of file
diff --git a/packages/react-bootstrap-table2/test/header-cell.test.js b/packages/react-bootstrap-table2/test/header-cell.test.js
index 134de2d..408b853 100644
--- a/packages/react-bootstrap-table2/test/header-cell.test.js
+++ b/packages/react-bootstrap-table2/test/header-cell.test.js
@@ -2,6 +2,9 @@ import React from 'react';
import sinon from 'sinon';
import { shallow } from 'enzyme';
+import Const from '../src/const';
+import SortCaret from '../src/sort-caret';
+import SortSymbol from '../src/sort-symbol';
import HeaderCell from '../src/header-cell';
describe('HeaderCell', () => {
@@ -385,4 +388,75 @@ describe('HeaderCell', () => {
});
});
});
+
+ describe('when column.sort is enable', () => {
+ let column;
+ let onSortCallBack;
+
+ beforeEach(() => {
+ column = {
+ dataField: 'id',
+ text: 'ID',
+ sort: true
+ };
+ onSortCallBack = sinon.stub().withArgs(column);
+ wrapper = shallow();
+ });
+
+ it('should have sortable class on header cell', () => {
+ expect(wrapper.hasClass('sortable')).toBe(true);
+ });
+
+ it('should have onClick event on header cell', () => {
+ expect(wrapper.find('th').prop('onClick')).toBeDefined();
+ });
+
+ it('should trigger onSort callback when click on header cell', () => {
+ wrapper.find('th').simulate('click');
+ expect(onSortCallBack.callCount).toBe(1);
+ });
+
+ describe('and sorting prop is false', () => {
+ it('header should render SortSymbol as default', () => {
+ expect(wrapper.find(SortSymbol).length).toBe(1);
+ });
+ });
+
+ describe('and sorting prop is true', () => {
+ [Const.SORT_ASC, Const.SORT_DESC].forEach((order) => {
+ describe(`and sortOrder is ${order}`, () => {
+ beforeEach(() => {
+ wrapper = shallow(
+ );
+ });
+
+ it('should render SortCaret correctly', () => {
+ expect(wrapper.find(SortCaret).length).toBe(1);
+ expect(wrapper.find(SortCaret).prop('order')).toEqual(order);
+ });
+ });
+ });
+ });
+
+ describe('when column.headerEvents prop is defined and have custom onClick', () => {
+ beforeEach(() => {
+ column = {
+ dataField: 'id',
+ text: 'ID',
+ sort: true,
+ headerEvents: {
+ onClick: sinon.stub()
+ }
+ };
+ wrapper = shallow(
+ );
+ });
+
+ it('custom event hook should still be called when triggering sorting', () => {
+ wrapper.find('th').simulate('click');
+ expect(onSortCallBack.callCount).toBe(1);
+ expect(column.headerEvents.onClick.callCount).toBe(1);
+ });
+ });
+ });
});
diff --git a/packages/react-bootstrap-table2/test/header.test.js b/packages/react-bootstrap-table2/test/header.test.js
index 80abaa1..3f4e783 100644
--- a/packages/react-bootstrap-table2/test/header.test.js
+++ b/packages/react-bootstrap-table2/test/header.test.js
@@ -3,6 +3,7 @@ import { shallow } from 'enzyme';
import HeaderCell from '../src/header-cell';
import Header from '../src/header';
+import Const from '../src/const';
describe('Header', () => {
let wrapper;
@@ -25,4 +26,21 @@ describe('Header', () => {
expect(wrapper.find(HeaderCell).length).toBe(columns.length);
});
});
+
+ describe('header with columns enable sort', () => {
+ const sortField = columns[1].dataField;
+
+ beforeEach(() => {
+ wrapper = shallow(
+ );
+ });
+
+ it('The HeaderCell should receive correct sorting props', () => {
+ const headerCells = wrapper.find(HeaderCell);
+ expect(headerCells.length).toBe(columns.length);
+ expect(headerCells.at(0).prop('sorting')).toBe(false);
+ expect(headerCells.at(1).prop('sorting')).toBe(true);
+ expect(headerCells.at(1).prop('sortOrder')).toBe(Const.SORT_ASC);
+ });
+ });
});
diff --git a/packages/react-bootstrap-table2/test/sort-caret.test.js b/packages/react-bootstrap-table2/test/sort-caret.test.js
new file mode 100644
index 0000000..933525d
--- /dev/null
+++ b/packages/react-bootstrap-table2/test/sort-caret.test.js
@@ -0,0 +1,37 @@
+import React from 'react';
+import { shallow } from 'enzyme';
+
+import Const from '../src/const';
+import SortCaret from '../src/sort-caret';
+
+describe('SortCaret', () => {
+ let wrapper;
+
+ describe(`when order prop is ${Const.SORT_ASC}`, () => {
+ beforeEach(() => {
+ wrapper = shallow(
+ );
+ });
+
+ it('should render caret correctly', () => {
+ expect(wrapper.length).toBe(1);
+ expect(wrapper.find('span').length).toBe(2);
+ expect(wrapper.find('.caret').length).toBe(1);
+ expect(wrapper.find('.dropup').length).toBe(1);
+ });
+ });
+
+ describe(`when order prop is ${Const.SORT_DESC}`, () => {
+ beforeEach(() => {
+ wrapper = shallow(
+ );
+ });
+
+ it('should render caret correctly', () => {
+ expect(wrapper.length).toBe(1);
+ expect(wrapper.find('span').length).toBe(2);
+ expect(wrapper.find('.caret').length).toBe(1);
+ expect(wrapper.find('.dropup').length).toBe(0);
+ });
+ });
+});
diff --git a/packages/react-bootstrap-table2/test/sort-symbol.test.js b/packages/react-bootstrap-table2/test/sort-symbol.test.js
new file mode 100644
index 0000000..d13346c
--- /dev/null
+++ b/packages/react-bootstrap-table2/test/sort-symbol.test.js
@@ -0,0 +1,19 @@
+import React from 'react';
+import { shallow } from 'enzyme';
+
+import SortSymbol from '../src/sort-symbol';
+
+describe('SortSymbol', () => {
+ let wrapper;
+ beforeEach(() => {
+ wrapper = shallow(
+ );
+ });
+ it('should render sort symbol correctly', () => {
+ expect(wrapper.length).toBe(1);
+ expect(wrapper.find('.order').length).toBe(1);
+ expect(wrapper.find('.caret').length).toBe(2);
+ expect(wrapper.find('.dropdown').length).toBe(1);
+ expect(wrapper.find('.dropup').length).toBe(1);
+ });
+});
diff --git a/packages/react-bootstrap-table2/test/store/base.test.js b/packages/react-bootstrap-table2/test/store/base.test.js
new file mode 100644
index 0000000..e633071
--- /dev/null
+++ b/packages/react-bootstrap-table2/test/store/base.test.js
@@ -0,0 +1,75 @@
+import Base from '../../src/store/base';
+import Const from '../../src/const';
+
+describe('Store Base', () => {
+ let store;
+ const data = [
+ { id: 3, name: 'name2' },
+ { id: 2, name: 'ABC' },
+ { id: 4, name: '123tester' },
+ { id: 1, name: '!@#' }
+ ];
+
+ beforeEach(() => {
+ store = new Base({ data });
+ });
+
+ describe('initialize', () => {
+ it('should have correct initialize data', () => {
+ expect(store.sortOrder).toBeUndefined();
+ expect(store.sortField).toBeUndefined();
+ expect(store.data.length).toEqual(data.length);
+ });
+ });
+
+ describe('isEmpty', () => {
+ beforeEach(() => {
+ store = new Base({ data: [] });
+ });
+
+ it('should have correct initialize data', () => {
+ expect(store.isEmpty()).toBeTruthy();
+ });
+ });
+
+ describe('sortBy', () => {
+ let dataField;
+
+ beforeEach(() => {
+ dataField = 'name';
+ });
+
+ it('should change sortField by dataField param', () => {
+ store.sortBy({ dataField });
+ expect(store.sortField).toEqual(dataField);
+ });
+
+ it('should change sortOrder correctly when sortBy same dataField', () => {
+ store.sortBy({ dataField });
+ expect(store.sortOrder).toEqual(Const.SORT_DESC);
+ store.sortBy({ dataField });
+ expect(store.sortOrder).toEqual(Const.SORT_ASC);
+ });
+
+ it('should change sortOrder correctly when sortBy different dataField', () => {
+ store.sortBy({ dataField });
+ expect(store.sortOrder).toEqual(Const.SORT_DESC);
+
+ dataField = 'id';
+ store.sortBy({ dataField });
+ expect(store.sortOrder).toEqual(Const.SORT_DESC);
+
+ dataField = 'name';
+ store.sortBy({ dataField });
+ expect(store.sortOrder).toEqual(Const.SORT_DESC);
+ });
+
+ it('should have correct result after sortBy', () => {
+ store.sortBy({ dataField });
+ const result = store.data.map(e => e[dataField]).sort((a, b) => b - a);
+ store.get().forEach((e, i) => {
+ expect(e[dataField]).toEqual(result[i]);
+ });
+ });
+ });
+});
diff --git a/packages/react-bootstrap-table2/test/store/sort.test.js b/packages/react-bootstrap-table2/test/store/sort.test.js
new file mode 100644
index 0000000..1eb42ff
--- /dev/null
+++ b/packages/react-bootstrap-table2/test/store/sort.test.js
@@ -0,0 +1,39 @@
+import sinon from 'sinon';
+
+import { sort } from '../../src/store/sort';
+import Const from '../../src/const';
+
+describe('Sort Function', () => {
+ const data = [
+ { id: 3, name: 'name2' },
+ { id: 2, name: 'ABC' },
+ { id: 4, name: '123tester' },
+ { id: 1, name: '!@#' }
+ ];
+
+ it('should sort array with ASC order correctly', () => {
+ const result = sort('id', data, Const.SORT_ASC);
+ expect(result.length).toEqual(data.length);
+
+ const sortedArray = data.map(e => e.id).sort((a, b) => a - b);
+ sortedArray.forEach((e, i) => {
+ expect(e).toEqual(result[i].id);
+ });
+ });
+
+ it('should sort array with DESC order correctly', () => {
+ const result = sort('id', data, Const.SORT_DESC);
+ expect(result.length).toEqual(data.length);
+
+ const sortedArray = data.map(e => e.id).sort((a, b) => b - a);
+ sortedArray.forEach((e, i) => {
+ expect(e).toEqual(result[i].id);
+ });
+ });
+
+ it('should call custom sort function when sortFunc given', () => {
+ const sortFunc = sinon.stub().returns(1);
+ sort('id', data, Const.SORT_DESC, sortFunc);
+ expect(sortFunc.callCount).toBe(6);
+ });
+});