Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
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.
  • Loading branch information
jonathanhefner committed Jan 13, 2024
commit 048b1f1d890a29a6a731892aaeb8d194481c5e7b
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/tmp/
.byebug_history
*.gem

Expand Down
13 changes: 13 additions & 0 deletions test/bootstrap_installer_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
require "test_helper"
require_relative "shared_installer_tests"

class BootstrapInstallerTest < ActiveSupport::TestCase
include RailsAppHelpers
include SharedInstallerTests

private
def run_installer
stub_bins("gem", "yarn", "npm")
run_command("bin/rails", "css:install:bootstrap")
end
end
13 changes: 13 additions & 0 deletions test/bulma_installer_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
require "test_helper"
require_relative "shared_installer_tests"

class BulmaInstallerTest < ActiveSupport::TestCase
include RailsAppHelpers
include SharedInstallerTests

private
def run_installer
stub_bins("gem", "yarn", "npm")
run_command("bin/rails", "css:install:bulma")
end
end
13 changes: 13 additions & 0 deletions test/postcss_installer_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
require "test_helper"
require_relative "shared_installer_tests"

class PostcssInstallerTest < ActiveSupport::TestCase
include RailsAppHelpers
include SharedInstallerTests

private
def run_installer
stub_bins("gem", "yarn", "npm")
run_command("bin/rails", "css:install:postcss")
end
end
13 changes: 13 additions & 0 deletions test/sass_installer_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
require "test_helper"
require_relative "shared_installer_tests"

class SassInstallerTest < ActiveSupport::TestCase
include RailsAppHelpers
include SharedInstallerTests

private
def run_installer
stub_bins("gem", "yarn", "npm")
run_command("bin/rails", "css:install:sass")
end
end
123 changes: 123 additions & 0 deletions test/shared_installer_tests.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
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+")

run_installer

assert_equal 0, File.size("app/assets/builds/.keep")

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

assert_not File.exist?("app/assets/stylesheets/application.css")

File.read("Procfile.dev").tap do |procfile|
assert_match "pre: existing", procfile
assert_match "css: yarn", procfile
end

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
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")

out, _err = run_installer

assert_not File.exist?("app/views/layouts/application.html.erb")
assert_match "Add <%= stylesheet_link_tag", out

assert_not File.exist?(".gitignore")

assert_instance_of Hash, JSON.load_file("package.json")

File.read("Procfile.dev").tap do |procfile|
assert_match "css: yarn", procfile
end

assert_match "STUBBED gem install foreman", out
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
assert_no_match "//= link_directory ../stylesheets .css", 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

if Rails::VERSION::MAJOR >= 7
test "basic installation with Turbo" do
with_new_rails_app do
run_installer

File.read("app/views/layouts/application.html.erb").tap do |layout|
assert_match %(<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>), layout[%r{<head.*</head>}m]
end
end
end
end

test "basic installation without Turbo" do
with_new_rails_app(*("--skip-hotwire" if Rails::VERSION::MAJOR >= 7)) do
run_installer

File.read("app/views/layouts/application.html.erb").tap do |layout|
assert_match %(<%= stylesheet_link_tag "application" %>), layout[%r{<head.*</head>}m]
end
end
end

test "basic installation with Bun" do
with_new_rails_app do
stub_bins("bun")

run_installer

File.read("Procfile.dev").tap do |procfile|
assert_match "css: bun run", procfile
end
end
end
end
end
13 changes: 13 additions & 0 deletions test/tailwind_installer_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
require "test_helper"
require_relative "shared_installer_tests"

class TailwindInstallerTest < ActiveSupport::TestCase
include RailsAppHelpers
include SharedInstallerTests

private
def run_installer
stub_bins("gem", "yarn", "npm")
run_command("bin/rails", "css:install:tailwind")
end
end
65 changes: 65 additions & 0 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,68 @@
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 ["']cssbundling-rails["'].*/, "")
gemfile << %(gem "cssbundling-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