selenium-client 1.1 → 1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|