selenium-webdriver 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. data/chrome/prebuilt/Win32/Release/npchromedriver.dll +0 -0
  2. data/chrome/prebuilt/x64/Release/npchromedriver.dll +0 -0
  3. data/chrome/src/extension/background.html +9 -0
  4. data/chrome/src/extension/background.js +933 -0
  5. data/chrome/src/extension/content_script.js +1286 -0
  6. data/chrome/src/extension/manifest-nonwin.json +15 -0
  7. data/chrome/src/extension/manifest-win.json +16 -0
  8. data/chrome/src/extension/toolstrip.html +28 -0
  9. data/chrome/src/extension/utils.js +196 -0
  10. data/chrome/src/rb/lib/selenium/webdriver/chrome.rb +8 -0
  11. data/chrome/src/rb/lib/selenium/webdriver/chrome/bridge.rb +324 -0
  12. data/chrome/src/rb/lib/selenium/webdriver/chrome/command_executor.rb +70 -0
  13. data/chrome/src/rb/lib/selenium/webdriver/chrome/launcher.rb +119 -0
  14. data/common/src/js/abstractcommandprocessor.js +161 -0
  15. data/common/src/js/asserts.js +296 -0
  16. data/common/src/js/by.js +147 -0
  17. data/common/src/js/command.js +274 -0
  18. data/common/src/js/context.js +58 -0
  19. data/common/src/js/extension/README +2 -0
  20. data/common/src/js/extension/dommessenger.js +152 -0
  21. data/common/src/js/factory.js +55 -0
  22. data/common/src/js/future.js +118 -0
  23. data/common/src/js/key.js +117 -0
  24. data/common/src/js/localcommandprocessor.js +181 -0
  25. data/common/src/js/logging.js +249 -0
  26. data/common/src/js/testrunner.js +605 -0
  27. data/common/src/js/timing.js +89 -0
  28. data/common/src/js/wait.js +199 -0
  29. data/common/src/js/webdriver.js +853 -0
  30. data/common/src/js/webelement.js +683 -0
  31. data/common/src/rb/lib/selenium-webdriver.rb +1 -0
  32. data/common/src/rb/lib/selenium/webdriver.rb +52 -0
  33. data/common/src/rb/lib/selenium/webdriver/bridge_helper.rb +88 -0
  34. data/common/src/rb/lib/selenium/webdriver/child_process.rb +85 -0
  35. data/common/src/rb/lib/selenium/webdriver/core_ext/dir.rb +41 -0
  36. data/common/src/rb/lib/selenium/webdriver/driver.rb +128 -0
  37. data/common/src/rb/lib/selenium/webdriver/element.rb +126 -0
  38. data/common/src/rb/lib/selenium/webdriver/error.rb +68 -0
  39. data/common/src/rb/lib/selenium/webdriver/find.rb +69 -0
  40. data/common/src/rb/lib/selenium/webdriver/navigation.rb +23 -0
  41. data/common/src/rb/lib/selenium/webdriver/options.rb +50 -0
  42. data/common/src/rb/lib/selenium/webdriver/platform.rb +82 -0
  43. data/common/src/rb/lib/selenium/webdriver/target_locator.rb +23 -0
  44. data/firefox/prebuilt/nsICommandProcessor.xpt +0 -0
  45. data/firefox/prebuilt/nsINativeEvents.xpt +0 -0
  46. data/firefox/prebuilt/nsIResponseHandler.xpt +0 -0
  47. data/firefox/src/extension/chrome.manifest +3 -0
  48. data/firefox/src/extension/components/context.js +37 -0
  49. data/firefox/src/extension/components/driver-component.js +127 -0
  50. data/firefox/src/extension/components/firefoxDriver.js +706 -0
  51. data/firefox/src/extension/components/json2.js +273 -0
  52. data/firefox/src/extension/components/keytest.html +554 -0
  53. data/firefox/src/extension/components/nsCommandProcessor.js +586 -0
  54. data/firefox/src/extension/components/screenshooter.js +70 -0
  55. data/firefox/src/extension/components/socketListener.js +185 -0
  56. data/firefox/src/extension/components/utils.js +1200 -0
  57. data/firefox/src/extension/components/webLoadingListener.js +57 -0
  58. data/firefox/src/extension/components/webdriverserver.js +101 -0
  59. data/firefox/src/extension/components/wrappedElement.js +609 -0
  60. data/firefox/src/extension/content/fxdriver.xul +30 -0
  61. data/firefox/src/extension/content/server.js +95 -0
  62. data/firefox/src/extension/idl/nsICommandProcessor.idl +38 -0
  63. data/firefox/src/extension/idl/nsIResponseHandler.idl +34 -0
  64. data/firefox/src/extension/install.rdf +29 -0
  65. data/firefox/src/rb/lib/selenium/webdriver/firefox.rb +21 -0
  66. data/firefox/src/rb/lib/selenium/webdriver/firefox/binary.rb +86 -0
  67. data/firefox/src/rb/lib/selenium/webdriver/firefox/bridge.rb +426 -0
  68. data/firefox/src/rb/lib/selenium/webdriver/firefox/extension_connection.rb +82 -0
  69. data/firefox/src/rb/lib/selenium/webdriver/firefox/launcher.rb +132 -0
  70. data/firefox/src/rb/lib/selenium/webdriver/firefox/profile.rb +174 -0
  71. data/firefox/src/rb/lib/selenium/webdriver/firefox/profiles_ini.rb +60 -0
  72. data/firefox/src/rb/lib/selenium/webdriver/firefox/util.rb +23 -0
  73. data/jobbie/prebuilt/Win32/Release/InternetExplorerDriver.dll +0 -0
  74. data/jobbie/prebuilt/x64/Release/InternetExplorerDriver.dll +0 -0
  75. data/jobbie/src/rb/lib/selenium/webdriver/ie.rb +14 -0
  76. data/jobbie/src/rb/lib/selenium/webdriver/ie/bridge.rb +552 -0
  77. data/jobbie/src/rb/lib/selenium/webdriver/ie/lib.rb +94 -0
  78. data/jobbie/src/rb/lib/selenium/webdriver/ie/util.rb +147 -0
  79. data/remote/client/src/rb/lib/selenium/webdriver/remote.rb +16 -0
  80. data/remote/client/src/rb/lib/selenium/webdriver/remote/bridge.rb +374 -0
  81. data/remote/client/src/rb/lib/selenium/webdriver/remote/capabilities.rb +105 -0
  82. data/remote/client/src/rb/lib/selenium/webdriver/remote/commands.rb +53 -0
  83. data/remote/client/src/rb/lib/selenium/webdriver/remote/default_http_client.rb +71 -0
  84. data/remote/client/src/rb/lib/selenium/webdriver/remote/response.rb +43 -0
  85. data/remote/client/src/rb/lib/selenium/webdriver/remote/server_error.rb +32 -0
  86. metadata +182 -0
