selenium-webdriver 4.14.0 → 4.16.0

Sign up to get free protection for your applications and to get access to all the features.
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