You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

GridTest.java 27KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830
  1. package com.vaadin.tests.server.component.grid;
  2. import static org.junit.Assert.assertArrayEquals;
  3. import static org.junit.Assert.assertEquals;
  4. import static org.junit.Assert.assertFalse;
  5. import static org.junit.Assert.assertNotNull;
  6. import static org.junit.Assert.assertSame;
  7. import static org.junit.Assert.assertTrue;
  8. import static org.junit.Assert.fail;
  9. import java.lang.reflect.InvocationTargetException;
  10. import java.lang.reflect.Method;
  11. import java.text.DecimalFormat;
  12. import java.text.DecimalFormatSymbols;
  13. import java.util.ArrayList;
  14. import java.util.Arrays;
  15. import java.util.Collections;
  16. import java.util.Date;
  17. import java.util.HashSet;
  18. import java.util.List;
  19. import java.util.Locale;
  20. import java.util.Optional;
  21. import java.util.Random;
  22. import java.util.Set;
  23. import java.util.concurrent.atomic.AtomicInteger;
  24. import java.util.concurrent.atomic.AtomicReference;
  25. import java.util.stream.Collectors;
  26. import java.util.stream.Stream;
  27. import org.easymock.Capture;
  28. import org.junit.Assert;
  29. import org.junit.Before;
  30. import org.junit.Rule;
  31. import org.junit.Test;
  32. import org.junit.rules.ExpectedException;
  33. import com.vaadin.data.Binder.Binding;
  34. import com.vaadin.data.ValidationException;
  35. import com.vaadin.data.ValueProvider;
  36. import com.vaadin.data.provider.DataCommunicator;
  37. import com.vaadin.data.provider.DataGenerator;
  38. import com.vaadin.data.provider.DataProvider;
  39. import com.vaadin.data.provider.GridSortOrder;
  40. import com.vaadin.data.provider.QuerySortOrder;
  41. import com.vaadin.data.provider.bov.Person;
  42. import com.vaadin.event.selection.SelectionEvent;
  43. import com.vaadin.server.SerializableComparator;
  44. import com.vaadin.shared.communication.SharedState;
  45. import com.vaadin.shared.data.sort.SortDirection;
  46. import com.vaadin.shared.ui.grid.GridState;
  47. import com.vaadin.shared.ui.grid.HeightMode;
  48. import com.vaadin.tests.util.MockUI;
  49. import com.vaadin.ui.Grid;
  50. import com.vaadin.ui.Grid.Column;
  51. import com.vaadin.ui.Grid.SelectionMode;
  52. import com.vaadin.ui.TextField;
  53. import com.vaadin.ui.renderers.NumberRenderer;
  54. import elemental.json.Json;
  55. import elemental.json.JsonObject;
  56. import junit.framework.AssertionFailedError;
  57. public class GridTest {
  58. private Grid<String> grid;
  59. private Column<String, String> fooColumn;
  60. private Column<String, Integer> lengthColumn;
  61. private Column<String, Object> objectColumn;
  62. private Column<String, String> randomColumn;
  63. private GridState state;
  64. @Rule
  65. public ExpectedException thrown = ExpectedException.none();
  66. @Before
  67. public void setUp() {
  68. grid = new Grid<String>() {
  69. {
  70. state = getState(false);
  71. }
  72. };
  73. fooColumn = grid.addColumn(ValueProvider.identity()).setId("foo");
  74. lengthColumn = grid.addColumn(String::length, new NumberRenderer())
  75. .setId("length");
  76. objectColumn = grid.addColumn(string -> new Object());
  77. randomColumn = grid.addColumn(ValueProvider.identity())
  78. .setId("randomColumnId");
  79. }
  80. @Test
  81. public void testGridAssistiveCaption() {
  82. assertEquals(null, fooColumn.getAssistiveCaption());
  83. fooColumn.setAssistiveCaption("Press Enter to sort.");
  84. assertEquals("Press Enter to sort.", fooColumn.getAssistiveCaption());
  85. }
  86. @Test
  87. public void testCreateGridWithDataCommunicator() {
  88. DataCommunicator<String> specificDataCommunicator = new DataCommunicator<>();
  89. TestGrid<String> grid = new TestGrid<>(String.class,
  90. specificDataCommunicator);
  91. assertEquals(specificDataCommunicator, grid.getDataCommunicator());
  92. }
  93. @Test
  94. public void testGridHeightModeChange() {
  95. assertEquals("Initial height mode was not CSS", HeightMode.CSS,
  96. grid.getHeightMode());
  97. grid.setHeightByRows(13.24);
  98. assertEquals("Setting height by rows did not change height mode",
  99. HeightMode.ROW, grid.getHeightMode());
  100. grid.setHeight("100px");
  101. assertEquals("Setting height did not change height mode.",
  102. HeightMode.CSS, grid.getHeightMode());
  103. }
  104. @Test
  105. public void testFrozenColumnCountTooBig() {
  106. thrown.expect(IllegalArgumentException.class);
  107. thrown.expectMessage(
  108. "count must be between -1 and the current number of columns (4): 5");
  109. grid.setFrozenColumnCount(5);
  110. }
  111. @Test
  112. public void testFrozenColumnCountTooSmall() {
  113. thrown.expect(IllegalArgumentException.class);
  114. thrown.expectMessage(
  115. "count must be between -1 and the current number of columns (4): -2");
  116. grid.setFrozenColumnCount(-2);
  117. }
  118. @Test
  119. public void testSetFrozenColumnCount() {
  120. for (int i = -1; i < 2; ++i) {
  121. grid.setFrozenColumnCount(i);
  122. assertEquals("Frozen column count not updated", i,
  123. grid.getFrozenColumnCount());
  124. }
  125. }
  126. @Test
  127. public void testGridColumnIdentifier() {
  128. grid.getColumn("foo").setCaption("Bar");
  129. assertEquals("Column header not updated correctly", "Bar",
  130. grid.getHeaderRow(0).getCell("foo").getText());
  131. }
  132. @Test
  133. public void testGridMultipleColumnsWithSameIdentifier() {
  134. thrown.expect(IllegalArgumentException.class);
  135. thrown.expectMessage("Duplicate ID for columns");
  136. grid.addColumn(t -> t).setId("foo");
  137. }
  138. @Test
  139. public void testAddSelectionListener_singleSelectMode() {
  140. grid.setItems("foo", "bar", "baz");
  141. Capture<SelectionEvent<String>> eventCapture = new Capture<>();
  142. grid.addSelectionListener(event -> eventCapture.setValue(event));
  143. grid.getSelectionModel().select("foo");
  144. SelectionEvent<String> event = eventCapture.getValue();
  145. assertNotNull(event);
  146. assertFalse(event.isUserOriginated());
  147. assertEquals("foo", event.getFirstSelectedItem().get());
  148. assertEquals("foo",
  149. event.getAllSelectedItems().stream().findFirst().get());
  150. grid.getSelectionModel().select("bar");
  151. event = eventCapture.getValue();
  152. assertNotNull(event);
  153. assertFalse(event.isUserOriginated());
  154. assertEquals("bar", event.getFirstSelectedItem().get());
  155. assertEquals("bar",
  156. event.getAllSelectedItems().stream().findFirst().get());
  157. grid.getSelectionModel().deselect("bar");
  158. event = eventCapture.getValue();
  159. assertNotNull(event);
  160. assertFalse(event.isUserOriginated());
  161. assertEquals(Optional.empty(), event.getFirstSelectedItem());
  162. assertEquals(0, event.getAllSelectedItems().size());
  163. }
  164. @Test
  165. public void testAddSelectionListener_multiSelectMode() {
  166. grid.setItems("foo", "bar", "baz");
  167. grid.setSelectionMode(SelectionMode.MULTI);
  168. Capture<SelectionEvent<String>> eventCapture = new Capture<>();
  169. grid.addSelectionListener(event -> eventCapture.setValue(event));
  170. grid.getSelectionModel().select("foo");
  171. SelectionEvent<String> event = eventCapture.getValue();
  172. assertNotNull(event);
  173. assertFalse(event.isUserOriginated());
  174. assertEquals("foo", event.getFirstSelectedItem().get());
  175. assertEquals("foo",
  176. event.getAllSelectedItems().stream().findFirst().get());
  177. grid.getSelectionModel().select("bar");
  178. event = eventCapture.getValue();
  179. assertNotNull(event);
  180. assertFalse(event.isUserOriginated());
  181. assertEquals("foo", event.getFirstSelectedItem().get());
  182. assertEquals("foo",
  183. event.getAllSelectedItems().stream().findFirst().get());
  184. assertArrayEquals(new String[] { "foo", "bar" },
  185. event.getAllSelectedItems().toArray(new String[2]));
  186. grid.getSelectionModel().deselect("foo");
  187. event = eventCapture.getValue();
  188. assertNotNull(event);
  189. assertFalse(event.isUserOriginated());
  190. assertEquals("bar", event.getFirstSelectedItem().get());
  191. assertEquals("bar",
  192. event.getAllSelectedItems().stream().findFirst().get());
  193. assertArrayEquals(new String[] { "bar" },
  194. event.getAllSelectedItems().toArray(new String[1]));
  195. grid.getSelectionModel().deselectAll();
  196. event = eventCapture.getValue();
  197. assertNotNull(event);
  198. assertFalse(event.isUserOriginated());
  199. assertEquals(Optional.empty(), event.getFirstSelectedItem());
  200. assertEquals(0, event.getAllSelectedItems().size());
  201. }
  202. @Test
  203. public void testAddSelectionListener_noSelectionMode() {
  204. thrown.expect(UnsupportedOperationException.class);
  205. thrown.expectMessage(
  206. "This selection model doesn't allow selection, cannot add selection listeners to it");
  207. grid.setSelectionMode(SelectionMode.NONE);
  208. grid.addSelectionListener(event -> fail("never ever happens (tm)"));
  209. }
  210. @Test
  211. public void sortByColumn_sortOrderIsAscendingOneColumn() {
  212. Column<String, ?> column = grid.getColumns().get(1);
  213. grid.sort(column);
  214. GridSortOrder<String> sortOrder = grid.getSortOrder().get(0);
  215. assertEquals(column, sortOrder.getSorted());
  216. assertEquals(SortDirection.ASCENDING, sortOrder.getDirection());
  217. }
  218. @Test
  219. public void sortByColumnDesc_sortOrderIsDescendingOneColumn() {
  220. Column<String, ?> column = grid.getColumns().get(1);
  221. grid.sort(column, SortDirection.DESCENDING);
  222. GridSortOrder<String> sortOrder = grid.getSortOrder().get(0);
  223. assertEquals(column, sortOrder.getSorted());
  224. assertEquals(SortDirection.DESCENDING, sortOrder.getDirection());
  225. }
  226. @Test
  227. public void setSortOrder() {
  228. Column<String, ?> column1 = grid.getColumns().get(1);
  229. Column<String, ?> column2 = grid.getColumns().get(2);
  230. List<GridSortOrder<String>> order = Arrays.asList(
  231. new GridSortOrder<>(column2, SortDirection.DESCENDING),
  232. new GridSortOrder<>(column1, SortDirection.ASCENDING));
  233. grid.setSortOrder(order);
  234. List<GridSortOrder<String>> sortOrder = grid.getSortOrder();
  235. assertEquals(column2, sortOrder.get(0).getSorted());
  236. assertEquals(SortDirection.DESCENDING, sortOrder.get(0).getDirection());
  237. assertEquals(column1, sortOrder.get(1).getSorted());
  238. assertEquals(SortDirection.ASCENDING, sortOrder.get(1).getDirection());
  239. }
  240. @Test
  241. public void clearSortOrder() throws Exception {
  242. Column<String, ?> column = grid.getColumns().get(1);
  243. grid.sort(column);
  244. grid.clearSortOrder();
  245. assertEquals(0, grid.getSortOrder().size());
  246. // Make sure state is updated.
  247. assertEquals(0, state.sortColumns.length);
  248. assertEquals(0, state.sortDirs.length);
  249. }
  250. @Test
  251. public void sortOrderDoesnotContainRemovedColumns() {
  252. Column<String, ?> sortColumn = grid.getColumns().get(1);
  253. grid.sort(sortColumn);
  254. // Get id of column and check it's sorted.
  255. String id = state.columnOrder.get(1);
  256. assertEquals(id, state.sortColumns[0]);
  257. // Remove column and make sure it's cleared correctly
  258. grid.removeColumn(sortColumn);
  259. assertFalse("Column not removed", state.columnOrder.contains(id));
  260. assertEquals(0, state.sortColumns.length);
  261. assertEquals(0, state.sortDirs.length);
  262. }
  263. @Test
  264. public void sortListener_eventIsFired() {
  265. Column<String, ?> column1 = grid.getColumns().get(1);
  266. Column<String, ?> column2 = grid.getColumns().get(2);
  267. List<GridSortOrder<String>> list = new ArrayList<>();
  268. AtomicReference<Boolean> fired = new AtomicReference<>();
  269. grid.addSortListener(event -> {
  270. assertTrue(list.isEmpty());
  271. fired.set(true);
  272. list.addAll(event.getSortOrder());
  273. });
  274. grid.sort(column1, SortDirection.DESCENDING);
  275. assertEquals(column1, list.get(0).getSorted());
  276. assertEquals(SortDirection.DESCENDING, list.get(0).getDirection());
  277. List<GridSortOrder<String>> order = Arrays.asList(
  278. new GridSortOrder<>(column2, SortDirection.DESCENDING),
  279. new GridSortOrder<>(column1, SortDirection.ASCENDING));
  280. list.clear();
  281. grid.setSortOrder(order);
  282. assertEquals(column2, list.get(0).getSorted());
  283. assertEquals(SortDirection.DESCENDING, list.get(0).getDirection());
  284. assertEquals(column1, list.get(1).getSorted());
  285. assertEquals(SortDirection.ASCENDING, list.get(1).getDirection());
  286. list.clear();
  287. fired.set(false);
  288. grid.clearSortOrder();
  289. assertEquals(0, list.size());
  290. assertTrue(fired.get());
  291. }
  292. @Test
  293. public void beanGrid() {
  294. Grid<Person> grid = new Grid<>(Person.class);
  295. Column<Person, ?> nameColumn = grid.getColumn("name");
  296. Column<Person, ?> bornColumn = grid.getColumn("born");
  297. assertNotNull(nameColumn);
  298. assertNotNull(bornColumn);
  299. assertEquals("Name", nameColumn.getCaption());
  300. assertEquals("Born", bornColumn.getCaption());
  301. JsonObject json = getRowData(grid, new Person("Lorem", 2000));
  302. Set<String> values = Stream.of(json.keys()).map(json::getString)
  303. .collect(Collectors.toSet());
  304. assertEquals(new HashSet<>(Arrays.asList("Lorem", "2000")), values);
  305. assertSingleSortProperty(nameColumn, "name");
  306. assertSingleSortProperty(bornColumn, "born");
  307. }
  308. @Test
  309. public void beanGrid_editor() throws ValidationException {
  310. Grid<Person> grid = new Grid<>(Person.class);
  311. Column<Person, ?> nameColumn = grid.getColumn("name");
  312. TextField nameField = new TextField();
  313. nameColumn.setEditorComponent(nameField);
  314. Optional<Binding<Person, ?>> maybeBinding = grid.getEditor().getBinder()
  315. .getBinding("name");
  316. assertTrue(maybeBinding.isPresent());
  317. Binding<Person, ?> binding = maybeBinding.get();
  318. assertSame(nameField, binding.getField());
  319. Person person = new Person("Lorem", 2000);
  320. grid.getEditor().getBinder().setBean(person);
  321. assertEquals("Lorem", nameField.getValue());
  322. nameField.setValue("Ipsum");
  323. assertEquals("Ipsum", person.getName());
  324. }
  325. @Test
  326. public void oneArgSetEditor_nonBeanGrid() {
  327. thrown.expect(IllegalStateException.class);
  328. thrown.expectMessage(
  329. "A Grid created without a bean type class literal or a custom property set"
  330. + " doesn't support finding properties by name.");
  331. Grid<Person> grid = new Grid<>();
  332. Column<Person, String> nameCol = grid.addColumn(Person::getName)
  333. .setId("name");
  334. nameCol.setEditorComponent(new TextField());
  335. }
  336. @Test
  337. public void addExistingColumnById_throws() {
  338. thrown.expect(IllegalStateException.class);
  339. thrown.expectMessage("There is already a column for name");
  340. Grid<Person> grid = new Grid<>(Person.class);
  341. grid.addColumn("name");
  342. }
  343. @Test
  344. public void removeByColumn_readdById() {
  345. Grid<Person> grid = new Grid<>(Person.class);
  346. grid.removeColumn(grid.getColumn("name"));
  347. grid.addColumn("name");
  348. List<Column<Person, ?>> columns = grid.getColumns();
  349. assertEquals(2, columns.size());
  350. assertEquals("born", columns.get(0).getId());
  351. assertEquals("name", columns.get(1).getId());
  352. }
  353. @Test
  354. public void removeColumnByColumn() {
  355. grid.removeColumn(fooColumn);
  356. assertEquals(Arrays.asList(lengthColumn, objectColumn, randomColumn),
  357. grid.getColumns());
  358. }
  359. @Test
  360. public void removeColumnByColumn_alreadyRemoved() {
  361. thrown.expect(IllegalArgumentException.class);
  362. thrown.expectMessage(
  363. "Column with id foo cannot be removed from the grid");
  364. grid.removeColumn(fooColumn);
  365. grid.removeColumn(fooColumn);
  366. assertEquals(Arrays.asList(lengthColumn, objectColumn, randomColumn),
  367. grid.getColumns());
  368. }
  369. @Test
  370. public void removeColumnById_alreadyRemoved() {
  371. thrown.expect(IllegalStateException.class);
  372. thrown.expectMessage("There is no column with the id foo");
  373. grid.removeColumn("foo");
  374. grid.removeColumn("foo");
  375. }
  376. @Test
  377. public void removeColumnById() {
  378. grid.removeColumn("foo");
  379. assertEquals(Arrays.asList(lengthColumn, objectColumn, randomColumn),
  380. grid.getColumns());
  381. }
  382. @Test
  383. public void removeAllColumns() {
  384. grid.removeAllColumns();
  385. assertEquals(Collections.emptyList(), grid.getColumns());
  386. }
  387. @Test
  388. public void removeAllColumnsInGridWithoutColumns() {
  389. grid.removeAllColumns();
  390. grid.removeAllColumns();
  391. assertEquals(Collections.emptyList(), grid.getColumns());
  392. }
  393. @Test
  394. public void removeFrozenColumn() {
  395. grid.setFrozenColumnCount(3);
  396. grid.removeColumn(fooColumn);
  397. assertEquals(2, grid.getFrozenColumnCount());
  398. }
  399. @Test
  400. public void removeHiddenFrozenColumn() {
  401. lengthColumn.setHidden(true);
  402. grid.setFrozenColumnCount(3);
  403. grid.removeColumn(lengthColumn);
  404. assertEquals(2, grid.getFrozenColumnCount());
  405. }
  406. @Test
  407. public void removeNonFrozenColumn() {
  408. grid.setFrozenColumnCount(3);
  409. grid.removeColumn(randomColumn);
  410. assertEquals(3, grid.getFrozenColumnCount());
  411. }
  412. @Test
  413. public void testFrozenColumnRemoveColumn() {
  414. assertEquals("Grid should not start with a frozen column", 0,
  415. grid.getFrozenColumnCount());
  416. int columnCount = grid.getColumns().size();
  417. grid.setFrozenColumnCount(columnCount);
  418. grid.removeColumn(grid.getColumns().get(0));
  419. assertEquals(
  420. "Frozen column count should be updated when removing a frozen column",
  421. columnCount - 1, grid.getFrozenColumnCount());
  422. }
  423. @Test
  424. public void setColumns_reorder() {
  425. // Will remove other columns
  426. grid.setColumns("length", "foo");
  427. List<Column<String, ?>> columns = grid.getColumns();
  428. assertEquals(2, columns.size());
  429. assertEquals("length", columns.get(0).getId());
  430. assertEquals("foo", columns.get(1).getId());
  431. }
  432. @Test
  433. public void setColumns_addColumn_notBeangrid() {
  434. thrown.expect(IllegalStateException.class);
  435. thrown.expectMessage(
  436. "A Grid created without a bean type class literal or a custom property set"
  437. + " doesn't support finding properties by name.");
  438. // Not possible to add a column in a grid that cannot add columns based
  439. // on a string
  440. grid.setColumns("notHere");
  441. }
  442. @Test
  443. public void setColumns_addColumns_beangrid() {
  444. Grid<Person> grid = new Grid<>(Person.class);
  445. // Remove so we can add it back
  446. grid.removeColumn("name");
  447. grid.setColumns("born", "name");
  448. List<Column<Person, ?>> columns = grid.getColumns();
  449. assertEquals(2, columns.size());
  450. assertEquals("born", columns.get(0).getId());
  451. assertEquals("name", columns.get(1).getId());
  452. }
  453. @Test
  454. public void setColumns_addColumns_v2_beangrid() {
  455. Grid<Person> grid = new Grid<>(Person.class);
  456. // Remove so we can add it back
  457. grid.removeColumn("name");
  458. List<String> columnIds = new ArrayList<>();
  459. columnIds.add("born");
  460. columnIds.add("name");
  461. grid.setColumns(columnIds);
  462. List<Column<Person, ?>> columns = grid.getColumns();
  463. assertEquals(2, columns.size());
  464. assertEquals("born", columns.get(0).getId());
  465. assertEquals("name", columns.get(1).getId());
  466. }
  467. @Test
  468. public void setColumnOrder_byColumn() {
  469. grid.setColumnOrder(randomColumn, lengthColumn);
  470. assertEquals(Arrays.asList(randomColumn, lengthColumn, fooColumn,
  471. objectColumn), grid.getColumns());
  472. }
  473. @Test
  474. public void setColumnOrder_byColumn_removedColumn() {
  475. thrown.expect(IllegalStateException.class);
  476. thrown.expectMessage("setColumnOrder should not be called "
  477. + "with columns that are not in the grid.");
  478. grid.removeColumn(randomColumn);
  479. grid.setColumnOrder(randomColumn, lengthColumn);
  480. }
  481. @Test
  482. public void setColumnOrder_byString() {
  483. grid.setColumnOrder("randomColumnId", "length");
  484. assertEquals(Arrays.asList(randomColumn, lengthColumn, fooColumn,
  485. objectColumn), grid.getColumns());
  486. }
  487. @Test
  488. public void setColumnOrder_byString_removedColumn() {
  489. thrown.expect(IllegalStateException.class);
  490. thrown.expectMessage("There is no column with the id randomColumnId");
  491. grid.removeColumn("randomColumnId");
  492. grid.setColumnOrder("randomColumnId", "length");
  493. }
  494. @Test
  495. public void defaultSorting_comparableTypes() {
  496. testValueProviderSorting(1, 2, 3);
  497. }
  498. @Test
  499. public void defaultSorting_strings() {
  500. testValueProviderSorting("a", "b", "c");
  501. }
  502. @Test
  503. public void defaultSorting_notComparable() {
  504. assert !Comparable.class.isAssignableFrom(AtomicInteger.class);
  505. testValueProviderSorting(new AtomicInteger(10), new AtomicInteger(8),
  506. new AtomicInteger(9));
  507. }
  508. @Test
  509. public void defaultSorting_differentComparables() {
  510. testValueProviderSorting(10.1, 200, 3000.1, 4000);
  511. }
  512. @Test
  513. public void defaultSorting_mutuallyComparableTypes() {
  514. testValueProviderSorting(new Date(10), new java.sql.Date(1000000),
  515. new Date(100000000));
  516. }
  517. private static void testValueProviderSorting(Object... expectedOrder) {
  518. SerializableComparator<Object> comparator = new Grid<>()
  519. .addColumn(ValueProvider.identity())
  520. .getComparator(SortDirection.ASCENDING);
  521. assertNotNull(comparator);
  522. List<Object> values = new ArrayList<>(Arrays.asList(expectedOrder));
  523. Collections.shuffle(values, new Random(42));
  524. assertArrayEquals(expectedOrder,
  525. values.stream().sorted(comparator).toArray());
  526. }
  527. @Test
  528. public void addBeanColumn_validRenderer() {
  529. Grid<Person> grid = new Grid<>(Person.class);
  530. grid.removeColumn("born");
  531. grid.addColumn("born", new NumberRenderer(new DecimalFormat("#,###",
  532. DecimalFormatSymbols.getInstance(Locale.US))));
  533. Person person = new Person("Name", 2017);
  534. JsonObject rowData = getRowData(grid, person);
  535. String formattedValue = Stream.of(rowData.keys())
  536. .map(rowData::getString).filter(value -> !value.equals("Name"))
  537. .findFirst().orElse(null);
  538. assertEquals(formattedValue, "2,017");
  539. }
  540. @Test
  541. public void addBeanColumn_invalidRenderer() {
  542. thrown.expect(IllegalArgumentException.class);
  543. thrown.expectMessage("NumberRenderer");
  544. thrown.expectMessage(
  545. " cannot be used with a property of type java.lang.String");
  546. Grid<Person> grid = new Grid<>(Person.class);
  547. grid.removeColumn("name");
  548. grid.addColumn("name", new NumberRenderer());
  549. }
  550. @Test
  551. public void columnId_sortProperty() {
  552. assertSingleSortProperty(lengthColumn, "length");
  553. }
  554. @Test
  555. public void columnId_sortProperty_noId() {
  556. assertEquals(0,
  557. objectColumn.getSortOrder(SortDirection.ASCENDING).count());
  558. }
  559. @Test
  560. public void sortProperty_setId_doesntOverride() {
  561. objectColumn.setSortProperty("foo");
  562. objectColumn.setId("bar");
  563. assertSingleSortProperty(objectColumn, "foo");
  564. }
  565. private static void assertSingleSortProperty(Column<?, ?> column,
  566. String expectedProperty) {
  567. QuerySortOrder[] sortOrders = column
  568. .getSortOrder(SortDirection.ASCENDING)
  569. .toArray(QuerySortOrder[]::new);
  570. assertEquals(1, sortOrders.length);
  571. assertEquals(SortDirection.ASCENDING, sortOrders[0].getDirection());
  572. assertEquals(expectedProperty, sortOrders[0].getSorted());
  573. }
  574. private static <T> JsonObject getRowData(Grid<T> grid, T row) {
  575. JsonObject json = Json.createObject();
  576. if (grid.getColumns().isEmpty()) {
  577. return json;
  578. }
  579. // generateData only works if Grid is attached
  580. new MockUI().setContent(grid);
  581. Method getter = findDataGeneratorGetterMethod();
  582. grid.getColumns().forEach(column -> {
  583. DataGenerator<T> dataGenerator;
  584. try {
  585. dataGenerator = (DataGenerator<T>) getter.invoke(column,
  586. new Object[] {});
  587. dataGenerator.generateData(row, json);
  588. } catch (IllegalAccessException | IllegalArgumentException
  589. | InvocationTargetException e) {
  590. throw new AssertionFailedError(
  591. "Cannot get DataGenerator from Column");
  592. }
  593. });
  594. // Detach again
  595. grid.getUI().setContent(null);
  596. return json.getObject("d");
  597. }
  598. private static Method findDataGeneratorGetterMethod() {
  599. try {
  600. Method getter = Column.class.getDeclaredMethod("getDataGenerator",
  601. new Class<?>[] {});
  602. getter.setAccessible(true);
  603. return getter;
  604. } catch (NoSuchMethodException | SecurityException e) {
  605. throw new AssertionFailedError(
  606. "Cannot get DataGenerator from Column");
  607. }
  608. }
  609. @Test
  610. public void removeColumnToThrowForInvalidColumn() {
  611. thrown.expect(IllegalArgumentException.class);
  612. thrown.expectMessage(
  613. "Column with id null cannot be removed from the grid");
  614. Grid<Person> grid1 = new Grid<>();
  615. Grid<Person> grid2 = new Grid<>();
  616. Column<Person, ?> column1 = grid1.addColumn(ValueProvider.identity());
  617. grid2.removeColumn(column1);
  618. }
  619. @Test
  620. public void testColumnSortable() {
  621. Column<String, String> column = grid.addColumn(String::toString);
  622. // Use in-memory data provider
  623. grid.setItems(Collections.emptyList());
  624. Assert.assertTrue("Column should be initially sortable",
  625. column.isSortable());
  626. Assert.assertTrue("User should be able to sort the column",
  627. column.isSortableByUser());
  628. column.setSortable(false);
  629. Assert.assertFalse("Column should not be sortable",
  630. column.isSortable());
  631. Assert.assertFalse(
  632. "User should not be able to sort the column with in-memory data",
  633. column.isSortableByUser());
  634. // Use CallBackDataProvider
  635. grid.setDataProvider(
  636. DataProvider.fromCallbacks(q -> Stream.of(), q -> 0));
  637. Assert.assertFalse("Column should not be sortable",
  638. column.isSortable());
  639. Assert.assertFalse("User should not be able to sort the column",
  640. column.isSortableByUser());
  641. column.setSortable(true);
  642. Assert.assertTrue("Column should be marked sortable",
  643. column.isSortable());
  644. Assert.assertFalse(
  645. "User should not be able to sort the column since no sort order is provided",
  646. column.isSortableByUser());
  647. column.setSortProperty("toString");
  648. Assert.assertTrue("Column should be marked sortable",
  649. column.isSortable());
  650. Assert.assertTrue(
  651. "User should be able to sort the column with the sort order",
  652. column.isSortableByUser());
  653. }
  654. }