selenium-webdriver 4.14.0 → 4.16.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 (32) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +29 -1
  3. data/Gemfile +1 -0
  4. data/bin/linux/selenium-manager +0 -0
  5. data/bin/macos/selenium-manager +0 -0
  6. data/bin/windows/selenium-manager.exe +0 -0
  7. data/lib/selenium/webdriver/atoms/findElements.js +2 -1
  8. data/lib/selenium/webdriver/atoms/isDisplayed.js +2 -1
  9. data/lib/selenium/webdriver/chrome/features.rb +5 -1
  10. data/lib/selenium/webdriver/chromium/features.rb +0 -4
  11. data/lib/selenium/webdriver/common/driver_extensions/has_file_downloads.rb +65 -0
  12. data/lib/selenium/webdriver/common/logger.rb +5 -5
  13. data/lib/selenium/webdriver/common/options.rb +4 -0
  14. data/lib/selenium/webdriver/common/platform.rb +4 -0
  15. data/lib/selenium/webdriver/common/selenium_manager.rb +10 -4
  16. data/lib/selenium/webdriver/common.rb +1 -0
  17. data/lib/selenium/webdriver/edge/features.rb +5 -1
  18. data/lib/selenium/webdriver/firefox/features.rb +5 -1
  19. data/lib/selenium/webdriver/firefox/profile.rb +3 -1
  20. data/lib/selenium/webdriver/ie/features.rb +34 -0
  21. data/lib/selenium/webdriver/ie.rb +4 -3
  22. data/lib/selenium/webdriver/remote/bridge/commands.rb +0 -6
  23. data/lib/selenium/webdriver/remote/bridge.rb +1 -20
  24. data/lib/selenium/webdriver/remote/driver.rb +4 -0
  25. data/lib/selenium/webdriver/remote/features.rb +75 -0
  26. data/lib/selenium/webdriver/remote.rb +1 -0
  27. data/lib/selenium/webdriver/safari/features.rb +5 -1
  28. data/lib/selenium/webdriver/support/event_firing_bridge.rb +2 -2
  29. data/lib/selenium/webdriver/support/guards/guard.rb +6 -3
  30. data/lib/selenium/webdriver/support/guards.rb +1 -1
  31. data/lib/selenium/webdriver/version.rb +1 -1
  32. metadata +5 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dc5fa0275bc4e0f7675b6579bb652cb2efc20bc47797407a3c1da5cd3ac61959
4
- data.tar.gz: 35d845b2fab6603c02c7c6d56f8b2e2e21aa956ed1fcbe01adc0ec0e1b4627d6
3
+ metadata.gz: 7638be962a9b81fc47c44f342971675991879878eb23c46d7f8108e944adc054
4
+ data.tar.gz: 1b0cdd4f1d70fa58950549d92750d1d2836143418c42a868e7809e496f56726e
5
5
  SHA512:
