Skip to content

Conversation

@pedrofs
Copy link

@pedrofs pedrofs commented Dec 5, 2025

Summary

This PR adds comprehensive Minitest testing support alongside the existing RSpec matchers, providing the same testing capabilities for Minitest users who prefer classic assertion-style testing.

Motivation

Currently, inertia-rails only provides test helpers for RSpec. Many Rails developers use Minitest (Rails' default testing framework), and this PR brings first-class Minitest support to make testing Inertia responses easy and intuitive for those users.

Changes

New Features

  • 5 assertion methods for testing Inertia responses:

    • assert_inertia_component - Assert component name matches
    • assert_inertia_exact_props - Assert props match exactly
    • assert_inertia_includes_props - Assert props include specified keys/values
    • assert_inertia_exact_view_data - Assert view data matches exactly
    • assert_inertia_includes_view_data - Assert view data includes specified keys/values
  • Automatic render interception via setup/teardown hooks

  • Configuration system (InertiaRails::Minitest.config)

  • Warning system for missing Inertia renderers (suppressible)

  • Full documentation in README.md with usage examples

Files Added/Modified

  • lib/inertia_rails/minitest.rb - New Minitest test helpers implementation (160 lines)
  • spec/inertia/minitest_helper_spec.rb - Comprehensive test suite (320 lines, 23 passing specs)
  • README.md - Added Minitest documentation section with examples

Usage

# test/test_helper.rb
require 'inertia_rails/minitest'

class ActionDispatch::IntegrationTest
  include InertiaRails::Minitest::Helpers
end

# test/integration/events_test.rb
class EventsTest < ActionDispatch::IntegrationTest
  test "renders events index with correct data" do
    get events_path
    
    # Assert component
    assert_inertia_component 'Event/Index'
    
    # Assert props
    assert_inertia_exact_props(title: 'Events', events: [])
    assert_inertia_includes_props(title: 'Events')
    
    # Access inertia data directly
    assert_equal 'Event/Index', inertia.component
    assert_equal 'Events', inertia.props[:title]
  end
end

Implementation Details

  • The implementation mirrors the existing RSpec helpers in structure and functionality
  • Uses classic Minitest assertion style instead of expectation matchers
  • Handles both first-load (HTML with symbol keys) and sequential (JSON with string keys) requests
  • Includes the same InertiaRenderWrapper pattern used by RSpec helpers
  • Zero impact on existing RSpec functionality - both can coexist

Testing

  • All new Minitest helper tests pass (23 specs)
  • All existing RSpec helper tests still pass (16 specs)
  • No breaking changes to existing functionality

Documentation

  • Added comprehensive Minitest section to README.md
  • Included setup instructions, usage examples, and configuration options
  • Documented the difference between symbol/string keys for different request types

Related

This addresses the need for Minitest support mentioned in the community and provides feature parity with the RSpec testing experience.

pedrofs and others added 5 commits December 5, 2025 10:01
Adds comprehensive Minitest testing support alongside existing RSpec
matchers, providing the same testing capabilities for Minitest users.

Features:
- 5 assertion methods for testing Inertia responses:
  - assert_inertia_component
  - assert_inertia_exact_props
  - assert_inertia_includes_props
  - assert_inertia_exact_view_data
  - assert_inertia_includes_view_data
- Automatic render interception via setup/teardown hooks
- Configuration system (InertiaRails::Minitest.config)
- Warning system for missing Inertia renderers
- Full test coverage (23 passing specs)

Usage:
  require 'inertia_rails/minitest'

  class ActionDispatch::IntegrationTest
    include InertiaRails::Minitest::Helpers
  end

The implementation mirrors the RSpec helpers but uses classic Minitest
assertion style instead of expectation matchers.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
The intercepted Renderer.new method was treating named_args as a
positional parameter instead of keyword arguments, causing an
'ArgumentError: wrong number of arguments (given 5, expected 6)'
when rendering Inertia responses in tests.

Changed from:
  |component, controller, request, response, render, named_args|

To:
  |component, controller, request, response, render, **named_args|

This properly handles the keyword arguments passed by Rails when
calling InertiaRails::Renderer.new.

Fixes issue reported when testing real-world applications with
custom InertiaConfiguration concerns.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
The setup hook was trying to call inertia_wrap_render on the controller
instance, but that method only exists in the test helpers. This caused:

  NoMethodError: undefined method 'inertia_wrap_render' for an instance
  of Dashboard::WorkspacesController

Solution: Capture the test instance (self) in the setup block and call
inertia_wrap_render on it instead of on the controller.

This matches how RSpec's implementation works - the wrapping happens in
the test context, not the controller context.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
The define_singleton_method block was trying to access @_original_renderer_new
as an instance variable, but inside the closure it was looking for it on the
wrong object (InertiaRails::Renderer instead of the test instance), causing:

  NoMethodError: undefined method 'call' for nil

Solution: Capture both @_original_renderer_new and self as local variables
(original_renderer_new and test_instance) before creating the closure. This
ensures they're part of the closure's binding and accessible when the method
is called.

The instance variable @_original_renderer_new is still needed for teardown
to restore the original method.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Props and view_data now use HashWithIndifferentAccess, eliminating the
inconsistency where first-load (HTML) requests used symbol keys while
sequential (JSON) requests used string keys.

Benefits:
- Users can use either symbol or string keys in tests
- No need to remember which request type uses which key format
- Assertions accept either format: assert_inertia_exact_props(name: 'X')
  or assert_inertia_exact_props('name' => 'X')
- More intuitive and user-friendly testing experience

Implementation:
- Added require for 'active_support/core_ext/hash/indifferent_access'
- Wrapped props and view_data with .with_indifferent_access in
  InertiaRenderWrapper#assign_locals
- Updated assertion methods to convert expected values to indifferent
  access for consistent comparison
- Added tests to verify both symbol and string key access works

Updated README to document this improvement and removed the confusing
'Note on First Load vs Sequential Requests' section.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant