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.cell; 26 27 import client.test.Smoke; 28 import com.sun.glass.ui.Application; 29 import com.sun.javafx.scene.control.skin.LabeledText; 30 import java.util.ArrayList; 31 import java.util.List; 32 import java.util.logging.Level; 33 import java.util.logging.Logger; 34 import javafx.collections.ObservableList; 35 import javafx.scene.Node; 36 import javafx.scene.Scene; 37 import javafx.scene.control.*; 38 import javafx.scene.control.test.ControlsTestBase; 39 import javafx.scene.control.test.cellapps.CellCustomStringConverter; 40 import javafx.scene.control.test.cellapps.CellsApp; 41 import static javafx.scene.control.test.cellapps.CellsApp.*; 42 import javafx.scene.control.test.cellapps.CellsApp.CellType; 43 import javafx.scene.control.test.cellapps.CellsApp.DataItem; 44 import org.jemmy.action.GetAction; 45 import org.jemmy.control.Wrap; 46 import org.jemmy.fx.ByID; 47 import org.jemmy.fx.ByText; 48 import org.jemmy.fx.Root; 49 import org.jemmy.interfaces.Keyboard.KeyboardButtons; 50 import org.jemmy.interfaces.Keyboard.KeyboardModifiers; 51 import org.jemmy.interfaces.Parent; 52 import org.jemmy.interfaces.Selectable; 53 import org.jemmy.interfaces.Text; 54 import org.jemmy.lookup.Lookup; 55 import org.jemmy.lookup.LookupCriteria; 56 import org.jemmy.timing.State; 57 import org.junit.After; 58 import static org.junit.Assert.assertEquals; 59 import org.junit.Test; 60 import org.junit.runner.RunWith; 61 import test.javaclient.shared.FilteredTestRunner; 62 import test.javaclient.shared.Utils; 63 64 @RunWith(FilteredTestRunner.class) 65 public abstract class CellsTestBase extends ControlsTestBase { 66 67 protected static Wrap<? extends Scene> scene = null; 68 protected static Parent<Node> parent = null; 69 protected static String cellID = null; 70 protected static String choiceID = null; 71 protected static Wrap<? extends Control> testedControl = null; 72 73 protected static void updateWraps() { 74 scene = Root.ROOT.lookup().wrap(); 75 parent = scene.as(Parent.class, Node.class); 76 } 77 78 protected abstract Wrap select(String data); 79 80 protected abstract ObservableList<DataItem> getCurrentProgramValues(); 81 82 @After 83 public void tearDown() throws InterruptedException { 84 Wrap error = parent.lookup(Label.class, new ByID<Label>(ERROR_LABEL_ID)).wrap(); 85 assertEquals("", error.getProperty(Wrap.TEXT_PROP_NAME)); 86 new GetAction() { 87 @Override 88 public void run(Object... os) throws Exception { 89 ((Button) os[0]).getOnAction().handle(null); 90 } 91 }.dispatch(Root.ROOT.getEnvironment(), parent.lookup(Button.class, new ByID(RESET_SCENE_BTN_ID)).wrap().getControl()); 92 } 93 94 @Smoke 95 @Test(timeout = 300000) 96 public void enterTextTest() throws InterruptedException { 97 doFactoryChange(CellType.CustomCell); 98 startEditingByMouse("Data item 0"); 99 100 String newData = "New data"; 101 Wrap<? extends TextField> edit_wrap = parent.lookup(TextField.class, new ByID<TextField>(cellID)).wrap(); 102 edit_wrap.keyboard().pushKey(KeyboardButtons.A, Utils.isMacOS() ? KeyboardModifiers.META_DOWN_MASK : KeyboardModifiers.CTRL_DOWN_MASK); 103 edit_wrap.as(Text.class).type(newData); 104 commitEditing(newData); 105 select(newData); 106 } 107 108 @Smoke 109 @Test(timeout = 300000) 110 public void escapeEditingTest() throws Exception { 111 doFactoryChange(CellType.CustomCell); 112 startEditingByMouse("Data item 3"); 113 114 String newData = "New data"; 115 Wrap<? extends TextField> edit_wrap = parent.lookup(TextField.class, new ByID<TextField>(cellID)).wrap(); 116 edit_wrap.mouse().click(); 117 edit_wrap.keyboard().pushKey(KeyboardButtons.A, Utils.isMacOS() ? KeyboardModifiers.META_DOWN_MASK : KeyboardModifiers.CTRL_DOWN_MASK); 118 edit_wrap.as(Text.class).type(newData); 119 escapeEditing(newData); 120 121 try { 122 select(newData); 123 } catch (Exception ex) { 124 ex.printStackTrace(); 125 return; 126 } 127 128 throw new Exception("Test fails, because we've found item, which should be, because editing was escaped"); 129 } 130 131 @Smoke 132 @Test(timeout = 300000) 133 public void editInnerSelectionTest() throws InterruptedException { 134 doFactoryChange(CellType.CustomCell); 135 Wrap<String> item_wrap = startEditingByMouse("Data item 3"); 136 item_wrap.mouse().click(); 137 testedControl.as(Parent.class, Node.class).lookup(TextField.class, new ByID<TextField>(cellID)).wait(1); 138 } 139 140 @Smoke 141 @Test(timeout = 300000) 142 public void editFocusTest() throws InterruptedException { 143 doFactoryChange(CellType.CustomCell); 144 startEditingByMouse("Data item 3"); 145 scene.keyboard().pushKey(KeyboardButtons.TAB); 146 testedControl.as(Parent.class, Node.class).lookup(TextField.class, new ByID<TextField>(cellID)).wait(1); 147 } 148 149 @Smoke 150 @Test(timeout = 300000) 151 public void clickOtherItemTest() throws InterruptedException { 152 doFactoryChange(CellType.CustomCell); 153 startEditingByMouse("Data item 3"); 154 select("Data item 2"); 155 scene.waitState(new State<Integer>() { 156 public Integer reached() { 157 return parent.lookup(TextField.class, new ByID<TextField>(cellID)).size(); 158 } 159 }, 0); 160 } 161 162 @Smoke 163 @Test(timeout = 300000) 164 public void editOtherItemTest() throws InterruptedException { 165 doFactoryChange(CellType.CustomCell); 166 select("Data item 5"); 167 startEditingByMouse("Data item 3"); 168 startEditingByMouse("Data item 2"); 169 parent.lookup(TextField.class, new ByID<TextField>(cellID)).wait(1); 170 } 171 172 @Smoke 173 @Test(timeout = 300000) 174 public void commonCheckBoxFactoryWithMouseTest() { 175 doCommonCheckOfChanger(CellType.CheckBox, Boolean.FALSE, Boolean.TRUE, Boolean.TRUE, null, WayOfEditing.ByMouse); 176 } 177 178 @Smoke 179 @Test(timeout = 300000) 180 public void commonCheckBoxFactoryWithKeyboardTest() { 181 doCommonCheckOfChanger(CellType.CheckBox, Boolean.FALSE, Boolean.TRUE, Boolean.TRUE, null, WayOfEditing.ByKeyboard); 182 } 183 184 @Smoke 185 @Test(timeout = 300000) 186 public void commonChoiceBoxFacoryWithMouseTest() { 187 doCommonCheckOfChanger(CellType.ChoiceBox, data.get(5), someValues.get(1), someValues.get(1), new CellCustomStringConverter().toString(someValues.get(1).toString()), WayOfEditing.ByMouse); 188 } 189 190 @Smoke 191 @Test(timeout = 300000) 192 public void commonChoiceBoxFacoryWithKeyboardTest() { 193 doCommonCheckOfChanger(CellType.ChoiceBox, data.get(3), someValues.get(2), someValues.get(2), new CellCustomStringConverter().toString(someValues.get(2).toString()), WayOfEditing.ByKeyboard); 194 } 195 196 @Smoke 197 @Test(timeout = 300000) 198 public void commonComboBoxFacoryWithMouseTest() { 199 doCommonCheckOfChanger(CellType.ComboBox, data.get(8), someValues.get(2), someValues.get(2), new CellCustomStringConverter().toString(someValues.get(2).toString()), WayOfEditing.ByMouse); 200 } 201 202 @Smoke 203 @Test(timeout = 300000) 204 public void commonComboBoxFacoryWithKeyboardTest() { 205 doCommonCheckOfChanger(CellType.ComboBox, data.get(4), someValues.get(0), someValues.get(0), new CellCustomStringConverter().toString(someValues.get(0).toString()), WayOfEditing.ByKeyboard); 206 } 207 208 @Smoke 209 @Test(timeout = 300000) 210 public void commonTextFieldFacoryWithMouseTest() { 211 doCommonCheckOfChanger(CellType.TextField, data.get(7), someValues.get(0), new CellCustomStringConverter().fromString(someValues.get(0).toString()), 212 new CellCustomStringConverter().toString(new CellCustomStringConverter().fromString(someValues.get(0).toString())), WayOfEditing.ByMouse); 213 } 214 215 @Smoke 216 @Test(timeout = 300000) 217 public void commonTextFieldFacoryWithKeyboardTest() { 218 doCommonCheckOfChanger(CellType.TextField, data.get(2), someValues.get(1), new CellCustomStringConverter().fromString(someValues.get(1).toString()), 219 new CellCustomStringConverter().toString(new CellCustomStringConverter().fromString(someValues.get(1).toString())), WayOfEditing.ByKeyboard); 220 } 221 222 @Smoke 223 @Test(timeout = 300000) 224 public void commonCustomTextFieldFacoryWithMouseTest() { 225 doCommonCheckOfChanger(CellType.CustomCell, data.get(7), someValues.get(0), new CellCustomStringConverter().fromString(someValues.get(0).toString()), 226 new CellCustomStringConverter().toString(new CellCustomStringConverter().fromString(someValues.get(0).toString())), WayOfEditing.ByMouse); 227 } 228 229 @Smoke 230 @Test(timeout = 300000) 231 public void commonCustomTextFieldFacoryWithKeyboardTest() { 232 doCommonCheckOfChanger(CellType.CustomCell, data.get(2), someValues.get(1), new CellCustomStringConverter().fromString(someValues.get(1).toString()), 233 new CellCustomStringConverter().toString(new CellCustomStringConverter().fromString(someValues.get(1).toString())), WayOfEditing.ByKeyboard); 234 } 235 236 protected Wrap startEditingByMouse(String data) { 237 Wrap<? extends DataItem> wrap = select(data); 238 wrap.mouse().click(); 239 return wrap; 240 } 241 242 protected Wrap startEditingByKeyboard(String data) { 243 Wrap<? extends DataItem> wrap = select(data); 244 wrap.keyboard().pushKey(KeyboardButtons.F2); 245 return wrap; 246 } 247 248 protected void escapeEditing(String data) { 249 parent.lookup(TextField.class, new ByText<TextField>(data)).wrap().keyboard().pushKey(KeyboardButtons.ESCAPE); 250 } 251 252 protected void commitEditing(String data) { 253 parent.lookup(TextField.class, new ByText<TextField>(data)).wrap().keyboard().pushKey(KeyboardButtons.ENTER); 254 } 255 256 protected void doCommonCheckOfChanger(CellsApp.CellType cellType, Object editableValue, Object newValue, Object expectedValue, String expectedValueRepresentation, WayOfEditing way) { 257 doFactoryChange(cellType); 258 checkShowingChangeAfterTypeOfFactoryChanging(cellType); 259 changeValue(cellType, way, editableValue, newValue); 260 checkValueChangingProgrammly(expectedValue, cellType.equals(CellType.CheckBox) ? ValueType.Bool : ValueType.Str); 261 checkValueChangingByShowing(expectedValueRepresentation, cellType); 262 } 263 264 protected void doFactoryChange(final CellsApp.CellType cellType) { 265 final Wrap<? extends ComboBox<CellType>> comboBox = parent.lookup(ComboBox.class, new ByID(choiceID)).wrap(); 266 Application.invokeAndWait(new Runnable() { 267 268 @Override 269 public void run() { 270 try { 271 comboBox.getControl().getSelectionModel().select(cellType); 272 } catch (Throwable ex) { 273 ex.printStackTrace(); 274 } 275 } 276 }); 277 } 278 279 protected void changeValue(CellsApp.CellType cellType, WayOfEditing way, Object editableValue, final Object newValue) { 280 if (!cellType.equals(CellType.CheckBox)) { 281 switch (way) { 282 case ByKeyboard: 283 startEditingByKeyboard(editableValue.toString()); 284 break; 285 case ByMouse: 286 startEditingByMouse(editableValue.toString()); 287 } 288 } 289 290 switch (cellType) { 291 case CheckBox: 292 Lookup lookup = testedControl.as(Parent.class, Node.class).lookup(CheckBox.class); 293 int size = lookup.size(); 294 assertEquals(size, dataItemsSize + (testedControl.getControl() instanceof TreeView ? 1 : 0), 0); 295 for (int i = 0; i < size; i++) { 296 if (way == WayOfEditing.ByMouse) { 297 lookup.wrap(i).mouse().click(); 298 } else { 299 new GetAction() { 300 @Override 301 public void run(Object... os) throws Exception { 302 ((Control) os[0]).requestFocus(); 303 } 304 }.dispatch(Root.ROOT.getEnvironment(), (Control) lookup.wrap(i).getControl());//Otherwise it use mouse click to get focus and make "selected" value changed. 305 lookup.wrap(i).keyboard().pushKey(KeyboardButtons.SPACE); 306 } 307 } 308 break; 309 case ChoiceBox: 310 Lookup lookupChoiceBox = testedControl.as(Parent.class, Node.class).lookup(ChoiceBox.class); 311 final Wrap<? extends ChoiceBox> choiceBox = lookupChoiceBox.wrap(); 312 choiceBox.waitState(new State<Boolean>() { 313 public Boolean reached() { 314 return choiceBox.getControl().isVisible(); 315 } 316 }, true); 317 assertEquals(lookupChoiceBox.size(), 1, 0); 318 if (way == WayOfEditing.ByMouse) { 319 choiceBox.as(Selectable.class).selector().select(converter.toString(newValue)); 320 choiceBox.waitState(new State<Boolean>() { 321 public Boolean reached() { 322 return choiceBox.getControl().getSelectionModel().getSelectedItem().equals(newValue); 323 } 324 }, true); 325 } else { //by keyboard 326 //choiceBox.keyboard().pushKey(KeyboardButtons.SPACE); 327 for (int i = 0; i < getIndexOfValueInChoiceBox(choiceBox, newValue) + 1; i++) { 328 choiceBox.keyboard().pushKey(KeyboardButtons.DOWN); 329 } 330 choiceBox.keyboard().pushKey(KeyboardButtons.ENTER); 331 } 332 break; 333 case ComboBox: 334 Lookup lookupComboBox = testedControl.as(Parent.class, Node.class).lookup(ComboBox.class); 335 assertEquals(lookupComboBox.size(), 1, 0); 336 Wrap<? extends ComboBox> comboBox = lookupComboBox.wrap(); 337 if (way == WayOfEditing.ByMouse) { 338 comboBox.as(Selectable.class).selector().select(newValue); 339 } else { //by keyboard 340 comboBox.keyboard().pushKey(KeyboardButtons.SPACE); 341 for (int i = 0; i < getIndexOfValueInComboBox(comboBox, newValue) + 1; i++) { 342 comboBox.keyboard().pushKey(KeyboardButtons.DOWN); 343 } 344 comboBox.keyboard().pushKey(KeyboardButtons.ENTER); 345 } 346 break; 347 case TextField: 348 case CustomCell: 349 Lookup lookupTextField = testedControl.as(Parent.class, Node.class).lookup(TextField.class); 350 assertEquals(lookupTextField.size(), 1, 0); 351 final Wrap<? extends TextField> textField = lookupTextField.wrap(); 352 new GetAction() { 353 @Override 354 public void run(Object... os) throws Exception { 355 textField.getControl().requestFocus(); 356 } 357 }.dispatch(Root.ROOT.getEnvironment()); 358 textField.keyboard().pushKey(KeyboardButtons.HOME); 359 textField.keyboard().pushKey(KeyboardButtons.END, KeyboardModifiers.SHIFT_DOWN_MASK); 360 textField.keyboard().pushKey(KeyboardButtons.DELETE); 361 textField.as(Text.class).type(newValue.toString()); 362 textField.keyboard().pushKey(KeyboardButtons.ENTER); 363 break; 364 default: 365 throw new IllegalStateException("Unknown version"); 366 } 367 } 368 369 protected int getIndexOfValueInChoiceBox(final Wrap< ? extends ChoiceBox> choiceBox, final Object newValue) { 370 return new GetAction<Integer>() { 371 @Override 372 public void run(Object... os) throws Exception { 373 setResult(choiceBox.getControl().getItems().indexOf(newValue)); 374 } 375 }.dispatch(Root.ROOT.getEnvironment()); 376 } 377 378 protected int getIndexOfValueInComboBox(final Wrap< ? extends ComboBox> comboBox, final Object newValue) { 379 return new GetAction<Integer>() { 380 @Override 381 public void run(Object... os) throws Exception { 382 setResult(comboBox.getControl().getItems().indexOf(newValue)); 383 } 384 }.dispatch(Root.ROOT.getEnvironment()); 385 } 386 387 protected void checkValueChangingByShowing(final String expectedValue, CellType cellType) { 388 if (!cellType.equals(CellType.CheckBox)) { 389 final int size = testedControl.as(Parent.class, Node.class).lookup(new LookupCriteria<Node>() { 390 public boolean check(Node cntrl) { 391 return (cntrl instanceof LabeledText) 392 && ((LabeledText) cntrl).getText().equals(expectedValue) 393 && cntrl.isVisible(); 394 } 395 }).lookup().size(); 396 assertEquals("Failed to lookup visible labeled with text [" + expectedValue + "]", size, 1, 0); 397 } 398 } 399 400 protected void checkShowingChangeAfterTypeOfFactoryChanging(CellType cellType) { 401 testedControl.waitState(() -> { 402 List<String> shownValues = new ArrayList<>(); 403 Lookup lookup = testedControl.as(Parent.class, Node.class).lookup(new LookupCriteria<Node>() { 404 @Override 405 public boolean check(final Node cntrl) { 406 if (cntrl instanceof LabeledText) { 407 boolean isVisible = new GetAction<Boolean>() { 408 409 @Override 410 public void run(Object... os) throws Exception { 411 setResult(cntrl.isVisible()); 412 } 413 }.dispatch(Root.ROOT.getEnvironment()); 414 if (isVisible) { 415 return true; 416 } 417 } 418 return false; 419 } 420 }).lookup(); 421 int size = lookup.size(); 422 for (int i = 0; i < size; i++) { 423 shownValues.add(new GetAction<String>() { 424 @Override 425 public void run(Object... os) throws Exception { 426 setResult(((LabeledText) os[0]).getText()); 427 } 428 }.dispatch(Root.ROOT.getEnvironment(), (LabeledText) lookup.wrap(i).getControl())); 429 } 430 431 List<DataItem> failedAttemps = new ArrayList<>(); 432 for (DataItem item : data) { 433 int counter = 0; 434 for (String str : shownValues) { 435 if (str.contains(CellCustomStringConverter.TO_STRING_PREFIX) && str.contains(item.toString())) { 436 counter++; 437 } 438 } 439 if (counter != 1) { 440 System.out.println("For data item <" + item + "> cannot find proper representation."); 441 failedAttemps.add(item); 442 } 443 } 444 if (failedAttemps.isEmpty()) { 445 return true; 446 } else { 447 return null; 448 } 449 }); 450 } 451 452 protected void checkValueChangingProgrammly(Object expectedValue, ValueType type) { 453 switch (type) { 454 case Bool: 455 for (DataItem item : getCurrentProgramValues()) { 456 assertEquals((Boolean) expectedValue, item.choiceBoxChecker.getValue()); 457 } 458 break; 459 case Str: 460 int counter = 0; 461 for (DataItem item : getCurrentProgramValues()) { 462 if (item.toString().equals(expectedValue.toString())) { 463 counter++; 464 } 465 } 466 assertEquals(counter, 1, 0); 467 break; 468 default: 469 throw new IllegalStateException("Unknown option"); 470 } 471 } 472 473 protected enum ValueType { 474 475 Bool, Str 476 }; 477 478 protected enum WayOfEditing { 479 480 ByMouse, ByKeyboard 481 }; 482 }