Skip to main content

Testing Configuration

This guide explains how to configure React on Rails for optimal testing with RSpec, Minitest, or other test frameworks.

Quick Start

For most applications, the simplest approach is to let Shakapacker handle asset compilation automatically:

# config/shakapacker.yml
test:
compile: true
public_output_path: webpack/test

That's it! Shakapacker will automatically compile assets before running tests.

Two Approaches to Test Asset Compilation

React on Rails supports two mutually exclusive approaches for compiling webpack assets during tests:

Best for: Most applications, especially simpler test setups

Configuration:

# config/shakapacker.yml
test:
<<: *default
compile: true
public_output_path: webpack/test

Note: Ensure that source_path is correctly configured in your config/shakapacker.yml, or Shakapacker won't correctly detect source changes. This is only necessary if you're not using Shakapacker's defaults.

How it works:

  • Shakapacker automatically compiles assets when they're requested
  • No additional configuration in React on Rails or test helpers needed
  • Assets are compiled on-demand during test runs

Pros:

  • ✅ Simplest configuration
  • ✅ No extra setup in spec helpers
  • ✅ Automatically integrates with Rails test environment
  • ✅ Works with any test framework (RSpec, Minitest, etc.)

Cons:

  • ⚠️ May compile assets multiple times during test runs
  • ⚠️ Less explicit control over when compilation happens
  • ⚠️ Can slow down tests if assets change frequently

When to use:

  • You want the simplest possible configuration
  • Your test suite is relatively fast
  • You don't mind automatic compilation on-demand

Approach 2: React on Rails Test Helper (Explicit Control)

Best for: Applications needing precise control over compilation timing

Configuration:

Set your build command:

# config/initializers/react_on_rails.rb
ReactOnRails.configure do |config|
config.build_test_command = "NODE_ENV=test RAILS_ENV=test bin/shakapacker"

# Or use your project's package manager with a custom script:
# config.build_test_command = "pnpm run build:test" # or: npm run build:test, yarn run build:test
end

Then configure your test framework:

RSpec:

# spec/rails_helper.rb
require "react_on_rails/test_helper"

RSpec.configure do |config|
# Ensures webpack assets are compiled before the test suite runs
ReactOnRails::TestHelper.configure_rspec_to_compile_assets(config)
end

See lib/react_on_rails/test_helper.rb for more details and customization options.

By default, the helper triggers compilation for examples tagged with :js, :server_rendering, or :controller. You can pass custom metatags as an optional second parameter if you need compilation for other specs — for example, if you use Webpack to build CSS assets for request and feature specs:

# spec/rails_helper.rb
RSpec.configure do |config|
ReactOnRails::TestHelper.configure_rspec_to_compile_assets(config, :requires_webpack_assets)
config.define_derived_metadata(file_path: %r{spec/(features|requests)}) do |metadata|
metadata[:requires_webpack_assets] = true
end
end

Minitest:

# test/test_helper.rb
require "react_on_rails/test_helper"

class ActiveSupport::TestCase
setup do
ReactOnRails::TestHelper.ensure_assets_compiled
end
end

Alternatively, you can use a Minitest plugin to run the check in before_setup:

module MyMinitestPlugin
def before_setup
super
ReactOnRails::TestHelper.ensure_assets_compiled
end
end

class Minitest::Test
include MyMinitestPlugin
end

Asset detection settings:

The following settings in config/initializers/react_on_rails.rb control how the test helper detects stale assets:

ReactOnRails.configure do |config|
# Define the files to check for Webpack compilation when running tests.
config.webpack_generated_files = %w( manifest.json )

# If you're not hashing the server bundle, include it in the list:
# config.webpack_generated_files = %w( server-bundle.js manifest.json )
end

Important: The build_test_command must not include the --watch option. If you have separate server and client bundles, the command must build all of them.

How it works:

  • Compiles assets at most once per test run, and only when they're out of date (stale)
  • The helper checks the Webpack-generated files folder (configured via public_root_path and public_output_path in config/shakapacker.yml). If the folder is missing, empty, or contains files listed in webpack_generated_files with mtimes older than any source files, assets are recompiled.
  • Uses the build_test_command configuration
  • Fails fast if compilation has errors

Pros:

  • ✅ Explicit control over compilation timing
  • ✅ Assets compiled only once per test run
  • ✅ Clear error messages if compilation fails
  • ✅ Can customize the build command

Cons:

  • ⚠️ Requires additional configuration in test helpers
  • ⚠️ More setup to maintain
  • ⚠️ Requires build_test_command to be set

When to use:

  • You want to compile assets exactly once before tests
  • You need to customize the build command
  • You want explicit error handling for compilation failures
  • Your test suite is slow and you want to optimize compilation

Don't Mix Approaches

Do not use both approaches together. They are mutually exclusive:

# config/shakapacker.yml
test:
compile: true # ← Don't do this...
# config/initializers/react_on_rails.rb
config.build_test_command = "RAILS_ENV=test bin/shakapacker" # ← ...with this

# spec/rails_helper.rb
ReactOnRails::TestHelper.configure_rspec_to_compile_assets(config) # ← ...and this

This will cause assets to be compiled multiple times unnecessarily.

Migrating Between Approaches

From React on Rails Test Helper → Shakapacker Auto-Compilation

  1. Set compile: true in config/shakapacker.yml test section:

    test:
    compile: true
    public_output_path: webpack/test
  2. Remove test helper configuration from spec/test helpers:

    # spec/rails_helper.rb - REMOVE these lines:
    require "react_on_rails/test_helper"
    ReactOnRails::TestHelper.configure_rspec_to_compile_assets(config)
  3. Remove or comment out build_test_command in React on Rails config:

    # config/initializers/react_on_rails.rb
    # config.build_test_command = "RAILS_ENV=test bin/shakapacker" # ← Comment out

