selenium-webdriver 3.142.7 → 4.0.3

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 (137) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGES +350 -5
  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 +69 -63
  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 -83
  13. data/lib/selenium/webdriver/chrome/{bridge.rb → features.rb} +50 -12
  14. data/lib/selenium/webdriver/chrome/options.rb +129 -58
  15. data/lib/selenium/webdriver/chrome/profile.rb +6 -3
  16. data/lib/selenium/webdriver/chrome/service.rb +8 -15
  17. data/lib/selenium/webdriver/chrome.rb +10 -9
  18. data/lib/selenium/webdriver/common/action_builder.rb +97 -249
  19. data/lib/selenium/webdriver/common/driver.rb +112 -23
  20. data/lib/selenium/webdriver/common/driver_extensions/full_page_screenshot.rb +43 -0
  21. data/lib/selenium/webdriver/common/driver_extensions/has_apple_permissions.rb +51 -0
  22. data/lib/selenium/webdriver/common/driver_extensions/has_authentication.rb +89 -0
  23. data/lib/selenium/webdriver/common/driver_extensions/has_casting.rb +77 -0
  24. data/lib/selenium/webdriver/common/driver_extensions/{has_touch_screen.rb → has_cdp.rb} +10 -8
  25. data/lib/selenium/webdriver/common/driver_extensions/has_context.rb +45 -0
  26. data/lib/selenium/webdriver/{firefox/util.rb → common/driver_extensions/has_devtools.rb} +16 -19
  27. data/lib/selenium/webdriver/common/driver_extensions/has_launching.rb +38 -0
  28. data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +5 -8
  29. data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +144 -0
  30. data/lib/selenium/webdriver/common/driver_extensions/has_logs.rb +30 -0
  31. data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +17 -0
  32. data/lib/selenium/webdriver/common/driver_extensions/has_network_connection.rb +6 -27
  33. data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +136 -0
  34. data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +11 -11
  35. data/lib/selenium/webdriver/common/driver_extensions/has_pinned_scripts.rb +77 -0
  36. data/lib/selenium/webdriver/common/driver_extensions/has_remote_status.rb +1 -0
  37. data/lib/selenium/webdriver/common/driver_extensions/{rotatable.rb → prints_page.rb} +18 -20
  38. data/lib/selenium/webdriver/common/element.rb +82 -22
  39. data/lib/selenium/webdriver/common/error.rb +32 -196
  40. data/lib/selenium/webdriver/common/interactions/interaction.rb +4 -1
  41. data/lib/selenium/webdriver/common/interactions/key_actions.rb +5 -5
  42. data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +13 -13
  43. data/lib/selenium/webdriver/common/log_entry.rb +2 -2
  44. data/lib/selenium/webdriver/common/logger.rb +50 -15
  45. data/lib/selenium/webdriver/common/manager.rb +15 -15
  46. data/lib/selenium/webdriver/common/options.rb +154 -23
  47. data/lib/selenium/webdriver/common/platform.rb +6 -1
  48. data/lib/selenium/webdriver/common/port_prober.rb +4 -6
  49. data/lib/selenium/webdriver/common/profile_helper.rb +11 -9
  50. data/lib/selenium/webdriver/common/proxy.rb +6 -3
  51. data/lib/selenium/webdriver/common/search_context.rb +7 -3
  52. data/lib/selenium/webdriver/common/service.rb +17 -125
  53. data/lib/selenium/webdriver/common/service_manager.rb +151 -0
  54. data/lib/selenium/webdriver/common/shadow_root.rb +87 -0
  55. data/lib/selenium/webdriver/common/socket_lock.rb +2 -2
  56. data/lib/selenium/webdriver/common/socket_poller.rb +2 -2
  57. data/lib/selenium/webdriver/common/takes_screenshot.rb +66 -0
  58. data/lib/selenium/webdriver/common/target_locator.rb +32 -4
  59. data/lib/selenium/webdriver/common/timeouts.rb +31 -4
  60. data/lib/selenium/webdriver/common/wait.rb +1 -1
  61. data/lib/selenium/webdriver/common/window.rb +0 -4
  62. data/lib/selenium/webdriver/common/zipper.rb +1 -9
  63. data/lib/selenium/webdriver/common.rb +23 -17
  64. data/lib/selenium/webdriver/devtools/console_event.rb +38 -0
  65. data/lib/selenium/webdriver/devtools/exception_event.rb +36 -0
  66. data/lib/selenium/webdriver/devtools/mutation_event.rb +37 -0
  67. data/lib/selenium/webdriver/devtools/pinned_script.rb +59 -0
  68. data/lib/selenium/webdriver/devtools/request.rb +67 -0
  69. data/lib/selenium/webdriver/devtools/response.rb +66 -0
  70. data/lib/selenium/webdriver/devtools.rb +182 -0
  71. data/lib/selenium/webdriver/edge/driver.rb +7 -29
  72. data/lib/selenium/webdriver/edge/features.rb +44 -0
  73. data/lib/selenium/webdriver/edge/options.rb +11 -48
  74. data/lib/selenium/webdriver/{common/w3c_manager.rb → edge/profile.rb} +7 -19
  75. data/lib/selenium/webdriver/edge/service.rb +10 -26
  76. data/lib/selenium/webdriver/edge.rb +11 -14
  77. data/lib/selenium/webdriver/firefox/driver.rb +31 -19
  78. data/lib/selenium/webdriver/firefox/extension.rb +8 -0
  79. data/lib/selenium/webdriver/firefox/features.rb +66 -0
  80. data/lib/selenium/webdriver/firefox/options.rb +70 -49
  81. data/lib/selenium/webdriver/firefox/profile.rb +21 -71
  82. data/lib/selenium/webdriver/firefox/service.rb +5 -9
  83. data/lib/selenium/webdriver/firefox.rb +22 -20
  84. data/lib/selenium/webdriver/ie/driver.rb +1 -47
  85. data/lib/selenium/webdriver/ie/options.rb +13 -44
  86. data/lib/selenium/webdriver/ie/service.rb +13 -15
  87. data/lib/selenium/webdriver/ie.rb +8 -7
  88. data/lib/selenium/webdriver/remote/bridge.rb +558 -86
  89. data/lib/selenium/webdriver/remote/capabilities.rb +159 -123
  90. data/lib/selenium/webdriver/remote/commands.rb +163 -0
  91. data/lib/selenium/webdriver/remote/driver.rb +22 -12
  92. data/lib/selenium/webdriver/remote/http/common.rb +0 -5
  93. data/lib/selenium/webdriver/remote/http/default.rb +17 -20
  94. data/lib/selenium/webdriver/remote/http/persistent.rb +11 -6
  95. data/lib/selenium/webdriver/remote/response.rb +16 -47
  96. data/lib/selenium/webdriver/remote.rb +15 -13
  97. data/lib/selenium/webdriver/safari/driver.rb +3 -31
  98. data/lib/selenium/webdriver/safari/{bridge.rb → features.rb} +3 -3
  99. data/lib/selenium/webdriver/safari/options.rb +10 -29
  100. data/lib/selenium/webdriver/safari/service.rb +4 -8
  101. data/lib/selenium/webdriver/safari.rb +17 -9
  102. data/lib/selenium/webdriver/support/block_event_listener.rb +1 -1
  103. data/lib/selenium/webdriver/support/cdp/domain.rb.erb +63 -0
  104. data/lib/selenium/webdriver/support/cdp_client_generator.rb +108 -0
  105. data/lib/selenium/webdriver/support/color.rb +2 -2
  106. data/lib/selenium/webdriver/support/event_firing_bridge.rb +4 -4
  107. data/lib/selenium/webdriver/support/guards/guard.rb +89 -0
  108. data/lib/selenium/webdriver/{firefox/marionette/bridge.rb → support/guards/guard_condition.rb} +22 -19
  109. data/lib/selenium/webdriver/support/guards.rb +95 -0
  110. data/lib/selenium/webdriver/support/relative_locator.rb +51 -0
  111. data/lib/selenium/webdriver/support/select.rb +3 -3
  112. data/lib/selenium/webdriver/support.rb +1 -0
  113. data/lib/selenium/webdriver/version.rb +1 -1
  114. data/lib/selenium/webdriver.rb +12 -12
  115. data/selenium-webdriver.gemspec +28 -12
  116. metadata +128 -69
  117. data/lib/selenium/webdriver/common/bridge_helper.rb +0 -82
  118. data/lib/selenium/webdriver/common/driver_extensions/takes_screenshot.rb +0 -64
  119. data/lib/selenium/webdriver/common/keyboard.rb +0 -70
  120. data/lib/selenium/webdriver/common/mouse.rb +0 -89
  121. data/lib/selenium/webdriver/common/touch_action_builder.rb +0 -78
  122. data/lib/selenium/webdriver/common/touch_screen.rb +0 -123
  123. data/lib/selenium/webdriver/common/w3c_action_builder.rb +0 -212
  124. data/lib/selenium/webdriver/edge/bridge.rb +0 -76
  125. data/lib/selenium/webdriver/firefox/binary.rb +0 -187
  126. data/lib/selenium/webdriver/firefox/extension/prefs.json +0 -69
  127. data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
  128. data/lib/selenium/webdriver/firefox/launcher.rb +0 -111
  129. data/lib/selenium/webdriver/firefox/legacy/driver.rb +0 -83
  130. data/lib/selenium/webdriver/firefox/marionette/driver.rb +0 -90
  131. data/lib/selenium/webdriver/firefox/native/linux/amd64/x_ignore_nofocus.so +0 -0
  132. data/lib/selenium/webdriver/firefox/native/linux/x86/x_ignore_nofocus.so +0 -0
  133. data/lib/selenium/webdriver/remote/oss/bridge.rb +0 -594
  134. data/lib/selenium/webdriver/remote/oss/commands.rb +0 -223
  135. data/lib/selenium/webdriver/remote/w3c/bridge.rb +0 -605
  136. data/lib/selenium/webdriver/remote/w3c/capabilities.rb +0 -310
  137. data/lib/selenium/webdriver/remote/w3c/commands.rb +0 -157