@@ -0,0 +1,30 @@
1
+ <?xml version="1.0"?>
2
+
3
+ <!--
4
+ Copyright 2007-2009 WebDriver committers
5
+ Copyright 2007-2009 Google Inc.
6
+
7
+ Licensed under the Apache License, Version 2.0 (the "License");
8
+ you may not use this file except in compliance with the License.
9
+ You may obtain a copy of the License at
10
+
11
+ http://www.apache.org/licenses/LICENSE-2.0
12
+
13
+ Unless required by applicable law or agreed to in writing, software
14
+ distributed under the License is distributed on an "AS IS" BASIS,
15
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ See the License for the specific language governing permissions and
17
+ limitations under the License.
18
+ -->
19
+
20
+ <overlay id="fxdriver-overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
21
+ <script src="dommessenger.js" />
22
+ <script src="server.js" />
23
+ <statusbar id="status-bar">
24
+ <statusbarpanel>
25
+ <hbox>
26
+ <label id="fxdriver-label" value="WebDriver" tooltiptext="This Firefox can be remote controlled with WebDriver." />
27
+ </hbox>
28
+ </statusbarpanel>
29
+ </statusbar>
30
+ </overlay>
@@ -0,0 +1,95 @@
1
+ /*
2
+ Copyright 2007-2009 WebDriver committers
3
+ Copyright 2007-2009 Google Inc.
4
+ Portions copyright 2007 ThoughtWorks, Inc
5
+
6
+ Licensed under the Apache License, Version 2.0 (the "License");
7
+ you may not use this file except in compliance with the License.
8
+ You may obtain a copy of the License at
9
+
10
+ http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+ Unless required by applicable law or agreed to in writing, software
13
+ distributed under the License is distributed on an "AS IS" BASIS,
14
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ See the License for the specific language governing permissions and
16
+ limitations under the License.
17
+ */
18
+
19
+ var driver = false;
20
+ var domMessenger = null;
21
+
22
+ // This will configure a FirefoxDriver and DomMessenger for each
23
+ // _browser window_ (not chrome window). Multiple tabs in the same window will
24
+ // share a FirefoxDriver and DomMessenger instance.
25
+ window.addEventListener("load", function(e) {
26
+ handle = Components.classes["@googlecode.com/webdriver/fxdriver;1"].createInstance(Components.interfaces.nsISupports);
27
+ var server = handle.wrappedJSObject;
28
+
29
+ if (!domMessenger) {
30
+ var appcontent = document.getElementById('appcontent');
31
+ if (appcontent) {
32
+ try {
33
+ var commandProcessor = Components.
34
+ classes['@googlecode.com/webdriver/command-processor;1'].
35
+ getService(Components.interfaces.nsICommandProcessor);
36
+ domMessenger = new DomMessenger(commandProcessor);
37
+ appcontent.addEventListener('DOMContentLoaded',
38
+ function(e) {
39
+ domMessenger.onPageLoad(e);
40
+ }, true);
41
+ appcontent.addEventListener('pagehide',
42
+ function(e) {
43
+ domMessenger.onPageUnload(e);
44
+ }, true);
45
+ } catch (ex) {
46
+ // Not catching this can really mess things up and lead to inexplicable
47
+ // and hard to debug behavior.
48
+ Components.utils.reportError(ex);
49
+ }
50
+ }
51
+ }
52
+
53
+ if (!driver) {
54
+ driver = server.newDriver(window);
55
+ } else {
56
+ if (window.content)
57
+ var frames = window.content.frames;
58
+
59
+ // If we are already focused on a frame, try and stay focused
60
+ if (driver.context.frameId !== undefined && frames) {
61
+ if (frames && frames.length > driver.context.frameId) {
62
+ // do nothing
63
+ } else {
64
+ if (frames && frames.length && "FRAME" == frames[0].frameElement.tagName) {
65
+ if (!frames[driver.context.frameId]) {
66
+ driver.context.frameId = 0;
67
+ }
68
+ } else {
69
+ driver.context.frameId = undefined;
70
+ }
71
+
72
+ }
73
+ } else {
74
+ // Other use a sensible default
75
+ if (frames && frames.length && "FRAME" == frames[0].frameElement.tagName) {
76
+ if (!frames[driver.context.frameId]) {
77
+ driver.context.frameId = 0;
78
+ }
79
+ } else {
80
+ driver.context.frameId = undefined;
81
+ }
82
+ }
83
+ }
84
+
85
+ server.startListening();
86
+
87
+ }, true);
88
+
89
+ //window.addEventListener("focus", function(e) {
90
+ // var active = e.originalTarget;
91
+ // var doc = gBrowser.selectedBrowser.contentDocument;
92
+ // if (active.ownerDocument == doc) {
93
+ // driver.activeElement = active;
94
+ // }
95
+ //}, true);
@@ -0,0 +1,38 @@
1
+ /*
2
+ Copyright 2007-2009 WebDriver committers
3
+ Copyright 2007-2009 Google Inc.
4
+ Portions copyright 2007 ThoughtWorks, Inc
5
+
6
+ Licensed under the Apache License, Version 2.0 (the "License");
7
+ you may not use this file except in compliance with the License.
8
+ You may obtain a copy of the License at
9
+
10
+ http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+ Unless required by applicable law or agreed to in writing, software
13
+ distributed under the License is distributed on an "AS IS" BASIS,
14
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ See the License for the specific language governing permissions and
16
+ limitations under the License.
17
+ */
18
+
19
+ #include "nsISupports.idl"
20
+ #include "nsIResponseHandler.idl"
21
+
22
+ /**
23
+ * Defines a single method for executing commands specified as a JSON string.
24
+ */
25
+ [scriptable, uuid(4427729b-441e-47c3-8380-df0350cac636)]
26
+ interface nsICommandProcessor : nsISupports {
27
+
28
+ /**
29
+ * Executes the given command specified in a JSON string. When the command
30
+ * is fully processed, the response will be sent to the given
31
+ * {@code nsIResponseHandler} callback as a JSON string.
32
+ *
33
+ * @param jsonCommandString The command to execute, specified in JSON format.
34
+ * @param responseHandler The callback to send the command response to.
35
+ */
36
+ void execute(in AUTF8String jsonCommandString,
37
+ in nsIResponseHandler responseHandler);
38
+ };
@@ -0,0 +1,34 @@
1
+ /*
2
+ Copyright 2007-2009 WebDriver committers
3
+ Copyright 2007-2009 Google Inc.
4
+ Portions copyright 2007 ThoughtWorks, Inc
5
+
6
+ Licensed under the Apache License, Version 2.0 (the "License");
7
+ you may not use this file except in compliance with the License.
8
+ You may obtain a copy of the License at
9
+
10
+ http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+ Unless required by applicable law or agreed to in writing, software
13
+ distributed under the License is distributed on an "AS IS" BASIS,
14
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ See the License for the specific language governing permissions and
16
+ limitations under the License.
17
+ */
18
+
19
+ #include "nsISupports.idl"
20
+
21
+ /**
22
+ * Defines a callback used to process the response to a command sent to the
23
+ * {@code nsICommandProcessor}.
24
+ */
25
+ [scriptable, function, uuid(0539a68f-b4a8-4543-bf2a-031cef89aff1)]
26
+ interface nsIResponseHandler : nsISupports {
27
+
28
+ /**
29
+ * Handle a response from the {@code nsICommandProcessor}.
30
+ *
31
+ * @param jsonResponseString The command response as a string.
32
+ */
33
+ void handleResponse(in AUTF8String jsonResponseString);
34
+ };
@@ -0,0 +1,29 @@
1
+ <?xml version="1.0"?>
2
+ <RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#">
3
+
4
+ <Description about="urn:mozilla:install-manifest">
5
+ <em:id>fxdriver@googlecode.com</em:id>
6
+ <em:name>Firefox WebDriver</em:name>
7
+ <em:version>0.6.680</em:version>
8
+ <em:description>WebDriver implementation for Firefox</em:description>
9
+ <em:creator>Simon Stewart</em:creator>
10
+
11
+ <!-- Firefox -->
12
+ <em:targetApplication>
13
+ <Description>
14
+ <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
15
+ <em:minVersion>2.0</em:minVersion>
16
+ <em:maxVersion>3.*</em:maxVersion>
17
+ </Description>
18
+ </em:targetApplication>
19
+
20
+ <!-- Platforms where we're not compiling the native events -->
21
+ <em:targetPlatform>Darwin</em:targetPlatform>
22
+ <em:targetPlatform>Linux</em:targetPlatform>
23
+ <!-- Platforms where we are -->
24
+ <em:targetPlatform>WINNT_x86-msvc</em:targetPlatform>
25
+
26
+ <!-- We're probably missing lots of platforms here -->
27
+ </Description>
28
+
29
+ </RDF>
@@ -0,0 +1,21 @@
1
+ require "timeout"
2
+ require "socket"
3
+
4
+ require "selenium/webdriver/firefox/util"
5
+ require "selenium/webdriver/firefox/binary"
6
+ require "selenium/webdriver/firefox/profiles_ini"
7
+ require "selenium/webdriver/firefox/profile"
8
+ require "selenium/webdriver/firefox/extension_connection"
9
+ require "selenium/webdriver/firefox/launcher"
10
+ require "selenium/webdriver/firefox/bridge"
11
+
12
+ module Selenium
13
+ module WebDriver
14
+ module Firefox
15
+
16
+ DEFAULT_PROFILE_NAME = "WebDriver".freeze
17
+ DEFAULT_PORT = 7055
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,86 @@
1
+ module Selenium
2
+ module WebDriver
3
+ module Firefox
4
+ class Binary
5
+ def initialize
6
+ ENV['MOZ_NO_REMOTE'] = '1' # able to launch multiple instances
7
+ check_binary_exists
8
+ end
9
+
10
+ def create_base_profile(name)
11
+ execute("-CreateProfile", name)
12
+ Timeout.timeout(15, Error::TimeOutError) { wait }
13
+
14
+ unless $?.success?
15
+ raise Error::WebDriverError, "could not create base profile: (#{$?.exitstatus})"
16
+ end
17
+ end
18
+
19
+ def start_with(profile, *args)
20
+ ENV['XRE_PROFILE_PATH'] = profile.absolute_path
21
+
22
+ # TODO: native lib loading
23
+ # if Platform.os == :unix && (profile.enable_native_events || profile.always_load_no_focus_lib)
24
+ # modify_link_library_path profile
25
+ # end
26
+
27
+ execute(*args)
28
+ end
29
+
30
+ def execute(*extra_args)
31
+ args = [path, "-no-remote", "--verbose"] + extra_args
32
+ @process = ChildProcess.new(*args).start
33
+ end
34
+
35
+ def kill
36
+ @process.kill if @process
37
+ end
38
+
39
+ def wait
40
+ @process.wait if @process
41
+ end
42
+
43
+ private
44
+
45
+ def path
46
+ @path ||= case Platform.os
47
+ when :macosx
48
+ "/Applications/Firefox.app/Contents/MacOS/firefox-bin"
49
+ when :windows
50
+ windows_path
51
+ when :unix
52
+ "/usr/bin/firefox"
53
+ else
54
+ raise "Unknown platform: #{Platform.os}"
55
+ end
56
+ end
57
+
58
+ def check_binary_exists
59
+ unless File.file?(path)
60
+ raise Error::WebDriverError, "Could not find Firefox binary. Make sure Firefox is installed (OS: #{Platform.os})"
61
+ end
62
+ end
63
+
64
+ def windows_path
65
+ windows_registry_path || (ENV['PROGRAMFILES'] || "\\Program Files") + "\\Mozilla Firefox\\firefox.exe"
66
+ end
67
+
68
+ def windows_registry_path
69
+ return if Platform.jruby?
70
+ require "win32/registry"
71
+
72
+ lm = Win32::Registry::HKEY_LOCAL_MACHINE
73
+ lm.open("SOFTWARE\\Mozilla\\Mozilla Firefox") do |reg|
74
+ main = lm.open("SOFTWARE\\Mozilla\\Mozilla Firefox\\#{reg.keys[0]}\\Main")
75
+ if entry = main.find {|key, type, data| key =~ /pathtoexe/i}
76
+ return entry.last
77
+ end
78
+ end
79
+ rescue Win32::Registry::Error
80
+ raise Error::WebDriverError, "Firefox not found in Windows registry, please make sure you have it installed."
81
+ end
82
+
83
+ end # Binary
84
+ end # Firefox
85
+ end # WebDriver
86
+ end # Selenium
@@ -0,0 +1,426 @@
1
+ module Selenium
2
+ module WebDriver
3
+ module Firefox
4
+ class Bridge
5
+ include BridgeHelper
6
+
7
+ def initialize
8
+ @binary = Binary.new
9
+ @launcher = Launcher.new(@binary).launch
10
+ @connection = @launcher.connection
11
+ @context = newSession
12
+ end
13
+
14
+ def browser
15
+ :firefox
16
+ end
17
+
18
+ def quit
19
+ @connection.quit
20
+ @binary.wait
21
+ nil
22
+ end
23
+
24
+ def getPageSource
25
+ execute :getPageSource
26
+ end
27
+
28
+ def getWindowHandles
29
+ execute(:getWindowHandles).to_s.split(", ")
30
+ end
31
+
32
+ def getCurrentWindowHandle
33
+ execute :getCurrentWindowHandle
34
+ end
35
+
36
+
37
+ def get(url)
38
+ execute :get,
39
+ :parameters => [url]
40
+ end
41
+
42
+ def close
43
+ execute :close
44
+ # TODO: rescue ?
45
+ end
46
+
47
+ def goBack
48
+ execute :goBack
49
+ end
50
+
51
+ def goForward
52
+ execute :goForward
53
+ end
54
+
55
+ def getCurrentUrl
56
+ execute :getCurrentUrl
57
+ end
58
+
59
+ def getTitle
60
+ execute :title
61
+ end
62
+
63
+ def executeScript(string, *args)
64
+ typed_args = args.map { |e| wrap_script_argument(e) }
65
+
66
+ resp = raw_execute :executeScript, :parameters => [string, typed_args]
67
+
68
+ unwrap_script_argument resp
69
+ end
70
+
71
+ #
72
+ # Finders - TODO: should be shared with Chrome::Bridge
73
+ #
74
+
75
+ def findElementByClassName(parent, class_name)
76
+ find_element_by 'class name', class_name, parent
77
+ end
78
+
79
+ def findElementsByClassName(parent, class_name)
80
+ find_elements_by 'class name', class_name, parent
81
+ end
82
+
83
+ def findElementById(parent, id)
84
+ find_element_by 'id', id, parent
85
+ end
86
+
87
+ def findElementsById(parent, id)
88
+ find_elements_by 'id', id, parent
89
+ end
90
+
91
+ def findElementByLinkText(parent, link_text)
92
+ find_element_by 'link text', link_text, parent
93
+ end
94
+
95
+ def findElementsByLinkText(parent, link_text)
96
+ find_elements_by 'link text', link_text, parent
97
+ end
98
+
99
+ def findElementByPartialLinkText(parent, link_text)
100
+ find_element_by 'partial link text', link_text, parent
101
+ end
102
+
103
+ def findElementsByPartialLinkText(parent, link_text)
104
+ find_elements_by 'partial link text', link_text, parent
105
+ end
106
+
107
+ def findElementByName(parent, name)
108
+ find_element_by 'name', name, parent
109
+ end
110
+
111
+ def findElementsByName(parent, name)
112
+ find_elements_by 'name', name, parent
113
+ end
114
+
115
+ def findElementByTagName(parent, tag_name)
116
+ find_element_by 'tag name', tag_name, parent
117
+ end
118
+
119
+ def findElementsByTagName(parent, tag_name)
120
+ find_elements_by 'tag name', tag_name, parent
121
+ end
122
+
123
+ def findElementByXpath(parent, xpath)
124
+ find_element_by 'xpath', xpath, parent
125
+ end
126
+
127
+ def findElementsByXpath(parent, xpath)
128
+ find_elements_by 'xpath', xpath, parent
129
+ end
130
+
131
+ #
132
+ # Element functions
133
+ #
134
+
135
+ def clickElement(element)
136
+ # execute :clickElement, :element_id => element
137
+ execute :click,
138
+ :element_id => element
139
+ end
140
+
141
+ def getElementTagName(element)
142
+ # execute :getElementTagName, :element_id => element
143
+ execute :getTagName,
144
+ :element_id => element
145
+ end
146
+
147
+ def getElementAttribute(element, name)
148
+ # execute :getElementAttribute, :element_id => element, :parameters => [name]
149
+ execute :getAttribute,
150
+ :element_id => element,
151
+ :parameters => [name]
152
+ end
153
+
154
+ def getElementValue(element)
155
+ # execute :getElementValue, :element_id => element
156
+ execute :getValue,
157
+ :element_id => element
158
+ end
159
+
160
+ def getElementText(element)
161
+ # execute :getElementText, :element_id => element
162
+ execute :getText,
163
+ :element_id => element
164
+ end
165
+
166
+ def getElementLocation(element)
167
+ # data = execute :getElementLocation, :element_id => element
168
+ data = execute :getLocation,
169
+ :element_id => element
170
+
171
+ Point.new(*data.split(",").map { |e| Integer(e.strip) })
172
+ end
173
+
174
+ def getElementSize(element)
175
+ # execute :getElementSize, :element_id => element
176
+ execute :getSize,
177
+ :element_id => element
178
+ end
179
+
180
+ def sendKeysToElement(element, string)
181
+ # execute :sendKeysToElement, :element_id => element, :parameters => [string.split(//u)]
182
+ execute :sendKeys,
183
+ :element_id => element,
184
+ :parameters => [string.to_s]
185
+ end
186
+
187
+ def clearElement(element)
188
+ # execute :clearElement, :element_id => element
189
+ execute :clear,
190
+ :element_id => element
191
+ end
192
+
193
+ def isElementEnabled(element)
194
+ # execute :isElementEnabled, :element_id => element
195
+ !getElementAttribute(element, "disabled")
196
+ end
197
+
198
+ def isElementSelected(element)
199
+ # execute :isElementSelected, :element_id => element
200
+ execute :isSelected,
201
+ :element_id => element
202
+ end
203
+
204
+ def isElementDisplayed(element)
205
+ # execute :isElementDisplayed, :element_id => element
206
+ execute :isDisplayed,
207
+ :element_id => element
208
+ end
209
+
210
+ def submitElement(element)
211
+ # execute :submitElement, :element_id => element
212
+ execute :submit,
213
+ :element_id => element
214
+ end
215
+
216
+ def toggleElement(element)
217
+ # execute :toggleElement, :element_id => element
218
+ execute :toggle,
219
+ :element_id => element
220
+ end
221
+
222
+ def setElementSelected(element)
223
+ # execute :setElementSelected, :element_id => element
224
+ execute :setSelected,
225
+ :element_id => element
226
+ end
227
+
228
+ def getElementValueOfCssProperty(element, prop)
229
+ # execute :getElementValueOfCssProperty, :element_id => element, :parameters => [prop]
230
+ execute :getValueOfCssProperty,
231
+ :element_id => element,
232
+ :parameters => [prop]
233
+ end
234
+
235
+ def hoverOverElement
236
+ execute :hover,
237
+ :element_id => element
238
+ # execute :hoverOverElement, :element_id => element
239
+ end
240
+
241
+ def dragElement(element, rigth_by, down_by)
242
+ execute :dragElement,
243
+ :element_id => element,
244
+ :parameters => [rigth_by, down_by]
245
+ end
246
+
247
+
248
+ def setSpeed(speed)
249
+ pixel_speed = case speed
250
+ when "SLOW" then '1'
251
+ when "MEDIUM" then '10'
252
+ when "FAST" then '100'
253
+ else
254
+ raise ArgumentError, "unknown speed: #{speed.inspect}"
255
+ end
256
+
257
+ execute :setMouseSpeed,
258
+ :parameters => [pixel_speed]
259
+ end
260
+
261
+ def getSpeed
262
+ case execute(:getMouseSpeed)
263
+ when '1' then "SLOW"
264
+ when '10' then "MEDIUM"
265
+ when '100' then "FAST"
266
+ else
267
+ "FAST"
268
+ end
269
+ end
270
+
271
+ def addCookie(cookie)
272
+ execute :addCookie,
273
+ :parameters => [cookie.to_json] # uhm, sending text instead of data
274
+ end
275
+
276
+ def deleteCookie(name)
277
+ execute :deleteCookie,
278
+ :parameters => [{:name => name}.to_json] # ditto
279
+ end
280
+
281
+ def getAllCookies
282
+ data = execute :getCookie
283
+
284
+ data.strip.split("\n").map do |c|
285
+ parse_cookie_string(c) unless c.strip.empty?
286
+ end.compact
287
+ end
288
+
289
+ #
290
+ # FF-specific?
291
+ #
292
+
293
+ def deleteAllCookies
294
+ execute :deleteAllCookies
295
+ end
296
+
297
+ def getCookieNamed(name)
298
+ getCookies.find { |c| c['name'] == name }
299
+ end
300
+
301
+ def switchToFrame(name)
302
+ execute :switchToFrame,
303
+ :parameters => [name.to_s]
304
+ end
305
+
306
+ def switchToWindow(name)
307
+ @context = execute :switchToWindow,
308
+ :parameters => [name.to_s]
309
+ end
310
+
311
+ def switchToActiveElement
312
+ Element.new self, element_id_from(execute(:switchToActiveElement))
313
+ end
314
+ alias_method :getActiveElement, :switchToActiveElement
315
+
316
+ private
317
+
318
+ def find_element_by(how, what, parent = nil)
319
+ if parent
320
+ id = execute :findChildElement,
321
+ :parameters => [{:id => parent, :using => how, :value => what}]
322
+ else
323
+ id = execute :findElement,
324
+ :parameters => [how, what]
325
+ end
326
+
327
+ Element.new self, element_id_from(id)
328
+ end
329
+
330
+ def find_elements_by(how, what, parent = nil)
331
+ if parent
332
+ id_string = execute :findChildElements,
333
+ :parameters => [{:id => parent, :using => how, :value => what}]
334
+ else
335
+ id_string = execute :findElements,
336
+ :parameters => [how, what]
337
+ end
338
+
339
+ id_string.split(",").map { |id| Element.new self, element_id_from(id) }
340
+ end
341
+
342
+ def newSession
343
+ execute :newSession
344
+ end
345
+
346
+ def execute(*args)
347
+ raw_execute(*args)['response']
348
+ end
349
+
350
+ def raw_execute(command, opts = {})
351
+ request = {:commandName => command, :context => @context.to_s}
352
+
353
+ if eid = opts[:element_id]
354
+ request[:elementId] = eid
355
+ end
356
+
357
+ if params = opts[:parameters]
358
+ request[:parameters] = params
359
+ end
360
+
361
+ puts "--> #{request.inspect}" if $DEBUG
362
+
363
+ @connection.send_string request.to_json
364
+ resp = @connection.read_response
365
+
366
+ puts "<-- #{resp.inspect}" if $DEBUG
367
+
368
+ if resp['isError']
369
+ msg = resp['response']['message'] rescue nil
370
+ msg ||= resp['response'] || resp.inspect
371
+ raise Error::WebDriverError, msg
372
+ end
373
+
374
+ if ctx = resp['context']
375
+ @context = ctx
376
+ end
377
+
378
+ resp
379
+ end
380
+
381
+ #
382
+ # wrap/unwrap will be shared with Chrome (overrides BridgeHelper for now)
383
+ #
384
+
385
+ def wrap_script_argument(arg)
386
+ case arg
387
+ when Integer, Float
388
+ { :type => "NUMBER", :value => arg }
389
+ when TrueClass, FalseClass, NilClass
390
+ { :type => "BOOLEAN", :value => !!arg }
391
+ when Element
392
+ { :type => "ELEMENT", :value => arg.ref }
393
+ when String
394
+ { :type => "STRING", :value => arg.to_s }
395
+ when Array # Enumerable?
396
+ arg.map { |e| wrap_script_argument(e) }
397
+ else
398
+ raise TypeError, "Parameter is not of recognized type: #{arg.inspect}:#{arg.class}"
399
+ end
400
+ end
401
+
402
+ def unwrap_script_argument(arg)
403
+ raise TypeError, "expected Hash" unless arg.kind_of? Hash
404
+ case arg["resultType"]
405
+ when "NULL"
406
+ nil
407
+ when "ELEMENT"
408
+ Element.new self, element_id_from(arg["response"])
409
+ when "ARRAY"
410
+ arg['response'].map { |e| unwrap_script_argument(e) }
411
+ # when "POINT"
412
+ # Point.new arg['x'], arg['y']
413
+ # when "DIMENSION"
414
+ # Dimension.new arg['width'], arg['height']
415
+ # when "COOKIE"
416
+ # {:name => arg['name'], :value => arg['value']}
417
+ else
418
+ arg["response"]
419
+ end
420
+ end
421
+
422
+
423
+ end # Bridge
424
+ end # Firefox
425
+ end # WebDriver
426
+ end # Selenium