/* * Copyright 2000-2016 Vaadin Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.vaadin.tests.server.component.grid; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.List; import java.util.Locale; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.parser.Tag; import org.jsoup.select.Elements; import org.jsoup.select.Selector; import org.junit.Assert; import org.junit.Test; import com.vaadin.data.SelectionModel.Multi; import com.vaadin.data.SelectionModel.Single; import com.vaadin.data.provider.DataProvider; import com.vaadin.data.provider.Query; import com.vaadin.shared.ui.ContentMode; import com.vaadin.shared.ui.grid.HeightMode; import com.vaadin.tests.data.bean.Address; import com.vaadin.tests.data.bean.Country; import com.vaadin.tests.data.bean.Person; import com.vaadin.tests.data.bean.Sex; import com.vaadin.tests.server.component.abstractlisting.AbstractListingDeclarativeTest; import com.vaadin.ui.Grid; import com.vaadin.ui.Grid.Column; import com.vaadin.ui.Grid.SelectionMode; import com.vaadin.ui.Label; import com.vaadin.ui.TextField; import com.vaadin.ui.components.grid.FooterCell; import com.vaadin.ui.components.grid.FooterRow; import com.vaadin.ui.components.grid.HeaderCell; import com.vaadin.ui.components.grid.HeaderRow; import com.vaadin.ui.declarative.DesignContext; import com.vaadin.ui.declarative.DesignException; /** * @author Vaadin Ltd * */ public class GridDeclarativeTest extends AbstractListingDeclarativeTest<Grid> { @Test public void gridAttributes() { Grid<Person> grid = new Grid<>(); int frozenColumns = 1; HeightMode heightMode = HeightMode.ROW; double heightByRows = 13.7d; grid.addColumn(Person::getFirstName).setCaption("First Name"); grid.addColumn(Person::getLastName).setId("id").setCaption("Id"); grid.setFrozenColumnCount(frozenColumns); grid.setSelectionMode(SelectionMode.MULTI); grid.setHeightMode(heightMode); grid.setHeightByRows(heightByRows); String design = String.format( "<%s height-mode='%s' frozen-columns='%d' rows='%s' selection-mode='%s'><table><colgroup>" + "<col column-id='column0' sortable>" + "<col column-id='id' sortable>" + "</colgroup><thead>" + "<tr default><th plain-text column-ids='column0'>First Name</th>" + "<th plain-text column-ids='id'>Id</th></tr>" + "</thead></table></%s>", getComponentTag(), heightMode.toString().toLowerCase(Locale.ENGLISH), frozenColumns, heightByRows, SelectionMode.MULTI.toString().toLowerCase(Locale.ENGLISH), getComponentTag()); testRead(design, grid); testWrite(design, grid); } @Test public void mergedHeaderCells() { Grid<Person> grid = new Grid<>(); Column<Person, String> column1 = grid.addColumn(Person::getFirstName) .setCaption("First Name"); Column<Person, String> column2 = grid.addColumn(Person::getLastName) .setId("id").setCaption("Id"); Column<Person, String> column3 = grid.addColumn(Person::getEmail) .setId("mail").setCaption("Mail"); HeaderRow header = grid.addHeaderRowAt(1); String headerRowText1 = "foo"; header.getCell(column1).setText(headerRowText1); HeaderCell cell2 = header.getCell(column2); HeaderCell join = header.join(cell2, header.getCell(column3)); String headerRowText3 = "foobar"; join.setText(headerRowText3); String design = String.format( "<%s><table><colgroup>" + "<col column-id='column0' sortable>" + "<col column-id='id' sortable>" + "<col column-id='mail' sortable>" + "</colgroup><thead>" + "<tr default><th plain-text column-ids='column0'>First Name</th>" + "<th plain-text column-ids='id'>Id</th>" + "<th plain-text column-ids='mail'>Mail</th></tr>" + "<tr><th plain-text column-ids='column0'>%s</th>" + "<th colspan='2' plain-text column-ids='id,mail'>foobar</th></tr>" + "</thead></table></%s>", getComponentTag(), headerRowText1, headerRowText3, getComponentTag()); testRead(design, grid); testWrite(design, grid); } @Test public void mergedFooterCells() { Grid<Person> grid = new Grid<>(); Column<Person, String> column1 = grid.addColumn(Person::getFirstName) .setCaption("First Name"); Column<Person, String> column2 = grid.addColumn(Person::getLastName) .setId("id").setCaption("Id"); Column<Person, String> column3 = grid.addColumn(Person::getEmail) .setId("mail").setCaption("Mail"); FooterRow footer = grid.addFooterRowAt(0); FooterCell cell1 = footer.getCell(column1); String footerRowText1 = "foo"; cell1.setText(footerRowText1); FooterCell cell2 = footer.getCell(column2); FooterCell cell3 = footer.getCell(column3); String footerRowText2 = "foobar"; footer.join(cell2, cell3).setHtml(footerRowText2); String design = String.format( "<%s><table><colgroup>" + "<col column-id='column0' sortable>" + "<col column-id='id' sortable>" + "<col column-id='mail' sortable>" + "</colgroup><thead>" + "<tr default><th plain-text column-ids='column0'>First Name</th>" + "<th plain-text column-ids='id'>Id</th>" + "<th plain-text column-ids='mail'>Mail</th></tr></thead>" + "<tfoot><tr><td plain-text column-ids='column0'>%s</td>" + "<td colspan='2' column-ids='id,mail'>%s</td></tr></tfoot>" + "</table></%s>", getComponentTag(), footerRowText1, footerRowText2, getComponentTag()); testRead(design, grid); testWrite(design, grid); } @Test public void columnAttributes() { Grid<Person> grid = new Grid<>(); String secondColumnId = "id"; Column<Person, String> column1 = grid.addColumn(Person::getFirstName) .setCaption("First Name"); Column<Person, String> column2 = grid.addColumn(Person::getLastName) .setId(secondColumnId).setCaption("Id"); String caption = "test-caption"; column1.setCaption(caption); boolean sortable = false; column1.setSortable(sortable); boolean editable = true; column1.setEditorComponent(new TextField(), Person::setLastName); column1.setEditable(editable); boolean resizable = false; column1.setResizable(resizable); boolean hidable = true; column1.setHidable(hidable); boolean hidden = true; column1.setHidden(hidden); String hidingToggleCaption = "toggle-caption"; column2.setHidingToggleCaption(hidingToggleCaption); double width = 17.3; column2.setWidth(width); double minWidth = 37.3; column2.setMinimumWidth(minWidth); double maxWidth = 63.4; column2.setMaximumWidth(maxWidth); int expandRatio = 83; column2.setExpandRatio(expandRatio); String design = String.format( "<%s><table><colgroup>" + "<col column-id='column0' sortable='%s' editable resizable='%s' hidable hidden>" + "<col column-id='id' sortable hiding-toggle-caption='%s' width='%s' min-width='%s' max-width='%s' expand='%s'>" + "</colgroup><thead>" + "<tr default><th plain-text column-ids='column0'>%s</th>" + "<th plain-text column-ids='id'>%s</th>" + "</tr></thead>" + "</table></%s>", getComponentTag(), sortable, resizable, hidingToggleCaption, width, minWidth, maxWidth, expandRatio, caption, "Id", getComponentTag()); testRead(design, grid, true); testWrite(design, grid); } @Test public void headerFooterSerialization() { Grid<Person> grid = new Grid<>(); Column<Person, String> column1 = grid.addColumn(Person::getFirstName) .setCaption("First Name"); Column<Person, String> column2 = grid.addColumn(Person::getLastName) .setId("id").setCaption("Id"); FooterRow footerRow = grid.addFooterRowAt(0); footerRow.getCell(column1).setText("x"); footerRow.getCell(column2).setHtml("y"); String design = String.format( "<%s><table><colgroup>" + "<col column-id='column0' sortable>" + "<col column-id='id' sortable></colgroup><thead>" + "<tr default><th plain-text column-ids='column0'>First Name</th>" + "<th plain-text column-ids='id'>Id</th></tr>" + "</thead><tbody></tbody>" + "<tfoot><tr><td plain-text column-ids='column0'>x</td>" + "<td column-ids='id'>y</td></tr></tfoot>" + "</table></%s>", getComponentTag(), getComponentTag()); testRead(design, grid); testWrite(design, grid, true); } @Override public void dataSerialization() throws InstantiationException, IllegalAccessException, InvocationTargetException { Grid<Person> grid = new Grid<>(); Person person1 = createPerson("foo", "bar"); Person person2 = createPerson("name", "last-name"); grid.setItems(person1, person2); grid.addColumn(Person::getFirstName).setCaption("First Name"); grid.addColumn(Person::getLastName).setId("id").setCaption("Id"); String design = String.format( "<%s><table><colgroup>" + "<col column-id='column0' sortable>" + "<col column-id='id' sortable></colgroup><thead>" + "<tr default><th plain-text column-ids='column0'>First Name</th>" + "<th plain-text column-ids='id'>Id</th></tr>" + "</thead><tbody>" + "<tr item='%s'><td>%s</td><td>%s</td></tr>" + "<tr item='%s'><td>%s</td><td>%s</td></tr>" + "</tbody></table></%s>", getComponentTag(), person1.toString(), person1.getFirstName(), person1.getLastName(), person2.toString(), person2.getFirstName(), person2.getLastName(), getComponentTag()); Grid<?> readGrid = testRead(design, grid, true, true); Assert.assertEquals(2, readGrid.getDataProvider().size(new Query<>())); testWrite(design, grid, true); } /** * Value for single select */ @Override @Test public void valueSerialization() throws InstantiationException, IllegalAccessException, InvocationTargetException { valueSingleSelectSerialization(); } @SuppressWarnings("unchecked") @Test public void valueMultiSelectSerialization() throws InstantiationException, IllegalAccessException, InvocationTargetException { Grid<Person> grid = new Grid<>(); Person person1 = createPerson("foo", "bar"); Person person2 = createPerson("name", "last-name"); Person person3 = createPerson("foo", "last-name"); grid.setItems(person1, person2, person3); grid.addColumn(Person::getFirstName).setCaption("First Name"); grid.addColumn(Person::getLastName).setId("id").setCaption("Id"); Multi<Person> model = (Multi<Person>) grid .setSelectionMode(SelectionMode.MULTI); model.selectItems(person1, person3); String design = String.format( "<%s selection-mode='multi'><table><colgroup>" + "<col column-id='column0' sortable>" + "<col column-id='id' sortable></colgroup><thead>" + "<tr default><th plain-text column-ids='column0'>First Name</th>" + "<th plain-text column-ids='id'>Id</th></tr>" + "</thead><tbody>" + "<tr item='%s' selected><td>%s</td><td>%s</td></tr>" + "<tr item='%s'><td>%s</td><td>%s</td></tr>" + "<tr item='%s' selected><td>%s</td><td>%s</td></tr>" + "</tbody></table></%s>", getComponentTag(), person1.toString(), person1.getFirstName(), person1.getLastName(), person2.toString(), person2.getFirstName(), person2.getLastName(), person3.toString(), person3.getFirstName(), person3.getLastName(), getComponentTag()); Grid<?> readGrid = testRead(design, grid, true, true); Assert.assertEquals(3, readGrid.getDataProvider().size(new Query<>())); testWrite(design, grid, true); } @SuppressWarnings("unchecked") private void valueSingleSelectSerialization() throws InstantiationException, IllegalAccessException, InvocationTargetException { Grid<Person> grid = new Grid<>(); Person person1 = createPerson("foo", "bar"); Person person2 = createPerson("name", "last-name"); grid.setItems(person1, person2); grid.addColumn(Person::getFirstName).setCaption("First Name"); grid.addColumn(Person::getLastName).setId("id").setCaption("Id"); Single<Person> model = (Single<Person>) grid .setSelectionMode(SelectionMode.SINGLE); model.select(person2); String design = String.format( "<%s><table><colgroup>" + "<col column-id='column0' sortable>" + "<col column-id='id' sortable></colgroup><thead>" + "<tr default><th plain-text column-ids='column0'>First Name</th>" + "<th plain-text column-ids='id'>Id</th></tr>" + "</thead><tbody>" + "<tr item='%s'><td>%s</td><td>%s</td></tr>" + "<tr item='%s' selected><td>%s</td><td>%s</td></tr>" + "</tbody></table></%s>", getComponentTag(), person1.toString(), person1.getFirstName(), person1.getLastName(), person2.toString(), person2.getFirstName(), person2.getLastName(), getComponentTag()); Grid<?> readGrid = testRead(design, grid, true, true); Assert.assertEquals(2, readGrid.getDataProvider().size(new Query<>())); testWrite(design, grid, true); } @Override public void readOnlySelection() throws InstantiationException, IllegalAccessException, InvocationTargetException { Grid<Person> grid = new Grid<>(); Person person1 = createPerson("foo", "bar"); Person person2 = createPerson("name", "last-name"); grid.setItems(person1, person2); grid.addColumn(Person::getFirstName).setCaption("First Name"); grid.addColumn(Person::getLastName).setId("id").setCaption("Id"); grid.setSelectionMode(SelectionMode.MULTI); grid.asMultiSelect().setReadOnly(true); String formatString = "<%s %s selection-allowed><table><colgroup>" + "<col column-id='column0' sortable>" + "<col column-id='id' sortable>" + "</colgroup><thead>" + "<tr default><th plain-text column-ids='column0'>First Name</th>" + "<th plain-text column-ids='id'>Id</th></tr>" + "</thead><tbody>" + "<tr item='%s'><td>%s</td><td>%s</td></tr>" + "<tr item='%s'><td>%s</td><td>%s</td></tr>" + "</tbody></table></%s>"; String design = String.format(formatString, getComponentTag(), "selection-mode='multi'", person1.toString(), person1.getFirstName(), person1.getLastName(), person2.toString(), person2.getFirstName(), person2.getLastName(), getComponentTag()); Grid<?> readGrid = testRead(design, grid, true, true); Assert.assertEquals(2, readGrid.getDataProvider().size(new Query<>())); testWrite(design, grid, true); grid.setSelectionMode(SelectionMode.SINGLE); grid.asSingleSelect().setReadOnly(true); design = String.format(formatString, getComponentTag(), "", person1.toString(), person1.getFirstName(), person1.getLastName(), person2.toString(), person2.getFirstName(), person2.getLastName(), getComponentTag()); readGrid = testRead(design, grid, true, true); Assert.assertEquals(2, readGrid.getDataProvider().size(new Query<>())); testWrite(design, grid, true); } @Test public void testComponentInGridHeader() { Grid<Person> grid = new Grid<>(); Column<Person, String> column = grid.addColumn(Person::getFirstName) .setCaption("First Name"); String html = "<b>Foo</b>"; Label component = new Label(html); component.setContentMode(ContentMode.HTML); //@formatter:off String design = String.format( "<%s><table>" + "<colgroup>" + " <col sortable column-id='column0'>" + "</colgroup>" + "<thead>" + "<tr default><th column-ids='column0'><vaadin-label>%s</vaadin-label></th></tr>" + "</thead>" + "</table></%s>", getComponentTag(), html, getComponentTag()); //@formatter:on grid.getDefaultHeaderRow().getCell(column).setComponent(component); testRead(design, grid, true); testWrite(design, grid); } @Test public void testComponentInGridFooter() { Grid<Person> grid = new Grid<>(); Column<Person, String> column = grid.addColumn(Person::getFirstName) .setCaption("First Name"); String html = "<b>Foo</b>"; Label component = new Label(html); component.setContentMode(ContentMode.HTML); grid.prependFooterRow().getCell(column).setComponent(component); grid.removeHeaderRow(grid.getDefaultHeaderRow()); //@formatter:off String design = String.format( "<%s><table>" + "<colgroup>" + " <col sortable column-id='column0'>" + "</colgroup>" + "<thead>" +"<tfoot>" + "<tr><td column-ids='column0'><vaadin-label>%s</vaadin-label></td></tr>" + "</tfoot>" + "</table>" + "</%s>", getComponentTag(), html, getComponentTag()); //@formatter:on testRead(design, grid, true); testWrite(design, grid); } @Test public void testNoHeaderRows() { //@formatter:off String design = "<vaadin-grid><table>" + "<colgroup>" + " <col sortable column-id='column0'>" + "</colgroup>" + "<thead />" + "</table>" + "</vaadin-grid>"; //@formatter:on Grid<Person> grid = new Grid<>(); grid.addColumn(Person::getFirstName).setCaption("First Name"); grid.removeHeaderRow(grid.getDefaultHeaderRow()); testWrite(design, grid); testRead(design, grid, true); } @Test public void testReadEmptyGrid() { String design = "<vaadin-grid />"; testRead(design, new Grid<String>(), false); } @Test public void testEmptyGrid() { String design = "<vaadin-grid></vaadin-grid>"; Grid<String> expected = new Grid<>(); testWrite(design, expected); testRead(design, expected, true); } @Test(expected = DesignException.class) public void testMalformedGrid() { String design = "<vaadin-grid><vaadin-label /></vaadin-grid>"; testRead(design, new Grid<String>()); } @Test(expected = DesignException.class) public void testGridWithNoColGroup() { String design = "<vaadin-grid><table><thead><tr><th>Foo</tr></thead></table></vaadin-grid>"; testRead(design, new Grid<String>()); } @Test @SuppressWarnings("unchecked") public void testHtmlEntitiesinGridHeaderFooter() { String id = "> id"; String plainText = "plain-text"; //@formatter:off String design = String.format( "<%s><table>" + "<colgroup>" + " <col sortable column-id='%s'>" + "</colgroup>" + "<thead>" +" <tr default><th %s column-ids='%s'>> Test</th>" + "</thead>" + "<tfoot>" + "<tr><td %s column-ids='%s'>> Test</td></tr>" + "</tfoot>" + "<tbody />" + "</table></%s>", getComponentTag() , id, plainText, id, plainText, id, getComponentTag()); //@formatter:on Grid<Person> grid = read(design); String actualHeader = grid.getHeaderRow(0).getCell(id).getText(); String actualFooter = grid.getFooterRow(0).getCell(id).getText(); String expected = "> Test"; Assert.assertEquals(expected, actualHeader); Assert.assertEquals(expected, actualFooter); design = design.replace(plainText, ""); grid = read(design); actualHeader = grid.getHeaderRow(0).getCell(id).getHtml(); actualFooter = grid.getFooterRow(0).getCell(id).getHtml(); expected = "> Test"; Assert.assertEquals(expected, actualHeader); Assert.assertEquals(expected, actualFooter); grid = new Grid<>(); Column<Person, String> column = grid.addColumn(Person::getFirstName) .setId(id); HeaderRow header = grid.addHeaderRowAt(0); FooterRow footer = grid.addFooterRowAt(0); grid.removeHeaderRow(grid.getDefaultHeaderRow()); // entities should be encoded when writing back, not interpreted as HTML header.getCell(column).setText("& Test"); footer.getCell(column).setText("& Test"); Element root = new Element(Tag.valueOf(getComponentTag()), ""); grid.writeDesign(root, new DesignContext()); Assert.assertEquals("&amp; Test", root.getElementsByTag("th").get(0).html()); Assert.assertEquals("&amp; Test", root.getElementsByTag("td").get(0).html()); header = grid.addHeaderRowAt(0); footer = grid.addFooterRowAt(0); // entities should not be encoded, this is already given as HTML header.getCell(id).setHtml("& Test"); footer.getCell(id).setHtml("& Test"); root = new Element(Tag.valueOf(getComponentTag()), ""); grid.writeDesign(root, new DesignContext()); Assert.assertEquals("& Test", root.getElementsByTag("th").get(0).html()); Assert.assertEquals("& Test", root.getElementsByTag("td").get(0).html()); } @SuppressWarnings("rawtypes") @Override public Grid<?> testRead(String design, Grid expected) { return testRead(design, expected, false); } @Override @SuppressWarnings("rawtypes") public Grid<?> testRead(String design, Grid expected, boolean retestWrite) { return testRead(design, expected, retestWrite, false); } @SuppressWarnings("rawtypes") public Grid<?> testRead(String design, Grid expected, boolean retestWrite, boolean writeData) { Grid<?> actual = super.testRead(design, expected); compareGridColumns(expected, actual); compareHeaders(expected, actual); compareFooters(expected, actual); if (retestWrite) { testWrite(design, actual, writeData); } return actual; } private void compareHeaders(Grid<?> expected, Grid<?> actual) { Assert.assertEquals("Different header row count", expected.getHeaderRowCount(), actual.getHeaderRowCount()); for (int i = 0; i < expected.getHeaderRowCount(); ++i) { HeaderRow expectedRow = expected.getHeaderRow(i); HeaderRow actualRow = actual.getHeaderRow(i); if (expectedRow.equals(expected.getDefaultHeaderRow())) { Assert.assertEquals("Different index for default header row", actual.getDefaultHeaderRow(), actualRow); } for (Column<?, ?> column : expected.getColumns()) { String baseError = "Difference when comparing cell for " + column.toString() + " on header row " + i + ": "; HeaderCell expectedCell = expectedRow.getCell(column); HeaderCell actualCell = actualRow.getCell(column); switch (expectedCell.getCellType()) { case TEXT: Assert.assertEquals(baseError + "Text content", expectedCell.getText(), actualCell.getText()); break; case HTML: Assert.assertEquals(baseError + "HTML content", expectedCell.getHtml(), actualCell.getHtml()); break; case WIDGET: assertEquals(baseError + "Component content", expectedCell.getComponent(), actualCell.getComponent()); break; } } } } private void compareFooters(Grid<?> expected, Grid<?> actual) { Assert.assertEquals("Different footer row count", expected.getFooterRowCount(), actual.getFooterRowCount()); for (int i = 0; i < expected.getFooterRowCount(); ++i) { FooterRow expectedRow = expected.getFooterRow(i); FooterRow actualRow = actual.getFooterRow(i); for (Column<?, ?> column : expected.getColumns()) { String baseError = "Difference when comparing cell for " + column.toString() + " on footer row " + i + ": "; FooterCell expectedCell = expectedRow.getCell(column); FooterCell actualCell = actualRow.getCell(column); switch (expectedCell.getCellType()) { case TEXT: Assert.assertEquals(baseError + "Text content", expectedCell.getText(), actualCell.getText()); break; case HTML: Assert.assertEquals(baseError + "HTML content", expectedCell.getHtml(), actualCell.getHtml()); break; case WIDGET: assertEquals(baseError + "Component content", expectedCell.getComponent(), actualCell.getComponent()); break; } } } } private void compareGridColumns(Grid<?> expected, Grid<?> actual) { List<?> columns = expected.getColumns(); List<?> actualColumns = actual.getColumns(); Assert.assertEquals("Different amount of columns", columns.size(), actualColumns.size()); for (int i = 0; i < columns.size(); ++i) { Column<?, ?> col1 = (Column<?, ?>) columns.get(i); Column<?, ?> col2 = (Column<?, ?>) actualColumns.get(i); String baseError = "Error when comparing columns for property " + col1.getId() + ": "; assertEquals(baseError + "Width", col1.getWidth(), col2.getWidth()); assertEquals(baseError + "Maximum width", col1.getMaximumWidth(), col2.getMaximumWidth()); assertEquals(baseError + "Minimum width", col1.getMinimumWidth(), col2.getMinimumWidth()); assertEquals(baseError + "Expand ratio", col1.getExpandRatio(), col2.getExpandRatio()); assertEquals(baseError + "Sortable", col1.isSortable(), col2.isSortable()); assertEquals(baseError + "Editable", col1.isEditable(), col2.isEditable()); assertEquals(baseError + "Hidable", col1.isHidable(), col2.isHidable()); assertEquals(baseError + "Hidden", col1.isHidden(), col2.isHidden()); assertEquals(baseError + "HidingToggleCaption", col1.getHidingToggleCaption(), col2.getHidingToggleCaption()); } } @Override protected String getComponentTag() { return "vaadin-grid"; } @Override protected Class<? extends Grid> getComponentClass() { return Grid.class; } @Override protected boolean acceptProperty(Class<?> clazz, Method readMethod, Method writeMethod) { if (readMethod != null) { Class<?> returnType = readMethod.getReturnType(); if (HeaderRow.class.equals(returnType) || DataProvider.class.equals(returnType)) { return false; } } return super.acceptProperty(clazz, readMethod, writeMethod); } private Person createPerson(String name, String lastName) { Person person = new Person() { @Override public String toString() { return getFirstName() + " " + getLastName(); } }; person.setFirstName(name); person.setLastName(lastName); return person; } @Test public void beanItemType() throws Exception { Class<Person> beanClass = Person.class; String beanClassName = beanClass.getName(); //@formatter:off String design = String.format( "<%s data-item-type=\"%s\"></%s>", getComponentTag() , beanClassName, getComponentTag()); //@formatter:on @SuppressWarnings("unchecked") Grid<Person> grid = read(design); Assert.assertEquals(beanClass, grid.getBeanType()); testWrite(design, grid); } @Test public void beanGridDefaultColumns() { Grid<Person> grid = new Grid<>(Person.class); String design = write(grid, false); assertDeclarativeColumnCount(11, design); Person testPerson = new Person("the first", "the last", "The email", 64, Sex.MALE, new Address("the street", 12313, "The city", Country.SOUTH_AFRICA)); @SuppressWarnings("unchecked") Grid<Person> readGrid = read(design); assertColumns(11, grid.getColumns(), readGrid.getColumns(), testPerson); } private void assertDeclarativeColumnCount(int i, String design) { Document html = Jsoup.parse(design); Elements cols = Selector.select("vaadin-grid", html) .select("colgroup > col"); Assert.assertEquals("Number of columns in the design file", i, cols.size()); } private void assertColumns(int expectedCount, List<Column<Person, ?>> expectedColumns, List<Column<Person, ?>> columns, Person testPerson) { Assert.assertEquals(expectedCount, expectedColumns.size()); Assert.assertEquals(expectedCount, columns.size()); for (int i = 0; i < expectedColumns.size(); i++) { Column<Person, ?> expectedColumn = expectedColumns.get(i); Column<Person, ?> column = columns.get(i); // Property mapping Assert.assertEquals(expectedColumn.getId(), column.getId()); // Header caption Assert.assertEquals(expectedColumn.getCaption(), column.getCaption()); // Value providers are not stored in the declarative file // so this only works for bean properties if (column.getId() != null && !column.getId().equals("column" + i)) { Assert.assertEquals( expectedColumn.getValueProvider().apply(testPerson), column.getValueProvider().apply(testPerson)); } } } @Test public void beanGridNoColumns() { Grid<Person> grid = new Grid<>(Person.class); grid.setColumns(); String design = write(grid, false); assertDeclarativeColumnCount(0, design); Person testPerson = new Person("the first", "the last", "The email", 64, Sex.MALE, new Address("the street", 12313, "The city", Country.SOUTH_AFRICA)); @SuppressWarnings("unchecked") Grid<Person> readGrid = read(design); assertColumns(0, grid.getColumns(), readGrid.getColumns(), testPerson); // Can add a mapped property Assert.assertEquals("The email", readGrid.addColumn("email") .getValueProvider().apply(testPerson)); } @Test public void beanGridOnlyCustomColumns() { // Writes columns without propertyId even though name matches, reads // columns without propertyId mapping, can add new columns using // propertyId Grid<Person> grid = new Grid<>(Person.class); grid.setColumns(); grid.addColumn(Person::getFirstName).setCaption("First Name"); String design = write(grid, false); assertDeclarativeColumnCount(1, design); Person testPerson = new Person("the first", "the last", "The email", 64, Sex.MALE, new Address("the street", 12313, "The city", Country.SOUTH_AFRICA)); @SuppressWarnings("unchecked") Grid<Person> readGrid = read(design); assertColumns(1, grid.getColumns(), readGrid.getColumns(), testPerson); // First name should not be mapped to the property Assert.assertNull(readGrid.getColumns().get(0).getValueProvider() .apply(testPerson)); // Can add a mapped property Assert.assertEquals("the last", readGrid.addColumn("lastName") .getValueProvider().apply(testPerson)); } @Test public void beanGridOneCustomizedColumn() { // Writes columns with propertyId except one without // Reads columns to match initial setup Grid<Person> grid = new Grid<>(Person.class); grid.addColumn( person -> person.getFirstName() + " " + person.getLastName()) .setCaption("First and Last"); String design = write(grid, false); assertDeclarativeColumnCount(12, design); Person testPerson = new Person("the first", "the last", "The email", 64, Sex.MALE, new Address("the street", 12313, "The city", Country.SOUTH_AFRICA)); @SuppressWarnings("unchecked") Grid<Person> readGrid = read(design); assertColumns(12, grid.getColumns(), readGrid.getColumns(), testPerson); // First and last name should not be mapped to anything but should exist Assert.assertNull(readGrid.getColumns().get(11).getValueProvider() .apply(testPerson)); } }