@@ -17,40 +17,19 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
+ # TODO: Deprecated; Delete after 4.0 release
20
21
  module Selenium
21
22
  module WebDriver
22
23
  module DriverExtensions
23
24
  module HasNetworkConnection
24
25
  def network_connection_type
25
- connection_value = @bridge.network_connection
26
-
27
- connection_type = values_to_type[connection_value]
28
-
29
- # In case the connection type is not recognized return the
30
- # connection value.
31
- connection_type || connection_value
32
- end
33
-
34
- def network_connection_type=(connection_type)
35
- raise ArgumentError, 'Invalid connection type' unless valid_type? connection_type
36
-
37
- connection_value = type_to_values[connection_type]
38
-
39
- @bridge.network_connection = connection_value
40
- end
41
-
42
- private
43
-
44
- def type_to_values
45
- {airplane_mode: 1, wifi: 2, data: 4, all: 6, none: 0}
46
- end
47
-
48
- def values_to_type
49
- type_to_values.invert
26
+ raise Error::UnsupportedOperationError,
27
+ 'The W3C standard does not currently support getting network connection'
50
28
  end
51
29
 
52
- def valid_type?(type)
53
- type_to_values.key? type
30
+ def network_connection_type=(*)
31
+ raise Error::UnsupportedOperationError,
32
+ 'The W3C standard does not currently support setting network connection'
54
33
  end
