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 recommended approach is React on Rails TestHelper with build_test_command:
# config/initializers/react_on_rails.rb
ReactOnRails.configure do |config|
config.build_test_command = "RAILS_ENV=test bin/shakapacker"
end
Then wire TestHelper into your test framework. If your app uses both RSpec and Minitest, wire both files.
RSpec — add to spec/rails_helper.rb:
require "react_on_rails/test_helper"
RSpec.configure do |config|
ReactOnRails::TestHelper.configure_rspec_to_compile_assets(config)
end
Minitest — add to test/test_helper.rb:
require "react_on_rails/test_helper"
class ActiveSupport::TestCase
setup do
ReactOnRails::TestHelper.ensure_assets_compiled
end
end
Two Approaches to Test Asset Compilation
React on Rails supports two mutually exclusive approaches for compiling webpack assets during tests:
Approach 1: React on Rails Test Helper + build_test_command (Recommended)
Best for: Most applications, especially SSR, large suites, and explicit build control
Configuration:
# 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
In config/shakapacker.yml, keep test compilation off to avoid mixing approaches:
test:
<<: *default
compile: false
public_output_path: webpack/test
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_commandmust not include the--watchoption. 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_pathandpublic_output_pathinconfig/shakapacker.yml). If the folder is missing, empty, or contains files listed inwebpack_generated_fileswithmtimes older than any source files, assets are recompiled. - Uses the
build_test_commandconfiguration - 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
- ✅ Reliable for SSR tests because assets are built before first render
Cons:
- ⚠️ Requires additional configuration in test helpers
- ⚠️ More setup to maintain
- ⚠️ Requires
build_test_commandto 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
- You run SSR tests and need server bundles available before first request
Approach 2: Shakapacker Auto-Compilation (Alternative)
Best for: Simpler non-SSR test setups or teams that prefer minimal configuration
Configuration:
# config/shakapacker.yml
test:
<<: *default
compile: true
public_output_path: webpack/test
And remove React on Rails TestHelper wiring:
- Remove
config.build_test_command - Remove
ReactOnRails::TestHelpercalls inspec/rails_helper.rbortest/test_helper.rb
How it works:
- Shakapacker compiles assets on demand when packs are requested
- No React on Rails TestHelper setup is required
Pros:
- ✅ Simpler setup
- ✅ Works across frameworks without helper wiring
Cons:
- ⚠️ Less explicit compilation timing
- ⚠️ May compile multiple times in long or parallel runs
- ⚠️ For SSR tests, first-request ordering can matter if server bundles are not prebuilt
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
-
Set
compile: trueinconfig/shakapacker.ymltest section:test:
compile: true
public_output_path: webpack/test -
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) -
Remove or comment out
build_test_commandin 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
-
Set
compile: falseinconfig/shakapacker.ymltest section:test:
compile: false
public_output_path: webpack/test -
Add
build_test_commandto React on Rails config:# config/initializers/react_on_rails.rb
config.build_test_command = "RAILS_ENV=test bin/shakapacker" -
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
To auto-apply supported test-setup fixes (recommended path), run:
FIX=true bundle exec rake react_on_rails:doctor
The doctor will check:
- Whether
compile: trueis set in shakapacker.yml - Whether
build_test_commandis configured - Whether test helpers are properly set up
- Whether each detected framework (RSpec/Minitest) is wired independently
- 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:
-
If using Shakapacker auto-compilation:
# config/shakapacker.yml
test:
compile: true # ← Make sure this is true -
If using React on Rails test helper:
- Verify
build_test_commandis set - Check that test helper is configured in spec/test helper
- Run
bundle exec rake react_on_rails:doctor
- Verify
Assets compiling multiple times
Problem: Tests are slow because assets compile repeatedly.
Solutions:
-
If using Shakapacker auto-compilation:
- Switch to React on Rails test helper for one-time compilation
- Or ensure
cache_manifest: truein shakapacker.yml
-
If using React on Rails test helper:
- This shouldn't happen - assets should compile only once
- Check that you don't also have
compile: truein 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:
-
Does
bin/shakapackerexist and is it executable?ls -la bin/shakapacker
chmod +x bin/shakapacker # If needed -
Can you run the command manually?
RAILS_ENV=test bin/shakapacker -
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
--watchflag should only be used in a separate terminal process — never include it inbuild_test_command, which must exit after compilation.
Automatic Dev Asset Reuse (Static Mode)
When you run bin/dev static, React on Rails automatically detects the fresh development assets and reuses them for tests — no extra commands or environment variables needed.
# Terminal 1: Start static development
bin/dev static
# Terminal 2: Just run tests — they automatically use dev assets
bundle exec rspec
How it works: When bundle exec rspec (or Minitest) runs and test assets are stale or missing, the TestHelper checks if development assets in public/packs/ are:
- Present (manifest.json exists)
- Static mode (not HMR — no
http://URLs in manifest entries) - Fresh (manifest newer than all source files)
If all checks pass, React on Rails temporarily overrides Shakapacker's test config to point at the development output. You'll see:
====> React on Rails: Reusing development assets from packs
(detected fresh static-mode webpack output, skipping test compilation)
No shakapacker.yml changes are needed. The override only lasts for the test process.
Running bin/dev (HMR) and Tests Together
HMR assets are served from webpack-dev-server memory and contain http:// URLs in the manifest, so they cannot be reused by tests. When using HMR mode, you have two options:
Option A: Let TestHelper compile on demand (simplest)
# Terminal 1
bin/dev
# Terminal 2 — TestHelper runs build_test_command automatically if assets are stale
bundle exec rspec
This works but adds compilation time to the first test run.
Option B: Use a test watcher for fast iteration
# Terminal 1
bin/dev
# Terminal 2 — keeps test assets fresh in the background
bin/dev test-watch
# Terminal 3
bundle exec rspec
bin/dev test-watch auto-selects watch mode:
auto(default): picksclient-onlyif another shakapacker watcher is already running; otherwisefullfull: always builds test client + server bundles (--test-watch-mode=full)client-only: only builds test client bundles (--test-watch-mode=client-only)
Which Mode Should I Use?
| Scenario | Recommendation |
|---|---|
| General development | bin/dev static — simpler, no FOUC, tests just work |
| Need Hot Module Replacement | bin/dev + bin/dev test-watch for fast test iteration |
| CI / no dev server running | Just bundle exec rspec — TestHelper compiles automatically |
| Only running a few tests | bin/dev static + bundle exec rspec spec/path/to_spec.rb |
Migration to bin/dev test-watch
If you previously ran manual test watcher commands, migrate to the new wrapper:
-
Old:
RAILS_ENV=test bin/shakapacker --watch -
New:
bin/dev test-watch -
Old:
RAILS_ENV=test CLIENT_BUNDLE_ONLY=yes bin/shakapacker --watch -
New:
bin/dev test-watch --test-watch-mode=client-only
Advanced: Manual Shared Output (Alternative)
If you prefer to manually share output paths instead of using automatic detection:
-
Set the test output path equal to development in
config/shakapacker.yml:development:
public_output_path: packs
test:
public_output_path: packs -
Run static development mode and tests:
bin/dev static # Terminal 1
bundle exec rspec # Terminal 2
Warning: Do not share output paths with
bin/dev(HMR mode) — HMR manifests will cause test failures.
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:
- Caching
node_modulesbetween builds - Precompiling assets in Docker build stage
- Using bind mounts for local development
Best Practices
- Choose one approach - Don't mix Shakapacker auto-compilation with React on Rails test helper
- Use doctor command - Run
rake react_on_rails:doctorto verify configuration - Precompile in CI - Consider precompiling assets before running tests in CI
- Cache node_modules - Speed up installation with caching
- Monitor compile times - If tests are slow, check asset compilation timing
Summary Decision Matrix
| Scenario | Recommendation |
|---|---|
| Default setup | React on Rails test helper |
| SSR test coverage | React on Rails test helper |
| Large test suite | React on Rails test helper |
| Parallel testing | React on Rails test helper or precompile |
| CI/CD pipeline | Precompile before tests |
| Quick local tests | Shakapacker compile: true |
| Custom build command | React on Rails test helper |
Related Documentation
- Dev Server and Testing — How
bin/dev(HMR vs static) interacts with Capybara, Playwright, Minitest system tests, and SSR request specs - Configuration Reference
- Shakapacker Configuration
- TestHelper Source Code
Need Help?
- Forum: ShakaCode Forum
- Docs: React on Rails Guides
- Support: justin@shakacode.com