selenium-webdriver 4.0.0.alpha4 → 4.0.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/lib/selenium/devtools.rb +30 -0
  3. data/lib/selenium/server.rb +18 -26
  4. data/lib/selenium/webdriver.rb +1 -3
  5. data/lib/selenium/webdriver/atoms/findElements.js +93 -93
  6. data/lib/selenium/webdriver/atoms/getAttribute.js +75 -59
  7. data/lib/selenium/webdriver/atoms/isDisplayed.js +72 -72
  8. data/lib/selenium/webdriver/atoms/mutationListener.js +55 -0
  9. data/lib/selenium/webdriver/chrome.rb +1 -1
  10. data/lib/selenium/webdriver/chrome/driver.rb +17 -6
  11. data/lib/selenium/webdriver/chrome/{bridge.rb → features.rb} +6 -8
  12. data/lib/selenium/webdriver/chrome/options.rb +54 -37
  13. data/lib/selenium/webdriver/chrome/profile.rb +1 -1
  14. data/lib/selenium/webdriver/chrome/service.rb +4 -2
  15. data/lib/selenium/webdriver/common.rb +7 -2
  16. data/lib/selenium/webdriver/common/driver.rb +86 -26
  17. data/lib/selenium/webdriver/common/driver_extensions/has_authentication.rb +89 -0
  18. data/lib/selenium/webdriver/common/driver_extensions/has_devtools.rb +23 -1
  19. data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +5 -8
  20. data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +149 -0
  21. data/lib/selenium/webdriver/{edge_chrome/bridge.rb → common/driver_extensions/has_logs.rb} +7 -7
  22. data/lib/selenium/webdriver/common/driver_extensions/has_network_connection.rb +6 -27
  23. data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +67 -0
  24. data/lib/selenium/webdriver/common/driver_extensions/has_remote_status.rb +1 -0
  25. data/lib/selenium/webdriver/common/driver_extensions/prints_page.rb +32 -0
  26. data/lib/selenium/webdriver/common/element.rb +46 -12
  27. data/lib/selenium/webdriver/common/interactions/interaction.rb +4 -1
  28. data/lib/selenium/webdriver/common/logger.rb +6 -3
  29. data/lib/selenium/webdriver/common/manager.rb +11 -1
  30. data/lib/selenium/webdriver/common/options.rb +85 -11
  31. data/lib/selenium/webdriver/common/platform.rb +3 -1
  32. data/lib/selenium/webdriver/common/port_prober.rb +4 -6
  33. data/lib/selenium/webdriver/common/proxy.rb +4 -1
  34. data/lib/selenium/webdriver/common/search_context.rb +4 -1
  35. data/lib/selenium/webdriver/common/service.rb +13 -114
  36. data/lib/selenium/webdriver/common/service_manager.rb +151 -0
  37. data/lib/selenium/webdriver/common/takes_screenshot.rb +63 -0
  38. data/lib/selenium/webdriver/common/target_locator.rb +4 -4
  39. data/lib/selenium/webdriver/devtools.rb +144 -0
  40. data/lib/selenium/webdriver/devtools/console_event.rb +38 -0
  41. data/lib/selenium/webdriver/{edge_html/driver.rb → devtools/exception_event.rb} +10 -13
  42. data/lib/selenium/webdriver/devtools/mutation_event.rb +37 -0
  43. data/lib/selenium/webdriver/devtools/request.rb +57 -0
  44. data/lib/selenium/webdriver/edge.rb +7 -29
  45. data/lib/selenium/webdriver/{edge_chrome → edge}/driver.rb +10 -4
  46. data/lib/selenium/webdriver/edge/features.rb +39 -0
  47. data/lib/selenium/webdriver/{edge_chrome → edge}/options.rb +12 -3
  48. data/lib/selenium/webdriver/{edge_chrome → edge}/profile.rb +2 -2
  49. data/lib/selenium/webdriver/{edge_chrome → edge}/service.rb +2 -2
  50. data/lib/selenium/webdriver/firefox.rb +5 -1
  51. data/lib/selenium/webdriver/firefox/driver.rb +12 -3
  52. data/lib/selenium/webdriver/firefox/{bridge.rb → features.rb} +3 -3
  53. data/lib/selenium/webdriver/firefox/options.rb +25 -31
  54. data/lib/selenium/webdriver/firefox/profile.rb +12 -2
  55. data/lib/selenium/webdriver/firefox/service.rb +1 -1
  56. data/lib/selenium/webdriver/ie/driver.rb +1 -2
  57. data/lib/selenium/webdriver/ie/options.rb +7 -20
  58. data/lib/selenium/webdriver/ie/service.rb +4 -2
  59. data/lib/selenium/webdriver/remote/bridge.rb +37 -42
  60. data/lib/selenium/webdriver/remote/capabilities.rb +37 -34
  61. data/lib/selenium/webdriver/remote/commands.rb +1 -0
  62. data/lib/selenium/webdriver/remote/driver.rb +12 -3
  63. data/lib/selenium/webdriver/remote/http/common.rb +0 -5
  64. data/lib/selenium/webdriver/remote/http/default.rb +8 -7
  65. data/lib/selenium/webdriver/remote/http/persistent.rb +6 -0
  66. data/lib/selenium/webdriver/safari.rb +8 -1
  67. data/lib/selenium/webdriver/safari/driver.rb +3 -4
  68. data/lib/selenium/webdriver/safari/{bridge.rb → features.rb} +3 -3
  69. data/lib/selenium/webdriver/safari/options.rb +1 -33
  70. data/lib/selenium/webdriver/support/block_event_listener.rb +1 -1
  71. data/lib/selenium/webdriver/support/color.rb +2 -2
  72. data/lib/selenium/webdriver/support/event_firing_bridge.rb +1 -1
  73. data/lib/selenium/webdriver/support/guards.rb +95 -0
  74. data/lib/selenium/webdriver/support/guards/guard.rb +89 -0
  75. data/lib/selenium/webdriver/support/guards/guard_condition.rb +52 -0
  76. data/lib/selenium/webdriver/support/select.rb +2 -2
  77. data/lib/selenium/webdriver/version.rb +1 -1
  78. metadata +69 -32
  79. data/CHANGES +0 -1719
  80. data/Gemfile +0 -4
  81. data/LICENSE +0 -202
  82. data/README.md +0 -35
  83. data/lib/selenium/webdriver/common/driver_extensions/rotatable.rb +0 -61
  84. data/lib/selenium/webdriver/common/driver_extensions/takes_screenshot.rb +0 -65
  85. data/lib/selenium/webdriver/edge_html/options.rb +0 -91
  86. data/lib/selenium/webdriver/edge_html/service.rb +0 -47
  87. data/selenium-webdriver.gemspec +0 -48
