I’m currently building a Rails 7 app that was started with rails new myapp --css=bootstrap. This means Rails set up my app to use esbuild to compile all my CSS and JavaScript assets. This new --css flag provided by Rails is a fantastic improvement over previous implementations like Webpacker. Now we can just run bin/dev to start up our local development server and have it watch for changed files so that it can recompile the assets if needed.

That’s a good start, but what about testing? System tests, specifically, will need to interact with a current compilation of our assets. You shouldn’t be relegated to firing up a local development environment to get things compiled and accurate for your tests as you change your code. I’m sure there are several ways to solve this, but here’s what I’m doing.

Compile Before the Tests Run

I’m using rspec-rails for my tests, but the gist of this post should work with whatever you’re using. In rails_helper.rb I add a little check that runs the nifty rails test:prepare to get everything compiled.

# rails_helper.rb
RSpec.configure do |config|
  # Precompile the assets (used by system tests)
  config.before :all do
      prep_passed = system "rails test:prepare"
      abort "\nYour assets didn't compile. Exiting WITHOUT running any tests. Review the output above to resolve any errors." if !prep_passed

The system command returns true or false depending on whether asset compilation succeeds. If the compilation fails, we abort and skip running the tests. If things are successful, we continue with the tests while setting an environment variable that stops the compilation from running every time.

This should get you started in the correct direction to be able to compile your JavaScript and CSS for Rails system tests. Your solution may need to be tweaked based on what you and/or your team have set up.

Good luck!

Written by Matt Haliski

The First of His Name, Consumer of Tacos, Operator of Computers, Mower of Grass, Father of the Unsleeper, King of Bad Function Names, Feeder of AI Overlords.