6
- metadata.gz: 61ce01ca9e41da013f55b0a970f3c4fe68e496132fd3f70c7a4770e1874dfdbc3a0102e530cbc01e9e4cfc4dd02614eee6120366471e2e07da9cb0d097222e78
7
- data.tar.gz: 00ebdefe7adc44e8d535a6ab2099ea6233d6a2d9d5c2960a93ac001c34657a7860857e3387c3c93053f034bcccda4dc8120325c105c16bd0ba7151acb8e1211e
6
+ metadata.gz: 5247d707dc2b479973da7154b2bf96c9fefa9f134e56de8ed53fa596345c54a4c249debf357d6bcbc07eb000204bf1e8b4e031c02bb10bc110e346afbf0bf3af
7
+ data.tar.gz: af60275e2063f0ac2247b91bb148b45df2164b02893aeb7a2f21bda8def67d3c95ea620c58f04d5e8faa2561326afbe56903f23b4ff02686c80c84bda0b8746c
data/CHANGES CHANGED
@@ -1,4 +1,32 @@
1
- 4.14.0 (Unreleased)
1
+ 4.16.0 (unreleased)
2
+ =========================
3
+
4
+ Ruby:
5
+ * Add RBS files to Ruby (#12844)
6
+ * Convert binary locations for cygwin (#12618)
7
+ * Allow Selenium Manager to work with Unix (#13161)
8
+ * Extend RBS support for logger and log entry (#13192)
9
+ * Update rules_ruby to the latest version (#13235)
10
+
11
+ BiDi:
12
+ * Released selenium-devtools 0.120.0 (supports CDP v85, v118, v119, v120)
13
+
14
+ Chrome:
15
+ * Fix http proxy configuration for chrome (#13093)
16
+
17
+ Firefox:
18
+ * Delete 'lock' file in FF profile (#13090)
19
+
20
+ 4.15.0 (2023-11-01)
21
+ =========================
22
+
23
+ * Do not set browser binary in selenium manager if it is an empty string (#12738)
24
+ * Add flaky condition to guards to mark unreliable tests
25
+ * Rake update needs to build latest grid for running remote tests
26
+ * Add CDP v119 and remove v116
27
+ * Implement file downloads (#12979)
28
+
29
+ 4.14.0 (2023-10-09)
2
30
  =========================
3
31
  Ruby:
4
32
  * allow users to access the full script of the atom directly
data/Gemfile CHANGED
@@ -6,3 +6,4 @@ Dir["#{__dir__}/*.gemspec"].each do |spec|
6
6
  end
7
7
 
8
8
  gem 'debug', '~> 1.7', require: false, platforms: %i[mri mingw x64_mingw]
9
+ gem 'steep', '~> 1.5.0', require: false, platforms: %i[mri mingw x64_mingw]
Binary file
Binary file
Binary file
@@ -97,7 +97,8 @@ Number(d[1]),c=Number(d[2]),d=Number(d[3]),0<=b&&255>=b&&0<=c&&255>=c&&0<=d&&255
97
97
  function $c(a,b){var c=a.currentStyle||a.style,d=c[b];void 0===d&&ea(c.getPropertyValue)&&(d=c.getPropertyValue(b));return"inherit"!=d?void 0!==d?d:null:(a=Zc(a))?$c(a,b):null}
98
98
  function ad(a,b,c){function d(g){var h=W(g);return 0<h.height&&0<h.width?!0:S(g,"PATH")&&(0<h.height||0<h.width)?(g=V(g,"stroke-width"),!!g&&0<parseInt(g,10)):"hidden"!=V(g,"overflow")&&sa(g.childNodes,function(n){return 3==n.nodeType||S(n)&&d(n)})}function e(g){return bd(g)==X&&ta(g.childNodes,function(h){return!S(h)||e(h)||!d(h)})}if(!S(a))throw Error("Argument to isShown must be of type Element");if(S(a,"BODY"))return!0;if(S(a,"OPTION")||S(a,"OPTGROUP"))return a=lb(a,function(g){return S(g,"SELECT")}),
99
99
  !!a&&ad(a,!0,c);var f=cd(a);if(f)return!!f.image&&0<f.rect.width&&0<f.rect.height&&ad(f.image,b,c);if(S(a,"INPUT")&&"hidden"==a.type.toLowerCase()||S(a,"NOSCRIPT"))return!1;f=V(a,"visibility");return"collapse"!=f&&"hidden"!=f&&c(a)&&(b||0!=dd(a))&&d(a)?!e(a):!1}
100
- function ed(a){function b(c){if(S(c)&&"none"==V(c,"display"))return!1;var d;if((d=c.parentNode)&&d.shadowRoot&&void 0!==c.assignedSlot)d=c.assignedSlot?c.assignedSlot.parentNode:null;else if(c.getDestinationInsertionPoints){var e=c.getDestinationInsertionPoints();0<e.length&&(d=e[e.length-1])}if(Yc&&d instanceof ShadowRoot){if(d.host.shadowRoot!==d)return!1;d=d.host}return!d||9!=d.nodeType&&11!=d.nodeType?d&&S(d,"DETAILS")&&!d.open&&!S(c,"SUMMARY")?!1:!!d&&b(d):!0}return ad(a,!1,b)}var X="hidden";
100
+ function ed(a){function b(c){if(S(c)&&"none"==V(c,"display"))return!1;var d;if((d=c.parentNode)&&d.shadowRoot&&void 0!==c.assignedSlot)d=c.assignedSlot?c.assignedSlot.parentNode:null;else if(c.getDestinationInsertionPoints){var e=c.getDestinationInsertionPoints();0<e.length&&(d=e[e.length-1])}if(Yc&&d instanceof ShadowRoot){if(d.host.shadowRoot&&d.host.shadowRoot!==d)return!1;d=d.host}return!d||9!=d.nodeType&&11!=d.nodeType?d&&S(d,"DETAILS")&&!d.open&&!S(c,"SUMMARY")?!1:!!d&&b(d):!0}return ad(a,!1,
101
+ b)}var X="hidden";
101
102
  function bd(a){function b(m){function v(Ab){if(Ab==g)return!0;var pc=V(Ab,"display");return 0==pc.lastIndexOf("inline",0)||"contents"==pc||"absolute"==qc&&"static"==V(Ab,"position")?!1:!0}var qc=V(m,"position");if("fixed"==qc)return u=!0,m==g?null:g;for(m=Zc(m);m&&!v(m);)m=Zc(m);return m}function c(m){var v=m;if("visible"==n)if(m==g&&h)v=h;else if(m==h)return{x:"visible",y:"visible"};v={x:V(v,"overflow-x"),y:V(v,"overflow-y")};m==g&&(v.x="visible"==v.x?"auto":v.x,v.y="visible"==v.y?"auto":v.y);return v}
102
103
  function d(m){if(m==g){var v=(new fb(f)).a;m=v.scrollingElement?v.scrollingElement:Oa||"CSS1Compat"!=v.compatMode?v.body||v.documentElement:v.documentElement;v=v.parentWindow||v.defaultView;m=t&&Ua("10")&&v.pageYOffset!=m.scrollTop?new cb(m.scrollLeft,m.scrollTop):new cb(v.pageXOffset||m.scrollLeft,v.pageYOffset||m.scrollTop)}else m=new cb(m.scrollLeft,m.scrollTop);return m}var e=fd(a),f=A(a),g=f.documentElement,h=f.body,n=V(g,"overflow"),u;for(a=b(a);a;a=b(a)){var p=c(a);if("visible"!=p.x||"visible"!=
103
104
  p.y){var G=W(a);if(0==G.width||0==G.height)return X;var R=e.a<G.a,fa=e.b<G.b;if(R&&"hidden"==p.x||fa&&"hidden"==p.y)return X;if(R&&"visible"!=p.x||fa&&"visible"!=p.y){R=d(a);fa=e.b<G.b-R.y;if(e.a<G.a-R.x&&"visible"!=p.x||fa&&"visible"!=p.x)return X;e=bd(a);return e==X?X:"scroll"}R=e.f>=G.a+G.width;G=e.c>=G.b+G.height;if(R&&"hidden"==p.x||G&&"hidden"==p.y)return X;if(R&&"visible"!=p.x||G&&"visible"!=p.y){if(u&&(p=d(a),e.f>=g.scrollWidth-p.x||e.a>=g.scrollHeight-p.y))return X;e=bd(a);return e==X?X:
@@ -97,4 +97,5 @@ r.y){var D=Jc(a);if(0==D.width||0==D.height)return Z;var L=e.a<D.a,M=e.b<D.b;if(
97
97
  function Jc(a){var b=Lc(a);if(b)return b.rect;if(W(a,"HTML"))return a=A(a),a=((a?a.parentWindow||a.defaultView:window)||window).document,a="CSS1Compat"==a.compatMode?a.documentElement:a.body,a=new Va(a.clientWidth,a.clientHeight),new X(0,0,a.width,a.height);try{var c=a.getBoundingClientRect()}catch(d){return new X(0,0,0,0)}b=new X(c.left,c.top,c.right-c.left,c.bottom-c.top);v&&a.ownerDocument.body&&(a=A(a),b.a-=a.documentElement.clientLeft+a.body.clientLeft,b.b-=a.documentElement.clientTop+a.body.clientTop);
98
98
  return b}function Lc(a){var b=W(a,"MAP");if(!b&&!W(a,"AREA"))return null;var c=b?a:W(a.parentNode,"MAP")?a.parentNode:null,d=null,e=null;c&&c.name&&(d=Dc('/descendant::*[@usemap = "#'+c.name+'"]',A(c)))&&(e=Jc(d),b||"default"==a.shape.toLowerCase()||(a=Oc(a),b=Math.min(Math.max(a.a,0),e.width),c=Math.min(Math.max(a.b,0),e.height),e=new X(b+e.a,c+e.b,Math.min(a.width,e.width-b),Math.min(a.height,e.height-c))));return{image:d,rect:e||new X(0,0,0,0)}}
99
99
  function Oc(a){var b=a.shape.toLowerCase();a=a.coords.split(",");if("rect"==b&&4==a.length){b=a[0];var c=a[1];return new X(b,c,a[2]-b,a[3]-c)}if("circle"==b&&3==a.length)return b=a[2],new X(a[0]-b,a[1]-b,2*b,2*b);if("poly"==b&&2<a.length){b=a[0];c=a[1];for(var d=b,e=c,f=2;f+1<a.length;f+=2)b=Math.min(b,a[f]),d=Math.max(d,a[f]),c=Math.min(c,a[f+1]),e=Math.max(e,a[f+1]);return new X(b,c,d-b,e-c)}return new X(0,0,0,0)}function Nc(a){a=Jc(a);return new Ec(a.b,a.a+a.width,a.b+a.height,a.a)}
100
- function Mc(a){if(Ac){if("relative"==Y(a,"position"))return 1;a=Y(a,"filter");return(a=a.match(/^alpha\(opacity=(\d*)\)/)||a.match(/^progid:DXImageTransform.Microsoft.Alpha\(Opacity=(\d*)\)/))?Number(a[1])/100:1}return Pc(a)}function Pc(a){var b=1,c=Y(a,"opacity");c&&(b=Number(c));(a=Gc(a))&&(b*=Pc(a));return b};ba("_",function(a,b){function c(d){if(W(d)&&"none"==Y(d,"display"))return!1;var e;if((e=d.parentNode)&&e.shadowRoot&&void 0!==d.assignedSlot)e=d.assignedSlot?d.assignedSlot.parentNode:null;else if(d.getDestinationInsertionPoints){var f=d.getDestinationInsertionPoints();0<f.length&&(e=f[f.length-1])}if(Fc&&e instanceof ShadowRoot){if(e.host.shadowRoot!==e)return!1;e=e.host}return!e||9!=e.nodeType&&11!=e.nodeType?e&&W(e,"DETAILS")&&!e.open&&!W(d,"SUMMARY")?!1:!!e&&c(e):!0}return Ic(a,!!b,c)});; return this._.apply(null,arguments);}).apply({navigator:typeof window!='undefined'?window.navigator:null,document:typeof window!='undefined'?window.document:null}, arguments);}
100
+ function Mc(a){if(Ac){if("relative"==Y(a,"position"))return 1;a=Y(a,"filter");return(a=a.match(/^alpha\(opacity=(\d*)\)/)||a.match(/^progid:DXImageTransform.Microsoft.Alpha\(Opacity=(\d*)\)/))?Number(a[1])/100:1}return Pc(a)}function Pc(a){var b=1,c=Y(a,"opacity");c&&(b=Number(c));(a=Gc(a))&&(b*=Pc(a));return b};ba("_",function(a,b){function c(d){if(W(d)&&"none"==Y(d,"display"))return!1;var e;if((e=d.parentNode)&&e.shadowRoot&&void 0!==d.assignedSlot)e=d.assignedSlot?d.assignedSlot.parentNode:null;else if(d.getDestinationInsertionPoints){var f=d.getDestinationInsertionPoints();0<f.length&&(e=f[f.length-1])}if(Fc&&e instanceof ShadowRoot){if(e.host.shadowRoot&&e.host.shadowRoot!==e)return!1;e=e.host}return!e||9!=e.nodeType&&11!=e.nodeType?e&&W(e,"DETAILS")&&!e.open&&!W(d,"SUMMARY")?!1:!!e&&c(e):!0}return Ic(a,
101
+ !!b,c)});; return this._.apply(null,arguments);}).apply({navigator:typeof window!='undefined'?window.navigator:null,document:typeof window!='undefined'?window.document:null}, arguments);}
@@ -35,8 +35,12 @@ module Selenium
35
35
  send_command: [:post, 'session/:session_id/goog/cdp/execute']
36
36
  }.freeze
37
37
 
38
+ def command_list
39
+ CHROME_COMMANDS.merge(CHROMIUM_COMMANDS).merge(self.class::COMMANDS)
40
+ end
41
+
38
42
  def commands(command)
39
- CHROME_COMMANDS[command] || CHROMIUM_COMMANDS[command] || self.class::COMMANDS[command]
43
+ command_list[command]
40
44
  end
41
45
  end # Bridge
42
46
  end # Chrome
@@ -31,10 +31,6 @@ module Selenium
31
31
  get_log: [:post, 'session/:session_id/se/log']
32
32
  }.freeze
33
33
 
34
- def commands(command)
35
- CHROME_COMMANDS[command] || self.class::COMMANDS[command]
36
- end
37
-
38
34
  def launch_app(id)
39
35
  execute :launch_app, {}, {id: id}
40
36
  end
@@ -0,0 +1,65 @@
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 HasFileDownloads
24
+ def downloadable_files
25
+ verify_enabled
26
+
27
+ @bridge.downloadable_files['names']
28
+ end
29
+
30
+ def download_file(file_name, target_directory)
31
+ verify_enabled
32
+
33
+ response = @bridge.download_file(file_name)
34
+ contents = response['contents']
35
+
36
+ File.open("#{file_name}.zip", 'wb') { |f| f << Base64.decode64(contents) }
37
+ target_directory += '/' unless target_directory.end_with?('/')
38
+ FileUtils.mkdir_p(target_directory)
39
+
40
+ begin
41
+ Zip::File.open("#{file_name}.zip") do |zip|
42
+ zip.each { |entry| zip.extract(entry, "#{target_directory}#{file_name}") }
43
+ end
44
+ ensure
45
+ FileUtils.rm_f("#{file_name}.zip")
46
+ end
47
+ end
48
+
49
+ def delete_downloadable_files
50
+ verify_enabled
51
+
52
+ @bridge.delete_downloadable_files
53
+ end
54
+
55
+ private
56
+
57
+ def verify_enabled
58
+ return if capabilities['se:downloadsEnabled']
59
+
60
+ raise Error::WebDriverError, 'You must enable downloads in order to work with downloadable files.'
61
+ end
62
+ end # HasFileDownloads
63
+ end # DriverExtensions
64
+ end # WebDriver
65
+ end # Selenium
@@ -103,7 +103,7 @@ module Selenium
103
103
  #
104
104
  # @param [Array, Symbol] ids
105
105
  #
106
- def allow(ids)
106
+ def allow(*ids)
107
107
  @allowed += Array(ids).flatten
108
108
  end
109
109
 
@@ -112,7 +112,7 @@ module Selenium
112
112
  # Overrides default #debug to skip ignored messages by provided id
113
113
  #
114
114
  # @param [String] message
115
- # @param [Symbol, Array<Sybmol>] id
115
+ # @param [Symbol, Array<Symbol>] id
116
116
  # @yield see #deprecate
117
117
  #
118
118
  def debug(message, id: [], &block)
@@ -123,7 +123,7 @@ module Selenium
123
123
  # Used to supply information of general interest
124
124
  #
125
125
  # @param [String] message
126
- # @param [Symbol, Array<Sybmol>] id
126
+ # @param [Symbol, Array<Symbol>] id
127
127
  # @yield see #deprecate
128
128
  #
129
129
  def info(message, id: [], &block)
@@ -134,7 +134,7 @@ module Selenium
134
134
  # Used to supply information that suggests an error occurred
135
135
  #
136
136
  # @param [String] message
137
- # @param [Symbol, Array<Sybmol>] id
137
+ # @param [Symbol, Array<Symbol>] id
138
138
  # @yield see #deprecate
139
139
  #
140
140
  def error(message, id: [], &block)
@@ -145,7 +145,7 @@ module Selenium
145
145
  # Used to supply information that suggests action be taken by user
146
146
  #
147
147
  # @param [String] message
148
- # @param [Symbol, Array<Sybmol>] id
148
+ # @param [Symbol, Array<Symbol>] id
149
149
  # @yield see #deprecate
150
150
  #
151
151
  def warn(message, id: [], &block)
@@ -24,6 +24,8 @@ module Selenium
24
24
  set_window_rect timeouts unhandled_prompt_behavior strict_file_interactability
25
25
  web_socket_url].freeze
26
26
 
27
+ GRID_OPTIONS = %i[enable_downloads].freeze
28
+
27
29
  class << self
28
30
  attr_reader :driver_path
29
31
 
@@ -104,6 +106,8 @@ module Selenium
104
106
  def as_json(*)
105
107
  options = @options.dup
106
108
 
109
+ downloads = options.delete(:enable_downloads)
110
+ options['se:downloadsEnabled'] = downloads unless downloads.nil?
107
111
  w3c_options = process_w3c_options(options)
108
112
 
109
113
  browser_options = self.class::CAPABILITIES.each_with_object({}) do |(capability_alias, capability_name), hash|
@@ -86,6 +86,10 @@ module Selenium
86
86
  os == :linux
87
87
  end
88
88
 
89
+ def unix?
90
+ os == :unix
91
+ end
92
+
89
93
  def wsl?
90
94
  return false unless linux?
91
95
 
@@ -41,11 +41,11 @@ module Selenium
41
41
 
42
42
  output = run(*command)
43
43
 
44
- browser_path = output['browser_path']
45
- driver_path = output['driver_path']
44
+ browser_path = Platform.cygwin? ? Platform.cygwin_path(output['browser_path']) : output['browser_path']
45
+ driver_path = Platform.cygwin? ? Platform.cygwin_path(output['driver_path']) : output['driver_path']
46
46
  Platform.assert_executable driver_path
47
47
 
48
- if options.respond_to? :binary
48
+ if options.respond_to?(:binary) && browser_path && !browser_path.empty?
49
49
  options.binary = browser_path
50
50
  options.browser_version = nil
51
51
  end
@@ -67,7 +67,7 @@ module Selenium
67
67
  end
68
68
  if options.proxy
69
69
  command << '--proxy'
70
- (command << options.proxy.ssl) || options.proxy.http
70
+ command << (options.proxy.ssl || options.proxy.http)
71
71
  end
72
72
  command
73
73
  end
@@ -83,7 +83,13 @@ module Selenium
83
83
  "#{directory}/macos/selenium-manager"
84
84
  elsif Platform.linux?
85
85
  "#{directory}/linux/selenium-manager"
86
+ elsif Platform.unix?
87
+ WebDriver.logger.warn('Selenium Manager binary may not be compatible with Unix; verify settings',
88
+ id: %i[selenium_manager unix_binary])
89
+ "#{directory}/linux/selenium-manager"
86
90
  end
91
+ rescue Error::WebDriverError => e
92
+ raise Error::WebDriverError, "Unable to obtain Selenium Manager binary for #{e.message}"
87
93
  end)
88
94
 
89
95
  validate_location(location)
@@ -81,6 +81,7 @@ require 'selenium/webdriver/common/driver_extensions/full_page_screenshot'
81
81
  require 'selenium/webdriver/common/driver_extensions/has_addons'
82
82
  require 'selenium/webdriver/common/driver_extensions/has_bidi'
83
83
  require 'selenium/webdriver/common/driver_extensions/has_devtools'
84
+ require 'selenium/webdriver/common/driver_extensions/has_file_downloads'
84
85
  require 'selenium/webdriver/common/driver_extensions/has_authentication'
85
86
  require 'selenium/webdriver/common/driver_extensions/has_logs'
86
87
  require 'selenium/webdriver/common/driver_extensions/has_log_events'
@@ -35,8 +35,12 @@ module Selenium
35
35
  send_command: [:post, 'session/:session_id/ms/cdp/execute']
36
36
  }.freeze
37
37
 
38
+ def command_list
39
+ EDGE_COMMANDS.merge(CHROMIUM_COMMANDS).merge(self.class::COMMANDS)
40
+ end
41
+
38
42
  def commands(command)
39
- EDGE_COMMANDS[command] || CHROMIUM_COMMANDS[command] || self.class::COMMANDS[command]
43
+ command_list[command]
40
44
  end
41
45
  end # Bridge
42
46
  end # Edge
@@ -29,8 +29,12 @@ module Selenium
29
29
  full_page_screenshot: [:get, 'session/:session_id/moz/screenshot/full']
30
30
  }.freeze
31
31
 
32
+ def command_list
33
+ FIREFOX_COMMANDS.merge(self.class::COMMANDS)
34
+ end
35
+
32
36
  def commands(command)
33
- FIREFOX_COMMANDS[command] || self.class::COMMANDS[command]
37
+ command_list[command]
34
38
  end
35
39
 
36
40
  def install_addon(path, temporary)
@@ -33,6 +33,8 @@ module Selenium
33
33
  'security.csp.enable' => false
34
34
  }.freeze
35
35
 
36
+ LOCK_FILES = %w[.parentlock parent.lock lock].freeze
37
+
36
38
  attr_reader :name, :log_file
37
39
  attr_writer :secure_ssl, :load_no_focus_lib
38
40
 
@@ -176,7 +178,7 @@ module Selenium
176
178
  end
177
179
 
178
180
  def delete_lock_files(directory)
179
- %w[.parentlock parent.lock].each do |name|
181
+ LOCK_FILES.each do |name|
180
182
  FileUtils.rm_f File.join(directory, name)
181
183
  end
182
184
  end
@@ -0,0 +1,34 @@
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 IE
23
+ module Features
24
+ def command_list
25
+ self.class::COMMANDS
26
+ end
27
+
28
+ def commands(command)
29
+ command_list[command]
30
+ end
31
+ end # Bridge
32
+ end # Ie
33
+ end # WebDriver
34
+ end # Selenium
@@ -20,9 +20,10 @@
20
20
  module Selenium
21
21
  module WebDriver
22
22
  module IE
23
- autoload :Driver, 'selenium/webdriver/ie/driver'
24
- autoload :Options, 'selenium/webdriver/ie/options'
25
- autoload :Service, 'selenium/webdriver/ie/service'
23
+ autoload :Features, 'selenium/webdriver/ie/features'
24
+ autoload :Driver, 'selenium/webdriver/ie/driver'
25
+ autoload :Options, 'selenium/webdriver/ie/options'
26
+ autoload :Service, 'selenium/webdriver/ie/service'
26
27
  end # IE
27
28
  end # WebDriver
28
29
  end # Selenium
@@ -144,12 +144,6 @@ module Selenium
144
144
  take_screenshot: [:get, 'session/:session_id/screenshot'],
145
145
  take_element_screenshot: [:get, 'session/:session_id/element/:id/screenshot'],
146
146
 
147
- #
148
- # server extensions
149
- #
150
-
151
- upload_file: [:post, 'session/:session_id/se/file'],
152
-
153
147
  #
154
148
  # virtual-authenticator
155
149
  #
@@ -391,30 +391,11 @@ module Selenium
391
391
  end
392
392
 
393
393
  def send_keys_to_element(element, keys)
394
- # TODO: rework file detectors before Selenium 4.0
395
- if @file_detector
396
- local_files = keys.first&.split("\n")&.map { |key| @file_detector.call(Array(key)) }&.compact
397
- if local_files&.any?
398
- keys = local_files.map { |local_file| upload(local_file) }
399
- keys = Array(keys.join("\n"))
400
- end
401
- end
402
-
403
- # Keep .split(//) for backward compatibility for now
394
+ keys = upload_if_necessary(keys) if @file_detector
404
395
  text = keys.join
405
396
  execute :element_send_keys, {id: element}, {value: text.chars, text: text}
406
397
  end
407
398
 
408
- def upload(local_file)
409
- unless File.file?(local_file)
410
- WebDriver.logger.debug("File detector only works with files. #{local_file.inspect} isn`t a file!",
411
- id: :file_detector)
412
- raise Error::WebDriverError, "You are trying to work with something that isn't a file."
413
- end
414
-
415
- execute :upload_file, {}, {file: Zipper.zip_file(local_file)}
416
- end
417
-
418
399
  def clear_element(element)
419
400
  execute :element_clear, id: element
420
401
  end
@@ -28,6 +28,7 @@ module Selenium
28
28
  class Driver < WebDriver::Driver
29
29
  include DriverExtensions::UploadsFiles
30
30
  include DriverExtensions::HasSessionId
31
+ include DriverExtensions::HasFileDownloads
31
32
 
32
33
  def initialize(capabilities: nil, options: nil, service: nil, url: nil, **opts)
33
34
  raise ArgumentError, "Can not set :service object on #{self.class}" if service
@@ -36,6 +37,9 @@ module Selenium
36
37
  caps = process_options(options, capabilities)
37
38
  super(caps: caps, url: url, **opts)
38
39
  @bridge.file_detector = ->((filename, *)) { File.exist?(filename) && filename.to_s }
40
+ command_list = @bridge.command_list
41
+ @bridge.extend(WebDriver::Remote::Features)
42
+ @bridge.add_commands(command_list)
39
43
  end
40
44
 
41
45
  private
@@ -0,0 +1,75 @@
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 Remote
23
+ module Features
24
+ REMOTE_COMMANDS = {
25
+ upload_file: [:post, 'session/:session_id/se/file'],
26
+ get_downloadable_files: [:get, 'session/:session_id/se/files'],
27
+ download_file: [:post, 'session/:session_id/se/files'],
28
+ delete_downloadable_files: [:delete, 'session/:session_id/se/files']
29
+ }.freeze
30
+
31
+ def add_commands(commands)
32
+ @command_list = command_list.merge(commands)
33
+ end
34
+
35
+ def command_list
36
+ @command_list ||= REMOTE_COMMANDS
37
+ end
38
+
39
+ def commands(command)
40
+ command_list[command]
41
+ end
42
+
43
+ def upload(local_file)
44
+ unless File.file?(local_file)
45
+ WebDriver.logger.error("File detector only works with files. #{local_file.inspect} isn`t a file!",
46
+ id: :file_detector)
47
+ raise Error::WebDriverError, "You are trying to upload something that isn't a file."
48
+ end
49
+
50
+ execute :upload_file, {}, {file: Zipper.zip_file(local_file)}
51
+ end
52
+
53
+ def upload_if_necessary(keys)
54
+ local_files = keys.first&.split("\n")&.map { |key| @file_detector.call(Array(key)) }&.compact
55
+ return keys unless local_files&.any?
56
+
57
+ keys = local_files.map { |local_file| upload(local_file) }
58
+ Array(keys.join("\n"))
59
+ end
60
+
61
+ def downloadable_files
62
+ execute :get_downloadable_files
63
+ end
64
+
65
+ def download_file(name)
66
+ execute :download_file, {}, {name: name}
67
+ end
68
+
69
+ def delete_downloadable_files
70
+ execute :delete_downloadable_files
71
+ end
72
+ end
73
+ end # Remote
74
+ end # WebDriver
75
+ end # Selenium
@@ -23,6 +23,7 @@ require 'selenium/webdriver/remote/server_error'
23
23
  module Selenium
24
24
  module WebDriver
25
25
  module Remote
26
+ autoload :Features, 'selenium/webdriver/remote/features'
26
27
  autoload :Bridge, 'selenium/webdriver/remote/bridge'
27
28
  autoload :Driver, 'selenium/webdriver/remote/driver'
28
29
  autoload :Response, 'selenium/webdriver/remote/response'
@@ -28,8 +28,12 @@ module Selenium
28
28
  attach_debugger: [:post, 'session/:session_id/apple/attach_debugger']
29
29
  }.freeze