@@ -82,21 +82,11 @@ module Selenium
82
82
  end
83
83
 
84
84
  def edge(opts = {})
85
- edge_html(opts)
86
- end
87
-
88
- def edge_html(opts = {})
89
- new({
90
- browser_name: 'MicrosoftEdge',
91
- platform_name: :windows
92
- }.merge(opts))
93
- end
94
-
95
- def edge_chrome(opts = {})
96
85
  new({
97
86
  browser_name: 'MicrosoftEdge'
98
87
  }.merge(opts))
99
88
  end
89
+ alias_method :microsoftedge, :edge
100
90
 
101
91
  def firefox(opts = {})
102
92
  opts[:browser_version] = opts.delete(:version) if opts.key?(:version)
@@ -113,8 +103,7 @@ module Selenium
113
103
 
114
104
  def safari(opts = {})
115
105
  new({
116
- browser_name: 'safari',
117
- platform_name: :mac
106
+ browser_name: Selenium::WebDriver::Safari.technology_preview? ? "Safari Technology Preview" : 'safari'
118
107
  }.merge(opts))
119
108
  end
120
109
 
@@ -140,32 +129,42 @@ module Selenium
140
129
  data = data.dup
141
130
 
142
131
  caps = new
143
- caps.browser_name = data.delete('browserName') if data.key?('browserName')
144
- caps.browser_version = data.delete('browserVersion') if data.key?('browserVersion')
145
- caps.platform_name = data.delete('platformName') if data.key?('platformName')
146
- caps.accept_insecure_certs = data.delete('acceptInsecureCerts') if data.key?('acceptInsecureCerts')
147
- caps.page_load_strategy = data.delete('pageLoadStrategy') if data.key?('pageLoadStrategy')
148
-
149
- if data.key?('timeouts')
150
- timeouts = data.delete('timeouts')
151
- caps.implicit_timeout = timeouts['implicit'] if timeouts
152
- caps.page_load_timeout = timeouts['pageLoad'] if timeouts
153
- caps.script_timeout = timeouts['script'] if timeouts
132
+ (KNOWN - %i[timeouts proxy]).each do |cap|
133
+ data_value = camel_case(cap)
134
+ caps[cap] = data.delete(data_value) if data.key?(data_value)
154
135
  end
