001 /* 002 * Created on Feb 27, 2008 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 @2008-2010 the original author or authors. 015 */ 016 package org.fest.swing.driver; 017 018 import static javax.swing.JOptionPane.*; 019 import static org.fest.assertions.Assertions.assertThat; 020 import static org.fest.swing.driver.JOptionPaneMessageQuery.messageOf; 021 import static org.fest.swing.driver.JOptionPaneMessageTypeQuery.messageTypeOf; 022 import static org.fest.swing.driver.JOptionPaneMessageTypes.messageTypeAsText; 023 import static org.fest.swing.driver.JOptionPaneOptionsQuery.optionsOf; 024 import static org.fest.swing.driver.JOptionPaneTitleQuery.titleOf; 025 import static org.fest.swing.driver.TextAssert.verifyThat; 026 027 import java.util.regex.Pattern; 028 029 import javax.swing.*; 030 import javax.swing.text.JTextComponent; 031 032 import org.fest.assertions.Description; 033 import org.fest.swing.annotation.RunsInEDT; 034 import org.fest.swing.core.Robot; 035 import org.fest.swing.core.matcher.JButtonMatcher; 036 import org.fest.swing.exception.ComponentLookupException; 037 038 /** 039 * Understands functional testing of <code>{@link JOptionPane}</code>s: 040 * <ul> 041 * <li>user input simulation</li> 042 * <li>state verification</li> 043 * <li>property value query</li> 044 * </ul> 045 * This class is intended for internal use only. Please use the classes in the package 046 * <code>{@link org.fest.swing.fixture}</code> in your tests. 047 * 048 * @author Alex Ruiz 049 */ 050 public class JOptionPaneDriver extends JComponentDriver { 051 052 private static final String MESSAGE_PROPERTY = "message"; 053 private static final String MESSAGE_TYPE_PROPERTY = "messageType"; 054 private static final String OPTIONS_PROPERTY = "options"; 055 private static final String TITLE_PROPERTY = "title"; 056 057 /** 058 * Creates a new </code>{@link JOptionPaneDriver}</code>. 059 * @param robot the robot to use to simulate user input. 060 */ 061 public JOptionPaneDriver(Robot robot) { 062 super(robot); 063 } 064 065 /** 066 * Asserts that the title in the given <code>{@link JOptionPane}</code> matches the given value. 067 * @param optionPane the target {@code JOptionPane}. 068 * @param title the title to match. It can be a regular expression. 069 * @throws AssertionError if the {@code JOptionPane} does not have the given title. 070 */ 071 @RunsInEDT 072 public void requireTitle(JOptionPane optionPane, String title) { 073 verifyThat(title(optionPane)).as(propertyName(optionPane, TITLE_PROPERTY)).isEqualOrMatches(title); 074 } 075 076 /** 077 * Asserts that the title in the given <code>{@link JOptionPane}</code> matches the given regular expression pattern. 078 * @param optionPane the target {@code JOptionPane}. 079 * @param pattern the regular expression pattern to match. 080 * @throws NullPointerException if the given regular expression pattern is <code>null</code>. 081 * @throws AssertionError if the {@code JOptionPane} does not have the given title. 082 * @since 1.2 083 */ 084 @RunsInEDT 085 public void requireTitle(JOptionPane optionPane, Pattern pattern) { 086 verifyThat(title(optionPane)).as(propertyName(optionPane, TITLE_PROPERTY)).matches(pattern); 087 } 088 089 090 /** 091 * Returns the title of the given <code>{@link JOptionPane}</code>. 092 * @param optionPane the target {@code JOptionPane}. 093 * @return the title of the given {@code JOptionPane}. 094 * @since 1.2 095 */ 096 @RunsInEDT 097 public String title(JOptionPane optionPane) { 098 return titleOf(optionPane); 099 } 100 101 /** 102 * Asserts that the title of the <code>{@link JOptionPane}</code> matches the given value. If the given value is a 103 * regular expression and the message in the {@code JOptionPane} is not a <code>String</code>, this method will use the 104 * <code>toString</code> representation of such message. 105 * message in the {@code JOptionPane} is not a <code>String</code>, this method will use the 106 * <code>toString</code> representation of such message. 107 * @param optionPane the target {@code JOptionPane}. 108 * @param message the message to verify. If it is a <code>String</code>, it can be specified as a regular expression. 109 * @throws AssertionError if the message in the {@code JOptionPane} is not equal to or does not match the given 110 * message. 111 */ 112 @RunsInEDT 113 public void requireMessage(JOptionPane optionPane, Object message) { 114 Object actual = messageOf(optionPane); 115 if (message instanceof String) { 116 requireMessage(optionPane, (String)message, toStringOf(actual)); 117 return; 118 } 119 assertThat(actual).as(messageProperty(optionPane)).isEqualTo(message); 120 } 121 122 @RunsInEDT 123 private void requireMessage(JOptionPane optionPane, String expected, String actual) { 124 verifyThat(actual).as(messageProperty(optionPane)).isEqualOrMatches(expected); 125 } 126 127 /** 128 * Asserts that the title of the <code>{@link JOptionPane}</code> matches the given regular expression pattern. If the 129 * message in the {@code JOptionPane} is not a <code>String</code>, this method will use the 130 * <code>toString</code> representation of such message. 131 * @param optionPane the target {@code JOptionPane}. 132 * @param pattern the regular expression to match. 133 * @throws NullPointerException if the given regular expression pattern is <code>null</code>. 134 * @throws AssertionError if the message in the </code>JOptionPaneFixture</code> does not match the given regular 135 * expression pattern. 136 * @since 1.2 137 */ 138 @RunsInEDT 139 public void requireMessage(JOptionPane optionPane, Pattern pattern) { 140 Object actual = messageOf(optionPane); 141 verifyThat(toStringOf(actual)).as(messageProperty(optionPane)).matches(pattern); 142 } 143 144 private String toStringOf(Object o) { 145 return (o == null) ? null : o.toString(); 146 } 147 148 private Description messageProperty(JOptionPane optionPane) { 149 return propertyName(optionPane, MESSAGE_PROPERTY); 150 } 151 152 /** 153 * Asserts that the <code>{@link JOptionPane}</code> has the given options. 154 * @param optionPane the target {@code JOptionPane}. 155 * @param options the options to verify. 156 * @throws AssertionError if the {@code JOptionPane} does not have the given options. 157 */ 158 @RunsInEDT 159 public void requireOptions(JOptionPane optionPane, Object[] options) { 160 assertThat(optionsOf(optionPane)).as(propertyName(optionPane, OPTIONS_PROPERTY)).isEqualTo(options); 161 } 162 163 /** 164 * Finds the "OK" button in the <code>{@link JOptionPane}</code>. This method is independent of locale and platform. 165 * @param optionPane the target {@code JOptionPane}. 166 * @return the "OK" button. 167 * @throws ComponentLookupException if the a "OK" button cannot be found. 168 */ 169 @RunsInEDT 170 public JButton okButton(JOptionPane optionPane) { 171 return buttonWithTextFromUIManager(optionPane, "OptionPane.okButtonText"); 172 } 173 174 /** 175 * Finds the "Cancel" button in the <code>{@link JOptionPane}</code>. This method is independent of locale and 176 * platform. 177 * @param optionPane the target {@code JOptionPane}. 178 * @return the "Cancel" button. 179 * @throws ComponentLookupException if the a "Cancel" button cannot be found. 180 */ 181 @RunsInEDT 182 public JButton cancelButton(JOptionPane optionPane) { 183 return buttonWithTextFromUIManager(optionPane, "OptionPane.cancelButtonText"); 184 } 185 186 /** 187 * Finds the "Yes" button in the <code>{@link JOptionPane}</code>. This method is independent of locale and platform. 188 * @param optionPane the target {@code JOptionPane}. 189 * @return the "Yes" button. 190 * @throws ComponentLookupException if the a "Yes" button cannot be found. 191 */ 192 @RunsInEDT 193 public JButton yesButton(JOptionPane optionPane) { 194 return buttonWithTextFromUIManager(optionPane, "OptionPane.yesButtonText"); 195 } 196 197 /** 198 * Finds the "No" button in the <code>{@link JOptionPane}</code>. This method is independent of locale and platform. 199 * @param optionPane the target {@code JOptionPane}. 200 * @return the "No" button. 201 * @throws ComponentLookupException if the a "No" button cannot be found. 202 */ 203 @RunsInEDT 204 public JButton noButton(JOptionPane optionPane) { 205 return buttonWithTextFromUIManager(optionPane, "OptionPane.noButtonText"); 206 } 207 208 @RunsInEDT 209 private JButton buttonWithTextFromUIManager(JOptionPane optionPane, String key) { 210 return buttonWithText(optionPane, UIManager.getString(key)); 211 } 212 213 /** 214 * Finds a button in the <code>{@link JOptionPane}</code> containing the given text. 215 * @param optionPane the target {@code JOptionPane}. 216 * @param text the text of the button to find and return. It can be a regular expression. 217 * @return a button containing the given text. 218 * @throws ComponentLookupException if the a button with the given text cannot be found. 219 */ 220 @RunsInEDT 221 public JButton buttonWithText(JOptionPane optionPane, String text) { 222 return robot.finder().find(optionPane, JButtonMatcher.withText(text).andShowing()); 223 } 224 225 /** 226 * Finds a button in the <code>{@link JOptionPane}</code> whose text matches the given regular expression pattern. 227 * @param optionPane the target {@code JOptionPane}. 228 * @param pattern the regular expression pattern to match. 229 * @return a button containing the given text. 230 * @throws NullPointerException if the given regular expression pattern is <code>null</code>. 231 * @throws ComponentLookupException if the a button with the given text cannot be found. 232 * @since 1.2 233 */ 234 @RunsInEDT 235 public JButton buttonWithText(JOptionPane optionPane, Pattern pattern) { 236 return robot.finder().find(optionPane, JButtonMatcher.withText(pattern).andShowing()); 237 } 238 239 /** 240 * Finds a <code>{@link JButton}</code> in the <code>{@link JOptionPane}</code> (assuming it has only one button.) 241 * @param optionPane the target {@code JOptionPane}. 242 * @return the only <code>JButton</code> contained in the {@code JOptionPane}. 243 * @throws ComponentLookupException if a matching component could not be found. 244 * @throws ComponentLookupException if more than one matching component is found. 245 * @deprecated in 1.2 246 */ 247 @RunsInEDT 248 @Deprecated public JButton button(JOptionPane optionPane) { 249 return robot.finder().findByType(optionPane, JButton.class); 250 } 251 252 /** 253 * Returns the <code>{@link JTextComponent}</code> in the given message only if the message is of type input. 254 * @param optionPane the target {@code JOptionPane}. 255 * @return the text component in the given message. 256 * @throws ComponentLookupException if the message type is not input and therefore it does not contain a text component. 257 * @deprecated in 1.2 258 */ 259 @RunsInEDT 260 @Deprecated public JTextComponent textBox(JOptionPane optionPane) { 261 return robot.finder().findByType(optionPane, JTextComponent.class); 262 } 263 264 /** 265 * Asserts that the <code>{@link JOptionPane}</code> is displaying an error message. 266 * @param optionPane the target {@code JOptionPane}. 267 */ 268 @RunsInEDT 269 public void requireErrorMessage(JOptionPane optionPane) { 270 assertEqualMessageType(optionPane, ERROR_MESSAGE); 271 } 272 273 /** 274 * Asserts that the <code>{@link JOptionPane}</code> is displaying an information message. 275 * @param optionPane the target {@code JOptionPane}. 276 */ 277 @RunsInEDT 278 public void requireInformationMessage(JOptionPane optionPane) { 279 assertEqualMessageType(optionPane, INFORMATION_MESSAGE); 280 } 281 282 /** 283 * Asserts that the <code>{@link JOptionPane}</code> is displaying a warning message. 284 * @param optionPane the target {@code JOptionPane}. 285 */ 286 @RunsInEDT 287 public void requireWarningMessage(JOptionPane optionPane) { 288 assertEqualMessageType(optionPane, WARNING_MESSAGE); 289 } 290 291 /** 292 * Asserts that the <code>{@link JOptionPane}</code> is displaying a question. 293 * @param optionPane the target {@code JOptionPane}. 294 */ 295 @RunsInEDT 296 public void requireQuestionMessage(JOptionPane optionPane) { 297 assertEqualMessageType(optionPane, QUESTION_MESSAGE); 298 } 299 300 /** 301 * Asserts that the <code>{@link JOptionPane}</code> is displaying a plain message. 302 * @param optionPane the target {@code JOptionPane}. 303 */ 304 @RunsInEDT 305 public void requirePlainMessage(JOptionPane optionPane) { 306 assertEqualMessageType(optionPane, PLAIN_MESSAGE); 307 } 308 309 @RunsInEDT 310 private void assertEqualMessageType(JOptionPane optionPane, int expected) { 311 String actualType = actualMessageTypeAsText(optionPane); 312 assertThat(actualType).as(propertyName(optionPane, MESSAGE_TYPE_PROPERTY)).isEqualTo(messageTypeAsText(expected)); 313 } 314 315 @RunsInEDT 316 private String actualMessageTypeAsText(final JOptionPane optionPane) { 317 return messageTypeAsText(messageTypeOf(optionPane)); 318 } 319 }