async-webdriver 0.10.0 → 0.11.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5aad63b2a9668b73cce1b22358cd050e3b126b7c4fde2bc9d998338eacdc6377
4
- data.tar.gz: 73b0d6e9eb31c7ef19cdaa12307c00ba3ff09efb895f9d274f7e46cee552c785
3
+ metadata.gz: 9a70af1593c116227ab4863c4e209bb4002faf9bdfe18e7183b0656811b83066
4
+ data.tar.gz: 64ca1a5125e4a8289f2d55b6a6fe8b6e8579ae1b0b9ffd139bcc407d22a4702a
5
5
  SHA512:
6
- metadata.gz: ed9a55e1ad513fe7ae9a9143b97e348dce6c1d9eccc759397ab5c5005439398131085ab5f847e8560e3bd26232bd4486991b4f514e56b6272df2f2406510e422
7
- data.tar.gz: 876dd5764f7582f43f7ffe749f4a5c7aeb032d82abc920d64694804dc39500f23f04c998566fe0d48d4d3cdce1d56e6128a63eeeb3665e33f2f90d9b22ce7422
6
+ metadata.gz: e9770cacf231cf999256001afb4e53a6c8d2dbbe5ea34f9d67974651ba8c2d04ff7ce0984aa083dfe15895d63ec7c2265de7d6d919e9571a4e7cd11a8f65cc6a
7
+ data.tar.gz: f775e069001ebbf3a52a4d909e8734242c039410c218142c44cd1973921af1f6490098debd3be854dbd214e017908e277d4a6a5f6c1585393254cacce3992d97
checksums.yaml.gz.sig CHANGED
Binary file
@@ -84,7 +84,7 @@ The most reliable approach is to use `wait_for_navigation` to wait for the URL o
84
84
  ```ruby
85
85
  # ✅ RELIABLE: Wait for URL change
86
86
  session.click_button("Submit")
87
- session.wait_for_navigation {|url| url.end_with?("/success")}
87
+ session.wait_for_navigation{|url| url.end_with?("/success")}
88
88
  session.navigate_to("/next-page") # Now safe
89
89
  ```
90
90
 
@@ -96,7 +96,7 @@ For critical operations like authentication, wait for server-side effects to com
96
96
  # ✅ RELIABLE: Wait for authentication cookie
97
97
  session.click_button("Login")
98
98
  session.wait_for_navigation do |url, ready_state|
99
- ready_state == "complete" && session.cookies.any?{|cookie| cookie['name'] == 'auth_token'}
99
+ ready_state == "complete" && session.cookies.any?{|cookie| cookie["name"] == "auth_token"}
100
100
  end
101
101
  session.navigate_to("/dashboard") # Now safe
102
102
  ```
@@ -20,6 +20,7 @@ module Async
20
20
  # end
21
21
  # ```
22
22
  class Chrome < Generic
23
+ # @returns [String] The path to the `chromedriver` executable.
23
24
  def path
24
25
  @options.fetch(:path, "chromedriver")
25
26
  end
@@ -33,7 +34,10 @@ module Async
33
34
  return nil
34
35
  end
35
36
 
37
+ # A locally managed `chromedriver` process.
36
38
  class Driver < Bridge::Driver
39
+ # Initialize a managed Chrome driver process.
40
+ # @parameter options [Hash] Driver configuration options.
37
41
  def initialize(**options)
38
42
  super(**options)
39
43
  @process_group = nil
@@ -47,12 +51,14 @@ module Async
47
51
  ].compact
48
52
  end
49
53
 
54
+ # Start the managed Chrome driver process and wait for readiness.
50
55
  def start
51
56
  @process_group = ProcessGroup.spawn(*arguments(**@options))
52
57
 
53
58
  super
54
59
  end
55
60
 
61
+ # Stop the managed Chrome driver process.
56
62
  def close
57
63
  if @process_group
58
64
  @process_group.close
@@ -76,7 +82,7 @@ module Async
76
82
  alwaysMatch: {
77
83
  browserName: "chrome",
78
84
  "goog:chromeOptions": {
79
- args: [headless ? "--headless" : nil].compact,
85
+ args: [headless ? "--headless=new" : nil].compact,
80
86
  },
81
87
  webSocketUrl: true,
82
88
  },