155
136
 
137
+ process_timeouts(caps, data.delete('timeouts'))
138
+
156
139
  if data.key?('proxy')
157
140
  proxy = data.delete('proxy')
158
141
  caps.proxy = Proxy.json_create(proxy) unless proxy.nil? || proxy.empty?
159
142
  end
160
143
 
161
144
  # Remote Server Specific
162
- caps[:remote_session_id] = data.delete('webdriver.remote.sessionid') if data.key?('webdriver.remote.sessionid')
145
+ if data.key?('webdriver.remote.sessionid')
146
+ caps[:remote_session_id] = data.delete('webdriver.remote.sessionid')
147
+ end
163
148
 
164
149
  # any remaining pairs will be added as is, with no conversion
165
150
  caps.merge!(data)
166
151
 
167
152
  caps
168
153
  end
154
+
155
+ def camel_case(str_or_sym)
156
+ str_or_sym.to_s.gsub(/_([a-z])/) { Regexp.last_match(1).upcase }
157
+ end
158
+
159
+ private
160
+
161
+ def process_timeouts(caps, timeouts)
162
+ return if timeouts.nil?
163
+
164
+ caps.implicit_timeout = timeouts['implicit']
165
+ caps.page_load_timeout = timeouts['pageLoad']
166
+ caps.script_timeout = timeouts['script']
167
+ end
169
168
  end
170
169
 
171
170
  #
@@ -229,15 +228,15 @@ module Selenium
229
228
  when :platform
230
229
  hash['platform'] = value.to_s.upcase
231
230
  when :proxy
232
- if value
233
- hash['proxy'] = value.as_json
234
- hash['proxy']['proxyType'] &&= hash['proxy']['proxyType'].downcase
235
- hash['proxy']['noProxy'] = hash['proxy']['noProxy'].split(', ') if hash['proxy']['noProxy'].is_a?(String)
236
- end
231
+ next unless value
232
+
233
+ process_proxy(hash, value)
234
+ when :unhandled_prompt_behavior
235
+ hash['unhandledPromptBehavior'] = value.is_a?(Symbol) ? value.to_s.tr('_', ' ') : value
237
236
  when String
238
237
  hash[key.to_s] = value
239
238
  when Symbol
240
- hash[camel_case(key.to_s)] = value
239
+ hash[self.class.camel_case(key)] = value
241
240
  else
242
241
  raise TypeError, "expected String or Symbol, got #{key.inspect}:#{key.class} / #{value.inspect}"
243
242
  end
@@ -264,10 +263,14 @@ module Selenium
264
263
 
265
264
  private
266
265
 
267
- def camel_case(str)
268
- str.gsub(/_([a-z])/) { Regexp.last_match(1).upcase }
269
- end
266
+ def process_proxy(hash, value)
267
+ hash['proxy'] = value.as_json
268
+ hash['proxy']['proxyType'] &&= hash['proxy']['proxyType'].downcase
270
269
 
270
+ return unless hash['proxy']['noProxy'].is_a?(String)
271
+
272
+ hash['proxy']['noProxy'] = hash['proxy']['noProxy'].split(', ')
273
+ end
271
274
  end # Capabilities
272
275
  end # Remote
273
276
  end # WebDriver
@@ -117,6 +117,7 @@ module Selenium
117
117
 
118
118
  actions: [:post, 'session/:session_id/actions'],
119
119
  release_actions: [:delete, 'session/:session_id/actions'],
120
+ print_page: [:post, 'session/:session_id/print'],
120
121
 
121
122
  #
122
123
  # Element Operations
@@ -28,11 +28,8 @@ module Selenium
28
28
 
29
29
  class Driver < WebDriver::Driver
30
30
  include DriverExtensions::UploadsFiles
31
- include DriverExtensions::TakesScreenshot
32
31
  include DriverExtensions::HasSessionId
