venetian 0.3.0 → 0.3.1

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: 0c599b422e667a871ef1b770d925eba77b670865bc3e93d453467f8868158a96
4
- data.tar.gz: 10c75b357f976409bc73a3e7cb478e00f5f5bb34e2fdbcb02917ca88e96599e7
3
+ metadata.gz: aafa47a0f14da5b53e15342d47066d1949662794fd51bbcccf5c557a9aaa85ea
4
+ data.tar.gz: 0e3a2e04f9f0bc780f119767e4f681a2cd859b7962acd24b895f6b3f5a2d8148
5
5
  SHA512:
6
- metadata.gz: 78a685bc7a929fd1305905e727912787162f85f88d05983e4c1649d06a8a3055e37b9ba6bb979ca5ef3d15be2619b1ff93e46394849154d079081c5b7a10adfb
7
- data.tar.gz: 26e00d4ce95a2f03f5f816272788d917d092d78aae6de9423acb488021d74e9e9cfd19323e85d6e1c3644a23269de12b2357f9d935d39f0fc238f28eea17ecab
6
+ metadata.gz: dab03d644e9b48c4a0563767a997abff66a0d79161e575bcea79a26bd1c84efee33a73ba774d3612df3a7b8faecbaab5acf50411246381de6966607f0e2ed094
7
+ data.tar.gz: 5f024a8121cd70f4e48182cc192da2ed703b58c36b127969d673265fa994c67b88484a2665e171ebe6e8a1843d7d02cf83b4a8510c6964d425df819e09a851d9
data/README.md CHANGED
@@ -80,13 +80,20 @@ due to e.g. differences between package managers and package names across distro
80
80
  so dependency installation happens only if a compatible package manager is found.
81
81
  Depending on what you're doing, you may not need to install dependencies,
82
82
  but if you do and your distro is unsupported, you will need to work out what you need and deal with that first.
