Testing
There are many different ways to test an Inertia application. This page provides a quick overview of the tools available.
End-to-end Tests
One popular approach to testing your JavaScript page components is to use an end-to-end testing tool like Cypress or Pest. These are browser automation tools that allow you to run real simulations of your app in the browser. These tests are known to be slower; however, since they test your application at the same layer as your end users, they can provide a lot of confidence that your app is working correctly. And, since these tests are run in the browser, your JavaScript code is actually executed and tested as well.
Client-Side Unit Tests
Another approach to testing your page components is using a client-side unit testing framework, such as Vitest, Jest, or Mocha. This approach allows you to test your JavaScript page components in isolation using Node.js.
Endpoint Tests
Inertia Rails provides test helpers for both RSpec and Minitest.
# spec/rails_helper.rb
require 'inertia_rails/rspec'RSpec helpers are automatically available in all request specs. Minitest helpers are automatically included in ActionDispatch::IntegrationTest.
Assertions
Both RSpec and Minitest provide matchers/assertions for testing Inertia responses. In RSpec, negation is done with not_to.
The inertia helper gives you direct access to inertia.props, inertia.component, inertia.view_data, inertia.flash, and inertia.deferred_props.
| Description | RSpec | Minitest |
|---|---|---|
| Inertia response | be_inertia_response | assert_inertia_response / refute_inertia_response |
| Component name | render_component | assert_inertia_component / refute_inertia_component |
| Props (partial match) | have_props | assert_inertia_props / refute_inertia_props |
| Props (exact match) | have_exact_props | assert_inertia_props_equal / refute_inertia_props_equal |
| Prop key absent | have_no_prop | assert_no_inertia_prop |
| View data (partial match) | have_view_data | assert_inertia_view_data / refute_inertia_view_data |
| View data (exact match) | have_exact_view_data | assert_inertia_view_data_equal / refute_inertia_view_data_equal |
| View data key absent | have_no_view_data | assert_no_inertia_view_data |
| Flash (partial match) | have_flash | assert_inertia_flash / refute_inertia_flash |
| Flash (exact match) | have_exact_flash | assert_inertia_flash_equal / refute_inertia_flash_equal |
| Flash key absent | have_no_flash | assert_no_inertia_flash |
| Deferred props | have_deferred_props | assert_inertia_deferred_props / refute_inertia_deferred_props |
# spec/requests/events_spec.rb
RSpec.describe '/events' do
describe '#index' do
let!(:event) { Event.create!(title: 'Rails World', start_date: '2026-09-23', description: 'Annual Ruby on Rails conference') }
it 'renders inertia component' do
get events_path
expect(inertia).to be_inertia_response
expect(inertia).to render_component 'events/index'
expect(inertia).to have_props(title: 'Rails World')
expect(inertia).to have_exact_props(title: 'Rails World', start_date: '2026-09-23', description: 'Annual Ruby on Rails conference')
# Props support both symbol and string keys
expect(inertia.props[:title]).to eq 'Rails World'
expect(inertia.props['title']).to eq 'Rails World'
expect(inertia).to have_view_data(timezone: 'UTC')
expect(inertia).to have_exact_view_data(timezone: 'UTC')
expect(inertia.view_data[:timezone]).to eq 'UTC'
expect(inertia).to have_no_prop(:secret)
end
end
endCommon Testing Tasks
Test Flash Messages
Inertia Rails automatically shares flash data with your frontend.
RSpec.describe '/events' do
it 'shows flash message after create' do
post events_path, params: { event: { title: 'New Event' } }
expect(inertia).to have_flash(notice: 'Event created!')
expect(inertia).to have_exact_flash(notice: 'Event created!')
expect(inertia.flash[:notice]).to eq 'Event created!'
expect(inertia).to have_no_flash(:alert)
end
endTest Validation Errors
Validation errors are shared as props automatically when using redirect_to with inertia_errors. Assert them on the errors key.
RSpec.describe '/events' do
it 'returns validation errors' do
post events_path, params: { event: { title: '' } }
expect(inertia).to render_component 'events/new'
expect(inertia).to have_props(errors: { title: ["can't be blank"] })
end
endTest Redirects
After a redirect, use follow_redirect! and assert the resulting Inertia response.
RSpec.describe '/events' do
it 'redirects after create' do
post events_path, params: { event: { title: 'Conference' } }
follow_redirect!
expect(inertia).to render_component 'events/show'
expect(inertia).to have_flash(notice: 'Event created!')
end
endTest Deferred Props
Deferred props are excluded from the initial page load and fetched in a subsequent request.
RSpec.describe '/events' do
it 'defers expensive data' do
get events_path
expect(inertia).to have_deferred_props
expect(inertia).to have_deferred_props(:analytics)
expect(inertia).to have_deferred_props(:analytics, :statistics)
# Check a specific group
expect(inertia).to have_deferred_props(:other_data, group: :slow)
expect(inertia.deferred_props[:default]).to include('analytics')
expect(inertia.props[:analytics]).to be_nil
end
endTest Partial Reloads
Use inertia_reload_only, inertia_reload_except, and inertia_load_deferred_props to simulate partial reloads and deferred prop loading.
RSpec.describe '/events' do
it 'supports partial reloads' do
get events_path
inertia_reload_only(:analytics, :statistics)
expect(inertia.props[:analytics]).to be_present
inertia_reload_except(:expensive_data)
# Load deferred props by group
inertia_load_deferred_props(:default)
# Load all deferred props
inertia_load_deferred_props
end
endConfiguration
evaluate_optional_props
By default, optional and deferred props are excluded on first load — just like in production. This means inertia.props[:my_optional] returns nil unless you simulate a partial reload.
To have these props evaluated on first load in tests, enable evaluate_optional_props:
# spec/rails_helper.rb
require 'inertia_rails/rspec'
InertiaRails::Testing.evaluate_optional_props = trueOptional and deferred props are then included in inertia.props on first load:
get events_path
expect(inertia.props[:analytics]).to be_present
expect(inertia.props[:statistics]).to eq({ views: 100 })You can also toggle this setting per-test:
around do |example|
InertiaRails::Testing.evaluate_optional_props = true
example.run
ensure
InertiaRails::Testing.evaluate_optional_props = false
endWARNING
When evaluate_optional_props is enabled, deferred props will appear in inertia.props but will still be listed in inertia.deferred_props. Partial reload behaviour is unaffected — this setting only changes first-load behaviour.