001 /* 002 * Created on Jul 1, 2007 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 @2007-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.JSpinner; 022 import javax.swing.text.JTextComponent; 023 024 import org.fest.swing.core.*; 025 import org.fest.swing.driver.JSpinnerDriver; 026 import org.fest.swing.exception.*; 027 import org.fest.swing.timing.Timeout; 028 029 /** 030 * Understands functional testing of <code>{@link JSpinner}</code>s: 031 * <ul> 032 * <li>user input simulation</li> 033 * <li>state verification</li> 034 * <li>property value query</li> 035 * </ul> 036 * 037 * @author Yvonne Wang 038 * @author Alex Ruiz 039 */ 040 public class JSpinnerFixture extends ComponentFixture<JSpinner> implements CommonComponentFixture, 041 JComponentFixture, JPopupMenuInvokerFixture { 042 043 private JSpinnerDriver driver; 044 045 /** 046 * Creates a new <code>{@link JSpinnerFixture}</code>. 047 * @param robot performs simulation of user events on a <code>JSpinner</code>. 048 * @param spinnerName the name of the <code>JSpinner</code> to find using the given <code>Robot</code>. 049 * @throws NullPointerException if <code>robot</code> is <code>null</code>. 050 * @throws ComponentLookupException if a matching <code>JSpinner</code> could not be found. 051 * @throws ComponentLookupException if more than one matching <code>JSpinner</code> is found. 052 */ 053 public JSpinnerFixture(Robot robot, String spinnerName) { 054 super(robot, spinnerName, JSpinner.class); 055 createDriver(); 056 } 057 058 /** 059 * Creates a new <code>{@link JSpinnerFixture}</code>. 060 * @param robot performs simulation of user events on the given <code>JSpinner</code>. 061 * @param target the <code>JSpinner</code> to be managed by this fixture. 062 * @throws NullPointerException if <code>robot</code> is <code>null</code>. 063 * @throws NullPointerException if <code>target</code> is <code>null</code>. 064 */ 065 public JSpinnerFixture(Robot robot, JSpinner target) { 066 super(robot, target); 067 createDriver(); 068 } 069 070 private void createDriver() { 071 driver(new JSpinnerDriver(robot)); 072 } 073 074 /** 075 * Sets the <code>{@link JSpinnerDriver}</code> to be used by this fixture. 076 * @param newDriver the new <code>JSpinnerDriver</code>. 077 * @throws NullPointerException if the given driver is <code>null</code>. 078 */ 079 protected final void driver(JSpinnerDriver newDriver) { 080 validateNotNull(newDriver); 081 driver = newDriver; 082 } 083 084 /** 085 * Simulates a user incrementing the value of this fixture's <code>{@link JSpinner}</code> the given number of times. 086 * @param times how many times the value of this fixture's <code>JSpinner</code> should be incremented. 087 * @return this fixture. 088 * @throws IllegalArgumentException if <code>times</code> is less than or equal to zero. 089 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is disabled. 090 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is not showing on the screen. 091 */ 092 public JSpinnerFixture increment(int times) { 093 driver.increment(target, times); 094 return this; 095 } 096 097 /** 098 * Simulates a user incrementing the value of this fixture's <code>{@link JSpinner}</code> one time. 099 * @return this fixture. 100 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is disabled. 101 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is not showing on the screen. 102 */ 103 public JSpinnerFixture increment() { 104 driver.increment(target); 105 return this; 106 } 107 108 /** 109 * Simulates a user decrementing the value of this fixture's <code>{@link JSpinner}</code> the given number of times. 110 * @param times how many times the value of this fixture's <code>JSpinner</code> should be decremented. 111 * @return this fixture. 112 * @throws IllegalArgumentException if <code>times</code> is less than or equal to zero. 113 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is disabled. 114 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is not showing on the screen. 115 */ 116 public JSpinnerFixture decrement(int times) { 117 driver.decrement(target, times); 118 return this; 119 } 120 121 /** 122 * Simulates a user decrementing the value of this fixture's <code>{@link JSpinner}</code> one time. 123 * @return this fixture. 124 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is disabled. 125 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is not showing on the screen. 126 */ 127 public JSpinnerFixture decrement() { 128 driver.decrement(target); 129 return this; 130 } 131 132 /** 133 * Simulates a user entering the given text in this fixture's <code>{@link JSpinner}</code> (assuming its editor has a 134 * <code>{@link JTextComponent}</code> under it.) This method does not commit the value to the <code>JSpinner</code>. 135 * @param text the text to enter. 136 * @return this fixture. 137 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is disabled. 138 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is not showing on the screen. 139 * @throws ActionFailedException if the editor of the <code>JSpinner</code> is not a <code>JTextComponent</code> or 140 * cannot be found. 141 * @throws UnexpectedException if the entering the text in the <code>JSpinner</code>'s editor fails. 142 */ 143 public JSpinnerFixture enterText(String text) { 144 driver.enterText(target, text); 145 return this; 146 } 147 148 /** 149 * Simulates a user entering and committing the given text in this fixture's <code>{@link JSpinner}</code> (assuming 150 * its editor has a <code>{@link JTextComponent}</code> under it.) 151 * @param text the text to enter. 152 * @return this fixture. 153 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is disabled. 154 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is not showing on the screen. 155 * @throws ActionFailedException if the editor of the <code>JSpinner</code> is not a <code>JTextComponent</code> or 156 * cannot be found. 157 * @throws UnexpectedException if the entering the text in the <code>JSpinner</code>'s editor fails. 158 */ 159 public JSpinnerFixture enterTextAndCommit(String text) { 160 driver.enterTextAndCommit(target, text); 161 return this; 162 } 163 164 /** 165 * Selects the given value in this fixture's <code>{@link JSpinner}</code>. 166 * @param value the value to select. 167 * @return this fixture. 168 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is disabled. 169 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is not showing on the screen. 170 * @throws IllegalArgumentException if the <code>JSpinner</code> does not support the specified <code>value</code>. 171 */ 172 public Object select(Object value) { 173 driver.selectValue(target, value); 174 return this; 175 } 176 177 /** 178 * Simulates a user clicking this fixture's <code>{@link JSpinner}</code>. 179 * @return this fixture. 180 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is disabled. 181 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is not showing on the screen. 182 */ 183 public JSpinnerFixture click() { 184 driver.click(target); 185 return this; 186 } 187 188 /** 189 * Simulates a user clicking this fixture's <code>{@link JSpinner}</code>. 190 * @param button the button to click. 191 * @return this fixture. 192 * @throws NullPointerException if the given <code>MouseButton</code> is <code>null</code>. 193 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is disabled. 194 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is not showing on the screen. 195 */ 196 public JSpinnerFixture click(MouseButton button) { 197 driver.click(target, button); 198 return this; 199 } 200 201 /** 202 * Simulates a user clicking this fixture's <code>{@link JSpinner}</code>. 203 * @param mouseClickInfo specifies the button to click and the times the button should be clicked. 204 * @return this fixture. 205 * @throws NullPointerException if the given <code>MouseClickInfo</code> is <code>null</code>. 206 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is disabled. 207 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is not showing on the screen. 208 */ 209 public JSpinnerFixture click(MouseClickInfo mouseClickInfo) { 210 driver.click(target, mouseClickInfo); 211 return this; 212 } 213 214 /** 215 * Simulates a user right-clicking this fixture's <code>{@link JSpinner}</code>. 216 * @return this fixture. 217 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is disabled. 218 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is not showing on the screen. 219 */ 220 public JSpinnerFixture rightClick() { 221 driver.rightClick(target); 222 return this; 223 } 224 225 /** 226 * Simulates a user double-clicking this fixture's <code>{@link JSpinner}</code>. 227 * @return this fixture. 228 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is disabled. 229 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is not showing on the screen. 230 */ 231 public JSpinnerFixture doubleClick() { 232 driver.doubleClick(target); 233 return this; 234 } 235 236 /** 237 * Gives input focus to this fixture's <code>{@link JSpinner}</code>. 238 * @return this fixture. 239 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is disabled. 240 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is not showing on the screen. 241 */ 242 public JSpinnerFixture focus() { 243 driver.focus(target); 244 return this; 245 } 246 247 /** 248 * Simulates a user pressing given key with the given modifiers on this fixture's <code>{@link JSpinner}</code>. 249 * Modifiers is a mask from the available <code>{@link java.awt.event.InputEvent}</code> masks. 250 * @param keyPressInfo specifies the key and modifiers to press. 251 * @return this fixture. 252 * @throws NullPointerException if the given <code>KeyPressInfo</code> is <code>null</code>. 253 * @throws IllegalArgumentException if the given code is not a valid key code. 254 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is disabled. 255 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is not showing on the screen. 256 * @see KeyPressInfo 257 */ 258 public JSpinnerFixture pressAndReleaseKey(KeyPressInfo keyPressInfo) { 259 driver.pressAndReleaseKey(target, keyPressInfo); 260 return this; 261 } 262 263 /** 264 * Simulates a user pressing and releasing the given keys on this fixture's <code>{@link JSpinner}</code>. This method 265 * does not affect the current focus. 266 * @param keyCodes one or more codes of the keys to press. 267 * @return this fixture. 268 * @throws NullPointerException if the given array of codes is <code>null</code>. 269 * @throws IllegalArgumentException if any of the given code is not a valid key code. 270 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is disabled. 271 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is not showing on the screen. 272 * @see java.awt.event.KeyEvent 273 */ 274 public JSpinnerFixture pressAndReleaseKeys(int... keyCodes) { 275 driver.pressAndReleaseKeys(target, keyCodes); 276 return this; 277 } 278 279 /** 280 * Simulates a user pressing the given key on this fixture's <code>{@link JSpinner}</code>. 281 * @param keyCode the code of the key to press. 282 * @return this fixture. 283 * @throws IllegalArgumentException if any of the given code is not a valid key code. 284 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is disabled. 285 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is not showing on the screen. 286 * @see java.awt.event.KeyEvent 287 */ 288 public JSpinnerFixture pressKey(int keyCode) { 289 driver.pressKey(target, keyCode); 290 return this; 291 } 292 293 /** 294 * Simulates a user releasing the given key on this fixture's <code>{@link JSpinner}</code>. 295 * @param keyCode the code of the key to release. 296 * @return this fixture. 297 * @throws IllegalArgumentException if any of the given code is not a valid key code. 298 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is disabled. 299 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is not showing on the screen. 300 * @see java.awt.event.KeyEvent 301 */ 302 public JSpinnerFixture releaseKey(int keyCode) { 303 driver.releaseKey(target, keyCode); 304 return this; 305 } 306 307 /** 308 * Asserts that this fixture's <code>{@link JSpinner}</code> has input focus. 309 * @return this fixture. 310 * @throws AssertionError if this fixture's <code>JSpinner</code> does not have input focus. 311 */ 312 public JSpinnerFixture requireFocused() { 313 driver.requireFocused(target); 314 return this; 315 } 316 317 /** 318 * Asserts that this fixture's <code>{@link JSpinner}</code> is enabled. 319 * @return this fixture. 320 * @throws AssertionError if this fixture's <code>JSpinner</code> is disabled. 321 */ 322 public JSpinnerFixture requireEnabled() { 323 driver.requireEnabled(target); 324 return this; 325 } 326 327 /** 328 * Asserts that this fixture's <code>{@link JSpinner}</code> is enabled. 329 * @param timeout the time this fixture will wait for the component to be enabled. 330 * @return this fixture. 331 * @throws org.fest.swing.exception.WaitTimedOutError if this fixture's <code>JSpinner</code> is never enabled. 332 */ 333 public JSpinnerFixture requireEnabled(Timeout timeout) { 334 driver.requireEnabled(target, timeout); 335 return this; 336 } 337 338 /** 339 * Asserts that this fixture's <code>{@link JSpinner}</code> is disabled. 340 * @return this fixture. 341 * @throws AssertionError if this fixture's <code>JSpinner</code> is enabled. 342 */ 343 public JSpinnerFixture requireDisabled() { 344 driver.requireDisabled(target); 345 return this; 346 } 347 348 /** 349 * Asserts that this fixture's <code>{@link JSpinner}</code> is visible. 350 * @return this fixture. 351 * @throws AssertionError if this fixture's <code>JSpinner</code> is not visible. 352 */ 353 public JSpinnerFixture requireVisible() { 354 driver.requireVisible(target); 355 return this; 356 } 357 358 /** 359 * Asserts that this fixture's <code>{@link JSpinner}</code> is not visible. 360 * @return this fixture. 361 * @throws AssertionError if this fixture's <code>JSpinner</code> is visible. 362 */ 363 public JSpinnerFixture requireNotVisible() { 364 driver.requireNotVisible(target); 365 return this; 366 } 367 368 /** 369 * Verifies that the value of this fixture's <code>{@link JSpinner}</code> is equal to the given one. 370 * @param value the expected value of this fixture's <code>JSpinner</code>. 371 * @return this fixture. 372 * @throws AssertionError if the value of this fixture's <code>JSpinner</code> is not equal to the given one. 373 */ 374 public JSpinnerFixture requireValue(Object value) { 375 driver.requireValue(target, value); 376 return this; 377 } 378 379 /** 380 * Returns the text displayed by this fixture's <code>{@link JSpinner}</code>. This method first tries to get the text 381 * displayed in the <code>JSpinner</code>'s editor, assuming it is a <code>{@link JTextComponent}</code>. If the 382 * text from the editor cannot be retrieved, it will return the <code>String</code> representation of the value 383 * in the <code>JSpinner</code>'s model. 384 * @return the text displayed by this fixture's <code>JSpinner</code>. 385 * @since 1.2 386 */ 387 public String text() { 388 return driver.textOf(target); 389 } 390 391 392 /** 393 * Asserts that the toolTip in this fixture's <code>{@link JSpinner}</code> matches the given value. 394 * @param expected the given value. It can be a regular expression. 395 * @return this fixture. 396 * @throws AssertionError if the toolTip in this fixture's <code>JSpinner</code> does not match the given value. 397 * @since 1.2 398 */ 399 public JSpinnerFixture requireToolTip(String expected) { 400 driver.requireToolTip(target, expected); 401 return this; 402 } 403 404 /** 405 * Asserts that the toolTip in this fixture's <code>{@link JSpinner}</code> matches the given regular expression 406 * pattern. 407 * @param pattern the regular expression pattern to match. 408 * @return this fixture. 409 * @throws NullPointerException if the given regular expression pattern is <code>null</code>. 410 * @throws AssertionError if the toolTip in this fixture's <code>JSpinner</code> does not match the given regular 411 * expression. 412 * @since 1.2 413 */ 414 public JSpinnerFixture requireToolTip(Pattern pattern) { 415 driver.requireToolTip(target, pattern); 416 return this; 417 } 418 419 /** 420 * Returns the client property stored in this fixture's <code>{@link JSpinner}</code>, under the given key. 421 * @param key the key to use to retrieve the client property. 422 * @return the value of the client property stored under the given key, or <code>null</code> if the property was 423 * not found. 424 * @throws NullPointerException if the given key is <code>null</code>. 425 * @since 1.2 426 */ 427 public Object clientProperty(Object key) { 428 return driver.clientProperty(target, key); 429 } 430 431 /** 432 * Shows a pop-up menu using this fixture's <code>{@link JSpinner}</code> as the invoker of the pop-up menu. 433 * @return a fixture that manages the displayed pop-up menu. 434 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is disabled. 435 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is not showing on the screen. 436 * @throws ComponentLookupException if a pop-up menu cannot be found. 437 */ 438 public JPopupMenuFixture showPopupMenu() { 439 return new JPopupMenuFixture(robot, driver.invokePopupMenu(target)); 440 } 441 442 /** 443 * Shows a pop-up menu at the given point using this fixture's <code>{@link JSpinner}</code> as the invoker of the 444 * pop-up menu. 445 * @param p the given point where to show the pop-up menu. 446 * @return a fixture that manages the displayed pop-up menu. 447 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is disabled. 448 * @throws IllegalStateException if this fixture's <code>JSpinner</code> is not showing on the screen. 449 * @throws ComponentLookupException if a pop-up menu cannot be found. 450 */ 451 public JPopupMenuFixture showPopupMenuAt(Point p) { 452 return new JPopupMenuFixture(robot, driver.invokePopupMenu(target, p)); 453 } 454 }