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.treeview;
  26 
  27 import client.test.Smoke;
  28 import com.oracle.jdk.sqe.cc.markup.Covers;
  29 import com.oracle.jdk.sqe.cc.markup.Covers.Level;
  30 import javafx.scene.control.skin.TableHeaderRow;
  31 import java.util.Comparator;
  32 import java.util.HashMap;
  33 import java.util.Map;
  34 import java.util.Set;
  35 import java.util.logging.Logger;
  36 import javafx.beans.property.IntegerProperty;
  37 import javafx.beans.property.ObjectProperty;
  38 import javafx.beans.property.SimpleIntegerProperty;
  39 import javafx.beans.property.SimpleObjectProperty;
  40 import javafx.collections.FXCollections;
  41 import javafx.collections.ObservableList;
  42 import javafx.commons.SortValidator;
  43 import javafx.event.Event;
  44 import javafx.event.EventHandler;
  45 import javafx.scene.Group;
  46 import javafx.scene.Node;
  47 import javafx.scene.control.IndexedCell;
  48 import javafx.scene.control.TextField;
  49 import javafx.scene.control.TreeCell;
  50 import javafx.scene.control.TreeItem;
  51 import javafx.scene.control.TreeView;
  52 import static javafx.scene.control.test.treeview.TreeViewCommonFunctionality.*;
  53 import javafx.scene.control.test.treeview.TreeViewCommonFunctionality.Properties;
  54 import javafx.scene.control.test.utils.ptables.AbstractPropertyController.SettingType;
  55 import static javafx.scene.control.test.utils.ptables.NodeControllerFactory.TreeItemControllers.CHANGE_VALUE_BUTTON_ID;
  56 import static javafx.scene.control.test.utils.ptables.NodeControllerFactory.TreeItemControllers.NEW_VALUE_TEXT_FIELD_ID;
  57 import static javafx.scene.control.test.utils.ptables.SpecialTablePropertiesProvider.ForTreeItem.*;
  58 import javafx.scene.shape.Circle;
  59 import javafx.scene.shape.Polygon;
  60 import javafx.scene.shape.Rectangle;
  61 import javafx.scene.text.Text;
  62 import javafx.util.StringConverter;
  63 import org.jemmy.action.GetAction;
  64 import org.jemmy.control.Wrap;
  65 import org.jemmy.fx.ByID;
  66 import org.jemmy.fx.ByStyleClass;
  67 import org.jemmy.interfaces.Keyboard;
  68 import org.jemmy.interfaces.Keyboard.KeyboardButtons;
  69 import org.jemmy.interfaces.Keyboard.KeyboardModifiers;
  70 import org.jemmy.interfaces.Parent;
  71 import org.jemmy.lookup.Lookup;
  72 import org.jemmy.lookup.LookupCriteria;
  73 import org.jemmy.timing.State;
  74 import static org.junit.Assert.*;
  75 import org.junit.Test;
  76 import org.junit.runner.RunWith;
  77 import test.javaclient.shared.FilteredTestRunner;
  78 import static javafx.scene.control.test.treetable.TreeTableNewApp.*;
  79 import org.jemmy.TimeoutExpiredException;
  80 import org.jemmy.fx.control.TextFieldCellEditor;
  81 import org.jemmy.fx.control.TreeTableCellDock;
  82 import org.jemmy.fx.control.TreeTableViewWrap;
  83 import static javafx.commons.Consts.*;
  84 
  85 /**
  86  * @author Alexander Kirov, Dmitry Zinkevich
  87  */
  88 @RunWith(FilteredTestRunner.class)
  89 public class TreeViewTest extends TestBase {
  90 
  91     @Test(timeout = 600000)
  92 
  93     @Smoke
  94     /*
  95      * This test checks behavior of TreeItem.nextSibling(),
  96      * TreeiTem.nextSibling(TreeItem), TreeiTem.previousSibling(),
  97      * TreeiTem.previousSibling(TreeItem) functions, and their correctness,
  98      * during adding and removing procedures done over treeView.
  99      */
 100     public void nextAndPreviousSiblingTest() {
 101         String item[] = {"item0", "item1", "item2", "item3"};
 102         for (int i = 0; i < 3; i++) {
 103             addElement(item[i], ROOT_NAME, i, true);
 104         }
 105 
 106         switchToPropertiesTab(ROOT_NAME);
 107         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, true);
 108 
 109         for (int ind = 0; ind < 2; ind++) {
 110             switchToPropertiesTab(ROOT_NAME);
 111             checkSiblings("null", "null");
 112 
 113             for (int i = 0; i < 2; i++) {
 114                 switchToPropertiesTab(item[i]);
 115                 checkSiblings(i - 1 < 0 ? "null" : item[i - 1], i + 1 > 3 ? "null" : item[i + 1]);
 116             }
 117 
 118             switchToPropertiesTab(ROOT_NAME);
 119             setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, false);
 120         }
 121 
 122         switchToPropertiesTab(ROOT_NAME);
 123         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, true);
 124 
 125         addElement(item[3], item[1], 0, true);
 126 
 127         for (int i = 0; i < 2; i++) {
 128             switchToPropertiesTab(item[i]);
 129             checkSiblings(i - 1 < 0 ? "null" : item[i - 1], i + 1 > 3 ? "null" : item[i + 1]);
 130         }
 131 
 132         switchToPropertiesTab(item[1]);
 133         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, true);
 134 
 135         for (int i = 0; i < 2; i++) {
 136             switchToPropertiesTab(item[i]);
 137             checkSiblings(i - 1 < 0 ? "null" : item[i - 1], i + 1 > 3 ? "null" : item[i + 1]);
 138         }
 139 
 140         switchToPropertiesTab(item[3]);
 141         checkSiblings("null", "null");
 142 
 143         removeItem(item[3]);
 144 
 145         for (int i = 0; i < 2; i++) {
 146             switchToPropertiesTab(item[i]);
 147             checkSiblings(i - 1 < 0 ? "null" : item[i - 1], i + 1 > 3 ? "null" : item[i + 1]);
 148         }
 149 
 150         switchToPropertiesTab(item[3]);
 151         checkSiblings("null", "null");
 152 
 153         removeItem(item[1]);
 154 
 155         switchToPropertiesTab(item[0]);
 156         checkSiblings("null", item[2]);
 157 
 158         switchToPropertiesTab(item[1]);
 159         checkSiblings("null", "null");
 160 
 161         switchToPropertiesTab(item[2]);
 162         checkSiblings(item[0], "null");
 163     }
 164 
 165     @Test(timeout = 600000)
 166     @Smoke
 167     /*
 168      * this test checks behavior of isLeaf property. Removes, adds content and
 169      * see, how this property is modified.
 170      */
 171     public void isLeafTest() {
 172         checkLeafness(ROOT_NAME, true);
 173 
 174         addElement("item1", ROOT_NAME, 0, true);
 175         checkLeafness(ROOT_NAME, false);
 176         addElement("item2", ROOT_NAME, 1, true);
 177         checkLeafness(ROOT_NAME, false);
 178         checkLeafness("item1", true);
 179         checkLeafness("item2", true);
 180         addElement("item1-1", "item1", 0, true);
 181 
 182         switchToPropertiesTab(ROOT_NAME);
 183         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, true);
 184 
 185         switchToPropertiesTab("item1");
 186         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, true);
 187 
 188         checkLeafness("item1", false);
 189         checkLeafness("item1-1", true);
 190         checkLeafness("item2", true);
 191 
 192         removeItem("item1");
 193 
 194         checkLeafness(ROOT_NAME, false);
 195         checkLeafness("item1-1", true);
 196         checkLeafness("item1", false);
 197         checkLeafness("item2", true);
 198 
 199         removeItem("item2");
 200         checkLeafness(ROOT_NAME, true);
 201         checkLeafness("item1-1", true);
 202         checkLeafness("item1", false);
 203         checkLeafness("item2", true);
 204     }
 205 
 206     @Test(timeout = 600000)
 207     @Smoke
 208     /*
 209      * This test checks behavior of parent property. It is readonly property.
 210      * This test make some actions over tree and checks state of this property
 211      * in different treeItems.
 212      */
 213     public void parentPropertyTest() {
 214         switchToPropertiesTab(ROOT_NAME);
 215         checkParent(null);
 216 
 217         addElement("item1", ROOT_NAME, 0, true);
 218         addElement("item2", "item1", 0, true);
 219 
 220         switchToPropertiesTab("item2");
 221         checkParent("item1");
 222 
 223         switchToPropertiesTab("item1");
 224         checkParent(ROOT_NAME);
 225 
 226         removeItem("item1");
 227 
 228         switchToPropertiesTab("item2");
 229         checkParent("item1");
 230 
 231         switchToPropertiesTab("item1");
 232         checkParent(null);
 233     }
 234 
 235     @Test(timeout = 600000)
 236     @Smoke
 237     /*
 238      * This test create a tree : Root -> item1 -> item2 and apply
 239      * collapsing/expanding operations over it. And observe, how
 240      * expanding/collapsing events are called for all treeItems, participating
 241      * in a tree.
 242      * When visible items are collapsed or expanded then mouse clicking is used
 243      * to test that one mouse click on disclosure node or double click on the node do the job.
 244      */
 245     public void branchExpandedAndCollapsedTest() throws InterruptedException {
 246         final String ITEM_NAME = "item1";
 247 
 248         if (!isTreeTests) {
 249             switchToPropertiesTab(TREE_DATA_COLUMN_NAME);
 250             setPropertyBySlider(SettingType.SETTER, Properties.prefWidth, 150);
 251         }
 252 
 253         addElement(ITEM_NAME, ROOT_NAME, 0, true);
 254         addElement("item2", ITEM_NAME, 0, true);
 255 
 256         checkExpandedCollapsedCounters(0, 0, 0, 0, 0, 0);
 257 
 258         switchToPropertiesTab(ITEM_NAME);
 259         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, true);
 260         checkExpandedCollapsedCounters(1, 1, 0, 0, 0, 0);
 261 
 262         //Expand the root by single click
 263         final Wrap<? extends IndexedCell> wrap = parent.lookup(IndexedCell.class,
 264                 new LookupCriteria<IndexedCell>() {
 265                     public boolean check(IndexedCell cell) {
 266                         if (ROOT_NAME.equals(cell.getText())
 267                         && cell.getStyleClass().contains("tree-cell")) {
 268                             return true;
 269                         }
 270                         if (cell.getStyleClass().contains("tree-table-row-cell")) {
 271                             Set<Node> set = cell.lookupAll(".text");
 272                             for (Node node : set) {
 273                                 if (node instanceof Text) {
 274                                     final String text = ((Text) node).getText();
 275                                     if (text != null && text.equals(ROOT_NAME)) {
 276                                         return true;
 277                                     }
 278                                 }
 279                             }
 280                         }
 281                         return false;
 282                     }
 283                 }).wrap();
 284         wrap.as(Parent.class, Node.class).lookup(new ByStyleClass("tree-disclosure-node")).wrap().mouse().click();
 285         checkExpandedCollapsedCounters(2, 1, 0, 0, 0, 0);
 286 
 287         //Collapse the item by double ckick
 288         getCellWrap(ITEM_NAME).mouse().click(2);
 289         checkExpandedCollapsedCounters(2, 1, 0, 1, 1, 0);
 290 
 291         switchToPropertiesTab(ROOT_NAME);
 292         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, false);
 293         checkExpandedCollapsedCounters(2, 1, 0, 2, 1, 0);
 294 
 295         switchToPropertiesTab(ROOT_NAME);
 296         setPropertyByToggleClick(SettingType.BIDIRECTIONAL, Properties.expanded, true);
 297         checkExpandedCollapsedCounters(3, 1, 0, 2, 1, 0);
 298 
 299         switchToPropertiesTab(ITEM_NAME);
 300         setPropertyByToggleClick(SettingType.BIDIRECTIONAL, Properties.expanded, true);
 301         checkExpandedCollapsedCounters(4, 2, 0, 2, 1, 0);
 302 
 303         switchToPropertiesTab(ROOT_NAME);
 304         setPropertyByToggleClick(SettingType.UNIDIRECTIONAL, Properties.expanded, false);
 305         checkExpandedCollapsedCounters(4, 2, 0, 3, 1, 0);
 306 
 307         switchToPropertiesTab(ITEM_NAME);
 308         setPropertyByToggleClick(SettingType.UNIDIRECTIONAL, Properties.expanded, false);
 309         checkExpandedCollapsedCounters(4, 2, 0, 4, 2, 0);
 310     }
 311 
 312     private void checkExpandedCollapsedCounters(int expRoot, int expItem1, int expItem2, int colRoot, int colItem1, int colItem2) {
 313         intermediateStateCheck();
 314         checkExpandedCounter(ROOT_NAME, expRoot);
 315         checkExpandedCounter("item1", expItem1);
 316         checkExpandedCounter("item2", expItem2);
 317         checkCollapsedCounter(ROOT_NAME, colRoot);
 318         checkCollapsedCounter("item1", colItem1);
 319         checkCollapsedCounter("item2", colItem2);
 320     }
 321 
 322     @Test(timeout = 600000)
 323     @Smoke
 324     /*
 325      * This test checks ChildrenModificationEvent. This event is about changing
 326      * of size of visible subtree. This event is about adding and removing
 327      * TreeItems in subtree.
 328      *
 329      */
 330     public void ChildrenModificationEventTest() {
 331         switchToPropertiesTab(ROOT_NAME);
 332         checkCounterValue(CHILDREN_MODIFICATION_EVENT_COUNTER, 0);
 333         intermediateStateCheck();
 334 
 335         addElement("item1", ROOT_NAME, 0, true);
 336         checkCounterValue(CHILDREN_MODIFICATION_EVENT_COUNTER, 1);
 337         switchToPropertiesTab("item1");
 338         checkCounterValue(CHILDREN_MODIFICATION_EVENT_COUNTER, 0);
 339         addElement("item1-1", "item1", 0, true);
 340         addElement("item2", ROOT_NAME, 1, true);
 341         intermediateStateCheck();
 342 
 343         switchToPropertiesTab(ROOT_NAME);
 344         checkCounterValue(CHILDREN_MODIFICATION_EVENT_COUNTER, 3);
 345         switchToPropertiesTab("item1");
 346         checkCounterValue(CHILDREN_MODIFICATION_EVENT_COUNTER, 1);
 347         switchToPropertiesTab("item1-1");
 348         checkCounterValue(CHILDREN_MODIFICATION_EVENT_COUNTER, 0);
 349         switchToPropertiesTab("item2");
 350         checkCounterValue(CHILDREN_MODIFICATION_EVENT_COUNTER, 0);
 351         intermediateStateCheck();
 352 
 353         removeItem("item1");
 354         switchToPropertiesTab(ROOT_NAME);
 355         checkCounterValue(CHILDREN_MODIFICATION_EVENT_COUNTER, 4);
 356         switchToPropertiesTab("item1");
 357         checkCounterValue(CHILDREN_MODIFICATION_EVENT_COUNTER, 1);
 358         switchToPropertiesTab("item2");
 359         checkCounterValue(CHILDREN_MODIFICATION_EVENT_COUNTER, 0);
 360         switchToPropertiesTab("item1-1");
 361         checkCounterValue(CHILDREN_MODIFICATION_EVENT_COUNTER, 0);
 362         intermediateStateCheck();
 363 
 364         switchToPropertiesTab(ROOT_NAME);
 365         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, true);
 366         removeItem("item2");
 367         switchToPropertiesTab(ROOT_NAME);
 368         checkCounterValue(CHILDREN_MODIFICATION_EVENT_COUNTER, 5);
 369         switchToPropertiesTab("item1");
 370         checkCounterValue(CHILDREN_MODIFICATION_EVENT_COUNTER, 1);
 371         switchToPropertiesTab("item2");
 372         checkCounterValue(CHILDREN_MODIFICATION_EVENT_COUNTER, 0);
 373         switchToPropertiesTab("item1-1");
 374         checkCounterValue(CHILDREN_MODIFICATION_EVENT_COUNTER, 0);
 375         intermediateStateCheck();
 376     }
 377 
 378     @Smoke
 379     @Test(timeout = 600000)
 380     /*
 381      * Graphic modification - an event, which is propagated, when graphic
 382      * property is changed. Checking of it - changing of property of some
 383      * subnode, and watching on how it is propogated to the root of the tree.
 384      */
 385     public void graphicChangedEventTest() {
 386         addElement("item1", ROOT_NAME, 0, true);
 387         addElement("item2", "item1", 0, true);
 388 
 389         checkGraphicModificationEvent(0, 0, 0);
 390 
 391         switchToPropertiesTab(ROOT_NAME);
 392         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, true);
 393         selectObjectFromChoiceBox(SettingType.SETTER, Properties.graphic, Rectangle.class);
 394         checkGraphicModificationEvent(1, 0, 0);
 395 
 396         switchToPropertiesTab("item1");
 397         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, true);
 398         selectObjectFromChoiceBox(SettingType.UNIDIRECTIONAL, Properties.graphic, Text.class);
 399         checkGraphicModificationEvent(2, 1, 0);
 400 
 401         switchToPropertiesTab("item2");
 402         selectObjectFromChoiceBox(SettingType.BIDIRECTIONAL, Properties.graphic, Group.class);
 403         checkGraphicModificationEvent(3, 2, 1);
 404 
 405         switchToPropertiesTab("item2");
 406         selectObjectFromChoiceBox(SettingType.BIDIRECTIONAL, Properties.graphic, null);
 407         checkGraphicModificationEvent(4, 3, 2);
 408     }
 409 
 410     /*
 411      * Supposed, tree hirarchy: root -> item1 -> item2;
 412      */
 413     protected void checkGraphicModificationEvent(int counterRoot, int counterItem1, int counterItem2) {
 414         intermediateStateCheck();
 415         switchToPropertiesTab(ROOT_NAME);
 416         checkCounterValue(GRAPHIC_CHANGED_EVENT_COUNTER, counterRoot);
 417         switchToPropertiesTab("item1");
 418         checkCounterValue(GRAPHIC_CHANGED_EVENT_COUNTER, counterItem1);
 419         switchToPropertiesTab("item2");
 420         checkCounterValue(GRAPHIC_CHANGED_EVENT_COUNTER, counterItem2);
 421     }
 422 
 423     @Test(timeout = 600000)
 424     @Smoke
 425     @Covers(value = {"TreeView.onEditStartProperty.SET", "TreeView.onEditCancelProperty.SET"}, level = Level.FULL)
 426     public void testOnEditStartCancel() throws Throwable {
 427         switchToPropertiesTab(isTreeTests ? "TreeView" : "TreeTableView");
 428         clickButtonForTestPurpose(SET_CELL_FACTORY_FOR_EDITING);
 429         clickButtonForTestPurpose(BTN_SET_ON_EDIT_EVENT_HANDLERS);
 430         setPropertyByToggleClick(SettingType.UNIDIRECTIONAL, Properties.editable);
 431         adjustControl();
 432 
 433         final String testItemName = "item-1-1";
 434         getControlOverTreeItem(testItemName);
 435 
 436         Wrap<Text> cellWrap = getCellWrap(testItemName);
 437 
 438         cellWrap.mouse().click();
 439         cellWrap.keyboard().pushKey(Keyboard.KeyboardButtons.F2);
 440 
 441         cellWrap.keyboard().pushKey(Keyboard.KeyboardButtons.A, Keyboard.KeyboardModifiers.CTRL_DOWN_MASK);
 442         cellWrap.keyboard().pushKey(Keyboard.KeyboardButtons.A);
 443         cellWrap.keyboard().pushKey(Keyboard.KeyboardButtons.B);
 444         cellWrap.keyboard().pushKey(Keyboard.KeyboardButtons.C);
 445 
 446         cellWrap.keyboard().pushKey(Keyboard.KeyboardButtons.ESCAPE);
 447 
 448         checkCounterValue(EDIT_START_COUNTER, 1);
 449         checkCounterValue(EDIT_CANCEL_COUNTER, 1);
 450         checkCounterValue(EDIT_COMMIT_COUNTER, 0);
 451 
 452         switchToPropertiesTab(testItemName);
 453         checkTextFieldText(Properties.value, testItemName);
 454     }
 455 
 456     @Test(timeout = 600000)
 457     @Smoke
 458     @Covers(value = "TreeView.onEditCommitProperty.SET", level = Level.FULL)
 459     public void testOnEditCommit() throws Throwable {
 460         switchToPropertiesTab(isTreeTests ? "TreeView" : "TreeTableView");
 461         clickButtonForTestPurpose(SET_CELL_FACTORY_FOR_EDITING);
 462         clickButtonForTestPurpose(BTN_SET_ON_EDIT_EVENT_HANDLERS);
 463         setPropertyByToggleClick(SettingType.UNIDIRECTIONAL, Properties.editable);
 464         adjustControl();
 465 
 466         final String testItemName = "item-1-1";
 467         getControlOverTreeItem(testItemName);
 468 
 469         Wrap<Text> cellWrap = getCellWrap(testItemName);
 470 
 471         cellWrap.mouse().click();
 472         cellWrap.keyboard().pushKey(Keyboard.KeyboardButtons.F2);
 473 
 474         cellWrap.keyboard().pushKey(Keyboard.KeyboardButtons.A, Keyboard.KeyboardModifiers.CTRL_DOWN_MASK);
 475         cellWrap.keyboard().pushKey(Keyboard.KeyboardButtons.A);
 476         cellWrap.keyboard().pushKey(Keyboard.KeyboardButtons.B);
 477         cellWrap.keyboard().pushKey(Keyboard.KeyboardButtons.C);
 478 
 479         cellWrap.keyboard().pushKey(Keyboard.KeyboardButtons.ENTER);
 480 
 481         testedControl.waitState(new State() {
 482             public Object reached() {
 483                 try {
 484                     checkCounterValue(EDIT_COMMIT_COUNTER, 1);
 485                     return 42;
 486                 } catch (TimeoutExpiredException ignored) {
 487                     return null;
 488                 }
 489             }
 490 
 491             @Override
 492             public String toString() {
 493                 return "[Commit event fired]";
 494             }
 495         });
 496 
 497         checkCounterValue(EDIT_START_COUNTER, 1);
 498         checkCounterValue(EDIT_CANCEL_COUNTER, 0);
 499         checkCounterValue(EDIT_COMMIT_COUNTER, 1);
 500 
 501         switchToPropertiesTab(testItemName);
 502         checkTextFieldText(Properties.value, "abc");
 503     }
 504 
 505     @Test(timeout = 600000)
 506     @Smoke
 507     @Covers(value = {"TreeView.onEditStartProperty.GET", "TreeView.onEditCancelProperty.GET", "TreeView.onEditCommitProperty.GET"}, level = Level.FULL)
 508     public void testOnEditOnCancelEventSequence() throws Throwable {
 509         clickButtonForTestPurpose(BTN_SET_ON_EDIT_EVENT_HANDLERS);
 510 
 511         final EventHandler onEditStart = getOnEditStart(0);
 512         final EventHandler onEditCancel = getOnEditCancel(0);
 513         final EventHandler onEditCommit = getOnEditCommit(0);
 514 
 515         assertTrue(onEditStart != null);
 516         assertTrue(onEditCancel != null);
 517         assertTrue(onEditCommit != null);
 518         assertTrue(onEditStart != onEditCancel);
 519         assertTrue(onEditStart != onEditCommit);
 520         assertTrue(onEditCancel != onEditCommit);
 521 
 522         final Map<EventHandler, Long> timestampsOfEvents = new HashMap<EventHandler, Long>();
 523 
 524         setOnEditStart(new EventHandler<Event>() {
 525             public void handle(Event t) {
 526                 timestampsOfEvents.put(onEditStart, System.nanoTime());
 527                 System.out.println("onEditStart = " + timestampsOfEvents.get(onEditStart));
 528             }
 529         }, 0);
 530         setOnEditCancel(new EventHandler<Event>() {
 531             public void handle(Event t) {
 532                 timestampsOfEvents.put(onEditCancel, System.nanoTime());
 533                 System.out.println("onEditCancel = " + timestampsOfEvents.get(onEditCancel));
 534             }
 535         }, 0);
 536         setOnEditCommit(new EventHandler<Event>() {
 537             public void handle(Event t) {
 538                 timestampsOfEvents.put(onEditCommit, System.nanoTime());
 539                 System.out.println("onEditCommit = " + timestampsOfEvents.get(onEditCommit));
 540             }
 541         }, 0);
 542 
 543         switchToPropertiesTab(isTreeTests ? TreeViewNewApp.TREE_VIEW_TAB_NAME : TREE_TABLE_VIEW_TAB_NAME);
 544         setPropertyByToggleClick(SettingType.UNIDIRECTIONAL, Properties.editable);
 545         clickButtonForTestPurpose(SET_CELL_FACTORY_FOR_EDITING);
 546         adjustControl();
 547 
 548         Wrap<Text> cellWrap = getCellWrap("item-1-1");
 549         cellWrap.mouse().click();
 550         cellWrap.keyboard().pushKey(Keyboard.KeyboardButtons.F2);
 551         cellWrap.keyboard().pushKey(Keyboard.KeyboardButtons.A, Keyboard.KeyboardModifiers.SHIFT_DOWN_MASK);
 552         cellWrap.keyboard().pushKey(Keyboard.KeyboardButtons.B);
 553         cellWrap.keyboard().pushKey(Keyboard.KeyboardButtons.C, Keyboard.KeyboardModifiers.SHIFT_DOWN_MASK);
 554 
 555         cellWrap.keyboard().pushKey(Keyboard.KeyboardButtons.ESCAPE);
 556 
 557         testedControl.waitState(new State<Boolean>() {
 558             public Boolean reached() {
 559                 return null != timestampsOfEvents.get(onEditCancel);
 560             }
 561 
 562             @Override
 563             public String toString() {
 564                 return "[Cancel event fired]";
 565             }
 566         });
 567 
 568         System.out.println("Finally:");
 569         System.out.println("onEditStart = " + timestampsOfEvents.get(onEditStart));
 570         System.out.println("onEditCommit = " + timestampsOfEvents.get(onEditCommit));
 571         System.out.println("onEditCancel = " + timestampsOfEvents.get(onEditCancel));
 572 
 573         assertEquals(null, timestampsOfEvents.get(onEditCommit));
 574         assertTrue(timestampsOfEvents.get(onEditStart) <= timestampsOfEvents.get(onEditCancel));
 575     }
 576 
 577     @Test(timeout = 600000)
 578     @Smoke
 579     public void testOnEditOnCommitEventSequence() throws Throwable {
 580         clickButtonForTestPurpose(BTN_SET_ON_EDIT_EVENT_HANDLERS);
 581 
 582         final EventHandler onEditStart = getOnEditStart(0);
 583         final EventHandler onEditCancel = getOnEditCancel(0);
 584         final EventHandler onEditCommit = getOnEditCommit(0);
 585 
 586         final Map<EventHandler, Long> timestampsOfEvents = new HashMap<EventHandler, Long>();
 587 
 588         setOnEditStart(new EventHandler<Event>() {
 589             public void handle(Event t) {
 590                 timestampsOfEvents.put(onEditStart, System.nanoTime());
 591                 System.out.println("onEditStart = " + timestampsOfEvents.get(onEditStart));
 592             }
 593         }, 0);
 594         setOnEditCancel(new EventHandler<Event>() {
 595             public void handle(Event t) {
 596                 timestampsOfEvents.put(onEditCancel, System.nanoTime());
 597                 System.out.println("onEditCancel = " + timestampsOfEvents.get(onEditCancel));
 598             }
 599         }, 0);
 600         setOnEditCommit(new EventHandler<Event>() {
 601             public void handle(Event t) {
 602                 timestampsOfEvents.put(onEditCommit, System.nanoTime());
 603                 System.out.println("onEditCommit = " + timestampsOfEvents.get(onEditCommit));
 604             }
 605         }, 0);
 606 
 607         switchToPropertiesTab(isTreeTests ? TreeViewNewApp.TREE_VIEW_TAB_NAME : TREE_TABLE_VIEW_TAB_NAME);
 608         setPropertyByToggleClick(SettingType.UNIDIRECTIONAL, Properties.editable);
 609         clickButtonForTestPurpose(SET_CELL_FACTORY_FOR_EDITING);
 610         adjustControl();
 611         if (!isTreeTests) {
 612             switchToPropertiesTab(TREE_DATA_COLUMN_NAME);
 613             setPropertyBySlider(SettingType.SETTER, Properties.prefWidth, 150);
 614 
 615         }
 616 
 617         if (isTreeTests) {
 618             final String testItemName = "item-1-1";
 619             Wrap<Text> cellWrap = getCellWrap(testItemName);
 620 
 621             cellWrap.mouse().click();
 622             cellWrap.keyboard().pushKey(Keyboard.KeyboardButtons.F2);
 623             cellWrap.keyboard().pushKey(Keyboard.KeyboardButtons.A, Keyboard.KeyboardModifiers.SHIFT_DOWN_MASK);
 624             cellWrap.keyboard().pushKey(Keyboard.KeyboardButtons.B);
 625             cellWrap.keyboard().pushKey(Keyboard.KeyboardButtons.C, Keyboard.KeyboardModifiers.SHIFT_DOWN_MASK);
 626 
 627             cellWrap.keyboard().pushKey(Keyboard.KeyboardButtons.ENTER);
 628         } else {
 629             ((TreeTableViewWrap) testedControl).asTable(Object.class).setEditor(new TextFieldCellEditor());
 630             new TreeTableCellDock(((TreeTableViewWrap) testedControl).asTable(Object.class), 0, 8).asEditableCell().edit("ABC");
 631         }
 632 
 633         testedControl.waitState(new State<Boolean>() {
 634             public Boolean reached() {
 635                 return null != timestampsOfEvents.get(onEditCommit);
 636             }
 637 
 638             @Override
 639             public String toString() {
 640                 return "[Commit event fired]";
 641             }
 642         });
 643 
 644         System.out.println("Finally:");
 645         System.out.println("onEditStart = " + timestampsOfEvents.get(onEditStart));
 646         System.out.println("onEditCommit = " + timestampsOfEvents.get(onEditCommit));
 647         System.out.println("onEditCancel = " + timestampsOfEvents.get(onEditCancel));
 648 
 649         assertEquals(null, timestampsOfEvents.get(onEditCancel));
 650         assertTrue(timestampsOfEvents.get(onEditStart) <= timestampsOfEvents.get(onEditCommit));
 651     }
 652 
 653     @Smoke
 654     @Test(timeout = 600000)
 655     /*
 656      * This test checks working of scrollTo method of TreeView. Checks behavior,
 657      * when too big and negative values are used as paramteres, checks, that
 658      * scrolling is done correctly, and item is visible and correctly positioned.
 659      */
 660     public void scrollToTest() throws InterruptedException {
 661         int size = 21;
 662         adjustControl();
 663 
 664         scrollTo(size);
 665         checkScrollingState(1, false, true, size);
 666 
 667         scrollTo(0);
 668         checkScrollingState(0, true, false, size);
 669 
 670         scrollTo(size - 1);
 671         checkScrollingState(1, false, true, size);
 672 
 673         scrollTo(-1);
 674         checkScrollingState(0, true, false, size);
 675         intermediateStateCheck();
 676 
 677         scrollTo(size + 1);
 678         checkScrollingState(1, false, true, size);
 679 
 680         scrollTo(0);
 681         checkScrollingState(0, true, false, size);
 682 
 683         scrollTo(size * 2);
 684         checkScrollingState(1, false, true, size);
 685         intermediateStateCheck();
 686 
 687         scrollTo(-size);
 688         checkScrollingState(0, true, false, size);
 689 
 690         scrollTo(10);
 691         Wrap<Text> cellWrap = getCellWrap(10);
 692         org.jemmy.Rectangle cellRect = cellWrap.getScreenBounds();
 693         org.jemmy.Rectangle control = testedControl.getScreenBounds();
 694         if (isTreeTests) {
 695             assertEquals(cellRect.getY(), control.getY(), 2);
 696         } else {
 697             assertEquals(cellRect.getY(), control.getY() + testedControl.as(Parent.class, Node.class).lookup(TableHeaderRow.class).wrap().getScreenBounds().getHeight(), 2);
 698         }
 699     }
 700 
 701     @Smoke
 702     @Test(timeout = 600000)
 703     /**
 704      * This test checks the valueChangedEvent() of a tree item. When the value
 705      * of a leaf is changed the event should be fired for each item from the
 706      * leaf up to the root.
 707      */
 708     public void treeItemValueChangedEvent() throws Throwable {
 709         //Populate tree view
 710         final String parentItem = "item1";
 711         final String childItem = "item1-1";
 712         addElement(parentItem, ROOT_NAME, 0, true);
 713         addElement(childItem, parentItem, 0, true);
 714 
 715         //Add second branch which should't get any events
 716         final String item2 = "item2";
 717         final String item2_1 = "item2-1";
 718         addElement(item2, ROOT_NAME, 0, true);
 719         addElement(item2_1, item2, 0, true);
 720 
 721         //Enable editing in the tree view
 722         switchToPropertiesTab(isTreeTests ? "TreeView" : "TreeTableView");
 723         setPropertyByToggleClick(SettingType.UNIDIRECTIONAL, Properties.editable);
 724         clickButtonForTestPurpose(SET_CELL_FACTORY_FOR_EDITING);
 725 
 726         //Change child's value
 727         final String newValue = "qwerty";
 728         switchToPropertiesTab(childItem);
 729         setText(parent.lookup(TextField.class, new ByID(NEW_VALUE_TEXT_FIELD_ID)).wrap(), newValue);
 730         clickButtonForTestPurpose(CHANGE_VALUE_BUTTON_ID);
 731 
 732         //Check that event was fired for every item only once
 733         switchToPropertiesTab(ROOT_NAME);
 734         checkCounterValue(VALUE_CHANGED_EVENT_COUNTER, 1);
 735         switchToPropertiesTab(parentItem);
 736         checkCounterValue(VALUE_CHANGED_EVENT_COUNTER, 1);
 737         switchToPropertiesTab(childItem);
 738         checkCounterValue(VALUE_CHANGED_EVENT_COUNTER, 1);
 739 
 740         //Check that second branch hasn't received any events
 741         switchToPropertiesTab(item2);
 742         checkCounterValue(VALUE_CHANGED_EVENT_COUNTER, 0);
 743         switchToPropertiesTab(item2_1);
 744         checkCounterValue(VALUE_CHANGED_EVENT_COUNTER, 0);
 745     }
 746 
 747     @Test
 748     /**
 749      * Checks selection of items into treeView, if selection was done, so that
 750      * selection begin is on one side, and selection end is on the another side,
 751      * relative to the collapsed node.
 752      */
 753     public void selectionCorrectnessOnCollapsing1Test() {
 754         adjustControl();
 755         switchOnMultiple();
 756         selectionHelper.setMultiple(true);
 757         clickOnFirstCell();
 758 
 759         keyboardCheck(KeyboardButtons.DOWN);
 760 
 761         for (int i = 0; i < 11; i++) {
 762             keyboardCheck(KeyboardButtons.DOWN, KeyboardModifiers.SHIFT_DOWN_MASK);
 763         }
 764 
 765         switchToPropertiesTab("item-1");
 766         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, false);
 767         modifySelectionHelper("item-1", false);
 768 
 769         checkSelection();
 770         intermediateStateCheck();
 771     }
 772 
 773     @Test
 774     /**
 775      * Checks, that selection is correctly set, focus and anchor behavior, if
 776      * selection done in the way, so that the first selected item, and anchor on
 777      * it is on the collapsed item.
 778      */
 779     public void selectionCorrectnessOnCollapsing2Test() {
 780         adjustControl();
 781         switchOnMultiple();
 782         selectionHelper.setMultiple(true);
 783         clickOnFirstCell();
 784 
 785         for (int i = 0; i < 3; i++) {
 786             keyboardCheck(KeyboardButtons.DOWN);
 787         }
 788 
 789         for (int i = 0; i < 5; i++) {
 790             keyboardCheck(KeyboardButtons.DOWN, KeyboardModifiers.SHIFT_DOWN_MASK);
 791         }
 792 
 793         switchToPropertiesTab("item-0");
 794         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, false);
 795         modifySelectionHelper("item-0", false);
 796 
 797         checkSelection();
 798         intermediateStateCheck();
 799     }
 800 
 801     @Test
 802     /**
 803      * Checks selection correct preserving, focus and anchor behavior, if the
 804      * selection is done is the way, so that the last selected item, and focus
 805      * on it - is the collapsed item.
 806      */
 807     public void selectionCorrectnessOnCollapsing3Test() {
 808         adjustControl();
 809         switchOnMultiple();
 810         selectionHelper.setMultiple(true);
 811         clickOnFirstCell();
 812 
 813         for (int i = 0; i < 3; i++) {
 814             keyboardCheck(KeyboardButtons.DOWN);
 815         }
 816 
 817         for (int i = 0; i < 5; i++) {
 818             keyboardCheck(KeyboardButtons.DOWN, KeyboardModifiers.SHIFT_DOWN_MASK);
 819         }
 820 
 821         switchToPropertiesTab("item-1");
 822         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, false);
 823         modifySelectionHelper("item-1", false);
 824 
 825         checkSelection();
 826         intermediateStateCheck();
 827     }
 828 
 829     @Test
 830     /**
 831      * Checks situation with focus behavior, when some item is collapsed under
 832      * focus.
 833      */
 834     public void selectionCorrectnessOnCollapsing4Test() {
 835         adjustControl();
 836         switchOnMultiple();
 837         selectionHelper.setMultiple(true);
 838         clickOnFirstCell();
 839 
 840         keyboardCheck(KeyboardButtons.DOWN);
 841 
 842         switchToPropertiesTab("item-0");
 843         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, false);
 844         modifySelectionHelper("item-0", false);
 845         checkSelection();
 846 
 847         keyboardCheck(KeyboardButtons.DOWN);
 848 
 849         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, true);
 850         modifySelectionHelper("item-0", true);
 851         checkSelection();
 852         intermediateStateCheck();
 853     }
 854 
 855     @Test
 856     /**
 857      * Checks situation with focus, anchor and selection, when they are inside
 858      * the collapsed branch.
 859      */
 860     public void selectionCorrectnessOnCollapsing5Test() {
 861         adjustControl();
 862         switchOnMultiple();
 863         selectionHelper.setMultiple(true);
 864         clickOnFirstCell();
 865 
 866         for (int i = 0; i < 3; i++) {
 867             keyboardCheck(KeyboardButtons.DOWN);
 868         }
 869 
 870         for (int i = 0; i < 2; i++) {
 871             keyboardCheck(KeyboardButtons.DOWN, KeyboardModifiers.SHIFT_DOWN_MASK);
 872         }
 873 
 874         switchToPropertiesTab("item-0");
 875         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, false);
 876         modifySelectionHelper("item-0", false);
 877         checkSelection();
 878         intermediateStateCheck();
 879     }
 880 
 881     @Test
 882     /**
 883      * Checks situation with focus, anchor and selection, when they are inside
 884      * the collapsed branch, and multi line jump is needed.
 885      */
 886     public void multilevelJumpOnCollapsingTest() throws InterruptedException {
 887         if (isTreeTests) {
 888             switchToPropertiesTab("TreeView");
 889         } else {
 890             switchToPropertiesTab("TreeTableView");
 891         }
 892         setSize(200, 200);
 893 
 894         for (int i = 0; i < 2; i++) {
 895             addElement("item-" + String.valueOf(i), ROOT_NAME, i);
 896             for (int j = 0; j < 2; j++) {
 897                 addElement("item-" + String.valueOf(i) + "-" + String.valueOf(j), "item-" + String.valueOf(i), j);
 898                 for (int k = 0; k < 2; k++) {
 899                     addElement("item-" + String.valueOf(i) + "-" + String.valueOf(j) + "-" + String.valueOf(k), "item-" + String.valueOf(i) + "-" + String.valueOf(j), k);
 900                 }
 901             }
 902         }
 903         switchToPropertiesTab(ROOT_NAME);
 904         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, true);
 905 
 906         expand("item-1");
 907         expand("item-1-0");
 908         expand("item-1-0-0");
 909         expand("item-1-0-1");
 910 
 911         switchOnMultiple();
 912         selectionHelper.setMultiple(true);
 913         clickOnFirstCell();
 914 
 915         for (int i = 0; i < 4; i++) {
 916             keyboardCheck(KeyboardButtons.DOWN);
 917         }
 918 
 919         keyboardCheck(KeyboardButtons.DOWN, KeyboardModifiers.SHIFT_DOWN_MASK);
 920 
 921         switchToPropertiesTab("item-1");
 922         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, false);
 923         modifySelectionHelper("item-1", false);
 924         checkSelection();
 925         intermediateStateCheck();
 926     }
 927 
 928     private void expand(String name) {
 929         getControlOverTreeItem(name);
 930         switchToPropertiesTab(name);
 931         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, true);
 932     }
 933 
 934     @Test()
 935     /**
 936      * Checks situation with focus, selection and anchor, in case of
 937      * discontinuous selection, so that wrap between the selected parts is on
 938      * the item, which will be collapsed.
 939      */
 940     public void selectionCorrectnessOnCollapsing6Test() {
 941         adjustControl();
 942         switchOnMultiple();
 943         selectionHelper.setMultiple(true);
 944         clickOnFirstCell();
 945 
 946         for (int i = 0; i < 2; i++) {
 947             keyboardCheck(KeyboardButtons.DOWN);
 948         }
 949 
 950         for (int i = 0; i < 2; i++) {
 951             keyboardCheck(KeyboardButtons.DOWN, KeyboardModifiers.SHIFT_DOWN_MASK);
 952         }
 953 
 954         for (int i = 0; i < 10; i++) {
 955             keyboardCheck(KeyboardButtons.DOWN, CTRL_DOWN_MASK_OS);
 956         }
 957 
 958         keyboardCheck(KeyboardButtons.SPACE, CTRL_DOWN_MASK_OS);
 959 
 960         for (int i = 0; i < 2; i++) {
 961             keyboardCheck(KeyboardButtons.DOWN, KeyboardModifiers.SHIFT_DOWN_MASK, CTRL_DOWN_MASK_OS);
 962         }
 963 
 964         switchToPropertiesTab("item-1");
 965         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, false);
 966         modifySelectionHelper("item-1", false);
 967 
 968         checkSelection();
 969         intermediateStateCheck();
 970     }
 971 
 972     @Test
 973     /**
 974      * Check focus, anchor and selection, when ctrlA was applied and some item
 975      * was collapsed after it.
 976      */
 977     public void selectionCorrectnessOnCollapsingCtrlATest() {
 978         adjustControl();
 979         switchOnMultiple();
 980         selectionHelper.setMultiple(true);
 981         clickOnFirstCell();
 982 
 983         for (int i = 0; i < 3; i++) {
 984             keyboardCheck(KeyboardButtons.DOWN);
 985         }
 986 
 987         for (int i = 0; i < 15; i++) {
 988             keyboardCheck(KeyboardButtons.DOWN, KeyboardModifiers.SHIFT_DOWN_MASK);
 989         }
 990 
 991         testedControl.keyboard().pushKey(KeyboardButtons.A, CTRL_DOWN_MASK_OS);
 992         selectionHelper.ctrlA = true;
 993 
 994         switchToPropertiesTab("item-1");
 995         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, false);
 996         modifySelectionHelper("item-1", false);
 997 
 998         checkSelection();
 999         intermediateStateCheck();
