1
2 """
3 Copyright 2006 ThoughtWorks, Inc.
4
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 """
17 __docformat__ = "restructuredtext en"
18
19
20
21 import httplib
22 import urllib
23 import re
24
26 """
27 Defines an object that runs Selenium commands.
28
29 Element Locators
30 ~~~~~~~~~~~~~~~~
31 Element Locators tell Selenium which HTML element a command refers to.
32 The format of a locator is:
33 \ *locatorType*\ **=**\ \ *argument*
34 We support the following strategies for locating elements:
35
36 * \ **identifier**\ =\ *id*
37 Select the element with the specified @id attribute. If no match is
38 found, select the first element whose @name attribute is \ *id*.
39 (This is normally the default; see below.)
40 * \ **id**\ =\ *id*
41 Select the element with the specified @id attribute.
42 * \ **name**\ =\ *name*
43 Select the first element with the specified @name attribute.
44
45 * username
46 * name=username
47
48
49
50 The name may optionally be followed by one or more \ *element-filters*, separated from the name by whitespace. If the \ *filterType* is not specified, \ **value**\ is assumed.
51
52 * name=flavour value=chocolate
53
54
55 * \ **dom**\ =\ *javascriptExpression*
56
57 Find an element using JavaScript traversal of the HTML Document Object
58 Model. DOM locators \ *must* begin with "document.".
59 * dom=document.forms['myForm'].myDropdown
60 * dom=document.images[56]
61
62
63
64 * \ **xpath**\ =\ *xpathExpression*
65 Locate an element using an XPath expression.
66 * xpath=//img[@alt='The image alt text']
67 * xpath=//table[@id='table1']//tr[4]/td[2]
68
69
70 * \ **link**\ =\ *textPattern*
71 Select the link (anchor) element which contains text matching the
72 specified \ *pattern*.
73 * link=The link text
74
75
76
77
78 Without an explicit locator prefix, Selenium uses the following default
79 strategies:
80
81 * \ **dom**\ , for locators starting with "document."
82 * \ **xpath**\ , for locators starting with "//"
83 * \ **identifier**\ , otherwise
84
85 Element Filters
86 ~~~~~~~~~~~~~~~Element filters can be used with a locator to refine a list of candidate elements. They are currently used only in the 'name' element-locator.
87 Filters look much like locators, ie.
88 \ *filterType*\ **=**\ \ *argument*Supported element-filters are:
89 \ **value=**\ \ *valuePattern*
90
91 Matches elements based on their values. This is particularly useful for refining a list of similarly-named toggle-buttons.\ **index=**\ \ *index*
92
93 Selects a single element based on its position in the list (offset from zero).String-match Patterns
94 ~~~~~~~~~~~~~~~~~~~~~
95 Various Pattern syntaxes are available for matching string values:
96
97 * \ **glob:**\ \ *pattern*
98 Match a string against a "glob" (aka "wildmat") pattern. "Glob" is a
99 kind of limited regular-expression syntax typically used in command-line
100 shells. In a glob pattern, "*" represents any sequence of characters, and "?"
101 represents any single character. Glob patterns match against the entire
102 string.
103 * \ **regexp:**\ \ *regexp*
104 Match a string using a regular-expression. The full power of JavaScript
105 regular-expressions is available.
106 * \ **exact:**\ \ *string*
107 Match a string exactly, verbatim, without any of that fancy wildcard
108 stuff.
109
110
111 If no pattern prefix is specified, Selenium assumes that it's a "glob"
112 pattern.
113
114
115 """
116
117
118 - def __init__(self, host, port, browserStartCommand, browserURL):
119 self.host = host
120 self.port = port
121 self.browserStartCommand = browserStartCommand
122 self.browserURL = browserURL
123 self.sessionId = None
124
126 result = self.get_string("getNewBrowserSession", [self.browserStartCommand, self.browserURL])
127 try:
128 self.sessionId = long(result)
129 except ValueError:
130 raise Exception, result
131
133 self.do_command("testComplete", [])
134 self.sessionId = None
135
137 conn = httplib.HTTPConnection(self.host, self.port)
138 commandString = u'/selenium-server/driver/?cmd=' + urllib.quote_plus(unicode(verb).encode('utf-8'))
139 for i in range(len(args)):
140 commandString = commandString + '&' + unicode(i+1) + '=' + urllib.quote_plus(unicode(args[i]).encode('utf-8'))
141 if (None != self.sessionId):
142 commandString = commandString + "&sessionId=" + unicode(self.sessionId)
143 conn.request("GET", commandString)
144
145 response = conn.getresponse()
146
147 data = unicode(response.read(), "UTF-8")
148 result = response.reason
149
150 if (not data.startswith('OK')):
151 raise Exception, data
152 return data
153
155 result = self.do_command(verb, args)
156 return result[3:]
157
159 csv = self.get_string(verb, args)
160 token = ""
161 tokens = []
162 for i in range(len(csv)):
163 letter = csv[i]
164 if (letter == '\\'):
165 i = i + 1
166 letter = csv[i]
167 token = token + letter
168 elif (letter == ','):
169 tokens.append(token)
170 token = ""
171 else:
172 token = token + letter
173 tokens.append(token)
174 return tokens
175
179
183
185 boolstr = self.get_string(verb, args)
186 if ("true" == boolstr):
187 return True
188 if ("false" == boolstr):
189 return False
190 raise ValueError, "result is neither 'true' nor 'false': " + boolstr
191
193 boolarr = self.get_string_array(verb, args)
194 for i in range(len(boolarr)):
195 if ("true" == boolstr):
196 boolarr[i] = True
197 continue
198 if ("false" == boolstr):
199 boolarr[i] = False
200 continue
201 raise ValueError, "result is neither 'true' nor 'false': " + boolarr[i]
202 return boolarr
203
204
205
206
207
208
209 - def click(self,locator):
210 """
211 Clicks on a link, button, checkbox or radio button. If the click action
212 causes a new page to load (like a link usually does), call
213 waitForPageToLoad.
214
215 'locator' is an element locator
216 """
217 self.do_command("click", [locator,])
218
219
221 """
222 Explicitly simulate an event, to trigger the corresponding "on\ *event*"
223 handler.
224
225 'locator' is an element locator
226 'eventName' is the event name, e.g. "focus" or "blur"
227 """
228 self.do_command("fireEvent", [locator,eventName,])
229
230
232 """
233 Simulates a user pressing and releasing a key.
234
235 'locator' is an element locator
236 'keycode' is the numeric keycode of the key to be pressed, normally the
237 ASCII value of that key.
238 """
239 self.do_command("keyPress", [locator,keycode,])
240
241
243 """
244 Simulates a user pressing a key (without releasing it yet).
245
246 'locator' is an element locator
247 'keycode' is the numeric keycode of the key to be pressed, normally the
248 ASCII value of that key.
249 """
250 self.do_command("keyDown", [locator,keycode,])
251
252
253 - def key_up(self,locator,keycode):
254 """
255 Simulates a user releasing a key.
256
257 'locator' is an element locator
258 'keycode' is the numeric keycode of the key to be released, normally the
259 ASCII value of that key.
260 """
261 self.do_command("keyUp", [locator,keycode,])
262
263
265 """
266 Simulates a user hovering a mouse over the specified element.
267
268 'locator' is an element locator
269 """
270 self.do_command("mouseOver", [locator,])
271
272
274 """
275 Simulates a user pressing the mouse button (without releasing it yet) on
276 the specified element.
277
278 'locator' is an element locator
279 """
280 self.do_command("mouseDown", [locator,])
281
282
283 - def type(self,locator,value):
284 """
285 Sets the value of an input field, as though you typed it in.
286
287 Can also be used to set the value of combo boxes, check boxes, etc. In these cases,
288 value should be the value of the option selected, not the visible text.
289
290
291 'locator' is an element locator
292 'value' is the value to type
293 """
294 self.do_command("type", [locator,value,])
295
296
297 - def check(self,locator):
298 """
299 Check a toggle-button (checkbox/radio)
300
301 'locator' is an element locator
302 """
303 self.do_command("check", [locator,])
304
305
307 """
308 Uncheck a toggle-button (checkbox/radio)
309
310 'locator' is an element locator
311 """
312 self.do_command("uncheck", [locator,])
313
314
315 - def select(self,selectLocator,optionLocator):
316 """
317 Select an option from a drop-down using an option locator.
318
319
320 Option locators provide different ways of specifying options of an HTML
321 Select element (e.g. for selecting a specific option, or for asserting
322 that the selected option satisfies a specification). There are several
323 forms of Select Option Locator.
324
325 * \ **label**\ =\ *labelPattern*
326 matches options based on their labels, i.e. the visible text. (This
327 is the default.)
328 * label=regexp:^[Oo]ther
329
330
331 * \ **value**\ =\ *valuePattern*
332 matches options based on their values.
333 * value=other
334
335
336 * \ **id**\ =\ *id*
337 matches options based on their ids.
338 * id=option1
339
340
341 * \ **index**\ =\ *index*
342 matches an option based on its index (offset from zero).
343 * index=2
344
345
346
347
348 If no option locator prefix is provided, the default behaviour is to match on \ **label**\ .
349
350
351
352 'selectLocator' is an element locator identifying a drop-down menu
353 'optionLocator' is an option locator (a label by default)
354 """
355 self.do_command("select", [selectLocator,optionLocator,])
356
357
359 """
360 Add a selection to the set of selected options in a multi-select element using an option locator.
361
362 @see #doSelect for details of option locators
363
364 'locator' is an element locator identifying a multi-select box
365 'optionLocator' is an option locator (a label by default)
366 """
367 self.do_command("addSelection", [locator,optionLocator,])
368
369
371 """
372 Remove a selection from the set of selected options in a multi-select element using an option locator.
373
374 @see #doSelect for details of option locators
375
376 'locator' is an element locator identifying a multi-select box
377 'optionLocator' is an option locator (a label by default)
378 """
379 self.do_command("removeSelection", [locator,optionLocator,])
380
381
382 - def submit(self,formLocator):
383 """
384 Submit the specified form. This is particularly useful for forms without
385 submit buttons, e.g. single-input "Search" forms.
386
387 'formLocator' is an element locator for the form you want to submit
388 """
389 self.do_command("submit", [formLocator,])
390
391
392 - def open(self,url):
393 """
394 Opens an URL in the test frame. This accepts both relative and absolute
395 URLs.
396
397 The "open" command waits for the page to load before proceeding,
398 ie. the "AndWait" suffix is implicit.
399
400 \ *Note*: The URL must be on the same domain as the runner HTML
401 due to security restrictions in the browser (Same Origin Policy). If you
402 need to open an URL on another domain, use the Selenium Server to start a
403 new browser session on that domain.
404
405 'url' is the URL to open; may be relative or absolute
406 """
407 self.do_command("open", [url,])
408
409
411 """
412 Selects a popup window; once a popup window has been selected, all
413 commands go to that window. To select the main window again, use "null"
414 as the target.
415
416 'windowID' is the JavaScript window ID of the window to select
417 """
418 self.do_command("selectWindow", [windowID,])
419
420
422 """
423 Waits for a popup window to appear and load up.
424
425 'windowID' is the JavaScript window ID of the window that will appear
426 'timeout' is a timeout in milliseconds, after which the action will return with an error
427 """
428 self.do_command("waitForPopUp", [windowID,timeout,])
429
430
432 """
433 By default, Selenium's overridden window.confirm() function will
434 return true, as if the user had manually clicked OK. After running
435 this command, the next call to confirm() will return false, as if
436 the user had clicked Cancel.
437
438 """
439 self.do_command("chooseCancelOnNextConfirmation", [])
440
441
443 """
444 Instructs Selenium to return the specified answer string in response to
445 the next JavaScript prompt [window.prompt()].
446
447 'answer' is the answer to give in response to the prompt pop-up
448 """
449 self.do_command("answerOnNextPrompt", [answer,])
450
451
453 """
454 Simulates the user clicking the "back" button on their browser.
455
456 """
457 self.do_command("goBack", [])
458
459
461 """
462 Simulates the user clicking the "Refresh" button on their browser.
463
464 """
465 self.do_command("refresh", [])
466
467
469 """
470 Simulates the user clicking the "close" button in the titlebar of a popup
471 window or tab.
472
473 """
474 self.do_command("close", [])
475
476
478 """
479 Has an alert occurred?
480
481
482 This function never throws an exception
483
484
485
486 """
487 return self.get_boolean("isAlertPresent", [])
488
489
491 """
492 Has a prompt occurred?
493
494
495 This function never throws an exception
496
497
498
499 """
500 return self.get_boolean("isPromptPresent", [])
501
502
504 """
505 Has confirm() been called?
506
507
508 This function never throws an exception
509
510
511
512 """
513 return self.get_boolean("isConfirmationPresent", [])
514
515
517 """
518 Retrieves the message of a JavaScript alert generated during the previous action, or fail if there were no alerts.
519
520 Getting an alert has the same effect as manually clicking OK. If an
521 alert is generated but you do not get/verify it, the next Selenium action
522 will fail.
523 NOTE: under Selenium, JavaScript alerts will NOT pop up a visible alert
524 dialog.
525 NOTE: Selenium does NOT support JavaScript alerts that are generated in a
526 page's onload() event handler. In this case a visible dialog WILL be
527 generated and Selenium will hang until someone manually clicks OK.
528
529
530 """
531 return self.get_string("getAlert", [])
532
533
535 """
536 Retrieves the message of a JavaScript confirmation dialog generated during
537 the previous action.
538
539
540 By default, the confirm function will return true, having the same effect
541 as manually clicking OK. This can be changed by prior execution of the
542 chooseCancelOnNextConfirmation command. If an confirmation is generated
543 but you do not get/verify it, the next Selenium action will fail.
544
545
546 NOTE: under Selenium, JavaScript confirmations will NOT pop up a visible
547 dialog.
548
549
550 NOTE: Selenium does NOT support JavaScript confirmations that are
551 generated in a page's onload() event handler. In this case a visible
552 dialog WILL be generated and Selenium will hang until you manually click
553 OK.
554
555
556
557 """
558 return self.get_string("getConfirmation", [])
559
560
562 """
563 Retrieves the message of a JavaScript question prompt dialog generated during
564 the previous action.
565
566 Successful handling of the prompt requires prior execution of the
567 answerOnNextPrompt command. If a prompt is generated but you
568 do not get/verify it, the next Selenium action will fail.
569 NOTE: under Selenium, JavaScript prompts will NOT pop up a visible
570 dialog.
571 NOTE: Selenium does NOT support JavaScript prompts that are generated in a
572 page's onload() event handler. In this case a visible dialog WILL be
573 generated and Selenium will hang until someone manually clicks OK.
574
575
576 """
577 return self.get_string("getPrompt", [])
578
579
581 """
582 Gets the absolute URL of the current page.
583
584 """
585 return self.get_string("getLocation", [])
586
587
589 """
590 Gets the title of the current page.
591
592 """
593 return self.get_string("getTitle", [])
594
595
596 - def get_body_text(self):
597 """
598 Gets the entire text of the page.
599
600 """
601 return self.get_string("getBodyText", [])
602
603
605 """
606 Gets the (whitespace-trimmed) value of an input field (or anything else with a value parameter).
607 For checkbox/radio elements, the value will be "on" or "off" depending on
608 whether the element is checked or not.
609
610 'locator' is an element locator
611 """
612 return self.get_string("getValue", [locator,])
613
614
615 - def get_text(self,locator):
616 """
617 Gets the text of an element. This works for any element that contains
618 text. This command uses either the textContent (Mozilla-like browsers) or
619 the innerText (IE-like browsers) of the element, which is the rendered
620 text shown to the user.
621
622 'locator' is an element locator
623 """
624 return self.get_string("getText", [locator,])
625
626
628 """
629 Gets the result of evaluating the specified JavaScript snippet. The snippet may
630 have multiple lines, but only the result of the last line will be returned.
631
632 Note that, by default, the snippet will run in the context of the "selenium"
633 object itself, so ``this`` will refer to the Selenium object, and ``window`` will
634 refer to the top-level runner test window, not the window of your application.
635 If you need a reference to the window of your application, you can refer
636 to ``this.browserbot.getCurrentWindow()`` and if you need to use
637 a locator to refer to a single element in your application page, you can
638 use ``this.page().findElement("foo")`` where "foo" is your locator.
639
640
641 'script' is the JavaScript snippet to run
642 """
643 return self.get_string("getEval", [script,])
644
645
647 """
648 Gets whether a toggle-button (checkbox/radio) is checked. Fails if the specified element doesn't exist or isn't a toggle-button.
649
650 'locator' is an element locator pointing to a checkbox or radio button
651 """
652 return self.get_boolean("isChecked", [locator,])
653
654
656 """
657 Gets the text from a cell of a table. The cellAddress syntax
658 tableLocator.row.column, where row and column start at 0.
659
660 'tableCellAddress' is a cell address, e.g. "foo.1.4"
661 """
662 return self.get_string("getTable", [tableCellAddress,])
663
664
666 """
667 Gets all option labels (visible text) for selected options in the specified select or multi-select element.
668
669 'selectLocator' is an element locator identifying a drop-down menu
670 """
671 return self.get_string_array("getSelectedLabels", [selectLocator,])
672
673
675 """
676 Gets option label (visible text) for selected option in the specified select element.
677
678 'selectLocator' is an element locator identifying a drop-down menu
679 """
680 return self.get_string("getSelectedLabel", [selectLocator,])
681
682
684 """
685 Gets all option values (value attributes) for selected options in the specified select or multi-select element.
686
687 'selectLocator' is an element locator identifying a drop-down menu
688 """
689 return self.get_string_array("getSelectedValues", [selectLocator,])
690
691
693 """
694 Gets option value (value attribute) for selected option in the specified select element.
695
696 'selectLocator' is an element locator identifying a drop-down menu
697 """
698 return self.get_string("getSelectedValue", [selectLocator,])
699
700
702 """
703 Gets all option indexes (option number, starting at 0) for selected options in the specified select or multi-select element.
704
705 'selectLocator' is an element locator identifying a drop-down menu
706 """
707 return self.get_string_array("getSelectedIndexes", [selectLocator,])
708
709
711 """
712 Gets option index (option number, starting at 0) for selected option in the specified select element.
713
714 'selectLocator' is an element locator identifying a drop-down menu
715 """
716 return self.get_string("getSelectedIndex", [selectLocator,])
717
718
720 """
721 Gets all option element IDs for selected options in the specified select or multi-select element.
722
723 'selectLocator' is an element locator identifying a drop-down menu
724 """
725 return self.get_string_array("getSelectedIds", [selectLocator,])
726
727
729 """
730 Gets option element ID for selected option in the specified select element.
731
732 'selectLocator' is an element locator identifying a drop-down menu
733 """
734 return self.get_string("getSelectedId", [selectLocator,])
735
736
738 """
739 Determines whether some option in a drop-down menu is selected.
740
741 'selectLocator' is an element locator identifying a drop-down menu
742 """
743 return self.get_boolean("isSomethingSelected", [selectLocator,])
744
745
747 """
748 Gets all option labels in the specified select drop-down.
749
750 'selectLocator' is an element locator identifying a drop-down menu
751 """
752 return self.get_string_array("getSelectOptions", [selectLocator,])
753
754
756 """
757 Gets the value of an element attribute.
758
759 'attributeLocator' is an element locator followed by an
760 """
761 return self.get_string("getAttribute", [attributeLocator,])
762
763
764 - def is_text_present(self,pattern):
765 """
766 Verifies that the specified text pattern appears somewhere on the rendered page shown to the user.
767
768 'pattern' is a pattern to match with the text of the page
769 """
770 return self.get_boolean("isTextPresent", [pattern,])
771
772
774 """
775 Verifies that the specified element is somewhere on the page.
776
777 'locator' is an element locator
778 """
779 return self.get_boolean("isElementPresent", [locator,])
780
781
783 """
784 Determines if the specified element is visible. An
785 element can be rendered invisible by setting the CSS "visibility"
786 property to "hidden", or the "display" property to "none", either for the
787 element itself or one if its ancestors. This method will fail if
788 the element is not present.
789
790 'locator' is an element locator
791 """
792 return self.get_boolean("isVisible", [locator,])
793
794
796 """
797 Determines whether the specified input element is editable, ie hasn't been disabled.
798 This method will fail if the specified element isn't an input element.
799
800 'locator' is an element locator
801 """
802 return self.get_boolean("isEditable", [locator,])
803
804
814
815
817 """
818 Returns the IDs of all links on the page.
819
820 If a given link has no ID, it will appear as "" in this array.
821
822
823 """
824 return self.get_string_array("getAllLinks", [])
825
826
828 """
829 Returns the IDs of all input fields on the page.
830
831 If a given field has no ID, it will appear as "" in this array.
832
833
834 """
835 return self.get_string_array("getAllFields", [])
836
837
839 """
840 Returns the entire HTML source between the opening and
841 closing "html" tags.
842
843 """
844 return self.get_string("getHtmlSource", [])
845
846
848 """
849 Moves the text cursor to the specified position in the given input element or textarea.
850 This method will fail if the specified element isn't an input element or textarea.
851
852 'locator' is an element locator pointing to an input element or textarea
853 'position' is the numerical position of the cursor in the field; position should be 0 to move the position to the beginning of the field. You can also set the cursor to -1 to move it to the end of the field.
854 """
855 self.do_command("setCursorPosition", [locator,position,])
856
857
859 """
860 Retrieves the text cursor position in the given input element or textarea; beware, this may not work perfectly on all browsers.
861
862 Specifically, if the cursor/selection has been cleared by JavaScript, this command will tend to
863 return the position of the last location of the cursor, even though the cursor is now gone from the page. This is filed as SEL-243.
864
865 This method will fail if the specified element isn't an input element or textarea, or there is no cursor in the element.
866
867 'locator' is an element locator pointing to an input element or textarea
868 """
869 return self.get_number("getCursorPosition", [locator,])
870
871
872 - def set_context(self,context,logLevelThreshold):
873 """
874 Writes a message to the status bar and adds a note to the browser-side
875 log.
876
877 If logLevelThreshold is specified, set the threshold for logging
878 to that level (debug, info, warn, error).
879 (Note that the browser-side logs will \ *not* be sent back to the
880 server, and are invisible to the Client Driver.)
881
882
883 'context' is the message to be sent to the browser
884 'logLevelThreshold' is one of "debug", "info", "warn", "error", sets the threshold for browser-side logging
885 """
886 self.do_command("setContext", [context,logLevelThreshold,])
887
888
890 """
891 Returns the specified expression.
892
893 This is useful because of JavaScript preprocessing.
894 It is used to generate commands like assertExpression and waitForExpression.
895
896
897 'expression' is the value to return
898 """
899 return self.get_string("getExpression", [expression,])
900
901
903 """
904 Runs the specified JavaScript snippet repeatedly until it evaluates to "true".
905 The snippet may have multiple lines, but only the result of the last line
906 will be considered.
907
908 Note that, by default, the snippet will be run in the runner's test window, not in the window
909 of your application. To get the window of your application, you can use
910 the JavaScript snippet ``selenium.browserbot.getCurrentWindow()``, and then
911 run your JavaScript in there
912
913
914 'script' is the JavaScript snippet to run
915 'timeout' is a timeout in milliseconds, after which this command will return with an error
916 """
917 self.do_command("waitForCondition", [script,timeout,])
918
919
921 """
922 Specifies the amount of time that Selenium will wait for actions to complete.
923
924 Actions that require waiting include "open" and the "waitFor*" actions.
925
926 The default timeout is 30 seconds.
927
928 'timeout' is a timeout in milliseconds, after which the action will return with an error
929 """
930 self.do_command("setTimeout", [timeout,])
931
932
933 - def wait_for_page_to_load(self,timeout):
934 """
935 Waits for a new page to load.
936
937 You can use this command instead of the "AndWait" suffixes, "clickAndWait", "selectAndWait", "typeAndWait" etc.
938 (which are only available in the JS API).
939 Selenium constantly keeps track of new pages loading, and sets a "newPageLoaded"
940 flag when it first notices a page load. Running any other Selenium command after
941 turns the flag to false. Hence, if you want to wait for a page to load, you must
942 wait immediately after a Selenium command that caused a page-load.
943
944
945 'timeout' is a timeout in milliseconds, after which this command will return with an error
946 """
947 self.do_command("waitForPageToLoad", [timeout,])
948