001    /*
002     * Created on Dec 16, 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.JButton;
022    
023    import org.fest.swing.core.*;
024    import org.fest.swing.driver.AbstractButtonDriver;
025    import org.fest.swing.exception.ComponentLookupException;
026    import org.fest.swing.exception.WaitTimedOutError;
027    import org.fest.swing.timing.Timeout;
028    
029    /**
030     * Understands functional testing of <code>{@link JButton}</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 JButtonFixture extends ComponentFixture<JButton> implements CommonComponentFixture,
041      JComponentFixture, JPopupMenuInvokerFixture, TextDisplayFixture {
042    
043      private AbstractButtonDriver driver;
044    
045      /**
046       * Creates a new <code>{@link JButtonFixture}</code>.
047       * @param target the <code>JButton</code> to be managed by this fixture.
048       * @param robot performs simulation of user events on the given <code>JButton</code>.
049       * @throws NullPointerException if <code>robot</code> is <code>null</code>.
050       * @throws NullPointerException if <code>target</code> is <code>null</code>.
051       */
052      public JButtonFixture(Robot robot, JButton target) {
053        super(robot, target);
054        createDriver();
055      }
056    
057      /**
058       * Creates a new <code>{@link JButtonFixture}</code>.
059       * @param robot performs simulation of user events on a <code>JButton</code>.
060       * @param buttonName the name of the <code>JButton</code> to find using the given <code>RobotFixture</code>.
061       * @throws NullPointerException if <code>robot</code> is <code>null</code>.
062       * @throws ComponentLookupException if a matching <code>JButton</code> could not be found.
063       * @throws ComponentLookupException if more than one matching <code>JButton</code> is found.
064       */
065      public JButtonFixture(Robot robot, String buttonName) {
066        super(robot, buttonName, JButton.class);
067        createDriver();
068      }
069    
070      private void createDriver() {
071        driver(new AbstractButtonDriver(robot));
072      }
073    
074      /**
075       * Sets the <code>{@link AbstractButtonDriver}</code> to be used by this fixture.
076       * @param newDriver the new <code>AbstractButtonDriver</code>.
077       * @throws NullPointerException if the given driver is <code>null</code>.
078       */
079      protected final void driver(AbstractButtonDriver newDriver) {
080        validateNotNull(newDriver);
081        driver = newDriver;
082      }
083    
084      /**
085       * Returns the text of this fixture's <code>{@link JButton}</code>.
086       * @return the text of this fixture's <code>JButton</code>.
087       */
088      public String text() {
089        return driver.textOf(target);
090      }
091    
092      /**
093       * Simulates a user clicking this fixture's <code>{@link JButton}</code>.
094       * @return this fixture.
095       * @throws IllegalStateException if this fixture's <code>JButton</code> is disabled.
096       * @throws IllegalStateException if this fixture's <code>JButton</code> is not showing on the screen.
097       */
098      public JButtonFixture click() {
099        driver.click(target);
100        return this;
101      }
102    
103      /**
104       * Simulates a user clicking this fixture's <code>{@link JButton}</code>.
105       * @param button the button to click.
106       * @return this fixture.
107       * @throws NullPointerException if the given <code>MouseButton</code> is <code>null</code>.
108       * @throws IllegalStateException if this fixture's <code>JButton</code> is disabled.
109       * @throws IllegalStateException if this fixture's <code>JButton</code> is not showing on the screen.
110       */
111      public JButtonFixture click(MouseButton button) {
112        driver.click(target, button);
113        return this;
114      }
115    
116      /**
117       * Simulates a user clicking this fixture's <code>{@link JButton}</code>.
118       * @param mouseClickInfo specifies the button to click and the times the button should be clicked.
119       * @return this fixture.
120       * @throws NullPointerException if the given <code>MouseClickInfo</code> is <code>null</code>.
121       * @throws IllegalStateException if this fixture's <code>JButton</code> is disabled.
122       * @throws IllegalStateException if this fixture's <code>JButton</code> is not showing on the screen.
123       */
124      public JButtonFixture click(MouseClickInfo mouseClickInfo) {
125        driver.click(target, mouseClickInfo);
126        return this;
127      }
128    
129      /**
130       * Simulates a user double-clicking this fixture's <code>{@link JButton}</code>.
131       * @return this fixture.
132       * @throws IllegalStateException if this fixture's <code>JButton</code> is disabled.
133       * @throws IllegalStateException if this fixture's <code>JButton</code> is not showing on the screen.
134       */
135      public JButtonFixture doubleClick() {
136        driver.doubleClick(target);
137        return this;
138      }
139    
140      /**
141       * Simulates a user right-clicking this fixture's <code>{@link JButton}</code>.
142       * @return this fixture.
143       * @throws IllegalStateException if this fixture's <code>JButton</code> is disabled.
144       * @throws IllegalStateException if this fixture's <code>JButton</code> is not showing on the screen.
145       */
146      public JButtonFixture rightClick() {
147        driver.rightClick(target);
148        return this;
149      }
150    
151      /**
152       * Gives input focus to this fixture's <code>{@link JButton}</code>.
153       * @return this fixture.
154       * @throws IllegalStateException if this fixture's <code>JButton</code> is disabled.
155       * @throws IllegalStateException if this fixture's <code>JButton</code> is not showing on the screen.
156       */
157      public JButtonFixture focus() {
158        driver.focus(target);
159        return this;
160      }
161    
162      /**
163       * Simulates a user pressing given key with the given modifiers on this fixture's <code>{@link JButton}</code>.
164       * Modifiers is a mask from the available <code>{@link java.awt.event.InputEvent}</code> masks.
165       * @param keyPressInfo specifies the key and modifiers to press.
166       * @return this fixture.
167       * @throws NullPointerException if the given <code>KeyPressInfo</code> is <code>null</code>.
168       * @throws IllegalArgumentException if the given code is not a valid key code.
169       * @throws IllegalStateException if this fixture's <code>JButton</code> is disabled.
170       * @throws IllegalStateException if this fixture's <code>JButton</code> is not showing on the screen.
171       * @see KeyPressInfo
172       */
173      public JButtonFixture pressAndReleaseKey(KeyPressInfo keyPressInfo) {
174        driver.pressAndReleaseKey(target, keyPressInfo);
175        return this;
176      }
177    
178      /**
179       * Simulates a user pressing and releasing the given keys on this fixture's <code>{@link JButton}</code>.
180       * @param keyCodes one or more codes of the keys to press.
181       * @return this fixture.
182       * @throws NullPointerException if the given array of codes is <code>null</code>.
183       * @throws IllegalArgumentException if any of the given code is not a valid key code.
184       * @throws IllegalStateException if this fixture's <code>JButton</code> is disabled.
185       * @throws IllegalStateException if this fixture's <code>JButton</code> is not showing on the screen.
186       * @see java.awt.event.KeyEvent
187       */
188      public JButtonFixture pressAndReleaseKeys(int... keyCodes) {
189        driver.pressAndReleaseKeys(target, keyCodes);
190        return this;
191      }
192    
193      /**
194       * Simulates a user pressing the given key on this fixture's <code>{@link JButton}</code>.
195       * @param keyCode the code of the key to press.
196       * @return this fixture.
197       * @throws IllegalArgumentException if any of the given code is not a valid key code.
198       * @throws IllegalStateException if this fixture's <code>JButton</code> is disabled.
199       * @throws IllegalStateException if this fixture's <code>JButton</code> is not showing on the screen.
200       * @see java.awt.event.KeyEvent
201       */
202      public JButtonFixture pressKey(int keyCode) {
203        driver.pressKey(target, keyCode);
204        return this;
205      }
206    
207      /**
208       * Simulates a user releasing the given key on this fixture's <code>{@link JButton}</code>.
209       * @param keyCode the code of the key to release.
210       * @return this fixture.
211       * @throws IllegalArgumentException if any of the given code is not a valid key code.
212       * @throws IllegalStateException if this fixture's <code>JButton</code> is disabled.
213       * @throws IllegalStateException if this fixture's <code>JButton</code> is not showing on the screen.
214       * @see java.awt.event.KeyEvent
215       */
216      public JButtonFixture releaseKey(int keyCode) {
217        driver.releaseKey(target, keyCode);
218        return this;
219      }
220    
221      /**
222       * Asserts that this fixture's <code>{@link JButton}</code> has input focus.
223       * @return this fixture.
224       * @throws AssertionError if this fixture's <code>JButton</code> does not have input focus.
225       */
226      public JButtonFixture requireFocused() {
227        driver.requireFocused(target);
228        return this;
229      }
230    
231      /**
232       * Asserts that this fixture's <code>{@link JButton}</code> is enabled.
233       * @return this fixture.
234       * @throws AssertionError if this fixture's <code>JButton</code> is disabled.
235       */
236      public JButtonFixture requireEnabled() {
237        driver.requireEnabled(target);
238        return this;
239      }
240    
241      /**
242       * Asserts that this fixture's <code>{@link JButton}</code> is enabled.
243       * @param timeout the time this fixture will wait for the component to be enabled.
244       * @return this fixture.
245       * @throws WaitTimedOutError if this fixture's <code>JButton</code> is never enabled.
246       */
247      public JButtonFixture requireEnabled(Timeout timeout) {
248        driver.requireEnabled(target, timeout);
249        return this;
250      }
251    
252      /**
253       * Asserts that this fixture's <code>{@link JButton}</code> is disabled.
254       * @return this fixture.
255       * @throws AssertionError if this fixture's <code>JButton</code> is enabled.
256       */
257      public JButtonFixture requireDisabled() {
258        driver.requireDisabled(target);
259        return this;
260      }
261    
262      /**
263       * Asserts that this fixture's <code>{@link JButton}</code> is visible.
264       * @return this fixture.
265       * @throws AssertionError if this fixture's <code>JButton</code> is not visible.
266       */
267      public JButtonFixture requireVisible() {
268        driver.requireVisible(target);
269        return this;
270      }
271    
272      /**
273       * Asserts that this fixture's <code>{@link JButton}</code> is not visible.
274       * @return this fixture.
275       * @throws AssertionError if this fixture's <code>JButton</code> is visible.
276       */
277      public JButtonFixture requireNotVisible() {
278        driver.requireNotVisible(target);
279        return this;
280      }
281    
282      /**
283       * Asserts that the text of this fixture's <code>{@link JButton}</code> matches the specified value.
284       * @param expected the text to match. It can be a regular expression.
285       * @return this fixture.
286       * @throws AssertionError if the text of the target <code>JButton</code> does not match the given one.
287       */
288      public JButtonFixture requireText(String expected) {
289        driver.requireText(target, expected);
290        return this;
291      }
292    
293      /**
294       * Asserts that the text of this fixture's <code>{@link JButton}</code> matches the given regular expression pattern.
295       * @param pattern the regular expression pattern to match.
296       * @return this fixture.
297       * @throws NullPointerException if the given regular expression pattern is <code>null</code>.
298       * @throws AssertionError if the text of the target <code>JButton</code> does not match the given regular expression
299       * pattern.
300       * @since 1.2
301       */
302      public JButtonFixture requireText(Pattern pattern) {
303        driver.requireText(target, pattern);
304        return this;
305      }
306    
307      /**
308       * Asserts that the toolTip in this fixture's <code>{@link JButton}</code> matches the given value.
309       * @param expected the given value. It can be a regular expression.
310       * @return this fixture.
311       * @throws AssertionError if the toolTip in this fixture's <code>JButton</code> does not match the given value.
312       * @since 1.2
313       */
314      public JButtonFixture requireToolTip(String expected) {
315        driver.requireToolTip(target, expected);
316        return this;
317      }
318    
319      /**
320       * Asserts that the toolTip in this fixture's <code>{@link JButton}</code> matches the given regular expression
321       * pattern.
322       * @param pattern the regular expression pattern to match.
323       * @return this fixture.
324       * @throws NullPointerException if the given regular expression pattern is <code>null</code>.
325       * @throws AssertionError if the toolTip in this fixture's <code>JButton</code> does not match the given regular
326       * expression.
327       * @since 1.2
328       */
329      public JButtonFixture requireToolTip(Pattern pattern) {
330        driver.requireToolTip(target, pattern);
331        return this;
332      }
333    
334      /**
335       * Returns the client property stored in this fixture's <code>{@link JButton}</code>, under the given key.
336       * @param key the key to use to retrieve the client property.
337       * @return the value of the client property stored under the given key, or <code>null</code> if the property was
338       * not found.
339       * @throws NullPointerException if the given key is <code>null</code>.
340       * @since 1.2
341       */
342      public Object clientProperty(Object key) {
343        return driver.clientProperty(target, key);
344      }
345    
346      /**
347       * Shows a pop-up menu using this fixture's <code>{@link JButton}</code> as the invoker of the pop-up menu.
348       * @return a fixture that manages the displayed pop-up menu.
349       * @throws IllegalStateException if this fixture's <code>JButton</code> is disabled.
350       * @throws IllegalStateException if this fixture's <code>JButton</code> is not showing on the screen.
351       * @throws ComponentLookupException if a pop-up menu cannot be found.
352       */
353      public JPopupMenuFixture showPopupMenu() {
354        return new JPopupMenuFixture(robot, driver.invokePopupMenu(target));
355      }
356    
357      /**
358       * Shows a pop-up menu at the given point using this fixture's <code>{@link JButton}</code> as the invoker of the
359       * pop-up menu.
360       * @param p the given point where to show the pop-up menu.
361       * @return a fixture that manages the displayed pop-up menu.
362       * @throws IllegalStateException if this fixture's <code>JButton</code> is disabled.
363       * @throws IllegalStateException if this fixture's <code>JButton</code> is not showing on the screen.
364       * @throws ComponentLookupException if a pop-up menu cannot be found.
365       */
366      public JPopupMenuFixture showPopupMenuAt(Point p) {
367        return new JPopupMenuFixture(robot, driver.invokePopupMenu(target, p));
368      }
369    }
370