From 7054254b601a2eb05947e0d14bd9c5311aaa1307 Mon Sep 17 00:00:00 2001 From: Jonathan Hefner Date: Mon, 29 Jul 2024 13:42:18 -0500 Subject: [PATCH] Test installer commands (#182) * Add testing infrastructure This adds testing infrastructure to test against multiple versions of Rails, including Rails `main` branch. * Test shared behavior of installer commands This adds test coverage for the shared behavior of the installer commands. The commands are tested against a freshly generated Rails app using the version of Rails that is currently loaded. Thus the installers can be tested with different versions of Rails in CI. * Test specific behavior of javascript:install:bun This adds test coverage for specific behavior of the `javascript:install:bun` command. * Test specific behavior of javascript:install:esbuild This adds test coverage for specific behavior of the `javascript:install:esbuild` command. * Test specific behavior of javascript:install:rollup This adds test coverage for specific behavior of the `javascript:install:rollup` command. * Test specific behavior of javascript:install:webpack This adds test coverage for specific behavior of the `javascript:install:webpack` command. --- .github/workflows/ci.yml | 40 +++++ .gitignore | 4 + Appraisals | 14 ++ Gemfile | 6 +- Gemfile.lock | 257 ++++++++++++++++++-------------- Rakefile | 10 ++ gemfiles/rails_7_0.gemfile | 21 +++ gemfiles/rails_7_0.gemfile.lock | 220 +++++++++++++++++++++++++++ gemfiles/rails_7_1.gemfile | 21 +++ gemfiles/rails_7_1.gemfile.lock | 253 +++++++++++++++++++++++++++++++ gemfiles/rails_main.gemfile | 21 +++ test/bun_installer_test.rb | 55 +++++++ test/esbuild_installer_test.rb | 28 ++++ test/rollup_installer_test.rb | 31 ++++ test/shared_installer_tests.rb | 99 ++++++++++++ test/test_helper.rb | 71 +++++++++ test/webpack_installer_test.rb | 31 ++++ 17 files changed, 1066 insertions(+), 116 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 Appraisals create mode 100644 Rakefile create mode 100644 gemfiles/rails_7_0.gemfile create mode 100644 gemfiles/rails_7_0.gemfile.lock create mode 100644 gemfiles/rails_7_1.gemfile create mode 100644 gemfiles/rails_7_1.gemfile.lock create mode 100644 gemfiles/rails_main.gemfile create mode 100644 test/bun_installer_test.rb create mode 100644 test/esbuild_installer_test.rb create mode 100644 test/rollup_installer_test.rb create mode 100644 test/shared_installer_tests.rb create mode 100644 test/test_helper.rb create mode 100644 test/webpack_installer_test.rb diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..2c4a53c --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,40 @@ +name: CI +on: [push, pull_request] +jobs: + tests: + strategy: + fail-fast: false + matrix: + ruby-version: + - "3.1" + - "3.2" + - "3.3" + gemfile: + - gemfiles/rails_7_0.gemfile + - gemfiles/rails_7_1.gemfile + - gemfiles/rails_main.gemfile + continue-on-error: [ false ] + + name: ${{ format('Tests (Ruby {0}, {1})', matrix.ruby-version, matrix.gemfile) }} + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.continue-on-error }} + + env: + BUNDLE_GEMFILE: ${{ matrix.gemfile }} + + steps: + - uses: actions/checkout@v4 + + - name: Remove Gemfile lock + run: | + rm -f $BUNDLE_GEMFILE.lock + + - name: Install Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby-version }} + bundler-cache: true + + - name: Run tests + run: | + bundle exec rake diff --git a/.gitignore b/.gitignore index 7e1052c..34600ef 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ +/tmp/ .byebug_history *.gem + +# Ignore Gemfile.lock files for Rails main branch. +/gemfiles/rails_main*.gemfile.lock diff --git a/Appraisals b/Appraisals new file mode 100644 index 0000000..d6e6ee8 --- /dev/null +++ b/Appraisals @@ -0,0 +1,14 @@ +appraise "rails_7_0" do + gem "rails", "~> 7.0.0" + gem "propshaft" +end + +appraise "rails_7_1" do + gem "rails", "~> 7.1.0" + gem "propshaft" +end + +appraise "rails_main" do + gem "rails", github: "rails/rails", branch: "main" + gem "propshaft" +end diff --git a/Gemfile b/Gemfile index 1487b97..4f13599 100644 --- a/Gemfile +++ b/Gemfile @@ -4,9 +4,9 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" } # Specify your gem's dependencies in importmap-rails.gemspec. gemspec -rails_version = ENV["RAILS_VERSION"] || "6.1.0" -gem "rails", "~> #{rails_version}" - +gem "appraisal" +gem "rails", "~> 6.0.0" +gem "sprockets-rails" gem "sqlite3" group :test do diff --git a/Gemfile.lock b/Gemfile.lock index 86ed94f..6da3cae 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -7,162 +7,191 @@ PATH GEM remote: https://rubygems.org/ specs: - actioncable (6.1.3.1) - actionpack (= 6.1.3.1) - activesupport (= 6.1.3.1) + actioncable (6.0.6.1) + actionpack (= 6.0.6.1) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.1.3.1) - actionpack (= 6.1.3.1) - activejob (= 6.1.3.1) - activerecord (= 6.1.3.1) - activestorage (= 6.1.3.1) - activesupport (= 6.1.3.1) + actionmailbox (6.0.6.1) + actionpack (= 6.0.6.1) + activejob (= 6.0.6.1) + activerecord (= 6.0.6.1) + activestorage (= 6.0.6.1) + activesupport (= 6.0.6.1) mail (>= 2.7.1) - actionmailer (6.1.3.1) - actionpack (= 6.1.3.1) - actionview (= 6.1.3.1) - activejob (= 6.1.3.1) - activesupport (= 6.1.3.1) + actionmailer (6.0.6.1) + actionpack (= 6.0.6.1) + actionview (= 6.0.6.1) + activejob (= 6.0.6.1) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (6.1.3.1) - actionview (= 6.1.3.1) - activesupport (= 6.1.3.1) - rack (~> 2.0, >= 2.0.9) + actionpack (6.0.6.1) + actionview (= 6.0.6.1) + activesupport (= 6.0.6.1) + rack (~> 2.0, >= 2.0.8) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.1.3.1) - actionpack (= 6.1.3.1) - activerecord (= 6.1.3.1) - activestorage (= 6.1.3.1) - activesupport (= 6.1.3.1) + actiontext (6.0.6.1) + actionpack (= 6.0.6.1) + activerecord (= 6.0.6.1) + activestorage (= 6.0.6.1) + activesupport (= 6.0.6.1) nokogiri (>= 1.8.5) - actionview (6.1.3.1) - activesupport (= 6.1.3.1) + actionview (6.0.6.1) + activesupport (= 6.0.6.1) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.1.3.1) - activesupport (= 6.1.3.1) + activejob (6.0.6.1) + activesupport (= 6.0.6.1) globalid (>= 0.3.6) - activemodel (6.1.3.1) - activesupport (= 6.1.3.1) - activerecord (6.1.3.1) - activemodel (= 6.1.3.1) - activesupport (= 6.1.3.1) - activestorage (6.1.3.1) - actionpack (= 6.1.3.1) - activejob (= 6.1.3.1) - activerecord (= 6.1.3.1) - activesupport (= 6.1.3.1) - marcel (~> 1.0.0) - mini_mime (~> 1.0.2) - activesupport (6.1.3.1) + activemodel (6.0.6.1) + activesupport (= 6.0.6.1) + activerecord (6.0.6.1) + activemodel (= 6.0.6.1) + activesupport (= 6.0.6.1) + activestorage (6.0.6.1) + actionpack (= 6.0.6.1) + activejob (= 6.0.6.1) + activerecord (= 6.0.6.1) + marcel (~> 1.0) + activesupport (6.0.6.1) concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 1.6, < 2) - minitest (>= 5.1) - tzinfo (~> 2.0) - zeitwerk (~> 2.3) - addressable (2.8.0) - public_suffix (>= 2.0.2, < 5.0) + i18n (>= 0.7, < 2) + minitest (~> 5.1) + tzinfo (~> 1.1) + zeitwerk (~> 2.2, >= 2.2.2) + addressable (2.8.6) + public_suffix (>= 2.0.2, < 6.0) + appraisal (2.5.0) + bundler + rake + thor (>= 0.14.0) builder (3.2.4) byebug (11.1.3) - capybara (3.35.3) + capybara (3.39.2) addressable + matrix mini_mime (>= 0.1.3) nokogiri (~> 1.8) rack (>= 1.6.0) rack-test (>= 0.6.3) regexp_parser (>= 1.5, < 3.0) xpath (~> 3.2) - childprocess (3.0.0) - concurrent-ruby (1.1.9) + concurrent-ruby (1.2.2) crass (1.0.6) - erubi (1.10.0) - globalid (0.5.1) + date (3.3.4) + erubi (1.12.0) + globalid (1.1.0) activesupport (>= 5.0) - i18n (1.8.10) + i18n (1.14.1) concurrent-ruby (~> 1.0) - loofah (2.10.0) + loofah (2.22.0) crass (~> 1.0.2) - nokogiri (>= 1.5.9) - mail (2.7.1) + nokogiri (>= 1.12.0) + mail (2.8.1) mini_mime (>= 0.1.1) - marcel (1.0.1) + net-imap + net-pop + net-smtp + marcel (1.0.2) + matrix (0.4.2) method_source (1.0.0) - mini_mime (1.0.3) - mini_portile2 (2.8.2) - minitest (5.14.4) - nio4r (2.5.7) - nokogiri (1.13.6) - mini_portile2 (~> 2.8.0) + mini_mime (1.1.5) + minitest (5.20.0) + net-imap (0.4.9.1) + date + net-protocol + net-pop (0.1.2) + net-protocol + net-protocol (0.2.2) + timeout + net-smtp (0.4.0.1) + net-protocol + nio4r (2.7.0) + nokogiri (1.16.0-aarch64-linux) racc (~> 1.4) - public_suffix (4.0.6) - racc (1.5.2) - rack (2.2.3) - rack-test (1.1.0) - rack (>= 1.0, < 3) - rails (6.1.3.1) - actioncable (= 6.1.3.1) - actionmailbox (= 6.1.3.1) - actionmailer (= 6.1.3.1) - actionpack (= 6.1.3.1) - actiontext (= 6.1.3.1) - actionview (= 6.1.3.1) - activejob (= 6.1.3.1) - activemodel (= 6.1.3.1) - activerecord (= 6.1.3.1) - activestorage (= 6.1.3.1) - activesupport (= 6.1.3.1) - bundler (>= 1.15.0) - railties (= 6.1.3.1) + nokogiri (1.16.0-arm64-darwin) + racc (~> 1.4) + nokogiri (1.16.0-x86_64-darwin) + racc (~> 1.4) + nokogiri (1.16.0-x86_64-linux) + racc (~> 1.4) + public_suffix (5.0.4) + racc (1.7.3) + rack (2.2.8) + rack-test (2.1.0) + rack (>= 1.3) + rails (6.0.6.1) + actioncable (= 6.0.6.1) + actionmailbox (= 6.0.6.1) + actionmailer (= 6.0.6.1) + actionpack (= 6.0.6.1) + actiontext (= 6.0.6.1) + actionview (= 6.0.6.1) + activejob (= 6.0.6.1) + activemodel (= 6.0.6.1) + activerecord (= 6.0.6.1) + activestorage (= 6.0.6.1) + activesupport (= 6.0.6.1) + bundler (>= 1.3.0) + railties (= 6.0.6.1) sprockets-rails (>= 2.0.0) - rails-dom-testing (2.0.3) - activesupport (>= 4.2.0) + rails-dom-testing (2.2.0) + activesupport (>= 5.0.0) + minitest nokogiri (>= 1.6) - rails-html-sanitizer (1.3.0) - loofah (~> 2.3) - railties (6.1.3.1) - actionpack (= 6.1.3.1) - activesupport (= 6.1.3.1) + rails-html-sanitizer (1.6.0) + loofah (~> 2.21) + nokogiri (~> 1.14) + railties (6.0.6.1) + actionpack (= 6.0.6.1) + activesupport (= 6.0.6.1) method_source rake (>= 0.8.7) - thor (~> 1.0) - rake (13.0.6) - regexp_parser (2.1.1) - rexml (3.2.5) + thor (>= 0.20.3, < 2.0) + rake (13.1.0) + regexp_parser (2.9.0) + rexml (3.2.6) rubyzip (2.3.2) - selenium-webdriver (3.142.7) - childprocess (>= 0.5, < 4.0) - rubyzip (>= 1.2.2) - sprockets (4.0.2) + selenium-webdriver (4.10.0) + rexml (~> 3.2, >= 3.2.5) + rubyzip (>= 1.2.2, < 3.0) + websocket (~> 1.0) + sprockets (4.2.1) concurrent-ruby (~> 1.0) - rack (> 1, < 3) - sprockets-rails (3.2.2) - actionpack (>= 4.0) - activesupport (>= 4.0) + rack (>= 2.2.4, < 4) + sprockets-rails (3.4.2) + actionpack (>= 5.2) + activesupport (>= 5.2) sprockets (>= 3.0.0) - sqlite3 (1.4.2) - stimulus-rails (0.3.8) - rails (>= 6.0.0) - thor (1.1.0) - turbo-rails (0.7.4) - rails (>= 6.0.0) - tzinfo (2.0.4) - concurrent-ruby (~> 1.0) - webdrivers (4.6.0) + sqlite3 (1.7.0-aarch64-linux) + sqlite3 (1.7.0-arm64-darwin) + sqlite3 (1.7.0-x86_64-darwin) + sqlite3 (1.7.0-x86_64-linux) + stimulus-rails (1.3.3) + railties (>= 6.0.0) + thor (1.3.0) + thread_safe (0.3.6) + timeout (0.4.1) + turbo-rails (1.5.0) + actionpack (>= 6.0.0) + activejob (>= 6.0.0) + railties (>= 6.0.0) + tzinfo (1.2.11) + thread_safe (~> 0.1) + webdrivers (5.3.1) nokogiri (~> 1.6) rubyzip (>= 1.3.0) - selenium-webdriver (>= 3.0, < 4.0) - websocket-driver (0.7.5) + selenium-webdriver (~> 4.0, < 4.11) + websocket (1.2.10) + websocket-driver (0.7.6) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.4.2) + zeitwerk (2.6.12) PLATFORMS aarch64-linux @@ -174,12 +203,14 @@ PLATFORMS x86_64-linux DEPENDENCIES + appraisal byebug capybara jsbundling-rails! - rails (~> 6.1.0) + rails (~> 6.0.0) rexml selenium-webdriver + sprockets-rails sqlite3 stimulus-rails turbo-rails diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..793ce06 --- /dev/null +++ b/Rakefile @@ -0,0 +1,10 @@ +require "bundler/setup" +require "bundler/gem_tasks" +require "rake/testtask" + +Rake::TestTask.new(:test) do |t| + t.libs << "test" + t.pattern = "test/**/*_test.rb" +end + +task default: :test diff --git a/gemfiles/rails_7_0.gemfile b/gemfiles/rails_7_0.gemfile new file mode 100644 index 0000000..7c6a756 --- /dev/null +++ b/gemfiles/rails_7_0.gemfile @@ -0,0 +1,21 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "appraisal" +gem "rails", "~> 7.0.0" +gem "sprockets-rails" +gem "sqlite3" +gem "propshaft" + +group :test do + gem "turbo-rails" + gem "stimulus-rails" + gem "byebug" + gem "rexml" + gem "capybara" + gem "selenium-webdriver" + gem "webdrivers" +end + +gemspec path: "../" diff --git a/gemfiles/rails_7_0.gemfile.lock b/gemfiles/rails_7_0.gemfile.lock new file mode 100644 index 0000000..d75e0ea --- /dev/null +++ b/gemfiles/rails_7_0.gemfile.lock @@ -0,0 +1,220 @@ +PATH + remote: .. + specs: + jsbundling-rails (1.2.2) + railties (>= 6.0.0) + +GEM + remote: https://rubygems.org/ + specs: + actioncable (7.0.8) + actionpack (= 7.0.8) + activesupport (= 7.0.8) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + actionmailbox (7.0.8) + actionpack (= 7.0.8) + activejob (= 7.0.8) + activerecord (= 7.0.8) + activestorage (= 7.0.8) + activesupport (= 7.0.8) + mail (>= 2.7.1) + net-imap + net-pop + net-smtp + actionmailer (7.0.8) + actionpack (= 7.0.8) + actionview (= 7.0.8) + activejob (= 7.0.8) + activesupport (= 7.0.8) + mail (~> 2.5, >= 2.5.4) + net-imap + net-pop + net-smtp + rails-dom-testing (~> 2.0) + actionpack (7.0.8) + actionview (= 7.0.8) + activesupport (= 7.0.8) + rack (~> 2.0, >= 2.2.4) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.2.0) + actiontext (7.0.8) + actionpack (= 7.0.8) + activerecord (= 7.0.8) + activestorage (= 7.0.8) + activesupport (= 7.0.8) + globalid (>= 0.6.0) + nokogiri (>= 1.8.5) + actionview (7.0.8) + activesupport (= 7.0.8) + builder (~> 3.1) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.1, >= 1.2.0) + activejob (7.0.8) + activesupport (= 7.0.8) + globalid (>= 0.3.6) + activemodel (7.0.8) + activesupport (= 7.0.8) + activerecord (7.0.8) + activemodel (= 7.0.8) + activesupport (= 7.0.8) + activestorage (7.0.8) + actionpack (= 7.0.8) + activejob (= 7.0.8) + activerecord (= 7.0.8) + activesupport (= 7.0.8) + marcel (~> 1.0) + mini_mime (>= 1.1.0) + activesupport (7.0.8) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + addressable (2.8.6) + public_suffix (>= 2.0.2, < 6.0) + appraisal (2.5.0) + bundler + rake + thor (>= 0.14.0) + builder (3.2.4) + byebug (11.1.3) + capybara (3.39.2) + addressable + matrix + mini_mime (>= 0.1.3) + nokogiri (~> 1.8) + rack (>= 1.6.0) + rack-test (>= 0.6.3) + regexp_parser (>= 1.5, < 3.0) + xpath (~> 3.2) + concurrent-ruby (1.2.2) + crass (1.0.6) + date (3.3.4) + erubi (1.12.0) + globalid (1.2.1) + activesupport (>= 6.1) + i18n (1.14.1) + concurrent-ruby (~> 1.0) + loofah (2.22.0) + crass (~> 1.0.2) + nokogiri (>= 1.12.0) + mail (2.8.1) + mini_mime (>= 0.1.1) + net-imap + net-pop + net-smtp + marcel (1.0.2) + matrix (0.4.2) + method_source (1.0.0) + mini_mime (1.1.5) + minitest (5.21.1) + net-imap (0.4.9.1) + date + net-protocol + net-pop (0.1.2) + net-protocol + net-protocol (0.2.2) + timeout + net-smtp (0.4.0.1) + net-protocol + nio4r (2.7.0) + nokogiri (1.16.0-x86_64-linux) + racc (~> 1.4) + propshaft (0.8.0) + actionpack (>= 7.0.0) + activesupport (>= 7.0.0) + rack + railties (>= 7.0.0) + public_suffix (5.0.4) + racc (1.7.3) + rack (2.2.8) + rack-test (2.1.0) + rack (>= 1.3) + rails (7.0.8) + actioncable (= 7.0.8) + actionmailbox (= 7.0.8) + actionmailer (= 7.0.8) + actionpack (= 7.0.8) + actiontext (= 7.0.8) + actionview (= 7.0.8) + activejob (= 7.0.8) + activemodel (= 7.0.8) + activerecord (= 7.0.8) + activestorage (= 7.0.8) + activesupport (= 7.0.8) + bundler (>= 1.15.0) + railties (= 7.0.8) + rails-dom-testing (2.2.0) + activesupport (>= 5.0.0) + minitest + nokogiri (>= 1.6) + rails-html-sanitizer (1.6.0) + loofah (~> 2.21) + nokogiri (~> 1.14) + railties (7.0.8) + actionpack (= 7.0.8) + activesupport (= 7.0.8) + method_source + rake (>= 12.2) + thor (~> 1.0) + zeitwerk (~> 2.5) + rake (13.1.0) + regexp_parser (2.9.0) + rexml (3.2.6) + rubyzip (2.3.2) + selenium-webdriver (4.10.0) + rexml (~> 3.2, >= 3.2.5) + rubyzip (>= 1.2.2, < 3.0) + websocket (~> 1.0) + sprockets (4.2.1) + concurrent-ruby (~> 1.0) + rack (>= 2.2.4, < 4) + sprockets-rails (3.4.2) + actionpack (>= 5.2) + activesupport (>= 5.2) + sprockets (>= 3.0.0) + sqlite3 (1.7.0-x86_64-linux) + stimulus-rails (1.3.3) + railties (>= 6.0.0) + thor (1.3.0) + timeout (0.4.1) + turbo-rails (1.5.0) + actionpack (>= 6.0.0) + activejob (>= 6.0.0) + railties (>= 6.0.0) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + webdrivers (5.3.1) + nokogiri (~> 1.6) + rubyzip (>= 1.3.0) + selenium-webdriver (~> 4.0, < 4.11) + websocket (1.2.10) + websocket-driver (0.7.6) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.5) + xpath (3.2.0) + nokogiri (~> 1.8) + zeitwerk (2.6.12) + +PLATFORMS + x86_64-linux + +DEPENDENCIES + appraisal + byebug + capybara + jsbundling-rails! + propshaft + rails (~> 7.0.0) + rexml + selenium-webdriver + sprockets-rails + sqlite3 + stimulus-rails + turbo-rails + webdrivers + +BUNDLED WITH + 2.3.8 diff --git a/gemfiles/rails_7_1.gemfile b/gemfiles/rails_7_1.gemfile new file mode 100644 index 0000000..44414bb --- /dev/null +++ b/gemfiles/rails_7_1.gemfile @@ -0,0 +1,21 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "appraisal" +gem "rails", "~> 7.1.0" +gem "sprockets-rails" +gem "sqlite3" +gem "propshaft" + +group :test do + gem "turbo-rails" + gem "stimulus-rails" + gem "byebug" + gem "rexml" + gem "capybara" + gem "selenium-webdriver" + gem "webdrivers" +end + +gemspec path: "../" diff --git a/gemfiles/rails_7_1.gemfile.lock b/gemfiles/rails_7_1.gemfile.lock new file mode 100644 index 0000000..79fd262 --- /dev/null +++ b/gemfiles/rails_7_1.gemfile.lock @@ -0,0 +1,253 @@ +PATH + remote: .. + specs: + jsbundling-rails (1.2.2) + railties (>= 6.0.0) + +GEM + remote: https://rubygems.org/ + specs: + actioncable (7.1.2) + actionpack (= 7.1.2) + activesupport (= 7.1.2) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + zeitwerk (~> 2.6) + actionmailbox (7.1.2) + actionpack (= 7.1.2) + activejob (= 7.1.2) + activerecord (= 7.1.2) + activestorage (= 7.1.2) + activesupport (= 7.1.2) + mail (>= 2.7.1) + net-imap + net-pop + net-smtp + actionmailer (7.1.2) + actionpack (= 7.1.2) + actionview (= 7.1.2) + activejob (= 7.1.2) + activesupport (= 7.1.2) + mail (~> 2.5, >= 2.5.4) + net-imap + net-pop + net-smtp + rails-dom-testing (~> 2.2) + actionpack (7.1.2) + actionview (= 7.1.2) + activesupport (= 7.1.2) + nokogiri (>= 1.8.5) + racc + rack (>= 2.2.4) + rack-session (>= 1.0.1) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.2) + rails-html-sanitizer (~> 1.6) + actiontext (7.1.2) + actionpack (= 7.1.2) + activerecord (= 7.1.2) + activestorage (= 7.1.2) + activesupport (= 7.1.2) + globalid (>= 0.6.0) + nokogiri (>= 1.8.5) + actionview (7.1.2) + activesupport (= 7.1.2) + builder (~> 3.1) + erubi (~> 1.11) + rails-dom-testing (~> 2.2) + rails-html-sanitizer (~> 1.6) + activejob (7.1.2) + activesupport (= 7.1.2) + globalid (>= 0.3.6) + activemodel (7.1.2) + activesupport (= 7.1.2) + activerecord (7.1.2) + activemodel (= 7.1.2) + activesupport (= 7.1.2) + timeout (>= 0.4.0) + activestorage (7.1.2) + actionpack (= 7.1.2) + activejob (= 7.1.2) + activerecord (= 7.1.2) + activesupport (= 7.1.2) + marcel (~> 1.0) + activesupport (7.1.2) + base64 + bigdecimal + concurrent-ruby (~> 1.0, >= 1.0.2) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + minitest (>= 5.1) + mutex_m + tzinfo (~> 2.0) + addressable (2.8.6) + public_suffix (>= 2.0.2, < 6.0) + appraisal (2.5.0) + bundler + rake + thor (>= 0.14.0) + base64 (0.2.0) + bigdecimal (3.1.5) + builder (3.2.4) + byebug (11.1.3) + capybara (3.39.2) + addressable + matrix + mini_mime (>= 0.1.3) + nokogiri (~> 1.8) + rack (>= 1.6.0) + rack-test (>= 0.6.3) + regexp_parser (>= 1.5, < 3.0) + xpath (~> 3.2) + concurrent-ruby (1.2.2) + connection_pool (2.4.1) + crass (1.0.6) + date (3.3.4) + drb (2.2.0) + ruby2_keywords + erubi (1.12.0) + globalid (1.2.1) + activesupport (>= 6.1) + i18n (1.14.1) + concurrent-ruby (~> 1.0) + io-console (0.7.1) + irb (1.11.1) + rdoc + reline (>= 0.4.2) + loofah (2.22.0) + crass (~> 1.0.2) + nokogiri (>= 1.12.0) + mail (2.8.1) + mini_mime (>= 0.1.1) + net-imap + net-pop + net-smtp + marcel (1.0.2) + matrix (0.4.2) + mini_mime (1.1.5) + minitest (5.21.1) + mutex_m (0.2.0) + net-imap (0.4.9.1) + date + net-protocol + net-pop (0.1.2) + net-protocol + net-protocol (0.2.2) + timeout + net-smtp (0.4.0.1) + net-protocol + nio4r (2.7.0) + nokogiri (1.16.0-x86_64-linux) + racc (~> 1.4) + propshaft (0.8.0) + actionpack (>= 7.0.0) + activesupport (>= 7.0.0) + rack + railties (>= 7.0.0) + psych (5.1.2) + stringio + public_suffix (5.0.4) + racc (1.7.3) + rack (3.0.8) + rack-session (2.0.0) + rack (>= 3.0.0) + rack-test (2.1.0) + rack (>= 1.3) + rackup (2.1.0) + rack (>= 3) + webrick (~> 1.8) + rails (7.1.2) + actioncable (= 7.1.2) + actionmailbox (= 7.1.2) + actionmailer (= 7.1.2) + actionpack (= 7.1.2) + actiontext (= 7.1.2) + actionview (= 7.1.2) + activejob (= 7.1.2) + activemodel (= 7.1.2) + activerecord (= 7.1.2) + activestorage (= 7.1.2) + activesupport (= 7.1.2) + bundler (>= 1.15.0) + railties (= 7.1.2) + rails-dom-testing (2.2.0) + activesupport (>= 5.0.0) + minitest + nokogiri (>= 1.6) + rails-html-sanitizer (1.6.0) + loofah (~> 2.21) + nokogiri (~> 1.14) + railties (7.1.2) + actionpack (= 7.1.2) + activesupport (= 7.1.2) + irb + rackup (>= 1.0.0) + rake (>= 12.2) + thor (~> 1.0, >= 1.2.2) + zeitwerk (~> 2.6) + rake (13.1.0) + rdoc (6.6.2) + psych (>= 4.0.0) + regexp_parser (2.9.0) + reline (0.4.2) + io-console (~> 0.5) + rexml (3.2.6) + ruby2_keywords (0.0.5) + rubyzip (2.3.2) + selenium-webdriver (4.10.0) + rexml (~> 3.2, >= 3.2.5) + rubyzip (>= 1.2.2, < 3.0) + websocket (~> 1.0) + sprockets (4.2.1) + concurrent-ruby (~> 1.0) + rack (>= 2.2.4, < 4) + sprockets-rails (3.4.2) + actionpack (>= 5.2) + activesupport (>= 5.2) + sprockets (>= 3.0.0) + sqlite3 (1.7.0-x86_64-linux) + stimulus-rails (1.3.3) + railties (>= 6.0.0) + stringio (3.1.0) + thor (1.3.0) + timeout (0.4.1) + turbo-rails (1.5.0) + actionpack (>= 6.0.0) + activejob (>= 6.0.0) + railties (>= 6.0.0) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + webdrivers (5.3.1) + nokogiri (~> 1.6) + rubyzip (>= 1.3.0) + selenium-webdriver (~> 4.0, < 4.11) + webrick (1.8.1) + websocket (1.2.10) + websocket-driver (0.7.6) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.5) + xpath (3.2.0) + nokogiri (~> 1.8) + zeitwerk (2.6.12) + +PLATFORMS + x86_64-linux + +DEPENDENCIES + appraisal + byebug + capybara + jsbundling-rails! + propshaft + rails (~> 7.1.0) + rexml + selenium-webdriver + sprockets-rails + sqlite3 + stimulus-rails + turbo-rails + webdrivers + +BUNDLED WITH + 2.3.8 diff --git a/gemfiles/rails_main.gemfile b/gemfiles/rails_main.gemfile new file mode 100644 index 0000000..faf99e7 --- /dev/null +++ b/gemfiles/rails_main.gemfile @@ -0,0 +1,21 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "appraisal" +gem "rails", branch: "main", git: "https://github.com/rails/rails.git" +gem "sprockets-rails" +gem "sqlite3" +gem "propshaft" + +group :test do + gem "turbo-rails" + gem "stimulus-rails" + gem "byebug" + gem "rexml" + gem "capybara" + gem "selenium-webdriver" + gem "webdrivers" +end + +gemspec path: "../" diff --git a/test/bun_installer_test.rb b/test/bun_installer_test.rb new file mode 100644 index 0000000..cbb506c --- /dev/null +++ b/test/bun_installer_test.rb @@ -0,0 +1,55 @@ +require "test_helper" +require_relative "shared_installer_tests" + +class BunInstallerTest < ActiveSupport::TestCase + include RailsAppHelpers + include SharedInstallerTests + + test "bun installer with pre-existing files" do + with_new_rails_app do + File.write(".gitattributes", "# pre-existing\n", mode: "a+") + File.write("Procfile.dev", "pre: existing\n", mode: "a+") + + run_installer + + File.read(".gitattributes").tap do |gitattributes| + assert_match "# pre-existing", gitattributes + assert_match "*.lockb diff=lockb", gitattributes + end + + File.read("Procfile.dev").tap do |procfile| + assert_match "pre: existing", procfile + assert_match "js: bun run build --watch", procfile + end + + JSON.load_file("package.json").tap do |package_json| + assert_equal "bun bun.config.js", package_json["scripts"]["build"] + end + end + end + + test "bun installer without pre-existing files" do + with_new_rails_app do + FileUtils.rm_rf(".gitattributes") + FileUtils.rm_rf("Procfile.dev") + + out, _err = run_installer + + File.read(".gitattributes").tap do |gitattributes| + assert_match "*.lockb diff=lockb", gitattributes + end + + File.read("Procfile.dev").tap do |procfile| + assert_match "js: bun run build --watch", procfile + end + + assert_match "STUBBED gem install foreman", out + end + end + + private + def run_installer + stub_bins("gem") + run_command("bin/rails", "javascript:install:bun") + end +end diff --git a/test/esbuild_installer_test.rb b/test/esbuild_installer_test.rb new file mode 100644 index 0000000..f8d24c5 --- /dev/null +++ b/test/esbuild_installer_test.rb @@ -0,0 +1,28 @@ +require "test_helper" +require_relative "shared_installer_tests" + +class EsbuildInstallerTest < ActiveSupport::TestCase + include RailsAppHelpers + include SharedInstallerTests + + test "esbuild installer" do + with_new_rails_app do + out, _err = run_installer + + File.read("Procfile.dev").tap do |procfile| + assert_match "js: yarn build --watch", procfile + end + + assert_match "STUBBED gem install foreman", out + assert_match "STUBBED yarn add esbuild", out + assert_match %r{STUBBED npm (?:set-script build |pkg set scripts.build=)esbuild app/javascript/\*\.\*}, out + assert_match "STUBBED yarn build", out + end + end + + private + def run_installer + stub_bins("gem", "yarn", "npm") + run_command("bin/rails", "javascript:install:esbuild") + end +end diff --git a/test/rollup_installer_test.rb b/test/rollup_installer_test.rb new file mode 100644 index 0000000..d75bb49 --- /dev/null +++ b/test/rollup_installer_test.rb @@ -0,0 +1,31 @@ +require "test_helper" +require_relative "shared_installer_tests" + +class RollupInstallerTest < ActiveSupport::TestCase + include RailsAppHelpers + include SharedInstallerTests + + test "rollup installer" do + with_new_rails_app do + out, _err = run_installer + + File.read("Procfile.dev").tap do |procfile| + assert_match "js: yarn build --watch", procfile + end + + assert_match "STUBBED gem install foreman", out + + assert File.exist?("rollup.config.js") + + assert_match "STUBBED yarn add rollup", out + assert_match %r{STUBBED npm (?:set-script build |pkg set scripts.build=)rollup .*rollup.config.js}, out + assert_match "STUBBED yarn build", out + end + end + + private + def run_installer + stub_bins("gem", "yarn", "npm") + run_command("bin/rails", "javascript:install:rollup") + end +end diff --git a/test/shared_installer_tests.rb b/test/shared_installer_tests.rb new file mode 100644 index 0000000..4ceb687 --- /dev/null +++ b/test/shared_installer_tests.rb @@ -0,0 +1,99 @@ +require "json" + +module SharedInstallerTests + extend ActiveSupport::Concern + + included do + test "basic installation with pre-existing files" do + with_new_rails_app do + File.write(".gitignore", "# pre-existing\n", mode: "a+") + File.write("package.json", %({ "name": "pre-existing" }\n)) + File.write("Procfile.dev", "pre: existing\n", mode: "a+") + FileUtils.mkdir("app/javascript") + File.write("app/javascript/application.js", "// pre-existing\n", mode: "a+") + + run_installer + + File.read("bin/dev").tap do |bin_dev| + assert_equal File.read("#{__dir__}/../lib/install/dev"), bin_dev + assert_equal 0700, File.stat("bin/dev").mode & 0700 + end + + assert_equal 0, File.size("app/assets/builds/.keep") + + File.read("app/views/layouts/application.html.erb").tap do |layout| + assert_match %(<%= javascript_include_tag "application", "data-turbo-track": "reload", type: "module" %>), layout[%r{}m] + end + + File.read(".gitignore").tap do |gitignore| + assert_match "# pre-existing", gitignore + assert_match "/app/assets/builds/*\n!/app/assets/builds/.keep", gitignore + assert_match "/node_modules", gitignore + end + + JSON.load_file("package.json").tap do |package_json| + assert_equal "pre-existing", package_json["name"] + end + + File.read("Procfile.dev").tap do |procfile| + assert_match "pre: existing", procfile + assert_match %r{^js: }, procfile + end + + File.read("app/javascript/application.js").tap do |js_entrypoint| + assert_match "// pre-existing", js_entrypoint + end + end + end + + test "basic installation without pre-existing files" do + with_new_rails_app do + FileUtils.rm("app/views/layouts/application.html.erb") + FileUtils.rm(".gitignore") + FileUtils.rm_rf("package.json") + FileUtils.rm_rf("Procfile.dev") + FileUtils.rm_rf("app/javascript/application.js") + + out, _err = run_installer + + assert_not File.exist?("app/views/layouts/application.html.erb") + assert_match "Add <%= javascript_include_tag", out + + assert_not File.exist?(".gitignore") + + JSON.load_file("package.json").tap do |package_json| + assert_includes package_json, "name" + end + + File.read("Procfile.dev").tap do |procfile| + assert_match %r{^js: }, procfile + end + + assert File.exist?("app/javascript/application.js") + end + end + + test "basic installation with Sprockets" do + with_new_rails_app(*("--asset-pipeline=sprockets" if Rails::VERSION::MAJOR >= 7)) do + File.write("app/assets/config/manifest.js", "// pre-existing\n", mode: "a+") + + run_installer + + File.read("app/assets/config/manifest.js").tap do |sprockets_manifest| + assert_match "// pre-existing", sprockets_manifest + assert_match "//= link_tree ../builds", sprockets_manifest + end + end + end + + if Rails::VERSION::MAJOR == 7 + test "basic installation with Propshaft" do + with_new_rails_app("--asset-pipeline=propshaft") do + run_installer + + assert_not File.exist?("app/assets/config/manifest.js") + end + end + end + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb new file mode 100644 index 0000000..a235e65 --- /dev/null +++ b/test/test_helper.rb @@ -0,0 +1,71 @@ +# Configure Rails Environment +ENV["RAILS_ENV"] = "test" + +require "fileutils" +require "rails" +require "rails/test_help" + +module RailsAppHelpers + def self.included(base) + base.include ActiveSupport::Testing::Isolation + end + + private + def create_new_rails_app(app_dir, *cli_options) + require "rails/generators/rails/app/app_generator" + Rails::Generators::AppGenerator.start([app_dir, "--skip-bundle", "--skip-bootsnap", "--quiet", cli_options].flatten) + + Dir.chdir(app_dir) do + gemfile = File.read("Gemfile") + + gemfile.gsub!(/^gem ["']jsbundling-rails["'].*/, "") + gemfile << %(gem "jsbundling-rails", path: #{File.expand_path("..", __dir__).inspect}\n) + + if Rails::VERSION::PRE == "alpha" + gemfile.gsub!(/^gem ["']rails["'].*/, "") + gemfile << %(gem "rails", path: #{Gem.loaded_specs["rails"].full_gem_path.inspect}\n) + end + + File.write("Gemfile", gemfile) + + run_command("bundle", "install") + end + end + + def with_new_rails_app(*cli_options, &block) + require "digest/sha1" + variant = [RUBY_VERSION, Gem.loaded_specs["rails"].full_gem_path, cli_options.flatten.sort] + app_name = "app_#{Digest::SHA1.hexdigest(variant.to_s)}" + cache_dir = "#{__dir__}/../tmp" + FileUtils.mkdir_p(cache_dir) + + Dir.mktmpdir do |tmpdir| + if Dir.exist?("#{cache_dir}/#{app_name}") + FileUtils.cp_r("#{cache_dir}/#{app_name}", tmpdir) + else + create_new_rails_app("#{tmpdir}/#{app_name}", *cli_options) + FileUtils.cp_r("#{tmpdir}/#{app_name}", cache_dir) # Cache app for future runs. + end + + Dir.chdir("#{tmpdir}/#{app_name}", &block) + end + end + + def stub_bins(*names) + names.each do |name| + File.write("bin/#{name}", <<~BASH) + #!/usr/bin/env bash + echo STUBBED #{name} "$@" + BASH + + FileUtils.chmod(0755, "bin/#{name}") + end + end + + def run_command(*command) + Bundler.with_unbundled_env do + env = { "PATH" => "bin:#{ENV["PATH"]}" } + capture_subprocess_io { system(env, *command, exception: true) } + end + end +end diff --git a/test/webpack_installer_test.rb b/test/webpack_installer_test.rb new file mode 100644 index 0000000..cd51f9e --- /dev/null +++ b/test/webpack_installer_test.rb @@ -0,0 +1,31 @@ +require "test_helper" +require_relative "shared_installer_tests" + +class WebpackInstallerTest < ActiveSupport::TestCase + include RailsAppHelpers + include SharedInstallerTests + + test "webpack installer" do + with_new_rails_app do + out, _err = run_installer + + File.read("Procfile.dev").tap do |procfile| + assert_match "js: yarn build --watch", procfile + end + + assert_match "STUBBED gem install foreman", out + + assert File.exist?("webpack.config.js") + + assert_match "STUBBED yarn add webpack", out + assert_match %r{STUBBED npm (?:set-script build |pkg set scripts.build=)webpack --config webpack.config.js}, out + assert_match "STUBBED yarn build", out + end + end + + private + def run_installer + stub_bins("gem", "yarn", "npm") + run_command("bin/rails", "javascript:install:webpack") + end +end