selenium-client 1.1 → 1.2
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/lib/nautilus/shell.rb +32 -0
- data/lib/selenium.rb +8 -0
- data/lib/selenium/client/base.rb +26 -5
- data/lib/selenium/client/driver.rb +1 -0
- data/lib/selenium/client/idiomatic.rb +179 -0
- data/lib/selenium/client/selenese_client.rb +5 -5
- data/lib/selenium/client/selenium_helper.rb +5 -5
- data/lib/selenium/rake/remote_control_start_task.rb +43 -0
- data/lib/selenium/rake/remote_control_stop_task.rb +28 -0
- data/lib/selenium/rake/tasks.rb +6 -0
- data/lib/selenium/remote_control/remote_control.rb +30 -0
- data/lib/selenium/rspec/reporting/file_path_strategy.rb +70 -0
- data/lib/selenium/rspec/reporting/html_report.rb +123 -0
- data/lib/selenium/rspec/reporting/selenium_test_report_formatter.rb +88 -0
- data/lib/selenium/rspec/reporting/system_capture.rb +72 -0
- data/lib/selenium/rspec/rspec_extensions.rb +43 -0
- data/lib/selenium/rspec/spec_helper.rb +22 -0
- data/lib/tcp_socket_extension.rb +23 -0
- metadata +16 -6
- data/lib/selenium/client/generated_driver.rb +0 -1621
- data/lib/selenium/rspec/screenshot_formatter.rb +0 -187
- data/lib/selenium/screenshot_saver.rb +0 -25
@@ -0,0 +1,32 @@
|
|
1
|
+
module Nautilus
|
2
|
+
|
3
|
+
class Shell
|
4
|
+
|
5
|
+
def run(command, options = {})
|
6
|
+
sh build_command(command, options)
|
7
|
+
end
|
8
|
+
|
9
|
+
def build_command(command, options = {})
|
10
|
+
actual_command = command.kind_of?(Array) ? command.join(" ") : command
|
11
|
+
if options[:background]
|
12
|
+
if windows?
|
13
|
+
actual_command = "start /wait /b " + command
|
14
|
+
elsif options[:background]
|
15
|
+
actual_command << " &"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
actual_command
|
19
|
+
end
|
20
|
+
|
21
|
+
def windows?
|
22
|
+
PLATFORM['win32']
|
23
|
+
end
|
24
|
+
|
25
|
+
def sh(command)
|
26
|
+
successful = system(command)
|
27
|
+
raise "Error while running >>#{command}<<" unless successful
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
data/lib/selenium.rb
CHANGED
@@ -21,13 +21,21 @@
|
|
21
21
|
require 'net/http'
|
22
22
|
require 'uri'
|
23
23
|
require 'cgi'
|
24
|
+
require "digest/md5"
|
25
|
+
require "fileutils"
|
26
|
+
require File.expand_path(File.dirname(__FILE__) + '/tcp_socket_extension')
|
27
|
+
require File.expand_path(File.dirname(__FILE__) + '/nautilus/shell')
|
24
28
|
require File.expand_path(File.dirname(__FILE__) + '/selenium/command_error')
|
25
29
|
require File.expand_path(File.dirname(__FILE__) + '/selenium/protocol_error')
|
26
30
|
require File.expand_path(File.dirname(__FILE__) + '/selenium/client/selenese_client')
|
27
31
|
require File.expand_path(File.dirname(__FILE__) + '/selenium/client/generated_driver')
|
32
|
+
require File.expand_path(File.dirname(__FILE__) + '/selenium/client/idiomatic')
|
28
33
|
require File.expand_path(File.dirname(__FILE__) + '/selenium/client/base')
|
29
34
|
require File.expand_path(File.dirname(__FILE__) + '/selenium/client/driver')
|
30
35
|
require File.expand_path(File.dirname(__FILE__) + '/selenium/client/selenium_helper')
|
36
|
+
require File.expand_path(File.dirname(__FILE__) + '/selenium/remote_control/remote_control')
|
37
|
+
require File.expand_path(File.dirname(__FILE__) + '/selenium/rake/remote_control_start_task')
|
38
|
+
require File.expand_path(File.dirname(__FILE__) + '/selenium/rake/remote_control_stop_task')
|
31
39
|
|
32
40
|
# Backward compatibility
|
33
41
|
|
data/lib/selenium/client/base.rb
CHANGED
@@ -23,13 +23,14 @@ module Selenium
|
|
23
23
|
include Selenium::Client::SeleneseClient
|
24
24
|
include Selenium::Client::GeneratedDriver
|
25
25
|
|
26
|
-
def initialize(server_host, server_port,
|
26
|
+
def initialize(server_host, server_port, browser_string, browser_url, timeout_in_seconds=300)
|
27
27
|
@server_host = server_host
|
28
28
|
@server_port = server_port
|
29
|
-
@
|
30
|
-
@
|
31
|
-
@timeout =
|
29
|
+
@browser_string = browser_string
|
30
|
+
@browser_url = browser_url
|
31
|
+
@timeout = timeout_in_seconds
|
32
32
|
@extension_js = ""
|
33
|
+
@session_id = nil
|
33
34
|
end
|
34
35
|
|
35
36
|
def set_extension_js(extension_js)
|
@@ -37,7 +38,7 @@ module Selenium
|
|
37
38
|
end
|
38
39
|
|
39
40
|
def start()
|
40
|
-
result = get_string("getNewBrowserSession", [@
|
41
|
+
result = get_string("getNewBrowserSession", [@browser_string, @browser_url, @extension_js])
|
41
42
|
@session_id = result
|
42
43
|
end
|
43
44
|
|
@@ -46,6 +47,26 @@ module Selenium
|
|
46
47
|
@session_id = nil
|
47
48
|
end
|
48
49
|
|
50
|
+
def start_new_browser_session
|
51
|
+
start
|
52
|
+
end
|
53
|
+
|
54
|
+
def close_current_browser_session
|
55
|
+
stop
|
56
|
+
end
|
57
|
+
|
58
|
+
def session_started?
|
59
|
+
not @session_id.nil?
|
60
|
+
end
|
61
|
+
|
62
|
+
def default_timeout_in_seconds
|
63
|
+
@timeout
|
64
|
+
end
|
65
|
+
|
66
|
+
def chrome_backend?
|
67
|
+
["*chrome", "*firefox", "*firefox2", "*firefox3"].include?(@browser_string)
|
68
|
+
end
|
69
|
+
|
49
70
|
end
|
50
71
|
|
51
72
|
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
#
|
2
|
+
# Provide a more idiomatic API than the generated Ruby driver.
|
3
|
+
#
|
4
|
+
# Work on progress...
|
5
|
+
#
|
6
|
+
module Selenium
|
7
|
+
module Client
|
8
|
+
|
9
|
+
module Idiomatic
|
10
|
+
|
11
|
+
# Return the text content of an HTML element (rendered text shown to
|
12
|
+
# the user). Works for any HTML element that contains text.
|
13
|
+
#
|
14
|
+
#
|
15
|
+
# This command uses either the textContent (Mozilla-like browsers)
|
16
|
+
# or the innerText (IE-like browsers) of the element, which is the
|
17
|
+
# rendered text shown to the user.
|
18
|
+
#
|
19
|
+
# 'locator' is an Selenium element locator
|
20
|
+
def text_content(locator)
|
21
|
+
get_string "getText", [locator,]
|
22
|
+
end
|
23
|
+
|
24
|
+
# Return the title of the current HTML page.
|
25
|
+
def title
|
26
|
+
get_string "getTitle"
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns the absolute URL of the current page.
|
30
|
+
def location
|
31
|
+
get_string "getLocation"
|
32
|
+
end
|
33
|
+
|
34
|
+
# Waits for a new page to load.
|
35
|
+
#
|
36
|
+
# Selenium constantly keeps track of new pages loading, and sets a
|
37
|
+
# "newPageLoaded" flag when it first notices a page load. Running
|
38
|
+
# any other Selenium command after turns the flag to false. Hence,
|
39
|
+
# if you want to wait for a page to load, you must wait immediately
|
40
|
+
# after a Selenium command that caused a page-load.
|
41
|
+
#
|
42
|
+
# 'timeout_in_seconds' is a timeout in seconds, after which this
|
43
|
+
# command will return with an error
|
44
|
+
def wait_for_page(timeout_in_seconds=nil)
|
45
|
+
actual_timeout = timeout_in_seconds || default_timeout_in_seconds
|
46
|
+
do_command "waitForPageToLoad", [actual_timeout * 1000,]
|
47
|
+
end
|
48
|
+
|
49
|
+
# Gets the entire text of the page.
|
50
|
+
def body_text
|
51
|
+
get_string "getBodyText"
|
52
|
+
end
|
53
|
+
|
54
|
+
# Clicks on a link, button, checkbox or radio button. If the click action
|
55
|
+
# causes a new page to load (like a link usually does), call
|
56
|
+
# waitForPageToLoad.
|
57
|
+
#
|
58
|
+
# 'locator' is an element locator
|
59
|
+
def click(locator, options={})
|
60
|
+
do_command("click", [locator,])
|
61
|
+
if options[:wait_for] == :page
|
62
|
+
wait_for_page options[:timeout_in_seconds]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Verifies that the specified text pattern appears somewhere on the rendered page shown to the user.
|
67
|
+
#
|
68
|
+
# 'pattern' is a pattern to match with the text of the page
|
69
|
+
def text_present?(pattern)
|
70
|
+
get_boolean "isTextPresent", [pattern,]
|
71
|
+
end
|
72
|
+
|
73
|
+
# Verifies that the specified element is somewhere on the page.
|
74
|
+
#
|
75
|
+
# 'locator' is an element locator
|
76
|
+
def element_present?(locator)
|
77
|
+
get_boolean "isElementPresent", [locator,]
|
78
|
+
end
|
79
|
+
|
80
|
+
# Gets the (whitespace-trimmed) value of an input field
|
81
|
+
# (or anything else with a value parameter).
|
82
|
+
# For checkbox/radio elements, the value will be "on" or "off"
|
83
|
+
# depending on whether the element is checked or not.
|
84
|
+
#
|
85
|
+
# 'locator' is an element locator
|
86
|
+
def value(locator)
|
87
|
+
get_string "getValue", [locator,]
|
88
|
+
end
|
89
|
+
|
90
|
+
# Whether an alert occurred
|
91
|
+
def alert?
|
92
|
+
get_boolean "isAlertPresent"
|
93
|
+
end
|
94
|
+
|
95
|
+
# Retrieves the message of a JavaScript alert generated during the previous action,
|
96
|
+
# or fail if there were no alerts.
|
97
|
+
#
|
98
|
+
# Getting an alert has the same effect as manually clicking OK. If an
|
99
|
+
# alert is generated but you do not consume it with getAlert, the next Selenium action
|
100
|
+
# will fail.
|
101
|
+
# Under Selenium, JavaScript alerts will NOT pop up a visible alert
|
102
|
+
# dialog.
|
103
|
+
# Selenium does NOT support JavaScript alerts that are generated in a
|
104
|
+
# page's onload() event handler. In this case a visible dialog WILL be
|
105
|
+
# generated and Selenium will hang until someone manually clicks OK.
|
106
|
+
#
|
107
|
+
def alert
|
108
|
+
get_string "getAlert"
|
109
|
+
end
|
110
|
+
|
111
|
+
# Whether a confirmation has been auto-acknoledged (i.e. confirm() been called)
|
112
|
+
def confirmation?
|
113
|
+
get_boolean "isConfirmationPresent"
|
114
|
+
end
|
115
|
+
|
116
|
+
# Retrieves the message of a JavaScript confirmation dialog generated during
|
117
|
+
# the previous action.
|
118
|
+
#
|
119
|
+
# By default, the confirm function will return true, having the same effect
|
120
|
+
# as manually clicking OK. This can be changed by prior execution of the
|
121
|
+
# chooseCancelOnNextConfirmation command.
|
122
|
+
#
|
123
|
+
# If an confirmation is generated but you do not consume it with getConfirmation,
|
124
|
+
# the next Selenium action will fail.
|
125
|
+
#
|
126
|
+
# NOTE: under Selenium, JavaScript confirmations will NOT pop up a visible
|
127
|
+
# dialog.
|
128
|
+
#
|
129
|
+
# NOTE: Selenium does NOT support JavaScript confirmations that are
|
130
|
+
# generated in a page's onload() event handler. In this case a visible
|
131
|
+
# dialog WILL be generated and Selenium will hang until you manually click
|
132
|
+
# OK.
|
133
|
+
def confirmation
|
134
|
+
get_string "getConfirmation"
|
135
|
+
end
|
136
|
+
|
137
|
+
# Whether a prompt occurred
|
138
|
+
def prompt?
|
139
|
+
get_boolean "isPromptPresent"
|
140
|
+
end
|
141
|
+
|
142
|
+
# Retrieves the message of a JavaScript question prompt dialog generated during
|
143
|
+
# the previous action.
|
144
|
+
#
|
145
|
+
# Successful handling of the prompt requires prior execution of the
|
146
|
+
# answerOnNextPrompt command. If a prompt is generated but you
|
147
|
+
# do not get/verify it, the next Selenium action will fail.
|
148
|
+
#
|
149
|
+
# NOTE: under Selenium, JavaScript prompts will NOT pop up a visible
|
150
|
+
# dialog.
|
151
|
+
#
|
152
|
+
# NOTE: Selenium does NOT support JavaScript prompts that are generated in a
|
153
|
+
# page's onload() event handler. In this case a visible dialog WILL be
|
154
|
+
# generated and Selenium will hang until someone manually clicks OK.
|
155
|
+
def prompt
|
156
|
+
get_string "getPrompt"
|
157
|
+
end
|
158
|
+
|
159
|
+
# Returns the result of evaluating the specified JavaScript snippet whithin the browser.
|
160
|
+
# The snippet may have multiple lines, but only the result of the last line will be returned.
|
161
|
+
#
|
162
|
+
# Note that, by default, the snippet will run in the context of the "selenium"
|
163
|
+
# object itself, so <tt>this</tt> will refer to the Selenium object. Use <tt>window</tt> to
|
164
|
+
# refer to the window of your application, e.g. <tt>window.document.getElementById('foo')</tt>
|
165
|
+
# If you need to use
|
166
|
+
# a locator to refer to a single element in your application page, you can
|
167
|
+
# use <tt>this.browserbot.findElement("id=foo")</tt> where "id=foo" is your locator.
|
168
|
+
#
|
169
|
+
# 'script' is the JavaScript snippet to run
|
170
|
+
def js_eval(script)
|
171
|
+
get_string "getEval", [script,]
|
172
|
+
end
|
173
|
+
|
174
|
+
|
175
|
+
# set speed
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|
179
|
+
end
|
@@ -7,14 +7,14 @@ module Selenium
|
|
7
7
|
attr_reader :session_id
|
8
8
|
|
9
9
|
def do_command(verb, args)
|
10
|
-
timeout(
|
10
|
+
timeout(default_timeout_in_seconds) do
|
11
11
|
status, response = http_post(http_request_for(verb, args))
|
12
12
|
raise SeleniumCommandError, response unless status == "OK"
|
13
13
|
response
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
def get_string(verb, args)
|
17
|
+
def get_string(verb, args=[])
|
18
18
|
do_command(verb, args)
|
19
19
|
end
|
20
20
|
|
@@ -53,7 +53,7 @@ module Selenium
|
|
53
53
|
return get_string_array(verb, args)
|
54
54
|
end
|
55
55
|
|
56
|
-
def get_boolean(verb, args)
|
56
|
+
def get_boolean(verb, args=[])
|
57
57
|
parse_boolean_value get_string(verb, args)
|
58
58
|
end
|
59
59
|
|
@@ -82,10 +82,10 @@ module Selenium
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def http_post(data)
|
85
|
-
#
|
85
|
+
# puts "Requesting ---> #{data.inspect}"
|
86
86
|
http = Net::HTTP.new(@server_host, @server_port)
|
87
87
|
response = http.post('/selenium-server/driver/', data, HTTP_HEADERS)
|
88
|
-
#
|
88
|
+
# puts "RESULT: #{response.inspect}\n"
|
89
89
|
[ response.body[0..1], response.body[3..-1] ]
|
90
90
|
end
|
91
91
|
|
@@ -24,11 +24,11 @@ module Selenium
|
|
24
24
|
|
25
25
|
# Passes all calls to missing methods to @selenium
|
26
26
|
def method_missing(method_name, *args)
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
27
|
+
if args.empty?
|
28
|
+
@selenium.send(method_name)
|
29
|
+
else
|
30
|
+
@selenium.send(method_name, *args)
|
31
|
+
end
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Selenium
|
2
|
+
module Rake
|
3
|
+
|
4
|
+
class RemoteControlStartTask
|
5
|
+
attr_accessor :port, :timeout_in_seconds, :background,
|
6
|
+
:wait_until_up_and_running, :additional_args
|
7
|
+
attr_reader :jar_file
|
8
|
+
|
9
|
+
def initialize(name = :'selenium:rc:start')
|
10
|
+
@name = name
|
11
|
+
@port = 4444
|
12
|
+
@timeout_in_seconds = 5
|
13
|
+
@jar_file = "vendor/selenium/selenium-server-1.0-standalone.jar"
|
14
|
+
@additional_args = []
|
15
|
+
@background = false
|
16
|
+
@wait_until_up_and_running = false
|
17
|
+
yield self if block_given?
|
18
|
+
define
|
19
|
+
end
|
20
|
+
|
21
|
+
def jar_file=(new_jar_file)
|
22
|
+
@jar_file = File.expand_path(new_jar_file)
|
23
|
+
end
|
24
|
+
|
25
|
+
def define
|
26
|
+
desc "Launch Selenium Remote Control"
|
27
|
+
task @name do
|
28
|
+
puts "Starting Selenium Remote Control at 0.0.0.0:#{@port}..."
|
29
|
+
remote_control = Selenium::RemoteControl::RemoteControl.new("0.0.0.0", @port, @timeout_in_seconds)
|
30
|
+
remote_control.jar_file = @jar_file
|
31
|
+
remote_control.additional_args = @additional_args
|
32
|
+
remote_control.start :background => @background
|
33
|
+
if @background && @wait_until_up_and_running
|
34
|
+
puts "Waiting for Remote Control to be up and running..."
|
35
|
+
TCPSocket.wait_for_service :host => @host, :port => @port
|
36
|
+
end
|
37
|
+
puts "Selenium Remote Control at 0.0.0.0:#{@port} ready"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Selenium
|
2
|
+
module Rake
|
3
|
+
|
4
|
+
class RemoteControlStopTask
|
5
|
+
attr_accessor :host, :port, :timeout_in_seconds
|
6
|
+
|
7
|
+
def initialize(name = :'selenium:rc:stop')
|
8
|
+
@host = "localhost"
|
9
|
+
@name = name
|
10
|
+
@port = 4444
|
11
|
+
@timeout_in_seconds = 5
|
12
|
+
yield self if block_given?
|
13
|
+
define
|
14
|
+
end
|
15
|
+
|
16
|
+
def define
|
17
|
+
desc "Stop Selenium Remote Control running"
|
18
|
+
task @name do
|
19
|
+
puts "Stopping Selenium Remote Control running at #{@host}:#{@port}..."
|
20
|
+
remote_control = Selenium::RemoteControl::RemoteControl.new(@host, @port, @timeout_in_seconds)
|
21
|
+
remote_control.stop
|
22
|
+
puts "Stopped Selenium Remote Control running at #{@host}:#{@port}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
require "net/http"
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../nautilus/shell')
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../tcp_socket_extension')
|
4
|
+
require File.expand_path(File.dirname(__FILE__) + '/../remote_control/remote_control')
|
5
|
+
require File.expand_path(File.dirname(__FILE__) + '/remote_control_start_task')
|
6
|
+
require File.expand_path(File.dirname(__FILE__) + '/remote_control_stop_task')
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Selenium
|
2
|
+
module RemoteControl
|
3
|
+
|
4
|
+
class RemoteControl
|
5
|
+
attr_reader :host, :port, :timeout_in_seconds
|
6
|
+
attr_accessor :additional_args, :jar_file
|
7
|
+
|
8
|
+
def initialize(host, port, timeout_in_seconds = 2 * 60)
|
9
|
+
@host, @port, @timeout_in_seconds = host, port, timeout_in_seconds
|
10
|
+
@additional_args = []
|
11
|
+
@shell = Nautilus::Shell.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def start(options = {})
|
15
|
+
command = "java -jar \"#{jar_file}\""
|
16
|
+
command << " -port #{@port}"
|
17
|
+
command << " -timeout #{@timeout_in_seconds}"
|
18
|
+
command << " #{additional_args.join(' ')}" unless additional_args.empty?
|
19
|
+
|
20
|
+
@shell.run command, {:background => options[:background]}
|
21
|
+
end
|
22
|
+
|
23
|
+
def stop
|
24
|
+
Net::HTTP.get(@host, '/selenium-server/driver/?cmd=shutDown', @port)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|