aboutsummaryrefslogtreecommitdiffstats
path: root/vaadin-grid/test
diff options
context:
space:
mode:
authorManolo Carrasco <manolo@apache.org>2015-01-21 23:28:24 -0800
committerSauli Tähkäpää <sauli@vaadin.com>2015-05-21 14:42:07 +0300
commit5759ee06e8fbdc2caeb912d614ec5a42834d009d (patch)
treecaeef1516f932f5d96909054cf4b13e82d1c5a22 /vaadin-grid/test
downloadvaadin-core-5759ee06e8fbdc2caeb912d614ec5a42834d009d.tar.gz
vaadin-core-5759ee06e8fbdc2caeb912d614ec5a42834d009d.zip
Release version 0.2-snapshot.
Diffstat (limited to 'vaadin-grid/test')
-rw-r--r--vaadin-grid/test/common.js86
-rw-r--r--vaadin-grid/test/grid-binding-data.html185
-rw-r--r--vaadin-grid/test/grid-editing-columns.html412
-rw-r--r--vaadin-grid/test/grid-editor-handler.html202
-rw-r--r--vaadin-grid/test/grid-properties.html86
-rw-r--r--vaadin-grid/test/grid-redrawer.html201
-rw-r--r--vaadin-grid/test/grid-rendering-light-dom.html130
-rw-r--r--vaadin-grid/test/grid-scrolling-rows.html114
-rw-r--r--vaadin-grid/test/grid-selecting-rows.html645
-rw-r--r--vaadin-grid/test/grid-sorting-rows.html100
-rw-r--r--vaadin-grid/test/grid-static-sections.html222
-rw-r--r--vaadin-grid/test/index.html24
12 files changed, 2407 insertions, 0 deletions
diff --git a/vaadin-grid/test/common.js b/vaadin-grid/test/common.js
new file mode 100644
index 0000000..4815d96
--- /dev/null
+++ b/vaadin-grid/test/common.js
@@ -0,0 +1,86 @@
+var grid, wrapper;
+
+describe.feature = function(description, suite) {
+ describe(description, function() {
+ before(function(done) {
+ initializeGrid();
+
+ waitUntil(function() {
+ return grid.then;
+ }, done, done);
+ });
+
+ after(function() {
+ return grid; //make sure everything is finished before moving on.
+ });
+
+ suite();
+ });
+};
+
+function gridContainsText(_grid, text) {
+ return Polymer.dom(_grid.root).querySelector(".v-grid-tablewrapper").parentElement.innerHTML.indexOf(text) > -1;
+}
+
+function waitUntil(check, exec, onTimeout) {
+ var id = setInterval(function() {
+ if (check()) {
+ clearInterval(id);
+ clearTimeout(timeoutId);
+ exec();
+ }
+ }, 100);
+
+ var timeoutId = setTimeout(function() {
+ clearInterval(id);
+ assert.fail();
+ onTimeout();
+ }, 5000);
+}
+
+
+function initializeGrid() {
+ wrapper = document.getElementById("gridwrapper");
+ wrapper.innerHTML = "<v-grid>" +
+ " <table>" +
+ " <col header-text='Name'>" +
+ " <col header-text='Value'>" +
+ " <tbody>" +
+ " <tr>" +
+ " <td>Grid</td>" +
+ " <td>10000</td>" +
+ " </tr>" +
+ " <tr>" +
+ " <td>VaadinX</td>" +
+ " <td>1000</td>" +
+ " </tr>" +
+ " </tbody>" +
+ " <tfoot>" +
+ " <tr>" +
+ " <td>Name</td>" +
+ " <td>Value</td>" +
+ " </tr>" +
+ " </tfoot>"+
+ " </table>" +
+ " </v-grid>";
+ grid = wrapper.querySelector("v-grid");
+
+ return grid;
+};
+
+var local = function() {
+ return Polymer.dom(grid.root);
+};
+var light = function() {
+ return Polymer.dom(grid);
+};
+
+var qLocal = function(selector) {
+ return local().querySelector(selector);
+};
+var qaLocal = function(selector) {
+ return local().querySelectorAll(selector);
+};
+var qLight = function(selector) {
+ return light().querySelector(selector);
+};
diff --git a/vaadin-grid/test/grid-binding-data.html b/vaadin-grid/test/grid-binding-data.html
new file mode 100644
index 0000000..2d82b26
--- /dev/null
+++ b/vaadin-grid/test/grid-binding-data.html
@@ -0,0 +1,185 @@
+<!DOCTYPE html>
+<html>
+
+<head lang="en">
+ <meta charset="UTF-8">
+ <title></title>
+ <script src="../../webcomponentsjs/webcomponents-lite.min.js"></script>
+ <script src="../../web-component-tester/browser.js"></script>
+
+ <script src="common.js"></script>
+
+ <link rel="import" href="../vaadin-grid.html">
+</head>
+
+<body>
+
+<div id="gridwrapper"></div>
+
+<script>
+ describe.feature('binding data', function() {
+
+ afterEach(function() {
+ return grid.then(function() {
+
+ grid.selection.mode = 'single';
+ grid.columns = [{name: 'Name', headerHtml: 'Name'}, {name: 'Value', headerHtml: 'Value'}];
+ grid.data.source = [['Grid', '10000'], ['VaadinX', '1000']];
+
+ return grid;
+ });
+ });
+
+ it('data: object type', function(done) {
+ grid.columns[0].name = "firstname";
+ grid.columns[1].name = "lastname";
+ grid.columns.push({
+ name: 'salary',
+ headerHtml: "Salary"
+ });
+
+ var mydata = [{
+ firstname: "John",
+ lastname: "Doe",
+ salary: 1234.56
+ }, {
+ firstname: "Jane",
+ lastname: "Doe",
+ salary: 2345.67
+ }, ];
+
+ grid.data.source = function(request) {
+ request.success(mydata.slice(request.index, request.index +
+ request.count), mydata.length);
+ };
+
+
+ waitUntil(function() {
+ return gridContainsText(grid, "2345.67");
+ }, function() {
+ var cells = qaLocal(".v-grid-body .v-grid-cell");
+ assert.equal(cells[0].innerHTML, "John");
+ assert.equal(cells[2].innerHTML, "1234.56");
+ assert.equal(cells[3].innerHTML, "Jane");
+ assert.equal(cells[4].innerHTML, "Doe");
+ done();
+ }, done);
+
+ });
+
+ it('data: array type', function(done) {
+ grid.columns.push({
+ headerHtml: "Salary"
+ });
+
+ mydata = [
+ ["John", "Doe", 1234.56],
+ ["Jane", "Doe", 2345.67],
+ ];
+
+ grid.data.source = mydata;
+
+ waitUntil(function() {
+ return gridContainsText(grid, "2345.67");
+ }, function() {
+ var cells = qaLocal(".v-grid-body .v-grid-cell");
+ assert.equal(cells[0].innerHTML, "John");
+ assert.equal(cells[2].innerHTML, "1234.56");
+ assert.equal(cells[3].innerHTML, "Jane");
+ assert.equal(cells[4].innerHTML, "Doe");
+ done();
+ }, done);
+
+ });
+
+ it('data: boolean type', function(done) {
+ grid.columns.splice(0, 1);
+ grid.selection.mode = "multi";
+
+ waitUntil(function() {
+ return qLocal("input[type='checkbox']");
+ }, function() {
+ var mydata = [
+ false,
+ true,
+ ];
+
+ grid.data.source = function(request) {
+ request.success(mydata.slice(request.index, request.index +
+ request.count), mydata.length);
+ };
+
+ waitUntil(function() {
+ return gridContainsText(grid, "false");
+ }, function() {
+ var cells = qaLocal(".v-grid-body .v-grid-cell");
+ assert.equal(cells[3].innerHTML, "true");
+ done();
+ }, done);
+ }, done);
+
+ });
+
+ it('data: string type', function(done) {
+ grid.columns.splice(0, 1);
+ grid.selection.mode = "multi";
+
+ waitUntil(function() {
+ return qLocal("input[type='checkbox']");
+ }, function() {
+ var mydata = [
+ "Lorem",
+ "Ipsum",
+ ];
+
+ grid.data.source = function(request) {
+ request.success(mydata.slice(request.index, request.index +
+ request.count), mydata.length);
+ };
+
+ waitUntil(function() {
+ return gridContainsText(grid, "Lorem");
+ }, function() {
+ var cells = qaLocal(".v-grid-body .v-grid-cell");
+ assert.equal(cells[3].innerHTML, "Ipsum");
+ done();
+ }, done);
+ }, done);
+
+ });
+
+ it('data: non-object types', function(done) {
+ var first = grid.columns[0];
+ grid.columns.splice(0, 1);
+ grid.columns.push(first);
+ grid.columns.splice(1, 1);
+ grid._grid.setRows(5);
+
+
+ var mydata = [
+ 1, 2, null, undefined, 1, "cellsready"
+ ];
+
+ grid.data.source = function(request) {
+ request.success(mydata.slice(request.index, request.index +
+ request.count), mydata.length);
+ };
+
+ waitUntil(function() {
+ return gridContainsText(grid, "cellsready");
+ }, function() {
+ var cells = qaLocal(".v-grid-body .v-grid-cell");
+ assert.equal(cells[0].innerHTML, "1");
+ assert.equal(cells[1].innerHTML, "2");
+ assert.equal(cells[2].innerHTML, "");
+ assert.equal(cells[3].innerHTML, "");
+ assert.equal(cells[4].innerHTML, "1");
+ done();
+ }, done);
+
+ });
+ });
+</script>
+
+</body>
+</html>
diff --git a/vaadin-grid/test/grid-editing-columns.html b/vaadin-grid/test/grid-editing-columns.html
new file mode 100644
index 0000000..105aa3e
--- /dev/null
+++ b/vaadin-grid/test/grid-editing-columns.html
@@ -0,0 +1,412 @@
+<!DOCTYPE html>
+<html>
+
+<head lang="en">
+ <meta charset="UTF-8">
+ <title></title>
+ <script src="../../webcomponentsjs/webcomponents-lite.min.js"></script>
+ <script src="../../web-component-tester/browser.js"></script>
+
+ <script src="common.js"></script>
+
+ <link rel="import" href="../vaadin-grid.html">
+</head>
+
+<body>
+
+<div id="gridwrapper"></div>
+
+<script>
+ describe.feature('editing columns', function() {
+
+ function getFirstCell() {
+ return qLocal('.v-grid-body .v-grid-cell');
+ }
+
+ beforeEach(function() {
+ return grid.then(function() {
+
+ grid.selection.mode = 'single';
+ grid.frozenColumns = 0;
+ grid.columns = [{name: 'Name', headerContent: 'Name'}, {name: 'Value', headerContent: 'Value'}];
+ grid.data.source = [['Grid', '10000'], ['VaadinX', '1000']];
+
+ return grid;
+ });
+ });
+
+ it('add new column', function() {
+ grid.addColumn({
+ name: "foo",
+ headerContent: "<b>Foo</b>",
+ sortable: true,
+ minWidth: 100,
+ maxWidth: 200,
+ width: 150,
+ flex: 1,
+ });
+
+ var c = grid.columns[grid.columns.length - 1];
+ assert.equal(c.name, "foo");
+ assert.equal(c.headerContent, "<b>Foo</b>");
+ assert.equal(c.sortable, true);
+ assert.notOk(c.editable);
+ assert.equal(c.minWidth, 100);
+ assert.equal(c.maxWidth, 200);
+ assert.equal(c.width, 150);
+ assert.equal(c.flex, 1);
+ });
+
+ it('add new column before', function(done) {
+
+ expect(grid.addColumn.bind(grid, {
+ name: "foo"
+ }, -1)).to.throw("Column not found.");
+
+ expect(grid.addColumn.bind(grid, {
+ name: "foo"
+ }, 100)).to.throw("Column not found.");
+
+ grid.addColumn({
+ name: "foo",
+ headerContent: "foo"
+ }, 0);
+ grid.addColumn({
+ name: "bar",
+ headerContent: "testHtml"
+ }, "foo");
+
+ waitUntil(function() {
+ return gridContainsText(grid, "testHtml");
+ }, function() {
+ var headers = qaLocal(".v-grid-header .v-grid-row th");
+ assert.equal(headers[0].innerHTML, "testHtml");
+ assert.equal(headers[1].innerHTML, "foo");
+
+ expect(grid.addColumn.bind(grid, {
+ name: "baz"
+ }, "foobar")).to.throw("Column not found.");
+ done();
+ }, done);
+
+ });
+
+ it('edit new column', function(done) {
+ var c = {
+ name: "foo",
+ headerContent: "testHtml"
+ };
+ grid.addColumn(c);
+
+ waitUntil(function() {
+ return gridContainsText(grid, "testHtml");
+ }, function() {
+
+ var headers = qaLocal(".v-grid-header .v-grid-row th");
+ assert.equal(headers[grid.columns.length - 1].innerHTML, "testHtml");
+
+ c.headerContent = "testHtml2";
+
+ waitUntil(function() {
+ return gridContainsText(grid, "testHtml2");
+ }, function() {
+ assert.equal(headers[grid.columns.length - 1].innerHTML, "testHtml2");
+ done();
+ }, done);
+
+ }, done);
+
+ });
+
+ it('edit existing column', function(done) {
+ grid.columns[0].headerContent = "testHtml";
+ waitUntil(function() {
+ return gridContainsText(grid, "testHtml");
+ }, function() {
+ var headers = qaLocal(".v-grid-header .v-grid-row th");
+ assert.equal(headers[0].innerHTML, "testHtml");
+ done();
+ });
+ });
+
+ it('generated value', function(done) {
+ grid.addColumn({
+ valueGenerator: function(dataItem) {
+ return "foo " + dataItem[0];
+ }
+ });
+
+ waitUntil(function() {
+ return gridContainsText(grid, "foo Grid");
+ }, done, done);
+ });
+
+ it('setting valueGenerator shouldnt fire select', function() {
+ var selectListener = sinon.spy();
+ grid.addEventListener('select', selectListener);
+
+ grid.selection.mode = "multi";
+ grid.columns[0].valueGenerator = function() { return 1; };
+ expect(selectListener.notCalled).to.be.true;
+ });
+
+ it('should not update the generated value', function(done) {
+ grid.columns[0].valueGenerator = function(dataItem) {
+ return Math.random();
+ };
+
+ grid.then(function() {
+ var generatedValue = getFirstCell().innerText;
+ grid.selection.select(0);
+ expect(generatedValue).to.eql(getFirstCell().innerText);
+ done();
+ });
+
+ });
+
+ it('renderer property', function(done) {
+ grid.columns[0].renderer = function(cell) {
+ cell.element.innerHTML = "<b>" + cell.data + "</b>";
+ };
+
+ waitUntil(function() {
+ return gridContainsText(grid, "<b>Grid</b>");
+ }, done, done);
+ });
+
+ it('renderer: cell values on change', function(done) {
+ var mydata = [
+ ["John", "TestFoo"],
+ ["Jane", "TestBar"],
+ ];
+
+ grid.data.source = mydata;
+
+ grid.columns[1].renderer = function(cell) {
+ cell.element.innerHTML = cell.data;
+ cell.element.cell = cell;
+ };
+
+ waitUntil(function() {
+ return gridContainsText(grid, "TestFoo");
+ }, function() {
+ var cell = grid.querySelectorAll(".v-grid-body .v-grid-cell")[3].cell;
+ assert.equal(cell.row.index, 1);
+ assert.equal(cell.index, 1);
+
+ mydata.splice(0, 1);
+ mydata[0].splice(0, 1);
+ grid.data.clearCache();
+
+ grid.columns.splice(0, 1);
+ waitUntil(function() {
+ return !gridContainsText(grid, "TestFoo");
+ }, function() {
+ assert.equal(cell.row.index, 0);
+ assert.equal(cell.index, 0);
+ done();
+ }, done);
+ }, done);
+
+ });
+
+ it('initial property values', function() {
+ assert.equal(grid.columns[0].headerContent, "Name");
+ });
+
+ describe('modifying columns array directly', function() {
+ it('should replace header content', function() {
+ expect(grid.querySelector('th').textContent).to.equal('Name');
+
+ grid.columns[0].headerContent = 'Foo';
+
+ return grid.then(function() {
+ expect(grid.querySelector('th').textContent).to.equal('Foo');
+ });
+ });
+
+ // fails because of replacing columns doesn't render row contents,
+ // see https://trello.com/c/8e27Tv3q/58-v-grid-bugs
+ it.skip('should render row contents', function() {
+ expect(grid.querySelectorAll('td').textContent).to.equal('Grid');
+
+ grid.columns = [{headerContent: 'Foo'}];
+
+ return grid.then(function() {
+ expect(grid.querySelectorAll('td').textContent).to.equal('Grid');
+ });
+ });
+ });
+
+ it('modify columns array', function(done) {
+ var col = grid.columns[0];
+ grid.columns.splice(1, 1);
+
+ waitUntil(function() {
+ return !gridContainsText(grid, "Progress");
+ }, function() {
+ grid.columns.push({
+ headerContent: "testHtml"
+ });
+ waitUntil(function() {
+ return gridContainsText(grid, "testHtml");
+ }, done, done);
+ }, done);
+ });
+
+ it('remove column', function(done) {
+ grid.addColumn({
+ name: "test",
+ headerContent: "test"
+ });
+ grid.removeColumn(0);
+
+ waitUntil(function() {
+ return !gridContainsText(grid, "Name") && gridContainsText(grid, "test");
+ }, function() {
+ grid.removeColumn("test");
+ waitUntil(function() {
+ return !gridContainsText(grid, "test");
+ }, done, done);
+ }, done);
+ });
+
+ it('add new column to an empty grid', function(done) {
+ grid.columns = [];
+
+ grid.columns.push({
+ name: "foo",
+ headerContent: "fooheader"
+ });
+
+ grid.then(function() {
+ expect(gridContainsText(grid, 'fooheader')).to.be.true;
+ done();
+ });
+ });
+
+ it('frozen column', function(done) {
+ grid.frozenColumns = 1;
+
+ waitUntil(function() {
+ return gridContainsText(grid, "v-grid-cell frozen");
+ }, function() {
+ var headers = qaLocal(".v-grid-header .v-grid-row th");
+ assert.isTrue(headers[0].classList.contains("frozen"));
+ done();
+ }, done);
+
+ });
+
+ it('frozen column declarative', function() {
+ grid.setAttribute("frozen-columns", "1");
+
+ return grid.then(function() {
+ expect(function(){grid.selection.mode = "multi";}).not.to.throw();
+ });
+ });
+
+ it('frozen column: unfreeze selection column', function() {
+ grid.selection.mode = "multi";
+ assert.ok(qLocal(".frozen"));
+
+ grid.frozenColumns = -1;
+ assert.notOk(qLocal(".frozen"));
+ });
+
+ it('should add a column to an empty grid with an index', function() {
+ grid.columns = [];
+ return grid.then(function() {
+ grid.addColumn({headerContent: "foo"}, 0);
+ return grid;
+ }).then(function() {
+ expect(qaLocal(".v-grid-header .v-grid-cell")).to.have.length(1);
+ return grid;
+ });
+ });
+
+ it('should reference header cell after adding a new column', function() {
+ grid.addColumn({name: "foo"});
+ grid.header.getCell(0, "foo").content = "foo";
+ expect(grid.columns[2].headerContent).to.eql("foo");
+ });
+
+ it('should support nested column names', function() {
+ grid.addColumn({
+ name: "foo.bar.baz",
+ });
+ grid.data.source = [{
+ foo: {
+ bar: {
+ baz: "testing"
+ }
+ }
+ }];
+ return grid.then(function() {
+ expect(gridContainsText(grid, "testing")).to.be.true;
+ });
+ });
+
+ it('should not return values from name path', function() {
+ grid.addColumn({
+ name: "foo.bar.baz",
+ });
+ grid.data.source = [{
+ foo: {
+ bar: "testing"
+ }
+ }];
+ return grid.then(function() {
+ expect(gridContainsText(grid, "testing")).to.be.false;
+ });
+ });
+
+ it('should allow undefined nested values', function() {
+ grid.addColumn({
+ name: "foo.bar.baz",
+ });
+ grid.data.source = [{
+ foo: {
+ bar: undefined
+ }
+ }];
+ return grid.then(function() {
+ expect(qaLocal(".v-grid-body .v-grid-cell")[2].innerHTML).to.be.empty;
+ });
+ });
+
+ it('should have the right default value if flex attribute exists', function() {
+ qLight("table col").setAttribute("flex", "");
+ return grid.then(function() {
+ expect(grid.columns[0].flex).to.eql(1);
+ expect(grid.columns[1].flex).to.eql(-1);
+ });
+ });
+
+ it('should size columns with width property', function() {
+ grid.columns[0].width = 100;
+ return grid.then(function(){
+ expect(qLocal(".v-grid-cell").offsetWidth).to.eql(100);
+ });
+ });
+
+ it('should size columns with minWidth property', function() {
+ grid.columns[0].width = 100;
+ grid.columns[0].minWidth = 150;
+ return grid.then(function(){
+ expect(qLocal(".v-grid-cell").offsetWidth).to.eql(150);
+ });
+ });
+
+ it('should size columns with maxWidth property', function() {
+ grid.columns[0].maxWidth = 100;
+ return grid.then(function(){
+ expect(qLocal(".v-grid-cell").offsetWidth).to.eql(100);
+ });
+ });
+
+ });
+</script>
+
+</body>
+</html>
diff --git a/vaadin-grid/test/grid-editor-handler.html b/vaadin-grid/test/grid-editor-handler.html
new file mode 100644
index 0000000..20c6e66
--- /dev/null
+++ b/vaadin-grid/test/grid-editor-handler.html
@@ -0,0 +1,202 @@
+<!DOCTYPE html>
+<html>
+
+<head lang="en">
+ <meta charset="UTF-8">
+ <title></title>
+ <script src="../../webcomponentsjs/webcomponents-lite.min.js"></script>
+ <script src="../../web-component-tester/browser.js"></script>
+
+ <script src="common.js"></script>
+
+ <link rel="import" href="../vaadin-grid.html">
+</head>
+
+<body>
+
+<div id="gridwrapper"></div>
+
+<script>
+ describe.feature('using editor handler', function() {
+ var editorHandler;
+
+ beforeEach(function() {
+ grid.columns = [{name: 'Name'}, {name: 'Value'}];
+ grid.editor.cancel();
+
+ editorHandler = {
+ getCellEditor: function(columnObject) {
+ var input = document.createElement("input");
+ return input;
+ },
+ bind: function(req) {
+ for (var i = 0; i < req.grid.columns.length; i++) {
+ var col = req.grid.columns[i];
+ if (!col.readOnly) {
+ var el = req.getCellEditor(col);
+ el.value = req.dataItem[i];
+ }
+ }
+ req.success();
+ },
+ save: function(req) {
+ var failingColumns = [];
+ for (var i = 0; i < req.grid.columns.length; i++) {
+ var col = req.grid.columns[i];
+ var el = req.getCellEditor(col);
+ if (el.value == "fail") {
+ failingColumns.push(col);
+ }
+ }
+ if (failingColumns.length > 0) {
+ req.failure("Save failed", failingColumns);
+ } else {
+ req.success();
+ }
+ }
+ };
+
+ grid.editor.handler = editorHandler;
+
+ return grid;
+ });
+
+ it('editor: enabled', function() {
+ grid.columns[0].name = "name";
+ grid.columns[1].name = "value";
+ grid.editor.handler = editorHandler;
+ expect(grid.editor.editRow.bind(grid.editor, 0)).to.throw("editor is not enabled");
+ grid.editor.enabled = true;
+ grid.editor.editRow(0);
+
+ assert.isTrue(gridContainsText(grid, "v-grid-editor"));
+ });
+
+ it('editor: saveButtonText and cancelButtonText', function() {
+ grid.columns[0].name = "name";
+ grid.columns[1].name = "value";
+ grid.editor.handler = editorHandler;
+ grid.editor.enabled = true;
+ grid.editor.editRow(0);
+ grid.editor.saveButtonText = "saveButtonTextFoo";
+ grid.editor.cancelButtonText = "cancelButtonTextFoo";
+
+ assert.isTrue(gridContainsText(grid, "saveButtonTextFoo"));
+ assert.isTrue(gridContainsText(grid, "cancelButtonTextFoo"));
+ });
+
+ it('editor: editrow', function() {
+ grid.columns[0].name = "name";
+ grid.columns[1].name = "value";
+ grid.editor.handler = editorHandler;
+ grid.editor.enabled = true;
+
+ grid.editor.editRow(0);
+ assert.equal(qLocal(".v-grid-editor input").value, "Grid");
+ grid.editor.cancel();
+ assert.isFalse(gridContainsText(grid, "v-grid-editor"));
+ grid.editor.editRow(1);
+ assert.equal(qLocal(".v-grid-editor input").value, "VaadinX");
+ grid.editor.save();
+ assert.isFalse(gridContainsText(grid, "v-grid-editor"));
+
+ expect(grid.editor.editRow.bind(grid.editor, 10)).to.throw("Row index");
+ });
+
+ it('editor: failure', function() {
+ grid.columns[0].name = "name";
+ grid.columns[1].name = "value";
+ grid.editor.handler = editorHandler;
+ grid.editor.enabled = true;
+
+ grid.editor.editRow(0);
+ var fields = qaLocal(".v-grid-editor input");
+ fields[0].value = "fail";
+ grid.editor.save();
+
+ assert.isTrue(gridContainsText(grid, "Save failed"));
+ var cells = qaLocal(".v-grid-editor-cells > div");
+ assert.isTrue(cells[0].classList.contains("error"));
+ assert.isFalse(cells[1].classList.contains("error"));
+
+ });
+
+ it('editor: return null cell editor', function() {
+ grid.columns[0].name = "name";
+ grid.columns[1].name = "value";
+ grid.editor.handler = {
+ getCellEditor: function(columnObject) {
+ return columnObject === grid.columns[0] ? null : undefined;
+ },
+ bind: function(req) {
+ req.success();
+ }
+ };
+ grid.editor.enabled = true;
+
+ grid.editor.editRow(0);
+ var cells = qaLocal(".v-grid-editor .v-grid-editor-cells > div");
+ assert.lengthOf(cells, 2);
+
+ var editors = qaLocal(".v-grid-editor .v-grid-editor-cells > div *");
+ assert.lengthOf(editors, 0);
+ });
+
+ it('editor: element instance after save', function() {
+ grid.editor.enabled = true;
+ grid.editor.handler = editorHandler;
+
+ var editor1, editor2;
+ editorHandler.save = function(req) {
+ if (!editor1) {
+ editor1 = req.getCellEditor(grid.columns[0]);
+ req.failure();
+ } else {
+ editor2 = req.getCellEditor(grid.columns[0]);
+ req.success();
+ }
+ };
+ grid.editor.editRow(0);
+
+ //Save fails
+ grid.editor.save();
+ //Save succeeds
+ grid.editor.save();
+
+ assert.equal(editor1, editor2);
+ });
+
+ // fails because of replacing columns doesn't render row contents,
+ // see https://trello.com/c/8e27Tv3q/58-v-grid-bugs
+ it.skip('editor: default editor', function() {
+ grid.editor.enabled = true;
+ grid.editor.editRow(0);
+
+ return grid.then(function() {
+ assert.equal("Grid", grid.querySelector('tbody tr td').textContent);
+ assert.equal("Grid", grid.querySelector('input').value);
+
+ grid.querySelector('input').value = "Foo";
+ grid.editor.save();
+ });
+
+ });
+
+ it('editor: getCellEditor and read-only columns', function() {
+ grid.columns[0].readOnly = true;
+
+ sinon.spy(editorHandler, "getCellEditor");
+
+ grid.editor.handler = editorHandler;
+ grid.editor.enabled = true;
+ grid.editor.editRow(0);
+
+ assert.isTrue(editorHandler.getCellEditor.calledOnce);
+
+ editorHandler.getCellEditor.restore();
+ });
+ });
+</script>
+
+</body>
+</html>
diff --git a/vaadin-grid/test/grid-properties.html b/vaadin-grid/test/grid-properties.html
new file mode 100644
index 0000000..46743a4
--- /dev/null
+++ b/vaadin-grid/test/grid-properties.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<html>
+
+<head lang="en">
+ <meta charset="UTF-8">
+ <title></title>
+ <script src="../../webcomponentsjs/webcomponents-lite.min.js"></script>
+ <script src="../../web-component-tester/browser.js"></script>
+
+ <script src="common.js"></script>
+
+ <link rel="import" href="../vaadin-grid.html">
+</head>
+
+<body>
+
+<div id="gridwrapper"></div>
+
+<script>
+ describe.feature('using properties', function() {
+
+ it('rowClassGenerator', function() {
+ var gridEquals = true;
+ var elementEquals = true;
+ assert.notOk(grid.rowClassGenerator);
+ var rowClassGenerator = function(row) {
+ gridEquals = gridEquals && row.grid == grid;
+ elementEquals = elementEquals && row.element == qaLocal(".v-grid-body .v-grid-row")[row.index];
+ return row.index + "_" + row.data[0];
+ };
+
+ grid.rowClassGenerator = rowClassGenerator;
+
+ assert.isTrue(elementEquals && gridEquals);
+ assert.isTrue(qLocal(".v-grid-body .v-grid-row").classList.contains("0_Grid"));
+ assert.equal(grid.rowClassGenerator, rowClassGenerator);
+ });
+
+ it('cellClassGenerator', function() {
+ var elementEquals = true;
+
+ grid.columns[0].name = "name";
+ grid.columns[1].name = "value";
+ assert.notOk(grid.cellClassGenerator);
+ var cellClassGenerator = function(cell) {
+ var columnIndex = cell.columnName == "name" ? 0 : 1;
+ var cellElement = qaLocal(".v-grid-body .v-grid-row")[cell.row.index].querySelectorAll(".v-grid-cell")[columnIndex];
+ elementEquals = elementEquals && cell.element == cellElement;
+ return cell.columnName;
+ };
+
+ grid.cellClassGenerator = cellClassGenerator;
+
+ assert.isTrue(elementEquals);
+ assert.isTrue(qLocal(".v-grid-body .v-grid-row .v-grid-cell").classList.contains("name"));
+ assert.equal(grid.cellClassGenerator, cellClassGenerator);
+ });
+
+ it('should be enabled by default', function() {
+ expect(grid.disabled).to.be.false;
+ });
+
+ it('should disable', function() {
+ grid.disabled = true;
+ expect(grid.disabled).to.be.true;
+ });
+
+ it('should reflect disabled to attribute', function() {
+ grid.disabled = true;
+ expect(grid.hasAttribute("disabled")).to.be.true;
+ grid.disabled = false;
+ expect(grid.hasAttribute("disabled")).to.be.false;
+ });
+
+ it('should apply disabled attribute', function() {
+ grid.setAttribute("disabled", true);
+ expect(grid.disabled).to.be.true;
+ grid.removeAttribute("disabled");
+ expect(grid.disabled).to.be.false;
+ });
+ });
+
+</script>
+
+</body>
+</html>
diff --git a/vaadin-grid/test/grid-redrawer.html b/vaadin-grid/test/grid-redrawer.html
new file mode 100644
index 0000000..81c5f49
--- /dev/null
+++ b/vaadin-grid/test/grid-redrawer.html
@@ -0,0 +1,201 @@
+<!DOCTYPE html>
+<html>
+
+<head lang="en">
+ <meta charset="UTF-8">
+ <title></title>
+ <script src="../../webcomponentsjs/webcomponents-lite.min.js"></script>
+ <script src="../../web-component-tester/browser.js"></script>
+
+ <script src="common.js"></script>
+
+ <link rel="import" href="../vaadin-grid.html">
+</head>
+
+<body>
+
+<div id="gridwrapper"></div>
+
+<script>
+ describe.feature('redrawer', function() {
+ function width(e) {
+ return pxval(e, 'width');
+ }
+
+ function height(e) {
+ return pxval(e, 'height');
+ }
+
+ function pxval(e, prop) {
+ return parseInt(e.ownerDocument.defaultView.getComputedStyle(e).getPropertyValue(prop).replace('px', ''));
+ }
+
+ describe('redraw', function() {
+ function assertHeightByRows(rows) {
+ var headersHeight = headers * thHeight;
+ var footersHeight = footers * tfHeight;
+
+ h1 = headersHeight + footersHeight + rows * tdHeight;
+ // IE and FF add an aditional pixel to each row
+ h2 = h1 + rows + headers + footers;
+
+ expect([h1, h2]).to.include(height(inner));
+ }
+
+ function assertSameDimensions() {
+ expect(width(grid)).to.equal(width(inner));
+ expect(height(grid)).to.equal(height(inner));
+ }
+
+ var inner,
+ tbody,
+ headers,
+ footers,
+ tfHeight,
+ thHeight,
+ tdHeight
+
+ beforeEach(function() {
+ inner = qaLocal("div.v-grid")[1];
+ tbody = qLight('table tbody');
+
+ headers = qaLocal('thead tr').length;
+ footers = qaLocal('tfoot tr').length;
+
+ tfHeight = height(qLocal('tfoot tr td'));
+ thHeight = height(qLocal('thead tr th'));
+ tdHeight = height(qLocal('tbody tr td'));
+
+ grid.style.height = "";
+ grid.style.width = "";
+ grid.removeAttribute('rows');
+
+ // need to return thenable object for FF sake.
+ return grid;
+ });
+
+ // currently disabled because the grid.then call jams the test on IE.
+ it.skip('should draw correct dimensions and row heights by default', function() {
+ return grid.then(function() {
+ assertSameDimensions();
+ assertHeightByRows(2);
+ });
+ });
+
+ it('should redraw correctly after modifying body', function() {
+ tbody.innerHTML += tbody.innerHTML;
+
+ return grid.then(function() {
+ assertSameDimensions();
+ assertHeightByRows(4);
+ });
+ });
+
+ describe('using limited row visibility', function() {
+ before(function() {
+ // Increase the number of rows
+ tbody.innerHTML += tbody.innerHTML; //4
+ tbody.innerHTML += tbody.innerHTML; //8
+ tbody.innerHTML += tbody.innerHTML; //16
+
+ return grid;
+ });
+
+ it('should redraw only visible rows', function() {
+ return grid.then(function() {
+ assertSameDimensions();
+
+ // grid has a limit of 10 data rows by default
+ assertHeightByRows(10);
+ });
+ });
+
+ it('should redraw visible rows after limit is decreased', function() {
+ grid.rows = 3;
+
+ return grid.then(function() {
+ assertSameDimensions();
+
+ assertHeightByRows(3);
+ });
+ });
+
+ it('should redraw visible rows limit is removed', function() {
+ grid.rows = 0;
+
+ return grid.then(function() {
+ assertSameDimensions();
+
+ assertHeightByRows(10); // default
+ });
+ });
+ });
+
+ it('should redraw with fixed dimensions', function() {
+ grid.style.width = '300px';
+ grid.style.height = '100px';
+
+ return grid.then(function() {
+ return grid.then(function() {
+ assertSameDimensions();
+ });
+ });
+ });
+
+ describe('grid with a fixed height (issue #8)', function() {
+ it('should keep the correct height after sorting', function() {
+ grid.columns[0].sortable = true;
+ grid.style.height = "500px";
+
+ var firstNonFrozenHeaderCell = qLocal.bind(this, ".v-grid-header .v-grid-cell:not(.frozen)");
+ firstNonFrozenHeaderCell().click();
+
+ return grid.then(function() {
+ expect(qaLocal('.v-grid')[3].style.height).to.equal('100%');
+ });
+ });
+ });
+
+ describe('using scaled dimensions', function() {
+ beforeEach(function() {
+ grid.style.position = 'absolute';
+ grid.style.width = '100%';
+ grid.style.height = '100%';
+
+ return grid;
+ });
+
+ it('should redraw with scaled dimensions', function() {
+ assertSameDimensions();
+ });
+
+ it('should match dimensions with the surrounding div', function() {
+ expect(height(grid)).to.equal(document.body.clientHeight);
+
+ // For some reason in IE sometimes there is a slight difference of 1 pixels
+ expect(Math.abs(document.body.clientWidth - width(grid))).to.be.at.most(1);
+ })
+
+ it('should allow different dimensions for v-grid and inner div', function() {
+ // We can have different height for v-grid and the inner grid.
+ // Also we can define more than 10 rows.
+ tbody.innerHTML += tbody.innerHTML; //4
+ tbody.innerHTML += tbody.innerHTML; //8
+ tbody.innerHTML += tbody.innerHTML; //16
+
+ grid.rows = 12;
+ grid.style.width = '50%';
+
+ return grid.then(function() {
+ expect(height(grid)).to.not.equal(height(inner));
+ assert.equal(width(grid), width(inner));
+ assertHeightByRows(12);
+ });
+ });
+ });
+ });
+ });
+</script>
+
+</body>
+</html>
diff --git a/vaadin-grid/test/grid-rendering-light-dom.html b/vaadin-grid/test/grid-rendering-light-dom.html
new file mode 100644
index 0000000..0251cd7
--- /dev/null
+++ b/vaadin-grid/test/grid-rendering-light-dom.html
@@ -0,0 +1,130 @@
+<!DOCTYPE html>
+<html>
+
+<head lang="en">
+ <meta charset="UTF-8">
+ <title></title>
+ <script src="../../webcomponentsjs/webcomponents-lite.min.js"></script>
+ <script src="../../web-component-tester/browser.js"></script>
+
+ <script src="common.js"></script>
+
+ <link rel="import" href="../vaadin-grid.html">
+</head>
+
+<body>
+
+<div id="gridwrapper"></div>
+
+<script>
+ describe.feature('rendering light DOM', function() {
+ it('light dom table header gets rendered in the grid', function() {
+ var row = qLocal(".v-grid-header .v-grid-row");
+ var cells = row.childNodes;
+
+ assert.isTrue(cells[0].innerHTML == 'Name');
+ assert.isTrue(cells[1].innerHTML == 'Value');
+ });
+
+ it('light dom table body gets rendered in the grid', function() {
+ var row = qLocal(".v-grid-body .v-grid-row");
+ var cells = row.childNodes;
+
+ assert.isTrue(cells[0].innerHTML == 'Grid');
+ assert.isTrue(cells[1].innerHTML == '10000');
+ });
+
+ function removeGrid() {
+ if (grid) {
+ grid.style.visibility = "hidden";
+ document.body.appendChild(grid);
+ grid = null;
+ }
+ }
+
+ // makes grid.then in afterEach to never finish...
+ it.skip('DOM: headers & footers', function(done) {
+// removeGrid();
+ wrapper.innerHTML = "<v-grid><table>" +
+ "<thead hidden><tr class='red'><td colspan='2'></td></tr><tr class='pink'><th></th><th></th></tr></thead>" +
+ "<tfoot><tr class='foot1'><td colspan='2'></td></tr><tr class='foot2'><td></td><td></td></tr></tfoot>" +
+ "</table></v-grid>";
+ grid = wrapper.querySelector("v-grid");
+
+ waitUntil(function() {
+ return qLocal(".v-grid-body");
+ }, function() {
+ assert.equal(0, qaLocal("thead tr").length);
+ assert.equal(1, qaLocal("tfoot tr.foot1").length);
+ assert.equal(1, qaLocal("tfoot tr.foot2").length);
+ assert.equal(1, qaLocal("tfoot td[colspan='2']").length);
+
+ qLight("thead").setAttribute('hidden', false)
+ waitUntil(function() {
+ return qaLocal("thead tr").length > 0;
+ }, function() {
+ assert.equal(1, qaLocal("thead tr.red").length);
+ assert.equal(1, qaLocal("thead tr.pink").length);
+ assert.equal(1, qaLocal("thead th[colspan='2']").length);
+ done();
+ }, done);
+
+ }, done);
+ });
+
+ it('DOM: mutation', function(done) {
+ waitUntil(function() {
+ return qLocal(".v-grid-body");
+ }, function() {
+ var nrows = qaLocal("tbody tr").length;
+ var nheads = qaLocal("thead tr").length;
+ qLight("thead").innerHTML += qLight("table thead").innerHTML;
+ qLight("tbody").innerHTML += qLight("table tbody").innerHTML;
+ assert.equal("Name", qLocal("th").textContent);
+ qLight("th").textContent = "foo";
+ waitUntil(function() {
+ return qLocal("tbody tr") && qaLocal("tbody tr").length == nrows * 2;
+ }, function() {
+ assert.equal(qaLocal("tbody tr").length, nrows * 2);
+ assert.equal(qaLocal("thead tr").length, nheads * 2);
+ assert.equal("foo", qLocal("th").textContent);
+ done();
+ }, done);
+ }, done);
+ });
+
+ it('should have a sort-order', function(done) {
+ var ths = light().querySelectorAll("th");
+ ths[0].setAttribute("sort-direction", "asc");
+ ths[1].setAttribute("sort-direction", "desc");
+
+ grid.then(function(){
+ var sortOrder = grid.sortOrder;
+ expect(grid.sortOrder[0]).to.eql({column: 0, direction: "asc"});
+ expect(grid.sortOrder[1]).to.eql({column: 1, direction: "desc"});
+ }).then(done);
+ });
+
+ it('should apply header-text from a th element', function(done) {
+ light().querySelector("th").setAttribute("header-text", "foo");
+
+ grid.then(function(){
+ expect(grid.columns[0].headerHtml).to.eql("foo");
+ }).then(done);
+ });
+
+ it('should apply header-text from a col element', function(done) {
+ var col = document.createElement("col");
+ col.setAttribute("header-text", "foo");
+ light().querySelector("table").prependChild(col);
+
+ grid.then(function(){
+ expect(grid.columns[0].headerHtml).to.eql("foo");
+ }).then(done);
+ });
+
+ });
+</script>
+
+</body>
+</html>
diff --git a/vaadin-grid/test/grid-scrolling-rows.html b/vaadin-grid/test/grid-scrolling-rows.html
new file mode 100644
index 0000000..a0ff781
--- /dev/null
+++ b/vaadin-grid/test/grid-scrolling-rows.html
@@ -0,0 +1,114 @@
+<!DOCTYPE html>
+<html>
+
+<head lang="en">
+ <meta charset="UTF-8">
+ <title></title>
+ <script src="../../webcomponentsjs/webcomponents-lite.min.js"></script>
+ <script src="../../web-component-tester/browser.js"></script>
+
+ <script src="common.js"></script>
+
+ <link rel="import" href="../vaadin-grid.html">
+</head>
+
+<body>
+
+<div id="gridwrapper"></div>
+
+<script>
+ describe.feature('scrolling rows', function() {
+
+ var infiniteDataSource = function(req) {
+ var data = [];
+ for (var i = req.index; i < req.index + req.count; i++) {
+ data.push(["foo " + i, "bar " + i]);
+ }
+ req.success(data, this.size);
+ };
+
+ function firstColumnContents() {
+ var cells = qaLocal('td');
+
+ return _.chain(cells)
+ .filter(function(n) {
+ return _.indexOf(cells, n) % 2 == 0;
+ })
+ .map(function(n) {
+ return n.textContent;
+ })
+ .reduce(function(result, n) {
+ return result + ', ' + n;
+ }).value();
+ }
+
+ before(function() {
+ infiniteDataSource.size = 100;
+ grid.data.source = infiniteDataSource;
+ grid.rows = 5;
+
+ return grid;
+ });
+
+ beforeEach(function() {
+ //reset position to an arbitrary row.
+ return grid.scrollToRow(24).then(function () {
+ // calling scrollToRow - scrollToRow - then seems to quite often
+ // run the callback in 'then' before the latter scrolling has finished.
+ // This is most likely caused by multiple timers being fired inside the Grid,
+ // and there's some gap between them - which makes grid.isWorkPending() to return
+ // 'false' too soon.
+ // Adding one 'then' in between the scrolling calls
+ // doesn't seem to remedy the situation. So let's add more.
+ return grid;
+ });
+ });
+
+ it('should throw an error when scrolling to an invalid row', function() {
+ expect(grid.scrollToRow.bind(grid, -1)).to.throw("Row index");
+ expect(grid.scrollToRow.bind(grid, 100)).to.throw("Row index");
+ });
+
+ it('should scroll using scrollToRow', function() {
+ return grid.scrollToRow(50)
+ .then(function() {
+ expect(firstColumnContents()).to.contain('foo 50');
+ });
+ });
+
+ describe('scrolling with destination', function() {
+ it('should scroll to start', function() {
+ return grid.scrollToRow(50, 'start')
+ .then(function() {
+ expect(firstColumnContents()).to.contain('foo 50');
+ expect(firstColumnContents()).to.contain('foo 54');
+ });
+ });
+
+ it('should scroll to end', function() {
+ return grid.scrollToRow(50, 'end')
+ .then(function() {
+ expect(firstColumnContents()).to.contain('foo 46');
+ expect(firstColumnContents()).to.contain('foo 50');
+ });
+ });
+ });
+
+ it('should scroll to end', function() {
+ return grid.scrollToEnd()
+ .then(function() {
+ expect(firstColumnContents()).to.contain('foo 99');
+ });
+ });
+
+ it('should scroll to start', function() {
+ return grid.scrollToStart()
+ .then(function() {
+ expect(firstColumnContents()).to.contain('foo 0');
+ });
+ });
+ });
+</script>
+
+</body>
+</html>
diff --git a/vaadin-grid/test/grid-selecting-rows.html b/vaadin-grid/test/grid-selecting-rows.html
new file mode 100644
index 0000000..0ac2eee
--- /dev/null
+++ b/vaadin-grid/test/grid-selecting-rows.html
@@ -0,0 +1,645 @@
+<!DOCTYPE html>
+<html>
+
+<head lang="en">
+ <meta charset="UTF-8">
+ <title></title>
+ <script src="../../webcomponentsjs/webcomponents-lite.min.js"></script>
+ <script src="../../web-component-tester/browser.js"></script>
+
+ <script src="common.js"></script>
+
+ <link rel="import" href="../vaadin-grid.html">
+</head>
+
+<body>
+
+ <div id="gridwrapper"></div>
+
+ <script>
+ describe.feature('selecting rows', function() {
+ var selectListener;
+
+ before(function() {
+ selectListener = sinon.spy();
+ grid.addEventListener('select', selectListener);
+ });
+
+ function getSelectionModeAttr() {
+ return grid.getAttribute('selection-mode');
+ };
+
+ function setSelectionModeAttr(mode) {
+ grid.setAttribute('selection-mode', mode);
+
+ return grid;
+ };
+
+ afterEach(function() {
+ selectListener.reset();
+
+ return grid.then(function() {
+ // force selection clear
+ grid.selection.mode = 'disabled';
+ grid.selection.mode = 'single';
+
+ return grid;
+ });
+ });
+
+ describe('using attributes', function() {
+ describe('selection-mode', function() {
+ it('should set selectionMode to disabled', function() {
+ return setSelectionModeAttr('disabled').then(function() {
+ expect(grid.selection.mode).to.equal('disabled');
+ });
+ });
+
+ it('should set selectionMode to single', function() {
+ return setSelectionModeAttr('single').then(function() {
+ expect(grid.selection.mode).to.equal('single');
+ });
+ });
+
+ it('should set selectionMode to multi', function() {
+ return setSelectionModeAttr('multi').then(function() {
+ expect(grid.selection.mode).to.equal('multi');
+ });
+ });
+
+ it('should should remove selectionMode property', function() {
+ setSelectionModeAttr('disabled');
+ grid.removeAttribute('selection-mode');
+
+ return grid.then(function() {
+ // 'single' is the default
+ expect(grid.selection.mode).to.equal('single');
+ });
+ });
+
+ // TODO: throws an error, but for some reason expect doesn't catch it.
+ it.skip('should fail setting the value to foobar', function() {
+ expect(function() {
+ setSelectionModeAttr('foobar');
+ }).to.throw(Object);
+ });
+ });
+ });
+
+ describe('using properties', function() {
+ describe('selection.mode', function() {
+ var checkBoxQuery = "input[type='checkbox']";
+
+ it('should be single by default', function() {
+ expect(grid.selection.mode).to.equal('single');
+ });
+
+ it('should be use default value when removing the value', function() {
+ grid.selection.mode = 'disabled';
+
+ grid.selection.mode = undefined;
+
+ expect(grid.selection.mode).to.equal('single');
+ });
+
+ it('should set selection-mode to disabled', function() {
+ grid.selection.mode = 'disabled';
+
+ return grid.then(function() {
+ expect(getSelectionModeAttr()).to.equal('disabled');
+ expect(qLocal(checkBoxQuery)).to.be.undefined;
+ });
+ });
+
+ it('should set selection-mode to single', function() {
+ grid.selection.mode = 'single';
+
+ return grid.then(function() {
+ expect(getSelectionModeAttr()).to.equal('single');
+ expect(qLocal(checkBoxQuery)).to.be.undefined;
+ });
+ });
+
+ it('should set selection-mode to multi', function() {
+ grid.selection.mode = 'multi';
+
+ return grid.then(function() {
+ expect(getSelectionModeAttr()).to.equal('multi');
+ expect(qLocal(checkBoxQuery)).to.not.be.undefined;
+ });
+ });
+
+ it('should fail setting the value to foobar', function() {
+ expect(function() {
+ grid.selection.mode = 'foobar';
+ }).to.throw(Object);
+ });
+ });
+
+ describe('selected', function() {
+ describe('with mode: single', function() {
+ beforeEach(function() {
+ grid.selection.mode = 'single';
+ });
+
+ it('should clear the selection when changing mode to disabled', function() {
+ grid.selection.select(0);
+
+ grid.selection.mode = 'disabled';
+
+ expect(grid.selection.selected()).to.be.empty;
+ });
+
+ it('should clear selection when changing mode to multi', function() {
+ grid.selection.select(0);
+
+ grid.selection.mode = 'multi';
+
+ expect(grid.selection.selected()).to.be.empty;
+ });
+ });
+
+ describe('with selectionMode: multi', function() {
+ beforeEach(function() {
+ grid.selection.mode = 'multi';
+ });
+
+ it('should fire a \'select\' event', function() {
+ grid.selection.select(0);
+
+ expect(selectListener.calledOnce).to.be.true;
+ });
+
+ it('should clear the selection when changing mode to disabled', function() {
+ grid.selection.select(0);
+
+ grid.selection.mode = 'disabled';
+
+ expect(grid.selection.selected()).to.be.empty;
+ });
+
+ it('should clear selection when changing mode to single', function() {
+ grid.selection.select(0);
+
+ grid.selection.mode = 'single';
+
+ expect(grid.selection.selected()).to.be.empty;
+ });
+
+ it('should remove multiple selections when changing mode to single', function() {
+ grid.selection.select(0);
+ grid.selection.select(1);
+
+ grid.selection.mode = 'single';
+
+ expect(grid.selection.selected()).to.be.empty;
+ });
+ });
+
+ describe('with selectionMode: disabled', function() {
+ beforeEach(function() {
+ grid.selection.mode = 'disabled';
+ });
+
+ it('should not select any rows', function() {
+ grid.selection.select(0);
+
+ expect(grid.selection.selected()).to.be.empty;
+ });
+ });
+ });
+ });
+
+ describe('by clicking', function() {
+ function getFirstCell() {
+ return qLocal('.v-grid-body .v-grid-cell');
+ }
+
+ function clickFirstCell() {
+ getFirstCell().click();
+
+ return grid;
+ }
+
+ before(function() {
+ // extra 'wait' added for IE11.
+ return grid;
+ });
+
+ it('should fire a \'select\' event', function()  {
+ return clickFirstCell().then(function() {
+ expect(selectListener.calledOnce).to.be.true;
+ expect(selectListener.args[0][0]).to.have.property('type', 'select');
+ });
+ });
+
+ describe('with selection-mode: single', function() {
+ beforeEach(function() {
+ return setSelectionModeAttr('single');
+ });
+
+ it('should select a row', function() {
+ return clickFirstCell().then(function() {
+ expect(grid.selection.selected()).to.eql([0]);
+ });
+ });
+ });
+
+ describe('with selection-mode: multi', function() {
+ beforeEach(function() {
+ return setSelectionModeAttr('multi');
+ });
+
+ it('should only focus a clicked cell', function() {
+ return clickFirstCell().then(function() {
+ expect(grid.selection.selected()).to.be.empty;
+ expect(getFirstCell().getAttribute('class')).to.contain('focus');
+ });
+ });
+
+ // TODO: apparently clicking checkboxes isn't going to happen using JS...
+ it.skip('should select multiple rows', function() {
+ var inputs = qaLocal('input');
+ inputs[0].checked = true;
+ inputs[1].click();
+
+ expect(getSelectedRowsAttr()).to.equal('0,1');
+ });
+ });
+
+ describe('with selection-mode: disabled', function() {
+ beforeEach(function() {
+ return setSelectionModeAttr('disabled');
+ });
+
+ it('should not select a row', function() {
+ return clickFirstCell().then(function() {
+ expect(grid.selection.selected()).to.be.empty;
+ });
+ });
+ });
+ });
+
+ describe('by using API', function() {
+ it('should fire a \'select\' event', function() {
+ grid.selection.select(0);
+
+ expect(selectListener.calledOnce).to.be.true;
+ });
+
+ it('should not select invalid row', function() {
+ grid.selection.select('foo');
+
+ expect(grid.selection.selected()).to.be.empty;
+ });
+
+ it('should add \'row-selected\' class to the selected row', function() {
+ return grid.selection.select(1).then(function() {
+ expect(qaLocal('.v-grid-body .v-grid-row-selected')).to.have.length(1);
+ });
+ });
+
+ describe('with selectionMode: single', function() {
+ beforeEach(function() {
+ grid.selection.mode = 'single';
+ });
+
+ it('should select a row', function() {
+ grid.selection.select(1);
+
+ expect(grid.selection.selected()).to.eql([1]);
+ });
+
+ it('should select another row', function() {
+ grid.selection.select(1);
+ grid.selection.select(0);
+
+ expect(grid.selection.selected()).to.eql([0]);
+ });
+ });
+
+ describe('with selectionMode: multi', function() {
+ beforeEach(function() {
+ grid.selection.mode = 'multi';
+ })
+
+ it('should select multiple rows', function() {
+ grid.selection.select(0);
+ grid.selection.select(1);
+
+ expect(grid.selection.selected()).to.eql([0,1]);
+ });
+ });
+
+ describe('with selectionMode: disabled', function() {
+ beforeEach(function() {
+ grid.selection.mode = 'disabled';
+ });
+
+ it('should not select a row', function() {
+ grid.selection.select(0);
+
+ expect(grid.selection.selected()).to.be.empty;
+ });
+ });
+ });
+
+ describe('deselecting rows using API', function() {
+ it('should fire \'select\' event', function() {
+ grid.selection.select(0);
+
+ grid.selection.deselect(0);
+
+ expect(selectListener.calledTwice).to.be.true;
+ });
+
+ describe('with selectionMode: single', function() {
+ beforeEach(function() {
+ grid.selection.mode = 'single';
+ });
+
+ it('should deselect a row', function() {
+ grid.selection.select(0);
+
+ grid.selection.deselect(0);
+
+ expect(grid.selectedRows).to.be.empty;
+ });
+
+ it('should not deselect other rows', function() {
+ grid.selection.select(0);
+
+ grid.selection.deselect(1);
+
+ expect(grid.selection.selected()).to.eql([0]);
+ });
+ });
+
+ describe('with selectionMode: multi', function() {
+ beforeEach(function() {
+ grid.selection.mode = 'multi';
+ });
+
+ it('should deselect a single row', function() {
+ grid.selection.select(0);
+ grid.selection.select(1);
+
+ grid.selection.deselect(0);
+
+ expect(grid.selection.selected()).to.eql([1]);
+ });
+ });
+ });
+
+ describe('selected indexes', function() {
+
+ describe('in mode: single', function() {
+ beforeEach(function() {
+ grid.selection.mode = 'single';
+ grid.selection.select(0);
+ });
+
+ it('should have a right size', function() {
+ expect(grid.selection.size).to.eql(1);
+ });
+
+ it('should have right deselections', function() {
+ expect(grid.selection.deselected()).to.be.empty;
+ });
+
+ it('should have right selections', function() {
+ expect(grid.selection.selected()).to.eql([0]);
+ });
+
+ it('should iterate right selections', function() {
+ var spy = sinon.spy();
+ grid.selection.selected(spy);
+ expect(spy.calledOnce).to.be.true;
+ });
+
+ it('should return right mapped value', function() {
+ var mapper = function(index){
+ return "foo " + index;
+ };
+ expect(grid.selection.selected(mapper)).to.eql(["foo 0"]);
+ });
+
+ it('should return nothing with iterator', function() {
+ var iterator = function(i){
+ // Itearate
+ };
+ expect(grid.selection.selected(iterator)).to.be.empty;
+ });
+
+ it('clear should work right', function() {
+ grid.selection.clear();
+ expect(grid.selection.selected()).to.be.empty;
+ });
+
+ it('selectAll should work right', function() {
+ grid.selection.selectAll();
+ expect(grid.selection.selected()).to.be.empty;
+ });
+ });
+
+ describe('in mode: multi', function() {
+ beforeEach(function() {
+ grid.data.source = function(req) {
+ var data = [];
+ for (var i = req.index; i < req.index + req.count; i++) {
+ data.push(["foo " + i, "bar " + i]);
+ }
+ req.success(data, 100);
+ };
+ grid.selection.mode = 'multi';
+ grid.selection.select(0);
+ grid.selection.select(1);
+ grid.selection.select(80);
+ grid.selection.select(81);
+ });
+
+ it('should have a right size', function() {
+ expect(grid.selection.size).to.eql(4);
+ });
+
+ it('should have right deselections', function() {
+ expect(grid.selection.deselected()).to.be.empty;
+ });
+
+ it('should have right selections', function() {
+ expect(grid.selection.selected()).to.eql([0,1,80,81]);
+ });
+
+ it('should iterate right selections', function() {
+ var spy = sinon.spy();
+ grid.selection.selected(spy);
+ expect(spy.callCount).to.eql(4);
+ });
+
+ it('should return right mapped value', function() {
+ var mapper = function(index){
+ return "foo " + index;
+ };
+ expect(grid.selection.selected(mapper)).to.eql(["foo 0", "foo 1", "foo 80", "foo 81"]);
+ });
+
+ it('should return nothing with iterator', function() {
+ var iterator = function(i){
+ // Itearate
+ };
+ expect(grid.selection.selected(iterator)).to.be.empty;
+ });
+
+ it('should return tail', function() {
+ expect(grid.selection.selected(undefined, 3)).to.eql([81]);
+ });
+
+ it('should return head', function() {
+ expect(grid.selection.selected(undefined, undefined, 1)).to.eql([0, 1]);
+ });
+
+ it('should return range', function() {
+ expect(grid.selection.selected(undefined, 1, 2)).to.eql([1, 80]);
+ });
+
+ it('clear should work right', function() {
+ grid.selection.clear();
+ expect(grid.selection.selected()).to.be.empty;
+ });
+
+ it('selectAll should work right', function() {
+ grid.selection.selectAll();
+ expect(grid.selection.mode).to.eql("all");
+ });
+
+ });
+
+ describe('in mode: all', function() {
+ beforeEach(function() {
+ grid.data.source = function(req) {
+ var data = [];
+ for (var i = req.index; i < req.index + req.count; i++) {
+ data.push(["foo " + i, "bar " + i]);
+ }
+ req.success(data, 100);
+ };
+ grid.selection.mode = 'all';
+ grid.selection.deselect(0);
+ grid.selection.deselect(1);
+ grid.selection.deselect(80);
+ grid.selection.deselect(81);
+ });
+
+ it('should have a right size', function() {
+ expect(grid.selection.size).to.eql(96);
+ });
+
+ it('should have right deselections', function() {
+ expect(grid.selection.deselected()).to.eql([0,1,80,81]);
+ });
+
+ it('should have right selections', function() {
+ expect(grid.selection.selected()).to.have.length(96);
+ });
+
+ it('should iterate right selections', function() {
+ var spy = sinon.spy();
+ grid.selection.selected(spy);
+ expect(spy.callCount).to.eql(96);
+ });
+
+ it('should return right mapped value', function() {
+ var mapper = function(index){
+ return "foo " + index;
+ };
+ expect(grid.selection.selected(mapper)).to.contain("foo 2");
+ expect(grid.selection.deselected(mapper)).to.eql(["foo 0", "foo 1", "foo 80", "foo 81"]);
+ });
+
+ it('should return nothing with iterator', function() {
+ var iterator = function(i){
+ // Itearate
+ };
+ expect(grid.selection.selected(iterator)).to.be.empty;
+ expect(grid.selection.deselected(iterator)).to.be.empty;
+ });
+
+ it('should return tail', function() {
+ expect(grid.selection.selected(undefined, 50)).to.have.length(46);
+ expect(grid.selection.deselected(undefined, 3)).to.eql([81]);
+ });
+
+ it('should return head', function() {
+ expect(grid.selection.selected(undefined, undefined, 30)).to.have.length(31);
+ expect(grid.selection.deselected(undefined, undefined, 1)).to.eql([0, 1]);
+ });
+
+ it('should not contain deselected values', function() {
+ expect(grid.selection.selected()).not.to.contain(0);
+ expect(grid.selection.selected()).not.to.contain(80);
+ });
+
+ it('should return range', function() {
+ expect(grid.selection.selected(undefined, 1, 2)).to.eql([3, 4]);
+ expect(grid.selection.deselected(undefined, 1, 2)).to.eql([1, 80]);
+ });
+
+ it('clear should work right', function() {
+ grid.selection.clear();
+ expect(grid.selection.mode).to.eql("multi");
+ });
+
+ it('selectAll should work right', function() {
+ grid.selection.selectAll();
+ expect(grid.selection.deselected()).to.be.empty;
+ });
+
+ });
+
+ describe('in mode: disabled', function() {
+ beforeEach(function() {
+ grid.selection.mode = 'disabled';
+ grid.selection.select(0);
+ });
+
+ it('should have a right size', function() {
+ expect(grid.selection.size).to.eql(0);
+ });
+
+ it('should have right deselections', function() {
+ expect(grid.selection.deselected()).to.eql([]);
+ });
+
+ it('should have right selections', function() {
+ expect(grid.selection.selected()).to.eql([]);
+ });
+
+ it('should iterate right selections', function() {
+ var spy = sinon.spy();
+ grid.selection.selected(spy);
+ expect(spy.callCount).to.eql(0);
+ });
+
+ it('should return right mapped value', function() {
+ var mapper = function(index){
+ return "foo " + index;
+ };
+ expect(grid.selection.selected(mapper)).to.eql([]);
+ expect(grid.selection.deselected(mapper)).to.eql([]);
+ });
+
+ it('selectAll should work right', function() {
+ grid.selection.selectAll();
+ expect(grid.selection.selected()).to.eql([]);
+ });
+
+ });
+
+ });
+
+
+ });
+ </script>
+</body>
+
+</html>
diff --git a/vaadin-grid/test/grid-sorting-rows.html b/vaadin-grid/test/grid-sorting-rows.html
new file mode 100644
index 0000000..59acbbf
--- /dev/null
+++ b/vaadin-grid/test/grid-sorting-rows.html
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<html>
+
+<head lang="en">
+ <meta charset="UTF-8">
+ <title></title>
+
+ <script src="../../webcomponentsjs/webcomponents-lite.min.js"></script>
+ <script src="../../web-component-tester/browser.js"></script>
+ <script src="common.js"></script>
+
+ <link rel="import" href="../vaadin-grid.html">
+</head>
+
+<body>
+
+ <div id="gridwrapper"></div>
+
+ <script>
+ describe.feature('sorting rows', function() {
+
+ describe('using api', function() {
+
+ function assignInvalidSortOrder() {
+ grid.data.sortOrder = [{
+ column: 0,
+ direction: "ascending" // Should be asc or desc
+ }];
+ }
+
+ beforeEach(function() {
+ grid.columns[0].sortable = true;
+ grid.columns[1].sortable = true;
+ });
+
+ it('should set sortOrder property', function() {
+ grid.data.sortOrder = [{
+ column: 0,
+ direction: "desc"
+ }];
+
+ expect(qLocal(".v-grid-header th").classList.contains("sort-desc")).to.be.true;
+ });
+
+ it('should clear sort order', function() {
+ grid.data.sortOrder = [{
+ column: 0,
+ direction: "desc"
+ }];
+ grid.data.sortOrder = [];
+ expect(grid.data.sortOrder).to.be.empty;
+ });
+
+ it('should preserve existing sort order on invalid value', function() {
+ grid.data.sortOrder = [{
+ column: 0,
+ direction: "desc"
+ }];
+ expect(assignInvalidSortOrder).to.throw("Invalid sort direction");
+ expect(qLocal(".v-grid-header th").classList.contains("sort-desc")).to.be.true;
+ });
+
+ it('should be able to sort with multiple columns', function() {
+ grid.data.sortOrder = [{
+ column: 0,
+ direction: "desc"
+ }, {
+ column: 1
+ }];
+ assert.lengthOf(grid.data.sortOrder, 2);
+ expect(qaLocal(".v-grid-header th")[0].classList.contains("sort-desc")).to.be.true;
+ expect(qaLocal(".v-grid-header th")[1].classList.contains("sort-asc")).to.be.true;
+ });
+
+ it('should reset selection', function() {
+ grid.selectedRows = [0];
+
+ grid.data.sortOrder = [{
+ column: 0,
+ direction: "desc"
+ }];
+
+ expect(grid.selection.selected()).to.be.empty;
+ });
+
+ it('should ignore selection column from index', function() {
+ var firstNonFrozenHeaderCell = qLocal.bind(this, ".v-grid-header .v-grid-cell:not(.frozen)");
+
+ firstNonFrozenHeaderCell().click();
+ expect(grid.data.sortOrder[0].column).to.eql(0);
+
+ grid.selection.mode = "multi";
+ firstNonFrozenHeaderCell().click();
+ expect(grid.data.sortOrder[0].column).to.eql(0);
+ });
+
+
+ });
+ });
+ </script>
diff --git a/vaadin-grid/test/grid-static-sections.html b/vaadin-grid/test/grid-static-sections.html
new file mode 100644
index 0000000..757e8d2
--- /dev/null
+++ b/vaadin-grid/test/grid-static-sections.html
@@ -0,0 +1,222 @@
+<!DOCTYPE html>
+<html>
+<head lang="en">
+ <meta charset="UTF-8">
+ <title></title>
+ <script src="../../webcomponentsjs/webcomponents-lite.min.js"></script>
+ <script src="../../web-component-tester/browser.js"></script>
+
+ <script src="common.js"></script>
+
+ <link rel="import" href="../vaadin-grid.html">
+</head>
+<body>
+ <div id="gridwrapper"></div>
+
+ <script>
+ describe.feature('static sections', function() {
+ function removeHeaders() {
+ for(var i = grid.header.rowCount;i>0;i--) {
+ grid.header.removeRow();
+ }
+ }
+
+ function removeFooters() {
+ for(var i = grid.footer.rowCount;i>0;i--) {
+ grid.footer.removeRow();
+ }
+ }
+
+ beforeEach(function() {
+ removeHeaders();
+ removeFooters();
+
+ grid.header.addRow(0, ['Name', 'Value']);
+ grid.footer.addRow(0, ['Name', 'Value']);
+
+ grid.header.hidden = false;
+ grid.footer.hidden = false;
+
+ return grid;
+ });
+
+ describe('header.defaultRow', function() {
+ it('should be 0 by default', function() {
+ expect(grid.header.defaultRow).to.equal(0);
+ });
+
+ it('should fail when set to a nonexisting row', function() {
+ expect(function() {
+ grid.header.defaultRow = 1;
+ }).to.throw('Row with index 1 does not exist');
+ });
+
+ it('should set the defaultRow', function() {
+ grid.header.addRow();
+
+ // sorting indicator moves to the default row, so we'll
+ // use that to assert that default row has changed.
+ grid.columns[0].sortable = true;
+ grid.data.sortOrder = [{column: 0, direction: 'asc'}];
+
+ grid.header.defaultRow = 1;
+
+ var cells = qaLocal('.v-grid-header .v-grid-cell');
+ expect(cells[2].classList.toString()).to.contain('sort-asc');
+ });
+
+ it('should have content in sync with column.headerContent', function() {
+ var column = grid.columns[0];
+ var headerCell = grid.header.getCell(grid.header.defaultRow, 0);
+
+ column.headerContent = "foo";
+ expect(headerCell.content).to.eql("foo");
+
+ headerCell.content = "bar";
+ expect(column.headerContent).to.eql("bar");
+ });
+
+ });
+
+ ['header', 'footer'].forEach(function(section) {
+ describe(section, function() {
+ it('should be readonly', function() {
+ var originalValue = grid[section];
+
+ grid[section] = undefined;
+
+ expect(grid[section]).to.equal(originalValue);
+ });
+
+ describe('getCell', function() {
+ it('should return correct cell using indeces', function() {
+ var cell = grid[section].getCell(0,0);
+
+ expect(cell.content).to.equal('Name');
+ });
+
+ it('should return correct cell using identifier', function() {
+ grid.columns[0].name = 'foo';
+
+ var cell = grid[section].getCell(0, 'foo');
+
+ expect(cell.content).to.equal('Name');
+ });
+
+ it('should return correct cell from appended row', function() {
+ grid[section].addRow(1, [section + 'foo']);
+
+ var cell = grid[section].getCell(1, 0);
+
+ expect(cell.content).to.equal(section + 'foo');
+ });
+ });
+
+ describe('cell', function() {
+ describe('content', function() {
+ it('should set content', function() {
+ var cell = grid[section].getCell(0,0);
+ cell.content = 'foo';
+
+ expect(grid[section].getCell(0,0).content).to.equal('foo');
+ });
+
+ it('should set html content', function() {
+ var cell = grid[section].getCell(0, 0);
+
+ var input = document.createElement('input');
+ cell.content = input;
+
+ expect(qLocal('.v-grid-' + section + ' .v-grid-cell > input')).to.not.be.undefined;
+ });
+ });
+
+ describe('hidden', function() {
+ it('should clear innerHTML', function() {
+ grid[section].hidden = true;
+
+ expect(qLocal('.v-grid-' + section).innerHTML).to.be.empty;
+ });
+ });
+
+ describe('colspan', function() {
+ it('should hide spanned cells', function() {
+ var cell = grid[section].getCell(0, 0);
+
+ cell.colspan = 2;
+
+ return grid.then(function() {
+ expect(qaLocal(".v-grid-" + section + " .v-grid-cell")[1].style.display).to.equal('none');
+ });
+ });
+ });
+ });
+
+ describe('addRow', function() {
+ it('should append new row', function() {
+ grid[section].addRow();
+
+ grid[section].getCell(1,0).content = 'foo';
+ grid[section].getCell(1,1).content = 'bar';
+
+ var cells = qaLocal('.v-grid-' + section + ' .v-grid-cell');
+ expect(cells[0].innerHTML).to.equal('Name');
+ expect(cells[1].innerHTML).to.equal('Value');
+ expect(cells[2].innerHTML).to.equal('foo');
+ expect(cells[3].innerHTML).to.equal('bar');
+ });
+
+ it('should insert new row to correct index', function() {
+ grid[section].addRow(0);
+
+ grid[section].getCell(0,0).content = 'foo';
+ grid[section].getCell(0,1).content = 'bar';
+
+ var cells = qaLocal('.v-grid-' + section + ' .v-grid-cell');
+ expect(cells[0].innerHTML).to.equal('foo');
+ expect(cells[1].innerHTML).to.equal('bar');
+ expect(cells[2].innerHTML).to.equal('Name');
+ expect(cells[3].innerHTML).to.equal('Value');
+ });
+
+ it('should insert content to a new row', function() {
+ grid[section].addRow(0, ['foo', 'bar']);
+
+ var cells = qaLocal(".v-grid-" + section + " .v-grid-cell");
+ expect(cells[0].innerHTML).to.equal('foo');
+ expect(cells[1].innerHTML).to.equal('bar');
+ });
+ });
+
+ describe('removeRow', function() {
+ it('should remove first row', function() {
+ grid[section].removeRow();
+
+ expect(qaLocal('.v-grid-' + section + ' .v-grid-cell')).to.be.empty;
+ });
+
+ it('should remove a specific row', function() {
+ grid[section].addRow(0, ['foo', 'bar']);
+
+ grid[section].removeRow(1);
+
+ expect(qaLocal('.v-grid-' + section + ' .v-grid-cell')).to.have.length(2);
+ });
+ });
+
+ describe('setRowClassName', function() {
+ it('should set the classname of a specific row', function() {
+ grid[section].addRow();
+
+ grid[section].setRowClassName(1, 'second');
+
+ var rows = qaLocal(".v-grid-" + section + " .v-grid-row");
+ expect(rows[1].classList.toString()).to.contain('second');
+ });
+ });
+ });
+ });
+ });
+ </script>
+</body>
+</html> \ No newline at end of file
diff --git a/vaadin-grid/test/index.html b/vaadin-grid/test/index.html
new file mode 100644
index 0000000..e9bd2fc
--- /dev/null
+++ b/vaadin-grid/test/index.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <script src="../../webcomponentsjs/webcomponents.min.js"></script>
+ <script src="../../web-component-tester/browser.js"></script>
+</head>
+<body>
+<script>
+WCT.loadSuites([
+ 'grid-binding-data.html',
+ 'grid-editing-columns.html',
+ 'grid-editor-handler.html',
+ 'grid-properties.html',
+ 'grid-redrawer.html',
+// 'grid-rendering-light-dom.html',
+ 'grid-scrolling-rows.html',
+ 'grid-selecting-rows.html',
+ 'grid-static-sections.html',
+ 'grid-sorting-rows.html'
+]);
+</script>
+</body>
+</html>