@@ -8,12 +8,15 @@ module Async
8
8
  module Bridge
9
9
  # Represents an instance of a locally running driver (usually with a process group).
10
10
  class Driver
11
+ # Initialize a driver wrapper.
12
+ # @parameter options [Hash] Driver configuration options.
11
13
  def initialize(**options)
12
14
  @options = options
13
15
  @count = 0
14
16
  @closed = false
15
17
  end
16
18
 
19
+ # @returns [Integer] The number of concurrent sessions the driver can sustain.
17
20
  def concurrency
18
21
  @options.fetch(:concurrency, 128)
19
22
  end
@@ -23,18 +26,22 @@ module Async
23
26
  # @attribute [Hash] The status of the driver after a connection has been established.
24
27
  attr :status
25
28
 
29
+ # @returns [Boolean] Whether the driver can still be used.
26
30
  def viable?
27
31
  !@closed
28
32
  end
29
33
 
34
+ # @returns [Boolean] Whether the driver has been closed.
30
35
  def closed?
31
36
  @closed
32
37
  end
33
38
 
39
+ # Mark the driver as closed.
34
40
  def close
35
41
  @closed = true
36
42
  end
37
43
 
44
+ # @returns [Boolean] Whether the driver may be returned to a pool.
38
45
  def reusable?
39
46
  @options.fetch(:reusable, !@closed)
40
47
  end
@@ -50,14 +57,17 @@ module Async
50
57
  end
51
58
  end
52
59
 
60
+ # @returns [Integer] The port the driver listens on.
53
61
  def port
54
62
  @port ||= @options.fetch(:port, self.ephemeral_port)
55
63
  end
56
64
 
65
+ # @returns [Async::HTTP::Endpoint] The HTTP endpoint exposed by the driver.
57
66
  def endpoint
58
67
  Async::HTTP::Endpoint.parse("http://localhost", port: self.port)
59
68
  end
60
69
 
70
+ # @returns [Client] A client connected to the driver endpoint.
61
71
  def client
62
72
  Client.open(self.endpoint)
63
73
  end
@@ -19,6 +19,7 @@ module Async
19
19
  # bridge&.close
20
20
  # end
21
21
  class Firefox < Generic
22
+ # @returns [String] The path to the `geckodriver` executable.
22
23
  def path
23
24
  @options.fetch(:path, "geckodriver")
24
25
  end
@@ -32,12 +33,16 @@ module Async
32
33
  return nil
33
34
  end
34
35
 
36
+ # A locally managed `geckodriver` process.
35
37
  class Driver < Bridge::Driver
38
+ # Initialize a managed Firefox driver process.
39
+ # @parameter options [Hash] Driver configuration options.
36
40
  def initialize(**options)
37
41
  super(**options)
38
42
  @process_group = nil
39
43
  end
40
44
 
45
+ # @returns [Integer] Firefox drivers support one session at a time.
41
46
  def concurrency
42
47
  1
43
48
  end
@@ -50,12 +55,14 @@ module Async
50
55
  ].compact
51
56
  end
52
57
 
58
+ # Start the managed Firefox driver process and wait for readiness.
53
59
  def start
54
60
  @process_group = ProcessGroup.spawn(*arguments(**@options))
55
61
 
56
62
  super
57
63
  end
58
64
 
65
+ # Stop the managed Firefox driver process.
59
66
  def close
60
67
  if @process_group
61
68
  @process_group.close
@@ -12,6 +12,8 @@ module Async
12
12
  module Bridge
13
13
  # Generic W3C WebDriver implementation.
14
14
  class Generic
15
+ # Initialize a generic bridge wrapper.
16
+ # @parameter options [Hash] Bridge configuration options.
15
17
  def initialize(**options)
16
18
  @options = options
17
19
  end
@@ -26,6 +28,7 @@ module Async
26
28
  version != nil
27
29
  end
28
30
 
31
+ # @returns [Boolean] Whether headless mode is enabled by default.
29
32
  def headless?
30
33
  @options.fetch(:headless, true)
31
34
  end
@@ -24,14 +24,22 @@ module Async
24
24
  # end
25
25
  # ```
26
26
  class Pool
27
+ # Controls pooled drivers and cached sessions.
27
28
  class BridgeController
