selenium-client 1.2.14 → 1.2.15
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +42 -15
- data/examples/rspec/google_spec.rb +3 -3
- data/examples/script/google.rb +1 -1
- data/examples/testunit/google_test.rb +1 -1
- data/lib/selenium/client.rb +2 -1
- data/lib/selenium/client/base.rb +10 -2
- data/lib/selenium/client/generated_driver.rb +4 -4
- data/lib/selenium/client/idiomatic.rb +32 -0
- data/lib/selenium/client/protocol.rb +1 -1
- data/lib/selenium/client/selenium_helper.rb +14 -16
- data/lib/selenium/rake/remote_control_start_task.rb +26 -2
- data/lib/selenium/rake/remote_control_stop_task.rb +8 -0
- data/lib/selenium/remote_control/remote_control.rb +2 -1
- data/lib/selenium/rspec/reporting/file_path_strategy.rb +19 -13
- data/lib/selenium/rspec/reporting/html_report.rb +2 -2
- data/lib/selenium/rspec/reporting/selenium_test_report_formatter.rb +12 -22
- data/lib/selenium/rspec/reporting/system_capture.rb +2 -2
- data/lib/selenium/rspec/rspec_extensions.rb +62 -12
- data/lib/selenium/rspec/spec_helper.rb +3 -1
- metadata +6 -4
data/README.markdown
CHANGED
@@ -10,6 +10,7 @@ Mission
|
|
10
10
|
With screenshots, HTML snapshopts and log captures,
|
11
11
|
investigating test failures becomes a breeze.
|
12
12
|
|
13
|
+
|
13
14
|
Install It
|
14
15
|
==========
|
15
16
|
|
@@ -80,7 +81,7 @@ Plain API
|
|
80
81
|
# Sample Ruby script using the Selenium client API
|
81
82
|
#
|
82
83
|
require "rubygems"
|
83
|
-
gem "selenium-client", ">=1.2.
|
84
|
+
gem "selenium-client", ">=1.2.15"
|
84
85
|
require "selenium/client"
|
85
86
|
|
86
87
|
begin
|
@@ -113,7 +114,7 @@ Writing Tests
|
|
113
114
|
#
|
114
115
|
require "test/unit"
|
115
116
|
require "rubygems"
|
116
|
-
gem "selenium-client", ">=1.2.
|
117
|
+
gem "selenium-client", ">=1.2.15"
|
117
118
|
require "selenium/client"
|
118
119
|
|
119
120
|
class ExampleTest < Test::Unit::TestCase
|
@@ -150,8 +151,8 @@ Writing Tests
|
|
150
151
|
If BDD is more your style, here is how you can achieve the same thing using RSpec:
|
151
152
|
|
152
153
|
require 'rubygems'
|
153
|
-
gem "rspec", "=1.
|
154
|
-
gem "selenium-client", ">=1.2.
|
154
|
+
gem "rspec", "=1.2.6"
|
155
|
+
gem "selenium-client", ">=1.2.15"
|
155
156
|
require "selenium/client"
|
156
157
|
require "selenium/rspec/spec_helper"
|
157
158
|
|
@@ -218,8 +219,12 @@ Start/Stop a Selenium Remote Control Server
|
|
218
219
|
rc.port = 4444
|
219
220
|
rc.timeout_in_seconds = 3 * 60
|
220
221
|
end
|
221
|
-
|
222
|
-
|
222
|
+
|
223
|
+
If you do not explicitly specify the path to selenium remote control jar
|
224
|
+
it will be "auto-discovered" in `vendor` directory using the following
|
225
|
+
path : `vendor/selenium-remote-control/selenium-server*-standalone.jar`
|
226
|
+
|
227
|
+
Check out [RemoteControlStartTask](http://selenium-client.rubyforge.org/classes/Selenium/Rake/RemoteControlStartTask.html) and [RemoteControlStopTask](http://selenium-client.rubyforge.org/classes/Selenium/Rake/RemoteControlStopTask.html) for more
|
223
228
|
details.
|
224
229
|
|
225
230
|
State-of-the-Art RSpec Reporting
|
@@ -254,20 +259,34 @@ Grid](http://selenium-grid.openqa.org))
|
|
254
259
|
require "selenium/client"
|
255
260
|
require "selenium/rspec/spec_helper"
|
256
261
|
|
262
|
+
Other Resources
|
263
|
+
===============
|
264
|
+
|
265
|
+
* Report bugs at http://github.com/ph7/selenium-client/issues
|
266
|
+
* Browse API at http://selenium-client.rubyforge.org
|
267
|
+
|
257
268
|
|
258
269
|
Contribute and Join the Fun!
|
259
270
|
============================
|
260
271
|
|
261
|
-
We welcome new features, add-ons, bug fixes, example, documentation,
|
262
|
-
envision!
|
272
|
+
We welcome new features, add-ons, bug fixes, example, documentation,
|
273
|
+
etc. Make the gem work the way you envision!
|
274
|
+
|
275
|
+
* Report bugs at http://github.com/ph7/selenium-client/issues
|
263
276
|
|
264
|
-
* I recommend cloning the selenium-client
|
277
|
+
* I recommend cloning the selenium-client
|
278
|
+
[reference repository](http://github.com/ph7/selenium-client/tree/master)
|
265
279
|
|
266
|
-
* You can also check out the [RubyForge page](http://rubyforge.org/projects/selenium-client)
|
280
|
+
* You can also check out the [RubyForge page](http://rubyforge.org/projects/selenium-client)
|
281
|
+
and the [RDoc](http://selenium-client.rubyforge.org)
|
267
282
|
|
268
283
|
* We also have a [continuous integration server](http://xserve.openqa.org:8080/view/Ruby%20Client)
|
269
284
|
|
270
285
|
* Stories live in [Pivotal Tracker](https://www.pivotaltracker.com/projects/6280)
|
286
|
+
* To build, run `rake clean default package`. You can then install the
|
287
|
+
generated gem with `sudo gem install pkg/*.gem`
|
288
|
+
* You can also run all integration tests with `rake ci:integration`
|
289
|
+
|
271
290
|
|
272
291
|
Core Team
|
273
292
|
=========
|
@@ -279,12 +298,20 @@ Contributors
|
|
279
298
|
============
|
280
299
|
|
281
300
|
* Aaron Tinio (`aptinio`):
|
282
|
-
-
|
283
|
-
-
|
301
|
+
- More robust Selenium RC shutdown
|
302
|
+
- Support for locator including single quotes in `wait_for_...` methods
|
303
|
+
- Do not capture system state on execution errors for pending examples
|
304
|
+
(ExamplePendingError, NotYetImplementedError)
|
284
305
|
|
285
306
|
* Rick Lee-Morlang (`rleemorlang`):
|
286
|
-
-
|
307
|
+
- Fix for incremental calls to `wait_for_text`
|
287
308
|
- Regex support in `wait_for_text`
|
288
|
-
|
289
309
|
|
290
|
-
|
310
|
+
* [Paul Boone](http://www.mindbucket.com) (`paulboone`)
|
311
|
+
- Fixed method_missing in selenium_helper to only delegate to methods
|
312
|
+
that @selenium responds to
|
313
|
+
|
314
|
+
* [Adam Greene](http://blog.sweetspot.dm) (`skippy`)
|
315
|
+
- Added the ability to redirect output to a log file, when
|
316
|
+
launching Selenium Remote Control with the Rake task
|
317
|
+
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
gem "rspec", "=1.
|
3
|
-
gem "selenium-client", ">=1.2.
|
2
|
+
gem "rspec", "=1.2.6"
|
3
|
+
gem "selenium-client", ">=1.2.15"
|
4
4
|
require "selenium/client"
|
5
5
|
require "selenium/rspec/spec_helper"
|
6
6
|
|
@@ -38,4 +38,4 @@ describe "Google Search" do
|
|
38
38
|
page.element?("link=Cached").should be_true
|
39
39
|
end
|
40
40
|
|
41
|
-
end
|
41
|
+
end
|
data/examples/script/google.rb
CHANGED
data/lib/selenium/client.rb
CHANGED
@@ -6,7 +6,8 @@ require 'net/http'
|
|
6
6
|
require 'uri'
|
7
7
|
require 'cgi'
|
8
8
|
require "digest/md5"
|
9
|
-
require
|
9
|
+
require 'fileutils'
|
10
|
+
require 'tmpdir'
|
10
11
|
require File.expand_path(File.dirname(__FILE__) + '/../tcp_socket_extension')
|
11
12
|
require File.expand_path(File.dirname(__FILE__) + '/../nautilus/shell')
|
12
13
|
require File.expand_path(File.dirname(__FILE__) + '/command_error')
|
data/lib/selenium/client/base.rb
CHANGED
@@ -60,8 +60,16 @@ module Selenium
|
|
60
60
|
not @session_id.nil?
|
61
61
|
end
|
62
62
|
|
63
|
-
|
64
|
-
|
63
|
+
# Starts a new browser session (launching a new browser matching
|
64
|
+
# configuration provided at driver creation time).
|
65
|
+
#
|
66
|
+
# Browser session specific option can also be provided. e.g.
|
67
|
+
#
|
68
|
+
# driver.start_new_browser_session(:captureNetworkTraffic => true)
|
69
|
+
#
|
70
|
+
def start_new_browser_session(options={})
|
71
|
+
options_as_string = options.collect {|key,value| "#{key.to_s}=#{value.to_s}"}.sort.join(";")
|
72
|
+
result = string_command "getNewBrowserSession", [@browser_string, @browser_url, @extension_js, options_as_string]
|
65
73
|
@session_id = result
|
66
74
|
# Consistent timeout on the remote control and driver side.
|
67
75
|
# Intuitive and this is what you want 90% of the time
|
@@ -1140,7 +1140,7 @@ module Selenium
|
|
1140
1140
|
end
|
1141
1141
|
|
1142
1142
|
|
1143
|
-
# Returns
|
1143
|
+
# Returns an array of JavaScript property values from all known windows having one.
|
1144
1144
|
#
|
1145
1145
|
# 'attributeName' is name of an attribute on the windows
|
1146
1146
|
def get_attribute_from_all_windows(attributeName)
|
@@ -1210,21 +1210,21 @@ module Selenium
|
|
1210
1210
|
end
|
1211
1211
|
|
1212
1212
|
|
1213
|
-
# Returns the IDs of all windows that the browser knows about.
|
1213
|
+
# Returns the IDs of all windows that the browser knows about in an array.
|
1214
1214
|
#
|
1215
1215
|
def get_all_window_ids()
|
1216
1216
|
return string_array_command("getAllWindowIds", [])
|
1217
1217
|
end
|
1218
1218
|
|
1219
1219
|
|
1220
|
-
# Returns the names of all windows that the browser knows about.
|
1220
|
+
# Returns the names of all windows that the browser knows about in an array.
|
1221
1221
|
#
|
1222
1222
|
def get_all_window_names()
|
1223
1223
|
return string_array_command("getAllWindowNames", [])
|
1224
1224
|
end
|
1225
1225
|
|
1226
1226
|
|
1227
|
-
# Returns the titles of all windows that the browser knows about.
|
1227
|
+
# Returns the titles of all windows that the browser knows about in an array.
|
1228
1228
|
#
|
1229
1229
|
def get_all_window_titles()
|
1230
1230
|
return string_array_command("getAllWindowTitles", [])
|
@@ -410,6 +410,38 @@ module Selenium
|
|
410
410
|
string_array_command "getAllWindowTitles"
|
411
411
|
end
|
412
412
|
|
413
|
+
# Returns a string representation of the network traffic seen by the
|
414
|
+
# browser, including headers, AJAX requests, status codes, and timings.
|
415
|
+
# When this function is called, the traffic log is cleared, so the
|
416
|
+
# returned content is only the traffic seen since the last call.
|
417
|
+
#
|
418
|
+
# The network traffic is returned in the format it was requested. Valid
|
419
|
+
# values are: :json, :xml, or :plain.
|
420
|
+
#
|
421
|
+
# Warning: For browser_network_traffic to work you need to start your
|
422
|
+
# browser session with the option "captureNetworkTraffic=true", which
|
423
|
+
# will force ALL traffic to go to the Remote Control proxy even for
|
424
|
+
# more efficient browser modes like `*firefox` and `*safari`.
|
425
|
+
def browser_network_traffic(format = :plain)
|
426
|
+
raise "format must be :plain, :json, or :xml" \
|
427
|
+
unless [:plain, :json, :xml].include?(format)
|
428
|
+
|
429
|
+
remote_control_command "captureNetworkTraffic", [format.to_s]
|
430
|
+
end
|
431
|
+
|
432
|
+
# Allows choice of a specific XPath libraries for Xpath evualuation
|
433
|
+
# in the browser (e.g. to resolve XPath locators).
|
434
|
+
#
|
435
|
+
# `library_name' can be:
|
436
|
+
# * :ajaxslt : Google's library
|
437
|
+
# * :javascript-xpath : Cybozu Labs' faster library
|
438
|
+
# * :default : Selenium default library.
|
439
|
+
def browser_xpath_library=(library_name)
|
440
|
+
raise "library name must be :ajaxslt, :javascript-xpath, or :default" \
|
441
|
+
unless [:ajaxslt, :'javascript-xpath', :default].include?(library_name)
|
442
|
+
remote_control_command "useXpathLibrary", [library_name.to_s]
|
443
|
+
end
|
444
|
+
|
413
445
|
end
|
414
446
|
|
415
447
|
end
|
@@ -86,7 +86,7 @@ module Selenium
|
|
86
86
|
http.open_timeout = default_timeout_in_seconds
|
87
87
|
http.read_timeout = default_timeout_in_seconds
|
88
88
|
response = http.post('/selenium-server/driver/', data, HTTP_HEADERS)
|
89
|
-
# puts "RESULT: #{response.inspect}\n"
|
89
|
+
# puts "RESULT: #{response.body.inspect}\n"
|
90
90
|
[ response.body[0..1], response.body[3..-1] ]
|
91
91
|
end
|
92
92
|
|
@@ -7,29 +7,27 @@ module Selenium
|
|
7
7
|
|
8
8
|
module SeleniumHelper
|
9
9
|
|
10
|
-
# Overrides
|
11
|
-
def open(
|
12
|
-
@selenium.open
|
10
|
+
# Overrides default open method to actually delegates to @selenium
|
11
|
+
def open(url)
|
12
|
+
@selenium.open url
|
13
13
|
end
|
14
14
|
|
15
|
-
# Overrides
|
16
|
-
def type(
|
17
|
-
@selenium.type
|
15
|
+
# Overrides default type method to actually delegates to @selenium
|
16
|
+
def type(locator, value)
|
17
|
+
@selenium.type locator, value
|
18
18
|
end
|
19
19
|
|
20
|
-
# Overrides
|
21
|
-
def select(
|
22
|
-
@selenium.select
|
20
|
+
# Overrides default select method to actually delegates to @selenium
|
21
|
+
def select(input_locator, option_locator)
|
22
|
+
@selenium.select input_locator, option_locator
|
23
23
|
end
|
24
24
|
|
25
|
-
#
|
25
|
+
# Delegates to @selenium on method missing
|
26
26
|
def method_missing(method_name, *args)
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
end
|
32
|
-
end
|
27
|
+
return super unless @selenium.respond_to?(method_name)
|
28
|
+
|
29
|
+
@selenium.send(method_name, *args)
|
30
|
+
end
|
33
31
|
end
|
34
32
|
|
35
33
|
end
|
@@ -1,16 +1,39 @@
|
|
1
1
|
module Selenium
|
2
2
|
module Rake
|
3
3
|
|
4
|
+
# Rake tasks to start a Remote Control server.
|
5
|
+
#
|
6
|
+
# require 'selenium/rake/tasks'
|
7
|
+
#
|
8
|
+
# Selenium::Rake::RemoteControlStartTask.new do |rc|
|
9
|
+
# rc.port = 4444
|
10
|
+
# rc.timeout_in_seconds = 3 * 60
|
11
|
+
# rc.background = true
|
12
|
+
# rc.wait_until_up_and_running = true
|
13
|
+
# rc.jar_file = "/path/to/where/selenium-rc-standalone-jar-is-installed"
|
14
|
+
# rc.additional_args << "-singleWindow"
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# If you do not explicitly specify the path to selenium remote control jar
|
18
|
+
# it will be "auto-discovered" in `vendor` directory using the following
|
19
|
+
# path : `vendor/selenium-remote-control/selenium-server*-standalone.jar`
|
20
|
+
#
|
21
|
+
# To leverage all selenium-client capabilities I recommend downloading
|
22
|
+
# a recent nightly build of a standalone packaging of Selenium Remote
|
23
|
+
# Control. You will find the mightly build at
|
24
|
+
# http://archiva.openqa.org/repository/snapshots/org/openqa/selenium/selenium-remote-control/1.0-SNAPSHOT/
|
4
25
|
class RemoteControlStartTask
|
5
26
|
attr_accessor :port, :timeout_in_seconds, :background,
|
6
|
-
:wait_until_up_and_running, :additional_args
|
27
|
+
:wait_until_up_and_running, :additional_args,
|
28
|
+
:log_to
|
7
29
|
attr_reader :jar_file
|
8
30
|
|
9
31
|
def initialize(name = :'selenium:rc:start')
|
10
32
|
@name = name
|
11
33
|
@port = 4444
|
12
34
|
@timeout_in_seconds = 5
|
13
|
-
|
35
|
+
project_specific_jar = Dir["vendor/selenium-remote-control/selenium-server*-standalone.jar"].first
|
36
|
+
@jar_file = project_specific_jar
|
14
37
|
@additional_args = []
|
15
38
|
@background = false
|
16
39
|
@wait_until_up_and_running = false
|
@@ -29,6 +52,7 @@ module Selenium
|
|
29
52
|
remote_control = Selenium::RemoteControl::RemoteControl.new("0.0.0.0", @port, @timeout_in_seconds)
|
30
53
|
remote_control.jar_file = @jar_file
|
31
54
|
remote_control.additional_args = @additional_args
|
55
|
+
remote_control.log_to = @log_to
|
32
56
|
remote_control.start :background => @background
|
33
57
|
if @background && @wait_until_up_and_running
|
34
58
|
puts "Waiting for Remote Control to be up and running..."
|
@@ -1,6 +1,14 @@
|
|
1
1
|
module Selenium
|
2
2
|
module Rake
|
3
3
|
|
4
|
+
# Rake task to stop a Selenium Remote Control Server
|
5
|
+
#
|
6
|
+
# Selenium::Rake::RemoteControlStopTask.new do |rc|
|
7
|
+
# rc.host = "localhost"
|
8
|
+
# rc.port = 4444
|
9
|
+
# rc.timeout_in_seconds = 3 * 60
|
10
|
+
# end
|
11
|
+
#
|
4
12
|
class RemoteControlStopTask
|
5
13
|
attr_accessor :host, :port, :timeout_in_seconds, :wait_until_stopped
|
6
14
|
|
@@ -3,7 +3,7 @@ module Selenium
|
|
3
3
|
|
4
4
|
class RemoteControl
|
5
5
|
attr_reader :host, :port, :timeout_in_seconds
|
6
|
-
attr_accessor :additional_args, :jar_file
|
6
|
+
attr_accessor :additional_args, :jar_file, :log_to
|
7
7
|
|
8
8
|
def initialize(host, port, timeout_in_seconds = 2 * 60)
|
9
9
|
@host, @port, @timeout_in_seconds = host, port, timeout_in_seconds
|
@@ -16,6 +16,7 @@ module Selenium
|
|
16
16
|
command << " -port #{@port}"
|
17
17
|
command << " -timeout #{@timeout_in_seconds}"
|
18
18
|
command << " #{additional_args.join(' ')}" unless additional_args.empty?
|
19
|
+
command << " > #{log_to}" if log_to
|
19
20
|
|
20
21
|
@shell.run command, {:background => options[:background]}
|
21
22
|
end
|
@@ -3,9 +3,12 @@ module Selenium
|
|
3
3
|
module Reporting
|
4
4
|
|
5
5
|
class FilePathStrategy
|
6
|
-
|
6
|
+
attr_reader :final_report_file_path
|
7
|
+
|
8
|
+
REPORT_DEFAULT_FILE_PATH = File.join(Dir::tmpdir, "selenium_test_report", "index.html")
|
9
|
+
|
7
10
|
def initialize(final_report_file_path)
|
8
|
-
@final_report_file_path = final_report_file_path
|
11
|
+
@final_report_file_path = final_report_file_path || REPORT_DEFAULT_FILE_PATH
|
9
12
|
@relative_dir = nil
|
10
13
|
end
|
11
14
|
|
@@ -21,19 +24,23 @@ module Selenium
|
|
21
24
|
end
|
22
25
|
|
23
26
|
def relative_file_path_for_html_capture(example)
|
24
|
-
"#{relative_dir}/example_#{
|
27
|
+
"#{relative_dir}/example_#{example.reporting_uid}.html"
|
25
28
|
end
|
26
29
|
|
27
30
|
def relative_file_path_for_system_screenshot(example)
|
28
|
-
"#{relative_dir}/example_#{
|
31
|
+
"#{relative_dir}/example_#{example.reporting_uid}_system_screenshot.png"
|
29
32
|
end
|
30
33
|
|
31
34
|
def relative_file_path_for_page_screenshot(example)
|
32
|
-
"#{relative_dir}/example_#{
|
35
|
+
"#{relative_dir}/example_#{example.reporting_uid}_page_screenshot.png"
|
33
36
|
end
|
34
37
|
|
35
38
|
def relative_file_path_for_remote_control_logs(example)
|
36
|
-
"#{relative_dir}/example_#{
|
39
|
+
"#{relative_dir}/example_#{example.reporting_uid}_remote_control.log"
|
40
|
+
end
|
41
|
+
|
42
|
+
def relative_file_path_for_browser_network_traffic(example)
|
43
|
+
"#{relative_dir}/example_#{example.reporting_uid}_browser_network_traffic.log"
|
37
44
|
end
|
38
45
|
|
39
46
|
def file_path_for_html_capture(example)
|
@@ -52,6 +59,10 @@ module Selenium
|
|
52
59
|
file_path relative_file_path_for_remote_control_logs(example)
|
53
60
|
end
|
54
61
|
|
62
|
+
def file_path_for_browser_network_traffic(example)
|
63
|
+
file_path relative_file_path_for_browser_network_traffic(example)
|
64
|
+
end
|
65
|
+
|
55
66
|
def file_path(relative_file_path)
|
56
67
|
the_file_path = base_report_dir + "/" + relative_file_path
|
57
68
|
parent_dir = File.dirname(the_file_path)
|
@@ -59,14 +70,9 @@ module Selenium
|
|
59
70
|
the_file_path
|
60
71
|
end
|
61
72
|
|
62
|
-
|
63
|
-
# backtrace is not reliable anymore using the implementation proc
|
64
|
-
implementation = example.instance_variable_get :'@_implementation'
|
65
|
-
Digest::MD5.hexdigest implementation.inspect
|
66
|
-
end
|
67
|
-
|
73
|
+
|
68
74
|
end
|
69
75
|
|
70
76
|
end
|
71
77
|
end
|
72
|
-
end
|
78
|
+
end
|
@@ -19,7 +19,7 @@ module Selenium
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def logs_and_screenshot_sections(example)
|
22
|
-
dom_id = "example_" +
|
22
|
+
dom_id = "example_" + example.reporting_uid
|
23
23
|
system_screenshot_url = @file_path_strategy.relative_file_path_for_system_screenshot(example)
|
24
24
|
page_screenshot_url = @file_path_strategy.relative_file_path_for_page_screenshot(example)
|
25
25
|
snapshot_url = @file_path_strategy.relative_file_path_for_html_capture(example)
|
@@ -120,4 +120,4 @@ module Selenium
|
|
120
120
|
end
|
121
121
|
|
122
122
|
end
|
123
|
-
end
|
123
|
+
end
|
@@ -5,8 +5,9 @@
|
|
5
5
|
#
|
6
6
|
require "digest/md5"
|
7
7
|
require "base64"
|
8
|
+
require 'tmpdir'
|
8
9
|
require "rubygems"
|
9
|
-
gem "rspec", "1.
|
10
|
+
gem "rspec", "1.2.6"
|
10
11
|
require "spec"
|
11
12
|
require 'spec/runner/formatter/html_formatter'
|
12
13
|
require File.expand_path(File.dirname(__FILE__) + "/file_path_strategy")
|
@@ -18,14 +19,19 @@ module Selenium
|
|
18
19
|
|
19
20
|
class SeleniumTestReportFormatter < Spec::Runner::Formatter::HtmlFormatter
|
20
21
|
|
22
|
+
def initialize(options, output)
|
23
|
+
super
|
24
|
+
raise "Unexpected output type #{output.inspect}" unless output.kind_of?(String)
|
25
|
+
@@file_path_strategy = Selenium::RSpec::Reporting::FilePathStrategy.new(output)
|
26
|
+
end
|
27
|
+
|
21
28
|
def start(example_count)
|
22
29
|
super
|
23
30
|
# ensure there's at least 1 example group header (normally 0 with deep_test)
|
24
31
|
# prevents js and html validity errors
|
25
32
|
example_group = Object.new
|
26
33
|
def example_group.description; ""; end
|
27
|
-
|
28
|
-
@@file_path_strategy = Selenium::RSpec::Reporting::FilePathStrategy.new(@where)
|
34
|
+
example_group_started example_group
|
29
35
|
end
|
30
36
|
|
31
37
|
def move_progress
|
@@ -36,19 +42,11 @@ module Selenium
|
|
36
42
|
Selenium::RSpec::Reporting::HtmlReport.inject_placeholder(super)
|
37
43
|
end
|
38
44
|
|
39
|
-
def
|
40
|
-
include_example_group_description example
|
45
|
+
def example_pending(example_proxy, message, deprecated_pending_location=nil)
|
41
46
|
super
|
42
47
|
end
|
43
48
|
|
44
|
-
def
|
45
|
-
include_example_group_description example
|
46
|
-
super
|
47
|
-
end
|
48
|
-
|
49
|
-
def example_failed(example, counter, failure)
|
50
|
-
include_example_group_description example
|
51
|
-
|
49
|
+
def example_failed(example, counter, failure)
|
52
50
|
old_output = @output
|
53
51
|
@output = StringIO.new
|
54
52
|
super
|
@@ -83,15 +81,7 @@ module Selenium
|
|
83
81
|
# and RSpec reporting work for a proper fix.
|
84
82
|
@@file_path_strategy ||= Selenium::RSpec::Reporting::FilePathStrategy.new(ENV["SELENIUM_TEST_REPORT_FILE"])
|
85
83
|
end
|
86
|
-
|
87
|
-
protected
|
88
|
-
|
89
|
-
def include_example_group_description(example)
|
90
|
-
def example.description
|
91
|
-
self.class.description.to_s + " :: " + super
|
92
|
-
end
|
93
|
-
end
|
94
84
|
|
95
85
|
end
|
96
86
|
end
|
97
|
-
end
|
87
|
+
end
|
@@ -49,7 +49,7 @@ module Selenium
|
|
49
49
|
|
50
50
|
encodedImage = @selenium_driver.capture_screenshot_to_string
|
51
51
|
pngImage = Base64.decode64(encodedImage)
|
52
|
-
File.open(@file_path_strategy.file_path_for_system_screenshot(@example), "
|
52
|
+
File.open(@file_path_strategy.file_path_for_system_screenshot(@example), "wb") { |f| f.write pngImage }
|
53
53
|
end
|
54
54
|
|
55
55
|
def capture_page_screenshot
|
@@ -57,7 +57,7 @@ module Selenium
|
|
57
57
|
|
58
58
|
encodedImage = @selenium_driver.capture_entire_page_screenshot_to_string("")
|
59
59
|
pngImage = Base64.decode64(encodedImage)
|
60
|
-
File.open(@file_path_strategy.file_path_for_page_screenshot(@example), "
|
60
|
+
File.open(@file_path_strategy.file_path_for_page_screenshot(@example), "wb") { |f| f.write pngImage }
|
61
61
|
end
|
62
62
|
|
63
63
|
def retrieve_remote_control_logs
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require "rubygems"
|
2
|
-
gem "rspec", "=1.
|
2
|
+
gem "rspec", "=1.2.6"
|
3
3
|
require 'spec'
|
4
4
|
require 'spec/example/example_group'
|
5
5
|
|
@@ -7,26 +7,36 @@ require 'spec/example/example_group'
|
|
7
7
|
# Monkey-patch RSpec Example Group so that we can track whether an
|
8
8
|
# example already failed or not in an after(:each) block
|
9
9
|
#
|
10
|
-
#
|
10
|
+
# Useful to only capture Selenium screenshots when a test fails
|
11
11
|
#
|
12
|
-
#
|
13
|
-
#
|
12
|
+
# * Changed execution_error to be an instance variable (in lieu of
|
13
|
+
# a local variable).
|
14
|
+
#
|
15
|
+
# * Introduced an unique id (example_uid) that is the same for
|
16
|
+
# a real Example (passed in after(:each) when screenshot is
|
17
|
+
# taken) as well as the corresponding ExampleProxy
|
18
|
+
# (passed to the HTML formatter). This unique id gives us
|
19
|
+
# a way to correlate file names between generation and
|
20
|
+
# reporting time.
|
14
21
|
#
|
15
22
|
module Spec
|
16
23
|
module Example
|
17
|
-
|
18
|
-
|
24
|
+
module ExampleMethods
|
25
|
+
|
19
26
|
attr_reader :execution_error
|
20
27
|
|
21
|
-
|
22
|
-
|
28
|
+
remove_method :execute
|
29
|
+
def execute(run_options, instance_variables) # :nodoc:
|
30
|
+
@_proxy.options[:actual_example] = self
|
31
|
+
|
32
|
+
run_options.reporter.example_started(@_proxy)
|
23
33
|
set_instance_variables_from_hash(instance_variables)
|
24
34
|
|
25
35
|
@execution_error = nil
|
26
|
-
Timeout.timeout(
|
36
|
+
Timeout.timeout(run_options.timeout) do
|
27
37
|
begin
|
28
38
|
before_each_example
|
29
|
-
|
39
|
+
instance_eval(&@_implementation)
|
30
40
|
rescue Exception => e
|
31
41
|
@execution_error ||= e
|
32
42
|
end
|
@@ -37,10 +47,50 @@ module Spec
|
|
37
47
|
end
|
38
48
|
end
|
39
49
|
|
40
|
-
|
50
|
+
run_options.reporter.example_finished(@_proxy.update(description), @execution_error)
|
41
51
|
success = @execution_error.nil? || ExamplePendingError === @execution_error
|
42
52
|
end
|
43
|
-
|
53
|
+
|
54
|
+
def actual_failure?
|
55
|
+
case execution_error
|
56
|
+
when nil
|
57
|
+
false
|
58
|
+
when Spec::Example::ExamplePendingError,
|
59
|
+
Spec::Example::PendingExampleFixedError,
|
60
|
+
Spec::Example::NoDescriptionError
|
61
|
+
false
|
62
|
+
else
|
63
|
+
true
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def reporting_uid
|
68
|
+
# backtrace is not reliable anymore using the implementation proc
|
69
|
+
Digest::MD5.hexdigest @_implementation.inspect
|
70
|
+
end
|
71
|
+
|
72
|
+
def pending_for_browsers(*browser_regexps, &block)
|
73
|
+
actual_browser = selenium_driver.browser_string
|
74
|
+
match_browser_regexps = browser_regexps.inject(false) do |match, regexp|
|
75
|
+
match ||= actual_browser =~ Regexp.new(regexp.source, Regexp::IGNORECASE)
|
76
|
+
end
|
77
|
+
if match_browser_regexps
|
78
|
+
pending "#{actual_browser.gsub(/\*/, '').capitalize} does not support this feature yet"
|
79
|
+
else
|
80
|
+
yield
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
44
84
|
end
|
85
|
+
|
86
|
+
class ExampleProxy
|
87
|
+
|
88
|
+
def reporting_uid
|
89
|
+
options[:actual_example].reporting_uid
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
45
94
|
end
|
46
95
|
end
|
96
|
+
|
@@ -9,7 +9,9 @@ Spec::Runner.configure do |config|
|
|
9
9
|
|
10
10
|
config.prepend_after(:each) do
|
11
11
|
begin
|
12
|
-
|
12
|
+
if actual_failure?
|
13
|
+
Selenium::RSpec::SeleniumTestReportFormatter.capture_system_state(selenium_driver, self)
|
14
|
+
end
|
13
15
|
if selenium_driver.session_started?
|
14
16
|
selenium_driver.set_context "Ending example '#{self.description}'"
|
15
17
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: selenium-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- OpenQA
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-05-12 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -54,6 +54,8 @@ files:
|
|
54
54
|
- README.markdown
|
55
55
|
has_rdoc: true
|
56
56
|
homepage: http://selenium-client.rubyforge.com
|
57
|
+
licenses: []
|
58
|
+
|
57
59
|
post_install_message:
|
58
60
|
rdoc_options:
|
59
61
|
- --title
|
@@ -78,9 +80,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
78
80
|
requirements: []
|
79
81
|
|
80
82
|
rubyforge_project: selenium-client
|
81
|
-
rubygems_version: 1.3.
|
83
|
+
rubygems_version: 1.3.2
|
82
84
|
signing_key:
|
83
|
-
specification_version:
|
85
|
+
specification_version: 3
|
84
86
|
summary: Official Ruby Client for Selenium RC.
|
85
87
|
test_files:
|
86
88
|
- test/all_unit_tests.rb
|