venetian 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ee4a825fffe442202e0321928ba3aea21c82eebc8dcd0d8e6672b24a46ed6236
4
+ data.tar.gz: 500819233fcdc8ee6b1c97adb96ddbd1637a9ddac642e0f9bac8b452e835ced4
5
+ SHA512:
6
+ metadata.gz: e8bcf1bcf0ac89adc4b7f4e84a439579f1edcd815edf608f1d2ffbe90532e2b079ed64af6e1a58923519083956a5720336bdfe9cab6f2e40baf88ec3d794a360
7
+ data.tar.gz: a8300d7492ad92ae6bf615978a1ce24cb2f41328bf0918be81fc770e0b1478922067314e893a4a133190e99da86b386a4effe21fd0ce83b9ee1c743b99e7912c
@@ -0,0 +1,10 @@
1
+ # Code of Conduct
2
+
3
+ "venetian" follows [The Ruby Community Conduct Guideline](https://www.ruby-lang.org/en/conduct) in all "collaborative space", which is defined as community communications channels (such as mailing lists, submitted patches, commit comments, etc.):
4
+
5
+ * Participants will be tolerant of opposing views.
6
+ * Participants must ensure that their language and actions are free of personal attacks and disparaging personal remarks.
7
+ * When interpreting the words and actions of others, participants should always assume good intentions.
8
+ * Behaviour which can be reasonably considered harassment will not be tolerated.
9
+
10
+ If you have any concerns about behaviour within this project, please contact us at ["j.malcic@me.com"](mailto:"j.malcic@me.com").
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2026 Justin Malčić
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,52 @@
1
+ # Venetian
2
+
3
+ Want stable system tests with Playwright, but don't want a Heath Robinson/Rube Goldberg setup in CI to try to keep the Ruby gem and Node
4
+ package in sync? This gem packages a Node executable plus the common Playwright package, using builds produced by Playwright for other
5
+ languages.
6
+
7
+ ## Installation
8
+
9
+ Install the gem and add to the application's Gemfile by executing:
10
+
11
+ ```bash
12
+ bundle add venetian --group test
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ In your system test case, choose the Playwright driver. Venetian will provide the base command to run Playwright,
18
+ which you can still override by passing `:playwright_cli_executable_path`, and this plus any other options will be passed through
19
+ to `capybara-playwright-driver`. If you specify a browser, this will be automatically downloaded if necessary.
20
+
21
+ ```ruby
22
+ require "test_helper"
23
+
24
+ class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
25
+ driven_by :playwright
26
+ end
27
+ ```
28
+
29
+ ## Development
30
+
31
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests.
32
+ You can also run `bin/console` for an interactive prompt that will allow you to experiment.
33
+
34
+ To install this gem onto your local machine, run `bundle exec rake install`.
35
+ To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`,
36
+ which will create a git tag for the version, push git commits and the created tag,
37
+ and push the `.gem` file to [rubygems.org](https://rubygems.org).
38
+
39
+ ## Contributing
40
+
41
+ Bug reports and pull requests are welcome on GitHub at https://github.com/jmalcic/venetian.
42
+ This project is intended to be a safe, welcoming space for collaboration, and contributors are expected
43
+ to adhere to the [code of conduct](https://www.ruby-lang.org/en/conduct/).
44
+
45
+ ## License
46
+
47
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
48
+
49
+ ## Code of Conduct
50
+
51
+ Everyone interacting in the Venetian project's codebases, issue trackers, chat rooms and mailing lists is expected
52
+ to follow the [code of conduct](https://www.ruby-lang.org/en/conduct/).
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "minitest/test_task"
5
+
6
+ Minitest::TestTask.create
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[test rubocop]
13
+
14
+ import "rakelib/release.rake"
data/exe/playwright ADDED
@@ -0,0 +1,11 @@
1
+ #! /usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "venetian"
5
+
6
+ begin
7
+ Venetian.execute(*ARGV, echo: ENV.fetch("VENETIAN_DEBUG", nil))
8
+ rescue Venetian::Executable::UnsupportedPlatformError, Venetian::Executable::ExecutableNotFoundError => e
9
+ warn "ERROR: #{e.message}"
10
+ exit 1
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :venetian do
4
+ desc <<~USAGE
5
+ Install Playwright browsers. Pass a name to install a specific browser (e.g. venetian:install[chromium]), else installs default browsers.
6
+ USAGE
7
+ task :install, [:browser] do |_task, args|
8
+ require "venetian"
9
+ Venetian::BrowserInstaller.install(args[:browser])
10
+ end
11
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Venetian
4
+ # # Browser Installer
5
+ #
6
+ # Installs browsers using the Playwright executable.
7
+ class BrowserInstaller
8
+ # # Install Error
9
+ #
10
+ # Raised when the installation fails for some reason.
11
+ class InstallError < StandardError
12
+ INSTALL_FAILED_MESSAGE = "Playwright install failed. Run `rake venetian:install` manually."
13
+
14
+ def initialize(message = nil)
15
+ super([INSTALL_FAILED_MESSAGE, *message].join(": "))
16
+ end
17
+ end
18
+
19
+ # Installs a browser. Raises InstallError if installation fails.
20
+ def self.install(browser = nil)
21
+ Executable.system "install", *browser&.to_s, exception: true
22
+ rescue StandardError => e
23
+ raise InstallError, e.message
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Venetian
4
+ module BrowserRunnerExtensions # :nodoc:
5
+ def initialize(options = {}, *args)
6
+ @venetian_browser_type = options[:browser_type] || :chromium
7
+ super
8
+ end
9
+
10
+ def start
11
+ BrowserInstaller.install(@venetian_browser_type) if Venetian.auto_install_browsers
12
+ super
13
+ end
14
+ end
15
+ end
16
+
17
+ Capybara::Playwright::BrowserRunner.prepend(Venetian::BrowserRunnerExtensions)
@@ -0,0 +1,154 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Venetian
4
+ # # \Executable
5
+ #
6
+ # Provides methods for locating the Playwright executable.
7
+ module Executable
8
+ DEFAULT_DIR = File.expand_path(File.join(__dir__, "..", "..", "exe")) # :nodoc:
9
+ INSTALL_DIR_ENV_VAR = "VENETIAN_INSTALL_DIR" # :nodoc:
10
+
11
+ # # Unsupported Platform Error
12
+ #
13
+ # Raised when no platform targeted by this gem is supported by the Rubygems installation.
14
+ class UnsupportedPlatformError < StandardError
15
+ def initialize(platform) # :nodoc:
16
+ super(unsupported_platform_message(platform))
17
+ end
18
+
19
+ private
20
+
21
+ def unsupported_platform_message(platform)
22
+ <<~MSG
23
+ Playwright does not support the #{platform} platform.
24
+ Supported platforms:
25
+ #{supported_platforms}
26
+
27
+ Set #{INSTALL_DIR_ENV_VAR} to the directory containing your playwright executable.
28
+ See https://github.com/jmalcic/venetian for more details.
29
+ MSG
30
+ end
31
+
32
+ def supported_platforms
33
+ Upstream::NATIVE_PLATFORMS.keys
34
+ .collect { |platform| "- #{platform}" }
35
+ .join("\n ")
36
+ end
37
+ end
38
+
39
+ # # Executable Not Found Error
40
+ #
41
+ # Raised when the Playwright executable cannot be found for the current platform.
42
+ class ExecutableNotFoundError < StandardError
43
+ def initialize(reason, **context) # :nodoc:
44
+ super(case reason
45
+ in :directory_missing then directory_missing_message(context[:exe_dir])
46
+ in :executable_missing then executable_missing_message(context[:exe_dir])
47
+ else unsupported_platform_message(context[:platform], context[:exe_dir])
48
+ end)
49
+ end
50
+
51
+ private
52
+
53
+ def directory_missing_message(exe_dir)
54
+ "#{INSTALL_DIR_ENV_VAR} is set to #{exe_dir} but that directory does not exist."
55
+ end
56
+
57
+ def executable_missing_message(exe_dir)
58
+ "#{INSTALL_DIR_ENV_VAR} is set to #{exe_dir} but playwright was not found there."
59
+ end
60
+
61
+ def unsupported_platform_message(platform, exe_dir)
62
+ <<~MSG
63
+ Cannot find the Playwright executable for #{platform} in #{exe_dir}.
64
+
65
+ Make sure your Gemfile.lock includes this platform:
66
+ bundle lock --add-platform #{platform}
67
+ bundle install
68
+
69
+ Or set #{INSTALL_DIR_ENV_VAR} to the directory containing your Playwright executable.
70
+ MSG
71
+ end
72
+ end
73
+
74
+ class << self
75
+ # Returns the path to the Node executable. Raises an error if the executable cannot be found.
76
+ def path
77
+ ensure_exe_dir_exists!
78
+ ensure_gem_platform_supported! unless ENV.key?(INSTALL_DIR_ENV_VAR)
79
+ ensure_executable_exists!
80
+
81
+ exe_path
82
+ end
83
+
84
+ # Executes the Playwright executable with the given arguments.
85
+ def execute(*args, echo: true)
86
+ [base_command, *args].then do |command|
87
+ puts command.inspect if echo
88
+ # due to mysterious Windows behavior; see equivalent in `tailwindcss-ruby`
89
+ next system(*command, exception: true) if Gem.win_platform?
90
+
91
+ exec(*command)
92
+ end
93
+ end
94
+
95
+ # Runs the Playwright executable with the given arguments.
96
+ def system(*args, echo: true, **)
97
+ [*base_command, *args].then do |command|
98
+ puts command.inspect if echo
99
+ super(*command, exception: true)
100
+ end
101
+ end
102
+
103
+ # Returns the base command to execute Playwright.
104
+ def base_command
105
+ [path, File.join(File.dirname(path), "package", "cli.js")]
106
+ end
107
+
108
+ private
109
+
110
+ def ensure_exe_dir_exists!
111
+ raise ExecutableNotFoundError.new(:directory_missing, exe_dir: exe_dir) unless exe_dir_exists?
112
+ end
113
+
114
+ def ensure_gem_platform_supported!
115
+ raise UnsupportedPlatformError, platform if gem_platforms_unsupported?
116
+ end
117
+
118
+ def ensure_executable_exists!
119
+ return unless exe_path.nil?
120
+
121
+ raise ExecutableNotFoundError.new ENV.key?(INSTALL_DIR_ENV_VAR) ? :executable_missing : :missing_platform,
122
+ exe_dir: exe_dir, platform: platform
123
+ end
124
+
125
+ def exe_dir_exists?
126
+ File.directory?(exe_dir)
127
+ end
128
+
129
+ def exe_dir
130
+ ENV[INSTALL_DIR_ENV_VAR] || DEFAULT_DIR
131
+ end
132
+
133
+ def exe_path
134
+ return custom_exe_path if ENV.key?(INSTALL_DIR_ENV_VAR)
135
+
136
+ Upstream::NATIVE_PLATFORMS.select { |platform, _| Gem::Platform.match_gem?(Gem::Platform.new(platform), GEMSPEC.name) }
137
+ .collect { |platform, _info| File.join(exe_dir, platform, "node") }
138
+ .detect { |candidate| File.exist?(candidate) }
139
+ end
140
+
141
+ def custom_exe_path
142
+ File.join(exe_dir, "node").then { |path| path if File.exist?(path) }
143
+ end
144
+
145
+ def gem_platforms_unsupported?
146
+ Upstream::NATIVE_PLATFORMS.keys.none? { |platform| Gem::Platform.match_gem?(Gem::Platform.new(platform), GEMSPEC.name) }
147
+ end
148
+
149
+ def platform
150
+ Gem::Platform.local.to_s
151
+ end
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Venetian
4
+ GEMSPEC = Gem.loaded_specs.values.reverse.find do |spec|
5
+ spec.gem_dir == Pathname.new(__dir__).join("..", "..").expand_path.to_path
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Venetian
4
+ module PlaywrightCreateExtensions # :nodoc:
5
+ def initialize(options = {}, *)
6
+ super({ playwright_cli_executable_path: Executable.base_command.shelljoin }.merge(options), *)
7
+ end
8
+ end
9
+ end
10
+
11
+ Capybara::Playwright::BrowserRunner::PlaywrightCreate.prepend(Venetian::PlaywrightCreateExtensions)
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Venetian
4
+ class Railtie < Rails::Railtie # :nodoc:
5
+ rake_tasks do
6
+ load "tasks/venetian.rake"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ load "tasks/venetian.rake"
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "playwright"
4
+
5
+ module Venetian
6
+ # # \Upstream
7
+ #
8
+ # Provides platform mappings and URLs for Playwright.
9
+ module Upstream
10
+ # map of gem platform strings to Playwright CDN platform strings and executable names inside the driver zip
11
+ NATIVE_PLATFORMS = {
12
+ "x86_64-linux" => "linux",
13
+ "aarch64-linux" => "linux-arm64",
14
+ "x86_64-darwin" => "mac",
15
+ "arm64-darwin" => "mac-arm64",
16
+ "x64-mingw-ucrt" => "win32_x64"
17
+ }.freeze
18
+
19
+ # base for driver download URLs
20
+ BASE_URL = "https://playwright.azureedge.net/builds/driver"
21
+
22
+ # Returns the URL to download the driver for the given platform.
23
+ def self.driver_download_url(playwright_platform)
24
+ "#{BASE_URL}/playwright-#{Playwright::COMPATIBLE_PLAYWRIGHT_VERSION}-#{playwright_platform}.zip"
25
+ end
26
+
27
+ # Returns a hash that maps platforms to download URLs.
28
+ def self.download_urls
29
+ NATIVE_PLATFORMS.transform_values { |value| driver_download_url(value) }
30
+ end
31
+
32
+ # Returns the gemspec files for the base gem.
33
+ def self.base_files
34
+ GEMSPEC.files
35
+ end
36
+
37
+ # Builds a gemspec for the given platform, adding the files currently in the native platform directory.
38
+ def self.build_gemspec_for(platform)
39
+ GEMSPEC.dup.tap do |s|
40
+ s.platform = platform
41
+ s.files += Dir["exe/#{platform}/**/*"]
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Venetian
4
+ VERSION = "0.1.0"
5
+ end
data/lib/venetian.rb ADDED
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "capybara/playwright"
4
+
5
+ require "venetian/version"
6
+ require "venetian/upstream"
7
+ require "venetian/executable"
8
+ require "venetian/playwright_create_extensions"
9
+ require "venetian/browser_installer"
10
+ require "venetian/browser_runner_extensions"
11
+ require "venetian/gemspec"
12
+ require "venetian/railtie" if defined? Rails
13
+
14
+ # # Venetian
15
+ #
16
+ # Native Playwright driver for Capybara.
17
+ module Venetian
18
+ class << self
19
+ attr_accessor :auto_install_browsers
20
+ end
21
+
22
+ class Error < StandardError; end
23
+
24
+ self.auto_install_browsers = true
25
+
26
+ def self.execute(*, echo: true)
27
+ Executable.execute(*, echo: echo)
28
+ end
29
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: venetian
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Justin Malčić
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: capybara-playwright-driver
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '0.5'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '0.5'
26
+ description: Bundles the Playwright driver binary in platform-specific gem variants
27
+ and integrates with `capybara-playwright-driver`.
28
+ email:
29
+ - j.malcic@me.com
30
+ executables:
31
+ - playwright
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - CODE_OF_CONDUCT.md
36
+ - LICENSE.txt
37
+ - README.md
38
+ - Rakefile
39
+ - exe/playwright
40
+ - lib/tasks/venetian.rake
41
+ - lib/venetian.rb
42
+ - lib/venetian/browser_installer.rb
43
+ - lib/venetian/browser_runner_extensions.rb
44
+ - lib/venetian/executable.rb
45
+ - lib/venetian/gemspec.rb
46
+ - lib/venetian/playwright_create_extensions.rb
47
+ - lib/venetian/railtie.rb
48
+ - lib/venetian/tasks.rb
49
+ - lib/venetian/upstream.rb
50
+ - lib/venetian/version.rb
51
+ homepage: https://github.com/jmalcic/venetian
52
+ licenses:
53
+ - MIT
54
+ metadata:
55
+ homepage_uri: https://malcic.codes/software/venetian
56
+ source_code_uri: https://github.com/jmalcic/venetian
57
+ rubygems_mfa_required: 'true'
58
+ rdoc_options: []
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: 3.3.0
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ requirements: []
72
+ rubygems_version: 4.0.10
73
+ specification_version: 4
74
+ summary: Playwright executables for Ruby
75
+ test_files: []