1000     }
1001 
1002     @Test
1003     /**
1004      * Checks selection, focus and anchor, when some range will be selected, so
1005      * that expanded item will be inside this range.
1006      */
1007     public void selectionCorrectnessOnExpanding1Test() {
1008         if (!isTreeTests) {
1009             TreeViewCommonFunctionality.setCheckFocus(false);
1010         }
1011         adjustControl();
1012         switchOnMultiple();
1013         selectionHelper.setMultiple(true);
1014 
1015         switchToPropertiesTab("item-1");
1016         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, false);
1017 
1018         clickOnFirstCell();
1019 
1020         keyboardCheck(KeyboardButtons.DOWN);
1021 
1022         for (int i = 0; i < 13; i++) {
1023             keyboardCheck(KeyboardButtons.DOWN, KeyboardModifiers.SHIFT_DOWN_MASK);
1024         }
1025 
1026         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, true);
1027         modifySelectionHelper("item-1", true);
1028 
1029         //We don't check focus for this case, as we don't follow it.
1030         TreeViewCommonFunctionality.setCheckFocus(false);
1031 
1032         checkSelection();
1033         intermediateStateCheck();
1034     }
1035 
1036     @Test
1037     /**
1038      * Checks behavior of selection, focus and anchor if selection starts (and
1039      * anchor is) on the item, which will be expanded.
1040      */
1041     public void selectionCorrectnessOnExpanding2Test() {
1042         if (!isTreeTests) {
1043             TreeViewCommonFunctionality.setCheckFocus(false);
1044         }
1045         adjustControl();
1046         switchOnMultiple();
1047         selectionHelper.setMultiple(true);
1048 
1049         switchToPropertiesTab("item-0");
1050         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, false);
1051 
1052         clickOnFirstCell();
1053 
1054         keyboardCheck(KeyboardButtons.DOWN);
1055 
1056         for (int i = 0; i < 3; i++) {
1057             keyboardCheck(KeyboardButtons.DOWN, KeyboardModifiers.SHIFT_DOWN_MASK);
1058         }
1059 
1060         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, true);
1061         modifySelectionHelper("item-0", true);
1062 
1063         checkSelection();
1064         intermediateStateCheck();
1065     }
1066 
1067     @Test
1068     /**
1069      * Checks selection, focus and anchor, if selection ends (and focus is) on
1070      * the item, which will be expanded.
1071      */
1072     public void selectionCorrectnessOnExpanding3Test() {
1073         adjustControl();
1074         switchOnMultiple();
1075         selectionHelper.setMultiple(true);
1076 
1077         switchToPropertiesTab("item-1");
1078         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, false);
1079 
1080         clickOnFirstCell();
1081 
1082         for (int i = 0; i < 6; i++) {
1083             keyboardCheck(KeyboardButtons.DOWN, KeyboardModifiers.SHIFT_DOWN_MASK);
1084         }
1085 
1086         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, true);
1087         modifySelectionHelper("item-1", true);
1088 
1089         checkSelection();
1090         intermediateStateCheck();
1091     }
1092 
1093     @Test
1094     /**
1095      * Checks behavior of focus, anchor and selection, when focus is on the
1096      * item, which will be expanded.
1097      */
1098     public void selectionCorrectnessOnExpanding4Test() {
1099         adjustControl();
1100         switchOnMultiple();
1101         selectionHelper.setMultiple(true);
1102 
1103         switchToPropertiesTab("item-1");
1104         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, false);
1105 
1106         clickOnFirstCell();
1107 
1108         for (int i = 0; i < 6; i++) {
1109             keyboardCheck(KeyboardButtons.DOWN);
1110         }
1111 
1112         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, true);
1113         modifySelectionHelper("item-1", true);
1114 
1115         checkSelection();
1116         intermediateStateCheck();
1117     }
1118 
1119     @Test
1120     /**
1121      * Checks selection, focus and anchor for the case if discontinuous
1122      * selection, when wrap in selection contains item, which will be expanded.
1123      */
1124     public void selectionCorrectnessOnExpanding5Test() {
1125         adjustControl();
1126         switchOnMultiple();
1127         selectionHelper.setMultiple(true);
1128 
1129         switchToPropertiesTab("item-1");
1130         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, false);
1131 
1132         clickOnFirstCell();
1133 
1134         for (int i = 0; i < 2; i++) {
1135             keyboardCheck(KeyboardButtons.DOWN);
1136         }
1137 
1138         for (int i = 0; i < 2; i++) {
1139             keyboardCheck(KeyboardButtons.DOWN, KeyboardModifiers.SHIFT_DOWN_MASK);
1140         }
1141 
1142         for (int i = 0; i < 10; i++) {
1143             keyboardCheck(KeyboardButtons.DOWN, CTRL_DOWN_MASK_OS);
1144         }
1145 
1146         keyboardCheck(KeyboardButtons.SPACE, CTRL_DOWN_MASK_OS);
1147 
1148         for (int i = 0; i < 2; i++) {
1149             keyboardCheck(KeyboardButtons.DOWN, KeyboardModifiers.SHIFT_DOWN_MASK, CTRL_DOWN_MASK_OS);
1150         }
1151 
1152         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, true);
1153         modifySelectionHelper("item-1", true);
1154 
1155         checkSelection();
1156         intermediateStateCheck();
1157     }
1158 
1159     @Test
1160     /**
1161      * Checks selection, focus and anchor, if some item is expanded, when ctrlA
1162      * had been applied just before expansion.
1163      */
1164     public void selectionCorrectnessOnExpandingCtrlATest() {
1165         adjustControl();
1166         switchOnMultiple();
1167         selectionHelper.setMultiple(true);
1168 
1169         switchToPropertiesTab("item-1");
1170         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, false);
1171         selectionHelper.rows = selectionHelper.rows - 4;
1172 
1173         clickOnFirstCell();
1174 
1175         for (int i = 0; i < 3; i++) {
1176             keyboardCheck(KeyboardButtons.DOWN);
1177         }
1178 
1179         for (int i = 0; i < 15; i++) {
1180             keyboardCheck(KeyboardButtons.DOWN, KeyboardModifiers.SHIFT_DOWN_MASK);
1181         }
1182 
1183         selectionHelper.rows = selectionHelper.rows + 4;
1184         testedControl.keyboard().pushKey(KeyboardButtons.A, CTRL_DOWN_MASK_OS);
1185         selectionHelper.ctrlA = true;
1186 
1187         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, true);
1188         modifySelectionHelper("item-1", true);
1189 
1190         checkSelection();
1191         intermediateStateCheck();
1192     }
1193 
1194     /**
1195      * Checks that when the sorting is applied to the underlying data collection
1196      * the cells are rendered in the right order.
1197      */
1198     @Smoke
1199     @Test(timeout = 120000)
1200     public void renderingAfterSortingTest() throws Throwable {
1201         adjustControl();
1202 
1203         final int ITEMS_COUNT = 7;
1204 
1205         StringConverter<TreeItem<String>> conv = new StringConverter<TreeItem<String>>() {
1206             @Override
1207             public String toString(TreeItem<String> t) {
1208                 return t.getValue();
1209             }
1210 
1211             @Override
1212             public TreeItem fromString(String s) {
1213                 return new TreeItem(s);
1214             }
1215         };
1216 
1217         final Comparator<TreeItem<String>> comp = new Comparator<TreeItem<String>>() {
1218             public int compare(TreeItem<String> t1, TreeItem<String> t2) {
1219                 return t1.getValue().compareTo(t2.getValue());
1220             }
1221         };
1222 
1223         SortValidator<TreeItem<String>, TreeCell> validator = new SortValidator<TreeItem<String>, TreeCell>(ITEMS_COUNT, conv, comp) {
1224             @Override
1225             protected void setControlData(final ObservableList<TreeItem<String>> ls) {
1226                 new GetAction<Object>() {
1227                     @Override
1228                     public void run(Object... parameters) throws Exception {
1229                         TreeView tv = (TreeView) testedControl.getControl();
1230                         tv.getRoot().getChildren().setAll(ls);
1231                     }
1232                 }.dispatch(testedControl.getEnvironment());
1233             }
1234 
1235             @Override
1236             protected Lookup<? extends TreeCell> getCellsLookup() {
1237                 return testedControl.as(Parent.class, Node.class).lookup(TreeCell.class, new LookupCriteria<TreeCell>() {
1238                     public boolean check(TreeCell cell) {
1239                         return !"ROOT".equals(cell.getText()) && cell.isVisible();
1240                     }
1241                 });
1242             }
1243 
1244             @Override
1245             protected String getTextFromCell(TreeCell cell) {
1246                 return cell.getText();
1247             }
1248 
1249             @Override
1250             protected void sort() {
1251                 new GetAction<Object>() {
1252                     @Override
1253                     public void run(Object... parameters) throws Exception {
1254                         TreeView tv = (TreeView) testedControl.getControl();
1255                         FXCollections.sort(tv.getRoot().getChildren(), comp);
1256                     }
1257                 }.dispatch(testedControl.getEnvironment());
1258             }
1259         };
1260 
1261         boolean result = validator.check();
1262         String msg = validator.getFailureReason();
1263         assertTrue(msg, result);
1264     }
1265 
1266     /**
1267      * Check that after hiding the root item text in other items will be shifted
1268      * to the left and aligned correctly.
1269      */
1270     @Test(timeout = 120000)
1271     public void testTextAlignmentAfterHidingRoot() throws InterruptedException {
1272         adjustControl();
1273 
1274         if (!isTreeTests) {
1275             switchToPropertiesTab(TREE_DATA_COLUMN_NAME);
1276             setPropertyBySlider(SettingType.SETTER, Properties.prefWidth, 150);
1277         }
1278 
1279         final Wrap<Text> root = getCellWrap(ROOT_NAME);
1280         final ObjectProperty<org.jemmy.Rectangle> rootText
1281                 = new SimpleObjectProperty(root.as(Parent.class, Node.class).lookup(Text.class).wrap().getScreenBounds());
1282 
1283         Wrap<Text> firstItem = getCellWrap("item-1");
1284         final ObjectProperty<org.jemmy.Rectangle> text
1285                 = new SimpleObjectProperty(firstItem.as(Parent.class, Node.class).lookup(Text.class).wrap().getScreenBounds());
1286 
1287         final IntegerProperty delta = new SimpleIntegerProperty();
1288 
1289         testedControl.waitState(new State<Boolean>() {
1290             public Boolean reached() {
1291                 delta.set(text.get().x - rootText.get().x);
1292                 if (delta.get() > 0) {
1293                     return true;
1294                 } else {
1295                     System.out.println(delta.get());
1296                     return null;
1297                 }
1298             }
1299         });
1300 
1301         setPropertyByToggleClick(SettingType.SETTER, Properties.showRoot, Boolean.valueOf(false));
1302 
1303         text.set(getCellWrap("item-1").as(Parent.class, Node.class).lookup(Text.class).wrap().getScreenBounds());
1304         testedControl.waitState(new State<Boolean>() {
1305             int rootX, textX;
1306 
1307             public Boolean reached() {
1308                 return ((rootX = rootText.get().x) == (textX = text.get().x)) ? true : null;
1309             }
1310 
1311             @Override
1312             public String toString() {
1313                 return String.format("[Expected equal. Root x:%d Text x:%d]", rootX, textX);
1314             }
1315         });
1316 
1317         setPropertyByToggleClick(SettingType.SETTER, Properties.showRoot, Boolean.valueOf(true));
1318 
1319         rootText.set(root.as(Parent.class, Node.class).lookup(Text.class).wrap().getScreenBounds());
1320 
1321         testedControl.waitState(new State<Boolean>() {
1322             public Boolean reached() {
1323                 if ((rootText.get().x == rootText.get().x)
1324                         && (rootText.get().x - rootText.get().x < delta.get())) {
1325                     return true;
1326                 } else {
1327                     return null;
1328                 }
1329             }
1330         });
1331     }
1332 
1333     /**
1334      * Checks text alignment when graphic is added to the tree i. Test compares
1335      * coordinates of three nodes: disclosure node, graphic and text.
1336      */
1337     @Test(timeout = 120000)
1338     public void graphicsPropertyTest() throws InterruptedException {
1339         final String ITEM_TEXT = "item-0";
1340         final int RADIUS = 6;
1341         final int SIZE = 15;
1342 
1343         if (!isTreeTests) {
1344             switchToPropertiesTab(TREE_DATA_COLUMN_NAME);
1345             setPropertyBySlider(SettingType.SETTER, Properties.prefWidth, 150);
1346         }
1347 
1348         adjustControl();
1349         switchToPropertiesTab(ITEM_TEXT);
1350         Wrap<? extends IndexedCell> cellWrap = getIndexedCellWrap(ITEM_TEXT);
1351         Parent cellAsParent = cellWrap.as(Parent.class, Node.class);
1352 
1353         org.jemmy.Rectangle textRectInitial = cellAsParent.lookup(Text.class).wrap().getScreenBounds();
1354         org.jemmy.Rectangle arrowBoundsInitial = getDisclosureNode(cellWrap).getScreenBounds();
1355         assertTrue("[Initial state corrupted]", arrowBoundsInitial.x + arrowBoundsInitial.width <= textRectInitial.x);
1356 
1357         selectObjectFromChoiceBox(SettingType.SETTER, Properties.graphic, Circle.class);
1358         testedControl.waitState(new State() {
1359 
1360             public Object reached() {
1361                 if (1 != levelWrapUp(getIndexedCellWrap(ITEM_TEXT)).as(Parent.class, Node.class).lookup(Circle.class).size()) {
1362                     return null;
1363                 } else {
1364                     return true;
1365                 }
1366             }
1367         });
1368 
1369         Result res = checkCellChildNodes(arrowBoundsInitial, getDisclosureNode(cellWrap).getScreenBounds(),
1370                 textRectInitial, cellAsParent.lookup(Text.class).wrap().getScreenBounds(),
1371                 2 * RADIUS, levelWrapUp(cellWrap).as(Parent.class, Node.class).lookup(Circle.class).wrap().getScreenBounds());
1372 
1373         assertTrue(res.msg, res.value);
1374 
1375         selectObjectFromChoiceBox(SettingType.UNIDIRECTIONAL, Properties.graphic, Polygon.class);
1376 
1377         testedControl.waitState(new State() {
1378 
1379             public Object reached() {
1380                 if (1 != levelWrapUp(getIndexedCellWrap(ITEM_TEXT)).as(Parent.class, Node.class).lookup(Polygon.class).size()) {
1381                     return null;
1382                 } else {
1383                     return true;
1384                 }
1385             }
1386         });
1387 
1388         cellWrap = getIndexedCellWrap(ITEM_TEXT);
1389         cellAsParent = cellWrap.as(Parent.class, Node.class);
1390         res = checkCellChildNodes(arrowBoundsInitial, getDisclosureNode(cellWrap).getScreenBounds(),
1391                 textRectInitial, cellAsParent.lookup(Text.class).wrap().getScreenBounds(),
1392                 SIZE, levelWrapUp(cellWrap).as(Parent.class, Node.class).lookup(Polygon.class).wrap().getScreenBounds());
1393         assertTrue(res.msg, res.value);
1394 
1395         setPropertyByToggleClick(SettingType.BIDIRECTIONAL, Properties.expanded, false);
1396         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, true);
1397 
1398         testedControl.waitState(new State() {
1399 
1400             public Object reached() {
1401                 if (1 != levelWrapUp(getIndexedCellWrap(ITEM_TEXT)).as(Parent.class, Node.class).lookup(Polygon.class).size()) {
1402                     return null;
1403                 } else {
1404                     return true;
1405                 }
1406             }
1407         });
1408 
1409         cellWrap = getIndexedCellWrap(ITEM_TEXT);
1410         cellAsParent = cellWrap.as(Parent.class, Node.class);
1411         res = checkCellChildNodes(arrowBoundsInitial, getDisclosureNode(cellWrap).getScreenBounds(),
1412                 textRectInitial, cellAsParent.lookup(Text.class).wrap().getScreenBounds(),
1413                 2 * RADIUS, levelWrapUp(cellWrap).as(Parent.class, Node.class).lookup(Polygon.class).wrap().getScreenBounds());
1414         assertTrue(res.msg, res.value);
1415     }
1416 
1417     /**
1418      * Check that the control is rendered properly when tree item children are
1419      * modified.
1420      */
1421     @Test
1422     public void childrenModificationImmediateRenderingTest() {
1423 
1424         if (!isTreeTests) {
1425             switchToPropertiesTab(TREE_DATA_COLUMN_NAME);
1426             try {
1427                 setPropertyBySlider(SettingType.SETTER, Properties.prefWidth, 90);
1428             } catch (InterruptedException ex) {
1429                 Logger.getLogger(TreeViewTest.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
1430             }
1431         }
1432 
1433         final String PARENT_NAME = "parent";
1434         final LookupCriteria<IndexedCell> lookupCriterion = new LookupCriteria<IndexedCell>() {
1435             public boolean check(IndexedCell cell) {
1436                 return (cell.getStyleClass().contains("tree-table-cell") || cell.getStyleClass().contains("tree-cell"))
1437                         && null != cell.getText()
1438                         && cell.getText().length() > 4
1439                         && "item".equals(cell.getText().substring(0, 4));
1440             }
1441         };
1442         final State<Integer> state = new State<Integer>() {
1443             public Integer reached() {
1444                 return Integer.valueOf(parent.lookup(IndexedCell.class, lookupCriterion).size());
1445             }
1446 
1447             @Override
1448             public String toString() {
1449                 return "[Expected number of cells]";
1450             }
1451         };
1452 
1453         addElement(PARENT_NAME, ROOT_NAME, 0, true);
1454         switchToPropertiesTab(ROOT_NAME);
1455         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, true);
1456         switchToPropertiesTab(PARENT_NAME);
1457         setPropertyByToggleClick(SettingType.SETTER, Properties.expanded, true);
1458 
1459         addElement("item0", PARENT_NAME, 0);
1460         addElement("item1", PARENT_NAME, 1);
1461         testedControl.waitState(state, Integer.valueOf(2));
1462 
1463         addElement("item2", PARENT_NAME, 2);
1464         testedControl.waitState(state, Integer.valueOf(3));
1465 
1466         removeItem("item0");
1467         removeItem("item1");
1468         testedControl.waitState(state, Integer.valueOf(1));
1469     }
1470 
1471     private static class Result {
1472 
1473         private String msg;
1474         boolean value = true;
1475     }
1476 
1477     private Result checkCellChildNodes(org.jemmy.Rectangle arrowBoundsInitial, org.jemmy.Rectangle arrowBounds,
1478             org.jemmy.Rectangle textRectInitial, org.jemmy.Rectangle textBounds, int gap,
1479             org.jemmy.Rectangle graphicBounds) {
1480         Result res = new Result();
1481 
1482         StringBuilder sb = new StringBuilder();
1483 
1484         if (!arrowBoundsInitial.equals(arrowBounds)) {
1485             sb.append("[Arrow position changed]").append("\n");
1486             res.value = false;
1487         }
1488 
1489         if (!(textBounds.x - textRectInitial.x >= gap)) {
1490             sb.append("[Text didn't shift when grahic was set]").append("\n");
1491             res.value = false;
1492         }
1493 
1494         if (textBounds.intersects(graphicBounds)) {
1495             sb.append("[Graphics intersects text]").append("\n");
1496             res.value = false;
1497         }
1498 
1499         if (arrowBounds.intersects(graphicBounds)) {
1500             sb.append("[Graphics intersects arrow]");
1501             res.value = false;
1502         }
1503 
1504         res.msg = sb.toString();
1505 
1506         return res;
1507     }
1508 }