Skip to content

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

Available since:inertia_rails:3.17.0

Inertia Rails provides test helpers for both RSpec and Minitest.

ruby
# 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.

DescriptionRSpecMinitest
Inertia responsebe_inertia_responseassert_inertia_response / refute_inertia_response
Component namerender_componentassert_inertia_component / refute_inertia_component
Props (partial match)have_propsassert_inertia_props / refute_inertia_props
Props (exact match)have_exact_propsassert_inertia_props_equal / refute_inertia_props_equal
Prop key absenthave_no_propassert_no_inertia_prop
View data (partial match)have_view_dataassert_inertia_view_data / refute_inertia_view_data
View data (exact match)have_exact_view_dataassert_inertia_view_data_equal / refute_inertia_view_data_equal
View data key absenthave_no_view_dataassert_no_inertia_view_data
Flash (partial match)have_flashassert_inertia_flash / refute_inertia_flash
Flash (exact match)have_exact_flashassert_inertia_flash_equal / refute_inertia_flash_equal
Flash key absenthave_no_flashassert_no_inertia_flash
Deferred propshave_deferred_propsassert_inertia_deferred_props / refute_inertia_deferred_props
ruby
# 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
end

Common Testing Tasks

Test Flash Messages

Inertia Rails automatically shares flash data with your frontend.

ruby
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
end

Test Validation Errors

Validation errors are shared as props automatically when using redirect_to with inertia_errors. Assert them on the errors key.

ruby
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
end

Test Redirects

After a redirect, use follow_redirect! and assert the resulting Inertia response.

ruby
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
end

Test Deferred Props

Deferred props are excluded from the initial page load and fetched in a subsequent request.

ruby
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
end

Test Partial Reloads

Use inertia_reload_only, inertia_reload_except, and inertia_load_deferred_props to simulate partial reloads and deferred prop loading.

ruby
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
end

Configuration

evaluate_optional_props

Available since:inertia_rails:3.18.0

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:

ruby
# spec/rails_helper.rb
require 'inertia_rails/rspec'

InertiaRails::Testing.evaluate_optional_props = true

Optional and deferred props are then included in inertia.props on first load:

ruby
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:

ruby
around do |example|
  InertiaRails::Testing.evaluate_optional_props = true
  example.run
ensure
  InertiaRails::Testing.evaluate_optional_props = false
end

WARNING

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.