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 }