30
30
 
31
+ def command_list
32
+ SAFARI_COMMANDS.merge(self.class::COMMANDS)
33
+ end
34
+
31
35
  def commands(command)
32
- SAFARI_COMMANDS[command] || self.class::COMMANDS[command]
36
+ command_list[command]
33
37
  end
34
38
 
35
39
  def permissions
@@ -120,8 +120,8 @@ module Selenium
120
120
  returned
121
121
  end
122
122
 
123
- def method_missing(meth, *args, &blk) # rubocop:disable Style/MissingRespondToMissing
124
- @delegate.__send__(meth, *args, &blk)
123
+ def method_missing(meth, ...) # rubocop:disable Style/MissingRespondToMissing
124
+ @delegate.__send__(meth, ...)
125
125
  end
126
126
  end # EventFiringBridge
127
127
  end # Support
@@ -53,7 +53,9 @@ module Selenium
53
53
 
54
54
  case @type
55
55
  when :exclude
56
- "Test not guarded because it breaks test run; #{details}"
56
+ "Test skipped because it breaks test run; #{details}"
57
+ when :flaky
58
+ "Test skipped because it is unreliable in this configuration; #{details}"
57
59
  when :exclusive
58
60
  "Test does not apply to this configuration; #{details}"
59
61
  else
