001 /* 002 * Created on Oct 20, 2006 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 005 * in compliance with the License. You may obtain a copy of the License at 006 * 007 * http://www.apache.org/licenses/LICENSE-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, software distributed under the License 010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 011 * or implied. See the License for the specific language governing permissions and limitations under 012 * the License. 013 * 014 * Copyright @2006-2010 the original author or authors. 015 */ 016 package org.fest.swing.fixture; 017 018 import java.awt.Point; 019 import java.util.regex.Pattern; 020 021 import javax.swing.text.JTextComponent; 022 023 import org.fest.swing.core.*; 024 import org.fest.swing.driver.JTextComponentDriver; 025 import org.fest.swing.exception.*; 026 import org.fest.swing.timing.Timeout; 027 028 /** 029 * Understands functional testing of <code>{@link JTextComponent}</code>s: 030 * <ul> 031 * <li>user input simulation</li> 032 * <li>state verification</li> 033 * <li>property value query</li> 034 * </ul> 035 * 036 * @author Alex Ruiz 037 */ 038 public class JTextComponentFixture extends ComponentFixture<JTextComponent> 039 implements CommonComponentFixture, JComponentFixture, JPopupMenuInvokerFixture, TextInputFixture { 040 041 private JTextComponentDriver driver; 042 043 /** 044 * Creates a new <code>{@link JTextComponentFixture}</code>. 045 * @param robot performs simulation of user events on the given <code>JTextComponent</code>. 046 * @param target the <code>JTextComponent</code> to be managed by this fixture. 047 * @throws NullPointerException if <code>robot</code> is <code>null</code>. 048 * @throws NullPointerException if <code>target</code> is <code>null</code>. 049 */ 050 public JTextComponentFixture(Robot robot, JTextComponent target) { 051 super(robot, target); 052 createDriver(); 053 } 054 055 /** 056 * Creates a new <code>{@link JTextComponentFixture}</code>. 057 * @param robot performs simulation of user events on a <code>JTextComponent</code>. 058 * @param textComponentName the name of the <code>JTextComponent</code> to find using the given <code>Robot</code>. 059 * @throws NullPointerException if <code>robot</code> is <code>null</code>. 060 * @throws ComponentLookupException if a matching <code>JTextComponent</code> could not be found. 061 * @throws ComponentLookupException if more than one matching <code>JTextComponent</code> is found. 062 */ 063 public JTextComponentFixture(Robot robot, String textComponentName) { 064 super(robot, textComponentName, JTextComponent.class); 065 createDriver(); 066 } 067 068 private void createDriver() { 069 driver(new JTextComponentDriver(robot)); 070 } 071 072 /** 073 * Sets the <code>{@link JTextComponentDriver}</code> to be used by this fixture. 074 * @param newDriver the new <code>JTextComponentDriver</code>. 075 * @throws NullPointerException if the given driver is <code>null</code>. 076 */ 077 protected final void driver(JTextComponentDriver newDriver) { 078 validateNotNull(newDriver); 079 driver = newDriver; 080 } 081 082 /** 083 * Returns the text of this fixture's <code>{@link JTextComponent}</code>. 084 * @return the text of this fixture's <code>JTextComponent</code>. 085 */ 086 public String text() { 087 return driver.textOf(target); 088 } 089 090 /** 091 * Simulates a user selecting the given text contained in this fixture's <code>{@link JTextComponent}</code>. 092 * @param text the text to select. 093 * @return this fixture. 094 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is disabled. 095 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is not showing on the screen. 096 * @throws IllegalArgumentException if this fixture's <code>JTextComponent</code> does not contain the given text to 097 * select. 098 * @throws ActionFailedException if the selecting the text in the given range fails. 099 */ 100 public JTextComponentFixture select(String text) { 101 driver.selectText(target, text); 102 return this; 103 } 104 105 /** 106 * Simulates a user selecting a portion of the text contained in this fixture's <code>{@link JTextComponent}</code>. 107 * @param start index where selection should start. 108 * @param end index where selection should end. 109 * @return this fixture. 110 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is disabled. 111 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is not showing on the screen. 112 * @throws ActionFailedException if the selecting the text in the given range fails. 113 */ 114 public JTextComponentFixture selectText(int start, int end) { 115 driver.selectText(target, start, end); 116 return this; 117 } 118 119 /** 120 * Simulates a user selecting all the text contained in this fixture's <code>{@link JTextComponent}</code>. 121 * @return this fixture. 122 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is disabled. 123 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is not showing on the screen. 124 */ 125 public JTextComponentFixture selectAll() { 126 driver.selectAll(target); 127 return this; 128 } 129 130 /** 131 * Simulates a user clicking this fixture's <code>{@link JTextComponent}</code>. 132 * @return this fixture. 133 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is disabled. 134 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is not showing on the screen. 135 */ 136 public JTextComponentFixture click() { 137 driver.click(target); 138 return this; 139 } 140 141 /** 142 * Simulates a user clicking this fixture's <code>{@link JTextComponent}</code>. 143 * @param button the button to click. 144 * @return this fixture. 145 * @throws NullPointerException if the given <code>MouseButton</code> is <code>null</code>. 146 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is disabled. 147 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is not showing on the screen. 148 */ 149 public JTextComponentFixture click(MouseButton button) { 150 driver.click(target, button); 151 return this; 152 } 153 154 /** 155 * Simulates a user clicking this fixture's <code>{@link JTextComponent}</code>. 156 * @param mouseClickInfo specifies the button to click and the times the button should be clicked. 157 * @return this fixture. 158 * @throws NullPointerException if the given <code>MouseClickInfo</code> is <code>null</code>. 159 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is disabled. 160 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is not showing on the screen. 161 */ 162 public JTextComponentFixture click(MouseClickInfo mouseClickInfo) { 163 driver.click(target, mouseClickInfo); 164 return this; 165 } 166 167 /** 168 * Simulates a user double-clicking this fixture's <code>{@link JTextComponent}</code>. 169 * @return this fixture. 170 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is disabled. 171 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is not showing on the screen. 172 */ 173 public JTextComponentFixture doubleClick() { 174 driver.doubleClick(target); 175 return this; 176 } 177 178 /** 179 * Simulates a user right-clicking this fixture's <code>{@link JTextComponent}</code>. 180 * @return this fixture. 181 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is disabled. 182 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is not showing on the screen. 183 */ 184 public JTextComponentFixture rightClick() { 185 driver.rightClick(target); 186 return this; 187 } 188 189 /** 190 * Simulates a user deleting all the text in this fixture's <code>{@link JTextComponent}</code>. 191 * @return this fixture. 192 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is disabled. 193 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is not showing on the screen. 194 */ 195 public JTextComponentFixture deleteText() { 196 driver.deleteText(target); 197 return this; 198 } 199 200 /** 201 * Simulates a user entering the given text in this fixture's <code>{@link JTextComponent}</code>. 202 * @param text the text to enter. 203 * @return this fixture. 204 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is disabled. 205 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is not showing on the screen. 206 */ 207 public JTextComponentFixture enterText(String text) { 208 driver.enterText(target, text); 209 return this; 210 } 211 212 /** 213 * Sets the text in this fixture's <code>{@link JTextComponent}</code>. Unlike 214 * <code>{@link #enterText(String)}</code>, this method bypasses the event system and allows immediate updating on the 215 * underlying document model. 216 * <p> 217 * Primarily desired for speeding up tests when precise user event fidelity isn't necessary. 218 * </p> 219 * @param text the text to set. 220 * @return this fixture. 221 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is disabled. 222 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is not showing on the screen. 223 */ 224 public JTextComponentFixture setText(String text) { 225 driver.setText(target, text); 226 return this; 227 } 228 229 /** 230 * Gives input focus to this fixture's <code>{@link JTextComponent}</code>. 231 * @return this fixture. 232 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is disabled. 233 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is not showing on the screen. 234 */ 235 public JTextComponentFixture focus() { 236 driver.focus(target); 237 return this; 238 } 239 240 /** 241 * Simulates a user pressing given key with the given modifiers on this fixture's <code>{@link JTextComponent}</code>. 242 * Modifiers is a mask from the available <code>{@link java.awt.event.InputEvent}</code> masks. 243 * @param keyPressInfo specifies the key and modifiers to press. 244 * @return this fixture. 245 * @throws NullPointerException if the given <code>KeyPressInfo</code> is <code>null</code>. 246 * @throws IllegalArgumentException if the given code is not a valid key code. 247 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is disabled. 248 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is not showing on the screen. 249 * @see KeyPressInfo 250 */ 251 public JTextComponentFixture pressAndReleaseKey(KeyPressInfo keyPressInfo) { 252 driver.pressAndReleaseKey(target, keyPressInfo); 253 return this; 254 } 255 256 /** 257 * Simulates a user pressing and releasing the given keys in this fixture's <code>{@link JTextComponent}</code>. This 258 * method does not affect the current focus. 259 * @param keyCodes the codes of the keys to press. 260 * @return this fixture. 261 * @throws NullPointerException if the given array of codes is <code>null</code>. 262 * @throws IllegalArgumentException if any of the given code is not a valid key code. 263 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is disabled. 264 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is not showing on the screen. 265 * @see java.awt.event.KeyEvent 266 */ 267 public JTextComponentFixture pressAndReleaseKeys(int...keyCodes) { 268 driver.pressAndReleaseKeys(target, keyCodes); 269 return this; 270 } 271 272 /** 273 * Simulates a user pressing the given key on this fixture's <code>{@link JTextComponent}</code>. 274 * @param keyCode the code of the key to press. 275 * @return this fixture. 276 * @throws IllegalArgumentException if any of the given code is not a valid key code. 277 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is disabled. 278 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is not showing on the screen. 279 * @see java.awt.event.KeyEvent 280 */ 281 public JTextComponentFixture pressKey(int keyCode) { 282 driver.pressKey(target, keyCode); 283 return this; 284 } 285 286 /** 287 * Simulates a user releasing the given key on this fixture's <code>{@link JTextComponent}</code>. 288 * @param keyCode the code of the key to release. 289 * @return this fixture. 290 * @throws IllegalArgumentException if any of the given code is not a valid key code. 291 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is disabled. 292 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is not showing on the screen. 293 * @see java.awt.event.KeyEvent 294 */ 295 public JTextComponentFixture releaseKey(int keyCode) { 296 driver.releaseKey(target, keyCode); 297 return this; 298 } 299 300 /** 301 * Asserts that the text of this fixture's <code>{@link JTextComponent}</code> is equal to the specified value. 302 * @param expected the text to match. It can be a regular expression pattern. 303 * @return this fixture. 304 * @throws AssertionError if the text of this fixture's <code>JTextComponent</code> is not equal to the given one. 305 */ 306 public JTextComponentFixture requireText(String expected) { 307 driver.requireText(target, expected); 308 return this; 309 } 310 311 /** 312 * Asserts that the text of this fixture's <code>{@link JTextComponent}</code> matches the given regular expression 313 * pattern. 314 * @param pattern the regular expression pattern to match. 315 * @return this fixture. 316 * @throws NullPointerException if the given regular expression pattern is <code>null</code>. 317 * @throws AssertionError if the text of this fixture's <code>JTextComponent</code> is not eual to the given one. 318 * @since 1.2 319 */ 320 public JTextComponentFixture requireText(Pattern pattern) { 321 driver.requireText(target, pattern); 322 return this; 323 } 324 325 /** 326 * Asserts that the target text component does not contain any text. 327 * @return this fixture. 328 * @throws AssertionError if the target text component is not empty. 329 */ 330 public JTextComponentFixture requireEmpty() { 331 driver.requireEmpty(target); 332 return this; 333 } 334 335 /** 336 * Asserts that this fixture's <code>{@link JTextComponent}</code> has input focus. 337 * @return this fixture. 338 * @throws AssertionError if this fixture's <code>JTextComponent</code> does not have input focus. 339 */ 340 public JTextComponentFixture requireFocused() { 341 driver.requireFocused(target); 342 return this; 343 } 344 345 /** 346 * Asserts that this fixture's <code>{@link JTextComponent}</code> is enabled. 347 * @return this fixture. 348 * @throws AssertionError if this fixture's <code>JTextComponent</code> is disabled. 349 */ 350 public JTextComponentFixture requireEnabled() { 351 driver.requireEnabled(target); 352 return this; 353 } 354 355 /** 356 * Asserts that this fixture's <code>{@link JTextComponent}</code> is enabled. 357 * @param timeout the time this fixture will wait for the component to be enabled. 358 * @return this fixture. 359 * @throws WaitTimedOutError if this fixture's <code>JTextComponent</code> is never enabled. 360 */ 361 public JTextComponentFixture requireEnabled(Timeout timeout) { 362 driver.requireEnabled(target, timeout); 363 return this; 364 } 365 366 /** 367 * Asserts that this fixture's <code>{@link JTextComponent}</code> is disabled. 368 * @return this fixture. 369 * @throws AssertionError if this fixture's <code>JTextComponent</code> is enabled. 370 */ 371 public JTextComponentFixture requireDisabled() { 372 driver.requireDisabled(target); 373 return this; 374 } 375 376 /** 377 * Asserts that this fixture's <code>{@link JTextComponent}</code> is visible. 378 * @return this fixture. 379 * @throws AssertionError if this fixture's <code>JTextComponent</code> is not visible. 380 */ 381 public JTextComponentFixture requireVisible() { 382 driver.requireVisible(target); 383 return this; 384 } 385 386 /** 387 * Asserts that this fixture's <code>{@link JTextComponent}</code> is not visible. 388 * @return this fixture. 389 * @throws AssertionError if this fixture's <code>JTextComponent</code> is visible. 390 */ 391 public JTextComponentFixture requireNotVisible() { 392 driver.requireNotVisible(target); 393 return this; 394 } 395 396 /** 397 * Asserts that this fixture's <code>{@link JTextComponent}</code> is editable. 398 * @throws AssertionError if this fixture's <code>JTextComponent</code> is not editable. 399 * @return this fixture. 400 */ 401 public JTextComponentFixture requireEditable() { 402 driver.requireEditable(target); 403 return this; 404 } 405 406 /** 407 * Asserts that this fixture's <code>{@link JTextComponent}</code> is not editable. 408 * @throws AssertionError if this fixture's <code>JTextComponent</code> is editable. 409 * @return this fixture. 410 */ 411 public JTextComponentFixture requireNotEditable() { 412 driver.requireNotEditable(target); 413 return this; 414 } 415 416 /** 417 * Asserts that the toolTip in this fixture's <code>{@link JTextComponent}</code> matches the given value. 418 * @param expected the given value. It can be a regular expression. 419 * @return this fixture. 420 * @throws AssertionError if the toolTip in this fixture's <code>JTextComponent</code> does not match the given 421 * value. 422 * @since 1.2 423 */ 424 public JTextComponentFixture requireToolTip(String expected) { 425 driver.requireToolTip(target, expected); 426 return this; 427 } 428 429 /** 430 * Asserts that the toolTip in this fixture's <code>{@link JTextComponent}</code> matches the given regular expression 431 * pattern. 432 * @param pattern the regular expression pattern to match. 433 * @return this fixture. 434 * @throws NullPointerException if the given regular expression pattern is <code>null</code>. 435 * @throws AssertionError if the toolTip in this fixture's <code>JTextComponent</code> does not match the given 436 * regular expression pattern. 437 * @since 1.2 438 */ 439 public JTextComponentFixture requireToolTip(Pattern pattern) { 440 driver.requireToolTip(target, pattern); 441 return this; 442 } 443 444 445 /** 446 * Returns the client property stored in this fixture's <code>{@link JTextComponent}</code>, under the given key. 447 * @param key the key to use to retrieve the client property. 448 * @return the value of the client property stored under the given key, or <code>null</code> if the property was 449 * not found. 450 * @throws NullPointerException if the given key is <code>null</code>. 451 * @since 1.2 452 */ 453 public Object clientProperty(Object key) { 454 return driver.clientProperty(target, key); 455 } 456 457 /** 458 * Shows a pop-up menu using this fixture's <code>{@link JTextComponent}</code> as the invoker of the pop-up menu. 459 * @return a fixture that manages the displayed pop-up menu. 460 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is disabled. 461 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is not showing on the screen. 462 * @throws ComponentLookupException if a pop-up menu cannot be found. 463 */ 464 public JPopupMenuFixture showPopupMenu() { 465 return new JPopupMenuFixture(robot, driver.invokePopupMenu(target)); 466 } 467 468 /** 469 * Shows a pop-up menu at the given point using this fixture's <code>{@link JTextComponent}</code> as the invoker of 470 * the pop-up menu. 471 * @param p the given point where to show the pop-up menu. 472 * @return a fixture that manages the displayed pop-up menu. 473 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is disabled. 474 * @throws IllegalStateException if this fixture's <code>JTextComponent</code> is not showing on the screen. 475 * @throws ComponentLookupException if a pop-up menu cannot be found. 476 */ 477 public JPopupMenuFixture showPopupMenuAt(Point p) { 478 return new JPopupMenuFixture(robot, driver.invokePopupMenu(target, p)); 479 } 480 }