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.
@@ -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.13"
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.13"
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.1.12"
154
- gem "selenium-client", ">=1.2.13"
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
- 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
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, etc. Make the gem work the way you
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 [reference repository](http://github.com/ph7/selenium-client/tree/master)
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) and the [RDoc](http://selenium-client.rubyforge.org)
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
- - Patch for more robust Selenium RC shutdown
283
- - Patch to support locator including single quotes in `wait_for_...` methods
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
- - Patch for incremental calls to `wait_for_text`
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.1.12"
3
- gem "selenium-client", ">=1.2.13"
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
@@ -3,7 +3,7 @@
3
3
  # Sample Ruby script using the Selenium client API
4
4
  #
5
5
  require "rubygems"
6
- gem "selenium-client", ">=1.2.13"
6
+ gem "selenium-client", ">=1.2.15"
7
7
  require "selenium/client"
8
8
 
9
9
  begin
@@ -4,7 +4,7 @@
4
4
  #
5
5
  require "test/unit"
6
6
  require "rubygems"
7
- gem "selenium-client", ">=1.2.13"
7
+ gem "selenium-client", ">=1.2.15"
8
8
  require "selenium/client"
9
9
 
10
10
  class ExampleTest < Test::Unit::TestCase
@@ -6,7 +6,8 @@ require 'net/http'
6
6
  require 'uri'
7
7
  require 'cgi'
8
8
  require "digest/md5"
9
- require "fileutils"
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')
@@ -60,8 +60,16 @@ module Selenium
60
60
  not @session_id.nil?
61
61
  end
62
62
 
63
- def start_new_browser_session
64
- result = string_command "getNewBrowserSession", [@browser_string, @browser_url, @extension_js]
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 every instance of some attribute from all known windows.
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 standard "open" method with @selenium.open
11
- def open(addr)
12
- @selenium.open(addr)
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 standard "type" method with @selenium.type
16
- def type(inputLocator, value)
17
- @selenium.type(inputLocator, value)
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 standard "select" method with @selenium.select
21
- def select(inputLocator, optionLocator)
22
- @selenium.select(inputLocator, optionLocator)
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
- # Passes all calls to missing methods to @selenium
25
+ # Delegates to @selenium on method missing
26
26
  def method_missing(method_name, *args)
27
- if args.empty?
28
- @selenium.send(method_name)
29
- else
30
- @selenium.send(method_name, *args)
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
- @jar_file = "vendor/selenium/selenium-server-1.0-standalone.jar"
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_#{example_hash(example)}.html"
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_#{example_hash(example)}_system_screenshot.png"
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_#{example_hash(example)}_page_screenshot.png"
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_#{example_hash(example)}_remote_control.log"
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
- def example_hash(example)
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_" + @file_path_strategy.example_hash(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.1.12"
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
- add_example_group(example_group)
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 example_passed(example)
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 example_pending(example, message, pending_caller)
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), "w") { |f| f.write pngImage }
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), "w") { |f| f.write pngImage }
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.1.12"
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
- # useful to only capture Selenium screenshots when a test fails
10
+ # Useful to only capture Selenium screenshots when a test fails
11
11
  #
12
- # Only changed execution_error to be an instance variable (in lieu of
13
- # a local variable).
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
- class ExampleGroup
24
+ module ExampleMethods
25
+
19
26
  attr_reader :execution_error
20
27
 
21
- def execute(options, instance_variables)
22
- options.reporter.example_started(self)
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(options.timeout) do
36
+ Timeout.timeout(run_options.timeout) do
27
37
  begin
28
38
  before_each_example
29
- eval_block
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
- options.reporter.example_finished(self, @execution_error)
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
- Selenium::RSpec::SeleniumTestReportFormatter.capture_system_state(selenium_driver, self) if execution_error
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.14
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-03-07 23:00:00 -08:00
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.1
83
+ rubygems_version: 1.3.2
82
84
  signing_key:
83
- specification_version: 2
85
+ specification_version: 3
84
86
  summary: Official Ruby Client for Selenium RC.
85
87
  test_files:
86
88
  - test/all_unit_tests.rb