View Javadoc

1   package com.atlassian.selenium;
2   
3   import com.thoughtworks.selenium.DefaultSelenium;
4   
5   import java.io.InputStreamReader;
6   import java.io.BufferedReader;
7   import java.io.IOException;
8   import java.util.Map;
9   import java.util.HashMap;
10  
11  /**
12   * Extends the {@link DefaultSelenium} client to provide a more sensible implementation
13   * as well some extra utility methods such as keypress.
14   */
15  public class SeleniumClient extends DefaultSelenium
16  {
17      public enum Browser
18      {
19          FIREFOX("firefox"), OPERA("opera"), SAFARI("safari"), UNKNOWN("unkown"), IE("ie");
20  
21          private final String name;
22  
23          Browser(String name)
24          {
25              this.name = name;
26          }
27  
28          public String getName()
29          {
30              return name;
31          }
32  
33          public static Browser typeOf(String browserStartString)
34          {
35              for (Browser browser : Browser.values())
36              {
37                  if(browserStartString.contains(browser.getName()))
38                  {
39                      return browser;
40                  }
41              }
42              return null;
43          }
44  
45          
46      }
47  
48      private Browser browser;
49  
50      /**
51       * The maximum page load wait time used by Selenium. This value is set with
52       * {@link SeleniumConfiguration#getPageLoadWait()}.
53       */
54      protected final long PAGE_LOAD_WAIT;
55  
56      /**
57       * The maximum wait time for actions that don't require page loads. This value is set with
58       * {@link SeleniumConfiguration#getActionWait()}.
59       */
60      protected final long ACTION_WAIT;
61  
62      public SeleniumClient(SeleniumConfiguration config)
63      {
64          super(new HtmlDumpingHttpCommandProcessor(config.getServerLocation(), config.getServerPort(), config.getBrowserStartString(), config.getBaseUrl()));
65  
66          this.PAGE_LOAD_WAIT = config.getPageLoadWait();
67          this.ACTION_WAIT = config.getActionWait();
68  
69          browser = Browser.typeOf(config.getBrowserStartString());
70          
71          SeleniumStarter.getInstance().setUserAgent(browser.getName());
72      }
73  
74      public Browser getBrowser()
75      {
76          return browser;
77      }
78      
79      /**
80       * Unlike {@link DefaultSelenium#open}, this opens the provided URL relative to the application context path.
81       * It also waits for the page to load -- a maximum of {@link #PAGE_LOAD_WAIT} before returning.
82       */
83      public void open(String url)
84      {
85          open(url, PAGE_LOAD_WAIT);
86      }
87  
88      /**
89       * Wait for page to load doesn't work the case of non-HTML based resources (like images).
90       * So sometimes you really do want to open a url without waiting.
91       * @param url
92       */
93      public void openNoWait(String url)
94      {
95          super.open(url);
96      }
97  
98      /**
99       * Opens the given URL and waits a maximum of timeoutMillis for the page to load completely.
100      */
101     public void open(String url, long timeoutMillis)
102     {
103         super.open(url);
104         super.waitForPageToLoad(String.valueOf(timeoutMillis));
105     }
106 
107     /**
108      * Overloads {@link #waitForPageToLoad(String)} to take in a long.
109      */
110     public void waitForPageToLoad(long timeoutMillis)
111     {
112         super.waitForPageToLoad(String.valueOf(timeoutMillis));
113     }
114 
115     /**
116      * Waits for the page to load with the default timeout configured in {@link SeleniumConfiguration}.
117      */
118     public void waitForPageToLoad()
119     {
120         waitForPageToLoad(PAGE_LOAD_WAIT);
121     }
122 
123     /**
124      * Executes the given Javascript in the context of the text page and waits for it to evaluate to true
125      * for a maximum of {@link #ACTION_WAIT} milliseconds.
126      * @see #waitForCondition(String, long) if you would like to specify your own timeout.
127      */
128     public void waitForCondition(String javascript)
129     {
130         waitForCondition(javascript, ACTION_WAIT);
131     }
132 
133     /**
134      * Executes the given Javascript in the context of the text page and waits for it to evaluate to true
135      * for a maximum of timeoutMillis.
136      */
137     public void waitForCondition(String javascript, long timeoutMillis)
138     {
139         waitForCondition(javascript, Long.toString(timeoutMillis));
140     }
141 
142     /**
143      * Click the element with the given locator and optionally wait for the page to load, using {@link #PAGE_LOAD_WAIT}.
144      *
145      * @param locator the element to click, specified using Selenium selector syntax
146      * @param waitForPageToLoad whether to wait for the page to reload. Don't use this unless the page is completely
147      * reloaded.
148      * @see #click(String, long) if you would like to specify your own timeout.
149      */
150     public void click(String locator, boolean waitForPageToLoad)
151     {
152         super.click(locator);
153         if (waitForPageToLoad)
154             super.waitForPageToLoad(String.valueOf(PAGE_LOAD_WAIT));
155     }
156 
157     /**
158      * Submit the named form locator and optionally wait for the page to load, using {@link #PAGE_LOAD_WAIT}.
159      *
160      * @param form to click, specified using Selenium selector syntax
161      * @param waitForPageToLoad whether to wait for the page to reload. Don't use this unless the page is completely
162      * reloaded.
163      * @see #submit(String, long) if you would like to specify your own timeout.
164      */
165     public void submit(String form, boolean waitForPageToLoad)
166     {
167         super.submit(form);
168         if (waitForPageToLoad)
169             super.waitForPageToLoad(String.valueOf(PAGE_LOAD_WAIT));
170     }
171 
172     /**
173      * Click the element with the given locator and wait for the page to load, for a maximum of timeoutMillis.
174      * <p/>
175      * Do not use this method if the page does not reload.
176      *
177      * @param locator the element to click, specified using Selenium selector syntax
178      * @param timeoutMillis the maximum number of milliseconds to wait for the page to load. Polling takes place
179      * more frequently.
180      * @see #click(String, boolean) if you would like to use the default timeout
181      */
182     public void click(String locator, long timeoutMillis)
183     {
184         super.click(locator);
185         super.waitForPageToLoad(Long.toString(timeoutMillis));
186     }
187 
188     /**
189      * Submit the given form and wait for the page to load, for a maximum of timeoutMillis.
190      * <p/>
191      * Do not use this method if the page does not reload.
192      *
193      * @param form the form to submit
194      * @param timeoutMillis the maximum number of milliseconds to wait for the page to load. Polling takes place
195      * more frequently.
196      * @see #click(String, boolean) if you would like to use the default timeout
197      */
198     public void submit(String form, long timeoutMillis)
199     {
200         super.submit(form);
201         super.waitForPageToLoad(Long.toString(timeoutMillis));
202     }
203 
204     /**
205      * This will type into a field by sending key down / key press / key up events.
206      * @param locator Uses the Selenium locator syntax
207      * @param key The key to be pressed
208      */
209     public void keyPress(String locator, String key)
210     {
211         super.keyDown(locator, key);
212         super.keyPress(locator, key);
213         super.keyUp(locator, key);
214     }
215 
216     /**
217      * This will type into a field by first blanking it out and then sending key down / key press / key up
218      * events.
219      *
220      * @param locator the Selenium locator
221      * @param string  the string to type
222      * @param reset   Should the field be reset first?
223      */
224     public void typeWithFullKeyEvents(String locator, String string, boolean reset)
225     {
226         super.focus(locator);
227         if (reset)
228         {
229             super.type(locator, "");
230         }
231 
232         // The typeKeys method doesn't work properly in Firefox
233         if (Browser.FIREFOX.equals(browser))
234         {
235             char[] chars = string.toCharArray();
236             for (char aChar : chars)
237             {
238                 super.focus(locator);
239                 //Using codes because the methhod doesn't worki n  
240                 keyPress(locator, "\\" + (int) aChar);
241             }
242         }
243         else
244         {
245             if(!reset)
246             {
247                 string = super.getValue(locator) + string;
248             }
249             super.type(locator, string);
250             super.typeKeys(locator, string);
251         }
252     }
253 
254     /**
255      * This will type into a field by first blanking it out and then sending key down / key press / key up
256      * events. This really only calls {@link #typeWithFullKeyEvents(String,String,boolean)})}
257      *
258      * @param locator - the usual Selenium locator
259      * @param string  the string to type into a field
260      */
261     public void typeWithFullKeyEvents(String locator, String string)
262     {
263         typeWithFullKeyEvents(locator, string, true);
264     }
265 
266     public void selectOption(String selectName, String label)
267     {
268         // In some browsers (i.e. Safari) the select items have funny padding
269         // so we need to use this funny method to find how the select item is
270         // padded so that it can be matched
271         String[] options = super.getSelectOptions(selectName);
272         int i = 0;
273         for(; i < options.length; i++)
274         {
275             if(options[i].trim().equals(label))
276             {
277                 break;
278             }
279         }
280         if(i < options.length)
281         {
282             super.select(selectName, options[i]);
283         }
284     }
285 
286     /**
287      * Checks a checkbox given a name and value.
288      */
289     public void check(String name, String value)
290     {
291         check("name=" + name + " value=" + value);
292     }
293 
294     public void clickLinkWithText(String text, boolean waitForPageToLoad)
295     {
296         super.click("link=" + text);
297         if (waitForPageToLoad) waitForPageToLoad();
298     }
299 
300     public void clickButton(String buttonText, boolean waitForPageToLoad)
301     {
302         clickElementWithXpath("//input[@value = '" + buttonText + "']");
303         if (waitForPageToLoad) waitForPageToLoad();
304     }
305 
306     public void clickButtonWithName(String buttonName, boolean waitForPageToLoad)
307     {
308         clickElementWithXpath("//input[@name = '" + buttonName + "']");
309         if (waitForPageToLoad) waitForPageToLoad();
310     }
311 
312     public void clickElementWithTitle(String title)
313     {
314         super.click("xpath=//*[@title='" + title + "']");
315     }
316 
317     public void clickElementWithClass(String className)
318     {
319         super.click("css=." + className);
320     }
321 
322     public void clickElementWithCss(String cssSelector)
323     {
324         super.click("css=" + cssSelector);
325     }
326 
327     public void clickElementWithXpath(String xpath)
328     {
329         super.click("xpath=" + xpath);
330     }
331 
332     public void typeInElementWithName(String elementName, String text)
333     {
334         super.type("name=" + elementName, text);
335     }
336 
337     public void typeInElementWithCss(String cssSelector, String text)
338     {
339         super.type("css=" + cssSelector, text);
340     }
341 
342 
343 
344     private void addJqueryLocator() throws IOException
345     {
346         String jqueryImpl = readFile("jquery-1.3.1.min.js");
347         String jqueryLocStrategy = readFile("jquery-locationStrategy.js");
348         //client.setExtensionJs(jqueryImpl);
349         addScript(jqueryImpl, "jquery");
350         addLocationStrategy("jquery", jqueryLocStrategy );
351     }
352 
353     private static String readFile(String file) throws IOException
354     {
355         BufferedReader reader =  new BufferedReader(new InputStreamReader(ClassLoader.getSystemClassLoader().getResourceAsStream(file)));
356 
357         String line = reader.readLine();
358         StringBuffer contents = new StringBuffer();
359 
360         while(line != null)
361         {
362             contents.append(line + "\n");
363             line = reader.readLine();
364         }
365 
366         return contents.toString();
367     }
368 
369     public void start()
370     {
371         super.start();
372         try {
373             addJqueryLocator();
374         }
375         catch (IOException ioe)
376         {
377             System.err.println("Unable to load JQuery locator strategy: " + ioe);
378             ioe.printStackTrace(System.err);
379         }
380 
381     }
382 
383 
384 
385 }