33
- include DriverExtensions::Rotatable
34
32
  include DriverExtensions::HasRemoteStatus
35
- include DriverExtensions::HasWebStorage
36
33
 
37
34
  def initialize(bridge: nil, listener: nil, **opts)
38
35
  desired_capabilities = opts[:desired_capabilities]
@@ -46,6 +43,18 @@ module Selenium
46
43
  opts[:url] ||= "http://#{Platform.localhost}:4444/wd/hub"
47
44
  super
48
45
  end
46
+
47
+ def print_page(**options)
48
+ options[:page_ranges] &&= Array(options[:page_ranges])
49
+
50
+ @bridge.print_page(options)
51
+ end
52
+
53
+ private
54
+
55
+ def devtools_address
56
+ capabilities['se:cdp']
57
+ end
49
58
  end # Driver
50
59
  end # Remote
51
60
  end # WebDriver
@@ -30,13 +30,8 @@ module Selenium
30
30
  'User-Agent' => "selenium/#{WebDriver::VERSION} (ruby #{Platform.os})"
31
31
  }.freeze
32
32
 
33
- attr_accessor :timeout
34
33
  attr_writer :server_url
35
34
 
36
- def initialize
37
- @timeout = nil
38
- end
39
-
40
35
  def quit_errors
41
36
  [IOError]
42
37
  end
@@ -28,8 +28,7 @@ module Selenium
28
28
  class Default < Common
29
29
  attr_writer :proxy
30
30
 
31
- attr_accessor :open_timeout
32
- attr_accessor :read_timeout
31
+ attr_accessor :open_timeout, :read_timeout
33
32
 
34
33
  # Initializes object.
35
34
  # Warning: Setting {#open_timeout} to non-nil values will cause a separate thread to spawn.
@@ -39,6 +38,7 @@ module Selenium
39
38
  def initialize(open_timeout: nil, read_timeout: nil)
40
39
  @open_timeout = open_timeout
41
40
  @read_timeout = read_timeout
41
+ super()
42
42
  end
43
43
 
44
44
  def close
@@ -55,8 +55,7 @@ module Selenium
55
55
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE
56
56
  end
57
57
 
58
- # Defaulting open_timeout to nil to be consistent with Ruby 2.2 and earlier.
59
- http.open_timeout = open_timeout
58
+ http.open_timeout = open_timeout if open_timeout
60
59
  http.read_timeout = read_timeout if read_timeout
61
60
 
62
61
  start(http)
@@ -128,12 +127,14 @@ module Selenium
128
127
  def new_http_client
129
128
  if use_proxy?
130
129
  url = @proxy.http
131
- raise Error::WebDriverError, "expected HTTP proxy, got #{@proxy.inspect}" unless proxy.respond_to?(:http) && url
130
+ unless proxy.respond_to?(:http) && url
131
+ raise Error::WebDriverError,
132
+ "expected HTTP proxy, got #{@proxy.inspect}"
133
+ end
132
134
 
133
135
  proxy = URI.parse(url)
134
136
 
135
- clazz = Net::HTTP::Proxy(proxy.host, proxy.port, proxy.user, proxy.password)
136
- clazz.new(server_url.host, server_url.port)
137
+ Net::HTTP.new(server_url.host, server_url.port, proxy.host, proxy.port, proxy.user, proxy.password)
137
138
  else
138
139
  Net::HTTP.new server_url.host, server_url.port
139
140
  end
@@ -25,6 +25,12 @@ module Selenium
25
25
  module Http
26
26
  # @api private
27
27
  class Persistent < Default
28
+ def initialize(open_timeout: nil, read_timeout: nil)
29
+ WebDriver.logger.deprecate("Selenium::WebDriver::Remote::Http::Persistent",
30
+ id: :http_persistent) { "The default HTTP client now uses persistence." }
31
+ super
32
+ end
33
+
28
34
  def close
29
35
  @http&.shutdown
30
36
  end
@@ -20,18 +20,25 @@
20
20
  module Selenium
21
21
  module WebDriver
22
22
  module Safari
23
- autoload :Bridge, 'selenium/webdriver/safari/bridge'
23
+ autoload :Features, 'selenium/webdriver/safari/features'
24
24
  autoload :Driver, 'selenium/webdriver/safari/driver'