55
34
  end # HasNetworkConnection
56
35
  end # DriverExtensions
@@ -0,0 +1,136 @@
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 DriverExtensions
23
+ module HasNetworkInterception
24
+
25
+ #
26
+ # Intercepts requests coming from browser allowing
27
+ # to either pass them through like proxy or provide
28
+ # a stubbed response instead.
29
+ #
30
+ # @example Log requests and pass through
31
+ # driver.intercept do |request, &continue|
32
+ # puts "#{request.method} #{request.url}"
33
+ # continue.call(request)
34
+ # end
35
+ #
36
+ # @example Stub requests for images
37
+ # driver.intercept do |request, &continue|
38
+ # if request.url.match?(/\.png$/)
39
+ # request.url = 'https://upload.wikimedia.org/wikipedia/commons/d/d5/Selenium_Logo.png'
40
+ # end
41
+ # continue.call(request)
42
+ # end
43
+ #
44
+ # @example Log responses and pass through
45
+ # driver.intercept do |request, &continue|
46
+ # continue.call(request) do |response|
47
+ # puts "#{response.code} #{response.body}"
48
+ # end
49
+ # end
50
+ #
51
+ # @example Mutate specific response
52
+ # driver.intercept do |request, &continue|
53
+ # continue.call(request) do |response|
54
+ # response.body << 'Added by Selenium!' if request.url.include?('/myurl')
55
+ # end
56
+ # end
57
+ #
58
+ # @param [Proc] block which is called when request is intercepted
59
+ # @yieldparam [DevTools::Request] request
60
+ # @yieldparam [Proc] continue block which proceeds with the request and optionally yields response
61
+ #
62
+
63
+ def intercept(&block)
64
+ devtools.network.set_cache_disabled(cache_disabled: true)
65
+ devtools.fetch.on(:request_paused) do |params|
66
+ id = params['requestId']
67
+ if params.key?('responseStatusCode') || params.key?('responseErrorReason')
68
+ intercept_response(id, params, &pending_response_requests.delete(id))
69
+ else
70
+ intercept_request(id, params, &block)
71
+ end
72
+ end
73
+ devtools.fetch.enable(patterns: [{requestStage: 'Request'}, {requestStage: 'Response'}])
74
+ end
75
+
76
+ private
77
+
78
+ def pending_response_requests
79
+ @pending_response_requests ||= {}
80
+ end
81
+
82
+ def intercept_request(id, params, &block)
83
+ original = DevTools::Request.from(id, params)
84
+ mutable = DevTools::Request.from(id, params)
85
+
86
+ block.call(mutable) do |&continue| # rubocop:disable Performance/RedundantBlockCall
87
+ pending_response_requests[id] = continue
88
+
89
+ if original == mutable
90
+ devtools.fetch.continue_request(request_id: id)
91
+ else
92
+ devtools.fetch.continue_request(
93
+ request_id: id,
94
+ url: mutable.url,
95
+ method: mutable.method,
96
+ post_data: mutable.post_data,
97
+ headers: mutable.headers.map do |k, v|
98
+ {name: k, value: v}
99
+ end
100
+ )
101
+ end
102
+ end
103
+ end
104
+
105
+ def intercept_response(id, params)
106
+ return devtools.fetch.continue_request(request_id: id) unless block_given?
107
+
108
+ body = fetch_response_body(id)
109
+ original = DevTools::Response.from(id, body, params)
110
+ mutable = DevTools::Response.from(id, body, params)
111
+ yield mutable
112
+
113
+ if original == mutable
114
+ devtools.fetch.continue_request(request_id: id)
115
+ else
116
+ devtools.fetch.fulfill_request(
117
+ request_id: id,
118
+ body: (Base64.strict_encode64(mutable.body) if mutable.body),
119
+ response_code: mutable.code,
120
+ response_headers: mutable.headers.map do |k, v|
121
+ {name: k, value: v}
122
+ end
123
+ )
124
+ end
125
+ end
126
+
127
+ def fetch_response_body(id)
128
+ devtools.fetch.get_response_body(request_id: id).dig('result', 'body')
129
+ rescue Error::WebDriverError
130
+ # CDP fails to get body on certain responses (301) and raises:
131
+ # Can only get response body on requests captured after headers received.
132
+ end
133
+ end # HasNetworkInterception
134
+ end # DriverExtensions
135
+ end # WebDriver
136
+ end # Selenium
@@ -23,26 +23,26 @@ module Selenium
23
23
  module HasPermissions