29
+ # Initialize the bridge controller.
30
+ # @parameter bridge [Bridge] The bridge used to create drivers.
31
+ # @parameter capabilities [Hash] Capabilities used for new sessions.
28
32
  def initialize(bridge, capabilities: bridge.default_capabilities)
29
33
  @bridge = bridge
30
34
  @capabilities = capabilities
31
35
  @pool = Async::Pool::Controller.new(self)
32
36
  end
33
37
 
38
+ # Caches sessions created from a single driver instance.
34
39
  class SessionCache
40
+ # Initialize a session cache for one driver instance.
41
+ # @parameter driver [Driver] The driver backing cached sessions.
42
+ # @parameter capabilities [Hash] Capabilities for newly created sessions.
35
43
  def initialize(driver, capabilities)
36
44
  @driver = driver
37
45
  @capabilities = capabilities
@@ -40,14 +48,17 @@ module Async
40
48
  @sessions = []
41
49
  end
42
50
 
51
+ # @returns [Boolean] Whether the underlying driver remains usable.
43
52
  def viable?
44
53
  @driver&.viable?
45
54
  end
46
55
 
56
+ # @returns [Boolean] Whether cached sessions may be reused.
47
57
  def reusable?
48
58
  @driver&.reusable?
49
59
  end
50
60
 
61
+ # Close the cached sessions, driver, and HTTP client.
51
62
  def close
52
63
  if @driver
53
64
  @driver.close
@@ -64,10 +75,13 @@ module Async
64
75
  end
65
76
  end
66
77
 
78
+ # @returns [Integer] The number of concurrently usable sessions.
67
79
  def concurrency
68
80
  @driver.concurrency
69
81
  end
70
82
 
83
+ # Acquire a cached or newly created session payload.
84
+ # @returns [Hash] A WebDriver session payload.
71
85
  def acquire
72
86
  if @sessions.empty?
73
87
  session = @client.post("session", {capabilities: @capabilities})
@@ -85,6 +99,8 @@ module Async
85
99
  end
86
100
  end
87
101
 
102
+ # Return a session payload to the cache.
103
+ # @parameter session [Hash] The session payload to cache.
88
104
  def release(session)
89
105
  @sessions.push(session)
90
106
  end
@@ -95,12 +111,16 @@ module Async
95
111
  SessionCache.new(@bridge.start, @capabilities)
96
112
  end
97
113
 
114
+ # Acquire a session payload from the pool.
115
+ # @returns [Hash] The acquired session payload.
98
116
  def acquire
99
117
  session_cache = @pool.acquire
100
118
 
101
119
  return session_cache.acquire
102
120
  end
103
121
 
122
+ # Return a session payload to the pool.
123
+ # @parameter session [Hash] The session payload to release.
104
124
  def release(session)
105
125
  session_cache = session[:cache]
106
126
 
@@ -109,6 +129,8 @@ module Async
109
129
  @pool.release(session_cache)
110
130
  end
111
131
 
132
+ # Retire a session payload and its cache from the pool.
133
+ # @parameter session [Hash] The session payload to retire.
112
134
  def retire(session)
113
135
  session_cache = session[:cache]
114
136
 
@@ -117,6 +139,7 @@ module Async
117
139
  @pool.retire(session_cache)
118
140
  end
119
141
 
142
+ # Close the underlying driver pool.
120
143
  def close
121
144
  if @pool
122
145
  @pool.close
@@ -136,15 +159,19 @@ module Async
136
159
  @controller.close
137
160
  end
138
161
 
162
+ # A pooled session wrapper that returns sessions to the cache on close.
139
163
  class CachedWrapper < Session
164
+ # @returns [Pool] The pool responsible for reusing this session.
140
165
  def pool
141
166
  @options[:pool]
142
167
  end
143
168
 
169
+ # @returns [Hash] The raw session payload returned by the bridge.
144
170
  def payload
145
171
  @options[:payload]
146
172
  end
147
173
 
174
+ # Return the session to the pool when possible.
148
175
  def close
149
176
  unless self.pool.reuse(self)
150
177
  super
@@ -167,6 +194,9 @@ module Async
167
194
  end
168
195
  end
169
196
 