@@ -71,9 +73,10 @@ module Selenium
71
73
  @type == :only
72
74
  end
73
75
 
74
- # Bug is present on all configurations specified, but test can not be run because it breaks other tests
76
+ # Bug is present on all configurations specified, but test can not be run because it breaks other tests,
77
+ # or it is flaky and unreliable
75
78
  def exclude?
76
- @type == :exclude
79
+ @type == :exclude || @type == :flaky
77
80
  end
78
81
 
79
82
  # Test only applies to configurations specified
@@ -24,7 +24,7 @@ module Selenium
24
24
  module WebDriver
25
25
  module Support
26
26
  class Guards
27
- GUARD_TYPES = %i[except only exclude exclusive].freeze
27
+ GUARD_TYPES = %i[except only exclude exclusive flaky].freeze
28
28
 
29
29
  attr_reader :messages
30
30
  attr_accessor :bug_tracker
@@ -19,6 +19,6 @@
19
19
 
20
20
  module Selenium
21
21
  module WebDriver
22
- VERSION = '4.14.0'
22
+ VERSION = '4.16.0'
23
23
  end # WebDriver
24
24
  end # Selenium
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: selenium-webdriver
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.14.0
4
+ version: 4.16.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Rodionov
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2023-10-10 00:00:00.000000000 Z
13
+ date: 2023-12-06 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rexml
@@ -258,6 +258,7 @@ files:
258
258
  - lib/selenium/webdriver/common/driver_extensions/has_context.rb