24
24
 
25
25
  #
26
- # Returns permissions.
26
+ # Set one permission.
27
27
  #
28
- # @return [Hash]
28
+ # @param [String] name which permission to set
29
+ # @param [String] value what to set the permission to
29
30
  #
30
31
 
31
- def permissions
32
- @bridge.permissions
32
+ def add_permission(name, value)
33
+ @bridge.set_permission(name, value)
33
34
  end
34
35
 
35
36
  #
36
- # Sets permissions.
37
+ # Set multiple permissions.
37
38
  #
38
- # @example
39
- # driver.permissions = {'getUserMedia' => true}
40
- #
41
- # @param [Hash<Symbol, Boolean>] permissions
39
+ # @param [Hash] opt key/value pairs to set permissions
42
40
  #
43
41
 
44
- def permissions=(permissions)
45
- @bridge.permissions = permissions
42
+ def add_permissions(opt)
43
+ opt.each do |key, value|
44
+ @bridge.set_permission(key, value)
45
+ end
46
46
  end
47
47
 
48
48
  end # HasPermissions
@@ -0,0 +1,77 @@
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 DriverExtensions
23
+ module HasPinnedScripts
24
+
25
+ #
26
+ # Returns the list of all pinned scripts.
27
+ #
28
+ # @return [Array<DevTools::PinnedScript>]
29
+ #
30
+
31
+ def pinned_scripts
32
+ @pinned_scripts ||= []
33
+ end
34
+
35
+ #
36
+ # Pins JavaScript snippet that is available during the whole
37
+ # session on every page. This allows to store and call
38
+ # scripts without sending them over the wire every time.
39
+ #
40
+ # @example
41
+ # script = driver.pin_script('return window.location.href')
42
+ # driver.execute_script(script)
43
+ # # navigate to a new page
44
+ # driver.execute_script(script)
45
+ #
46
+ # @param [String] script
47
+ # @return [DevTools::PinnedScript]
48
+ #
49
+
50
+ def pin_script(script)
51
+ script = DevTools::PinnedScript.new(script)
52
+ pinned_scripts << script
53
+
54
+ devtools.page.enable
55
+ devtools.runtime.evaluate(expression: script.callable)
56
+ response = devtools.page.add_script_to_evaluate_on_new_document(source: script.callable)
57
+ script.devtools_identifier = response.dig('result', 'identifier')
58
+
59
+ script
60
+ end
61
+
62
+ #
63
+ # Unpins script making it undefined for the subsequent calls.
64
+ #
65
+ # @param [DevTools::PinnedScript]
66
+ #
67
+
68
+ def unpin_script(script)
69
+ devtools.runtime.evaluate(expression: script.remove)
70
+ devtools.page.remove_script_to_evaluate_on_new_document(identifier: script.devtools_identifier)
71
+ pinned_scripts.delete(script)
72
+ end
73
+
74
+ end # HasPinnedScripts
75
+ end # DriverExtensions
76
+ end # WebDriver
77
+ end # Selenium
@@ -22,6 +22,7 @@ module Selenium
22
22
  module DriverExtensions
