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 static org.fest.swing.fixture.ComponentFixtureValidator.notNullRobot;
019    
020    import java.util.regex.Pattern;
021    
022    import javax.swing.JOptionPane;
023    
024    import org.fest.swing.core.*;
025    import org.fest.swing.driver.JOptionPaneDriver;
026    import org.fest.swing.exception.ComponentLookupException;
027    import org.fest.swing.timing.Timeout;
028    
029    /**
030     * Understands functional testing of <code>{@link JOptionPane}</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 Alex Ruiz
038     */
039    public class JOptionPaneFixture extends ContainerFixture<JOptionPane> implements CommonComponentFixture {
040    
041      private JOptionPaneDriver driver;
042    
043      /**
044       * Creates a new <code>{@link JOptionPaneFixture}</code>.
045       * @param robot finds a showing {@code JOptionPane}, which will be managed by this fixture.
046       * @throws NullPointerException if <code>robot</code> is <code>null</code>.
047       * @throws ComponentLookupException if a showing {@code JOptionPane} could not be found.
048       * @throws ComponentLookupException if more than one showing {@code JOptionPane} is found.
049       */
050      public JOptionPaneFixture(Robot robot) {
051        this(robot, findShowingOptionPane(robot));
052      }
053    
054      private static JOptionPane findShowingOptionPane(Robot robot) {
055        notNullRobot(robot);
056        return robot.finder().findByType(JOptionPane.class, true);
057      }
058    
059      /**
060       * Creates a new <code>{@link JOptionPaneFixture}</code>.
061       * @param robot performs simulation of user events on the given {@code JOptionPane}.
062       * @param target the {@code JOptionPane} to be managed by this fixture.
063       * @throws NullPointerException if <code>robot</code> is <code>null</code>.
064       * @throws IllegalArgumentException if <code>target</code> is <code>null</code>.
065       */
066      public JOptionPaneFixture(Robot robot, JOptionPane target) {
067        super(robot, target);
068        driver(new JOptionPaneDriver(robot));
069      }
070    
071      /**
072       * Sets the <code>{@link JOptionPaneDriver}</code> to be used by this fixture.
073       * @param newDriver the new <code>JOptionPaneDriver</code>.
074       * @throws NullPointerException if the given driver is <code>null</code>.
075       */
076      protected final void driver(JOptionPaneDriver newDriver) {
077        validateNotNull(newDriver);
078        driver = newDriver;
079      }
080    
081      /**
082       * Returns the title of this fixture's <code>{@link JOptionPane}</code>.
083       * @return the title of this fixture's {@code JOptionPane}.
084       * @since 1.2
085       */
086      public String title() {
087        return driver.title(target);
088      }
089    
090      /**
091       * Returns a fixture wrapping the "OK" button in this fixture's <code>{@link JOptionPane}</code>. This method is
092       * locale-independent and platform-independent.
093       * @return a fixture wrapping the "OK" button.
094       * @throws ComponentLookupException if the a "OK" button cannot be found.
095       */
096      public JButtonFixture okButton() {
097        return new JButtonFixture(robot, driver.okButton(target));
098      }
099    
100      /**
101       * Returns a fixture wrapping the "Cancel" button in this fixture's <code>{@link JOptionPane}</code>. This method is
102       * locale-independent and platform-independent.
103       * @return a fixture wrapping the "Cancel" button.
104       * @throws ComponentLookupException if the a "Cancel" button cannot be found.
105       */
106      public JButtonFixture cancelButton() {
107        return new JButtonFixture(robot, driver.cancelButton(target));
108      }
109    
110      /**
111       * Returns a fixture wrapping the "Yes" button in this fixture's <code>{@link JOptionPane}</code>. This method is
112       * locale-independent and platform-independent.
113       * @return a fixture wrapping the "Yes" button.
114       * @throws ComponentLookupException if the a "Yes" button cannot be found.
115       */
116      public JButtonFixture yesButton() {
117        return new JButtonFixture(robot, driver.yesButton(target));
118      }
119    
120      /**
121       * Returns a fixture wrapping the "No" button in this fixture's <code>{@link JOptionPane}</code>. This method is
122       * locale-independent and platform-independent.
123       * @return a fixture wrapping the "No" button.
124       * @throws ComponentLookupException if the a "No" button cannot be found.
125       */
126      public JButtonFixture noButton() {
127        return new JButtonFixture(robot, driver.noButton(target));
128      }
129    
130      /**
131       * Finds and returns a fixture wrapping a button (this fixture's <code>{@link JOptionPane}</code>) matching the
132       * given text.
133       * @param text the text of the button to find. It can be a regular expression.
134       * @return a fixture wrapping a button matching the given text.
135       * @throws ComponentLookupException if the a button with the given text cannot be found.
136       */
137      public JButtonFixture buttonWithText(String text) {
138        return new JButtonFixture(robot, driver.buttonWithText(target, text));
139      }
140    
141      /**
142       * Finds and returns a fixture wrapping a button (this fixture's <code>{@link JOptionPane}</code>) matching the
143       * given text.
144       * @param pattern the regular expression pattern to match.
145       * @return a fixture wrapping a button matching the given regular expression pattern.
146       * @throws NullPointerException if the given regular expression pattern is <code>null</code>.
147       * @throws ComponentLookupException if the a button with the given text cannot be found.
148       * @since 1.2
149       */
150      public JButtonFixture buttonWithText(Pattern pattern) {
151        return new JButtonFixture(robot, driver.buttonWithText(target, pattern));
152      }
153    
154      /**
155       * Simulates a user clicking this fixture's <code>{@link JOptionPane}</code>.
156       * @return this fixture.
157       * @throws IllegalStateException if this fixture's {@code JOptionPane} is disabled.
158       * @throws IllegalStateException if this fixture's {@code JOptionPane} is not showing on the screen.
159       */
160      public JOptionPaneFixture click() {
161        driver.click(target);
162        return this;
163      }
164    
165      /**
166       * Simulates a user clicking this fixture's <code>{@link JOptionPane}</code>.
167       * @param button the button to click.
168       * @throws NullPointerException if the given <code>MouseButton</code> is <code>null</code>.
169       * @throws IllegalStateException if this fixture's {@code JOptionPane} is disabled.
170       * @throws IllegalStateException if this fixture's {@code JOptionPane} is not showing on the screen.
171       * @return this fixture.
172       */
173      public JOptionPaneFixture click(MouseButton button) {
174        driver.click(target, button);
175        return this;
176      }
177    
178      /**
179       * Simulates a user clicking this fixture's <code>{@link JOptionPane}</code>.
180       * @param mouseClickInfo specifies the button to click and the times the button should be clicked.
181       * @return this fixture.
182       * @throws NullPointerException if the given <code>MouseClickInfo</code> is <code>null</code>.
183       * @throws IllegalStateException if this fixture's {@code JOptionPane} is disabled.
184       * @throws IllegalStateException if this fixture's {@code JOptionPane} is not showing on the screen.
185       */
186      public JOptionPaneFixture click(MouseClickInfo mouseClickInfo) {
187        driver.click(target, mouseClickInfo);
188        return this;
189      }
190    
191      /**
192       * Simulates a user right-clicking this fixture's <code>{@link JOptionPane}</code>.
193       * @return this fixture.
194       * @throws IllegalStateException if this fixture's {@code JOptionPane} is disabled.
195       * @throws IllegalStateException if this fixture's {@code JOptionPane} is not showing on the screen.
196       */
197      public JOptionPaneFixture rightClick() {
198        driver.rightClick(target);
199        return this;
200      }
201    
202      /**
203       * Simulates a user double-clicking this fixture's <code>{@link JOptionPane}</code>.
204       * @return this fixture.
205       * @throws IllegalStateException if this fixture's {@code JOptionPane} is disabled.
206       * @throws IllegalStateException if this fixture's {@code JOptionPane} is not showing on the screen.
207       */
208      public JOptionPaneFixture doubleClick() {
209        driver.doubleClick(target);
210        return this;
211      }
212    
213      /**
214       * Gives input focus to this fixture's <code>{@link JOptionPane}</code>.
215       * @return this fixture.
216       * @throws IllegalStateException if this fixture's {@code JOptionPane} is disabled.
217       * @throws IllegalStateException if this fixture's {@code JOptionPane} is not showing on the screen.
218       */
219      public JOptionPaneFixture focus() {
220        driver.focus(target);
221        return this;
222      }
223    
224      /**
225       * Asserts that this fixture's <code>{@link JOptionPane}</code> is displaying an error message.
226       * @return this fixture.
227       */
228      public JOptionPaneFixture requireErrorMessage() {
229        driver.requireErrorMessage(target);
230        return this;
231      }
232    
233      /**
234       * Asserts that this fixture's <code>{@link JOptionPane}</code> is displaying an information
235       * message.
236       * @return this fixture.
237       */
238      public JOptionPaneFixture requireInformationMessage() {
239        driver.requireInformationMessage(target);
240        return this;
241      }
242    
243      /**
244       * Asserts that this fixture's <code>{@link JOptionPane}</code> is displaying a warning message.
245       * @return this fixture.
246       */
247      public JOptionPaneFixture requireWarningMessage() {
248        driver.requireWarningMessage(target);
249        return this;
250      }
251    
252      /**
253       * Asserts that this fixture's <code>{@link JOptionPane}</code> is displaying a question.
254       * @return this fixture.
255       */
256      public JOptionPaneFixture requireQuestionMessage() {
257        driver.requireQuestionMessage(target);
258        return this;
259      }
260    
261      /**
262       * Asserts that this fixture's <code>{@link JOptionPane}</code> is displaying a plain message.
263       * @return this fixture.
264       */
265      public JOptionPaneFixture requirePlainMessage() {
266        driver.requirePlainMessage(target);
267        return this;
268      }
269    
270      /**
271       * Simulates a user pressing given key with the given modifiers on this fixture's <code>{@link JOptionPane}</code>.
272       * Modifiers is a mask from the available <code>{@link java.awt.event.InputEvent}</code> masks.
273       * @param keyPressInfo specifies the key and modifiers to press.
274       * @return this fixture.
275       * @throws NullPointerException if the given <code>KeyPressInfo</code> is <code>null</code>.
276       * @throws IllegalArgumentException if the given code is not a valid key code.
277       * @see KeyPressInfo
278       */
279      public JOptionPaneFixture pressAndReleaseKey(KeyPressInfo keyPressInfo) {
280        driver.pressAndReleaseKey(target, keyPressInfo);
281        return this;
282      }
283    
284      /**
285       * Simulates a user pressing and releasing the given keys this fixture's <code>{@link JOptionPane}</code>. This method
286       * does not affect the current focus.
287       * @param keyCodes one or more codes of the keys to press.
288       * @return this fixture.
289       * @throws NullPointerException if the given array of codes is <code>null</code>.
290       * @throws IllegalArgumentException if any of the given code is not a valid key code.
291       * @see java.awt.event.KeyEvent
292       */
293      public JOptionPaneFixture pressAndReleaseKeys(int... keyCodes) {
294        driver.pressAndReleaseKeys(target, keyCodes);
295        return this;
296      }
297    
298      /**
299       * Simulates a user pressing the given key on this fixture's <code>{@link JOptionPane}</code>.
300       * @param keyCode the code of the key to press.
301       * @return this fixture.
302       * @throws IllegalArgumentException if any of the given code is not a valid key code.
303       * @see java.awt.event.KeyEvent
304       */
305      public JOptionPaneFixture pressKey(int keyCode) {
306        driver.pressKey(target, keyCode);
307        return this;
308      }
309    
310      /**
311       * Simulates a user releasing the given key on this fixture's <code>{@link JOptionPane}</code>.
312       * @param keyCode the code of the key to release.
313       * @return this fixture.
314       * @throws IllegalArgumentException if any of the given code is not a valid key code.
315       * @see java.awt.event.KeyEvent
316       */
317      public JOptionPaneFixture releaseKey(int keyCode) {
318        driver.releaseKey(target, keyCode);
319        return this;
320      }
321    
322      /**
323       * Asserts that the title of this fixture's <code>{@link JOptionPane}</code> matches the given value.
324       * @param title the title to match. It can be a regular expression.
325       * @return this fixture.
326       * @throws AssertionError if this fixture's </code>JOptionPaneFixture</code> does not have the given title.
327       */
328      public JOptionPaneFixture requireTitle(String title) {
329        driver.requireTitle(target, title);
330        return this;
331      }
332    
333      /**
334       * Asserts that the title of this fixture's <code>{@link JOptionPane}</code> matches the given regular expression
335       * pattern.
336       * @param pattern the regular expression pattern to match.
337       * @return this fixture.
338       * @throws NullPointerException if the given regular expression is <code>null</code>.
339       * @throws AssertionError if this fixture's </code>JOptionPaneFixture</code> does not have the given title.
340       * @since 1.2
341       */
342      public JOptionPaneFixture requireTitle(Pattern pattern) {
343        driver.requireTitle(target, pattern);
344        return this;
345      }
346    
347      /**
348       * Asserts that the message of this fixture's <code>{@link JOptionPane}</code> matches the given value.
349       * @param message the message to verify. If it is a <code>String</code>, it can be specified as a regular expression.
350       * @return this fixture.
351       * @throws AssertionError if the message in this fixture's </code>JOptionPaneFixture</code> is not equal to or does
352       * not match the given message.
353       */
354      public JOptionPaneFixture requireMessage(Object message) {
355        driver.requireMessage(target, message);
356        return this;
357      }
358    
359      /**
360       * Asserts that the message of this fixture's <code>{@link JOptionPane}</code> matches the given regular expression
361       * pattern. If the message in the {@code JOptionPane} is not a <code>String</code>, this method will use the
362       * <code>toString</code> representation of such message.
363       * @param pattern the regular expression to match.
364       * @return this fixture.
365       * @throws NullPointerException if the given regular expression pattern is <code>null</code>.
366       * @throws AssertionError if the message in this fixture's </code>JOptionPaneFixture</code> does not match the given
367       * regular expression pattern.
368       * @since 1.2
369       */
370      public JOptionPaneFixture requireMessage(Pattern pattern) {
371        driver.requireMessage(target, pattern);
372        return this;
373      }
374    
375      /**
376       * Asserts that this fixture's <code>{@link JOptionPane}</code> has the given options.
377       * @param options the options to verify.
378       * @return this fixture.
379       * @throws AssertionError if this fixture's </code>JOptionPaneFixture</code> does not have the given options.
380       */
381      public JOptionPaneFixture requireOptions(Object[] options) {
382        driver.requireOptions(target, options);
383        return this;
384      }
385    
386      /**
387       * Asserts that this fixture's <code>{@link JOptionPane}</code> has input focus.
388       * @return this fixture.
389       * @throws AssertionError if this fixture's {@code JOptionPane} does not have input focus.
390       */
391      public JOptionPaneFixture requireFocused() {
392        driver.requireFocused(target);
393        return this;
394      }
395    
396      /**
397       * Asserts that this fixture's <code>{@link JOptionPane}</code> is enabled.
398       * @return this fixture.
399       * @throws AssertionError if this fixture's {@code JOptionPane} is disabled.
400       */
401      public JOptionPaneFixture requireEnabled() {
402        driver.requireEnabled(target);
403        return this;
404      }
405    
406      /**
407       * Asserts that this fixture's <code>{@link JOptionPane}</code> is enabled.
408       * @param timeout the time this fixture will wait for the component to be enabled.
409       * @return this fixture.
410       * @throws org.fest.swing.exception.WaitTimedOutError if this fixture's {@code JOptionPane} is never enabled.
411       */
412      public JOptionPaneFixture requireEnabled(Timeout timeout) {
413        driver.requireEnabled(target, timeout);
414        return this;
415      }
416    
417      /**
418       * Asserts that this fixture's <code>{@link JOptionPane}</code> is disabled.
419       * @return this fixture.
420       * @throws AssertionError if this fixture's {@code JOptionPane} is enabled.
421       */
422      public JOptionPaneFixture requireDisabled() {
423        driver.requireDisabled(target);
424        return this;
425      }
426    
427      /**
428       * Asserts that this fixture's <code>{@link JOptionPane}</code> is visible.
429       * @return this fixture.
430       * @throws AssertionError if this fixture's {@code JOptionPane} is not visible.
431       */
432      public JOptionPaneFixture requireVisible() {
433        driver.requireVisible(target);
434        return this;
435      }
436    
437      /**
438       * Asserts that this fixture's <code>{@link JOptionPane}</code> is not visible.
439       * @return this fixture.
440       * @throws AssertionError if this fixture's {@code JOptionPane} is visible.
441       */
442      public JOptionPaneFixture requireNotVisible() {
443        driver.requireNotVisible(target);
444        return this;
445      }
446    }