197
+ # Reset and return a session to the pool.
198
+ # @parameter session [CachedWrapper] The session to reuse.
199
+ # @returns [Boolean] Always returns `true` once the session is released.
170
200
  def reuse(session)
171
201
  session.reset!
172
202
 
@@ -75,13 +75,18 @@ module Async
75
75
  end
76
76
  end
77
77
 
78
+ # A driver wrapper that closes an associated process handle.
78
79
  class ProcessDriver < Driver
80
+ # Initialize a process-backed driver.
81
+ # @parameter endpoint [Object] Driver options or endpoint information.
82
+ # @parameter process [ProcessGroup] The managed process group.
79
83
  def initialize(endpoint, process)
80
84
  super(endpoint)
81
85
 
82
86
  @process = process
83
87
  end
84
88
 
89
+ # Close the driver and its process group.
85
90
  def close
86
91
  super
87
92
 
@@ -20,6 +20,7 @@ module Async
20
20
  # end
21
21
  # ```
22
22
  class Safari < Generic
23
+ # @returns [String] The path to the `safaridriver` executable.
23
24
  def path
24
25
  @options.fetch(:path, "safaridriver")
25
26
  end
@@ -33,7 +34,10 @@ module Async
33
34
  return nil
34
35
  end
35
36
 
37
+ # A locally managed `safaridriver` process.
36
38
  class Driver < Bridge::Driver
39
+ # Initialize a managed Safari driver process.
40
+ # @parameter options [Hash] Driver configuration options.
37
41
  def initialize(**options)
38
42
  super(**options)
39
43
  @process_group = nil
@@ -47,12 +51,14 @@ module Async
47
51
  ].compact
48
52
  end
49
53
 
54
+ # Start the managed Safari driver process and wait for readiness.
50
55
  def start
51
56
  @process_group = ProcessGroup.spawn(*arguments(**@options))
52
57
 
53
58
  super
54
59
  end
55
60
 
61
+ # Stop the managed Safari driver process.
56
62
  def close
57
63
  if @process_group
58
64
  @process_group.close
@@ -21,6 +21,9 @@ module Async
21
21
  Bridge::Safari,
22
22
  ]
23
23
 
24
+ # Iterate over supported bridge implementations.
25
+ # @yields {|bridge| ...} Each supported bridge class.
26
+ # @parameter bridge [Class] A supported bridge implementation.
24
27
  def self.each(&block)
25
28
  return enum_for(:each) unless block_given?
26
29
 
@@ -45,6 +48,7 @@ module Async
45
48
  # ```
46
49
  ASYNC_WEBDRIVER_BRIDGE_HEADLESS = "ASYNC_WEBDRIVER_BRIDGE_HEADLESS"
47
50
 
51
+ # Raised when no supported bridge implementation is available.
48
52
  class UnsupportedError < Error
49
53
  end
50
54
 
@@ -20,6 +20,8 @@ module Async
20
20
  class Attributes
21
21
  include Enumerable
22
22
 
23
+ # Initialize the attribute wrapper for an element.
24
+ # @parameter element [Element] The element whose attributes will be accessed.
23
25
  def initialize(element)
24
26
  @element = element
25
27
  @keys = nil
@@ -7,6 +7,7 @@ require_relative "version"
7
7
 
8
8
  module Async
9
9
  module WebDriver
10
+ # The base class for WebDriver protocol errors.
10
11
  class Error < StandardError
11
12
  end
12
13
 
@@ -8,13 +8,45 @@ require "base64"
8
8
  module Async
9
9
  module WebDriver
10
10
  module Scope
11
- # Helpers for working with printing.
11
+ # Helpers for printing the current page to PDF.
12
12
  module Printing
