selenium-webdriver 4.0.0.alpha2 → 4.0.0

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.
Files changed (113) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGES +338 -4
  3. data/Gemfile +3 -1
  4. data/LICENSE +1 -1
  5. data/NOTICE +2 -0
  6. data/README.md +4 -5
  7. data/lib/selenium/server.rb +21 -29
  8. data/lib/selenium/webdriver/atoms/findElements.js +122 -0
  9. data/lib/selenium/webdriver/atoms/getAttribute.js +100 -7
  10. data/lib/selenium/webdriver/atoms/isDisplayed.js +76 -78
  11. data/lib/selenium/webdriver/atoms/mutationListener.js +55 -0
  12. data/lib/selenium/webdriver/chrome/driver.rb +26 -56
  13. data/lib/selenium/webdriver/chrome/features.rb +106 -0
  14. data/lib/selenium/webdriver/chrome/options.rb +127 -52
  15. data/lib/selenium/webdriver/chrome/profile.rb +8 -5
  16. data/lib/selenium/webdriver/chrome/service.rb +4 -6
  17. data/lib/selenium/webdriver/chrome.rb +10 -9
  18. data/lib/selenium/webdriver/common/driver.rb +110 -19
  19. data/lib/selenium/webdriver/common/driver_extensions/full_page_screenshot.rb +43 -0
  20. data/lib/selenium/webdriver/common/driver_extensions/has_apple_permissions.rb +51 -0
  21. data/lib/selenium/webdriver/common/driver_extensions/has_authentication.rb +89 -0
  22. data/lib/selenium/webdriver/common/driver_extensions/has_casting.rb +77 -0
  23. data/lib/selenium/webdriver/common/driver_extensions/has_cdp.rb +38 -0
  24. data/lib/selenium/webdriver/common/driver_extensions/has_context.rb +45 -0
  25. data/lib/selenium/webdriver/common/driver_extensions/has_devtools.rb +43 -0
  26. data/lib/selenium/webdriver/common/driver_extensions/has_launching.rb +38 -0
  27. data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +5 -8
  28. data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +144 -0
  29. data/lib/selenium/webdriver/common/driver_extensions/has_logs.rb +30 -0
  30. data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +17 -0
  31. data/lib/selenium/webdriver/common/driver_extensions/has_network_connection.rb +6 -27
  32. data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +136 -0
  33. data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +11 -11
  34. data/lib/selenium/webdriver/common/driver_extensions/has_pinned_scripts.rb +77 -0
  35. data/lib/selenium/webdriver/common/driver_extensions/has_remote_status.rb +1 -0
  36. data/lib/selenium/webdriver/common/driver_extensions/{rotatable.rb → prints_page.rb} +18 -20
  37. data/lib/selenium/webdriver/common/element.rb +79 -16
  38. data/lib/selenium/webdriver/common/error.rb +12 -0
  39. data/lib/selenium/webdriver/common/interactions/interaction.rb +4 -1
  40. data/lib/selenium/webdriver/common/log_entry.rb +2 -2
  41. data/lib/selenium/webdriver/common/logger.rb +50 -15
  42. data/lib/selenium/webdriver/common/manager.rb +14 -14
  43. data/lib/selenium/webdriver/common/options.rb +186 -0
  44. data/lib/selenium/webdriver/common/platform.rb +6 -1
  45. data/lib/selenium/webdriver/common/port_prober.rb +4 -6
  46. data/lib/selenium/webdriver/common/profile_helper.rb +10 -2
  47. data/lib/selenium/webdriver/common/proxy.rb +6 -3
  48. data/lib/selenium/webdriver/common/search_context.rb +7 -3
  49. data/lib/selenium/webdriver/common/service.rb +23 -113
  50. data/lib/selenium/webdriver/common/service_manager.rb +151 -0
  51. data/lib/selenium/webdriver/common/shadow_root.rb +87 -0
  52. data/lib/selenium/webdriver/common/socket_lock.rb +2 -2
  53. data/lib/selenium/webdriver/common/takes_screenshot.rb +66 -0
  54. data/lib/selenium/webdriver/common/target_locator.rb +32 -4
  55. data/lib/selenium/webdriver/common/timeouts.rb +31 -4
  56. data/lib/selenium/webdriver/common/wait.rb +1 -1
  57. data/lib/selenium/webdriver/common/window.rb +0 -4
  58. data/lib/selenium/webdriver/common.rb +17 -2
  59. data/lib/selenium/webdriver/devtools/console_event.rb +38 -0
  60. data/lib/selenium/webdriver/devtools/exception_event.rb +36 -0
  61. data/lib/selenium/webdriver/devtools/mutation_event.rb +37 -0
  62. data/lib/selenium/webdriver/{chrome/bridge.rb → devtools/pinned_script.rb} +26 -17
  63. data/lib/selenium/webdriver/devtools/request.rb +67 -0
  64. data/lib/selenium/webdriver/devtools/response.rb +66 -0
  65. data/lib/selenium/webdriver/devtools.rb +182 -0
  66. data/lib/selenium/webdriver/edge/driver.rb +5 -31
  67. data/lib/selenium/webdriver/edge/features.rb +44 -0
  68. data/lib/selenium/webdriver/edge/options.rb +11 -48
  69. data/lib/selenium/webdriver/edge/profile.rb +33 -0
  70. data/lib/selenium/webdriver/edge/service.rb +9 -24
  71. data/lib/selenium/webdriver/edge.rb +11 -13
  72. data/lib/selenium/webdriver/firefox/driver.rb +20 -30
  73. data/lib/selenium/webdriver/firefox/extension.rb +8 -0
  74. data/lib/selenium/webdriver/firefox/{bridge.rb → features.rb} +23 -4
  75. data/lib/selenium/webdriver/firefox/options.rb +70 -49
  76. data/lib/selenium/webdriver/firefox/profile.rb +16 -77
  77. data/lib/selenium/webdriver/firefox/service.rb +1 -5
  78. data/lib/selenium/webdriver/firefox.rb +22 -16
  79. data/lib/selenium/webdriver/ie/driver.rb +1 -34
  80. data/lib/selenium/webdriver/ie/options.rb +13 -44
  81. data/lib/selenium/webdriver/ie/service.rb +9 -11
  82. data/lib/selenium/webdriver/ie.rb +8 -7
  83. data/lib/selenium/webdriver/remote/bridge.rb +112 -86
  84. data/lib/selenium/webdriver/remote/capabilities.rb +120 -62
  85. data/lib/selenium/webdriver/remote/commands.rb +7 -0
  86. data/lib/selenium/webdriver/remote/driver.rb +15 -12
  87. data/lib/selenium/webdriver/remote/http/common.rb +0 -5
  88. data/lib/selenium/webdriver/remote/http/default.rb +17 -11
  89. data/lib/selenium/webdriver/remote/http/persistent.rb +11 -6
  90. data/lib/selenium/webdriver/remote.rb +15 -9
  91. data/lib/selenium/webdriver/safari/driver.rb +3 -34
  92. data/lib/selenium/webdriver/safari/{bridge.rb → features.rb} +6 -6
  93. data/lib/selenium/webdriver/safari/options.rb +10 -29
  94. data/lib/selenium/webdriver/safari/service.rb +0 -4
  95. data/lib/selenium/webdriver/safari.rb +16 -8
  96. data/lib/selenium/webdriver/support/block_event_listener.rb +1 -1
  97. data/lib/selenium/webdriver/support/cdp/domain.rb.erb +63 -0
  98. data/lib/selenium/webdriver/support/cdp_client_generator.rb +108 -0
  99. data/lib/selenium/webdriver/support/color.rb +2 -2
  100. data/lib/selenium/webdriver/support/event_firing_bridge.rb +4 -4
  101. data/lib/selenium/webdriver/support/guards/guard.rb +89 -0
  102. data/lib/selenium/webdriver/support/guards/guard_condition.rb +52 -0
  103. data/lib/selenium/webdriver/support/guards.rb +95 -0
  104. data/lib/selenium/webdriver/support/relative_locator.rb +51 -0
  105. data/lib/selenium/webdriver/support/select.rb +2 -2
  106. data/lib/selenium/webdriver/support.rb +1 -0
  107. data/lib/selenium/webdriver/version.rb +1 -1
  108. data/lib/selenium/webdriver.rb +10 -8
  109. data/selenium-webdriver.gemspec +29 -13
  110. metadata +125 -51
  111. data/lib/selenium/webdriver/common/driver_extensions/takes_screenshot.rb +0 -64
  112. data/lib/selenium/webdriver/firefox/binary.rb +0 -110
  113. data/lib/selenium/webdriver/firefox/extension/prefs.json +0 -69
