From 6c874989a800a96fb9805c8dad0421d7c0245575 Mon Sep 17 00:00:00 2001 From: zzak Date: Thu, 11 Jan 2024 16:07:05 +0900 Subject: [PATCH] Test installer This commit adds test coverage for the installer Rake task and application template. The installer is run against a freshly generated Rails app using the version of Rails that is currently loaded. Thus the installer can be tested with different versions of Rails in CI. Similar to rails/importmap-rails#206 for stimulus-rails The motivation is to be able to move these tests from railties, see: rails/rails#49679 Co-authored-by: Jonathan Hefner --- .github/workflows/ci.yml | 2 + test/installer_test.rb | 79 ++++++++++++++++++++++++++++++++++++++++ test/test_helper.rb | 46 +++++++++++++++++++++++ 3 files changed, 127 insertions(+) create mode 100644 test/installer_test.rb diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bc9499c..42fd05c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,6 +12,7 @@ jobs: '6.0.0', '6.1.0', '7.0.1', + '7.1.2' ] ruby: [ '2.7', @@ -36,6 +37,7 @@ jobs: ruby-version: ${{ matrix.ruby }} bundler-cache: false + - uses: oven-sh/setup-bun@v1 - name: Install Dependencies env: RAILS_VERSION: ${{ matrix.rails }} diff --git a/test/installer_test.rb b/test/installer_test.rb new file mode 100644 index 0000000..14f9803 --- /dev/null +++ b/test/installer_test.rb @@ -0,0 +1,79 @@ +require 'test_helper' + +class InstallerTest < ActiveSupport::TestCase + include RailsAppHelpers + + test "installer" do + with_new_rails_app do + if Rails::VERSION::MAJOR >= 7 && File.read("Gemfile").match?(/importmap-rails/) + run_command("bin/rails", "importmap:install") + end + _out, _err = run_command("bin/rails", "stimulus:install") + + assert_match %r(import "(./)?controllers"), File.read("app/javascript/application.js") + assert_equal File.read("#{__dir__}/../lib/install/app/javascript/controllers/application.js"), File.read("app/javascript/controllers/application.js") + assert_equal File.read("#{__dir__}/../lib/install/app/javascript/controllers/hello_controller.js"), File.read("app/javascript/controllers/hello_controller.js") + + if Rails::VERSION::MAJOR >= 7 + assert_equal File.read("#{__dir__}/../lib/install/app/javascript/controllers/index_for_importmap.js"), File.read("app/javascript/controllers/index.js") + assert_match %(pin "@hotwired/stimulus", to: "stimulus.min.js"), File.read("config/importmap.rb") + assert_match %(pin "@hotwired/stimulus-loading", to: "stimulus-loading.js"), File.read("config/importmap.rb") + assert_match %(pin_all_from "app/javascript/controllers", under: "controllers"), File.read("config/importmap.rb") + else + assert_equal File.read("#{__dir__}/../lib/install/app/javascript/controllers/index_for_node.js"), File.read("app/javascript/controllers/index.js") + assert_match "@hotwired/stimulus", File.read("package.json") + assert_match "@hotwired/stimulus", File.read("yarn.lock") + end + end + end + + test "installer with no javascript" do + with_new_rails_app %w[--skip-javascript] do + out, _err = run_command("bin/rails", "stimulus:install") + + assert_match "You must either be running with node (package.json) or importmap-rails (config/importmap.rb) to use this gem.", out + end + end + + test "installer with pre-existing application.js" do + with_new_rails_app do + if Rails::VERSION::MAJOR >= 7 && File.read("Gemfile").match?(/importmap-rails/) + run_command("bin/rails", "importmap:install") + end + File.write("app/javascript/application.js", "// pre-existing") + _out, _err = run_command("bin/rails", "stimulus:install") + + assert_match "// pre-existing", File.read("app/javascript/application.js") + end + end + + if Gem::Version.new(Rails.version) >= Gem::Version.new("7.1") + test "installer with bun" do + with_new_rails_app %w[--javascript=bun] do + run_command("bin/rails", "javascript:install:bun") + _out, _err = run_command("bin/rails", "stimulus:install") + + assert_match %r(import "(./)?controllers"), File.read("app/javascript/application.js") + assert_equal File.read("#{__dir__}/../lib/install/app/javascript/controllers/application.js"), File.read("app/javascript/controllers/application.js") + assert_equal File.read("#{__dir__}/../lib/install/app/javascript/controllers/hello_controller.js"), File.read("app/javascript/controllers/hello_controller.js") + + assert_equal File.read("#{__dir__}/../lib/install/app/javascript/controllers/index_for_node.js"), File.read("app/javascript/controllers/index.js") + + assert_match "@hotwired/stimulus", File.read("package.json") + end + end + end + + private + def with_new_rails_app(options=[], &block) + super do + if Dir.exist?("app/javascript") && !File.exist?("app/javascript/application.js") + File.write("app/javascript/application.js", <<~JS, mode: "a+") + import "./controllers" + JS + end + + block.call + end + end +end \ No newline at end of file diff --git a/test/test_helper.rb b/test/test_helper.rb index 3a34ab7..f53612b 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,8 +1,54 @@ require 'rails' require "rails/test_help" +require "fileutils" # Configure Rails Environment ENV["RAILS_ENV"] = "test" # Set fixture path ActiveSupport::TestCase.file_fixture_path = File.expand_path("fixtures", __dir__) + +module RailsAppHelpers + def self.included(base) + base.include ActiveSupport::Testing::Isolation + end + + private + def create_new_rails_app(app_dir, options=[]) + require "rails/generators/rails/app/app_generator" + Rails::Generators::AppGenerator.start([app_dir, *options, "--skip-bundle", "--skip-bootsnap", "--quiet"]) + + Dir.chdir(app_dir) do + gemfile = File.read("Gemfile") + + gemfile.gsub!(/^gem ["']stimulus-rails["'].*/, "") + gemfile << %(gem "stimulus-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(options=[], &block) + require "digest/sha1" + variant = [RUBY_VERSION, Gem.loaded_specs["rails"].full_gem_path,] + app_name = "app_#{Digest::SHA1.hexdigest(variant.to_s)}" + + Dir.mktmpdir do |tmpdir| + create_new_rails_app("#{tmpdir}/#{app_name}", *options) + Dir.chdir("#{tmpdir}/#{app_name}", &block) + end + end + + def run_command(*command) + Bundler.with_unbundled_env do + capture_subprocess_io { system(*command, exception: true) } + end + end +end \ No newline at end of file