259
259
  - lib/selenium/webdriver/common/driver_extensions/has_debugger.rb
260
260
  - lib/selenium/webdriver/common/driver_extensions/has_devtools.rb
261
+ - lib/selenium/webdriver/common/driver_extensions/has_file_downloads.rb
261
262
  - lib/selenium/webdriver/common/driver_extensions/has_launching.rb
262
263
  - lib/selenium/webdriver/common/driver_extensions/has_log_events.rb
263
264
  - lib/selenium/webdriver/common/driver_extensions/has_logs.rb
@@ -348,6 +349,7 @@ files:
348
349
  - lib/selenium/webdriver/firefox/util.rb
349
350
  - lib/selenium/webdriver/ie.rb
350
351
  - lib/selenium/webdriver/ie/driver.rb
352
+ - lib/selenium/webdriver/ie/features.rb
351
353
  - lib/selenium/webdriver/ie/options.rb
352
354
  - lib/selenium/webdriver/ie/service.rb
353
355
  - lib/selenium/webdriver/remote.rb
@@ -355,6 +357,7 @@ files:
355
357
  - lib/selenium/webdriver/remote/bridge/commands.rb
356
358
  - lib/selenium/webdriver/remote/capabilities.rb
357
359
  - lib/selenium/webdriver/remote/driver.rb
360
+ - lib/selenium/webdriver/remote/features.rb
358
361
  - lib/selenium/webdriver/remote/http/common.rb
359
362
  - lib/selenium/webdriver/remote/http/curb.rb
360
363
  - lib/selenium/webdriver/remote/http/default.rb