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