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.textinput; 26 27 import client.test.ScreenshotCheck; 28 import com.sun.javafx.scene.control.skin.TextInputControlSkin; 29 import java.lang.reflect.Field; 30 import java.util.HashMap; 31 import java.util.HashSet; 32 import java.util.List; 33 import java.util.Map; 34 import java.util.logging.Level; 35 import java.util.logging.Logger; 36 import javafx.beans.property.BooleanProperty; 37 import javafx.scene.Node; 38 import javafx.scene.Scene; 39 import javafx.scene.control.Button; 40 import javafx.scene.control.Control; 41 import javafx.scene.control.MenuItem; 42 import javafx.scene.control.PasswordField; 43 import javafx.scene.control.TextInputControl; 44 import javafx.scene.control.test.Change; 45 import javafx.scene.control.test.mix.PopupMenuTest; 46 import javafx.scene.control.test.textinput.TextInputBaseApp.Pages; 47 import javafx.scene.control.test.textinput.TextInputChanger.TextInputControlWrapInterface; 48 import javafx.scene.control.test.textinput.TextInputChanger.TextInputPages; 49 import javafx.scene.input.Clipboard; 50 import javafx.scene.input.DataFormat; 51 import javafx.scene.layout.Pane; 52 import org.jemmy.Point; 53 import org.jemmy.action.GetAction; 54 import org.jemmy.control.Wrap; 55 import org.jemmy.fx.ByID; 56 import org.jemmy.fx.Root; 57 import org.jemmy.interfaces.Keyboard; 58 import org.jemmy.interfaces.Keyboard.KeyboardButtons; 59 import org.jemmy.interfaces.Keyboard.KeyboardModifiers; 60 import org.jemmy.interfaces.Mouse.MouseButtons; 61 import org.jemmy.interfaces.Parent; 62 import org.jemmy.interfaces.Text; 63 import org.jemmy.lookup.LookupCriteria; 64 import org.jemmy.timing.State; 65 import org.junit.Assert; 66 import static org.junit.Assert.*; 67 import org.junit.Test; 68 import org.junit.runner.RunWith; 69 import test.javaclient.shared.FilteredTestRunner; 70 import test.javaclient.shared.TestBase; 71 import test.javaclient.shared.Utils; 72 import test.javaclient.shared.screenshots.ScreenshotUtils; 73 74 /** 75 * @author Oleg Barbashov 76 */ 77 @RunWith(FilteredTestRunner.class) 78 public class TextInputBase extends TestBase { 79 80 { 81 ScreenshotUtils.setComparatorDistance(0.003f); 82 } 83 private Wrap<? extends TextInputControl> taTesting = null; 84 85 static final KeyboardModifiers CTRL = Utils.isMacOS() ? KeyboardModifiers.META_DOWN_MASK : KeyboardModifiers.CTRL_DOWN_MASK; 86 // /** 87 // * Test for TextInput setMaximumLength API 88 // */ 89 // @ScreenshotCheck 90 // @Test(timeout=300000) 91 // public void maximumLengthTest() throws InterruptedException, Throwable { 92 // openPage(Pages.MaximumLength.name()); 93 // 94 // verifyFailures(); 95 // 96 // Parent<Node> parent = scene.as(Parent.class, Node.class); 97 // Lookup lookup = parent.lookup(TextInput.class); 98 // for (int i = 0; i < lookup.size(); i++) { 99 // final Wrap<? extends TextInput> wrap = lookup.wrap(i); 100 // final Integer maximumLength = new GetAction<Integer>() { 101 // @Override 102 // public void run(Object... parameters) { 103 // setResult(wrap.getControl().getMaximumLength()); 104 // } 105 // }.dispatch(Root.ROOT.getEnvironment()); 106 // Text text = wrap.as(Text.class); 107 // long timeout = Wrap.WAIT_STATE_TIMEOUT.getValue(); 108 // String str = createLongString(maximumLength + 2); 109 // try { 110 // text.type(str); 111 // } catch (Exception ex) { 112 // // expected as text length is limited but Jemmy does not expect limitation and wait for all sequence 113 // } 114 // Wrap.WAIT_STATE_TIMEOUT.setValue(timeout); 115 // wrap.waitProperty(Wrap.TEXT_PROP_NAME, str.subSequence(0, maximumLength)); 116 // } 117 // checkScreenshot(getClass().getSimpleName() + "-" + Pages.MaximumLength.name()); 118 // throwScreenshotError(); 119 // } 120 /** 121 * Test for backward API 122 */ 123 @ScreenshotCheck 124 @Test(timeout = 300000) 125 public void backwardInternalTest() throws InterruptedException { 126 textInputControlInput(TextInputPages.backward.name(), true); 127 } 128 129 /** 130 * Test for copy API 131 */ 132 @ScreenshotCheck 133 @Test(timeout = 300000) 134 public void copyInternalTest() throws InterruptedException { 135 textInputControlInput(TextInputPages.copy.name(), true); 136 } 137 138 /** 139 * Test for cut API 140 */ 141 @ScreenshotCheck 142 @Test(timeout = 300000) 143 public void cutInternalTest() throws InterruptedException { 144 textInputControlInput(TextInputPages.cut.name(), true); 145 } 146 147 /** 148 * Test for deleteNextChar API 149 */ 150 @ScreenshotCheck 151 @Test(timeout = 300000) 152 public void deleteNextCharInternalTest() throws InterruptedException { 153 textInputControlInput(TextInputPages.deleteNextChar.name(), true); 154 } 155 156 /** 157 * Test for deletePreviousChar API 158 */ 159 @ScreenshotCheck 160 @Test(timeout = 300000) 161 public void deletePreviousCharInternalTest() throws InterruptedException { 162 textInputControlInput(TextInputPages.deletePreviousChar.name(), true); 163 } 164 165 /** 166 * Test for end API 167 */ 168 @ScreenshotCheck 169 @Test(timeout = 300000) 170 public void endInternalTest() throws InterruptedException { 171 textInputControlInput(TextInputPages.end.name(), true); 172 } 173 174 /** 175 * Test for forward API 176 */ 177 @ScreenshotCheck 178 @Test(timeout = 300000) 179 public void forwardInternalTest() throws InterruptedException { 180 textInputControlInput(TextInputPages.forward.name(), true); 181 } 182 183 /** 184 * Test for home API 185 */ 186 @ScreenshotCheck 187 @Test(timeout = 300000) 188 public void homeInternalTest() throws InterruptedException { 189 textInputControlInput(TextInputPages.home.name(), true); 190 } 191 192 /** 193 * Test for isEditableTextBoxWrap API 194 */ 195 @ScreenshotCheck 196 @Test(timeout = 300000) 197 public void isEditableTextBoxWrapInternalTest() throws InterruptedException { 198 textInputControlInput(TextInputPages.isEditable.name(), true); 199 } 200 201 /** 202 * Test for nextWord API 203 */ 204 @ScreenshotCheck 205 @Test(timeout = 300000) 206 public void nextWordInternalTest() throws InterruptedException { 207 textInputControlInput(TextInputPages.nextWord.name(), true); 208 } 209 210 /** 211 * Test for paste API 212 */ 213 @ScreenshotCheck 214 @Test(timeout = 300000) 215 public void pasteInternalTest() throws InterruptedException { 216 textInputControlInput(TextInputPages.paste.name(), true); 217 } 218 219 /** 220 * Test for positionCaret API 221 */ 222 @ScreenshotCheck 223 @Test(timeout = 300000) 224 public void positionCaretInternalTest() throws InterruptedException { 225 textInputControlInput(TextInputPages.positionCaret.name(), true); 226 } 227 228 /** 229 * Test for previousWord API 230 */ 231 @ScreenshotCheck 232 @Test(timeout = 300000) 233 public void previousWordInternalTest() throws InterruptedException { 234 textInputControlInput(TextInputPages.previousWord.name(), true); 235 } 236 237 /** 238 * Test for selectAll API 239 */ 240 @ScreenshotCheck 241 @Test(timeout = 300000) 242 public void selectAllInternalTest() throws InterruptedException { 243 textInputControlInput(TextInputPages.selectAll.name(), true); 244 } 245 246 /** 247 * Test for selectBackward API 248 */ 249 @ScreenshotCheck 250 @Test(timeout = 300000) 251 public void selectBackwardInternalTest() throws InterruptedException { 252 textInputControlInput(TextInputPages.selectBackward.name(), true); 253 } 254 255 /** 256 * Test for selectEnd API 257 */ 258 @ScreenshotCheck 259 @Test(timeout = 300000) 260 public void selectEndInternalTest() throws InterruptedException { 261 textInputControlInput(TextInputPages.selectEnd.name(), true); 262 } 263 264 /** 265 * Test for selectForward API 266 */ 267 @ScreenshotCheck 268 @Test(timeout = 300000) 269 public void selectForwardInternalTest() throws InterruptedException { 270 textInputControlInput(TextInputPages.selectForward.name(), true); 271 } 272 273 /** 274 * Test for selectHome API 275 */ 276 @ScreenshotCheck 277 @Test(timeout = 300000) 278 public void selectHomeInternalTest() throws InterruptedException { 279 textInputControlInput(TextInputPages.selectHome.name(), true); 280 } 281 282 /** 283 * Test for selectNext API 284 */ 285 @ScreenshotCheck 286 @Test(timeout = 300000) 287 public void selectNextWordInternalTest() throws InterruptedException { 288 textInputControlInput(TextInputPages.selectNextWord.name(), true); 289 } 290 291 /** 292 * Test for selectPreviousWord API 293 */ 294 @ScreenshotCheck 295 @Test(timeout = 300000) 296 public void selectPreviousWordInternalTest() throws InterruptedException { 297 textInputControlInput(TextInputPages.selectPreviousWord.name(), true); 298 } 299 300 /** 301 * Test for setText API 302 */ 303 @ScreenshotCheck 304 @Test(timeout = 300000) 305 public void setTextInternalTest() throws InterruptedException { 306 textInputControlInput(TextInputPages.setText.name(), true); 307 } 308 309 /** 310 * Test for backward API by simulating user input 311 */ 312 @ScreenshotCheck 313 @Test(timeout = 300000) 314 public void backwardExternalTest() throws InterruptedException { 315 textInputControlInput(TextInputPages.backward.name(), false); 316 } 317 318 /** 319 * Test for copy API by simulating user input 320 */ 321 @ScreenshotCheck 322 @Test(timeout = 300000) 323 public void copyExternalTest() throws InterruptedException { 324 textInputControlInput(TextInputPages.copy.name(), false); 325 } 326 327 /** 328 * Test for cut API by simulating user input 329 */ 330 @ScreenshotCheck 331 @Test(timeout = 300000) 332 public void cutExternalTest() throws InterruptedException { 333 textInputControlInput(TextInputPages.cut.name(), false); 334 } 335 336 /** 337 * Test for deleteNextChar API by simulating user input 338 */ 339 @ScreenshotCheck 340 @Test(timeout = 300000) 341 public void deleteNextCharExternalTest() throws InterruptedException { 342 textInputControlInput(TextInputPages.deleteNextChar.name(), false); 343 } 344 345 /** 346 * Test for deletePreviousChar API by simulating user input 347 */ 348 @ScreenshotCheck 349 @Test(timeout = 300000) 350 public void deletePreviousCharExternalTest() throws InterruptedException { 351 textInputControlInput(TextInputPages.deletePreviousChar.name(), false); 352 } 353 354 /** 355 * Test for end API by simulating user input 356 */ 357 @ScreenshotCheck 358 @Test(timeout = 300000) 359 public void endExternalTest() throws InterruptedException { 360 textInputControlInput(TextInputPages.end.name(), false); 361 } 362 363 /** 364 * Test for forward API by simulating user input 365 */ 366 @ScreenshotCheck 367 @Test(timeout = 300000) 368 public void forwardExternalTest() throws InterruptedException { 369 textInputControlInput(TextInputPages.forward.name(), false); 370 } 371 372 /** 373 * Test for home API by simulating user input 374 */ 375 @ScreenshotCheck 376 @Test(timeout = 300000) 377 public void homeExternalTest() throws InterruptedException { 378 textInputControlInput(TextInputPages.home.name(), false); 379 } 380 381 /** 382 * Test for isEditableTextBoxWrap API by simulating user input 383 */ 384 @ScreenshotCheck 385 @Test(timeout = 300000) 386 public void isEditableTextBoxWrapExternalTest() throws InterruptedException { 387 textInputControlInput(TextInputPages.isEditable.name(), false); 388 } 389 390 /** 391 * Test for nextWord API by simulating user input 392 */ 393 @ScreenshotCheck 394 @Test(timeout = 300000) 395 public void nextWordExternalTest() throws InterruptedException { 396 if (Utils.isMacOS()) { 397 textInputControlInput(TextInputPages.macNextWordExternal.name(), false); 398 } else { 399 textInputControlInput(TextInputPages.nextWord.name(), false); 400 } 401 } 402 403 /** 404 * Test for paste API by simulating user input 405 */ 406 @ScreenshotCheck 407 @Test(timeout = 300000) 408 public void pasteExternalTest() throws InterruptedException { 409 textInputControlInput(TextInputPages.paste.name(), false); 410 } 411 412 /** 413 * Test for positionCaret API by simulating user input 414 */ 415 @ScreenshotCheck 416 @Test(timeout = 300000) 417 public void positionCaretExternalTest() throws InterruptedException { 418 textInputControlInput(TextInputPages.positionCaret.name(), false); 419 } 420 421 /** 422 * Test for previousWord API by simulating user input 423 */ 424 @ScreenshotCheck 425 @Test(timeout = 300000) 426 public void previousWordExternalTest() throws InterruptedException { 427 textInputControlInput(TextInputPages.previousWord.name(), false); 428 } 429 430 /** 431 * Test for selectAll API by simulating user input 432 */ 433 @ScreenshotCheck 434 @Test(timeout = 300000) 435 public void selectAllExternalTest() throws InterruptedException { 436 textInputControlInput(TextInputPages.selectAll.name(), false); 437 } 438 439 /** 440 * Test for selectBackward API by simulating user input 441 */ 442 @ScreenshotCheck 443 @Test(timeout = 300000) 444 public void selectBackwardExternalTest() throws InterruptedException { 445 textInputControlInput(TextInputPages.selectBackward.name(), false); 446 } 447 448 /** 449 * Test for selectEnd API by simulating user input 450 */ 451 @ScreenshotCheck 452 @Test(timeout = 300000) 453 public void selectEndExternalTest() throws InterruptedException { 454 textInputControlInput(TextInputPages.selectEnd.name(), false); 455 } 456 457 /** 458 * Test for selectForward API by simulating user input 459 */ 460 @ScreenshotCheck 461 @Test(timeout = 300000) 462 public void selectForwardExternalTest() throws InterruptedException { 463 textInputControlInput(TextInputPages.selectForward.name(), false); 464 } 465 466 /** 467 * Test for selectHome API by simulating user input 468 */ 469 @ScreenshotCheck 470 @Test(timeout = 300000) 471 public void selectHomeExternalTest() throws InterruptedException { 472 textInputControlInput(TextInputPages.selectHome.name(), false); 473 } 474 475 /** 476 * Test for selectNext API by simulating user input 477 */ 478 @ScreenshotCheck 479 @Test(timeout = 300000) 480 public void selectNextWordExternalTest() throws InterruptedException { 481 textInputControlInput(TextInputPages.selectNextWord.name(), false); 482 } 483 484 /** 485 * Test for selectPreviousWord API by simulating user input 486 */ 487 @ScreenshotCheck 488 @Test(timeout = 300000) 489 public void selectPreviousWordExternalTest() throws InterruptedException { 490 textInputControlInput(TextInputPages.selectPreviousWord.name(), false); 491 } 492 493 /** 494 * Test for setText API by simulating user input 495 */ 496 @ScreenshotCheck 497 @Test(timeout = 300000) 498 public void setTextExternalTest() throws InterruptedException { 499 textInputControlInput(TextInputPages.setText.name(), false); 500 } 501 502 /** 503 * Test for Context Menu 504 */ 505 @ScreenshotCheck 506 @Test(timeout = 300000) 507 public void contextMenuTest() throws InterruptedException { 508 openPage(Pages.InputTest.name()); 509 510 final Wrap<? extends TextInputControl> wrap = getScene().as(Parent.class, Node.class).lookup(TextInputControl.class).wrap(); 511 final Text text = wrap.as(Text.class); 512 513 initContext(); 514 boolean password = PasswordField.class.isAssignableFrom(wrap.getControl().getClass()); 515 if (!password) { 516 getMenuItem("Select All").mouse().move(); 517 getMenuItem("Copy").mouse().click(); 518 checkClipboard(SAMPLE_STRING); 519 520 getMenuItem("Cut").mouse().click(); 521 checkClipboard(SAMPLE_STRING); 522 checkText(text, ""); 523 } else { 524 checkState("Copy", true); 525 checkState("Cut", true); 526 } 527 528 initContext(); 529 getMenuItem("Delete").mouse().click(); 530 checkText(text, ""); 531 532 initContext(); 533 getMenuItem("Select All").mouse().click(); 534 getScene().waitState(new State() { 535 public Object reached() { 536 return wrap.getControl().getSelection().getLength() == SAMPLE_STRING.length() ? true : null; 537 } 538 }); 539 540 initContext(); 541 final Map<DataFormat, Object> data_map = new HashMap<DataFormat, Object>(); 542 data_map.put(DataFormat.PLAIN_TEXT, SAMPLE_STRING); 543 544 new GetAction() { 545 @Override 546 public void run(Object... os) throws Exception { 547 Clipboard.getSystemClipboard().setContent(data_map); 548 } 549 }.dispatch(Root.ROOT.getEnvironment()); 550 551 getMenuItem("Paste").mouse().click(); 552 checkText(text, SAMPLE_STRING); 553 554 wrap.keyboard().pushKey(KeyboardButtons.HOME); 555 checkState("Copy", true); 556 checkState("Cut", true); 557 checkState("Paste", false); 558 559 new GetAction() { 560 @Override 561 public void run(Object... os) throws Exception { 562 Clipboard.getSystemClipboard().clear(); 563 } 564 }.dispatch(Root.ROOT.getEnvironment()); 565 566 checkState("Paste", true); 567 checkState("Delete", true); 568 checkState("Select All", false); 569 } 570 571 @ScreenshotCheck 572 @Test 573 public void ctrlBackspaceMultilineTest() { 574 openPage(Pages.CtrlBackspaceTest.name()); 575 Wrap<? extends Button> btn = getScene().as(org.jemmy.interfaces.Parent.class, Node.class).lookup(new ByID<Button>(TextAreaApp.MULTILINE_BTN_ID + Pages.CtrlBackspaceTest.name())).wrap(); 576 click(btn); 577 ctrlBackspaceTest(); 578 } 579 580 @ScreenshotCheck 581 @Test 582 public void ctrlBackspaceRandomSymbolsTest() { 583 openPage(Pages.CtrlBackspaceTest.name()); 584 Wrap<? extends Button> btn = getScene().as(org.jemmy.interfaces.Parent.class, Node.class).lookup(new ByID<Button>(TextAreaApp.RANDOM_TEXT_BTN_ID + Pages.CtrlBackspaceTest.name())).wrap(); 585 click(btn); 586 ctrlBackspaceTest(); 587 } 588 589 @ScreenshotCheck 590 @Test 591 public void ctrlDeleteMultilineTest() { 592 openPage(Pages.CtrlDeleteTest.name()); 593 Wrap<? extends Button> btn = getScene().as(org.jemmy.interfaces.Parent.class, Node.class).lookup(new ByID<Button>(TextAreaApp.MULTILINE_BTN_ID + Pages.CtrlDeleteTest.name())).wrap(); 594 click(btn); 595 ctrlDeleteTest(); 596 } 597 598 @ScreenshotCheck 599 @Test 600 public void ctrlDeleteRandomSymbolsTest() { 601 openPage(Pages.CtrlDeleteTest.name()); 602 Wrap<? extends Button> btn = getScene().as(org.jemmy.interfaces.Parent.class, Node.class).lookup(new ByID<Button>(TextAreaApp.RANDOM_TEXT_BTN_ID + Pages.CtrlDeleteTest.name())).wrap(); 603 click(btn); 604 ctrlDeleteTest(); 605 } 606 607 private void ctrlBackspaceTest() { 608 taTesting = getScene().as(org.jemmy.interfaces.Parent.class, Node.class).lookup(new ByID<TextInputControl>(TextAreaApp.INPUT_AREA_ID + Pages.CtrlBackspaceTest.name())).wrap(); 609 click(taTesting); 610 end(); 611 612 String text = getTextFromControl(); 613 final String initialText = text; 614 while (!"".equals(text)) { 615 text = deleteLastWord(text); 616 taTesting.keyboard().pushKey(Keyboard.KeyboardButtons.BACK_SPACE, CTRL); 617 if (isPasswordField()) { 618 Assert.assertEquals(initialText, getTextFromControl()); 619 } else { 620 if (!text.equals(getTextFromControl())) { 621 out(initialText, text); 622 } 623 Assert.assertEquals(text, getTextFromControl()); 624 } 625 } 626 } 627 628 private void ctrlDeleteTest() { 629 taTesting = getScene().as(org.jemmy.interfaces.Parent.class, Node.class).lookup(new ByID<TextInputControl>(TextAreaApp.INPUT_AREA_ID + Pages.CtrlDeleteTest.name())).wrap(); 630 631 click(taTesting); 632 home(); 633 String text = getTextFromControl(); 634 final String initialText = text; 635 while (!"".equals(text)) { 636 text = deleteFirstWord(text, true); 637 taTesting.keyboard().pushKey(Keyboard.KeyboardButtons.DELETE, CTRL); 638 if (isPasswordField()) { 639 Assert.assertEquals(initialText, getTextFromControl()); 640 } else { 641 if (!text.equals(getTextFromControl())) { 642 out(initialText, text); 643 } 644 Assert.assertEquals(text, getTextFromControl()); 645 } 646 } 647 } 648 649 private void out(String initial, String text) { 650 System.out.println("Initial text : "); 651 System.out.println(initial); 652 System.out.println("Control's text : "); 653 System.out.println(getTextFromControl()); 654 System.out.println("Text : "); 655 System.out.println(text); 656 System.out.println("END"); 657 } 658 659 private String deleteLastWord(String text) { 660 String reverce = new StringBuffer(text).reverse().toString(); 661 reverce = deleteFirstWord(reverce, false); 662 return new StringBuffer(reverce).reverse().toString(); 663 } 664 665 /* 666 * Deletes first word according to specific rules. 667 * Behavior depend on whether deleting is made 668 * using Ctrl + Delete in the beginning of the string or 669 * using Ctrl + Backspace in the end of the string. 670 * <code>deleteFromBeginning</code> flag separates these cases. 671 * 672 * @param text initial string 673 * @param deleteFromBeginning flag which shows how deletion is performed. 674 * @return string without first word. 675 */ 676 private String deleteFirstWord(String text, boolean deleteFromBeginning) { 677 final String[] punctuation = new String[]{" ", "\n", "\t", "/", ",", ";", "!", "@", "#", "$", "%", "^", "*", "(", ")", "&", "."}; 678 if (!deleteFromBeginning) { 679 while (startsWithAnyOf(text, punctuation)) { 680 text = text.substring(1); 681 } 682 text = removeLeadingChars(text, punctuation); 683 } else { 684 if (!Utils.isWindows()) { 685 if (' ' == text.charAt(0)) { 686 int pos = 0; 687 while(' ' == text.charAt(pos)) ++pos; 688 text = text.substring(pos); 689 } else if (startsWithAnyOf(text, punctuation)) { 690 text = text.substring(1); 691 } 692 } 693 694 text = removeLeadingChars(text, punctuation); 695 696 while (startsWithAnyOf(text, punctuation)) { 697 if (!Utils.isWindows()) { 698 break; 699 } 700 text = text.substring(1); 701 } 702 } 703 return text; 704 } 705 706 /* 707 For each charachter from <code>toRemove</code> finds which occurs first and deletes it. 708 If none is found then returns empty string. 709 */ 710 String removeLeadingChars(String str, String[] toRemove) { 711 int idx = Integer.MAX_VALUE; 712 for (String ch : toRemove) { 713 if (str.indexOf(ch) >= 0) { 714 idx = Math.min(str.indexOf(ch), idx); 715 } 716 } 717 idx = idx == Integer.MAX_VALUE ? -1 : idx; 718 return (idx < 0) ? "" : str.substring(idx); 719 } 720 721 protected boolean startsWithAnyOf(String str, String[] symbols) { 722 for (String sym : symbols) { 723 if (str.startsWith(sym)) { 724 return true; 725 } 726 } 727 return false; 728 } 729 730 protected void click(Wrap<? extends Control> control) { 731 Point p = control.getClickPoint(); 732 control.mouse().move(p); 733 control.mouse().click(); 734 } 735 736 protected void initContext() { 737 final Wrap<? extends TextInputControl> wrap = getScene().as(Parent.class, Node.class).lookup(TextInputControl.class).wrap(); 738 wrap.as(Text.class).clear(); 739 wrap.as(Text.class).type(SAMPLE_STRING); 740 wrap.keyboard().pushKey(KeyboardButtons.A, Utils.isMacOS() ? KeyboardModifiers.META_DOWN_MASK : CTRL); 741 new GetAction() { 742 @Override 743 public void run(Object... os) throws Exception { 744 Clipboard.getSystemClipboard().clear(); 745 } 746 }.dispatch(Root.ROOT.getEnvironment()); 747 } 748 749 protected void checkState(final String menu, boolean disabled) { 750 Wrap<? extends Node> wrap = getMenuItem(menu); 751 MenuItem menu_item = ((MenuItem) wrap.getControl().getProperties().get(MenuItem.class)); 752 assertEquals(menu_item.isDisable(), disabled); 753 } 754 755 protected void checkText(final Text text, final String str) { 756 getScene().waitState(new State() { 757 public Object reached() { 758 return text.text().contentEquals(str) ? true : null; 759 } 760 }); 761 } 762 763 protected void checkClipboard(final String str) { 764 getScene().waitState(new State() { 765 public Object reached() { 766 return new GetAction<String>() { 767 @Override 768 public void run(Object... os) throws Exception { 769 setResult(Clipboard.getSystemClipboard().getString()); 770 } 771 }.dispatch(Root.ROOT.getEnvironment()).contentEquals(str) ? true : null; 772 } 773 }); 774 } 775 776 protected Wrap<? extends Node> getMenuItem(final String menu) { 777 getScene().mouse().click(); 778 Parent<Node> parent = getScene().as(Parent.class, Node.class); 779 final Wrap<? extends TextInputControl> wrap = parent.lookup(TextInputControl.class).wrap(); 780 wrap.mouse().click(1, wrap.getClickPoint(), MouseButtons.BUTTON3); 781 Wrap<? extends Scene> scene_wrap = PopupMenuTest.getPopupSceneWrap(); 782 Wrap<? extends Node> menu_item = scene_wrap.as(Parent.class, Node.class).lookup(Node.class, new LookupCriteria<Node>() { 783 public boolean check(Node node) { 784 if (node.getProperties().containsKey(MenuItem.class)) { 785 String text = ((MenuItem) node.getProperties().get(MenuItem.class)).getText(); 786 if (text != null && text.contentEquals(menu)) { 787 return true; 788 } 789 } 790 return false; 791 } 792 }).wrap(); 793 return menu_item; 794 } 795 final protected String SAMPLE_STRING = "Sample string"; 796 protected Boolean focused; 797 798 /** 799 * Test for textInputControl API by simulating user input 800 */ 801 public void textInputControlInput(final String changeName, boolean internal) throws InterruptedException { 802 openPage(Pages.InputTest.name()); 803 Thread.sleep(500); 804 Parent<Node> parent = getScene().as(Parent.class, Node.class); 805 806 //Take focus on scene. 807 getScene().mouse().click(1, new Point(1, 1)); 808 809 final Wrap<? extends TextInputControl> wrap = parent.lookup(TextInputControl.class).wrap(); 810 811 //Request focus on control. 812 new GetAction() { 813 @Override 814 public void run(Object... os) throws Exception { 815 wrap.getControl().requestFocus(); 816 } 817 }.dispatch(Root.ROOT.getEnvironment()); 818 819 820 final ReporterImpl reporter = new ReporterImpl(); 821 List<Change<TextInputControlWrapInterface>> text_wrap_input_changers = TextInputChanger.getTextInputWrapChangers(reporter); 822 823 for (final Change<TextInputControlWrapInterface> change : text_wrap_input_changers) { 824 if (change.getMarker().startsWith(changeName)) { 825 if (internal) { 826 applyChange(new TextInputInternalWrap(wrap.getControl()), change, reporter, wrap, true); 827 } else { 828 applyChange(new TextInputExternalWrap(wrap), change, reporter, wrap, false); 829 } 830 } 831 } 832 833 if (reporter.isFailed()) { 834 Assert.fail(reporter.getReason()); 835 } 836 } 837 838 void applyChange(final TextInputControlWrapInterface control, final Change<TextInputControlWrapInterface> change, 839 ReporterImpl reporter, final Wrap<? extends TextInputControl> wrap, final boolean internal) { 840 final String text = new GetAction<String>() { 841 @Override 842 public void run(Object... os) throws Exception { 843 setResult(control.getControl().getText()); 844 } 845 }.dispatch(Root.ROOT.getEnvironment()); 846 control.getControl().setEditable(true); 847 848 final TextInputControl controlInstance = (TextInputControl) wrap.getControl(); 849 new GetAction() { 850 @Override 851 public void run(Object... parameters) { 852 ((TextInputControlSkin) controlInstance.getSkin()).setCaretAnimating(false); 853 try { 854 Field blink_field; 855 blink_field = TextInputControlSkin.class.getDeclaredField("blink"); 856 blink_field.setAccessible(true); 857 BooleanProperty blink = (BooleanProperty) blink_field.get((TextInputControlSkin) controlInstance.getSkin()); 858 blink.set(false); 859 } catch (Exception ex) { 860 Logger.getLogger(TextInputBase.class.getName()).log(Level.SEVERE, null, ex); 861 } 862 } 863 }.dispatch(Root.ROOT.getEnvironment()); 864 865 if (internal) { 866 new GetAction() { 867 @Override 868 public void run(Object... parameters) { 869 change.apply(control, internal); 870 } 871 }.dispatch(Root.ROOT.getEnvironment()); 872 } else { 873 change.apply(control, internal); 874 } 875 876 try { 877 Wrap<? extends Pane> paneWrap = (Wrap<? extends Pane>) ScreenshotUtils.getPageContent(); 878 ScreenshotUtils.checkScreenshot(new StringBuilder(getName()).append("-").append(change.getMarker().replace(' ', '_')).append(internal ? "-internal" : "-external").toString(), paneWrap); 879 } catch (Throwable e) { 880 reporter.report("For change <" + change.getMarker() + "> message : " + e.getMessage()); 881 } finally { 882 new GetAction() { 883 @Override 884 public void run(Object... parameters) { 885 ((TextInputControlSkin) controlInstance.getSkin()).setCaretAnimating(true); 886 } 887 }.dispatch(Root.ROOT.getEnvironment()); 888 } 889 new GetAction() { 890 @Override 891 public void run(Object... os) throws Exception { 892 control.setText(text); 893 } 894 }.dispatch(Root.ROOT.getEnvironment()); 895 System.err.println(">>got text: " + getTextFromControl(wrap.getControl())); 896 wrap.waitState(new State() { 897 public Object reached() { 898 String currentText = getTextFromControl(wrap.getControl()); 899 return text.equalsIgnoreCase(currentText) ? 42 : null; 900 } 901 }); 902 903 wrap.waitState(new State() { 904 String s1; 905 String s2; 906 907 public Object reached() { 908 s1 = text.toUpperCase(); 909 s2 = getTextFromControl(wrap.getControl()).toUpperCase(); 910 return s1.equals(s2) ? true : null; 911 } 912 913 public String toString() { 914 return "s1 = <" + s1 + ">, s2 = <" + s2 + ">."; 915 } 916 }); 917 } 918 919 String getTextFromControl(final TextInputControl cntrl) { 920 return new GetAction<String>() { 921 @Override 922 public void run(Object... os) throws Exception { 923 setResult(cntrl.getText()); 924 } 925 }.dispatch(Root.ROOT.getEnvironment()); 926 } 927 928 String getTextFromControl() { 929 return new GetAction<String>() { 930 @Override 931 public void run(Object... os) throws Exception { 932 setResult(taTesting.getControl().getText()); 933 } 934 }.dispatch(Root.ROOT.getEnvironment()); 935 } 936 937 void forward() { 938 new GetAction<Void>() { 939 @Override 940 public void run(Object... os) throws Exception { 941 taTesting.getControl().forward(); 942 } 943 }.dispatch(Root.ROOT.getEnvironment()); 944 } 945 946 void home() { 947 new GetAction<Void>() { 948 @Override 949 public void run(Object... os) throws Exception { 950 taTesting.getControl().home(); 951 } 952 }.dispatch(Root.ROOT.getEnvironment()); 953 } 954 955 private boolean isPasswordField() { 956 return new GetAction<Boolean>() { 957 @Override 958 public void run(Object... os) throws Exception { 959 setResult(PasswordField.class.isAssignableFrom(taTesting.getControl().getClass())); 960 } 961 }.dispatch(Root.ROOT.getEnvironment()); 962 } 963 964 void end() { 965 new GetAction<Void>() { 966 @Override 967 public void run(Object... os) throws Exception { 968 taTesting.getControl().end(); 969 } 970 }.dispatch(Root.ROOT.getEnvironment()); 971 } 972 973 public class ReporterImpl extends Reporter { 974 975 protected boolean failed = false; 976 protected HashSet<String> reasons = new HashSet<String>(); 977 978 public boolean isFailed() { 979 return failed; 980 } 981 982 public String getReason() { 983 String reason = "Fault reasons:\n"; 984 for (String str : reasons) { 985 reason += " <" + str + ">\n"; 986 } 987 return reason; 988 } 989 990 @Override 991 public void report(String string) { 992 failed = true; 993 reasons.add(string + "\n" + getStackTrace()); 994 } 995 996 protected String getStackTrace() { 997 String trace = "Stack trace:\n"; 998 for (StackTraceElement ste : new Throwable().getStackTrace()) { 999 trace += "\t" + ste + "\n"; 1000 } 1001 return trace; 1002 } 1003 } 1004 1005 protected static String createLongString(int length) { 1006 StringBuilder builder = new StringBuilder("L"); 1007 for (int j = 0; j < length - 3; j++) { 1008 builder.append("o"); 1009 } 1010 builder.append("ng"); 1011 return builder.substring(0, length).toString(); 1012 } 1013 }