25
25
  autoload :Options, 'selenium/webdriver/safari/options'
26
26
  autoload :Service, 'selenium/webdriver/safari/service'
27
27
 
28
28
  class << self
29
+ attr_accessor :use_technology_preview
30
+
29
31
  def technology_preview
30
32
  "/Applications/Safari\ Technology\ Preview.app/Contents/MacOS/safaridriver"
31
33
  end
32
34
 
33
35
  def technology_preview!
34
36
  Service.driver_path = technology_preview
37
+ @use_technology_preview = true
38
+ end
39
+
40
+ def technology_preview?
41
+ use_technology_preview
35
42
  end
36
43
 
37
44
  def path=(path)
@@ -27,10 +27,9 @@ module Selenium
27
27
  #
28
28
 
29
29
  class Driver < WebDriver::Driver
30
- include DriverExtensions::HasDebugger
31
- include DriverExtensions::HasPermissions
32
- include DriverExtensions::HasWebStorage
33
- include DriverExtensions::TakesScreenshot
30
+ EXTENSIONS = [DriverExtensions::HasDebugger,
31
+ DriverExtensions::HasPermissions,
32
+ DriverExtensions::HasWebStorage].freeze
34
33
 
35
34
  def browser
36
35
  :safari
@@ -20,17 +20,17 @@
20
20
  module Selenium
21
21
  module WebDriver
22
22
  module Safari
23
- module Bridge
23
+ module Features
24
24
 
25
25
  # https://developer.apple.com/library/content/documentation/NetworkingInternetWeb/Conceptual/WebDriverEndpointDoc/Commands/Commands.html