23
23
  module HasRemoteStatus
24
24
  def remote_status
25
+ WebDriver.logger.deprecate('#remote_status', '#status')
25
26
  @bridge.status
26
27
  end
27
28
  end # HasRemoteStatus
@@ -19,43 +19,41 @@
19
19
 
20
20
  module Selenium
21
21
  module WebDriver
22
- #
23
- # @api private
24
- #
25
-
26
22
  module DriverExtensions
27
- module Rotatable
28
- ORIENTATIONS = %i[landscape portrait].freeze
29
-
23
+ module PrintsPage
24
+ #
25
+ # Save a page as a PDF to the given path
30
26
  #
31
- # Change the screen orientation
27
+ # @example Save Printed Page
28
+ # driver.save_print_page('../printed_page.pdf')
32
29
  #
33
- # @param [:landscape, :portrait] orientation
30
+ # @param [String] path to where the pdf should be saved
34
31
  #
35
32
  # @api public
36
33
  #
37
34
 
38
- def rotation=(orientation)
39
- unless ORIENTATIONS.include?(orientation)
40
- raise ArgumentError, "expected #{ORIENTATIONS.inspect}, got #{orientation.inspect}"
35
+ def save_print_page(path, **options)
36
+ File.open(path, 'wb') do |file|
37
+ content = Base64.decode64 print_page(**options)
38
+ file << content
41
39
  end
