| <!DOCTYPE html> |
| <!-- |
| Copyright (c) 2014 The Chromium Authors. All rights reserved. |
| Use of this source code is governed by a BSD-style license that can be |
| found in the LICENSE file. |
| --> |
| |
| <link rel="import" href="/tracing/ui/base/deep_utils.html"> |
| <link rel="import" href="/tracing/ui/base/table.html"> |
| |
| <script> |
| 'use strict'; |
| |
| tr.b.unittest.testSuite(function() { |
| var THIS_DOC = document.currentScript.ownerDocument; |
| var SelectionMode = tr.ui.b.TableFormat.SelectionMode; |
| var HighlightStyle = tr.ui.b.TableFormat.HighlightStyle; |
| var ColumnAlignment = tr.ui.b.TableFormat.ColumnAlignment; |
| |
| function isSelected(element) { |
| if (!element.hasAttribute('selected')) |
| return false; |
| return element.getAttribute('selected') === 'true'; |
| } |
| |
| function simulateDoubleClick(element) { |
| // See https://developer.mozilla.org/en/docs/Web/API/MouseEvent#Example. |
| var event = new MouseEvent('dblclick', { |
| bubbles: true, |
| cancelable: true, |
| view: window |
| }); |
| return element.dispatchEvent(event); |
| } |
| |
| test('instantiateEmptyTable_withoutEmptyValue', function() { |
| var columns = [ |
| { |
| title: 'First Column', |
| value: function(row) { return row.firstData; }, |
| width: '300px' |
| }, |
| { |
| title: 'Second Column', |
| value: function(row) { return row.secondData; } |
| } |
| ]; |
| |
| var table = document.createElement('tr-ui-b-table'); |
| table.tableColumns = columns; |
| table.tableRows = []; |
| table.rebuild(); |
| |
| this.addHTMLOutput(table); |
| |
| // Check that the width of the first column was set correctly (despite no |
| // body rows). |
| var firstColumnHeader = table.$.head.children[0].children[0]; |
| assert.closeTo(firstColumnHeader.offsetWidth, 300, 20); |
| |
| // Check that the first column has a non-empty header. |
| var firstColumnTitle = tr.b.findDeepElementMatchingPredicate( |
| firstColumnHeader, function(element) { |
| return Polymer.dom(element).textContent === 'First Column'; |
| }); |
| assert.isDefined(firstColumnTitle); |
| |
| // Check that empty value was not appended. |
| assert.lengthOf(table.$.body.children, 0); |
| }); |
| |
| test('instantiateEmptyTable_withEmptyValue', function() { |
| var columns = [ |
| { |
| title: 'First Column', |
| value: function(row) { return row.firstData; }, |
| width: '300px' |
| }, |
| { |
| title: 'Second Column', |
| value: function(row) { return row.secondData; } |
| } |
| ]; |
| |
| var table = document.createElement('tr-ui-b-table'); |
| table.tableColumns = columns; |
| table.tableRows = []; |
| table.emptyValue = 'This table is left intentionally empty'; |
| table.rebuild(); |
| |
| this.addHTMLOutput(table); |
| |
| // Check that the width of the first column was set correctly (despite no |
| // body rows). |
| var firstColumnHeader = table.$.head.children[0].children[0]; |
| assert.closeTo(firstColumnHeader.offsetWidth, 300, 20); |
| |
| // Check that empty value was appended. |
| assert.lengthOf(table.$.body.children, 1); |
| }); |
| |
| test('instantiateNestedTableNoNests', function() { |
| var columns = [ |
| { |
| title: 'First Column', |
| value: function(row) { return row.firstData; }, |
| width: '200px' |
| }, |
| { |
| title: 'Second Column', |
| value: function(row) { return row.secondData; } |
| } |
| ]; |
| |
| var rows = [ |
| { |
| firstData: 'A1', |
| secondData: 'A2' |
| }, |
| { |
| firstData: 'B1', |
| secondData: 'B2' |
| } |
| ]; |
| |
| var table = document.createElement('tr-ui-b-table'); |
| table.tableColumns = columns; |
| table.tableRows = rows; |
| table.emptyValue = 'THIS SHOULD NOT BE VISIBLE!!!'; |
| table.rebuild(); |
| |
| this.addHTMLOutput(table); |
| |
| // Check that empty value was not appended. |
| assert.lengthOf(table.$.body.children, 2); |
| }); |
| |
| test('sequentialRebuildsBehaveSanely', function() { |
| var columns = [ |
| { |
| title: 'First Column', |
| value: function(row) { return row.firstData; }, |
| width: '200px' |
| }, |
| { |
| title: 'Second Column', |
| value: function(row) { return row.secondData; } |
| } |
| ]; |
| |
| var rows = [ |
| { |
| firstData: 'A1', |
| secondData: 'A2' |
| }, |
| { |
| firstData: 'B1', |
| secondData: 'B2' |
| } |
| ]; |
| var footerRows = [ |
| { |
| firstData: 'A1', |
| secondData: 'A2' |
| }, |
| { |
| firstData: 'B1', |
| secondData: 'B2' |
| } |
| ]; |
| |
| var table = document.createElement('tr-ui-b-table'); |
| table.tableColumns = columns; |
| table.tableRows = rows; |
| table.footerRows = footerRows; |
| table.rebuild(); |
| table.rebuild(); |
| assert.equal(table.$.body.children.length, 2); |
| assert.equal(table.$.foot.children.length, 2); |
| |
| this.addHTMLOutput(table); |
| }); |
| |
| test('instantiateNestedTableWithNests', function() { |
| var columns = [ |
| { |
| title: 'First Column', |
| value: function(row) { return row.firstData; }, |
| width: '250px' |
| }, |
| { |
| title: 'Second Column', |
| value: function(row) { return row.secondData; }, |
| width: '50%' |
| } |
| ]; |
| |
| var rows = [ |
| { |
| firstData: 'A1', |
| secondData: 'A2', |
| subRows: [ |
| { |
| firstData: 'Sub1 A1', |
| secondData: 'Sub1 A2' |
| }, |
| { |
| firstData: 'Sub2 A1', |
| secondData: 'Sub2 A2', |
| subRows: [ |
| { |
| firstData: 'SubSub1 A1', |
| secondData: 'SubSub1 A2' |
| }, |
| { |
| firstData: 'SubSub2 A1', |
| secondData: 'SubSub2 A2' |
| } |
| ] |
| }, |
| { |
| firstData: 'Sub3 A1', |
| secondData: 'Sub3 A2' |
| } |
| ] |
| }, |
| { |
| firstData: 'B1', |
| secondData: 'B2' |
| } |
| ]; |
| |
| var table = document.createElement('tr-ui-b-table'); |
| table.tableColumns = columns; |
| table.tableRows = rows; |
| table.rebuild(); |
| |
| this.addHTMLOutput(table); |
| }); |
| |
| test('instantiateSortingCallbacksWithNests', function() { |
| var table = document.createElement('tr-ui-b-table'); |
| |
| var columns = [ |
| { |
| title: 'First Column', |
| value: function(row) { return row.firstData; }, |
| width: '50%' |
| }, |
| { |
| title: 'Second Column', |
| value: function(row) { return row.secondData; }, |
| width: '250px', |
| cmp: function(rowA, rowB) { |
| return rowA.secondData.toString().localeCompare( |
| rowB.secondData.toString()); |
| }, |
| showExpandButtons: true |
| } |
| ]; |
| |
| var rows = [ |
| { |
| firstData: 'A1', |
| secondData: 'A2', |
| subRows: [ |
| { |
| firstData: 'Sub1 A1', |
| secondData: 'Sub1 A2' |
| }, |
| { |
| firstData: 'Sub2 A1', |
| secondData: 'Sub2 A2', |
| subRows: [ |
| { |
| firstData: 'SubSub1 A1', |
| secondData: 'SubSub1 A2' |
| }, |
| { |
| firstData: 'SubSub2 A1', |
| secondData: 'SubSub2 A2' |
| } |
| ] |
| }, |
| { |
| firstData: 'Sub3 A1', |
| secondData: 'Sub3 A2' |
| } |
| ] |
| }, |
| { |
| firstData: 'B1', |
| secondData: 'B2' |
| } |
| ]; |
| |
| var footerRows = [ |
| { |
| firstData: 'F1', |
| secondData: 'F2', |
| subRows: [ |
| { |
| firstData: 'Sub1F1', |
| secondData: 'Sub1F2' |
| }, |
| { |
| firstData: 'Sub2F1', |
| secondData: 'Sub2F2', |
| subRows: [ |
| { |
| firstData: 'SubSub1F1', |
| secondData: 'SubSub1F2' |
| }, |
| { |
| firstData: 'SubSub2F1', |
| secondData: 'SubSub2F2' |
| } |
| ] |
| }, |
| { |
| firstData: 'Sub3F1', |
| secondData: 'Sub3F2' |
| } |
| ] |
| }, |
| { |
| firstData: 'F\'1', |
| secondData: 'F\'2' |
| } |
| |
| ]; |
| |
| table.tableColumns = columns; |
| table.tableRows = rows; |
| table.footerRows = footerRows; |
| table.rebuild(); |
| |
| this.addHTMLOutput(table); |
| |
| var button = THIS_DOC.createElement('button'); |
| Polymer.dom(button).textContent = 'Sort By Col 0'; |
| button.addEventListener('click', function() { |
| table.sortDescending = !table.sortDescending; |
| table.sortColumnIndex = 0; |
| }); |
| table.rebuild(); |
| |
| this.addHTMLOutput(button); |
| }); |
| |
| |
| test('instantiateNestedTableAlreadyExpanded', function() { |
| var columns = [ |
| { |
| title: 'a', |
| value: function(row) { return row.a; }, |
| width: '150px' |
| }, |
| { |
| title: 'a', |
| value: function(row) { return row.b; }, |
| width: '50%' |
| } |
| ]; |
| |
| var rows = [ |
| { |
| a: 'aToplevel', |
| b: 'bToplevel', |
| isExpanded: true, |
| subRows: [ |
| { |
| a: 'a1', |
| b: 'b1' |
| } |
| ] |
| } |
| ]; |
| |
| var table = document.createElement('tr-ui-b-table'); |
| table.tableColumns = columns; |
| table.tableRows = rows; |
| table.rebuild(); |
| this.addHTMLOutput(table); |
| |
| var a1El = tr.b.findDeepElementMatchingPredicate(table, function(element) { |
| return Polymer.dom(element).textContent == 'a1'; |
| }); |
| assert.isDefined(a1El); |
| |
| var bToplevelEl = tr.b.findDeepElementMatchingPredicate( |
| table, |
| function(element) { |
| return Polymer.dom(element).textContent == 'bToplevel'; |
| }); |
| assert.isDefined(bToplevelEl); |
| var expandButton = Polymer.dom(bToplevelEl.parentElement) |
| .querySelector('expand-button'); |
| assert.isTrue(Polymer.dom(expandButton).classList.contains( |
| 'button-expanded')); |
| }); |
| |
| |
| test('subRowsThatAreRetrievedOnDemand', function() { |
| var columns = [ |
| { |
| title: 'a', |
| value: function(row) { return row.a; }, |
| width: '150px' |
| } |
| ]; |
| |
| var rows = [ |
| { |
| a: 'row1', |
| subRows: [ |
| { |
| b: 'row1.1', |
| get subRows() { |
| throw new Error('Shold not be called'); |
| } |
| } |
| ] |
| } |
| ]; |
| |
| var table = document.createElement('tr-ui-b-table'); |
| table.tableColumns = columns; |
| table.tableRows = rows; |
| table.rebuild(); |
| this.addHTMLOutput(table); |
| }); |
| |
| |
| test('instantiateTableWithHiddenHeader', function() { |
| var columns = [ |
| { |
| title: 'a', |
| value: function(row) { return row.a; }, |
| width: '150px' |
| }, |
| { |
| title: 'a', |
| value: function(row) { return row.b; }, |
| width: '50%' |
| } |
| ]; |
| |
| var rows = [ |
| { |
| a: 'aToplevel', |
| b: 'bToplevel' |
| } |
| ]; |
| |
| var table = document.createElement('tr-ui-b-table'); |
| table.showHeader = false; |
| table.tableColumns = columns; |
| table.tableRows = rows; |
| table.rebuild(); |
| this.addHTMLOutput(table); |
| |
| var tHead = table.$.head; |
| assert.equal(table.$.head.children.length, 0); |
| assert.equal(0, tHead.getBoundingClientRect().height); |
| |
| table.showHeader = true; |
| table.rebuild(); |
| table.showHeader = false; |
| table.rebuild(); |
| assert.equal(table.$.head.children.length, 0); |
| }); |
| |
| |
| test('sortColumnsNotPossibleOnPercentSizedColumns', function() { |
| var columns = [ |
| { |
| title: 'Title', |
| value: function(row) { return row.a; }, |
| width: '150px' |
| }, |
| { |
| title: 'Value', |
| value: function(row) { return row.b; }, |
| width: '100%', |
| showExpandButtons: true |
| } |
| ]; |
| |
| var table1 = document.createElement('tr-ui-b-table'); |
| table1.showHeader = true; |
| |
| assert.throws(function() { |
| table1.tableColumns = columns; |
| }); |
| }); |
| |
| test('twoTablesFirstColumnMatching', function() { |
| var columns = [ |
| { |
| title: 'Title', |
| value: function(row) { return row.a; }, |
| width: '150px' |
| }, |
| { |
| title: 'Value', |
| value: function(row) { return row.b; }, |
| width: '100%' |
| } |
| ]; |
| |
| var table1 = document.createElement('tr-ui-b-table'); |
| table1.showHeader = true; |
| table1.tableColumns = columns; |
| table1.tableRows = [ |
| { |
| a: 'first', |
| b: 'row' |
| } |
| ]; |
| table1.rebuild(); |
| this.addHTMLOutput(table1); |
| |
| var table2 = document.createElement('tr-ui-b-table'); |
| table2.showHeader = false; |
| table2.tableColumns = columns; |
| table2.tableRows = [ |
| { |
| a: 'second', |
| b: 'row' |
| } |
| ]; |
| table2.rebuild(); |
| this.addHTMLOutput(table2); |
| |
| var h1FirstCol = table1.$.head.children[0].children[0]; |
| var h2FirstCol = table2.$.body.children[0].children[0]; |
| assert.equal(h1FirstCol.getBoundingClientRect().width, |
| h2FirstCol.getBoundingClientRect().width); |
| }); |
| |
| test('programmaticSorting', function() { |
| var table = document.createElement('tr-ui-b-table'); |
| |
| var columns = [ |
| { |
| title: 'Column', |
| value: function(row) { return row.value; }, |
| cmp: function(rowA, rowB) { |
| return rowA.value.toString().localeCompare( |
| rowB.value.toString()); |
| } |
| } |
| ]; |
| |
| var rows = [ |
| { |
| value: 'A1', |
| subRows: [ |
| { |
| value: 'A1.1' |
| }, |
| { |
| value: 'A1.2', |
| subRows: [ |
| { |
| value: 'A1.2.1' |
| }, |
| { |
| value: 'A1.2.2' |
| } |
| ] |
| }, |
| { |
| value: 'A1.3' |
| } |
| ] |
| }, |
| { |
| value: 'A2' |
| } |
| ]; |
| |
| table.tableColumns = columns; |
| table.tableRows = rows; |
| table.rebuild(); |
| |
| this.addHTMLOutput(table); |
| |
| table.sortDescending = true; |
| table.sortColumnIndex = 0; |
| table.rebuild(); |
| var r0 = table.$.body.children[0]; |
| assert.equal(r0.rowInfo.userRow, rows[1]); |
| |
| var r1 = table.$.body.children[1]; |
| assert.equal(r1.rowInfo.userRow, rows[0]); |
| }); |
| |
| test('sortDispatchesEvent', function() { |
| var table = document.createElement('tr-ui-b-table'); |
| var columns = [ |
| { |
| title: 'Column 0', |
| value: function(row) { return row.value0; }, |
| cmp: function(rowA, rowB) { return rowA.value0 - rowB.value0; } |
| }, |
| { |
| title: 'Column 1', |
| value: function(row) { return row.value1; }, |
| cmp: function(rowA, rowB) { return rowA.value1 - rowB.value1; } |
| } |
| ]; |
| |
| var sortColumnIndex = undefined; |
| var sortDescending = undefined; |
| var numListenerCalls = 0; |
| table.tableColumns = columns; |
| table.addEventListener('sort-column-changed', function(e) { |
| sortColumnIndex = e.sortColumnIndex; |
| sortDescending = e.sortDescending; |
| numListenerCalls++; |
| }); |
| table.rebuild(); |
| |
| table.sortColumnIndex = 0; |
| assert.equal(sortColumnIndex, 0); |
| assert.equal(numListenerCalls, 1); |
| |
| table.sortDescending = true; |
| assert.equal(sortColumnIndex, 0); |
| assert.isTrue(sortDescending); |
| assert.equal(numListenerCalls, 2); |
| |
| table.sortColumnIndex = 1; |
| table.sortDescending = false; |
| assert.equal(sortColumnIndex, 1); |
| assert.isFalse(sortDescending); |
| assert.equal(numListenerCalls, 4); |
| |
| table.sortColumnIndex = undefined; |
| assert.equal(sortColumnIndex, undefined); |
| assert.equal(numListenerCalls, 5); |
| }); |
| |
| test('sortingAfterExpand', function() { |
| var table = document.createElement('tr-ui-b-table'); |
| |
| var columns = [ |
| { |
| title: 'Column', |
| value: function(row) { return row.value; }, |
| cmp: function(rowA, rowB) { |
| return rowA.value.toString().localeCompare( |
| rowB.value.toString()); |
| } |
| } |
| ]; |
| |
| var rows = [ |
| { |
| value: 'A1', |
| isExpanded: true, |
| subRows: [ |
| { |
| value: 'A1.1' |
| }, |
| { |
| value: 'A1.2', |
| subRows: [ |
| { |
| value: 'A1.2.1' |
| }, |
| { |
| value: 'A1.2.2' |
| } |
| ] |
| }, |
| { |
| value: 'A1.3' |
| } |
| ] |
| }, |
| { |
| value: 'A2' |
| } |
| ]; |
| |
| table.tableColumns = columns; |
| table.tableRows = rows; |
| table.rebuild(); |
| |
| this.addHTMLOutput(table); |
| |
| table.sortDescending = true; |
| table.sortColumnIndex = 0; |
| table.rebuild(); |
| var r0 = table.$.body.children[0]; |
| assert.equal(r0.rowInfo.userRow, rows[1]); |
| |
| var r1 = table.$.body.children[1]; |
| assert.equal(r1.rowInfo.userRow, rows[0]); |
| |
| var r2 = table.$.body.children[2]; |
| assert.equal(r2.rowInfo.userRow, rows[0].subRows[2]); |
| |
| assert.isFalse(r0.hasAttribute('tabIndex')); |
| }); |
| |
| function createSimpleOneColumnNestedTable() { |
| var table = document.createElement('tr-ui-b-table'); |
| |
| var columns = [ |
| { |
| title: 'Column', |
| value: function(row) { return row.value; }, |
| cmp: function(rowA, rowB) { |
| return rowA.value.toString().localeCompare( |
| rowB.value.toString()); |
| } |
| } |
| ]; |
| |
| var rows = [ |
| { |
| value: 'A1', |
| subRows: [ |
| { |
| value: 'A1.1' |
| }, |
| { |
| value: 'A1.2', |
| subRows: [ |
| { |
| value: 'A1.2.1' |
| }, |
| { |
| value: 'A1.2.2' |
| } |
| ] |
| }, |
| { |
| value: 'A1.3' |
| } |
| ] |
| }, |
| { |
| value: 'A2' |
| } |
| ]; |
| |
| table.tableColumns = columns; |
| table.tableRows = rows; |
| return table; |
| } |
| |
| test('expandAfterRebuild', function() { |
| var table = createSimpleOneColumnNestedTable(); |
| table.rebuild(); |
| var rows = table.tableRows; |
| |
| this.addHTMLOutput(table); |
| |
| table.rebuild(); |
| assert.isFalse(table.getExpandedForTableRow(rows[0])); |
| table.setExpandedForTableRow(rows[0], true); |
| assert.isTrue(table.getExpandedForTableRow(rows[0])); |
| |
| var r1 = table.$.body.children[1]; |
| assert.equal(r1.rowInfo.userRow, rows[0].subRows[0]); |
| }); |
| |
| test('tableSelection', function() { |
| var table = createSimpleOneColumnNestedTable(); |
| var rows = table.tableRows; |
| |
| table.selectionMode = SelectionMode.ROW; |
| table.selectedTableRow = rows[0]; |
| |
| table.setExpandedForTableRow(rows[0], true); |
| table.selectedTableRow = rows[0].subRows[1]; |
| assert.equal(table.selectedTableRow, rows[0].subRows[1]); |
| |
| table.setExpandedForTableRow(rows[0], false); |
| assert.equal(table.selectedTableRow, rows[0]); |
| |
| table.selectionMode = SelectionMode.NONE; |
| assert.equal(table.selectedTableRow, undefined); |
| |
| table.selectionMode = SelectionMode.ROW; |
| table.setExpandedForTableRow(rows[0].subRows[1], true); |
| this.addHTMLOutput(table); |
| |
| var r0 = table.$.body.children[0]; |
| assert.isTrue(r0.hasAttribute('tabIndex')); |
| }); |
| |
| |
| test('keyMovement', function() { |
| var table = createSimpleOneColumnNestedTable(); |
| table.selectionMode = SelectionMode.ROW; |
| this.addHTMLOutput(table); |
| |
| var rows = table.tableRows; |
| table.selectedTableRow = rows[0]; |
| |
| table.performKeyCommand_('ARROW_DOWN'); |
| assert.equal(table.selectedTableRow, rows[1]); |
| |
| table.performKeyCommand_('ARROW_UP'); |
| assert.equal(table.selectedTableRow, rows[0]); |
| |
| // Enter on collapsed row should expand. |
| table.selectedTableRow = rows[0]; |
| table.performKeyCommand_('SPACE'); |
| assert.equal(table.selectedTableRow, rows[0]); |
| assert.isTrue(table.getExpandedForTableRow(rows[0])); |
| |
| table.performKeyCommand_('SPACE'); |
| assert.isFalse(table.getExpandedForTableRow(rows[0])); |
| |
| // Arrow right on collapsed row should expand. |
| table.selectedTableRow = rows[0]; |
| table.performKeyCommand_('ARROW_RIGHT'); |
| assert.equal(table.selectedTableRow, rows[0].subRows[0]); |
| assert.isTrue(table.getExpandedForTableRow(rows[0])); |
| |
| table.performKeyCommand_('ARROW_DOWN'); |
| assert.equal(table.selectedTableRow, rows[0].subRows[1]); |
| |
| // Arrow left on collapsed item should select parent. |
| table.performKeyCommand_('ARROW_LEFT'); |
| assert.equal(table.selectedTableRow, rows[0]); |
| assert.isTrue(table.getExpandedForTableRow(rows[0])); |
| // Arrow left on parent should collapse its children. |
| table.performKeyCommand_('ARROW_LEFT'); |
| assert.isFalse(table.getExpandedForTableRow(rows[0])); |
| |
| // Arrow right on expanded row should select first child. |
| table.selectedTableRow = rows[0]; |
| table.setExpandedForTableRow(rows[0], true); |
| table.performKeyCommand_('ARROW_RIGHT'); |
| assert.equal(table.selectedTableRow, rows[0].subRows[0]); |
| |
| // Arrow right on a non-expandable row should do nothing. |
| table.selectedTableRow = rows[1]; |
| assert.equal(table.selectedTableRow, rows[1]); |
| table.performKeyCommand_('ARROW_RIGHT'); |
| assert.equal(table.selectedTableRow, rows[1]); |
| assert.isFalse(table.getExpandedForTableRow(rows[1])); |
| }); |
| |
| test('RightArrowKeyWhenTableSorted', function() { |
| var table = createSimpleOneColumnNestedTable(); |
| table.selectionMode = SelectionMode.ROW; |
| this.addHTMLOutput(table); |
| table.sortDescending = true; |
| table.sortColumnIndex = 0; |
| table.rebuild(); |
| var rows = table.tableRows; |
| |
| // Arrow right should select the first child showing up on the viewer, |
| // rather than first child in sub rows since sorted. |
| table.selectedTableRow = rows[0]; |
| table.performKeyCommand_('ARROW_RIGHT'); |
| assert.equal(table.selectedTableRow, rows[0].subRows[2]); |
| }); |
| |
| test('reduceNumberOfColumnsAfterRebuild', function() { |
| // Create a table with two columns. |
| var table = document.createElement('tr-ui-b-table'); |
| table.tableColumns = [ |
| { |
| title: 'First Column', |
| value: function(row) { return row.firstData; }, |
| width: '100px' |
| }, |
| { |
| title: 'Second Column', |
| value: function(row) { return row.secondData; }, |
| width: '100px' |
| } |
| ]; |
| |
| // Build the table. |
| table.rebuild(); |
| |
| // Check that reducing the number of columns doesn't throw an exception. |
| table.tableColumns = [ |
| { |
| title: 'First Column', |
| value: function(row) { return row.firstData; }, |
| width: '200px' |
| } |
| ]; |
| }); |
| |
| test('rowHighlightDark', function() { |
| var columns = [ |
| { |
| title: 'Title', |
| value: function(row) { return row.a; }, |
| width: '150px', |
| supportsCellSelection: false |
| }, |
| { |
| title: 'Col1', |
| value: function(row) { return row.b; }, |
| width: '33%' |
| }, |
| { |
| title: 'Col2', |
| value: function(row) { return row.b * 2; }, |
| width: '33%' |
| }, |
| { |
| title: 'Col3', |
| value: function(row) { return row.b * 3; }, |
| width: '33%' |
| } |
| ]; |
| |
| var table = document.createElement('tr-ui-b-table'); |
| table.showHeader = true; |
| table.rowHighlightStyle = HighlightStyle.DARK; |
| table.tableColumns = columns; |
| table.tableRows = [ |
| { |
| a: 'first', |
| b: '1' |
| }, |
| { |
| a: 'second', |
| b: '2' |
| } |
| ]; |
| table.rebuild(); |
| this.addHTMLOutput(table); |
| }); |
| |
| test('cellHighlightLight', function() { |
| var columns = [ |
| { |
| title: 'Title', |
| value: function(row) { return row.a; }, |
| width: '150px', |
| supportsCellSelection: false |
| }, |
| { |
| title: 'Col1', |
| value: function(row) { return row.b; }, |
| width: '33%' |
| }, |
| { |
| title: 'Col2', |
| value: function(row) { return row.b * 2; }, |
| width: '33%' |
| }, |
| { |
| title: 'Col3', |
| value: function(row) { return row.b * 3; }, |
| width: '33%' |
| } |
| ]; |
| |
| var table = document.createElement('tr-ui-b-table'); |
| table.showHeader = true; |
| table.cellHighlightStyle = HighlightStyle.LIGHT; |
| table.tableColumns = columns; |
| table.tableRows = [ |
| { |
| a: 'first', |
| b: '1' |
| }, |
| { |
| a: 'second', |
| b: '2' |
| } |
| ]; |
| table.rebuild(); |
| this.addHTMLOutput(table); |
| }); |
| |
| test('cellSelectionBasic', function() { |
| var columns = [ |
| { |
| title: 'Title', |
| value: function(row) { return row.a; }, |
| width: '150px', |
| supportsCellSelection: false |
| }, |
| { |
| title: 'Col1', |
| value: function(row) { return row.b; }, |
| width: '33%' |
| }, |
| { |
| title: 'Col2', |
| value: function(row) { return row.b * 2; }, |
| width: '33%' |
| }, |
| { |
| title: 'Col3', |
| value: function(row) { return row.b * 3; }, |
| width: '33%' |
| } |
| ]; |
| |
| var table = document.createElement('tr-ui-b-table'); |
| table.showHeader = true; |
| table.selectionMode = SelectionMode.CELL; |
| table.rowHighlightStyle = HighlightStyle.NONE; |
| table.tableColumns = columns; |
| table.tableRows = [ |
| { |
| a: 'first', |
| b: '1' |
| }, |
| { |
| a: 'second', |
| b: '2' |
| } |
| ]; |
| table.rebuild(); |
| this.addHTMLOutput(table); |
| |
| table.selectedTableRow = table.tableRows[0]; |
| assert.equal(table.selectedColumnIndex, 1); |
| var selectedCell = table.selectedCell; |
| assert.strictEqual(selectedCell.row, table.tableRows[0]); |
| assert.strictEqual(selectedCell.column, columns[1]); |
| assert.strictEqual(selectedCell.value, '1'); |
| |
| table.performKeyCommand_('ARROW_DOWN'); |
| table.performKeyCommand_('ARROW_RIGHT'); |
| table.performKeyCommand_('ARROW_RIGHT'); |
| table.performKeyCommand_('ARROW_LEFT'); |
| assert.equal(table.selectedTableRow, table.tableRows[1]); |
| assert.equal(table.selectedColumnIndex, 2); |
| selectedCell = table.selectedCell; |
| assert.strictEqual(selectedCell.row, table.tableRows[1]); |
| assert.strictEqual(selectedCell.column, columns[2]); |
| assert.strictEqual(selectedCell.value, 4); |
| |
| table.selectedTableRow = undefined; |
| assert.isUndefined(table.selectedTableRow); |
| assert.isUndefined(table.selectedColumnIndex); |
| assert.isUndefined(table.selectedColumnIndex); |
| assert.isUndefined(table.selectedCell); |
| }); |
| |
| test('cellSelectionNested', function() { |
| var columns = [ |
| { |
| title: 'Title', |
| value: function(row) { return row.a; }, |
| width: '150px', |
| supportsCellSelection: false |
| }, |
| { |
| title: 'Value', |
| value: function(row) { return row.b; }, |
| width: '150px' |
| } |
| ]; |
| |
| var rows = [ |
| { |
| a: 'parent', |
| b: '1', |
| subRows: [ |
| { |
| a: 'child', |
| b: '2' |
| } |
| ] |
| } |
| ]; |
| |
| var table = document.createElement('tr-ui-b-table'); |
| table.showHeader = true; |
| table.selectionMode = SelectionMode.CELL; |
| table.tableColumns = columns; |
| table.tableRows = rows; |
| table.rebuild(); |
| this.addHTMLOutput(table); |
| |
| // Expand the parent row. |
| table.setExpandedForTableRow(rows[0], true); |
| |
| // Select the second cell in the child row. |
| table.selectedTableRow = rows[0].subRows[0]; |
| assert.isFalse(isSelected(table.$.body.children[0])); |
| assert.isFalse(isSelected(table.$.body.children[0].children[1])); |
| assert.isTrue(isSelected(table.$.body.children[1])); |
| assert.isTrue(isSelected(table.$.body.children[1].children[1])); |
| |
| // Fold the parent row. The second cell in the parent row should be |
| // automatically selected. |
| table.setExpandedForTableRow(rows[0], false); |
| assert.isTrue(isSelected(table.$.body.children[0])); |
| assert.isTrue(isSelected(table.$.body.children[0].children[1])); |
| |
| // Expand the parent row again. Only the second cell of the parent row |
| // should still be selected. |
| table.setExpandedForTableRow(rows[0], true); |
| assert.isTrue(isSelected(table.$.body.children[0])); |
| assert.isTrue(isSelected(table.$.body.children[0].children[1])); |
| assert.isFalse(isSelected(table.$.body.children[1])); |
| assert.isFalse(isSelected(table.$.body.children[1].children[1])); |
| }); |
| |
| test('resolvedHighlightStyle', function() { |
| var table = document.createElement('tr-ui-b-table'); |
| |
| // Undefined selection mode. |
| assert.strictEqual(table.resolvedRowHighlightStyle, HighlightStyle.NONE); |
| assert.strictEqual(table.resolvedCellHighlightStyle, HighlightStyle.NONE); |
| |
| // Row selection mode. |
| table.selectionMode = SelectionMode.ROW; |
| assert.strictEqual(table.resolvedRowHighlightStyle, HighlightStyle.DARK); |
| assert.strictEqual(table.resolvedCellHighlightStyle, HighlightStyle.NONE); |
| |
| // Cell selection mode. |
| table.selectionMode = SelectionMode.CELL; |
| assert.strictEqual(table.resolvedRowHighlightStyle, HighlightStyle.LIGHT); |
| assert.strictEqual(table.resolvedCellHighlightStyle, HighlightStyle.DARK); |
| |
| // Explicit row highlight style. |
| table.rowHighlightStyle = HighlightStyle.NONE; |
| assert.strictEqual(table.resolvedRowHighlightStyle, HighlightStyle.NONE); |
| assert.strictEqual(table.resolvedCellHighlightStyle, HighlightStyle.DARK); |
| |
| // Explicit row and cell highlight styles. |
| table.cellHighlightStyle = HighlightStyle.LIGHT; |
| assert.strictEqual(table.resolvedRowHighlightStyle, HighlightStyle.NONE); |
| assert.strictEqual(table.resolvedCellHighlightStyle, HighlightStyle.LIGHT); |
| |
| // Back to default highlight styles. |
| table.cellHighlightStyle = HighlightStyle.DEFAULT; |
| table.rowHighlightStyle = HighlightStyle.DEFAULT; |
| assert.strictEqual(table.resolvedRowHighlightStyle, HighlightStyle.LIGHT); |
| assert.strictEqual(table.resolvedCellHighlightStyle, HighlightStyle.DARK); |
| }); |
| |
| test('headersWithHtmlElements', function() { |
| var firstColumnTitle = document.createTextNode('First Column'); |
| var secondColumnTitle = document.createElement('span'); |
| secondColumnTitle.innerText = 'Second Column'; |
| secondColumnTitle.style.color = 'blue'; |
| |
| var columns = [ |
| { |
| title: firstColumnTitle, |
| value: function(row) { return row.firstData; }, |
| width: '200px' |
| }, |
| { |
| title: secondColumnTitle, |
| value: function(row) { return row.secondData; } |
| } |
| ]; |
| |
| var rows = [ |
| { |
| firstData: 'A1', |
| secondData: 'A2' |
| }, |
| { |
| firstData: 'B1', |
| secondData: 'B2' |
| } |
| ]; |
| |
| var table = document.createElement('tr-ui-b-table'); |
| table.tableColumns = columns; |
| table.tableRows = rows; |
| table.rebuild(); |
| |
| this.addHTMLOutput(table); |
| |
| var firstColumnHeader = table.$.head.children[0].children[0].children[0]; |
| var secondColumnHeader = table.$.head.children[0].children[1].children[0]; |
| assert.equal(Polymer.dom(firstColumnHeader.cellTitle).textContent, |
| 'First Column'); |
| assert.equal(Polymer.dom(secondColumnHeader.cellTitle).textContent, |
| 'Second Column'); |
| }); |
| |
| test('align', function() { |
| var columns = [ |
| { |
| title: 'a', |
| align: ColumnAlignment.RIGHT, |
| value: function(row) { |
| return row.a; |
| } |
| } |
| ]; |
| var rows = [{a: 1}, {a: 'long-row-so-that-alignment-would-be-visible'}]; |
| |
| var table = document.createElement('tr-ui-b-table'); |
| table.tableColumns = columns; |
| table.tableRows = rows; |
| table.rebuild(); |
| |
| this.addHTMLOutput(table); |
| |
| assert.strictEqual( |
| table.$.body.children[0].children[0].style.textAlign, 'right'); |
| }); |
| |
| test('subRowsPropertyName', function() { |
| var columns = [ |
| { |
| title: 'a', |
| value: function(row) { |
| return row.a; |
| } |
| } |
| ]; |
| var rows = [ |
| { |
| a: 1, |
| isExpanded: true, |
| children: [ |
| {a: 2} |
| ] |
| } |
| ]; |
| |
| var table = document.createElement('tr-ui-b-table'); |
| table.subRowsPropertyName = 'children'; |
| table.tableColumns = columns; |
| table.tableRows = rows; |
| table.rebuild(); |
| |
| this.addHTMLOutput(table); |
| |
| assert.equal( |
| 2, Polymer.dom(table.$.body.children[1].children[0]).textContent); |
| }); |
| |
| test('shouldNotRenderUndefined', function() { |
| var columns = [ |
| { |
| title: 'Column', |
| value: function(row) { return row.firstData; } |
| } |
| ]; |
| |
| var rows = [ |
| { |
| firstData: undefined, |
| secondData: 'A2' |
| } |
| ]; |
| |
| var table = document.createElement('tr-ui-b-table'); |
| table.tableColumns = columns; |
| table.tableRows = rows; |
| table.rebuild(); |
| |
| this.addHTMLOutput(table); |
| |
| // check that we don't have 'undefined' anywhere |
| assert.isTrue(Polymer.dom(table.$.body).innerHTML.indexOf('undefined') < 0); |
| }); |
| |
| test('customizeTableRowCallback', function() { |
| var columns = [ |
| { |
| title: 'Column', |
| value: function(row) { return row.data; } |
| } |
| ]; |
| |
| var rows = [ |
| { |
| data: 'data' |
| } |
| ]; |
| |
| var table = document.createElement('tr-ui-b-table'); |
| var callbackCalled = false; |
| table.tableColumns = columns; |
| table.tableRows = rows; |
| table.customizeTableRowCallback = function(userRow, trElement) { |
| callbackCalled = (userRow === rows[0]); |
| }; |
| table.rebuild(); |
| assert.isTrue(callbackCalled); |
| |
| this.addHTMLOutput(table); |
| |
| // The callback can also be set after the table is first built. |
| table.customizeTableRowCallback = function(userRow, trElement) { |
| callbackCalled = (userRow === rows[0]); |
| }; |
| |
| // Setting the customize callback should set the body dirty. |
| assert.isTrue(table.bodyDirty_); |
| |
| callbackCalled = false; |
| |
| // Don't bother waiting for the timeout. |
| table.rebuild(); |
| |
| assert.isTrue(callbackCalled); |
| }); |
| |
| test('selectionEdgeCases', function() { |
| var table = document.createElement('tr-ui-b-table'); |
| table.tableColumns = [ |
| { |
| title: 'Column', |
| value: function(row) { return row.data; }, |
| supportsCellSelection: false |
| } |
| ]; |
| table.tableRows = [{ data: 'body row' }]; |
| table.footerRows = [{ data: 'footer row' }]; |
| table.selectionMode = SelectionMode.ROW; |
| this.addHTMLOutput(table); |
| |
| // Clicking on the body row should *not* throw an exception (despite the |
| // column not supporting cell selection). |
| table.$.body.children[0].children[0].click(); |
| |
| // Clicking on the footer row should *not* throw an exception (despite |
| // footer rows not being selectable in general). |
| table.$.foot.children[0].children[0].click(); |
| }); |
| |
| test('defaultExpansionStateCallback', function() { |
| var columns = [ |
| { |
| title: 'Name', |
| value: function(row) { return row.name; } |
| }, |
| { |
| title: 'Value', |
| value: function(row) { return row.value; } |
| } |
| ]; |
| |
| var rows = [ |
| { |
| name: 'A', |
| value: 10, |
| subRows: [ |
| { |
| name: 'B', |
| value: 8, |
| subRows: [ |
| { |
| name: 'C', |
| value: 4 |
| }, |
| { |
| name: 'D', |
| value: 4 |
| } |
| ] |
| }, |
| { |
| name: 'E', |
| value: 2, |
| subRows: [ |
| { |
| name: 'F', |
| value: 1 |
| }, |
| { |
| name: 'G', |
| value: 1 |
| } |
| ] |
| } |
| ] |
| } |
| ]; |
| |
| var table = document.createElement('tr-ui-b-table'); |
| table.tableColumns = columns; |
| table.tableRows = rows; |
| table.rebuild(); |
| |
| this.addHTMLOutput(table); |
| |
| var cRow = tr.b.findDeepElementMatchingPredicate( |
| table, function(element) { |
| return Polymer.dom(element).textContent === 'C'; |
| }); |
| assert.equal(cRow, undefined); |
| |
| var callbackCalled = false; |
| table.defaultExpansionStateCallback = function(row, parentRow) { |
| callbackCalled = true; |
| |
| if (parentRow === undefined) |
| return true; |
| |
| if (row.value >= (parentRow.value * 0.8)) |
| return true; |
| |
| return false; |
| }; |
| |
| // Setting the callback should set the body dirty. |
| assert.isTrue(table.bodyDirty_); |
| assert.isFalse(callbackCalled); |
| |
| table.rebuild(); |
| |
| assert.isTrue(callbackCalled); |
| cRow = tr.b.findDeepElementMatchingPredicate(table, function(element) { |
| return Polymer.dom(element).textContent === 'C'; |
| }); |
| assert.isDefined(cRow); |
| }); |
| |
| test('sortExpanded', function() { |
| var columns = [ |
| { |
| title: 'Name', |
| value: function(row) { return row.name; } |
| }, |
| { |
| title: 'Value', |
| value: function(row) { return row.value; }, |
| cmp: function(x, y) { return x.value - y.value; } |
| } |
| ]; |
| |
| var rows = [ |
| { |
| name: 'A', |
| value: 10, |
| subRows: [ |
| { |
| name: 'B', |
| value: 8 |
| }, |
| { |
| name: 'C', |
| value: 4 |
| }, |
| ] |
| } |
| ]; |
| |
| var table = document.createElement('tr-ui-b-table'); |
| table.tableColumns = columns; |
| table.tableRows = rows; |
| table.rebuild(); |
| |
| this.addHTMLOutput(table); |
| |
| function isB(row) { |
| return row.textContent === 'B'; |
| } |
| |
| // Check that 'A' row is not expanded. |
| assert.isUndefined(tr.b.findDeepElementMatchingPredicate(table, isB)); |
| |
| // Expand 'A' row. |
| table.setExpandedForTableRow(rows[0], true); |
| |
| // Check that 'A' is expanded. |
| assert.isDefined(tr.b.findDeepElementMatchingPredicate(table, isB)); |
| |
| // Sort by value. |
| table.sortColumnIndex = 1; |
| |
| // Rebuild the table synchronously instead of waiting for scheduleRebuild_'s |
| // setTimeout(0). |
| table.rebuild(); |
| |
| // Check that 'A' is still expanded. |
| assert.isDefined(tr.b.findDeepElementMatchingPredicate(table, isB)); |
| }); |
| |
| test('userCanModifySortOrder', function() { |
| var table = document.createElement('tr-ui-b-table'); |
| table.tableColumns = [ |
| { |
| title: 'Name', |
| value: row => row.name |
| }, |
| { |
| title: 'colA', |
| value: row => row.a, |
| cmp: (rowA, rowB) => rowA.a - rowB.a |
| }, |
| { |
| title: 'colB', |
| value: row => row.b, |
| cmp: (rowA, rowB) => rowA.b - rowB.b |
| } |
| ]; |
| table.tableRows = [ |
| {name: 'A', a: 42, b: 0}, |
| {name: 'B', a: 89, b: 100}, |
| {name: 'C', a: 65, b: -273.15} |
| ]; |
| table.userCanModifySortOrder = false; |
| table.sortColumnIndex = 2; |
| table.sortDescending = true; |
| table.rebuild(); |
| this.addHTMLOutput(table); |
| |
| var toggleButton = document.createElement('button'); |
| Polymer.dom(toggleButton).textContent = |
| 'Toggle table.userCanModifySortOrder'; |
| toggleButton.addEventListener('click', function() { |
| table.userCanModifySortOrder = !table.userCanModifySortOrder; |
| }); |
| this.addHTMLOutput(toggleButton); |
| |
| var unsetButton = document.createElement('button'); |
| Polymer.dom(unsetButton).textContent = 'Unset sort order'; |
| unsetButton.addEventListener('click', function() { |
| table.sortColumnIndex = undefined; |
| }); |
| this.addHTMLOutput(unsetButton); |
| }); |
| |
| test('columnSelection', function() { |
| var table = document.createElement('tr-ui-b-table'); |
| table.tableColumns = [ |
| { |
| title: 'Name', |
| value: (row) => row.name |
| }, |
| { |
| title: 'colA', |
| selectable: true, |
| value: (row) => row.a, |
| cmp: (rowA, rowB) => rowA.a - rowB.a |
| }, |
| { |
| title: 'colB', |
| selectable: true, |
| value: (row) => row.b, |
| cmp: (rowA, rowB) => rowA.b - rowB.b |
| } |
| ]; |
| table.tableRows = [ |
| {name: 'foo', a: 42, b: -42}, |
| {name: 'bar', a: 57, b: 133} |
| ]; |
| table.rebuild(); |
| table.selectionMode = SelectionMode.CELL; |
| this.addHTMLOutput(table); |
| |
| table.selectedTableColumnIndex = 1; |
| var cols = tr.b.findDeepElementMatchingPredicate(table, |
| e => e.tagName === 'COLGROUP').children; |
| assert.isNull(cols[0].getAttribute('selected')); |
| assert.strictEqual(cols[1].getAttribute('selected'), 'true'); |
| assert.isNull(cols[2].getAttribute('selected')); |
| assert.strictEqual(1, table.selectedTableColumnIndex); |
| |
| table.selectedTableColumnIndex = undefined; |
| cols = tr.b.findDeepElementMatchingPredicate(table, |
| e => e.tagName === 'COLGROUP').children; |
| assert.isNull(cols[0].getAttribute('selected')); |
| assert.isNull(cols[1].getAttribute('selected')); |
| assert.isNull(cols[2].getAttribute('selected')); |
| assert.isUndefined(table.selectedTableColumnIndex); |
| |
| table.selectedTableColumnIndex = 2; |
| cols = tr.b.findDeepElementMatchingPredicate(table, |
| e => e.tagName === 'COLGROUP').children; |
| assert.isNull(cols[0].getAttribute('selected')); |
| assert.isNull(cols[1].getAttribute('selected')); |
| assert.strictEqual(cols[2].getAttribute('selected'), 'true'); |
| assert.strictEqual(2, table.selectedTableColumnIndex); |
| }); |
| |
| test('stepInto', function() { |
| var columns = [ |
| { |
| title: 'Title', |
| value: function(row) { return row.a; }, |
| width: '150px', |
| supportsCellSelection: false |
| }, |
| { |
| title: 'Col1', |
| value: function(row) { return row.b; }, |
| width: '33%' |
| }, |
| { |
| title: 'Col2', |
| value: function(row) { return row.b * 2; }, |
| width: '33%' |
| }, |
| { |
| title: 'Col3', |
| value: function(row) { return row.b * 3; }, |
| width: '33%' |
| } |
| ]; |
| var rows = [ |
| { |
| a: 'first', |
| b: '1' |
| }, |
| { |
| a: 'second', |
| b: '2' |
| } |
| ]; |
| |
| var table = document.createElement('tr-ui-b-table'); |
| |
| var firedStepIntoEvents = []; |
| table.addEventListener('step-into', e => firedStepIntoEvents.push(e)); |
| |
| table.cellHighlightStyle = HighlightStyle.DARK; |
| table.tableColumns = columns; |
| table.tableRows = rows; |
| table.rebuild(); |
| this.addHTMLOutput(table); |
| |
| assert.lengthOf(firedStepIntoEvents, 0); |
| |
| // Double click. |
| simulateDoubleClick(table.$.body.children[0].children[1]); |
| assert.lengthOf(firedStepIntoEvents, 1); |
| assert.strictEqual(firedStepIntoEvents[0].tableRow, rows[0]); |
| assert.strictEqual(firedStepIntoEvents[0].tableColumn, columns[1]); |
| assert.strictEqual(firedStepIntoEvents[0].columnIndex, 1); |
| |
| simulateDoubleClick(table.$.body.children[1].children[3]); |
| assert.lengthOf(firedStepIntoEvents, 2); |
| assert.strictEqual(firedStepIntoEvents[1].tableRow, rows[1]); |
| assert.strictEqual(firedStepIntoEvents[1].tableColumn, columns[3]); |
| assert.strictEqual(firedStepIntoEvents[1].columnIndex, 3); |
| |
| // Shift+Enter in cell selection mode. |
| table.selectionMode = SelectionMode.CELL; |
| table.selectedTableRow = rows[0]; |
| table.selectedColumnIndex = 2; |
| table.performKeyCommand_('ENTER'); |
| assert.lengthOf(firedStepIntoEvents, 3); |
| assert.strictEqual(firedStepIntoEvents[2].tableRow, rows[0]); |
| assert.strictEqual(firedStepIntoEvents[2].tableColumn, columns[2]); |
| assert.strictEqual(firedStepIntoEvents[2].columnIndex, 2); |
| |
| // Shift+Enter in row selection mode. |
| table.selectionMode = SelectionMode.ROW; |
| table.selectedTableRow = rows[1]; |
| table.performKeyCommand_('ENTER'); |
| assert.lengthOf(firedStepIntoEvents, 4); |
| assert.strictEqual(firedStepIntoEvents[3].tableRow, rows[1]); |
| assert.isUndefined(firedStepIntoEvents[3].tableColumn); |
| assert.isUndefined(firedStepIntoEvents[3].columnIndex); |
| }); |
| }); |
| </script> |