warnold-selenium-client 1.2.19
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/README.markdown +338 -0
- data/examples/rspec/google_spec.rb +41 -0
- data/examples/script/google.rb +25 -0
- data/examples/testunit/google_test.rb +39 -0
- data/lib/nautilus/shell.rb +34 -0
- data/lib/selenium.rb +14 -0
- data/lib/selenium/client.rb +27 -0
- data/lib/selenium/client/base.rb +118 -0
- data/lib/selenium/client/driver.rb +11 -0
- data/lib/selenium/client/extensions.rb +118 -0
- data/lib/selenium/client/idiomatic.rb +488 -0
- data/lib/selenium/client/javascript_expression_builder.rb +116 -0
- data/lib/selenium/client/javascript_frameworks/jquery.rb +13 -0
- data/lib/selenium/client/javascript_frameworks/prototype.rb +13 -0
- data/lib/selenium/client/legacy_driver.rb +1711 -0
- data/lib/selenium/client/protocol.rb +104 -0
- data/lib/selenium/client/selenium_helper.rb +34 -0
- data/lib/selenium/command_error.rb +4 -0
- data/lib/selenium/protocol_error.rb +4 -0
- data/lib/selenium/rake/default_tasks.rb +17 -0
- data/lib/selenium/rake/remote_control_start_task.rb +71 -0
- data/lib/selenium/rake/remote_control_stop_task.rb +44 -0
- data/lib/selenium/rake/tasks.rb +6 -0
- data/lib/selenium/remote_control/remote_control.rb +35 -0
- data/lib/selenium/rspec/reporting/file_path_strategy.rb +78 -0
- data/lib/selenium/rspec/reporting/html_report.rb +155 -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 +104 -0
- data/lib/selenium/rspec/spec_helper.rb +34 -0
- data/lib/tcp_socket_extension.rb +32 -0
- data/test/all_unit_tests.rb +3 -0
- metadata +102 -0
@@ -0,0 +1,88 @@
|
|
1
|
+
#
|
2
|
+
# Explicit requires in this file so that we can invoke RSpec runner with a
|
3
|
+
# single:
|
4
|
+
# --require 'lib/selenium/rspec/reporting/selenium_test_report_formatter'
|
5
|
+
#
|
6
|
+
require "digest/md5"
|
7
|
+
require "base64"
|
8
|
+
require 'tmpdir'
|
9
|
+
require "rubygems"
|
10
|
+
gem "rspec", ">=1.2.8"
|
11
|
+
require "spec"
|
12
|
+
require 'spec/runner/formatter/html_formatter'
|
13
|
+
require File.expand_path(File.dirname(__FILE__) + "/file_path_strategy")
|
14
|
+
require File.expand_path(File.dirname(__FILE__) + "/system_capture")
|
15
|
+
require File.expand_path(File.dirname(__FILE__) + "/html_report")
|
16
|
+
|
17
|
+
module Selenium
|
18
|
+
module RSpec
|
19
|
+
|
20
|
+
class SeleniumTestReportFormatter < Spec::Runner::Formatter::HtmlFormatter
|
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
|
+
|
28
|
+
def start(example_count)
|
29
|
+
super
|
30
|
+
# ensure there's at least 1 example group header (normally 0 with deep_test)
|
31
|
+
# prevents js and html validity errors
|
32
|
+
example_group = Object.new
|
33
|
+
def example_group.description; ""; end
|
34
|
+
example_group_started example_group
|
35
|
+
end
|
36
|
+
|
37
|
+
def move_progress
|
38
|
+
# we don't have current_example_number, and we don't really care about the progress bar
|
39
|
+
end
|
40
|
+
|
41
|
+
def extra_failure_content(failure)
|
42
|
+
Selenium::RSpec::Reporting::HtmlReport.inject_placeholder(super)
|
43
|
+
end
|
44
|
+
|
45
|
+
def example_pending(example_proxy, message, deprecated_pending_location=nil)
|
46
|
+
super
|
47
|
+
end
|
48
|
+
|
49
|
+
def example_failed(example, counter, failure)
|
50
|
+
old_output = @output
|
51
|
+
@output = StringIO.new
|
52
|
+
SeleniumQuietBacktraceTweaker.new.tweak_backtrace(failure.exception)
|
53
|
+
super
|
54
|
+
|
55
|
+
result = @output.string
|
56
|
+
report = Selenium::RSpec::Reporting::HtmlReport.new(@@file_path_strategy)
|
57
|
+
report.replace_placeholder_with_system_state_content(result, example)
|
58
|
+
old_output.puts result
|
59
|
+
old_output.flush
|
60
|
+
ensure
|
61
|
+
@output = old_output
|
62
|
+
end
|
63
|
+
|
64
|
+
# Should be called from config.after(:each) in spec helper
|
65
|
+
def self.capture_system_state(selenium_driver, example)
|
66
|
+
system_capture = Selenium::RSpec::Reporting::SystemCapture.new(selenium_driver, example, file_path_strategy)
|
67
|
+
system_capture.capture_system_state
|
68
|
+
end
|
69
|
+
|
70
|
+
def global_scripts
|
71
|
+
Selenium::RSpec::Reporting::HtmlReport.append_javascript(super)
|
72
|
+
end
|
73
|
+
|
74
|
+
def global_styles
|
75
|
+
Selenium::RSpec::Reporting::HtmlReport.append_css(super)
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.file_path_strategy
|
79
|
+
### HACK ####
|
80
|
+
# When running with DeepTest the class instance variable could not have been set
|
81
|
+
# For now you must set the env variable before launching the tests. We need to revisit the way DeepTest
|
82
|
+
# and RSpec reporting work for a proper fix.
|
83
|
+
@@file_path_strategy ||= Selenium::RSpec::Reporting::FilePathStrategy.new(ENV["SELENIUM_TEST_REPORT_FILE"])
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Selenium
|
2
|
+
module RSpec
|
3
|
+
module Reporting
|
4
|
+
|
5
|
+
class SystemCapture
|
6
|
+
|
7
|
+
def initialize(selenium_driver, example, file_path_strategy)
|
8
|
+
@selenium_driver = selenium_driver
|
9
|
+
@example = example
|
10
|
+
@file_path_strategy = file_path_strategy
|
11
|
+
end
|
12
|
+
|
13
|
+
def capture_system_state
|
14
|
+
# Selenium RC seems to 'freeze' every so often when calling
|
15
|
+
# getHTMLSource, especially when DeepTest timeout is low, I need to investigate...
|
16
|
+
# Set deeptest :timeout_in_seconds => 30 to see it happen
|
17
|
+
begin
|
18
|
+
retrieve_remote_control_logs
|
19
|
+
rescue Exception => e
|
20
|
+
STDERR.puts "WARNING: Could not retrieve remote control logs: #{e}"
|
21
|
+
end
|
22
|
+
begin
|
23
|
+
capture_html_snapshot
|
24
|
+
rescue Exception => e
|
25
|
+
STDERR.puts "WARNING: Could not capture HTML snapshot: #{e}"
|
26
|
+
end
|
27
|
+
begin
|
28
|
+
capture_page_screenshot
|
29
|
+
rescue Exception => e
|
30
|
+
STDERR.puts "WARNING: Could not capture page screenshot: #{e}"
|
31
|
+
end
|
32
|
+
begin
|
33
|
+
capture_system_screenshot
|
34
|
+
rescue Exception => e
|
35
|
+
STDERR.puts "WARNING: Could not capture system screenshot: #{e}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def capture_html_snapshot
|
40
|
+
# Skipping HTML Snapshot retrieval, if there is no current Selenium session
|
41
|
+
return unless @selenium_driver.session_started?
|
42
|
+
|
43
|
+
html = @selenium_driver.get_html_source
|
44
|
+
File.open(@file_path_strategy.file_path_for_html_capture(@example), "w") { |f| f.write html }
|
45
|
+
end
|
46
|
+
|
47
|
+
def capture_system_screenshot
|
48
|
+
@selenium_driver.window_maximize if @selenium_driver.session_started?
|
49
|
+
|
50
|
+
encodedImage = @selenium_driver.capture_screenshot_to_string
|
51
|
+
pngImage = Base64.decode64(encodedImage)
|
52
|
+
File.open(@file_path_strategy.file_path_for_system_screenshot(@example), "wb") { |f| f.write pngImage }
|
53
|
+
end
|
54
|
+
|
55
|
+
def capture_page_screenshot
|
56
|
+
return unless @selenium_driver.chrome_backend? && @selenium_driver.session_started?
|
57
|
+
|
58
|
+
encodedImage = @selenium_driver.capture_entire_page_screenshot_to_string("")
|
59
|
+
pngImage = Base64.decode64(encodedImage)
|
60
|
+
File.open(@file_path_strategy.file_path_for_page_screenshot(@example), "wb") { |f| f.write pngImage }
|
61
|
+
end
|
62
|
+
|
63
|
+
def retrieve_remote_control_logs
|
64
|
+
logs = @selenium_driver.retrieve_last_remote_control_logs
|
65
|
+
File.open(@file_path_strategy.file_path_for_remote_control_logs(@example), "w") { |f| f.write logs }
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
gem "rspec", ">=1.2.8"
|
3
|
+
require 'spec'
|
4
|
+
require 'spec/example/example_group'
|
5
|
+
|
6
|
+
#
|
7
|
+
# Monkey-patch RSpec Example Group so that we can track whether an
|
8
|
+
# example already failed or not in an after(:each) block
|
9
|
+
#
|
10
|
+
# Useful to only capture Selenium screenshots when a test fails
|
11
|
+
#
|
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.
|
21
|
+
#
|
22
|
+
module Spec
|
23
|
+
module Example
|
24
|
+
module ExampleMethods
|
25
|
+
|
26
|
+
attr_reader :execution_error
|
27
|
+
|
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)
|
33
|
+
set_instance_variables_from_hash(instance_variables)
|
34
|
+
|
35
|
+
@execution_error = nil
|
36
|
+
Timeout.timeout(run_options.timeout) do
|
37
|
+
begin
|
38
|
+
before_each_example
|
39
|
+
instance_eval(&@_implementation)
|
40
|
+
rescue Timeout::Error => e
|
41
|
+
@execution_error ||= e
|
42
|
+
rescue Interrupt
|
43
|
+
exit 1
|
44
|
+
rescue Exception => e
|
45
|
+
@execution_error ||= e
|
46
|
+
end
|
47
|
+
begin
|
48
|
+
after_each_example
|
49
|
+
rescue Timeout::Error => e
|
50
|
+
@execution_error ||= e
|
51
|
+
rescue Interrupt
|
52
|
+
exit 1
|
53
|
+
rescue Exception => e
|
54
|
+
@execution_error ||= e
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
run_options.reporter.example_finished(@_proxy.update(description), @execution_error)
|
59
|
+
success = @execution_error.nil? || ExamplePendingError === @execution_error
|
60
|
+
end
|
61
|
+
|
62
|
+
def actual_failure?
|
63
|
+
case execution_error
|
64
|
+
when nil
|
65
|
+
false
|
66
|
+
when Spec::Example::ExamplePendingError,
|
67
|
+
Spec::Example::PendingExampleFixedError,
|
68
|
+
Spec::Example::NoDescriptionError
|
69
|
+
false
|
70
|
+
else
|
71
|
+
true
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def reporting_uid
|
76
|
+
# backtrace is not reliable anymore using the implementation proc
|
77
|
+
Digest::MD5.hexdigest @_implementation.inspect
|
78
|
+
end
|
79
|
+
|
80
|
+
def pending_for_browsers(*browser_regexps, &block)
|
81
|
+
actual_browser = selenium_driver.browser_string
|
82
|
+
match_browser_regexps = browser_regexps.inject(false) do |match, regexp|
|
83
|
+
match ||= actual_browser =~ Regexp.new(regexp.source, Regexp::IGNORECASE)
|
84
|
+
end
|
85
|
+
if match_browser_regexps
|
86
|
+
pending "#{actual_browser.gsub(/\*/, '').capitalize} does not support this feature yet"
|
87
|
+
else
|
88
|
+
yield
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
class ExampleProxy
|
95
|
+
|
96
|
+
def reporting_uid
|
97
|
+
options[:actual_example].reporting_uid
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'spec'
|
3
|
+
require 'base64'
|
4
|
+
require 'fileutils'
|
5
|
+
require File.expand_path(File.dirname(__FILE__) + "/rspec_extensions")
|
6
|
+
require File.expand_path(File.dirname(__FILE__) + "/reporting/selenium_test_report_formatter")
|
7
|
+
|
8
|
+
Spec::Runner.configure do |config|
|
9
|
+
|
10
|
+
config.prepend_after(:each) do
|
11
|
+
begin
|
12
|
+
if actual_failure?
|
13
|
+
Selenium::RSpec::SeleniumTestReportFormatter.capture_system_state(selenium_driver, self)
|
14
|
+
end
|
15
|
+
if selenium_driver.session_started?
|
16
|
+
selenium_driver.set_context "Ending example '#{self.description}'"
|
17
|
+
end
|
18
|
+
rescue Exception => e
|
19
|
+
STDERR.puts "Problem while capturing system state" + e
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
config.append_before(:each) do
|
24
|
+
begin
|
25
|
+
if selenium_driver && selenium_driver.session_started?
|
26
|
+
selenium_driver.set_context "Starting example '#{self.description}'"
|
27
|
+
end
|
28
|
+
rescue Exception => e
|
29
|
+
STDERR.puts "Problem while setting context on example start" + e
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
require 'socket'
|
3
|
+
|
4
|
+
class TCPSocket
|
5
|
+
|
6
|
+
def self.wait_for_service(options)
|
7
|
+
verbose_wait until listening_service?(options)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.wait_for_service_termination(options)
|
11
|
+
verbose_wait while listening_service?(options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.listening_service?(options)
|
15
|
+
Timeout::timeout(options[:timeout] || 20) do
|
16
|
+
begin
|
17
|
+
socket = TCPSocket.new(options[:host], options[:port])
|
18
|
+
socket.close unless socket.nil?
|
19
|
+
true
|
20
|
+
rescue Errno::ECONNREFUSED,
|
21
|
+
Errno::EBADF # Windows
|
22
|
+
false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.verbose_wait
|
28
|
+
puts ".\n"
|
29
|
+
sleep 2
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
metadata
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: warnold-selenium-client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 57
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 2
|
9
|
+
- 19
|
10
|
+
version: 1.2.19
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- OpenQA, Philippe Hanrigou, Joshua Krall, Wolfram Arnold
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-06-27 00:00:00 -07:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description:
|
23
|
+
email: wolfram@rubyfocus.biz
|
24
|
+
executables: []
|
25
|
+
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files:
|
29
|
+
- README.markdown
|
30
|
+
files:
|
31
|
+
- lib/selenium/client/selenium_helper.rb
|
32
|
+
- lib/selenium/client/idiomatic.rb
|
33
|
+
- lib/selenium/client/javascript_expression_builder.rb
|
34
|
+
- lib/selenium/client/legacy_driver.rb
|
35
|
+
- lib/selenium/client/protocol.rb
|
36
|
+
- lib/selenium/client/driver.rb
|
37
|
+
- lib/selenium/client/base.rb
|
38
|
+
- lib/selenium/client/javascript_frameworks/jquery.rb
|
39
|
+
- lib/selenium/client/javascript_frameworks/prototype.rb
|
40
|
+
- lib/selenium/client/extensions.rb
|
41
|
+
- lib/selenium/rake/default_tasks.rb
|
42
|
+
- lib/selenium/rake/remote_control_start_task.rb
|
43
|
+
- lib/selenium/rake/remote_control_stop_task.rb
|
44
|
+
- lib/selenium/rake/tasks.rb
|
45
|
+
- lib/selenium/remote_control/remote_control.rb
|
46
|
+
- lib/selenium/command_error.rb
|
47
|
+
- lib/selenium/protocol_error.rb
|
48
|
+
- lib/selenium/rspec/rspec_extensions.rb
|
49
|
+
- lib/selenium/rspec/spec_helper.rb
|
50
|
+
- lib/selenium/rspec/reporting/selenium_test_report_formatter.rb
|
51
|
+
- lib/selenium/rspec/reporting/file_path_strategy.rb
|
52
|
+
- lib/selenium/rspec/reporting/html_report.rb
|
53
|
+
- lib/selenium/rspec/reporting/system_capture.rb
|
54
|
+
- lib/selenium/client.rb
|
55
|
+
- lib/tcp_socket_extension.rb
|
56
|
+
- lib/nautilus/shell.rb
|
57
|
+
- lib/selenium.rb
|
58
|
+
- examples/script/google.rb
|
59
|
+
- examples/rspec/google_spec.rb
|
60
|
+
- examples/testunit/google_test.rb
|
61
|
+
- README.markdown
|
62
|
+
- test/all_unit_tests.rb
|
63
|
+
has_rdoc: true
|
64
|
+
homepage: http://selenium-client.rubyforge.com
|
65
|
+
licenses: []
|
66
|
+
|
67
|
+
post_install_message:
|
68
|
+
rdoc_options:
|
69
|
+
- --title
|
70
|
+
- Selenium Client
|
71
|
+
- --main
|
72
|
+
- README
|
73
|
+
- --line-numbers
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
hash: 3
|
82
|
+
segments:
|
83
|
+
- 0
|
84
|
+
version: "0"
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
hash: 3
|
91
|
+
segments:
|
92
|
+
- 0
|
93
|
+
version: "0"
|
94
|
+
requirements: []
|
95
|
+
|
96
|
+
rubyforge_project: selenium-client
|
97
|
+
rubygems_version: 1.3.7
|
98
|
+
signing_key:
|
99
|
+
specification_version: 3
|
100
|
+
summary: Official Ruby Client for Selenium RC, modified by W. Arnold
|
101
|
+
test_files:
|
102
|
+
- test/all_unit_tests.rb
|