42
-
43
- bridge.screen_orientation = orientation.to_s.upcase
44
40
  end
45
- alias_method :rotate, :rotation=
46
41
 
47
42
  #
48
- # Get the current screen orientation
43
+ # Return a Base64 encoded Print Page as a string
49
44
  #
50
- # @return [:landscape, :portrait] orientation
45
+ # @see https://w3c.github.io/webdriver/#print-page
51
46
  #
52
47
  # @api public
53
48
  #
54
49
 
55
- def orientation
56
- bridge.screen_orientation.to_sym.downcase
50
+ def print_page(**options)
51
+ options[:pageRanges] = Array(options.delete(:page_ranges)) || []
52
+ options[:shrinkToFit] = options.delete(:shrink_to_fit) { true }
53
+
54
+ @bridge.print_page(options)
57
55
  end
58
- end # Rotatable
56
+ end # PrintsPage
59
57
  end # DriverExtensions
60
58
  end # WebDriver
61
59
  end # Selenium
@@ -20,7 +20,10 @@
20
20
  module Selenium
21
21
  module WebDriver
22
22
  class Element
23
+ ELEMENT_KEY = 'element-6066-11e4-a52e-4f735466cecf'
24
+
23
25
  include SearchContext
26
+ include TakesScreenshot
24
27
 
25
28
  #
26
29
  # Creates a new Element
@@ -89,13 +92,18 @@ module Selenium
89
92
  end
90
93
 
91
94
  #
92
- # Get the value of a the given attribute of the element. Will return the current value, even if
93
- # this has been modified after the page has been loaded. More exactly, this method will return
94
- # the value of the given attribute, unless that attribute is not present, in which case the
95
- # value of the property with the same name is returned. If neither value is set, nil is
96
- # returned. The "style" attribute is converted as best can be to a text representation with a
97
- # trailing semi-colon. The following are deemed to be "boolean" attributes, and will
98
- # return either "true" or "false":
95
+ # This method attempts to provide the most likely desired current value for the attribute
96
+ # of the element, even when that desired value is actually a JavaScript property.
97
+ # It is implemented with a custom JavaScript atom. To obtain the exact value of the attribute or property,
98
+ # use #dom_attribute or #property methods respectively.
99
+ #
100
+ # More exactly, this method will return the value of the property with the given name,
101
+ # if it exists. If it does not, then the value of the attribute with the given name is returned.
102
+ # If neither exists, null is returned.
103
+ #
104
+ # The "style" attribute is converted as best can be to a text representation with a trailing semi-colon.
105
+ #
106
+ # The following are deemed to be "boolean" attributes, and will return either "true" or "false":
99
107
  #
100
108
  # async, autofocus, autoplay, checked, compact, complete, controls, declare, defaultchecked,
101
109
  # defaultselected, defer, disabled, draggable, ended, formnovalidate, hidden, indeterminate,
@@ -103,29 +111,73 @@ module Selenium
103
111
  # nowrap, open, paused, pubdate, readonly, required, reversed, scoped, seamless, seeking,
104
112
  # selected, spellcheck, truespeed, willvalidate
105
113
  #
106
- # Finally, the following commonly mis-capitalized attribute/property names are evaluated as
107
- # expected:
114
+ # Finally, the following commonly mis-capitalized attribute/property names are evaluated as expected:
108
115
  #
