1 /*
   2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation. Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package javafx.scene.control.test.tableview;
  26 
  27 import client.test.ScreenshotCheck;
  28 import client.test.Smoke;
  29 import java.util.Iterator;
  30 import java.util.Map.Entry;
  31 import java.util.Set;
  32 import java.util.logging.Level;
  33 import java.util.logging.Logger;
  34 import javafx.collections.ObservableList;
  35 import javafx.commons.SortValidator;
  36 import javafx.geometry.Orientation;
  37 import javafx.scene.Node;
  38 import javafx.scene.control.*;
  39 import javafx.scene.control.test.tableview.TableViewApp.Data;
  40 import static javafx.scene.control.test.tableview.TestBase.DATA_FIELDS_NUM;
  41 import javafx.scene.control.test.treetable.TreeTableAsOldTableApp;
  42 import javafx.util.StringConverter;
  43 import org.jemmy.Point;
  44 import org.jemmy.Rectangle;
  45 import org.jemmy.action.GetAction;
  46 import org.jemmy.control.Wrap;
  47 import org.jemmy.fx.*;
  48 import org.jemmy.interfaces.Parent;
  49 import org.jemmy.lookup.Lookup;
  50 import org.jemmy.lookup.LookupCriteria;
  51 import org.jemmy.timing.State;
  52 import org.junit.Assert;
  53 import static org.junit.Assert.assertEquals;
  54 import static org.junit.Assert.assertTrue;
  55 import org.junit.Test;
  56 import org.junit.runner.RunWith;
  57 import test.javaclient.shared.FilteredTestRunner;
  58 import test.javaclient.shared.screenshots.ScreenshotUtils;
  59 
  60 @RunWith(FilteredTestRunner.class)
  61 public class TableViewTest extends TestBase {
  62 
  63     /*
  64      * removed
  65      * @Smoke
  66      @Test(timeout=300000) public void keyboardCtrlShiftPageUpPageDownTest() throws
  67      * Throwable { keyboardPageUpPageDownCycle(CTRL_DOWN_MASK_OS,
  68      * KeyboardModifiers.SHIFT_DOWN_MASK); }
  69      */
  70     @ScreenshotCheck
  71     @Smoke
  72     @Test(timeout = 300000)
  73     public void insertSingleItemTest() throws Throwable {
  74         insertAt(0);
  75         insertAt(TableViewApp.DATA_ITEMS_NUM / 2);
  76         ScreenshotUtils.checkScreenshot(getControlName() + "Test-insert-item", contentPane);
  77     }
  78 
  79     @ScreenshotCheck
  80     @Smoke
  81     @Test(timeout = 300000)
  82     public void removeSingleItemTest() throws Throwable {
  83         removeAt(0);
  84         removeAt(TableViewApp.DATA_ITEMS_NUM / 2);
  85         ScreenshotUtils.checkScreenshot(getControlName() + "Test-remove-item", contentPane);
  86     }
  87 
  88     @ScreenshotCheck
  89     @Smoke
  90     @Test(timeout = 300000)
  91     public void insertSingleColumnTest() throws Throwable {
  92         insertColumnAt(0);
  93         insertColumnAt(TableViewApp.DATA_FIELDS_NUM / 2);
  94         ScreenshotUtils.checkScreenshot(getControlName() + "Test-insert-column", contentPane);
  95     }
  96 
  97     @ScreenshotCheck
  98     @Smoke
  99     @Test(timeout = 300000)
 100     public void removeSingleColumnTest() throws Throwable {
 101         removeColumnAt(0);
 102         removeColumnAt(TableViewApp.DATA_FIELDS_NUM / 2);
 103         ScreenshotUtils.checkScreenshot(getControlName() + "Test-remove-column", contentPane);
 104     }
 105 
 106     @Smoke
 107     @Test(timeout = 300000)
 108     public void scrollBarsTest() throws Throwable {
 109         final Lookup vScrollBar = getScrollLookup(Orientation.VERTICAL);
 110         final Lookup hScrollBar = getScrollLookup(Orientation.HORIZONTAL);
 111         final int ROWS_TO_REMOVE = DATA_ITEMS_NUM - pageHeightInCells;
 112         final int COLS_TO_REMOVE = DATA_FIELDS_NUM - pageWidthInCells;
 113 
 114         final State<Integer> vScrollBarCount = new State<Integer>() {
 115             public Integer reached() { return Integer.valueOf(vScrollBar.size()); }
 116         };
 117 
 118         final State<Integer> hScrollBarCount = new State<Integer>() {
 119             public Integer reached() { return Integer.valueOf(hScrollBar.size()); }
 120         };
 121 
 122         testedControl.waitState(hScrollBarCount, Integer.valueOf(1));
 123         testedControl.waitState(vScrollBarCount, Integer.valueOf(1));
 124         for (int i = 0; i < ROWS_TO_REMOVE; i++) {
 125             btnRemoveItem.mouse().click();
 126         }
 127         testedControl.waitState(vScrollBarCount, Integer.valueOf(0));
 128 
 129         testedControl.waitState(hScrollBarCount, Integer.valueOf(1));
 130         for (int i = 0; i < COLS_TO_REMOVE; i++) {
 131             btnRemoveColumn.mouse().click();
 132         }
 133         testedControl.waitState(hScrollBarCount, Integer.valueOf(0));
 134 
 135         btnInsertItem.mouse().click();
 136         testedControl.waitState(vScrollBarCount, Integer.valueOf(1));
 137 
 138         btnInsertColumn.mouse().click();
 139         testedControl.waitState(hScrollBarCount, Integer.valueOf(1));
 140     }
 141 
 142     /**
 143      * Checks that sort works for the column. According to the spec there are
 144      * three states of sorting and all of them are checked
 145      *
 146      * http://xdesign.us.oracle.com/projects/javaFX/fxcontrols-ue/specifications/treetable/treetable.html#sorting
 147      */
 148     @Smoke
 149     @Test(timeout = 300000)
 150     public void columnSortTest() throws Throwable {
 151         Wrap<? extends Node> columHeader = headerWrap.as(Parent.class, Node.class).lookup(Label.class, new ByText("field 0")).wrap();
 152 
 153         //Ascending sort
 154         columHeader.mouse().click();
 155         Wrap<? extends IndexedCell> cellWrap = getCellWrap(0, isTableTests ? 0 : 1);// first line for treeTable - is root line.
 156         assertTrue(cellWrap.getControl().getItem().equals("item 00 field 0"));
 157 
 158         //Descending sort
 159         columHeader.mouse().click();
 160         cellWrap = getCellWrap(0, isTableTests ? 0 : 1);
 161         int expectedIndex = isTableTests
 162                              ? TableViewApp.DATA_ITEMS_NUM - 1
 163                              : TreeTableAsOldTableApp.DATA_ITEMS_NUM - 2;
 164         assertEquals(String.format("item %02d field 0", expectedIndex), cellWrap.getControl().getItem());
 165 
 166         //Disable sort
 167         columHeader.mouse().click();
 168 
 169          //Ascending sort
 170         columHeader.mouse().click();
 171         cellWrap = getCellWrap(0, isTableTests ? 0 : 1);
 172         assertTrue(cellWrap.getControl().getItem().equals("item 00 field 0"));
 173 
 174         scrollTo(0, TableViewApp.DATA_ITEMS_NUM - 1);
 175         cellWrap = getCellWrap(0, TableViewApp.DATA_ITEMS_NUM - 1);
 176         Rectangle old_bounds = cellWrap.getScreenBounds();
 177         columHeader.mouse().click();
 178         cellWrap = getCellWrap(0, TableViewApp.DATA_ITEMS_NUM - 1);
 179         Rectangle newBounds = cellWrap.getScreenBounds();
 180         assertEquals(old_bounds.x, newBounds.x, 1);
 181         assertEquals(old_bounds.y, newBounds.y, 1);
 182         assertEquals(old_bounds.width, newBounds.width, 1);
 183         assertEquals(old_bounds.height, newBounds.height, 1);
 184     }
 185 
 186     @ScreenshotCheck
 187     @Test(timeout = 300000)
 188     public void columnDragTest() throws Throwable {
 189         Wrap<? extends Node> column_header_0 = headerWrap.as(Parent.class, Node.class).lookup(Label.class, new ByText("field 0")).wrap();
 190 
 191         Rectangle header_bounds = column_header_0.getScreenBounds();
 192         Rectangle content_bounds = contentPane.getScreenBounds();
 193         Double x = header_bounds.getX() - content_bounds.getX() + header_bounds.getWidth() / 2;
 194         Double y = header_bounds.getY() - content_bounds.getY() + header_bounds.getHeight() / 2;
 195         contentPane.mouse().move(new Point(x, y));
 196         contentPane.mouse().press();
 197         contentPane.mouse().move(new Point(0, 0));
 198         checkScreenshot(getControlName() + "Test-columnDrag-outside-0", contentPane);
 199         contentPane.mouse().move(new Point(content_bounds.getWidth(), 0));
 200         checkScreenshot(getControlName() + "Test-columnDrag-outside-1", contentPane);
 201         contentPane.mouse().move(new Point(content_bounds.getWidth(), content_bounds.getHeight()));
 202         checkScreenshot(getControlName() + "Test-columnDrag-outside-2", contentPane);
 203         contentPane.mouse().move(new Point(0, content_bounds.getHeight()));
 204         checkScreenshot(getControlName() + "Test-columnDrag-outside-3", contentPane);
 205         contentPane.mouse().move(new Point(0, 0));
 206         checkScreenshot(getControlName() + "Test-columnDrag-outside-0", contentPane);
 207         contentPane.mouse().release();
 208 
 209         Rectangle table_bounds = tableViewWrap.getScreenBounds();
 210         x = header_bounds.getX() - table_bounds.getX() + header_bounds.getWidth() / 2;
 211         y = header_bounds.getY() - table_bounds.getY() + header_bounds.getHeight() / 2;
 212         tableViewWrap.mouse().move(new Point(x, y));
 213         tableViewWrap.mouse().press();
 214         tableViewWrap.mouse().move(new Point(0, 0));
 215         checkScreenshot(getControlName() + "Test-columnDrag-inside-0", contentPane);
 216         tableViewWrap.mouse().move(new Point(table_bounds.getWidth() / 2, header_bounds.getHeight() / 2));
 217         checkScreenshot(getControlName() + "Test-columnDrag-inside-1", contentPane);
 218         tableViewWrap.mouse().move(new Point(table_bounds.getWidth(), header_bounds.getHeight() / 2));
 219         checkScreenshot(getControlName() + "Test-columnDrag-inside-2", contentPane);
 220         tableViewWrap.mouse().move(new Point(x, y));
 221         tableViewWrap.mouse().release();
 222 
 223         Wrap<? extends Node> column_header_3 = headerWrap.as(Parent.class, Node.class).lookup(Label.class, new ByText("field 3")).wrap();
 224         column_header_0.drag().dnd(column_header_3, column_header_3.getClickPoint().translate(5, 0));
 225         Wrap<? extends IndexedCell> cell_wrap = getCellWrap(0, 0);
 226         assertTrue(cell_wrap.getControl().getItem().equals("item 00 field 1"));
 227         cell_wrap = getCellWrap(3, 0);
 228         assertTrue(cell_wrap.getControl().getItem().equals("item 00 field 0"));
 229 
 230         throwScreenshotError();
 231     }
 232 
 233     @Smoke
 234     @Test(timeout = 300000)
 235     public void columnAutoSize() throws Throwable {
 236         final double AUTO_WIDTH = isTableTests ? 85 : 215;
 237 
 238         final Wrap<? extends Node> columnHeader0 = headerWrap.as(Parent.class, Node.class).lookup(Label.class, new ByText("field 0")).wrap();
 239 
 240         Rectangle headerBounds = columnHeader0.getScreenBounds();
 241 
 242         final double shrinkedWidth = headerBounds.getWidth() / 2;
 243         columnHeader0.mouse().move(new Point(headerBounds.getWidth(), headerBounds.getHeight() / 2));
 244         columnHeader0.mouse().press();
 245         columnHeader0.mouse().move(new Point(shrinkedWidth, headerBounds.getHeight() / 2));
 246         columnHeader0.mouse().release();
 247 
 248         columnHeader0.waitState(new State() {
 249             public Object reached() {
 250                 System.out.println("Checking, that width reducing was applied correctly (by 1 times).");
 251                 Rectangle header_bounds = columnHeader0.getScreenBounds();
 252                 if (Math.abs(header_bounds.getWidth() - shrinkedWidth) <= 5) {
 253                     System.out.println("Correct.");
 254                     return Boolean.TRUE;
 255                 }
 256                 System.out.println("Incorrect.");
 257                 return null;
 258             }
 259         });
 260 
 261         headerBounds = columnHeader0.getScreenBounds();
 262         columnHeader0.mouse().click(2, new Point(headerBounds.getWidth(), headerBounds.getHeight() / 2));
 263 
 264         columnHeader0.waitState(new State() {
 265             public Object reached() {
 266                 System.out.println("Checking, that autosizing was applied correctly.");
 267                 Rectangle header_bounds = columnHeader0.getScreenBounds();
 268                 if (Math.abs(header_bounds.getWidth() - AUTO_WIDTH) < 5) { // TODO:
 269                     System.out.println("Correct.");
 270                     return Boolean.TRUE;
 271                 }
 272                 System.out.println("Incorrect.");
 273                 return null;
 274             }
 275         });
 276     }
 277 
 278     @Smoke
 279     @Test(timeout = 300000)
 280     public void userDataColumnTest() {
 281         ObservableList<TableColumnBase> columns;
 282         if (isTableTests) {
 283             columns = ((TableView) tableViewWrap.getControl()).getColumns();
 284         } else {
 285             columns = ((TreeTableView) tableViewWrap.getControl()).getColumns();
 286         }
 287         Object userData[] = new Object[columns.size()];
 288         for (int i = 0; i < userData.length; i++) {
 289             userData[i] = new Object();
 290             columns.get(i).setUserData(userData[i]);
 291         }
 292         for (int i = 0; i < userData.length; i++) {
 293             System.out.println("userData[i] = " + userData[i]);
 294             System.out.println("columns.get(i).getUserData() = " + columns.get(i).getUserData());
 295             System.out.println("columns.get(i).getProperties().entrySet() = " + columns.get(i).getProperties().entrySet());
 296 //            Assert.assertTrue(columns.get(i).getProperties().containsKey(userData[i]));
 297             Assert.assertTrue(columns.get(i).getProperties().containsValue(userData[i]));
 298 
 299             Set entrySet = columns.get(i).getProperties().entrySet();
 300             for (Iterator<Entry> it = entrySet.iterator(); it.hasNext();) {
 301                 Entry entry = it.next();
 302                 System.out.println("key = " + entry.getKey() + "; val = " + entry.getValue());
 303             }
 304 
 305             Assert.assertEquals(userData[i], columns.get(i).getUserData());
 306             //Assert.assertTrue(columns.get(i).getProperties().entrySet().contains(userData[i]));
 307         }
 308     }
 309 
 310     /**
 311      * Checks that when the sorting is applied
 312      * to the underlying data collection
 313      * the cells are rendered in the right order.
 314      */
 315     @Smoke
 316     @Test(timeout=300000)
 317     public void renderingAfterSortingTest() throws Throwable {
 318 
 319         final int ITEMS_COUNT = 7;
 320         final int COL_IDX = 0;
 321 
 322         StringConverter<Data> conv = new StringConverter<Data>() {
 323             @Override
 324             public String toString(Data item) {
 325                 return String.format("item %s field %d", item.toString(), COL_IDX);
 326             }
 327 
 328             @Override
 329             public Data fromString(String s) { return new Data(s, DATA_FIELDS_NUM, 0); }
 330         };
 331 
 332         SortValidator<Data, TableCell> validator = new SortValidator<Data, TableCell>(ITEMS_COUNT, conv) {
 333 
 334             @Override
 335             protected void setControlData(final ObservableList<Data> ls) {
 336                 new GetAction<Object>() {
 337                     @Override
 338                     public void run(Object... os) throws Exception {
 339                         if (isTableTests) {
 340                             ((TableView) testedControl.getControl()).setItems(ls);
 341                         } else {
 342                             for (Data data : ls) {
 343                                 ((TreeTableView) testedControl.getControl()).getRoot().getChildren().addAll(new TreeItem(data));
 344                             }
 345                             ((TreeTableView) testedControl.getControl()).setShowRoot(false);
 346                         }
 347                     }
 348                 }.dispatch(testedControl.getEnvironment());
 349             }
 350 
 351             @Override
 352             protected Lookup<? extends TableCell> getCellsLookup() {
 353                 return testedControl.as(Parent.class, Node.class).lookup(TableCell.class, new LookupCriteria<TableCell>() {
 354                             public boolean check(TableCell cell) {
 355                                 TableColumn col = cell.getTableColumn();
 356                                 return COL_IDX == cell.getTableView().getColumns().indexOf(col) && cell.isVisible();
 357                             }
 358                         });
 359             }
 360 
 361             @Override
 362             protected String getTextFromCell(TableCell cell) {
 363                return cell.getText();
 364             }
 365         };
 366 
 367         boolean result = validator.check();
 368         String msg = validator.getFailureReason();
 369         assertTrue(msg, result);
 370     }
 371 
 372     @Smoke
 373     @Test(timeout=300000)
 374     public void scrollToColumnIndex() {
 375         DATA_FIELDS_NUM = 64;
 376         refill(DATA_FIELDS_NUM, DATA_ITEMS_NUM);
 377 
 378         scrollToColumnByIndex(DATA_FIELDS_NUM - 1);
 379         assertTrue(isColumnHeaderVisible(DATA_FIELDS_NUM - 1));
 380         assertTrue(!isColumnHeaderVisible(0));
 381         assertEquals(getScrollBarMaxValue(Orientation.HORIZONTAL), getScrollBarValue(Orientation.HORIZONTAL), 1e-7);
 382 
 383         scrollToColumnByIndex(0);
 384         assertTrue(isColumnHeaderVisible(0));
 385         assertTrue(!isColumnHeaderVisible(DATA_FIELDS_NUM - 1));
 386         assertEquals(getScrollBarMinValue(Orientation.HORIZONTAL), getScrollBarValue(Orientation.HORIZONTAL), 1e-7);
 387 
 388         scrollToColumn(DATA_FIELDS_NUM - 1);
 389         assertTrue(isColumnHeaderVisible(DATA_FIELDS_NUM - 1));
 390         assertTrue(!isColumnHeaderVisible(0));
 391         assertEquals(getScrollBarMaxValue(Orientation.HORIZONTAL), getScrollBarValue(Orientation.HORIZONTAL), 1e-7);
 392 
 393         scrollToColumn(0);
 394         assertTrue(isColumnHeaderVisible(0));
 395         assertTrue(!isColumnHeaderVisible(DATA_FIELDS_NUM - 1));
 396         assertEquals(getScrollBarMinValue(Orientation.HORIZONTAL), getScrollBarValue(Orientation.HORIZONTAL), 1e-7);
 397 
 398         scrollToColumnByIndex(DATA_FIELDS_NUM / 3);
 399         assertTrue(isColumnHeaderVisible(DATA_FIELDS_NUM / 3));
 400         assertTrue(!isColumnHeaderVisible(0));
 401         assertTrue(!isColumnHeaderVisible(DATA_FIELDS_NUM - 1));
 402         double delta = testedControl.getScreenBounds().getWidth() / 2;
 403         assertEquals(getScrollBarMaxValue(Orientation.HORIZONTAL) / 3, getScrollBarValue(Orientation.HORIZONTAL), delta);
 404     }
 405 
 406     /**
 407      * Checks that column resizing is correct
 408      * according to desired values
 409      */
 410     @Smoke
 411     @Test
 412     public void columnResizeTest() {
 413         final int columnIndex = 0;
 414 
 415         double delta = 0.0;
 416         double expectedWidth = getColumnWidth(columnIndex);
 417         resizeColumn(columnIndex, delta);
 418         assertEquals(expectedWidth, getColumnWidth(columnIndex), 1e-7);
 419 
 420         delta = 100.0;
 421         expectedWidth += delta;
 422         resizeColumn(columnIndex, delta);
 423         assertEquals(expectedWidth, getColumnWidth(columnIndex), 1e-7);
 424 
 425         delta = 0.0;
 426         resizeColumn(columnIndex, delta);
 427         assertEquals(expectedWidth, getColumnWidth(columnIndex), 1e-7);
 428 
 429         delta = 100.0;
 430         expectedWidth += delta;
 431         resizeColumn(columnIndex, delta);
 432         assertEquals(expectedWidth, getColumnWidth(columnIndex), 1e-7);
 433     }
 434 
 435     @Override
 436     protected void insertAt(int pos) {
 437         txtItemInsertIndex.clear();
 438         txtItemInsertIndex.type(String.valueOf(pos));
 439         btnInsertItem.mouse().click();
 440     }
 441 
 442     @Override
 443     protected void insertColumnAt(int pos) {
 444         txtColumnInserIndex.clear();
 445         txtColumnInserIndex.type(String.valueOf(pos));
 446         btnInsertColumn.mouse().click();
 447     }
 448 
 449     @Override
 450     protected void removeAt(int pos) {
 451         txtItemRemoveIndex.clear();
 452         txtItemRemoveIndex.type(String.valueOf(pos));
 453         btnRemoveItem.mouse().click();
 454     }
 455 
 456     @Override
 457     protected void removeColumnAt(int pos) {
 458         txtColumnRemoveIndex.clear();
 459         txtColumnRemoveIndex.type(String.valueOf(pos));
 460         btnRemoveColumn.mouse().click();
 461     }
 462 }