UNPKG

@quantlab/handsontable

Version:

Spreadsheet-like data grid editor that provides copy/paste functionality compatible with Excel/Google Docs

1,640 lines (1,385 loc) 75.9 kB
describe('ColumnSorting', () => { var id = 'testContainer'; beforeEach(function() { this.$container = $(`<div id="${id}" style="overflow: auto; width: 300px; height: 200px;"></div>`).appendTo('body'); this.sortByColumn = function(columnIndex) { var element = this.$container.find(`th span.columnSorting:eq(${columnIndex})`); element.simulate('mousedown'); element.simulate('mouseup'); }; }); afterEach(function() { if (this.$container) { destroy(); this.$container.remove(); } }); var arrayOfObjects = function() { return [ {id: 1, name: 'Ted', lastName: 'Right'}, {id: 2, name: 'Frank', lastName: 'Honest'}, {id: 3, name: 'Joan', lastName: 'Well'}, {id: 4, name: 'Sid', lastName: 'Strong'}, {id: 5, name: 'Jane', lastName: 'Neat'}, {id: 6, name: 'Chuck', lastName: 'Jackson'}, {id: 7, name: 'Meg', lastName: 'Jansen'}, {id: 8, name: 'Rob', lastName: 'Norris'}, {id: 9, name: 'Sean', lastName: 'O\'Hara'}, {id: 10, name: 'Eve', lastName: 'Branson'} ]; }; it('should sort table by first visible column', function() { var hot = handsontable({ data: [ [1, 9, 3, 4, 5, 6, 7, 8, 9], [9, 8, 7, 6, 5, 4, 3, 2, 1], [8, 7, 6, 5, 4, 3, 3, 1, 9], [0, 3, 0, 5, 6, 7, 8, 9, 1] ], colHeaders: true, columnSorting: true }); var htCore = getHtCore(); expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('1'); expect(htCore.find('tbody tr:eq(0) td:eq(1)').text()).toEqual('9'); expect(htCore.find('tbody tr:eq(0) td:eq(2)').text()).toEqual('3'); expect(htCore.find('tbody tr:eq(0) td:eq(3)').text()).toEqual('4'); this.sortByColumn(0); expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0'); expect(htCore.find('tbody tr:eq(0) td:eq(1)').text()).toEqual('3'); expect(htCore.find('tbody tr:eq(0) td:eq(2)').text()).toEqual('0'); expect(htCore.find('tbody tr:eq(0) td:eq(3)').text()).toEqual('5'); }); it('should apply stable sort function #3606', () => { var hot = handsontable({ data: [ ['mercedes1', 'Mercedes', 'A 160', '01/14/2007'], ['citroen1', 'Citroen', 'C4 Coupe', '12/01/2007'], ['opel1', 'Opel', 'Astra', '02/02/2006'], ['bmw1', 'BMW', '320i Coupe', '07/24/2009'], ['citroen2', 'Citroen', 'C4 Coupe', '12/01/2012'], ['opel2', 'Opel', 'Astra', '02/02/2004'], ['mercedes2', 'Mercedes', 'A 160', '01/14/2008'], ['citroen3', 'Citroen', 'C4 Coupe', '12/01/2007'], ['mercedes3', 'Mercedes', 'A 160', '01/14/2009'], ['opel3', 'Opel', 'Astra', '02/02/2006'], ['bmw2', 'BMW', '320i Coupe', '07/24/2013'], ['bmw3', 'BMW', '320i Coupe', '07/24/2012'], ], columns: [ {}, {}, { type: 'date', dateFormat: 'mm/dd/yy' }, { type: 'numeric' } ], columnSorting: true }); hot.sort(1, true); // ASC expect(hot.getDataAtCol(0)).toEqual([ 'bmw1', 'bmw2', 'bmw3', 'citroen1', 'citroen2', 'citroen3', 'mercedes1', 'mercedes2', 'mercedes3', 'opel1', 'opel2', 'opel3' ]); hot.sort(1, false); // DESC expect(hot.getDataAtCol(0)).toEqual([ 'opel1', 'opel2', 'opel3', 'mercedes1', 'mercedes2', 'mercedes3', 'citroen1', 'citroen2', 'citroen3', 'bmw1', 'bmw2', 'bmw3' ]); }); it('should not throw error when trying run handsontable with columnSorting and autoRowSize in the same time.', () => { var errors = 0; try { handsontable({ data: arrayOfObjects(), autoRowSize: true, columnSorting: true }); } catch (e) { errors++; } expect(errors).toBe(0); }); it('should sort numbers descending after 2 clicks on table header', function() { handsontable({ data: arrayOfObjects(), colHeaders: true, columnSorting: true }); this.sortByColumn(0); this.sortByColumn(0); expect(this.$container.find('tr td').first().html()).toEqual('10'); }); it('should remove specified row from sorted table and NOT sort the table again', function() { var hot = handsontable({ data: [ [1, 'B'], [3, 'D'], [2, 'A'], [0, 'C'] ], colHeaders: true, columnSorting: true }); this.sortByColumn(0); var htCore = getHtCore(); expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0'); expect(htCore.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('1'); expect(htCore.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('2'); expect(htCore.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('3'); expect(htCore.find('tbody tr').length).toEqual(4); // Now if sort is launched, sorting ordered will be reversed hot.sortOrder = false; hot.alter('remove_row', 0); expect(htCore.find('tbody tr').length).toEqual(3); expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('1'); expect(htCore.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('2'); expect(htCore.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('3'); }); it('should add an empty row to sorted table', function() { var hot = handsontable({ data: [ [1, 'B'], [0, 'A'], [3, 'D'], [2, 'C'] ], colHeaders: true, columnSorting: true }); this.sortByColumn(0); var htCore = getHtCore(); expect(htCore.find('tbody tr').length).toEqual(4); expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0'); expect(htCore.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('1'); expect(htCore.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('2'); expect(htCore.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('3'); hot.alter('insert_row', 1, 2); expect(htCore.find('tbody tr').length).toEqual(6); expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0'); expect(htCore.find('tbody tr:eq(1) td:eq(0)').text()).toEqual(''); expect(htCore.find('tbody tr:eq(2) td:eq(0)').text()).toEqual(''); expect(htCore.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('1'); expect(htCore.find('tbody tr:eq(4) td:eq(0)').text()).toEqual('2'); expect(htCore.find('tbody tr:eq(5) td:eq(0)').text()).toEqual('3'); }); it('should add an empty row to sorted table at a given index', function() { var hot = handsontable({ data: [ [1, 'B'], [0, 'A'], [3, 'D'], [2, 'C'] ], colHeaders: true, columnSorting: true }); var htCore = getHtCore(); this.sortByColumn(0); expect(htCore.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('3'); expect(htCore.find('tbody tr:eq(4) td:eq(0)').text()).toEqual(''); hot.alter('insert_row', 2); expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0'); expect(htCore.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('1'); expect(htCore.find('tbody tr:eq(2) td:eq(0)').text()).toEqual(''); expect(htCore.find('tbody tr:eq(2) td:eq(0)').text()).toEqual(''); expect(htCore.find('tbody tr:eq(2) td:eq(0)').text()).toEqual(''); expect(htCore.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('2'); }); it('should NOT sort the table after value update in sorted column', function() { var hot = handsontable({ data: [ [1, 'B'], [0, 'A'], [3, 'D'], [2, 'C'] ], colHeaders: true, columnSorting: true }); var htCore = getHtCore(); expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('1'); this.sortByColumn(0); this.sortByColumn(0); expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('3'); expect(htCore.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('2'); hot.setDataAtCell(1, 0, 20); render(); expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('3'); expect(htCore.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('20'); }); it('defaultSort comparing function shouldn\'t change order when comparing empty string, null and undefined', () => { var hot = handsontable({}); var defaultSort = hot.getPlugin('columnSorting').defaultSort; expect(defaultSort(false, {})(['key1', null], ['key2', null])).toEqual(0); expect(defaultSort(false, {})(['key1', ''], ['key2', ''])).toEqual(0); expect(defaultSort(false, {})(['key1', undefined], ['key2', undefined])).toEqual(0); expect(defaultSort(false, {})(['key1', ''], ['key2', null])).toEqual(0); expect(defaultSort(false, {})(['key1', null], ['key2', ''])).toEqual(0); expect(defaultSort(false, {})(['key1', ''], ['key2', undefined])).toEqual(0); expect(defaultSort(false, {})(['key1', undefined], ['key2', ''])).toEqual(0); expect(defaultSort(false, {})(['key1', null], ['key2', undefined])).toEqual(0); expect(defaultSort(false, {})(['key1', undefined], ['key2', null])).toEqual(0); }); it('should place empty strings, null and undefined values at proper position (stability of default comparing function)', () => { var hot = handsontable({ data: [ [null, 'Ted Right'], [undefined, 'Jane Neat'], [null, 'Meg Jansen'], ['', 'Sean Hara'], ['', 'Eve Branson'], [6, 'Frank Honest'], [7, 'Joan Well'], [8, 'Sid Strong'], [9, 'Chuck Jackson'], [10, 'Rob Norris'], [11, 'Eve Well'] ], columnSorting: true }); hot.sort(0, true); // ASC expect(hot.getDataAtCol(1)).toEqual([ 'Frank Honest', 'Joan Well', 'Sid Strong', 'Chuck Jackson', 'Rob Norris', 'Eve Well', // empty cells below 'Ted Right', 'Jane Neat', 'Meg Jansen', 'Sean Hara', 'Eve Branson', ]); hot.sort(0, false); // DESC expect(hot.getDataAtCol(1)).toEqual([ 'Eve Well', 'Rob Norris', 'Chuck Jackson', 'Sid Strong', 'Joan Well', 'Frank Honest', // empty cells below 'Ted Right', 'Jane Neat', 'Meg Jansen', 'Sean Hara', 'Eve Branson', ]); }); it('should place empty strings, null and undefined values at proper position when `sortEmptyCells` option is enabled ' + '(API call, data type: default)', () => { var hot = handsontable({ data: [ [6, 'Frank Honest'], [null, 'Ted Right'], [7, 'Joan Well'], [8, 'Sid Strong'], [undefined, 'Jane Neat'], [9, 'Chuck Jackson'], [null, 'Meg Jansen'], [10, 'Rob Norris'], ['', 'Sean Hara'], ['', 'Eve Branson'] ], columnSorting: { sortEmptyCells: true } }); hot.sort(0, true); // ASC expect(hot.getDataAtCol(1)).toEqual([ 'Ted Right', 'Jane Neat', 'Meg Jansen', 'Sean Hara', 'Eve Branson', // empty cells above 'Frank Honest', 'Joan Well', 'Sid Strong', 'Chuck Jackson', 'Rob Norris' ]); hot.sort(0, false); // DESC expect(hot.getDataAtCol(1)).toEqual([ 'Rob Norris', 'Chuck Jackson', 'Sid Strong', 'Joan Well', 'Frank Honest', // empty cells below 'Ted Right', 'Jane Neat', 'Meg Jansen', 'Sean Hara', 'Eve Branson', ]); }); it('should place empty strings, null and undefined values at proper position when `sortEmptyCells` ' + 'option is enabled and `column` property of `columnSorting` option is set (data type: default)', function() { var hot = handsontable({ data: [ [6, 'Frank Honest'], [null, 'Ted Right'], [7, 'Joan Well'], [8, 'Sid Strong'], [undefined, 'Jane Neat'], [9, 'Chuck Jackson'], [null, 'Meg Jansen'], [10, 'Rob Norris'], ['', 'Sean Hara'], ['', 'Eve Branson'] ], columnSorting: { sortEmptyCells: true, sortOrder: true, column: 0 } }); // ASC expect(hot.getDataAtCol(1)).toEqual([ 'Ted Right', 'Jane Neat', 'Meg Jansen', 'Sean Hara', 'Eve Branson', // empty cells above 'Frank Honest', 'Joan Well', 'Sid Strong', 'Chuck Jackson', 'Rob Norris' ]); if (this.$container) { destroy(); this.$container.remove(); } hot = handsontable({ data: [ [6, 'Frank Honest'], [null, 'Ted Right'], [7, 'Joan Well'], [8, 'Sid Strong'], [undefined, 'Jane Neat'], [9, 'Chuck Jackson'], [null, 'Meg Jansen'], [10, 'Rob Norris'], ['', 'Sean Hara'], ['', 'Eve Branson'] ], columnSorting: { sortEmptyCells: true, sortOrder: false, column: 0 } }); // DESC expect(hot.getDataAtCol(1)).toEqual([ 'Rob Norris', 'Chuck Jackson', 'Sid Strong', 'Joan Well', 'Frank Honest', // empty cells below 'Ted Right', 'Jane Neat', 'Meg Jansen', 'Sean Hara', 'Eve Branson', ]); }); it('should place empty strings, null and undefined values at proper position when `sortEmptyCells` ' + 'option is enabled and `column` property of `columnSorting` option is set (data type: numeric)', function() { var hot = handsontable({ data: [ [6, 'Frank Honest'], [null, 'Ted Right'], [7, 'Joan Well'], [8, 'Sid Strong'], [undefined, 'Jane Neat'], [9, 'Chuck Jackson'], [null, 'Meg Jansen'], [10, 'Rob Norris'], ['', 'Sean Hara'], ['', 'Eve Branson'] ], columns: [ { type: 'numeric' }, {} ], columnSorting: { sortEmptyCells: true, sortOrder: true, column: 0 } }); // ASC expect(hot.getDataAtCol(1)).toEqual([ 'Ted Right', 'Jane Neat', 'Meg Jansen', 'Sean Hara', 'Eve Branson', // empty cells above 'Frank Honest', 'Joan Well', 'Sid Strong', 'Chuck Jackson', 'Rob Norris' ]); if (this.$container) { destroy(); this.$container.remove(); } hot = handsontable({ data: [ [6, 'Frank Honest'], [null, 'Ted Right'], [7, 'Joan Well'], [8, 'Sid Strong'], [undefined, 'Jane Neat'], [9, 'Chuck Jackson'], [null, 'Meg Jansen'], [10, 'Rob Norris'], ['', 'Sean Hara'], ['', 'Eve Branson'] ], columnSorting: { sortEmptyCells: true, sortOrder: false, column: 0 } }); // DESC expect(hot.getDataAtCol(1)).toEqual([ 'Rob Norris', 'Chuck Jackson', 'Sid Strong', 'Joan Well', 'Frank Honest', // empty cells below 'Ted Right', 'Jane Neat', 'Meg Jansen', 'Sean Hara', 'Eve Branson', ]); }); describe('data type: date', () => { it('dateSort comparing function shouldn\'t change order when comparing empty string, null and undefined', () => { var hot = handsontable({}); var dateSort = hot.getPlugin('columnSorting').dateSort; expect(dateSort(false, {})(['key1', null], ['key2', null])).toEqual(0); expect(dateSort(false, {})(['key1', ''], ['key2', ''])).toEqual(0); expect(dateSort(false, {})(['key1', undefined], ['key2', undefined])).toEqual(0); expect(dateSort(false, {})(['key1', ''], ['key2', null])).toEqual(0); expect(dateSort(false, {})(['key1', null], ['key2', ''])).toEqual(0); expect(dateSort(false, {})(['key1', ''], ['key2', undefined])).toEqual(0); expect(dateSort(false, {})(['key1', undefined], ['key2', ''])).toEqual(0); expect(dateSort(false, {})(['key1', null], ['key2', undefined])).toEqual(0); expect(dateSort(false, {})(['key1', undefined], ['key2', null])).toEqual(0); }); it('should place empty strings, null and undefined values at proper position when `sortEmptyCells` ' + 'option is enabled and `column` property of `columnSorting` option is set', function() { var hot = handsontable({ data: [ ['Citroen1', 'C4 Coupe', null], ['Mercedes1', 'A 160', '12/01/2008'], ['Mercedes2', 'A 160', '01/14/2006'], ['Citroen2', 'C4 Coupe', undefined], ['Audi1', 'A4 Avant', '11/19/2011'], ['Opel1', 'Astra', '02/02/2004'], ['Citroen3', 'C4 Coupe', null], ['BMW1', '320i Coupe', '07/24/2011'], ['Citroen4', 'C4 Coupe', ''], ['Citroen5', 'C4 Coupe', ''], ], columns: [ {}, {}, { type: 'date', dateFormat: 'MM/DD/YYYY' } ], columnSorting: { sortEmptyCells: true, sortOrder: true, column: 2 } }); // ASC expect(hot.getDataAtCol(0)).toEqual([ 'Citroen1', 'Citroen2', 'Citroen3', 'Citroen4', 'Citroen5', // empty cells above 'Opel1', 'Mercedes2', 'Mercedes1', 'BMW1', 'Audi1' ]); if (this.$container) { destroy(); this.$container.remove(); } hot = handsontable({ data: [ ['Citroen1', 'C4 Coupe', null], ['Mercedes1', 'A 160', '12/01/2008'], ['Mercedes2', 'A 160', '01/14/2006'], ['Citroen2', 'C4 Coupe', undefined], ['Audi1', 'A4 Avant', '11/19/2011'], ['Opel1', 'Astra', '02/02/2004'], ['Citroen3', 'C4 Coupe', null], ['BMW1', '320i Coupe', '07/24/2011'], ['Citroen4', 'C4 Coupe', ''], ['Citroen5', 'C4 Coupe', ''], ], columns: [ {}, {}, { type: 'date', dateFormat: 'MM/DD/YYYY' } ], columnSorting: { sortEmptyCells: true, sortOrder: false, column: 2 } }); // DESC expect(hot.getDataAtCol(0)).toEqual([ 'Audi1', 'BMW1', 'Mercedes1', 'Mercedes2', 'Opel1', // empty cells below 'Citroen1', 'Citroen2', 'Citroen3', 'Citroen4', 'Citroen5' ]); }); it('should sort date columns (MM/DD/YYYY)', () => { var hot = handsontable({ data: [ ['Mercedes', 'A 160', '01/14/2006', 6999.9999], ['Citroen', 'C4 Coupe', '12/01/2008', 8330], ['Audi', 'A4 Avant', '11/19/2011', 33900], ['Opel', 'Astra', '02/02/2004', 7000], ['BMW', '320i Coupe', '07/24/2011', 30500] ], columns: [ {}, {}, { type: 'date', dateFormat: 'MM/DD/YYYY' }, { type: 'numeric' } ], colHeaders: true, columnSorting: true }); hot.sort(2, true); // ASC expect(hot.getDataAtRow(0)).toEqual(['Opel', 'Astra', '02/02/2004', 7000]); expect(hot.getDataAtRow(1)).toEqual(['Mercedes', 'A 160', '01/14/2006', 6999.9999]); expect(hot.getDataAtRow(2)).toEqual(['Citroen', 'C4 Coupe', '12/01/2008', 8330]); expect(hot.getDataAtRow(3)).toEqual(['BMW', '320i Coupe', '07/24/2011', 30500]); expect(hot.getDataAtRow(4)).toEqual(['Audi', 'A4 Avant', '11/19/2011', 33900]); hot.sort(2, false); // DESC expect(hot.getDataAtRow(0)).toEqual(['Audi', 'A4 Avant', '11/19/2011', 33900]); expect(hot.getDataAtRow(1)).toEqual(['BMW', '320i Coupe', '07/24/2011', 30500]); expect(hot.getDataAtRow(2)).toEqual(['Citroen', 'C4 Coupe', '12/01/2008', 8330]); expect(hot.getDataAtRow(3)).toEqual(['Mercedes', 'A 160', '01/14/2006', 6999.9999]); expect(hot.getDataAtRow(4)).toEqual(['Opel', 'Astra', '02/02/2004', 7000]); }); it('should sort date columns (DD/MM/YYYY)', () => { var hot = handsontable({ data: [ ['Mercedes', 'A 160', '01/12/2012', 6999.9999], ['Citroen', 'C4 Coupe', '12/01/2013', 8330], ['Audi', 'A4 Avant', '11/10/2014', 33900], ['Opel', 'Astra', '02/02/2015', 7000], ['BMW', '320i Coupe', '07/02/2013', 30500] ], columns: [ {}, {}, { type: 'date', dateFormat: 'DD/MM/YYYY' }, { type: 'numeric' } ], colHeaders: true, columnSorting: true }); hot.sort(2, true); // ASC expect(hot.getDataAtRow(0)).toEqual(['Mercedes', 'A 160', '01/12/2012', 6999.9999]); expect(hot.getDataAtRow(1)).toEqual(['Citroen', 'C4 Coupe', '12/01/2013', 8330]); expect(hot.getDataAtRow(2)).toEqual(['BMW', '320i Coupe', '07/02/2013', 30500]); expect(hot.getDataAtRow(3)).toEqual(['Audi', 'A4 Avant', '11/10/2014', 33900]); expect(hot.getDataAtRow(4)).toEqual(['Opel', 'Astra', '02/02/2015', 7000]); hot.sort(2, false); // DESC expect(hot.getDataAtRow(0)).toEqual(['Opel', 'Astra', '02/02/2015', 7000]); expect(hot.getDataAtRow(1)).toEqual(['Audi', 'A4 Avant', '11/10/2014', 33900]); expect(hot.getDataAtRow(2)).toEqual(['BMW', '320i Coupe', '07/02/2013', 30500]); expect(hot.getDataAtRow(3)).toEqual(['Citroen', 'C4 Coupe', '12/01/2013', 8330]); expect(hot.getDataAtRow(4)).toEqual(['Mercedes', 'A 160', '01/12/2012', 6999.9999]); }); it('should sort date columns (MMMM Do YYYY)', () => { var hot = handsontable({ data: [ ['Mercedes', 'A 160', 'October 28th 2016', 6999.9999], ['Citroen', 'C4 Coupe', 'October 27th 2001', 8330], ['Audi', 'A4 Avant', 'July 8th 1999', 33900], ['Opel', 'Astra', 'June 1st 2001', 7000], ['BMW', '320i Coupe', 'August 3rd 2001', 30500] ], columns: [ {}, {}, { type: 'date', dateFormat: 'MMMM Do YYYY' }, { type: 'numeric' } ], colHeaders: true, columnSorting: true }); hot.sort(2, true); // ASC expect(hot.getDataAtRow(0)).toEqual(['Audi', 'A4 Avant', 'July 8th 1999', 33900]); expect(hot.getDataAtRow(1)).toEqual(['Opel', 'Astra', 'June 1st 2001', 7000]); expect(hot.getDataAtRow(2)).toEqual(['BMW', '320i Coupe', 'August 3rd 2001', 30500]); expect(hot.getDataAtRow(3)).toEqual(['Citroen', 'C4 Coupe', 'October 27th 2001', 8330]); expect(hot.getDataAtRow(4)).toEqual(['Mercedes', 'A 160', 'October 28th 2016', 6999.9999]); hot.sort(2, false); // DESC expect(hot.getDataAtRow(0)).toEqual(['Mercedes', 'A 160', 'October 28th 2016', 6999.9999]); expect(hot.getDataAtRow(1)).toEqual(['Citroen', 'C4 Coupe', 'October 27th 2001', 8330]); expect(hot.getDataAtRow(2)).toEqual(['BMW', '320i Coupe', 'August 3rd 2001', 30500]); expect(hot.getDataAtRow(3)).toEqual(['Opel', 'Astra', 'June 1st 2001', 7000]); expect(hot.getDataAtRow(4)).toEqual(['Audi', 'A4 Avant', 'July 8th 1999', 33900]); }); it('should sort date columns along with empty and null values', () => { var hot = handsontable({ data: [ ['Mercedes', 'A 160', '01/14/2006', 6999.9999], ['Citroen', 'C4 Coupe', '12/01/2008', 8330], ['Citroen', 'C4 Coupe null', null, 8330], ['Citroen', 'C4 Coupe empty', '', 8330], ['Audi', 'A4 Avant', '11/19/2011', 33900], ['Opel', 'Astra', '02/02/2004', 7000], ['BMW', '320i Coupe', '07/24/2011', 30500] ], columns: [ {}, {}, { type: 'date', dateFormat: 'mm/dd/yy' }, { type: 'numeric' } ], colHeaders: true, columnSorting: true }); hot.sort(2, true); // ASC expect(hot.getDataAtRow(0)).toEqual(['Mercedes', 'A 160', '01/14/2006', 6999.9999]); expect(hot.getDataAtRow(1)).toEqual(['Opel', 'Astra', '02/02/2004', 7000]); expect(hot.getDataAtRow(2)).toEqual(['BMW', '320i Coupe', '07/24/2011', 30500]); expect(hot.getDataAtRow(3)).toEqual(['Audi', 'A4 Avant', '11/19/2011', 33900]); expect(hot.getDataAtRow(4)).toEqual(['Citroen', 'C4 Coupe', '12/01/2008', 8330]); hot.sort(2, false); // DESC expect(hot.getDataAtRow(0)).toEqual(['Citroen', 'C4 Coupe', '12/01/2008', 8330]); expect(hot.getDataAtRow(1)).toEqual(['Audi', 'A4 Avant', '11/19/2011', 33900]); expect(hot.getDataAtRow(2)).toEqual(['BMW', '320i Coupe', '07/24/2011', 30500]); expect(hot.getDataAtRow(3)).toEqual(['Opel', 'Astra', '02/02/2004', 7000]); expect(hot.getDataAtRow(4)).toEqual(['Mercedes', 'A 160', '01/14/2006', 6999.9999]); }); }); describe('data type: time', () => { it('should properly rewrite time into correct format after sort', (done) => { var hot = handsontable({ data: [ ['0:00:01 am'], ['5:30:14 pm'], ['8:00:00 pm'], ['11:15:05 am'], ['4:07:48 am'] ], columns: [ { type: 'time', dateFormat: 'h:mm:ss a', correctFormat: true } ], colHeaders: true, columnSorting: { column: 0, sortOrder: false } }); hot.setDataAtCell(0, 0, '19:55', 'edit'); setTimeout(() => { expect(hot.getDataAtCell(0, 0)).toEqual('7:55:00 pm'); done(); }, 250); }); }); it('should properly sort numeric data', function() { var hot = handsontable({ data: [ ['Mercedes', 'A 160', '01/14/2006', '6999.9999'], ['Citroen', 'C4 Coupe', '12/01/2008', 8330], ['Citroen', 'C4 Coupe null', null, '8330'], ['Citroen', 'C4 Coupe empty', '', 8333], ['Audi', 'A4 Avant', '11/19/2011', '33900'], ['Opel', 'Astra', '02/02/2004', '7000'], ['BMW', '320i Coupe', '07/24/2011', 30500] ], columns: [ {}, {}, {}, { type: 'numeric' } ], colHeaders: true, columnSorting: true }); var htCore = getHtCore(); this.sortByColumn(3); expect(hot.getDataAtCol(3)).toEqual(['6999.9999', '7000', 8330, '8330', 8333, 30500, '33900']); this.sortByColumn(3); expect(hot.getDataAtCol(3)).toEqual(['33900', 30500, 8333, 8330, '8330', '7000', '6999.9999']); this.sortByColumn(3); expect(hot.getDataAtCol(3)).toEqual(['6999.9999', 8330, '8330', 8333, '33900', '7000', 30500]); }); it('numericSort comparing function shouldn\'t change order when comparing empty string, null and undefined', () => { var hot = handsontable({}); var numericSort = hot.getPlugin('columnSorting').numericSort; expect(numericSort(false, {})(['key1', null], ['key2', null])).toEqual(0); expect(numericSort(false, {})(['key1', ''], ['key2', ''])).toEqual(0); expect(numericSort(false, {})(['key1', undefined], ['key2', undefined])).toEqual(0); expect(numericSort(false, {})(['key1', ''], ['key2', null])).toEqual(0); expect(numericSort(false, {})(['key1', null], ['key2', ''])).toEqual(0); expect(numericSort(false, {})(['key1', ''], ['key2', undefined])).toEqual(0); expect(numericSort(false, {})(['key1', undefined], ['key2', ''])).toEqual(0); expect(numericSort(false, {})(['key1', null], ['key2', undefined])).toEqual(0); expect(numericSort(false, {})(['key1', undefined], ['key2', null])).toEqual(0); }); it('should sort table with multiple row headers', function() { var hot = handsontable({ data: [ [1, 'B'], [0, 'D'], [3, 'A'], [2, 'C'] ], columns: [ {}, {}, { type: 'date', dateFormat: 'mm/dd/yy' }, { type: 'numeric' } ], colHeaders: true, columnSorting: true, removeRowPlugin: true // this plugin ads an extra row header, so now we have 2 instead of 1 }); expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('1'); this.sortByColumn(0); // sort by first column expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0'); expect(this.$container.find('tbody tr:eq(0) td:eq(1)').text()).toEqual('D'); this.sortByColumn(1); // sort by second column expect(this.$container.find('tbody tr:eq(0) td:eq(1)').text()).toEqual('A'); }); it('should allow to define sorting column and order during initialization', function() { var hot = handsontable({ data: [ [1, 'B'], [0, 'D'], [3, 'A'], [2, 'C'] ], colHeaders: true, columnSorting: { column: 0, sortOrder: true } }); expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0'); expect(this.$container.find('tbody tr:eq(0) td:eq(1)').text()).toEqual('D'); }); it('should allow to change sorting column with updateSettings', function() { var hot = handsontable({ data: [ [1, 'B'], [0, 'D'], [3, 'A'], [2, 'C'] ], colHeaders: true, columnSorting: { column: 0, sortOrder: true } }); expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0'); expect(this.$container.find('tbody tr:eq(0) td:eq(1)').text()).toEqual('D'); updateSettings({ columnSorting: { column: 1, sortOrder: true } }); expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('3'); expect(this.$container.find('tbody tr:eq(0) td:eq(1)').text()).toEqual('A'); }); it('should allow to change sorting order with updateSettings', function() { var hot = handsontable({ data: [ [1, 'B'], [0, 'D'], [3, 'A'], [2, 'C'] ], colHeaders: true, columnSorting: { column: 0, sortOrder: true } }); expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0'); updateSettings({ columnSorting: { column: 0, sortOrder: false } }); expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('3'); }); it('should allow to change if sorting empty cells with updateSettings', () => { var hot = handsontable({ data: [ [1, 'B'], [2, ''], [3, 'A'], [4, ''], [6, 'E'], [7, ''], [8, 'F'], ], colHeaders: true, columnSorting: { column: 1, sortOrder: false, sortEmptyCells: false } }); updateSettings({ columnSorting: { column: 1, sortOrder: true, sortEmptyCells: true } }); // ASC with empty cells sorting expect(hot.getDataAtCol(0)).toEqual([2, 4, 7, 3, 1, 6, 8]); updateSettings({ columnSorting: { column: 1, sortOrder: true, sortEmptyCells: false } }); // ASC without empty cells sorting expect(hot.getDataAtCol(0)).toEqual([3, 1, 6, 8, 2, 4, 7]); }); it('should NOT sort spare rows', () => { var myData = [ {a: 'aaa', b: 2, c: 3}, {a: 'z', b: 11, c: -4}, {a: 'dddd', b: 13, c: 13}, {a: 'bbbb', b: 10, c: 11} ]; function customIsEmptyRow(row) { var data = this.getSourceData(); return data[row].isNew; } handsontable({ data: myData, rowHeaders: true, colHeaders: ['A', 'B', 'C'], columns: [ {data: 'a', type: 'text'}, {data: 'b', type: 'text'}, {data: 'c', type: 'text'} ], dataSchema: {isNew: true, a: false}, // default for a to avoid #bad value# columnSorting: true, minSpareRows: 3, isEmptyRow: customIsEmptyRow }); // ASC updateSettings({ columnSorting: { column: 0, sortOrder: true } }); expect(getData()).toEqual([ ['aaa', 2, 3], ['bbbb', 10, 11], ['dddd', 13, 13], ['z', 11, -4], [false, null, null], [false, null, null], [false, null, null] ]); updateSettings({ columnSorting: { column: 0, sortOrder: false } }); expect(getData()).toEqual([ ['z', 11, -4], ['dddd', 13, 13], ['bbbb', 10, 11], ['aaa', 2, 3], [false, null, null], [false, null, null], [false, null, null] ]); }); it('should reset column sorting with updateSettings', function() { var hot = handsontable({ data: [ [1, 'B'], [0, 'D'], [3, 'A'], [2, 'C'] ], colHeaders: true, columnSorting: { column: 0, sortOrder: true } }); expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0'); updateSettings({ columnSorting: void 0 }); expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('1'); }); it('should expose sort method when columnSorting is enabled', () => { var hot = handsontable(); expect(hot.getSettings().columnSorting).toBeFalsy(); expect(hot.sort).toBeUndefined(); updateSettings({ columnSorting: true }); expect(hot.getSettings().columnSorting).toBe(true); expect(hot.sort).toBeDefined(); expect(typeof hot.sort).toBe('function'); updateSettings({ columnSorting: false }); expect(hot.getSettings().columnSorting).toBeFalsy(); expect(hot.sort).toBeUndefined(); }); it('should sort table using HOT.sort method', function() { var hot = handsontable({ data: [ [1, 'B'], [0, 'D'], [3, 'A'], [2, 'C'] ], columnSorting: true }); expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('1'); expect(this.$container.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('0'); expect(this.$container.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('3'); expect(this.$container.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('2'); hot.sort(0, true); expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0'); expect(this.$container.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('1'); expect(this.$container.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('2'); expect(this.$container.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('3'); }); it('should reset column sorting with updateSettings', function() { var hot = handsontable({ data: [ [1, 'B'], [0, 'D'], [3, 'A'], [2, 'C'] ], colHeaders: true, columnSorting: { column: 0, sortOrder: true } }); expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0'); updateSettings({ columnSorting: void 0 }); expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('1'); }); it('should fire beforeColumnSort event before sorting data', function() { var hot = handsontable({ data: [ [2], [4], [1], [3] ], columnSorting: true }); this.beforeColumnSortHandler = function() { expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('2'); expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('4'); expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('1'); expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('3'); }; spyOn(this, 'beforeColumnSortHandler'); hot.addHook('beforeColumnSort', this.beforeColumnSortHandler); var sortColumn = 0; var sortOrder = true; hot.sort(sortColumn, sortOrder); expect(this.beforeColumnSortHandler.calls.count()).toEqual(1); expect(this.beforeColumnSortHandler).toHaveBeenCalledWith(sortColumn, sortOrder, void 0, void 0, void 0, void 0); }); it('should not sorting column when beforeColumnSort returns false', (done) => { var hot = handsontable({ data: [ [2], [4], [1], [3] ], columnSorting: true, beforeColumnSort() { return false; } }); hot.sort(0, true); setTimeout(() => { expect(spec().$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('2'); expect(spec().$container.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('4'); expect(spec().$container.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('1'); expect(spec().$container.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('3'); done(); }, 200); }); it('should add beforeColumnSort event listener in constructor', () => { var beforeColumnSortCallback = jasmine.createSpy('beforeColumnSortHandler'); var hot = handsontable({ data: [[2], [4], [1], [3]], columnSorting: true, beforeColumnSort: beforeColumnSortCallback }); var sortColumn = 0; var sortOrder = true; hot.sort(sortColumn, sortOrder); expect(beforeColumnSortCallback.calls.count()).toEqual(1); expect(beforeColumnSortCallback).toHaveBeenCalledWith(sortColumn, sortOrder, void 0, void 0, void 0, void 0); }); it('should fire afterColumnSort event before data has been sorted but before table render', () => { var hot = handsontable({ data: [ [2], [4], [1], [3] ], columnSorting: true }); var rendered = false; var afterColumnSortHandler = jasmine.createSpy('afterColumnSortHandler'); var afterRenderSpy = jasmine.createSpy('afterRender'); hot.addHook('afterColumnSort', function() { expect(rendered).toBe(false); afterColumnSortHandler.apply(afterColumnSortHandler, arguments); }); hot.addHook('afterRender', function() { rendered = true; afterRenderSpy.apply(afterRenderSpy, arguments); }); var sortColumn = 0; var sortOrder = true; afterRenderSpy.calls.reset(); hot.sort(sortColumn, sortOrder); expect(afterColumnSortHandler.calls.count()).toBe(1); expect(afterColumnSortHandler).toHaveBeenCalledWith(sortColumn, sortOrder, void 0, void 0, void 0, void 0); expect(afterRenderSpy.calls.count()).toBe(1); }); it('should add afterColumnSort event listener in constructor', () => { var afterColumnSortCallback = jasmine.createSpy('afterColumnSortHandler'); var hot = handsontable({ data: [[2], [4], [1], [3]], columnSorting: true, afterColumnSort: afterColumnSortCallback }); var sortColumn = 0; var sortOrder = true; hot.sort(sortColumn, sortOrder); expect(afterColumnSortCallback.calls.count()).toEqual(1); expect(afterColumnSortCallback).toHaveBeenCalledWith(sortColumn, sortOrder, void 0, void 0, void 0, void 0); }); it('should insert row when plugin is enabled, but table hasn\'t been sorted', () => { var hot = handsontable({ data: [ [1, 'B'], [0, 'D'], [3, 'A'], [2, 'C'] ], columnSorting: true }); expect(countRows()).toEqual(4); expect(hot.sortColumn).toBeUndefined(); alter('insert_row'); expect(countRows()).toEqual(5); }); it('should remove row when plugin is enabled, but table hasn\'t been sorted', () => { var hot = handsontable({ data: [ [1, 'B'], [0, 'D'], [3, 'A'], [2, 'C'] ], columnSorting: true }); expect(countRows()).toEqual(4); expect(hot.sortColumn).toBeUndefined(); alter('remove_row'); expect(countRows()).toEqual(3); }); it('should display new row added directly to dataSource, when observeChanges plugin is enabled', function(done) { var data = [ [1, 'B'], [0, 'A'], [3, 'D'], [2, 'C'] ]; var hot = handsontable({ data, colHeaders: true, columnSorting: true, observeChanges: true }); var htCore = getHtCore(); expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('1'); expect(htCore.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('0'); expect(htCore.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('3'); expect(htCore.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('2'); this.sortByColumn(0); expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0'); expect(htCore.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('1'); expect(htCore.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('2'); expect(htCore.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('3'); expect(htCore.find('tbody tr').length).toEqual(4); var afterChangesObservedCallback = jasmine.createSpy('afterChangesObservedCallback'); hot.addHook('afterChangesObserved', afterChangesObservedCallback); data.push([5, 'E']); setTimeout(() => { expect(countRows()).toEqual(5); expect(spec().$container.find('tbody tr:eq(4) td:eq(0)').text()).toEqual('5'); expect(spec().$container.find('tbody tr:eq(4) td:eq(1)').text()).toEqual('E'); done(); }, 200); }); it('should not display new row added directly to dataSource, when observeChanges plugin is explicitly disabled', function(done) { var data = [ [1, 'B'], [0, 'A'], [3, 'D'], [2, 'C'] ]; var hot = handsontable({ data, colHeaders: true, columnSorting: true, observeChanges: false }); var afterChangesObservedCallback = jasmine.createSpy('afterChangesObservedCallback'); hot.addHook('afterChangesObserved', afterChangesObservedCallback); var htCore = getHtCore(); expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('1'); expect(htCore.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('0'); expect(htCore.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('3'); expect(htCore.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('2'); this.sortByColumn(0); expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0'); expect(htCore.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('1'); expect(htCore.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('2'); expect(htCore.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('3'); expect(htCore.find('tbody tr').length).toEqual(4); data.push([5, 'E']); setTimeout(() => { expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0'); expect(htCore.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('1'); expect(htCore.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('2'); expect(htCore.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('3'); expect(htCore.find('tbody tr').length).toEqual(4); expect(afterChangesObservedCallback).not.toHaveBeenCalled(); done(); }, 100); }); it('should display new row added directly to dataSource, when observeChanges plugin status is undefined', (done) => { var data = [ [1, 'B'], [0, 'A'], [3, 'D'], [2, 'C'] ]; var onUpdateSettings = jasmine.createSpy('onUpdateSettings'); var hot = handsontable({ data, colHeaders: true, columnSorting: true, afterUpdateSettings: onUpdateSettings }); var afterChangesObservedCallback = jasmine.createSpy('afterChangesObservedCallback'); hot.addHook('afterChangesObserved', afterChangesObservedCallback); var htCore = getHtCore(); // columnSorting enables observeChanges plugin by asynchronously invoking updateSettings setTimeout(() => { expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('1'); expect(htCore.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('0'); expect(htCore.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('3'); expect(htCore.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('2'); spec().sortByColumn(0); expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0'); expect(htCore.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('1'); expect(htCore.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('2'); expect(htCore.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('3'); expect(htCore.find('tbody tr').length).toEqual(4); data.push([5, 'E']); }, 100); setTimeout(() => { expect(countRows()).toEqual(5); expect(htCore.find('tbody tr:eq(4) td:eq(0)').text()).toEqual('5'); expect(htCore.find('tbody tr:eq(4) td:eq(1)').text()).toEqual('E'); done(); }, 2000); // 2s delayed needs for safari env }); it('should apply sorting when there are two tables and only one has sorting enabled and has been already sorted (#1020)', function() { var hot = handsontable({ data: [ [1, 'B'], [0, 'D'], [3, 'A'], [2, 'C'] ], columnSorting: { column: 1 } }); this.$container2 = $(`<div id="${id}-2"></div>`).appendTo('body'); this.$container2.handsontable(); var hot2 = this.$container2.handsontable('getInstance'); selectCell(0, 1); keyDown('enter'); expect($('.handsontableInput').val()).toEqual('A'); this.$container2.handsontable('destroy'); this.$container2.remove(); }); it('should reset sorting after loading new data', function() { var hot = handsontable({ data: [ [1, 'B'], [0, 'D'], [3, 'A'], [2, 'C'] ], columnSorting: true }); expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('1'); expect(this.$container.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('0'); expect(this.$container.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('3'); expect(this.$container.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('2'); hot.sort(0, true); expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0'); expect(this.$container.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('1'); expect(this.$container.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('2'); expect(this.$container.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('3'); loadData([ [50, 'E'], [10, 'G'], [30, 'F'], [60, 'I'], [40, 'J'], [20, 'H'] ]); expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('50'); expect(this.$container.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('10'); expect(this.$container.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('30'); expect(this.$container.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('60'); expect(this.$container.find('tbody tr:eq(4) td:eq(0)').text()).toEqual('40'); expect(this.$container.find('tbody tr:eq(5) td:eq(0)').text()).toEqual('20'); }); it('should reset sorting after loading new data (default sorting column and order set)', function() { var hot = handsontable({ data: [ [1, 'B'], [0, 'D'], [3, 'A'], [2, 'C'] ], columnSorting: { column: 1, sortOrder: true } }); expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('3'); expect(this.$container.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('1'); expect(this.$container.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('2'); expect(this.$container.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('0'); expect(this.$container.find('tbody tr:eq(0) td:eq(1)').text()).toEqual('A'); expect(this.$container.find('tbody tr:eq(1) td:eq(1)').text()).toEqual('B'); expect(this.$container.find('tbody tr:eq(2) td:eq(1)').text()).toEqual('C'); expect(this.$container.find('tbody tr:eq(3) td:eq(1)').text()).toEqual('D'); hot.sort(0, true); expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0'); expect(this.$container.find('tbody tr:eq(1) td:eq(0)').text()