109
- # class, readonly
116
+ # When the value of "class" is requested, the "className" property is returned.
117
+ # When the value of "readonly" is requested, the "readOnly" property is returned.
110
118
  #
111
119
  # @param [String] name attribute name
112
120
  # @return [String, nil] attribute value
113
121
  #
122
+ # @see #dom_attribute
123
+ # @see #property
124
+ #
114
125
 
115
126
  def attribute(name)
116
127
  bridge.element_attribute self, name
117
128
  end
118
129
 
119
130
  #
120
- # Get the value of a the given property with the same name of the element. If the value is not
121
- # set, nil is returned.
131
+ # Gets the value of a declared HTML attribute of this element.
132
+ #
133
+ # As opposed to the #attribute method, this method
134
+ # only returns attributes declared in the element's HTML markup.
135
+ #
136
+ # If the attribute is not set, nil is returned.
137
+ #
138
+ # @param [String] name attribute name
139
+ # @return [String, nil] attribute value
140
+ #
141
+ # @see #attribute
142
+ # @see #property
143
+ #
144
+
145
+ def dom_attribute(name)
146
+ bridge.element_dom_attribute @id, name
147
+ end
148
+
149
+ #
150
+ # Gets the value of a JavaScript property of this element
151
+ # This will return the current value,
152
+ # even if this has been modified after the page has been loaded.
153
+ # If the value is not set, nil is returned.
122
154
  #
123
155
  # @param [String] name property name
124
156
  # @return [String, nil] property value
125
157
  #
126
158
 
127
159
  def property(name)
128
- bridge.element_property self, name
160
+ bridge.element_property @id, name
161
+ end
162
+
163
+ #
164
+ # Gets the computed WAI-ARIA role of element
165
+ #
166
+ # @return [String]
167
+ #
168
+
169
+ def aria_role
170
+ bridge.element_aria_role @id
171
+ end
172
+
173
+ #
174
+ # Gets the computed WAI-ARIA label of element.
175
+ #
176
+ # @return [String]
177
+ #
178
+
179
+ def accessible_name
180
+ bridge.element_aria_label @id
129
181
  end
130
182
 
131
183
  #
@@ -265,6 +317,16 @@ module Selenium
265
317
  bridge.element_size @id
266
318
  end
267
319
 
320
+ #
321
+ # Returns the shadow root of an element.
322
+ #
323
+ # @return [WebDriver::ShadowRoot]
324
+ #
325
+
326
+ def shadow_root
327
+ bridge.shadow_root @id
328
+ end
329
+
268
330
  #-------------------------------- sugar --------------------------------
269
331
 
270
332
  #
@@ -284,14 +346,13 @@ module Selenium
284
346
  #
285
347
  alias_method :[], :attribute
286
348
 
287
- #
288
- # for SearchContext and execute_script
289
349
  #
290
350
  # @api private
351
+ # @see SearchContext
291
352
  #
292
353
 
293
354
  def ref
294
- @id
355
+ [:element, @id]
295
356
  end
296
357
 
297
358
  #
@@ -312,12 +373,7 @@ module Selenium
312
373
  #
313
374
 
314
375
  def as_json(*)
315
- key = if bridge.dialect == :w3c
316
- 'element-6066-11e4-a52e-4f735466cecf'
317
- else
318
- 'ELEMENT'
319
- end
320
- @id.is_a?(Hash) ? @id : {key => @id}
376
+ @id.is_a?(Hash) ? @id : {ELEMENT_KEY => @id}
321
377
  end
322
378
 
323
379
  private
@@ -330,6 +386,10 @@ module Selenium
330
386
 
331
387
  tn == 'option' || (tn == 'input' && %w[radio checkbox].include?(type))
332
388
  end
389
+
390
+ def screenshot
391
+ bridge.element_screenshot(@id)
392
+ end
333
393
  end # Element
334
394
  end # WebDriver
335
395
  end # Selenium