diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 6e8a8558e..7cbb5aabb 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -82,7 +82,7 @@ jobs: run: echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p - name: Main CI if: steps.changed-files.outputs.any_changed == 'true' - run: bundle exec rake run_rspec:examples + run: bundle exec rake run_rspec:${{ matrix.versions == 'oldest' && 'web' || 'shaka' }}packer_examples - name: Store test results uses: actions/upload-artifact@v3 with: diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4837e6c00..b0dcc5357 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -81,15 +81,12 @@ jobs: path: spec/dummy/public/webpack key: dummy-app-webpack-bundle-${{ steps.get-sha.outputs.sha }}-${{ matrix.versions }} - main: + dummy-app-integration-tests: needs: build-dummy-app-webpack-test-bundles strategy: matrix: versions: ['oldest', 'newest'] runs-on: ubuntu-22.04 - env: - # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps - BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.versions }}.gemfile steps: - uses: actions/checkout@v4 with: diff --git a/rakelib/run_rspec.rake b/rakelib/run_rspec.rake index 24b0f3c3b..3507749a7 100644 --- a/rakelib/run_rspec.rake +++ b/rakelib/run_rspec.rake @@ -38,8 +38,13 @@ namespace :run_rspec do end end - desc "Runs Rspec for example apps only" - task examples: "examples:gen_all" do + desc "Runs Rspec for webpacker example apps only" + task webpacker_examples: "webpacker_examples:gen_all" do + ExampleType.all.each { |example_type| Rake::Task[example_type.rspec_task_name].invoke } + end + + desc "Runs Rspec for shakapacker example apps only" + task shakapacker_examples: "shakapacker_examples:gen_all" do ExampleType.all.each { |example_type| Rake::Task[example_type.rspec_task_name].invoke } end @@ -56,7 +61,8 @@ namespace :run_rspec do end desc "run all tests" - task run_rspec: %i[all_but_examples examples] do + task :run_rspec, [:packer] => ["all_but_examples"] do + Rake::Task["run_rspec:#{packer}_examples"].invoke puts "Completed all RSpec tests" end end diff --git a/rakelib/shakapacker_examples.rake b/rakelib/shakapacker_examples.rake new file mode 100644 index 000000000..cfd002856 --- /dev/null +++ b/rakelib/shakapacker_examples.rake @@ -0,0 +1,71 @@ +# frozen_string_literal: true + +# Defines tasks related to generating example apps using the gem's generator. +# Allows us to create and test apps generated using a wide range of options. +# +# Also see example_type.rb + +require "yaml" +require "rails/version" +require "pathname" + +require_relative "example_type" +require_relative "task_helpers" + +namespace :shakapacker_examples do # rubocop:disable Metrics/BlockLength + include ReactOnRails::TaskHelpers + # Loads data from examples_config.yml and instantiates corresponding ExampleType objects + examples_config_file = File.expand_path("examples_config.yml", __dir__) + examples_config = symbolize_keys(YAML.safe_load_file(examples_config_file)) + examples_config[:example_type_data].each { |example_type_data| ExampleType.new(**symbolize_keys(example_type_data)) } + + # Define tasks for each example type + ExampleType.all.each do |example_type| + # CLOBBER + desc "Clobbers (deletes) #{example_type.name_pretty}" + task example_type.clobber_task_name_short do + rm_rf(example_type.dir) + end + + # GENERATE + desc "Generates #{example_type.name_pretty}" + task example_type.gen_task_name_short => example_type.clobber_task_name do + mkdir_p(example_type.dir) + example_type.rails_options += "--skip-javascript" + sh_in_dir(examples_dir, "rails new #{example_type.name} #{example_type.rails_options}") + sh_in_dir(example_type.dir, "touch .gitignore") + append_to_gemfile(packer_type, example_type.gemfile) + bundle_install_in(example_type.dir) + sh_in_dir(example_type.dir, "rake shakapacker:install") + sh_in_dir(example_type.dir, example_type.generator_shell_commands) + sh_in_dir(example_type.dir, "yarn") + end + end + + desc "Clobbers (deletes) all example apps" + task :clobber do + rm_rf(examples_dir) + end + + desc "Generates all example apps" + task gen_all: ExampleType.all.map(&:gen_task_name) +end + +desc "Generates all example apps. Run `rake -D examples` to see all available options" +task shakapacker_examples: ["shakapacker_examples:gen_all"] + +private + +# Appends each string in an array as a new line of text in the given Gemfile. +# Automatically adds line returns. +def append_to_gemfile(packer_type, gemfile) + relative_gem_root = Pathname(gem_root).relative_path_from(Pathname(dir)) + shakapacker_version = packer_type.to_s == 'shakapacker' ? '6.6.0' : '8.0.0' + lines = [ + "gem 'react_on_rails', path: '#{relative_gem_root}'", + "gem 'shakapacker', '~> #{shakapacker_version}'" + ] + old_text = File.read(gemfile) + new_text = lines.reduce(old_text) { |a, e| a << "#{e}\n" } + File.open(gemfile, "w") { |f| f.puts(new_text) } +end diff --git a/rakelib/examples.rake b/rakelib/webpacker_examples.rake similarity index 92% rename from rakelib/examples.rake rename to rakelib/webpacker_examples.rake index f64f311d9..6cef0fe9c 100644 --- a/rakelib/examples.rake +++ b/rakelib/webpacker_examples.rake @@ -12,7 +12,7 @@ require "pathname" require_relative "example_type" require_relative "task_helpers" -namespace :examples, [:packer_type] do # rubocop:disable Metrics/BlockLength +namespace :webpacker_examples do # rubocop:disable Metrics/BlockLength include ReactOnRails::TaskHelpers # Loads data from examples_config.yml and instantiates corresponding ExampleType objects examples_config_file = File.expand_path("examples_config.yml", __dir__) @@ -36,7 +36,7 @@ namespace :examples, [:packer_type] do # rubocop:disable Metrics/BlockLength sh_in_dir(example_type.dir, "touch .gitignore") append_to_gemfile(packer_type, example_type.gemfile) bundle_install_in(example_type.dir) - sh_in_dir(example_type.dir, "rake #{packer_type.to_s}:install") + sh_in_dir(example_type.dir, "rake webpacker:install") sh_in_dir(example_type.dir, example_type.generator_shell_commands) sh_in_dir(example_type.dir, "yarn") end @@ -52,7 +52,7 @@ namespace :examples, [:packer_type] do # rubocop:disable Metrics/BlockLength end desc "Generates all example apps. Run `rake -D examples` to see all available options" -task :examples, [:packer_type] => "examples:gen_all" +task webpacker_examples: ["webpacker_examples:gen_all"] private diff --git a/spec/react_on_rails/configuration_spec.rb b/spec/react_on_rails/configuration_spec.rb index e8b147855..c4e764f67 100644 --- a/spec/react_on_rails/configuration_spec.rb +++ b/spec/react_on_rails/configuration_spec.rb @@ -75,15 +75,10 @@ module ReactOnRails end describe ".build_production_command" do - context "when using Shakapacker 7" do - before do - allow(ReactOnRails::PackerUtils) - .to receive("shakapacker_version") - .and_return("7.0.0") - end + context "when using Shakapacker 7", :unless ReactOnRails::PackerUtils.packer_type == "shakapacker" do it "fails when \"shakapacker_precompile\" is truly and \"build_production_command\" is truly" do - allow(ReactOnRails::PackerUtils).to receive_message_chain("packer.precompile?") + allow(Webpacker).to receive_message_chain("config.webpacker_precompile?") .and_return(true) expect do ReactOnRails.configure do |config| @@ -93,7 +88,7 @@ module ReactOnRails end it "doesn't fail when \"shakapacker_precompile\" is falsy and \"build_production_command\" is truly" do - allow(ReactOnRails::PackerUtils).to receive_message_chain("packer.precompile?") + allow(Webpacker).to receive_message_chain("config.webpacker_precompile?") .and_return(false) expect do ReactOnRails.configure do |config| @@ -103,7 +98,7 @@ module ReactOnRails end it "doesn't fail when \"shakapacker_precompile\" is truly and \"build_production_command\" is falsy" do - allow(ReactOnRails::PackerUtils).to receive_message_chain("packer.precompile?") + allow(Webpacker).to receive_message_chain("config.webpacker_precompile?") .and_return(true) expect do ReactOnRails.configure {} # rubocop:disable-line Lint/EmptyBlock @@ -111,7 +106,7 @@ module ReactOnRails end it "doesn't fail when \"shakapacker_precompile\" is falsy and \"build_production_command\" is falsy" do - allow(ReactOnRails::PackerUtils).to receive_message_chain("packer.precompile?") + allow(Webpacker).to receive_message_chain("config.webpacker_precompile?") .and_return(false) expect do ReactOnRails.configure {} # rubocop:disable-line Lint/EmptyBlock @@ -119,15 +114,10 @@ module ReactOnRails end end - context "when using Shakapacker 8" do - before do - allow(ReactOnRails::PackerUtils) - .to receive("shakapacker_version") - .and_return("8.0.0") - end + context "when using Shakapacker 8", :unless ReactOnRails::PackerUtils.packer_type == "shakapacker" do it "fails when \"shakapacker_precompile\" is truly and \"build_production_command\" is truly" do - allow(ReactOnRails::PackerUtils).to receive_message_chain("packer.precompile?") + allow(Shakapacker).to receive_message_chain("config.shakapacker_precompile?") .and_return(true) expect do ReactOnRails.configure do |config| @@ -137,7 +127,7 @@ module ReactOnRails end it "doesn't fail when \"shakapacker_precompile\" is falsy and \"build_production_command\" is truly" do - allow(ReactOnRails::PackerUtils).to receive_message_chain("packer.precompile?") + allow(Shakapacker).to receive_message_chain("config.shakapacker_precompile?") .and_return(false) expect do ReactOnRails.configure do |config| @@ -147,7 +137,7 @@ module ReactOnRails end it "doesn't fail when \"shakapacker_precompile\" is truly and \"build_production_command\" is falsy" do - allow(ReactOnRails::PackerUtils).to receive_message_chain("packer.precompile?") + allow(Shakapacker).to receive_message_chain("config.shakapacker_precompile?") .and_return(true) expect do ReactOnRails.configure {} # rubocop:disable-line Lint/EmptyBlock @@ -155,7 +145,7 @@ module ReactOnRails end it "doesn't fail when \"shakapacker_precompile\" is falsy and \"build_production_command\" is falsy" do - allow(ReactOnRails::PackerUtils).to receive_message_chain("packer.precompile?") + allow(Shakapacker).to receive_message_chain("config.shakapacker_precompile?") .and_return(false) expect do ReactOnRails.configure {} # rubocop:disable-line Lint/EmptyBlock diff --git a/spec/react_on_rails/utils_spec.rb b/spec/react_on_rails/utils_spec.rb index 65434eb33..34615c520 100644 --- a/spec/react_on_rails/utils_spec.rb +++ b/spec/react_on_rails/utils_spec.rb @@ -113,7 +113,7 @@ module ReactOnRails server_bundle_name = "server-bundle.js" allow(ReactOnRails).to receive_message_chain("configuration.server_bundle_js_file") .and_return(server_bundle_name) - allow(ReactOnRails::PackerUtils).to receive_message_chain("packer.manifest.lookup!") + allow(Packer).to receive_message_chain("manifest.lookup!") .with(server_bundle_name) .and_raise(Packer::Manifest::MissingEntryError) @@ -125,11 +125,12 @@ module ReactOnRails context "with server file in the manifest, used for client", :shakapacker do it "returns the correct path hashed server path" do + Packer = ReactOnRails::PackerUtils.packer allow(ReactOnRails).to receive_message_chain("configuration.server_bundle_js_file") .and_return("webpack-bundle.js") allow(ReactOnRails).to receive_message_chain("configuration.same_bundle_for_client_and_server") .and_return(true) - allow(ReactOnRails::PackerUtils).to receive_message_chain("packer.manifest.lookup!") + allow(Packer).to receive_message_chain("manifest.lookup!") .with("webpack-bundle.js") .and_return("webpack/development/webpack-bundle-123456.js")