@@ -17,20 +17,28 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
- require 'selenium/webdriver/safari/bridge'
21
- require 'selenium/webdriver/safari/driver'
22
- require 'selenium/webdriver/safari/options'
23
-
24
20
  module Selenium
25
21
  module WebDriver
26
22
  module Safari
23
+ autoload :Features, 'selenium/webdriver/safari/features'
24
+ autoload :Driver, 'selenium/webdriver/safari/driver'
25
+ autoload :Options, 'selenium/webdriver/safari/options'
26
+ autoload :Service, 'selenium/webdriver/safari/service'
27
+
27
28
  class << self
29
+ attr_accessor :use_technology_preview
30
+
28
31
  def technology_preview
29
32
  "/Applications/Safari\ Technology\ Preview.app/Contents/MacOS/safaridriver"
30
33
  end
31
34
 
32
35
  def technology_preview!
33
36
  Service.driver_path = technology_preview
37
+ @use_technology_preview = true
38
+ end
39
+
40
+ def technology_preview?
41
+ use_technology_preview
34
42
  end
35
43
 
36
44
  def path=(path)
@@ -48,18 +56,18 @@ module Selenium
48
56
 
49
57
  def driver_path=(path)
50
58
  WebDriver.logger.deprecate 'Selenium::WebDriver::Safari#driver_path=',