13
- # Print the current page and return the result as a Base64 encoded string containing a PDF representation of the paginated document.
14
- def print(page_ranges: nil, total_pages: nil)
15
- reply = session.post("print", {pageRanges: page_ranges, totalPages: total_pages}.compact)
13
+ # Print the current page as a PDF and return the raw binary data.
14
+ #
15
+ # All margin and page measurements are in centimetres. The W3C WebDriver
16
+ # default page size is US Letter (21.59 × 27.94 cm) with 1 cm margins.
17
+ #
18
+ # @parameter orientation [String | Nil] `"portrait"` or `"landscape"`. Default: `"portrait"`.
19
+ # @parameter scale [Float | Nil] Scaling factor between 0.1 and 2.0. Default: `1.0`.
20
+ # @parameter background [Boolean | Nil] Whether to print background graphics and colours. Default: `false`.
21
+ # @parameter page [Hash | Nil] Page dimensions in cm. Keys: `:width`, `:height`.
22
+ # @parameter margin [Hash | Nil] Page margins in cm. Keys: `:top`, `:bottom`, `:left`, `:right`.
23
+ # @parameter page_ranges [Array(String) | Nil] Page ranges to print, e.g. `["1-5", "8"]`. Default: all pages.
24
+ # @parameter shrink_to_fit [Boolean | Nil] Whether to shrink content to fit the page. Default: `true`.
25
+ # @returns [String] The raw PDF binary data.
26
+ def print(orientation: nil, scale: nil, background: nil, page: nil, margin: nil, page_ranges: nil, shrink_to_fit: nil)
27
+ parameters = {
28
+ orientation: orientation,
29
+ scale: scale,
30
+ background: background,
31
+ page: page,
32
+ margin: margin,
33
+ pageRanges: page_ranges,
34
+ shrinkToFit: shrink_to_fit,
35
+ }.compact
16
36
 
17
- return Base64.decode64(reply["value"])
37
+ # Synchronise with Chrome's rendering pipeline before issuing the print
38
+ # command. The underlying CDP call (Page.printToPDF) is synchronous: if
39
+ # the renderer process has not yet fully initialised its print pipeline
40
+ # by the time the command arrives, Chrome returns JSON-RPC error -32000
41
+ # ("Printing failed") with no retry. A JavaScript round-trip forces
42
+ # ChromeDriver to wait for the renderer to be live (a JS execution
43
+ # context must exist), which also guarantees the print pipeline is ready.
44
+ # Without this, fast-loading pages can trigger the race intermittently.
45
+ session.execute("return document.readyState")
46
+
47
+ reply = session.post("print", parameters)
48
+
49
+ return Base64.decode64(reply)
18
50
  end
19
51
  end
20
52
  end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2023-2025, by Samuel Williams.
5
+
6
+ module Async
7
+ module WebDriver
8
+ module Scope
9
+ # Helpers for managing the browser window size and position.
10
+ module Window
11
+ # Get the current window rect (position and size).
12
+ # @returns [Hash] The window rect with keys `"x"`, `"y"`, `"width"`, `"height"`.
13
+ def window_rect
14
+ session.get("window/rect")
15
+ end
16
+
17
+ # Set the window rect (position and/or size).
18
+ # @parameter x [Integer | Nil] The x position of the window.
19
+ # @parameter y [Integer | Nil] The y position of the window.
20
+ # @parameter width [Integer | Nil] The width of the window in CSS pixels.
21
+ # @parameter height [Integer | Nil] The height of the window in CSS pixels.
22
+ def set_window_rect(x: nil, y: nil, width: nil, height: nil)
23
+ session.post("window/rect", {x: x, y: y, width: width, height: height}.compact)
24
+ end
25
+
26
+ # Resize the browser window to the given dimensions.
27
+ # @parameter width [Integer] The new width in CSS pixels.
28
+ # @parameter height [Integer] The new height in CSS pixels.
29
+ def resize_window(width, height)
30
+ set_window_rect(width: width, height: height)
31
+ end
32
+
33
+ # Maximize the browser window.
34
+ def maximize_window
35
+ session.post("window/maximize")
36
+ end
37
+
38
+ # Minimize the browser window.
39
+ def minimize_window
40
+ session.post("window/minimize")
41
+ end
42
+
43
+ # Make the browser window fullscreen.
44
+ def fullscreen_window
45
+ session.post("window/fullscreen")
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -13,3 +13,12 @@ require_relative "scope/navigation"
13
13
  require_relative "scope/printing"
14
14
  require_relative "scope/screen_capture"
15
15
  require_relative "scope/timeouts"
16
+ require_relative "scope/window"
17
+
18
+ module Async
19
+ module WebDriver
20
+ # @namespace
21
+ module Scope
22
+ end
23
+ end
24
+ end
@@ -56,6 +56,7 @@ module Async
56
56
  @options = options
57
57
  end