26
- COMMANDS = {
26
+ SAFARI_COMMANDS = {
27
27
  get_permissions: [:get, 'session/:session_id/apple/permissions'],
28
28
  set_permissions: [:post, 'session/:session_id/apple/permissions'],
29
29
  attach_debugger: [:post, 'session/:session_id/apple/attach_debugger']
30
30
  }.freeze
31
31
 
32
32
  def commands(command)
33
- COMMANDS[command] || super
33
+ SAFARI_COMMANDS[command] || self.class::COMMANDS[command]
34
34
  end
35
35
 
36
36
  def permissions
@@ -26,40 +26,8 @@ module Selenium
26
26
  # @see https://developer.apple.com/documentation/webkit/about_webdriver_for_safari
27
27
  CAPABILITIES = {automatic_inspection: 'safari:automaticInspection',
28
28
  automatic_profiling: 'safari:automaticProfiling'}.freeze
29
+ BROWSER = 'safari'
29
30
 
30
- CAPABILITIES.each_key do |key|
31
- define_method key do
32
- @options[key]
33
- end
34
-
35
- define_method "#{key}=" do |value|
36
- @options[key] = value
37
- end
38
- end
39
-
40
- #
41
- # Create a new Options instance for W3C-capable versions of Safari.
42
- #
43
- # @example
44
- # options = Selenium::WebDriver::Safari::Options.new(automatic_inspection: true)
45
- # driver = Selenium::WebDriver.for :safari, options: options
46
- #
47
- # @param [Hash] opts the pre-defined options to create the Safari::Options with
48
- # @option opts [Boolean] :automatic_inspection Preloads Web Inspector and JavaScript debugger. Default is false
49
- # @option opts [Boolean] :automatic_profiling Preloads Web Inspector and starts a timeline recording. Default is false
50
- #
51
-
52
- def initialize(**opts)
53
- super
54
- end
55
-
56
- #
57
- # @api private
58
- #
59
-
60
- def as_json(*)
61
- generate_as_json(super)
62
- end
63
31
  end # Options
64
32
  end # Safari
65
33
  end # WebDriver
@@ -25,7 +25,7 @@ module Selenium
25
25
  @callback = callback
26
26
  end
27
27
 
28
- def method_missing(meth, *args) # rubocop:disable Style/MethodMissingSuper, Style/MissingRespondToMissing
28
+ def method_missing(meth, *args) # rubocop:disable Style/MissingRespondToMissing
29
29
  @callback.call meth, *args
30
30
  end
31
31
  end # BlockEventListener
@@ -72,7 +72,7 @@ module Selenium
72
72
  end
73
73
  end
74
74
 
75
- def self.from_hsl(h, s, l, a) # rubocop:disable Naming/UncommunicativeMethodParamName
75
+ def self.from_hsl(h, s, l, a) # rubocop:disable Naming/MethodParameterName
76
76
  h = Float(h) / 360
77
77
  s = Float(s) / 100
78
78
  l = Float(l) / 100
@@ -138,7 +138,7 @@ module Selenium
138
138
  end
139
139
 
140
140
  def hex
141
- format '#%02x%02x%02x', red, green, blue
141
+ format '#%<red>02x%<green>02x%<blue>02x', red: red, green: green, blue: blue
142
142
  end
143
143
  end # Color
144
144
  end # Support
@@ -120,7 +120,7 @@ module Selenium
120
120
  returned
121
121
  end
122
122
 
123
- def method_missing(meth, *args, &blk) # rubocop:disable Style/MethodMissingSuper, Style/MissingRespondToMissing
123
+ def method_missing(meth, *args, &blk) # rubocop:disable Style/MissingRespondToMissing
124
124
  @delegate.__send__(meth, *args, &blk)
125
125
  end
126
126
  end # EventFiringBridge
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Licensed to the Software Freedom Conservancy (SFC) under one
4
+ # or more contributor license agreements. See the NOTICE file
5
+ # distributed with this work for additional information
6
+ # regarding copyright ownership. The SFC licenses this file
7
+ # to you under the Apache License, Version 2.0 (the
8
+ # "License"); you may not use this file except in compliance
9
+ # with the License. You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing,
14
+ # software distributed under the License is distributed on an
15
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
+ # KIND, either express or implied. See the License for the
17
+ # specific language governing permissions and limitations
18
+ # under the License.
19
+
20
+ require_relative 'guards/guard_condition'
21
+ require_relative 'guards/guard'
22
+
23
+ module Selenium
24
+ module WebDriver
25
+ module Support
26
+ class Guards
27
+ GUARD_TYPES = %i[except only exclude exclusive].freeze
28
+
29
+ attr_reader :messages
30
+ attr_accessor :bug_tracker
31
+
32
+ def initialize(example, bug_tracker: '', conditions: nil)
33
+ @example = example
34
+ @bug_tracker = bug_tracker
35
+ @guard_conditions = conditions || []
36
+ @guards = collect_example_guards
37
+ @messages = {}
38
+ end
39
+
40
+ def add_condition(name, condition = nil, &blk)
41
+ @guard_conditions << GuardCondition.new(name, condition, &blk)
42
+ end
43
+
44
+ def add_message(name, message)
45
+ @messages[name] = message
46
+ end
47
+
48
+ def disposition
49
+ if !skipping_guard.nil?
50
+ [:skip, skipping_guard.message]
51
+ elsif !pending_guard.nil? && ENV['SKIP_PENDING']
52
+ [:skip, pending_guard.message]
53
+ elsif !pending_guard.nil?
54
+ [:pending, pending_guard.message]
55
+ end
56
+ end
57
+
58
+ def satisfied?(guard)
59
+ @guard_conditions.all? { |condition| condition.satisfied?(guard) }
60
+ end
61
+
62
+ private
63
+
64
+ def collect_example_guards
65
+ guards = []
66
+
67
+ GUARD_TYPES.each do |guard_type|
68
+ example_group = @example.metadata[:example_group]
69
+ example_guards = [@example.metadata[guard_type], example_group[guard_type]]
70
+ while example_group[:parent_example_group]
71
+ example_group = example_group[:parent_example_group]
72
+ example_guards << example_group[guard_type]
73
+ end
74
+
75
+ example_guards.flatten.uniq.compact.each do |example_guard|
76
+ guards << Guard.new(example_guard, guard_type, self)
77
+ end
78
+ end
79
+
80
+ guards
81
+ end
82
+
83
+ def skipping_guard
84
+ @guards.select(&:exclusive?).find { |guard| !satisfied?(guard) } ||
85
+ @guards.select(&:exclude?).find { |guard| satisfied?(guard) }
86
+ end
87
+
88
+ def pending_guard
89
+ @guards.select(&:except?).find { |guard| satisfied?(guard) } ||
90
+ @guards.select(&:only?).find { |guard| !satisfied?(guard) }
91
+ end
92
+ end # Guards
93
+ end # Support
94
+ end # WebDriver
95
+ end # Selenium