selenium-webdriver 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/chrome/prebuilt/Win32/Release/npchromedriver.dll +0 -0
- data/chrome/prebuilt/x64/Release/npchromedriver.dll +0 -0
- data/chrome/src/extension/background.html +9 -0
- data/chrome/src/extension/background.js +933 -0
- data/chrome/src/extension/content_script.js +1286 -0
- data/chrome/src/extension/manifest-nonwin.json +15 -0
- data/chrome/src/extension/manifest-win.json +16 -0
- data/chrome/src/extension/toolstrip.html +28 -0
- data/chrome/src/extension/utils.js +196 -0
- data/chrome/src/rb/lib/selenium/webdriver/chrome.rb +8 -0
- data/chrome/src/rb/lib/selenium/webdriver/chrome/bridge.rb +324 -0
- data/chrome/src/rb/lib/selenium/webdriver/chrome/command_executor.rb +70 -0
- data/chrome/src/rb/lib/selenium/webdriver/chrome/launcher.rb +119 -0
- data/common/src/js/abstractcommandprocessor.js +161 -0
- data/common/src/js/asserts.js +296 -0
- data/common/src/js/by.js +147 -0
- data/common/src/js/command.js +274 -0
- data/common/src/js/context.js +58 -0
- data/common/src/js/extension/README +2 -0
- data/common/src/js/extension/dommessenger.js +152 -0
- data/common/src/js/factory.js +55 -0
- data/common/src/js/future.js +118 -0
- data/common/src/js/key.js +117 -0
- data/common/src/js/localcommandprocessor.js +181 -0
- data/common/src/js/logging.js +249 -0
- data/common/src/js/testrunner.js +605 -0
- data/common/src/js/timing.js +89 -0
- data/common/src/js/wait.js +199 -0
- data/common/src/js/webdriver.js +853 -0
- data/common/src/js/webelement.js +683 -0
- data/common/src/rb/lib/selenium-webdriver.rb +1 -0
- data/common/src/rb/lib/selenium/webdriver.rb +52 -0
- data/common/src/rb/lib/selenium/webdriver/bridge_helper.rb +88 -0
- data/common/src/rb/lib/selenium/webdriver/child_process.rb +85 -0
- data/common/src/rb/lib/selenium/webdriver/core_ext/dir.rb +41 -0
- data/common/src/rb/lib/selenium/webdriver/driver.rb +128 -0
- data/common/src/rb/lib/selenium/webdriver/element.rb +126 -0
- data/common/src/rb/lib/selenium/webdriver/error.rb +68 -0
- data/common/src/rb/lib/selenium/webdriver/find.rb +69 -0
- data/common/src/rb/lib/selenium/webdriver/navigation.rb +23 -0
- data/common/src/rb/lib/selenium/webdriver/options.rb +50 -0
- data/common/src/rb/lib/selenium/webdriver/platform.rb +82 -0
- data/common/src/rb/lib/selenium/webdriver/target_locator.rb +23 -0
- data/firefox/prebuilt/nsICommandProcessor.xpt +0 -0
- data/firefox/prebuilt/nsINativeEvents.xpt +0 -0
- data/firefox/prebuilt/nsIResponseHandler.xpt +0 -0
- data/firefox/src/extension/chrome.manifest +3 -0
- data/firefox/src/extension/components/context.js +37 -0
- data/firefox/src/extension/components/driver-component.js +127 -0
- data/firefox/src/extension/components/firefoxDriver.js +706 -0
- data/firefox/src/extension/components/json2.js +273 -0
- data/firefox/src/extension/components/keytest.html +554 -0
- data/firefox/src/extension/components/nsCommandProcessor.js +586 -0
- data/firefox/src/extension/components/screenshooter.js +70 -0
- data/firefox/src/extension/components/socketListener.js +185 -0
- data/firefox/src/extension/components/utils.js +1200 -0
- data/firefox/src/extension/components/webLoadingListener.js +57 -0
- data/firefox/src/extension/components/webdriverserver.js +101 -0
- data/firefox/src/extension/components/wrappedElement.js +609 -0
- data/firefox/src/extension/content/fxdriver.xul +30 -0
- data/firefox/src/extension/content/server.js +95 -0
- data/firefox/src/extension/idl/nsICommandProcessor.idl +38 -0
- data/firefox/src/extension/idl/nsIResponseHandler.idl +34 -0
- data/firefox/src/extension/install.rdf +29 -0
- data/firefox/src/rb/lib/selenium/webdriver/firefox.rb +21 -0
- data/firefox/src/rb/lib/selenium/webdriver/firefox/binary.rb +86 -0
- data/firefox/src/rb/lib/selenium/webdriver/firefox/bridge.rb +426 -0
- data/firefox/src/rb/lib/selenium/webdriver/firefox/extension_connection.rb +82 -0
- data/firefox/src/rb/lib/selenium/webdriver/firefox/launcher.rb +132 -0
- data/firefox/src/rb/lib/selenium/webdriver/firefox/profile.rb +174 -0
- data/firefox/src/rb/lib/selenium/webdriver/firefox/profiles_ini.rb +60 -0
- data/firefox/src/rb/lib/selenium/webdriver/firefox/util.rb +23 -0
- data/jobbie/prebuilt/Win32/Release/InternetExplorerDriver.dll +0 -0
- data/jobbie/prebuilt/x64/Release/InternetExplorerDriver.dll +0 -0
- data/jobbie/src/rb/lib/selenium/webdriver/ie.rb +14 -0
- data/jobbie/src/rb/lib/selenium/webdriver/ie/bridge.rb +552 -0
- data/jobbie/src/rb/lib/selenium/webdriver/ie/lib.rb +94 -0
- data/jobbie/src/rb/lib/selenium/webdriver/ie/util.rb +147 -0
- data/remote/client/src/rb/lib/selenium/webdriver/remote.rb +16 -0
- data/remote/client/src/rb/lib/selenium/webdriver/remote/bridge.rb +374 -0
- data/remote/client/src/rb/lib/selenium/webdriver/remote/capabilities.rb +105 -0
- data/remote/client/src/rb/lib/selenium/webdriver/remote/commands.rb +53 -0
- data/remote/client/src/rb/lib/selenium/webdriver/remote/default_http_client.rb +71 -0
- data/remote/client/src/rb/lib/selenium/webdriver/remote/response.rb +43 -0
- data/remote/client/src/rb/lib/selenium/webdriver/remote/server_error.rb +32 -0
- metadata +182 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
module Selenium
|
|
2
|
+
module WebDriver
|
|
3
|
+
module Chrome
|
|
4
|
+
class CommandExecutor
|
|
5
|
+
TEMPLATE = "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: application/json; charset=UTF-8\r\n\r\n%s"
|
|
6
|
+
|
|
7
|
+
def initialize
|
|
8
|
+
@server = TCPServer.new("0.0.0.0", 9700)
|
|
9
|
+
@queue = Queue.new
|
|
10
|
+
@accepted_any = false
|
|
11
|
+
@next_socket = nil
|
|
12
|
+
|
|
13
|
+
Thread.new { start_run_loop }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def execute(command)
|
|
17
|
+
until accepted_any?
|
|
18
|
+
Thread.pass
|
|
19
|
+
sleep 0.01
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
json = command.to_json
|
|
23
|
+
data = TEMPLATE % [json.length, json]
|
|
24
|
+
|
|
25
|
+
@next_socket.write data
|
|
26
|
+
@next_socket.close
|
|
27
|
+
|
|
28
|
+
JSON.parse read_response(@queue.pop)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def start_run_loop
|
|
34
|
+
loop do
|
|
35
|
+
socket = @server.accept
|
|
36
|
+
@queue << socket
|
|
37
|
+
|
|
38
|
+
unless accepted_any?
|
|
39
|
+
read_response socket
|
|
40
|
+
@queue.pop
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
@accepted_any ||= true
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def read_response(socket)
|
|
48
|
+
result = ''
|
|
49
|
+
|
|
50
|
+
seen_double_crlf = false
|
|
51
|
+
while !socket.closed? && ((line = socket.gets.chomp) != "EOResponse")
|
|
52
|
+
seen_double_crlf = true if line.empty?
|
|
53
|
+
result << "#{line}\n" if seen_double_crlf
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
@next_socket = socket
|
|
57
|
+
|
|
58
|
+
result.strip!
|
|
59
|
+
# p result
|
|
60
|
+
result
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def accepted_any?
|
|
64
|
+
@accepted_any
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
end # CommandExecutor
|
|
68
|
+
end # Chrome
|
|
69
|
+
end # WebDriver
|
|
70
|
+
end # Selenium
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
module Selenium
|
|
2
|
+
module WebDriver
|
|
3
|
+
module Chrome
|
|
4
|
+
class Launcher
|
|
5
|
+
include FileUtils
|
|
6
|
+
|
|
7
|
+
attr_reader :pid
|
|
8
|
+
|
|
9
|
+
def self.launcher
|
|
10
|
+
launcher = case Platform.os
|
|
11
|
+
when :windows
|
|
12
|
+
WindowsLauncher.new
|
|
13
|
+
when :macosx
|
|
14
|
+
MacOSXLauncher.new
|
|
15
|
+
when :unix
|
|
16
|
+
UnixLauncher.new
|
|
17
|
+
else
|
|
18
|
+
raise "unknown OS: #{Platform.os}"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
launcher
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def launch
|
|
25
|
+
create_extension
|
|
26
|
+
create_profile
|
|
27
|
+
launch_chrome
|
|
28
|
+
|
|
29
|
+
pid
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def kill
|
|
33
|
+
@process.kill
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def create_extension
|
|
39
|
+
ext_files.each { |file| cp file, tmp_extension_dir }
|
|
40
|
+
|
|
41
|
+
if Platform.win?
|
|
42
|
+
cp linked_lib_path, tmp_extension_dir
|
|
43
|
+
mv "#{tmp_extension_dir}/manifest-win.json", "#{tmp_extension_dir}/manifest.json"
|
|
44
|
+
else
|
|
45
|
+
mv "#{tmp_extension_dir}/manifest-nonwin.json", "#{tmp_extension_dir}/manifest.json"
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def create_profile
|
|
50
|
+
touch "#{tmp_profile_dir}/First Run Dev"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def launch_chrome
|
|
54
|
+
@process = ChildProcess.new Platform.wrap_in_quotes_if_necessary(binary_path),
|
|
55
|
+
"--load-extension=#{Platform.wrap_in_quotes_if_necessary tmp_extension_dir}",
|
|
56
|
+
"--user-data-dir=#{Platform.wrap_in_quotes_if_necessary tmp_profile_dir}",
|
|
57
|
+
"--activate-on-launch",
|
|
58
|
+
"--disable-hang-monitor",
|
|
59
|
+
"--disable-popup-blocking",
|
|
60
|
+
"--disable-prompt-on-repost",
|
|
61
|
+
"about:blank"
|
|
62
|
+
@process.start
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def ext_files
|
|
66
|
+
Dir["#{ext_path}/*"]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def ext_path
|
|
70
|
+
@ext_path ||= "#{WebDriver.root}/chrome/src/extension"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def tmp_extension_dir
|
|
74
|
+
@tmp_extension_dir ||= begin
|
|
75
|
+
dir = Dir.mktmpdir("webdriver-chrome-extension")
|
|
76
|
+
Platform.make_writable(dir)
|
|
77
|
+
|
|
78
|
+
dir
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def tmp_profile_dir
|
|
83
|
+
@tmp_profile_dir ||= begin
|
|
84
|
+
dir = Dir.mktmpdir("webdriver-chrome-profile")
|
|
85
|
+
Platform.make_writable(dir)
|
|
86
|
+
|
|
87
|
+
dir
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
class WindowsLauncher < Launcher
|
|
92
|
+
def linked_lib_path
|
|
93
|
+
# TODO: x64
|
|
94
|
+
@linked_lib_path ||= "#{WebDriver.root}/chrome/prebuilt/Win32/Release/npchromedriver.dll"
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def binary_path
|
|
98
|
+
@binary_path ||= "#{Platform.home}\\Local Settings\\Application Data\\Google\\Chrome\\Application\\chrome.exe"
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
class UnixLauncher < Launcher
|
|
104
|
+
def binary_path
|
|
105
|
+
@binary_path ||= "/usr/bin/google-chrome"
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
class MacOSXLauncher < UnixLauncher
|
|
111
|
+
def binary_path
|
|
112
|
+
@binary_path ||= "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
end # Launcher
|
|
117
|
+
end # Chrome
|
|
118
|
+
end # WebDriver
|
|
119
|
+
end # Selenium
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/** @license
|
|
2
|
+
Copyright 2007-2009 WebDriver committers
|
|
3
|
+
Copyright 2007-2009 Google 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
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @fileoverview Base class for all WebDriver command processors.
|
|
20
|
+
* @author jmleyba@gmail.com (Jason Leyba)
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
goog.provide('webdriver.AbstractCommandProcessor');
|
|
24
|
+
|
|
25
|
+
goog.require('goog.Disposable');
|
|
26
|
+
goog.require('goog.array');
|
|
27
|
+
goog.require('goog.object');
|
|
28
|
+
goog.require('webdriver.CommandName');
|
|
29
|
+
goog.require('webdriver.Context');
|
|
30
|
+
goog.require('webdriver.Future');
|
|
31
|
+
goog.require('webdriver.Response');
|
|
32
|
+
goog.require('webdriver.timing');
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Base class for all WebDriver command processors.
|
|
37
|
+
* @constructor
|
|
38
|
+
* @extends {goog.Disposable}
|
|
39
|
+
*/
|
|
40
|
+
webdriver.AbstractCommandProcessor = function() {
|
|
41
|
+
goog.Disposable.call(this);
|
|
42
|
+
};
|
|
43
|
+
goog.inherits(webdriver.AbstractCommandProcessor, goog.Disposable);
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Updates a {@code webdriver.Command} instance so that any parameters that
|
|
48
|
+
* are {@code webdriver.Future} values are converted to their asynchronously set
|
|
49
|
+
* values.
|
|
50
|
+
* @param {webdriver.Command} command The command object to modify.
|
|
51
|
+
* @throws If an attempt is made to fetch the value of a
|
|
52
|
+
* {@code webdriver.Future} that hasn't been computed yet.
|
|
53
|
+
* @private
|
|
54
|
+
*/
|
|
55
|
+
webdriver.AbstractCommandProcessor.resolveFutureParams_ = function(
|
|
56
|
+
command) {
|
|
57
|
+
function getValue(obj) {
|
|
58
|
+
if (obj instanceof webdriver.Future) {
|
|
59
|
+
return obj.getValue();
|
|
60
|
+
} else if (goog.isFunction(obj)) {
|
|
61
|
+
return obj;
|
|
62
|
+
} else if (goog.isObject(obj)) {
|
|
63
|
+
goog.object.forEach(obj, function(value, key) {
|
|
64
|
+
obj[key] = getValue(value);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
return obj;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
command.parameters = goog.array.map(command.parameters, function(param) {
|
|
71
|
+
if (goog.isArray(param)) {
|
|
72
|
+
return goog.array.map(param, getValue);
|
|
73
|
+
} else {
|
|
74
|
+
return getValue(param);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Executes a command.
|
|
82
|
+
* @param {webdriver.Command} command The command to execute.
|
|
83
|
+
* @param {string} sessionId The current session ID.
|
|
84
|
+
* @param {webdriver.Context} context The context to execute the command in.
|
|
85
|
+
*/
|
|
86
|
+
webdriver.AbstractCommandProcessor.prototype.execute = function(command,
|
|
87
|
+
sessionId,
|
|
88
|
+
context) {
|
|
89
|
+
webdriver.AbstractCommandProcessor.resolveFutureParams_(command);
|
|
90
|
+
switch (command.name) {
|
|
91
|
+
case webdriver.CommandName.SLEEP:
|
|
92
|
+
var ms = command.parameters[0];
|
|
93
|
+
webdriver.timing.setTimeout(function() {
|
|
94
|
+
command.setResponse(new webdriver.Response(false, context, ms));
|
|
95
|
+
}, ms);
|
|
96
|
+
break;
|
|
97
|
+
|
|
98
|
+
case webdriver.CommandName.WAIT:
|
|
99
|
+
var callback = goog.bind(this.waitCallback_, this, command, context);
|
|
100
|
+
command.parameters[0].start(callback);
|
|
101
|
+
break;
|
|
102
|
+
|
|
103
|
+
case webdriver.CommandName.FUNCTION:
|
|
104
|
+
try {
|
|
105
|
+
var result = command.parameters[0]();
|
|
106
|
+
command.setResponse(new webdriver.Response(false, context, result));
|
|
107
|
+
} catch (ex) {
|
|
108
|
+
command.setResponse(new webdriver.Response(true, context, null, ex));
|
|
109
|
+
}
|
|
110
|
+
break;
|
|
111
|
+
|
|
112
|
+
default:
|
|
113
|
+
try {
|
|
114
|
+
this.executeDriverCommand(command, sessionId, context);
|
|
115
|
+
} catch (ex) {
|
|
116
|
+
command.setResponse(new webdriver.Response(true, context, null, ex));
|
|
117
|
+
}
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Callback for {@code webdriver.CommandName.WAIT} commands.
|
|
125
|
+
* @param {webdriver.Command} command The wait command.
|
|
126
|
+
* @param {webdriver.Context} context The context the command executed in.
|
|
127
|
+
* @param {boolean} isTimeout Whether the wait finished from a timeout.
|
|
128
|
+
* @param {number} elapsedTime The amount of time spent waiting, in
|
|
129
|
+
* milliseconds.
|
|
130
|
+
* @param {Error} opt_ex If defined, an error that caused the wait to terminate
|
|
131
|
+
* early.
|
|
132
|
+
*/
|
|
133
|
+
webdriver.AbstractCommandProcessor.prototype.waitCallback_ = function(
|
|
134
|
+
command, context, isTimeout, elapsedTime, opt_ex) {
|
|
135
|
+
var message;
|
|
136
|
+
if (opt_ex) {
|
|
137
|
+
message = 'Error';
|
|
138
|
+
} else if (isTimeout) {
|
|
139
|
+
message = 'Timeout';
|
|
140
|
+
} else {
|
|
141
|
+
message = 'Ready';
|
|
142
|
+
}
|
|
143
|
+
var response = new webdriver.Response(isTimeout || opt_ex, context,
|
|
144
|
+
message + ' after ' + elapsedTime + 'ms');
|
|
145
|
+
if (opt_ex) {
|
|
146
|
+
response.errors.push(opt_ex);
|
|
147
|
+
}
|
|
148
|
+
command.setResponse(response);
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Sends a command to be executed by a browser driver. This method must be
|
|
154
|
+
* implemented by each subclass.
|
|
155
|
+
* @param {webdriver.Command} command The command to execute.
|
|
156
|
+
* @param {string} sessionId The current session ID.
|
|
157
|
+
* @param {webdriver.Context} context The context to execute the command in.
|
|
158
|
+
* @protected
|
|
159
|
+
*/
|
|
160
|
+
webdriver.AbstractCommandProcessor.prototype.executeDriverCommand =
|
|
161
|
+
goog.abstractMethod;
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
/** @license
|
|
2
|
+
Copyright 2007-2009 WebDriver committers
|
|
3
|
+
Copyright 2007-2009 Google 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
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @fileoverview Assertion functions for use in webdriver test cases.
|
|
20
|
+
* @author jmleyba@gmail.com (Jason Leyba)
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
goog.provide('webdriver.asserts');
|
|
24
|
+
|
|
25
|
+
goog.require('goog.math.Coordinate');
|
|
26
|
+
goog.require('goog.string');
|
|
27
|
+
goog.require('webdriver.Future');
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @param {webdriver.Future|Object} obj The object to get the value form.
|
|
32
|
+
* @return {*} The value of the given object.
|
|
33
|
+
*/
|
|
34
|
+
webdriver.asserts.getValue_ = function(obj) {
|
|
35
|
+
return obj instanceof webdriver.Future ? obj.getValue() : obj;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Returns a string with the following format: "<$value> ($type)" where $value
|
|
41
|
+
* is the String representation of the {@code obj} and $type is its type.
|
|
42
|
+
* @param {*} obj The object to build a string for.
|
|
43
|
+
* @return {string} A string describing the given object.
|
|
44
|
+
*/
|
|
45
|
+
webdriver.asserts.objToString = function(obj) {
|
|
46
|
+
var value = webdriver.asserts.getValue_(obj);
|
|
47
|
+
var valueStr = goog.isDef(value) ? String(value) : 'undefined';
|
|
48
|
+
return '<' + valueStr + '> (' + goog.typeOf(value) + ')';
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* A class for determining if a value matches a defined criteria.
|
|
54
|
+
* @param {function} matchFn A function that takes a single argument and whether
|
|
55
|
+
* that argument matches the criteria defined by this Matcher.
|
|
56
|
+
* @param {function} describeFn A function that returns a string describing the
|
|
57
|
+
* criteria for this matcher. The string returned by this function should
|
|
58
|
+
* finish this sentence: "Expected to..."
|
|
59
|
+
* @constructor
|
|
60
|
+
*/
|
|
61
|
+
webdriver.asserts.Matcher = function(matchFn, describeFn) {
|
|
62
|
+
this.matches = matchFn;
|
|
63
|
+
this.describe = describeFn;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Factory method for a {@code webdriver.asserts.Matcher} that does a
|
|
69
|
+
* {@code ===} comparison between the expected and actual values.
|
|
70
|
+
* @param {*} expected The expected value.
|
|
71
|
+
* @return {webdriver.asserts.Matcher} An equality matcher.
|
|
72
|
+
*/
|
|
73
|
+
webdriver.asserts.Matcher.equals = function(expected) {
|
|
74
|
+
return new webdriver.asserts.Matcher(
|
|
75
|
+
function (actual) {
|
|
76
|
+
return webdriver.asserts.getValue_(expected) ===
|
|
77
|
+
webdriver.asserts.getValue_(actual);
|
|
78
|
+
},
|
|
79
|
+
function () {
|
|
80
|
+
return 'equal ' + webdriver.asserts.objToString(expected);
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
goog.exportSymbol('equals', webdriver.asserts.Matcher.equals);
|
|
84
|
+
goog.exportSymbol('is', webdriver.asserts.Matcher.equals);
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Creates a {@code webdriver.asserts.Matcher} that tests if the actual
|
|
89
|
+
* value contains the expected value.
|
|
90
|
+
* @param {string} expected The string expected to be in the actual value.
|
|
91
|
+
* @return {webdriver.asserts.Matcher} A new matcher.
|
|
92
|
+
*/
|
|
93
|
+
webdriver.asserts.Matcher.contains = function(expected) {
|
|
94
|
+
return new webdriver.asserts.Matcher(
|
|
95
|
+
function (actual) {
|
|
96
|
+
var ev = webdriver.asserts.getValue_(expected);
|
|
97
|
+
var av = webdriver.asserts.getValue_(actual);
|
|
98
|
+
return goog.string.contains(av, ev);
|
|
99
|
+
},
|
|
100
|
+
function () {
|
|
101
|
+
return 'contain ' + webdriver.asserts.objToString(expected);
|
|
102
|
+
});
|
|
103
|
+
};
|
|
104
|
+
goog.exportSymbol('contains', webdriver.asserts.Matcher.contains);
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Creates a {@code webdriver.asserts.Matcher} that tests if the actual value
|
|
109
|
+
* matches the given regular expression.
|
|
110
|
+
* @param {RegEx} regex The expected regular expression.
|
|
111
|
+
* @return {webdriver.asserts.Matcher} A new matcher.
|
|
112
|
+
*/
|
|
113
|
+
webdriver.asserts.Matcher.matchesRegex = function(regex) {
|
|
114
|
+
if (!(regex instanceof RegExp)) {
|
|
115
|
+
throw new Error('IllegalArgument; must be a RegExp, but was: ' + regex +
|
|
116
|
+
'(' + goog.typeOf(regex) + ')');
|
|
117
|
+
}
|
|
118
|
+
return new webdriver.asserts.Matcher(
|
|
119
|
+
function (actual) {
|
|
120
|
+
var av = webdriver.asserts.getValue_(actual);
|
|
121
|
+
return av.match(regex) != null;
|
|
122
|
+
},
|
|
123
|
+
function () {
|
|
124
|
+
return 'match regex ' + regex;
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
goog.exportSymbol('matchesRegex', webdriver.asserts.Matcher.matchesRegex);
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Creates a {@code webdriver.asserts.Matcher} that tests if the actual value
|
|
132
|
+
* starts with the given string.
|
|
133
|
+
* @param {string} expected The expected beginning of the tested string.
|
|
134
|
+
* @return {webdriver.asserts.Matcher} A new matcher.
|
|
135
|
+
*/
|
|
136
|
+
webdriver.asserts.Matcher.startsWith = function(expected) {
|
|
137
|
+
return new webdriver.asserts.Matcher(
|
|
138
|
+
function (actual) {
|
|
139
|
+
var ev = webdriver.asserts.getValue_(expected);
|
|
140
|
+
var av = webdriver.asserts.getValue_(actual);
|
|
141
|
+
return goog.string.startsWith(av, ev);
|
|
142
|
+
},
|
|
143
|
+
function () {
|
|
144
|
+
return 'start with ' + webdriver.asserts.objToString(expected);
|
|
145
|
+
});
|
|
146
|
+
};
|
|
147
|
+
goog.exportSymbol('startsWith', webdriver.asserts.Matcher.startsWith);
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Creates a {@code webdriver.asserts.Matcher} that tests if the actual value is
|
|
152
|
+
* the same location as the expected value.
|
|
153
|
+
* @param {goog.math.Coordinate} expected The expected location, or a future
|
|
154
|
+
* whose pending result is the expected location.
|
|
155
|
+
* @return {webdriver.asserts.Matcher} A new matcher.
|
|
156
|
+
*/
|
|
157
|
+
webdriver.asserts.Matcher.isTheSameLocationAs = function(expected) {
|
|
158
|
+
return new webdriver.asserts.Matcher(
|
|
159
|
+
function (actual) {
|
|
160
|
+
var ev = webdriver.asserts.getValue_(expected);
|
|
161
|
+
var av = webdriver.asserts.getValue_(actual);
|
|
162
|
+
return goog.math.Coordinate.equals(ev, av);
|
|
163
|
+
},
|
|
164
|
+
function () {
|
|
165
|
+
return 'equal ' + webdriver.asserts.getValueAndType_(expected);
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
goog.exportSymbol('isTheSameLocationAs',
|
|
169
|
+
webdriver.asserts.Matcher.isTheSameLocationAs);
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Verifies that that given value matches the provided {@code Matcher}. This
|
|
174
|
+
* method has two signatures based on the number of arguments:
|
|
175
|
+
* Two arguments:
|
|
176
|
+
* assertThat(actualValue, matcher)
|
|
177
|
+
* Three arguments:
|
|
178
|
+
* assertThat(failureMessage, actualValue, matcher)
|
|
179
|
+
* @param {string} failureMessage The message to include in the resulting error
|
|
180
|
+
* if actualValue does not match matcher.
|
|
181
|
+
* @param {webdriver.Future|Object} The actual value to verify.
|
|
182
|
+
* @param {webdriver.asserts.Matcher} matcher The object to match the actual
|
|
183
|
+
* value against. If not an instanceof {@code webdriver.Matcher}, will
|
|
184
|
+
* default to the matcher returned by the {@code webdriver.equals} factory
|
|
185
|
+
* function.
|
|
186
|
+
*/
|
|
187
|
+
webdriver.asserts.assertThat = function(a, b, opt_c) {
|
|
188
|
+
var args = goog.array.slice(arguments, 0);
|
|
189
|
+
var message = args.length > 2 ? (args[0] + '\n') : '';
|
|
190
|
+
var future = args.length > 2 ? args[1] : args[0];
|
|
191
|
+
|
|
192
|
+
var matcher = args.length > 2 ? args[2] : args[1];
|
|
193
|
+
if (!(matcher instanceof webdriver.asserts.Matcher)) {
|
|
194
|
+
matcher = webdriver.asserts.Matcher.equals(matcher);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
var doAssertion = function() {
|
|
198
|
+
if (!matcher.matches(future)) {
|
|
199
|
+
throw new Error(message +
|
|
200
|
+
'Expected to ' + matcher.describe() +
|
|
201
|
+
'\n but was ' + webdriver.asserts.objToString(future));
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (future instanceof webdriver.Future) {
|
|
206
|
+
// Schedule a function with the Future's controlling driver so the value
|
|
207
|
+
// is verified after it has been set.
|
|
208
|
+
future.getDriver().callFunction(doAssertion);
|
|
209
|
+
} else {
|
|
210
|
+
doAssertion();
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
goog.exportSymbol('assertThat', webdriver.asserts.assertThat);
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
// ----------------------------------------------------------------------------
|
|
217
|
+
// Define some common xUnit paradigm assertion functions, but do not override
|
|
218
|
+
// any pre-existing function (e.g. if the jsapi is being used with the jsunit
|
|
219
|
+
// library.
|
|
220
|
+
// ----------------------------------------------------------------------------
|
|
221
|
+
|
|
222
|
+
goog.global.fail = goog.global.fail || function(opt_msg) {
|
|
223
|
+
var msg = 'Call to fail()';
|
|
224
|
+
if (opt_msg) {
|
|
225
|
+
msg += ': ' + opt_msg;
|
|
226
|
+
}
|
|
227
|
+
throw new Error(msg);
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
goog.global.assertEquals = goog.global.assertEquals || function(a, b, opt_c) {
|
|
232
|
+
var args = goog.array.slice(arguments, 0);
|
|
233
|
+
var msg = args.length > 2 ? args[0] : '';
|
|
234
|
+
var expected = args.length > 2 ? args[1] : args[0];
|
|
235
|
+
var actual = args.length > 2 ? args[2] : args[1];
|
|
236
|
+
if (expected !== actual) {
|
|
237
|
+
webdriver.asserts.assertThat(msg, actual, equals(expected));
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
goog.global.assertTrue = goog.global.assertTrue || function(a, opt_b) {
|
|
243
|
+
var args = goog.array.slice(arguments, 0);
|
|
244
|
+
if (args.length > 1) {
|
|
245
|
+
goog.global.assertEquals(args[0], true, args[1]);
|
|
246
|
+
} else {
|
|
247
|
+
goog.global.assertEquals(true, args[0]);
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
goog.global.assertFalse = goog.global.assertFalse || function(a, opt_b) {
|
|
253
|
+
var args = goog.array.slice(arguments, 0);
|
|
254
|
+
if (args.length > 1) {
|
|
255
|
+
goog.global.assertEquals(args[0], false, args[1]);
|
|
256
|
+
} else {
|
|
257
|
+
goog.global.assertEquals(false, args[0]);
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Utility function for inverting a value. If the input is a...
|
|
264
|
+
* <ul>
|
|
265
|
+
* <li>{@code webdriver.asserts.Matcher}, returns a new Matcher that inverts
|
|
266
|
+
* the result of the input</li>
|
|
267
|
+
* <li>{@code webdriver.Future}, returns a new Future whose result will be the
|
|
268
|
+
* inverse of hte input</li>
|
|
269
|
+
* <li>any other type of object, it will be converted to a boolean and
|
|
270
|
+
* inverted</li>
|
|
271
|
+
* </ul>
|
|
272
|
+
* @param {*) input The value to invert.
|
|
273
|
+
* @return {webdriver.asserts.Matcher|webdriver.Future|boolean} The inverted
|
|
274
|
+
* value according to the rules defined above.
|
|
275
|
+
*/
|
|
276
|
+
webdriver.not = function(input) {
|
|
277
|
+
if (input instanceof webdriver.Future) {
|
|
278
|
+
var invertedFuture = new webdriver.Future(input.getDriver());
|
|
279
|
+
goog.events.listen(input, goog.events.EventType.CHANGE,
|
|
280
|
+
function() {
|
|
281
|
+
invertedFuture.setValue(!!!input.getValue());
|
|
282
|
+
});
|
|
283
|
+
return invertedFuture;
|
|
284
|
+
} else if (input instanceof webdriver.asserts.Matcher) {
|
|
285
|
+
return new webdriver.asserts.Matcher(
|
|
286
|
+
function (actual) {
|
|
287
|
+
return !input.matches(actual);
|
|
288
|
+
},
|
|
289
|
+
function () {
|
|
290
|
+
return 'not ' + input.describe();
|
|
291
|
+
});
|
|
292
|
+
} else {
|
|
293
|
+
return !!!value;
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
goog.exportSymbol('not', webdriver.not);
|