83
+ On Windows, Firefox also needs the [Microsoft Visual C++ Redistributable](https://learn.microsoft.com/cpp/windows/latest-supported-vc-redist),
84
+ which Playwright doesn't install; you'll get a warning after installation if it's missing.
83
85
 
84
- When parallelizing tests, there's also the issue of multiple processes all trying to acquire the package manager lock:
85
- if you use Rails system tests with `ActionDispatch::SystemTestCase`,
86
- this is handled automatically by installing all required browsers before disabling auto-installation and then forking.
86
+ Browsers already installed (e.g. from a restored cache) are left alone. If the browsers directory
87
+ (or `PLAYWRIGHT_BROWSERS_PATH`, if set) is read-only, as with a prepopulated cache, browsers aren't installed at all,
88
+ since Playwright can't take its lock there, though dependencies still are if needed.
89
+ When parallelizing tests, there's also the issue of multiple processes all trying to acquire the package manager lock,
90
+ so installations are serialized across processes. On top of this, if you use Rails system tests with `ActionDispatch::SystemTestCase`,
91
+ all required browsers are installed before disabling auto-installation and then forking.
87
92
 
88
93
  Browsers aren't installed automatically if you pass your own `:playwright_cli_executable_path`, or connect to a server with
89
94
  `:playwright_server_endpoint_url` or `:browser_server_endpoint_url`, since the bundled executable won't be the one running them.
95
+ Nor are they if you pass `:executablePath`, or a `:channel` for a system-wide browser like `chrome` or `msedge`
96
+ (install these with e.g. `playwright install chrome`), but other channels are installed instead of the browser type.
90
97
  You can also turn installation off with `Venetian.auto_install_browsers = false`, or just dependency installation with
91
98
  `Venetian.auto_install_dependencies = false`.
92
99
 
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "pathname"
4
+ require "tmpdir"
5
+
3
6
  module Venetian
4
7
  # # Browser Installer
5
8
  #
@@ -18,10 +21,63 @@ module Venetian
18
21
  Executable.capture("install-deps", *browser&.to_s, "--dry-run", echo: debug?)
19
22
  end
20
23
 
24
+ def install_into_browsers_path(browser, deps: nil)
25
+ if browsers_to_install.fetch(browser) { browsers_path_writable? }
26
+ run_installer "install", *browser, *("--with-deps" if deps)
27
+ elsif deps
28
+ run_installer "install-deps", *browser
29
+ end
30
+ browsers_to_install[browser] = false
31
+ dependencies_to_install[browser] = false if deps
32
+ end
33
+
34
+ def browsers_path_writable?
35
+ [expanded_browsers_path, expanded_browsers_path.join(LINKS_DIRECTORY)].all? do |path|
36
+ Dir.mktmpdir(WRITE_PROBE_PREFIX, path.ascend.find(&:directory?)) { true }
37
+ end
38
+ rescue SystemCallError
39
+ false
40
+ end
41
+
42
+ def default_cache_path
43
+ if Gem.win_platform?
44
+ env_path("LOCALAPPDATA") || Pathname(Dir.home).join("AppData", "Local")
45
+ elsif Gem::Platform.local.os == "darwin"
46
+ Pathname(Dir.home).join("Library", "Caches")
47
+ else
48
+ env_path("XDG_CACHE_HOME") || Pathname(Dir.home).join(".cache")
49
+ end
50
+ end
51
+
52
+ def env_path(name)
53
+ return if (path = ENV.fetch(name, "")).empty?
54
+
55
+ Pathname(path)
56
+ end
57
+
21
58
  def dependencies_to_install
22
59
  @dependencies_to_install ||= {}
23
60
  end
24
61
 
62
+ def browsers_to_install
63
+ @browsers_to_install ||= {}
64
+ end
65
+
66
+ def with_install_lock
67
+ File.open(File.join(Dir.tmpdir, "venetian-#{Process.uid}.lock"), File::RDWR | File::CREAT, 0o600) do |file|
68
+ file.flock(File::LOCK_EX)
69
+ yield
70
+ end
71
+ end
72
+
73
+ def run_installer(*args)
74
+ return Venetian.system(*args, exception: true, echo: true) if debug?
75
+
76
+ Executable.capture(*args, echo: false, merge_stderr: false).then do |output, status|
77
+ raise InstallError, "exit status #{status.exitstatus}\n#{output}".strip unless status.success?
78
+ end
79
+ end
80
+
25
81
  def debug?
26
82
  ENV.fetch("VENETIAN_DEBUG", nil)
27
83
  end
@@ -36,17 +92,26 @@ module Venetian
36
92
  def initialize(message = nil)
37
93
  super([INSTALL_FAILED_MESSAGE, *message].join(": "))
38
94
  end
95
+
96
+ def self.wrap(error) # :nodoc:
97
+ error.is_a?(self) ? error : new(error.message)
98
+ end
39
99
  end
40
100
 
41
- # Installs a browser. Raises InstallError if installation fails.
101
+ # Installs a browser, unless it and any dependencies are already installed. Playwright skips browsers already in the
102
+ # browsers path, and if that's read-only (e.g. a prepopulated cache), only dependencies are installed. Raises
103
+ # InstallError if installation fails.
42
104
  def self.install(browser = nil, install_dependencies: nil)
43
- Venetian.system "install", *browser&.to_s,
44
- *("--with-deps" if install_dependencies?(browser, force: install_dependencies)),
45
- exception: true, echo: debug?
105
+ with_install_lock do
106
+ install_into_browsers_path(browser&.to_s, deps: install_dependencies?(browser, force: install_dependencies))
107
+ end
46
108
  rescue StandardError => e
47
- raise InstallError, e.message
109
+ raise InstallError.wrap(e)
48
110
  end
49
111
 
112
+ LINKS_DIRECTORY = ".links" # :nodoc:
113
+ WRITE_PROBE_PREFIX = ".venetian-write-probe" # :nodoc:
114
+
50
115
  # Output from a dry run where Playwright couldn't spawn its package manager, so has no way to install dependencies.
51
116
  NO_PACKAGE_MANAGER_OUTPUT = "ENOENT" # :nodoc:
52
117
 
@@ -68,6 +133,18 @@ module Venetian
68
133
  end
69
134
  end
70
135
 
136
+ def self.browsers_path # :nodoc:
137
+ case ENV.fetch("PLAYWRIGHT_BROWSERS_PATH", "")
138
+ when "" then default_cache_path.join("ms-playwright")
139
+ when "0" then Pathname(Executable.base_command.last).dirname.join(".local-browsers")
140
+ else Pathname(ENV.fetch("PLAYWRIGHT_BROWSERS_PATH"))
141
+ end
142
+ end
143
+
144
+ def self.expanded_browsers_path # :nodoc:
145
+ browsers_path.expand_path(ENV.fetch("INIT_CWD", nil) || Dir.pwd)
146
+ end
147
+
71
148
  def self.dependencies_supported?(...) # :nodoc:
72
149
  warn "Venetian::BrowserInstaller.dependencies_supported? is deprecated; use dependencies_to_install? instead.",
73
150
  category: :deprecated, uplevel: 1
@@ -4,18 +4,22 @@ module Venetian
4
4
  module BrowserRunnerExtensions # :nodoc:
5
5
  ALTERNATIVE_DRIVER_OPTIONS = %i[playwright_cli_executable_path playwright_server_endpoint_url
6
6
  browser_server_endpoint_url].freeze
7
+ SYSTEM_CHANNEL_PATTERN = /\A(chrome|msedge)/
7
8
 
8
9
  def self.browser_to_preinstall_from(options)
9
- (options[:browser_type] || :chromium).to_sym if options.values_at(*ALTERNATIVE_DRIVER_OPTIONS).none?
10
+ return if options.values_at(*ALTERNATIVE_DRIVER_OPTIONS, :executablePath).any?
11
+ return if options[:channel].to_s.match?(SYSTEM_CHANNEL_PATTERN)
12
+
13
+ (options[:channel] || options[:browser_type] || :chromium).to_sym
10
14
  end
11
15
 
12
16
  def initialize(options = {}, *args)
13
- @venetian_browser = BrowserRunnerExtensions.browser_to_preinstall_from(options) if Venetian.auto_install_browsers
17
+ @venetian_browser = BrowserRunnerExtensions.browser_to_preinstall_from(options)
14
18
  super
15
19
  end
16
20
 
17
21
  def start
18
- BrowserInstaller.install(@venetian_browser) if @venetian_browser
22
+ BrowserInstaller.install(@venetian_browser) if @venetian_browser && Venetian.auto_install_browsers
19
23
  super
20
24
  end
21
25
  end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Venetian
4
+ # # Forked Connection Error
5
+ #
6
+ # Raised when a Playwright connection is used by a process forked from the one that started it.
7
+ class ForkedConnectionError < Error
8
+ def initialize(pid) # :nodoc:
9
+ super("This Playwright connection belongs to process #{pid}, so can't be used after forking. " \
10
+ "Start Playwright again in this process instead.")
11
+ end
12
+ end
13
+
14
+ module ConnectionExtensions # :nodoc:
15
+ def initialize(...)
16
+ @venetian_pid = Process.pid
17
+ super
18
+ end
19
+
20
+ def async_send_message_to_server(...)
21
+ raise ForkedConnectionError, @venetian_pid unless Process.pid == @venetian_pid
22
+
23
+ super
24
+ end
25
+ end
26
+ end
27
+
28
+ Playwright::Connection.prepend(Venetian::ConnectionExtensions)
@@ -11,8 +11,12 @@ module Venetian
11
11
  class Executor # :nodoc:
12
12
  public :system, :exec
13
13
 
14
- def capture(*command)
15
- Open3.capture2e(*command)
14
+ def capture(*command, merge_stderr: true, **)
15
+ merge_stderr ? Open3.capture2e(*command, **) : Open3.capture2(*command, **)
16
+ end
17
+
18
+ def run(*command, **)
19
+ Process.wait2(Process.spawn(*command, **)).last
16
20
  end
17
21
  end
18
22
 
@@ -51,11 +55,14 @@ module Venetian
51
55
  #
52
56
  # Raised when the Playwright executable cannot be found for the current platform.
53
57
  class ExecutableNotFoundError < StandardError
54
- def initialize(reason, **context) # :nodoc:
58
+ def initialize(reason, exe_dir: nil, exe_path: nil, cli_path: nil, platform: nil) # :nodoc:
55
59
  super(case reason
56
- in :directory_missing then directory_missing_message(context[:exe_dir])
57
- in :executable_missing then executable_missing_message(context[:exe_dir])
58
- else unsupported_platform_message(context[:platform], context[:exe_dir])
60
+ in :directory_missing then directory_missing_message(exe_dir)
61
+ in :executable_missing then executable_missing_message(exe_dir)
62
+ in :missing_platform then unsupported_platform_message(platform, exe_dir)
63
+ in :not_a_file then incomplete_message(exe_path, "#{exe_path} is not a file")
64
+ in :not_executable then incomplete_message(exe_path, "#{exe_path} is not executable")
65
+ in :cli_missing then incomplete_message(exe_path, "#{cli_path} is missing")
59
66
  end)
60
67
  end
61
68
 
@@ -69,6 +76,14 @@ module Venetian
69
76
  "#{INSTALL_DIR_ENV_VAR} is set to #{exe_dir} but playwright was not found there."
70
77
  end
71
78
 
79
+ def incomplete_message(exe_path, problem)
80
+ <<~MSG
81
+ The Playwright driver at #{File.dirname(exe_path)} is incomplete: #{problem}.
82
+
83
+ Reinstall the gem, or check #{INSTALL_DIR_ENV_VAR} points to a complete driver.
84
+ MSG
85
+ end
86
+
72
87
  def unsupported_platform_message(platform, exe_dir)
73
88
  <<~MSG
74
89
  Cannot find the Playwright executable for #{platform} in #{exe_dir}.
@@ -82,28 +97,103 @@ module Venetian
82
97
  end
83
98
  end
84
99
 
85
- class << self
86
- # Returns the path to the Node executable. Raises an error if the executable cannot be found.
87
- def path
100
+ # # Unsupported Path Error
101
+ #
102
+ # Raised on Windows when the path to the Playwright executable contains an environment variable reference such as
103
+ # +%USERNAME%+, as Ruby would then run the command with +cmd.exe+, which expands it.
104
+ class UnsupportedPathError < StandardError
105
+ def initialize(path) # :nodoc:
106
+ super(<<~MSG)
107
+ Cannot run Playwright from #{path} as Windows would expand the environment variable references in its path.
108
+
109
+ Set #{INSTALL_DIR_ENV_VAR} to a directory without them (e.g. %NAME%) containing your Playwright executable.
110
+ MSG
111
+ end
112
+ end
113
+
114
+ module Command # :nodoc:
115
+ TOKEN_PATTERN = /\\.?|%[A-Za-z_][A-Za-z0-9_]*.?|./m
116
+ VARIABLE_REFERENCE_PATTERN = /\A%[A-Za-z_][A-Za-z0-9_]*%\z/
117
+
118
+ def self.shelljoin(command)
119
+ return command.shelljoin unless Gem.win_platform?
120
+
121
+ command.collect { |arg| %("#{arg}") }
122
+ .join(" ")
123
+ .tap { |string| raise UnsupportedPathError, command.first if run_by_cmd?(string) }
124
+ end
125
+
126
+ def self.run_by_cmd?(string)
127
+ string.scan(TOKEN_PATTERN).any? { |token| token.match?(VARIABLE_REFERENCE_PATTERN) }
128
+ end
129
+ end
130
+
131
+ module Validations # :nodoc:
132
+ private
133
+
134
+ def validate!
88
135
  ensure_exe_dir_exists!
89
136
  ensure_gem_platform_supported! unless ENV.key?(INSTALL_DIR_ENV_VAR)
90
137
  ensure_executable_exists!
138
+ ensure_exe_file!
139
+ ensure_exe_executable!
140
+ ensure_cli_path_exists!
141
+ end
142
+
143
+ def ensure_exe_dir_exists!
144
+ raise ExecutableNotFoundError.new(:directory_missing, exe_dir: exe_dir) unless exe_dir_exists?
145
+ end
146
+
147
+ def ensure_gem_platform_supported!
148
+ raise UnsupportedPlatformError, platform if gem_platforms_unsupported?
149
+ end
150
+
151
+ def ensure_executable_exists!
152
+ return unless exe_path.nil?
153
+
154
+ raise ExecutableNotFoundError.new ENV.key?(INSTALL_DIR_ENV_VAR) ? :executable_missing : :missing_platform,
155
+ exe_dir: exe_dir, platform: platform
156
+ end
157
+
158
+ def ensure_exe_file!
159
+ return if exe_file?
160
+
161
+ raise ExecutableNotFoundError.new(:not_a_file, exe_path: exe_path)
162
+ end
163
+
164
+ def ensure_exe_executable!
165
+ return if exe_executable?
166
+
167
+ raise ExecutableNotFoundError.new(:not_executable, exe_path: exe_path)
168
+ end
169
+
170
+ def ensure_cli_path_exists!
171
+ return if cli_path_exists?
172
+
173
+ raise ExecutableNotFoundError.new(:cli_missing, exe_path: exe_path, cli_path: cli_path_for(exe_path))
174
+ end
175
+ end
176
+
177
+ extend Validations
178
+
179
+ class << self
180
+ # Returns the path to the Node executable. Raises an error if the executable cannot be found.
181
+ def path
182
+ validate!
91
183
 
92
184
  exe_path
93
185
  end
94
186
 
95
- # Executes the Playwright executable with the given arguments.
187
+ # Executes the Playwright executable with the given arguments, replacing the current process.
96
188
  def execute(*args, echo: true, exception: true, **)
97
189
  [*base_command, *args].then do |command|
98
- # due to mysterious Windows behavior; see equivalent in `tailwindcss-ruby`
99
- next system(*args, exception:, echo:) if Gem.win_platform?
100
-
101
190
  puts command.shelljoin if echo
102
- begin
103
- executor.exec(*command)
104
- rescue StandardError
105
- exception ? raise : false
106
- end
191
+ # exec misbehaves on Windows (see equivalent in `tailwindcss-ruby`), so run Playwright and exit likewise
192
+ exit executor.run(*command, **).exitstatus if Gem.win_platform?
193
+
194
+ executor.exec(*command, **)
195
+ rescue StandardError
196
+ exception ? raise : false
107
197
  end
108
198
  end
109
199
 
@@ -111,16 +201,15 @@ module Venetian
111
201
  def system(*args, echo: true, exception: true, **)
112
202
  [*base_command, *args].then do |command|
113
203
  puts command.shelljoin if echo
114
- executor.system(*command,
115
- exception:, **{ out: echo ? nil : File::NULL, err: echo ? nil : File::NULL }.compact)
204
+ executor.system(*command, exception:, **(echo ? {} : { out: File::NULL, err: File::NULL }), **)
116
205
  end
117
206
  end
118
207
 
119
208
  # Runs the Playwright executable with the given arguments, returning its combined output and status.
120
- def capture(*args, echo: true)
209
+ def capture(*args, echo: true, **)
121
210
  [*base_command, *args].then do |command|
122
211
  puts command.shelljoin if echo
123
- executor.capture(*command).tap do |output, _|
212
+ executor.capture(*command, **).tap do |output, _|
124
213
  puts output if echo
125
214
  end
126
215
  end
@@ -128,50 +217,45 @@ module Venetian
128
217
 
129
218
  # Returns the base command to execute Playwright.
130
219
  def base_command
131
- [path, File.join(File.dirname(path), "package", "cli.js")]
220
+ path.then { |path| [path, cli_path_for(path)] }
132
221
  end
133
222
 
134
223
  # Returns the base command as a single string, as expected by +:playwright_cli_executable_path+.
135
224
  def cli_command
136
- if Gem.win_platform?
137
- base_command.collect { |arg| %("#{arg}") }
138
- .join(" ")
139
- else
140
- base_command.shelljoin
141
- end
225
+ Command.shelljoin(base_command)
142
226
  end
143
227
 
144
228
  private
145
229
 
146
- def ensure_exe_dir_exists!
147
- raise ExecutableNotFoundError.new(:directory_missing, exe_dir: exe_dir) unless exe_dir_exists?
230
+ def exe_dir_exists?
231
+ File.directory?(exe_dir)
148
232
  end
149
233
 
150
- def ensure_gem_platform_supported!
151
- raise UnsupportedPlatformError, platform if gem_platforms_unsupported?
234
+ def exe_dir
235
+ ENV[INSTALL_DIR_ENV_VAR] || DEFAULT_DIR
152
236
  end
153
237
 
154
- def ensure_executable_exists!
155
- return unless exe_path.nil?
238
+ def exe_file?
239
+ File.file?(exe_path.to_s)
240
+ end
156
241
 
157
- raise ExecutableNotFoundError.new ENV.key?(INSTALL_DIR_ENV_VAR) ? :executable_missing : :missing_platform,
158
- exe_dir: exe_dir, platform: platform
242
+ def exe_executable?
243
+ File.executable?(exe_path.to_s)
159
244
  end
160
245
 
161
- def exe_dir_exists?
162
- File.directory?(exe_dir)
246
+ def cli_path_exists?
247
+ File.file?(cli_path_for(exe_path))
163
248
  end
164
249
 
165
- def exe_dir
166
- ENV[INSTALL_DIR_ENV_VAR] || DEFAULT_DIR
250
+ def cli_path_for(exe_path)
251
+ File.join(File.dirname(exe_path), "package", "cli.js")
167
252
  end
168
253
 
169
254
  def exe_path
170
255
  return custom_exe_path if ENV.key?(INSTALL_DIR_ENV_VAR)
171
256
 
172
- Upstream::NATIVE_PLATFORMS.select { |platform, _| Gem::Platform.match_gem?(Gem::Platform.new(platform), gem_name) }
173
- .collect { |platform, info| File.join(exe_dir, platform, info.executable_name) }
174
- .detect { |candidate| File.exist?(candidate) }
257
+ native_platforms.collect { |platform, info| File.join(exe_dir, platform, info.executable_name) }
258
+ .detect { |candidate| File.exist?(candidate) }
175
259
  end
176
260
 
177
261
  def custom_exe_path
@@ -183,7 +267,17 @@ module Venetian
183
267
  end
184
268
 
185
269
  def gem_platforms_unsupported?
186
- Upstream::NATIVE_PLATFORMS.keys.none? { |platform| Gem::Platform.match_gem?(Gem::Platform.new(platform), gem_name) }
270
+ native_platforms.none?
271
+ end
272
+
273
+ def native_platforms
274
+ return {} if musl? # musl isn't supported because official Linux Node binaries require glibc
275
+
276
+ Upstream::NATIVE_PLATFORMS.select { |platform, _| Gem::Platform.match_gem?(Gem::Platform.new(platform), gem_name) }
277
+ end
278
+
279
+ def musl?
280
+ Gem::Platform.local.then { |local| local.os == "linux" && local.version.to_s.start_with?("musl") }
187
281
  end
188
282
 
189
283
  def gem_name
@@ -3,6 +3,7 @@
3
3
  require "playwright"
4
4
 
5
5
  require "venetian/core"
6
+ require "venetian/connection_extensions"
6
7
 
7
8
  module Venetian # :nodoc:
8
9
  # Starts Playwright using the bundled executable. Accepts the same arguments as +Playwright.create+,
@@ -1,24 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Venetian
4
- module SystemTestCaseExtension # :nodoc:
4
+ module SystemTestCaseExtension # :nodoc: all
5
5
  extend ActiveSupport::Concern
6
6
 
7
+ module ParallelizationExtension
8
+ def start
9
+ ActionDispatch::SystemTestCase.venetian_before_fork
10
+ super
11
+ end
12
+ end
13
+
7
14
  prepended do
8
- class_attribute :venetian_browser_type, default: :chromium, instance_writer: false
15
+ # Set by +driven_by+, so classes using a driver registered under another name are still included.
16
+ class_attribute :venetian_browser_type, default: nil, instance_writer: false
9
17
 
10
- parallelize_before_fork do
11
- install_playwright_browsers if venetian_preinstall_browsers_before_fork?
18
+ if respond_to?(:parallelize_before_fork)
19
+ parallelize_before_fork { venetian_before_fork }
20
+ else
21
+ ActiveSupport::Testing::Parallelization.prepend(ParallelizationExtension)
12
22
  end
13
23
  end
14
24
 
15
- class_methods do # :nodoc:
25
+ class_methods do
16
26
  def driven_by(driver, options: {}, **)
17
- super
18
-
19
27
  self.venetian_browser_type = if driver == :playwright
20
28
  BrowserRunnerExtensions.browser_to_preinstall_from(options)
21
29
  end
30
+ super
22
31
  end
23
32
 
24
33
  def install_playwright_browsers
@@ -28,6 +37,10 @@ module Venetian
28
37
  end
29
38
  end
30
39
 
40
+ def venetian_before_fork
41
+ install_playwright_browsers if venetian_preinstall_browsers_before_fork?
42
+ end
43
+
31
44
  private
32
45
 
33
46
  def venetian_preinstall_browsers_before_fork?
@@ -36,7 +49,7 @@ module Venetian
36
49
 
37
50
  def venetian_browsers
38
51
  Minitest::Runnable.runnables
39
- .select { |klass| klass < ActionDispatch::SystemTestCase && klass.driver&.name == :playwright }
52
+ .select { |klass| klass < ActionDispatch::SystemTestCase }
40
53
  .filter_map(&:venetian_browser_type)
41
54
  .uniq
42
55
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "playwright/version"
3
+ require "venetian/version"
4
4
 
5
5
  module Venetian
6
6
  # # \Upstream
@@ -43,7 +43,7 @@ module Venetian
43
43
 
44
44
  # Returns the URL to download the playwright-core npm package containing the driver's JS sources.
45
45
  def self.playwright_core_url
46
- "#{NPM_REGISTRY_URL}/playwright-core/-/playwright-core-#{Playwright::COMPATIBLE_PLAYWRIGHT_VERSION}.tgz"
46
+ "#{NPM_REGISTRY_URL}/playwright-core/-/playwright-core-#{COMPATIBLE_PLAYWRIGHT_VERSION}.tgz"
47
47
  end
48
48
 
49
49
  # Returns the gemspec files for the base gem.
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Venetian
4
- VERSION = "0.3.0"
4
+ VERSION = "0.3.1"
5
5
  COMPATIBLE_PLAYWRIGHT_VERSION = "1.63.0"
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: venetian
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Malčić
@@ -27,14 +27,14 @@ dependencies:
27
27
  name: playwright-ruby-client
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
- - - ">="
30
+ - - "~>"
31
31
  - !ruby/object:Gem::Version
32
32
  version: 1.63.0
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
- - - ">="
37
+ - - "~>"
38
38
  - !ruby/object:Gem::Version
39
39
  version: 1.63.0
40
40
  description: Bundles the Playwright driver binary in platform-specific gem variants
@@ -55,6 +55,7 @@ files:
55
55
  - lib/venetian.rb
56
56
  - lib/venetian/browser_installer.rb
57
57
  - lib/venetian/browser_runner_extensions.rb
58
+ - lib/venetian/connection_extensions.rb
58
59
  - lib/venetian/core.rb
59
60
  - lib/venetian/executable.rb
60
61
  - lib/venetian/gemspec.rb