From Shakapacker Auto-Compilation → React on Rails Test Helper

  1. Set compile: false in config/shakapacker.yml test section:

    test:
    compile: false
    public_output_path: webpack/test
  2. Add build_test_command to React on Rails config:

    # config/initializers/react_on_rails.rb
    config.build_test_command = "RAILS_ENV=test bin/shakapacker"
  3. Add test helper configuration:

    # spec/rails_helper.rb (for RSpec)
    require "react_on_rails/test_helper"

    RSpec.configure do |config|
    ReactOnRails::TestHelper.configure_rspec_to_compile_assets(config)
    end

Verifying Your Configuration

Use the React on Rails doctor command to verify your test configuration:

bundle exec rake react_on_rails:doctor

The doctor will check:

  • Whether compile: true is set in shakapacker.yml
  • Whether build_test_command is configured
  • Whether test helpers are properly set up
  • Whether you're accidentally using both approaches

Troubleshooting

Assets not compiling during tests

Problem: Tests fail because JavaScript/CSS assets are not compiled.

Solution: Check which approach you're using:

  1. If using Shakapacker auto-compilation:

    # config/shakapacker.yml
    test:
    compile: true # ← Make sure this is true
  2. If using React on Rails test helper:

    • Verify build_test_command is set
    • Check that test helper is configured in spec/test helper
    • Run bundle exec rake react_on_rails:doctor

Assets compiling multiple times

Problem: Tests are slow because assets compile repeatedly.

Solutions:

  1. If using Shakapacker auto-compilation:

    • Switch to React on Rails test helper for one-time compilation
    • Or ensure cache_manifest: true in shakapacker.yml
  2. If using React on Rails test helper:

    • This shouldn't happen - assets should compile only once
    • Check that you don't also have compile: true in shakapacker.yml

Stale assets not recompiling

Problem: You added a source file but the test helper doesn't trigger recompilation.

Cause: The test helper compares mtimes of source files against generated output files. If you add a source file that has an older timestamp than the existing output (e.g., copied from another directory or restored from version control), it won't be detected as a change.

Solution: Clear out your Webpack-generated files directory to force recompilation:

rm -rf public/webpack/test

Build command fails

Problem: build_test_command fails with errors.

Check:

  1. Does bin/shakapacker exist and is it executable?

    ls -la bin/shakapacker
    chmod +x bin/shakapacker # If needed
  2. Can you run the command manually?

    RAILS_ENV=test bin/shakapacker
  3. Are your webpack configs valid for test environment?

Test helper not found

Problem: LoadError: cannot load such file -- react_on_rails/test_helper

Solution: Make sure react_on_rails gem is available in test environment:

# Gemfile
gem "react_on_rails", ">= 16.0" # Not in a specific group

# Or explicitly in test group:
group :test do
gem "react_on_rails"
end

Performance Considerations

Asset Compilation Speed

Shakapacker auto-compilation:

  • Compiles on first request per test process
  • May compile multiple times in parallel test environments
  • Good for: Small test suites, simple webpack configs

React on Rails test helper:

  • Compiles once before entire test suite
  • Blocks test start until compilation complete
  • Good for: Large test suites, complex webpack configs

Faster Development with Watch Mode

If you're using the React on Rails test helper and want to avoid waiting for compilation on each test run, run your build command with the --watch flag in a separate terminal:

RAILS_ENV=test bin/shakapacker --watch

# Or with your package manager:
# pnpm run build:test --watch
# npm run build:test -- --watch
# yarn run build:test --watch

This keeps webpack running and recompiling automatically when files change, so your tests start faster.

Note: The --watch flag should only be used in a separate terminal process — never include it in build_test_command, which must exit after compilation.

Caching Strategies

Improve compilation speed with caching:

# config/shakapacker.yml
test:
cache_manifest: true # Cache manifest between runs

Parallel Testing

When running tests in parallel (with parallel_tests gem):

Shakapacker auto-compilation:

  • Each process compiles independently (may be slow)
  • Consider precompiling assets before running parallel tests:
    RAILS_ENV=test bin/shakapacker
    bundle exec rake parallel:spec

React on Rails test helper:

  • Compiles once before forking processes (efficient)
  • Works well out of the box with parallel testing

CI/CD Considerations

GitHub Actions / GitLab CI

Option 1: Precompile before tests

- name: Compile test assets
run: RAILS_ENV=test bundle exec rake react_on_rails:assets:compile_environment

- name: Run tests
run: bundle exec rspec

Option 2: Use Shakapacker auto-compilation

# config/shakapacker.yml
test:
compile: true

# CI workflow
- name: Run tests (assets auto-compile)
run: bundle exec rspec

Docker

When running tests in Docker, consider:

  1. Caching node_modules between builds
  2. Precompiling assets in Docker build stage
  3. Using bind mounts for local development

Best Practices

  1. Choose one approach - Don't mix Shakapacker auto-compilation with React on Rails test helper
  2. Use doctor command - Run rake react_on_rails:doctor to verify configuration
  3. Precompile in CI - Consider precompiling assets before running tests in CI
  4. Cache node_modules - Speed up installation with caching
  5. Monitor compile times - If tests are slow, check asset compilation timing

Summary Decision Matrix

ScenarioRecommendation
Simple test setupShakapacker compile: true
Large test suiteReact on Rails test helper
Parallel testingReact on Rails test helper or precompile
CI/CD pipelinePrecompile before tests
Quick local testsShakapacker compile: true
Custom build commandReact on Rails test helper

Need Help?