58
58
 
59
+ # @returns [String] A concise representation of the session.
59
60
  def inspect
60
61
  "\#<#{self.class} id=#{@id.inspect}>"
61
62
  end
@@ -126,6 +127,7 @@ module Async
126
127
  include Scope::Printing
127
128
  include Scope::ScreenCapture
128
129
  include Scope::Timeouts
130
+ include Scope::Window
129
131
 
130
132
  # Reset the session to a clean state.
131
133
  def reset!
@@ -3,8 +3,10 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2023-2025, by Samuel Williams.
5
5
 
6
+ # @namespace
6
7
  module Async
8
+ # @namespace
7
9
  module WebDriver
8
- VERSION = "0.10.0"
10
+ VERSION = "0.11.0"
9
11
  end
10
12
  end
data/readme.md CHANGED
@@ -28,6 +28,11 @@ Please see the [project documentation](https://socketry.github.io/async-webdrive
28
28
 
29
29
  Please see the [project releases](https://socketry.github.io/async-webdriver/releases/index) for all releases.
30
30
 
31
+ ### v0.11.0
32
+
33
+ - Add `Scope::Window` with `#window_rect`, `#resize_window`, `#set_window_rect`, `#maximize_window`, `#minimize_window`, and `#fullscreen_window`.
34
+ - Expand `Scope::Printing#print` with full W3C WebDriver parameters: `orientation`, `scale`, `background`, `page`, `margin`, `page_ranges`, and `shrink_to_fit`.
35
+
31
36
  ### v0.10.0
32
37
 
33
38
  - Introduce `Scope#wait_for_navigation` to properly wait for page navigations to complete.
@@ -55,6 +60,22 @@ We welcome contributions to this project.
55
60
  4. Push to the branch (`git push origin my-new-feature`).
56
61
  5. Create new Pull Request.
57
62
 
63
+ ### Running Tests
64
+
65
+ To run the test suite:
66
+
67
+ ``` shell
68
+ bundle exec sus
69
+ ```
70
+
71
+ ### Making Releases
72
+
73
+ To make a new release:
74
+
75
+ ``` shell
76
+ bundle exec bake gem:release:patch # or minor or major
77
+ ```
78
+
58
79
  ### Developer Certificate of Origin
59
80
 
60
81
  In order to protect users of this project, we require all contributors to comply with the [Developer Certificate of Origin](https://developercertificate.org/). This ensures that all contributions are properly licensed and attributed.
data/releases.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Releases
2
2
 
3
+ ## v0.11.0
4
+
5
+ - Add `Scope::Window` with `#window_rect`, `#resize_window`, `#set_window_rect`, `#maximize_window`, `#minimize_window`, and `#fullscreen_window`.
6
+ - Expand `Scope::Printing#print` with full W3C WebDriver parameters: `orientation`, `scale`, `background`, `page`, `margin`, `page_ranges`, and `shrink_to_fit`.
7
+
3
8
  ## v0.10.0
4
9
 
5
10
  - Introduce `Scope#wait_for_navigation` to properly wait for page navigations to complete.
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-webdriver
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -143,6 +143,7 @@ files:
143
143
  - lib/async/webdriver/scope/printing.rb
144
144
  - lib/async/webdriver/scope/screen_capture.rb
145
145
  - lib/async/webdriver/scope/timeouts.rb
146
+ - lib/async/webdriver/scope/window.rb
146
147
  - lib/async/webdriver/session.rb
147
148
  - lib/async/webdriver/version.rb
148
149
  - lib/async/webdriver/xpath.rb
@@ -163,14 +164,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
163
164
  requirements:
164
165
  - - ">="
165
166
  - !ruby/object:Gem::Version
166
- version: '3.2'
167
+ version: '3.3'
167
168
  required_rubygems_version: !ruby/object:Gem::Requirement
168
169
  requirements:
169
170
  - - ">="
170
171
  - !ruby/object:Gem::Version
171
172
  version: '0'
172
173
  requirements: []
173
- rubygems_version: 3.6.9
174
+ rubygems_version: 4.0.6
174
175
  specification_version: 4
175
176
  summary: A native library implementing the W3C WebDriver client specification.
176
177
  test_files: []
metadata.gz.sig CHANGED
Binary file