51
- 'Selenium::WebDriver::Safari::Service#driver_path='
59
+ 'Selenium::WebDriver::Safari::Service#driver_path=',
60
+ id: :driver_path
52
61
  Selenium::WebDriver::Safari::Service.driver_path = path
53
62
  end
54
63
 
55
64
  def driver_path
56
65
  WebDriver.logger.deprecate 'Selenium::WebDriver::Safari#driver_path',
57
- 'Selenium::WebDriver::Safari::Service#driver_path'
66
+ 'Selenium::WebDriver::Safari::Service#driver_path',
67
+ id: :driver_path
58
68
  Selenium::WebDriver::Safari::Service.driver_path
59
69
  end
60
70
  end
61
71
  end # Safari
62
72
  end # WebDriver
63
73
  end # Selenium
64
-
65
- require 'selenium/webdriver/safari/service'
@@ -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
@@ -0,0 +1,63 @@
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
+ # This file is automatically generated. Any changes will be lost!
21
+ module Selenium
22
+ module DevTools
23
+ module <%= version %>
24
+ class <%= domain[:domain] %>
25
+ <% if domain[:events] %>
26
+ EVENTS = {
27
+ <% domain[:events].each do |event| %>
28
+ <%= h.snake_case(event[:name]) %>: '<%= event[:name] %>',
29
+ <% end %>
30
+ }.freeze
31
+ <% end %>
32
+
33
+ def initialize(devtools)
34
+ @devtools = devtools
35
+ end
36
+
37
+ def on(event, &block)
38
+ event = EVENTS[event] if event.is_a?(Symbol)
39
+ @devtools.callbacks["<%= domain[:domain] %>.#{event}"] << block
40
+ end
41
+
42
+ <% domain[:commands].each do |command| %>
43
+ <% if command[:parameters] %>
44
+ def <%= h.snake_case(command[:name]) %>(<%= h.kwargs(command[:parameters]) %>)
45
+ <% else %>
46
+ def <%= h.snake_case(command[:name]) %>
47
+ <% end %>
48
+ <% if command[:parameters] %>
49
+ @devtools.send_cmd('<%= domain[:domain] %>.<%= command[:name] %>',
50
+ <% until command[:parameters].empty? %>
51
+ <% parameter = command[:parameters].shift %>
52
+ <%= parameter[:name] %>: <%= h.snake_case(parameter[:name]) %><%= command[:parameters].empty? ? ')' : ',' %>
53
+ <% end %>
54
+ <% else %>
55
+ @devtools.send_cmd('<%= domain[:domain] %>.<%= command[:name] %>')
56
+ <% end %>
57
+ end
58
+
59
+ <% end %>
60
+ end # <%= domain[:domain] %>
61
+ end # <%= version %>
62
+ end # DevTools
63
+ end # Selenium
@@ -0,0 +1,108 @@
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 'erb'
21
+ require 'fileutils'
22
+ require 'json'
23
+
24
+ module Selenium
25
+ module WebDriver
26
+ module Support
27
+ class CDPClientGenerator
28
+ # Input JSON files are generated from PDL tasks.
29
+ TEMPLATE_PATH = File.expand_path('cdp/domain.rb.erb', __dir__)
30
+
31
+ RESERVED_KEYWORDS = %w[end].freeze
32
+
33
+ def call(output_dir:, version:, browser_protocol_path: nil, js_protocol_path: nil, loader_path: nil, **)
34
+ @template = ERB.new(File.read(TEMPLATE_PATH))
35
+ @output_dir = output_dir
36
+ @loader_path = loader_path || "#{@output_dir}.rb"
37
+ @version = version
38
+
39
+ browser_protocol_path ||= File.expand_path('cdp/browser_protocol.json', __dir__)
40
+ js_protocol_path ||= File.expand_path('cdp/js_protocol.json', __dir__)
41
+
42
+ browser_protocol = JSON.parse(File.read(browser_protocol_path), symbolize_names: true)
43
+ js_protocol = JSON.parse(File.read(js_protocol_path), symbolize_names: true)
44
+
45
+ FileUtils.mkdir_p(@output_dir)
46
+
47
+ browser_protocol[:domains].each(&method(:process_domain))
48
+ js_protocol[:domains].each(&method(:process_domain))
49
+ require_file
50
+ end
51
+
52
+ def process_domain(domain)
53
+ result = @template.result_with_hash(domain: domain, version: @version.upcase, h: self)
54
+ filename = File.join(@output_dir, "#{snake_case(domain[:domain])}.rb")
55
+ File.write(filename, remove_empty_lines(result))
56
+ end
57
+
58
+ def snake_case(string)
59
+ name = string.gsub('JavaScript', 'Javascript')
60
+ .gsub(/([A-Z]+)([A-Z][a-z]{2,})/, '\1_\2')
61
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
62
+ .downcase
63
+ # Certain CDP parameters conflict with Ruby keywords
64
+ # so we prefix the name with underscore.
65
+ name = "_#{name}" if RESERVED_KEYWORDS.include?(name)
66
+
67
+ name
68
+ end
69
+
70
+ def kwargs(parameters)
71
+ parameters = parameters.map do |parameter|
72
+ if parameter[:optional]
73
+ "#{snake_case(parameter[:name])}: nil"
74
+ else
75
+ "#{snake_case(parameter[:name])}:"
76
+ end
77
+ end
78
+ parameters.join(', ')
79
+ end
80
+
81
+ def remove_empty_lines(string)
82
+ string.split("\n").reject { |l| l =~ /^\s+$/ }.join("\n")
83
+ end
84
+
85
+ def require_file
86
+ # rubocop:disable Lint/InterpolationCheck
87
+ dynamic_location = '#{File.dirname(File.absolute_path(__FILE__))}'
88
+ # rubocop:enable Lint/InterpolationCheck
89
+
90
+ require_all = "Dir.glob(\"#{dynamic_location}/#{@version}/*\", &method(:require))"
91
+ File.open(@loader_path, 'w') { |file| file.write(require_all) }
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
97
+
98
+ if $PROGRAM_NAME == __FILE__
99
+ browser_protocol_path, js_protocol_path, output_dir, loader_path, version = *ARGV
100
+
101
+ Selenium::WebDriver::Support::CDPClientGenerator.new.call(
102
+ browser_protocol_path: browser_protocol_path,
103
+ js_protocol_path: js_protocol_path,
104
+ output_dir: output_dir,
105
+ loader_path: loader_path,
106
+ version: version
107
+ )
108
+ end
@@ -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
@@ -76,7 +76,7 @@ module Selenium
76
76
  @delegate.find_element_by how, what, parent
77
77
  end
78
78
 
79
- Element.new self, e.ref
79
+ Element.new self, e.ref.last
80
80
  end
81
81
 
82
82
  def find_elements_by(how, what, parent = nil)
@@ -84,7 +84,7 @@ module Selenium
84
84
  @delegate.find_elements_by(how, what, parent)
85
85
  end
86
86
 
87
- es.map { |e| Element.new self, e.ref }
87
+ es.map { |e| Element.new self, e.ref.last }
88
88
  end
89
89
 
90
90
  def execute_script(script, *args)
@@ -109,7 +109,7 @@ module Selenium
109
109
  end
110
110
 
111
111
  def driver
112
- @driver ||= Driver.new(self)
112
+ @driver ||= Driver.new(bridge: self)
113
113
  end
114
114
 
115
115
  def dispatch(name, *args)
@@ -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,89 @@
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
+ module Selenium
21
+ module WebDriver
22
+ module Support
23
+ class Guards
24
+
25
+ #
26
+ # Guard derived from RSpec example metadata.
27
+ # @api private
28
+ #
29
+
30
+ class Guard
31
+
32
+ attr_reader :guarded, :type, :messages, :reason
33
+
34
+ def initialize(guarded, type, guards = nil)
35
+ @guarded = guarded
36
+ @tracker = guards&.bug_tracker || ''
37
+ @messages = guards&.messages || {}
38
+ @messages[:unknown] = 'TODO: Investigate why this is failing and file a bug report'
39
+ @type = type
40
+
41
+ @reason = @guarded.delete(:reason)
42
+ end
43
+
44
+ def message
45
+ details = case @reason
46
+ when Integer
47
+ "Bug Filed: #{@tracker}/#{@reason}"
48
+ when Symbol
49
+ @messages[@reason]
50
+ when String
51
+ @reason
52
+ else
53
+ 'no reason given'
54
+ end
55
+
56
+ case @type
57
+ when :exclude
58
+ "Test not guarded because it breaks test run; #{details}"
59
+ when :exclusive
60
+ "Test does not apply to this configuration; #{details}"
61
+ else
62
+ "Test guarded; #{details}"
63
+ end
64
+ end
65
+
66
+ # Bug is present on all configurations specified
67
+ def except?
68
+ @type == :except
69
+ end
70
+
71
+ # Bug is present on all configurations not specified
72
+ def only?
73
+ @type == :only
74
+ end
75
+
76
+ # Bug is present on all configurations specified, but test can not be run because it breaks other tests
77
+ def exclude?
78
+ @type == :exclude
79
+ end
80
+
81
+ # Test only applies to configurations specified
82
+ def exclusive?
83
+ @type == :exclusive
84
+ end
85
+ end # Guard
86
+ end # Guards
87
+ end # Support
88
+ end # WebDriver
89
+ end # Selenium
@@ -0,0 +1,52 @@
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
+ module Selenium
21
+ module WebDriver
22
+ module Support
23
+ class Guards
24
+
25
+ #
26
+ # Guard derived from RSpec example metadata.
27
+ # @api private
28
+ #
29
+
30
+ class GuardCondition
31
+ attr_accessor :name, :execution
32
+
33
+ def initialize(name, condition = nil, &blk)
34
+ @name = name
35
+ @execution = if block_given?
36
+ proc(&blk)
37
+ else
38
+ proc { |guarded| guarded.include?(condition) }
39
+ end
40
+ end
41
+
42
+ def satisfied?(guard)
43
+ list = Array(guard.guarded[@name])
44
+
45
+ list.empty? || @execution.call(list)
46
+ end
47
+
48
+ end # GuardCondition
49
+ end # Guards
50
+ end # Support
51
+ end # WebDriver
52
+ end # Selenium
@@ -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
@@ -0,0 +1,51 @@
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
+ module Selenium
21
+ module WebDriver
22
+ module Support
23
+
24
+ #
25
+ # @api private
26
+ #
27
+
28
+ class RelativeLocator
29
+ KEYS = %w[above below left right near distance].freeze
30
+
31
+ def initialize(locator)
32
+ @filters, @root = locator.partition { |how, _| KEYS.include?(how) }.map(&:to_h)
33
+ end
34
+
35
+ def as_json
36
+ {
37
+ relative: {
38
+ root: @root,
39
+ filters: @filters.map do |kind, filter|
40
+ {
41
+ kind: kind,
42
+ args: [filter]
43
+ }
44
+ end
45
+ }
46
+ }
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -31,7 +31,7 @@ module Selenium
31
31
  raise ArgumentError, "unexpected tag name #{tag_name.inspect}" unless tag_name.casecmp('select').zero?
32
32
 
33
33
  @element = element
34
- @multi = ![nil, 'false'].include?(element.attribute(:multiple))
34
+ @multi = ![nil, 'false'].include?(element.dom_attribute(:multiple))
35
35
  end
36
36
 
37
37
  #
@@ -258,7 +258,7 @@ module Selenium
258
258
  end
259
259
 
260
260
  def find_by_index(index)
261
- options.select { |option| option.attribute(:index) == index.to_s }
261
+ options.select { |option| option.dom_attribute(:index) == index.to_s }
262
262
  end
263
263
 
264
264
  def find_by_value(value)
@@ -23,3 +23,4 @@ require 'selenium/webdriver/support/block_event_listener'
23
23
  require 'selenium/webdriver/support/escaper'
24
24
  require 'selenium/webdriver/support/select'
25
25
  require 'selenium/webdriver/support/color'
26
+ require 'selenium/webdriver/support/relative_locator'
@@ -19,6 +19,6 @@
19
19
 
20
20
  module Selenium
21
21
  module WebDriver
22
- VERSION = '4.0.0.alpha2'
22
+ VERSION = '4.0.0'
23
23
  end # WebDriver
24
24
  end # Selenium
@@ -23,9 +23,10 @@ require 'fileutils'
23
23
  require 'date'
24
24
  require 'json'
25
25
  require 'set'
26
+ require 'uri'
26
27
 
27
- require 'selenium/webdriver/common'
28
28
  require 'selenium/webdriver/atoms'
29
+ require 'selenium/webdriver/common'
29
30
  require 'selenium/webdriver/version'
30
31
 
31
32
  module Selenium
@@ -35,13 +36,14 @@ module Selenium
35
36
  Rectangle = Struct.new(:x, :y, :width, :height)
36
37
  Location = Struct.new(:latitude, :longitude, :altitude)
37
38
 
38
- autoload :Chrome, 'selenium/webdriver/chrome'
39
- autoload :Edge, 'selenium/webdriver/edge'
40
- autoload :Firefox, 'selenium/webdriver/firefox'
41
- autoload :IE, 'selenium/webdriver/ie'
42
- autoload :Remote, 'selenium/webdriver/remote'
43
- autoload :Safari, 'selenium/webdriver/safari'
44
- autoload :Support, 'selenium/webdriver/support'
39
+ autoload :Chrome, 'selenium/webdriver/chrome'
40
+ autoload :DevTools, 'selenium/webdriver/devtools'
41
+ autoload :Edge, 'selenium/webdriver/edge'
42
+ autoload :Firefox, 'selenium/webdriver/firefox'
43
+ autoload :IE, 'selenium/webdriver/ie'
44
+ autoload :Remote, 'selenium/webdriver/remote'
45
+ autoload :Safari, 'selenium/webdriver/safari'
46
+ autoload :Support, 'selenium/webdriver/support'
45
47
 
46
48
  # @api private
47
49