diff --git a/test/installer_test.rb b/test/installer_test.rb new file mode 100644 index 0000000..4921f95 --- /dev/null +++ b/test/installer_test.rb @@ -0,0 +1,71 @@ +require "test_helper" + +class InstallerTest < ActiveSupport::TestCase + include RailsAppHelpers + + test "installer" do + with_new_rails_app do + out, _err = run_command("bin/rails", "dartsass:install") + + assert_match "", out + assert_equal 0, File.size("app/assets/builds/.keep") + assert_match "/app/assets/builds/*\n!/app/assets/builds/.keep", File.read(".gitignore") + assert_equal File.read("#{__dir__}/../lib/install/application.scss"), File.read("app/assets/stylesheets/application.scss") + assert_equal File.read("#{__dir__}/../lib/install/Procfile.dev"), File.read("Procfile.dev") + assert_equal File.read("#{__dir__}/../lib/install/dev"), File.read("bin/dev") + assert_equal 0700, File.stat("bin/dev").mode & 0700 + + if sprockets? + assert_match "//= link_tree ../builds", File.read("app/assets/config/manifest.js") + assert_no_match "//= link_directory ../stylesheets .css", File.read("app/assets/config/manifest.js") + end + end + end + + test "installer with missing .gitignore" do + with_new_rails_app do + FileUtils.rm(".gitignore") + out, _err = run_command("bin/rails", "dartsass:install") + + assert_match "", out + assert_not File.exist?(".gitignore") + end + end + + test "installer with pre-existing application.scss" do + with_new_rails_app do + File.write("app/assets/stylesheets/application.scss", "// pre-existing") + out, _err = run_command("bin/rails", "dartsass:install") + + assert_match "", out + assert_equal "// pre-existing", File.read("app/assets/stylesheets/application.scss") + end + end + + test "installer with pre-existing Procfile" do + with_new_rails_app do + File.write("Procfile.dev", "pre: existing\n") + out, _err = run_command("bin/rails", "dartsass:install") + + assert_match "", out + assert_equal "pre: existing\ncss: bin/rails dartsass:watch\n", File.read("Procfile.dev") + end + end + + private + def with_new_rails_app(&block) + super do + # Override `dartsass:build` to check that installation completed and to reduce test run time. + File.write("Rakefile", <<~RAKEFILE, mode: "a+") + Rake::Task["dartsass:build"].clear + namespace :dartsass do + task build: :environment do + puts "" + end + end + RAKEFILE + + block.call + end + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb index b65a5ab..02e5424 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -4,3 +4,75 @@ require "fileutils" require "rails" require "rails/test_help" + +module RailsAppHelpers + def self.included(base) + base.include ActiveSupport::Testing::Isolation + end + + private + def sprockets? + Gem.loaded_specs.key?("sprockets-rails") + end + + def propshaft? + Gem.loaded_specs.key?("propshaft") + end + + def asset_pipeline_option + if Rails::VERSION::MAJOR > 7 + if propshaft? + "--asset-pipeline=propshaft" + elsif sprockets? + "--asset-pipeline=sprockets" + end + end + end + + def create_new_rails_app(app_dir) + require "rails/generators/rails/app/app_generator" + Rails::Generators::AppGenerator.start([app_dir, *asset_pipeline_option, "--skip-bundle", "--skip-bootsnap", "--quiet"]) + + Dir.chdir(app_dir) do + gemfile = File.read("Gemfile") + + gemfile.gsub!(/^gem ["']sassc?-rails["'].*/, "") # for Rails 6.1 and 7.0 + gemfile.gsub!(/^gem ["']dartsass-rails["'].*/, "") + gemfile << %(gem "dartsass-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(&block) + require "digest/sha1" + variant = [RUBY_VERSION, Gem.loaded_specs["rails"].full_gem_path, asset_pipeline_option] + 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}") + FileUtils.cp_r("#{tmpdir}/#{app_name}", cache_dir) # Cache app for future runs. + end + + 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