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      */
 147     @Smoke
 148     @Test(timeout = 300000)
 149     public void columnSortTest() throws Throwable {
 150         Wrap<? extends Node> columHeader = headerWrap.as(Parent.class, Node.class).lookup(Label.class, new ByText("field 0")).wrap();
 151 
 152         //Ascending sort
 153         columHeader.mouse().click();
 154         Wrap<? extends IndexedCell> cellWrap = getCellWrap(0, isTableTests ? 0 : 1);// first line for treeTable - is root line.
 155         assertTrue(cellWrap.getControl().getItem().equals("item 00 field 0"));
 156 
 157         //Descending sort
 158         columHeader.mouse().click();
 159         cellWrap = getCellWrap(0, isTableTests ? 0 : 1);
 160         int expectedIndex = isTableTests
 161                              ? TableViewApp.DATA_ITEMS_NUM - 1
 162                              : TreeTableAsOldTableApp.DATA_ITEMS_NUM - 2;
 163         assertEquals(String.format("item %02d field 0", expectedIndex), cellWrap.getControl().getItem());
 164 
 165         //Disable sort
 166         columHeader.mouse().click();
 167 
 168          //Ascending sort
 169         columHeader.mouse().click();
 170         cellWrap = getCellWrap(0, isTableTests ? 0 : 1);
 171         assertTrue(cellWrap.getControl().getItem().equals("item 00 field 0"));
 172 
 173         scrollTo(0, TableViewApp.DATA_ITEMS_NUM - 1);
 174         cellWrap = getCellWrap(0, TableViewApp.DATA_ITEMS_NUM - 1);
 175         Rectangle old_bounds = cellWrap.getScreenBounds();
 176         columHeader.mouse().click();
 177         cellWrap = getCellWrap(0, TableViewApp.DATA_ITEMS_NUM - 1);
 178         Rectangle newBounds = cellWrap.getScreenBounds();
 179         assertEquals(old_bounds.x, newBounds.x, 1);
 180         assertEquals(old_bounds.y, newBounds.y, 1);
 181         assertEquals(old_bounds.width, newBounds.width, 1);
 182         assertEquals(old_bounds.height, newBounds.height, 1);
 183     }
 184 
 185     @ScreenshotCheck
 186     @Test(timeout = 300000)
 187     public void columnDragTest() throws Throwable {
 188         Wrap<? extends Node> column_header_0 = headerWrap.as(Parent.class, Node.class).lookup(Label.class, new ByText("field 0")).wrap();
 189 
 190         Rectangle header_bounds = column_header_0.getScreenBounds();
 191         Rectangle content_bounds = contentPane.getScreenBounds();
 192         Double x = header_bounds.getX() - content_bounds.getX() + header_bounds.getWidth() / 2;
 193         Double y = header_bounds.getY() - content_bounds.getY() + header_bounds.getHeight() / 2;
 194         contentPane.mouse().move(new Point(x, y));
 195         contentPane.mouse().press();
 196         contentPane.mouse().move(new Point(0, 0));
 197         checkScreenshot(getControlName() + "Test-columnDrag-outside-0", contentPane);
 198         contentPane.mouse().move(new Point(content_bounds.getWidth(), 0));
 199         checkScreenshot(getControlName() + "Test-columnDrag-outside-1", contentPane);
 200         contentPane.mouse().move(new Point(content_bounds.getWidth(), content_bounds.getHeight()));
 201         checkScreenshot(getControlName() + "Test-columnDrag-outside-2", contentPane);
 202         contentPane.mouse().move(new Point(0, content_bounds.getHeight()));
 203         checkScreenshot(getControlName() + "Test-columnDrag-outside-3", contentPane);
 204         contentPane.mouse().move(new Point(0, 0));
 205         checkScreenshot(getControlName() + "Test-columnDrag-outside-0", contentPane);
 206         contentPane.mouse().release();
 207 
 208         Rectangle table_bounds = tableViewWrap.getScreenBounds();
 209         x = header_bounds.getX() - table_bounds.getX() + header_bounds.getWidth() / 2;
 210         y = header_bounds.getY() - table_bounds.getY() + header_bounds.getHeight() / 2;
 211         tableViewWrap.mouse().move(new Point(x, y));
 212         tableViewWrap.mouse().press();
 213         tableViewWrap.mouse().move(new Point(0, 0));
 214         checkScreenshot(getControlName() + "Test-columnDrag-inside-0", contentPane);
 215         tableViewWrap.mouse().move(new Point(table_bounds.getWidth() / 2, header_bounds.getHeight() / 2));
 216         checkScreenshot(getControlName() + "Test-columnDrag-inside-1", contentPane);
 217         tableViewWrap.mouse().move(new Point(table_bounds.getWidth(), header_bounds.getHeight() / 2));
 218         checkScreenshot(getControlName() + "Test-columnDrag-inside-2", contentPane);
 219         tableViewWrap.mouse().move(new Point(x, y));
 220         tableViewWrap.mouse().release();
 221 
 222         Wrap<? extends Node> column_header_3 = headerWrap.as(Parent.class, Node.class).lookup(Label.class, new ByText("field 3")).wrap();
 223         column_header_0.drag().dnd(column_header_3, column_header_3.getClickPoint().translate(5, 0));
 224         Wrap<? extends IndexedCell> cell_wrap = getCellWrap(0, 0);
 225         assertTrue(cell_wrap.getControl().getItem().equals("item 00 field 1"));
 226         cell_wrap = getCellWrap(3, 0);
 227         assertTrue(cell_wrap.getControl().getItem().equals("item 00 field 0"));
 228 
 229         throwScreenshotError();
 230     }
 231 
 232     @Smoke
 233     @Test(timeout = 300000)
 234     public void columnAutoSize() throws Throwable {
 235         final double AUTO_WIDTH = isTableTests ? 85 : 215;
 236 
 237         final Wrap<? extends Node> columnHeader0 = headerWrap.as(Parent.class, Node.class).lookup(Label.class, new ByText("field 0")).wrap();
 238 
 239         Rectangle headerBounds = columnHeader0.getScreenBounds();
 240 
 241         final double shrinkedWidth = headerBounds.getWidth() / 2;
 242         columnHeader0.mouse().move(new Point(headerBounds.getWidth(), headerBounds.getHeight() / 2));
 243         columnHeader0.mouse().press();
 244         columnHeader0.mouse().move(new Point(shrinkedWidth, headerBounds.getHeight() / 2));
 245         columnHeader0.mouse().release();
 246 
 247         columnHeader0.waitState(new State() {
 248             public Object reached() {
 249                 System.out.println("Checking, that width reducing was applied correctly (by 1 times).");
 250                 Rectangle header_bounds = columnHeader0.getScreenBounds();
 251                 if (Math.abs(header_bounds.getWidth() - shrinkedWidth) <= 5) {
 252                     System.out.println("Correct.");
 253                     return Boolean.TRUE;
 254                 }
 255                 System.out.println("Incorrect.");
 256                 return null;
 257             }
 258         });
 259 
 260         headerBounds = columnHeader0.getScreenBounds();
 261         columnHeader0.mouse().click(2, new Point(headerBounds.getWidth(), headerBounds.getHeight() / 2));
 262 
 263         columnHeader0.waitState(new State() {
 264             public Object reached() {
 265                 System.out.println("Checking, that autosizing was applied correctly.");
 266                 Rectangle header_bounds = columnHeader0.getScreenBounds();
 267                 if (Math.abs(header_bounds.getWidth() - AUTO_WIDTH) < 5) { // TODO:
 268                     System.out.println("Correct.");
 269                     return Boolean.TRUE;
 270                 }
 271                 System.out.println("Incorrect.");
 272                 return null;
 273             }
 274         });
 275     }
 276 
 277     @Smoke
 278     @Test(timeout = 300000)
 279     public void userDataColumnTest() {
 280         ObservableList<TableColumnBase> columns;
 281         if (isTableTests) {
 282             columns = ((TableView) tableViewWrap.getControl()).getColumns();
 283         } else {
 284             columns = ((TreeTableView) tableViewWrap.getControl()).getColumns();
 285         }
 286         Object userData[] = new Object[columns.size()];
 287         for (int i = 0; i < userData.length; i++) {
 288             userData[i] = new Object();
 289             columns.get(i).setUserData(userData[i]);
 290         }
 291         for (int i = 0; i < userData.length; i++) {
 292             System.out.println("userData[i] = " + userData[i]);
 293             System.out.println("columns.get(i).getUserData() = " + columns.get(i).getUserData());
 294             System.out.println("columns.get(i).getProperties().entrySet() = " + columns.get(i).getProperties().entrySet());
 295 //            Assert.assertTrue(columns.get(i).getProperties().containsKey(userData[i]));
 296             Assert.assertTrue(columns.get(i).getProperties().containsValue(userData[i]));
 297 
 298             Set entrySet = columns.get(i).getProperties().entrySet();
 299             for (Iterator<Entry> it = entrySet.iterator(); it.hasNext();) {
 300                 Entry entry = it.next();
 301                 System.out.println("key = " + entry.getKey() + "; val = " + entry.getValue());
 302             }
 303 
 304             Assert.assertEquals(userData[i], columns.get(i).getUserData());
 305             //Assert.assertTrue(columns.get(i).getProperties().entrySet().contains(userData[i]));
 306         }
 307     }
 308 
 309     /**
 310      * Checks that when the sorting is applied
 311      * to the underlying data collection
 312      * the cells are rendered in the right order.
 313      */
 314     @Smoke
 315     @Test(timeout=300000)
 316     public void renderingAfterSortingTest() throws Throwable {
 317 
 318         final int ITEMS_COUNT = 7;
 319         final int COL_IDX = 0;
 320 
 321         StringConverter<Data> conv = new StringConverter<Data>() {
 322             @Override
 323             public String toString(Data item) {
 324                 return String.format("item %s field %d", item.toString(), COL_IDX);
 325             }
 326 
 327             @Override
 328             public Data fromString(String s) { return new Data(s, DATA_FIELDS_NUM, 0); }
 329         };
 330 
 331         SortValidator<Data, TableCell> validator = new SortValidator<Data, TableCell>(ITEMS_COUNT, conv) {
 332 
 333             @Override
 334             protected void setControlData(final ObservableList<Data> ls) {
 335                 new GetAction<Object>() {
 336                     @Override
 337                     public void run(Object... os) throws Exception {
 338                         if (isTableTests) {
 339                             ((TableView) testedControl.getControl()).setItems(ls);
 340                         } else {
 341                             for (Data data : ls) {
 342                                 ((TreeTableView) testedControl.getControl()).getRoot().getChildren().addAll(new TreeItem(data));
 343                             }
 344                             ((TreeTableView) testedControl.getControl()).setShowRoot(false);
 345                         }
 346                     }
 347                 }.dispatch(testedControl.getEnvironment());
 348             }
 349 
 350             @Override
 351             protected Lookup<? extends TableCell> getCellsLookup() {
 352                 return testedControl.as(Parent.class, Node.class).lookup(TableCell.class, new LookupCriteria<TableCell>() {
 353                             public boolean check(TableCell cell) {
 354                                 TableColumn col = cell.getTableColumn();
 355                                 return COL_IDX == cell.getTableView().getColumns().indexOf(col) && cell.isVisible();
 356                             }
 357                         });
 358             }
 359 
 360             @Override
 361             protected String getTextFromCell(TableCell cell) {
 362                return cell.getText();
 363             }
 364         };
 365 
 366         boolean result = validator.check();
 367         String msg = validator.getFailureReason();
 368         assertTrue(msg, result);
 369     }
 370 
 371     @Smoke
 372     @Test(timeout=300000)
 373     public void scrollToColumnIndex() {
 374         DATA_FIELDS_NUM = 64;
 375         refill(DATA_FIELDS_NUM, DATA_ITEMS_NUM);
 376 
 377         scrollToColumnByIndex(DATA_FIELDS_NUM - 1);
 378         assertTrue(isColumnHeaderVisible(DATA_FIELDS_NUM - 1));
 379         assertTrue(!isColumnHeaderVisible(0));
 380         assertEquals(getScrollBarMaxValue(Orientation.HORIZONTAL), getScrollBarValue(Orientation.HORIZONTAL), 1e-7);
 381 
 382         scrollToColumnByIndex(0);
 383         assertTrue(isColumnHeaderVisible(0));
 384         assertTrue(!isColumnHeaderVisible(DATA_FIELDS_NUM - 1));
 385         assertEquals(getScrollBarMinValue(Orientation.HORIZONTAL), getScrollBarValue(Orientation.HORIZONTAL), 1e-7);
 386 
 387         scrollToColumn(DATA_FIELDS_NUM - 1);
 388         assertTrue(isColumnHeaderVisible(DATA_FIELDS_NUM - 1));
 389         assertTrue(!isColumnHeaderVisible(0));
 390         assertEquals(getScrollBarMaxValue(Orientation.HORIZONTAL), getScrollBarValue(Orientation.HORIZONTAL), 1e-7);
 391 
 392         scrollToColumn(0);
 393         assertTrue(isColumnHeaderVisible(0));
 394         assertTrue(!isColumnHeaderVisible(DATA_FIELDS_NUM - 1));
 395         assertEquals(getScrollBarMinValue(Orientation.HORIZONTAL), getScrollBarValue(Orientation.HORIZONTAL), 1e-7);
 396 
 397         scrollToColumnByIndex(DATA_FIELDS_NUM / 3);
 398         assertTrue(isColumnHeaderVisible(DATA_FIELDS_NUM / 3));
 399         assertTrue(!isColumnHeaderVisible(0));
 400         assertTrue(!isColumnHeaderVisible(DATA_FIELDS_NUM - 1));
 401         double delta = testedControl.getScreenBounds().getWidth() / 2;
 402         assertEquals(getScrollBarMaxValue(Orientation.HORIZONTAL) / 3, getScrollBarValue(Orientation.HORIZONTAL), delta);
 403     }
 404 
 405     /**
 406      * Checks that column resizing is correct
 407      * according to desired values
 408      */
 409     @Smoke
 410     @Test
 411     public void columnResizeTest() {
 412         final int columnIndex = 0;
 413 
 414         double delta = 0.0;
 415         double expectedWidth = getColumnWidth(columnIndex);
 416         resizeColumn(columnIndex, delta);
 417         assertEquals(expectedWidth, getColumnWidth(columnIndex), 1e-7);
 418 
 419         delta = 100.0;
 420         expectedWidth += delta;
 421         resizeColumn(columnIndex, delta);
 422         assertEquals(expectedWidth, getColumnWidth(columnIndex), 1e-7);
 423 
 424         delta = 0.0;
 425         resizeColumn(columnIndex, delta);
 426         assertEquals(expectedWidth, getColumnWidth(columnIndex), 1e-7);
 427 
 428         delta = 100.0;
 429         expectedWidth += delta;
 430         resizeColumn(columnIndex, delta);
 431         assertEquals(expectedWidth, getColumnWidth(columnIndex), 1e-7);
 432     }
 433 
 434     @Override
 435     protected void insertAt(int pos) {
 436         txtItemInsertIndex.clear();
 437         txtItemInsertIndex.type(String.valueOf(pos));
 438         btnInsertItem.mouse().click();
 439     }
 440 
 441     @Override
 442     protected void insertColumnAt(int pos) {
 443         txtColumnInserIndex.clear();
 444         txtColumnInserIndex.type(String.valueOf(pos));
 445         btnInsertColumn.mouse().click();
 446     }
 447 
 448     @Override
 449     protected void removeAt(int pos) {
 450         txtItemRemoveIndex.clear();
 451         txtItemRemoveIndex.type(String.valueOf(pos));
 452         btnRemoveItem.mouse().click();
 453     }
 454 
 455     @Override
 456     protected void removeColumnAt(int pos) {
 457         txtColumnRemoveIndex.clear();
 458         txtColumnRemoveIndex.type(String.valueOf(pos));
 459         btnRemoveColumn.mouse().click();
 460     }
 461 }