mcpField
I
inertia-rails-testing

inertia-rails-testing

github.com/inertia-rails测试与质量70467 次安装37 周前更新
代码仓库

关于 inertia-rails-testing

面向 Rails 应用中 Inertia 响应的 RSpec 和 Minitest 测试指南。涵盖响应匹配器、属性、flash 消息、延迟属性、重定向及全栈请求测试。

主要功能

  1. 01RSpec Inertia 匹配器
  2. 02属性与 flash 断言
  3. 03延迟属性测试辅助工具
  4. 04部分重新加载辅助工具
  5. 05Minitest 参考指南

适用场景

  1. 01检查渲染组件和属性
  2. 02测试重定向后的 flash 数据
  3. 03验证延迟属性与重新加载
  4. 04使用请求测试测试 Inertia 端点

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/inertia-rails/skills --skill inertia-rails-testing

安装后在 Claude Code 中输入/inertia-rails-testing确认已加载。

附带文件references/minitest.md

详细介绍

Inertia Rails 测试

使用 RSpec 和 Minitest 测试 Inertia 响应的模式。

对于每个控制器操作,请验证:

  • 正确的组件 → render_component('users/index')
  • 预期的 props → have_props(users: satisfy { ... })
  • 没有泄露数据 → have_no_prop(:secret)
  • Flash 消息 → follow_redirect!,然后使用 have_flash(notice: '...')
  • 延迟加载的 props → have_deferred_props(:analytics)

常见错误: PRG 后忘记调用 follow_redirect!——如果不调用,你断言的将是 302 重定向响应,而不是后续的 Inertia 页面。

设置

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

RSpec 匹配器

匹配器用途
be_inertia_response验证响应是否为 Inertia 格式
render_component('path')检查渲染的组件名称
have_props(key: value)部分匹配 props
have_exact_props(key: value)精确匹配 props
have_no_prop(:key)断言 prop 不存在
have_flash(key: value)部分匹配 flash
have_exact_flash(key: value)精确匹配 flash
have_no_flash(:key)断言 flash 不存在
have_deferred_props(:key)检查延迟加载的 props 是否存在
have_view_data(key: value)部分匹配 view_data

RSpec 示例

始终使用匹配器(render_component、have_props、have_flash),而不是 直接访问属性(inertia.component、inertia.props[:key]):

# BAD — direct property access:
# expect(inertia.component).to eq('users/index')
# expect(inertia.props[:users].length).to eq(3)

# GOOD — use matchers:
expect(inertia).to render_component('users/index')
expect(inertia).to have_props(users: satisfy { |u| u.length == 3 })
# Key pattern: follow_redirect! after POST/PATCH/DELETE before asserting
it 'redirects with flash on success' do
  post users_path, params: { user: valid_params }

  expect(response).to redirect_to(users_path)
  follow_redirect!
  expect(inertia).to have_flash(notice: 'User created!')
end

it 'returns validation errors on failure' do
  post users_path, params: { user: { name: '' } }

  follow_redirect!
  expect(inertia).to have_props(errors: hash_including('name' => anything))
end
测试共享 Props

来自 inertia_share 的共享 props 会包含在 inertia.props 中。需要先引入 inertia_rails/rspec,之后 type: :request 规格中即可使用 inertia 辅助方法:

it 'includes shared auth data' do
  sign_in(user)
  get dashboard_path

  expect(inertia).to have_props(
    auth: hash_including(user: hash_including(id: user.id))
  )
end
it 'excludes auth data for unauthenticated users' do
  get dashboard_path

  expect(inertia).to have_props(auth: hash_including(user: nil))
end
测试延迟加载的 Props
it 'defers expensive analytics data' do
  get dashboard_path

  expect(inertia).to have_deferred_props(:analytics, :statistics)
  expect(inertia).to have_deferred_props(:slow_data, group: :slow)
end
部分重新加载辅助方法
it 'supports partial reload' do
  get users_path

  # Simulate partial reload — only fetch specific props
  inertia_reload_only(:users, :pagination)

  # Or exclude specific props
  inertia_reload_except(:expensive_stats)

  # Load deferred props
  inertia_load_deferred_props(:default)
  inertia_load_deferred_props # loads all groups
end
测试外部重定向(inertia_location)
it 'redirects to Stripe via inertia_location' do
  post checkout_path

  # inertia_location returns 409 with X-Inertia-Location header
  expect(response).to have_http_status(:conflict)
  expect(response.headers['X-Inertia-Location']).to match(/stripe\.com/)
end
切勿测试以下内容
  • Inertia 框架行为——不要测试 <Form> 是否发送 CSRF 令牌,也不要测试 router.visit 是否有效。请测试你自己的控制器逻辑。
  • 精确的 prop 结构——使用 have_props(users: satisfy { ... }),而不是对完整 JSON 进行深度相等比较。脆弱的测试会在你添加列时失效。
  • 未调用 follow_redirect! 就断言 Flash——POST/PATCH/DELETE 后发生重定向时,断言 flash 或 props 之前,必须调用 follow_redirect!。否则你断言的将是 302 响应,而不是页面。
  • 断言初始加载时的延迟加载 prop 值——初始响应中的延迟加载 props 为 nil,因为它们会在页面渲染后通过单独的请求获取。使用 have_deferred_props(:key) 验证它们已注册,或使用 inertia_load_deferred_props 在测试中解析它们。
  • 模拟的 Inertia 响应——使用 type: :request 规格来测试完整堆栈。type: :controller 规格中的 assigns 不起作用,因为 Inertia 使用自定义渲染管线,该管线只会在完整请求周期中执行。
直接访问(尽可能使用上述匹配器)
inertia.component       # => 'users/index'
inertia.props           # => { users: [...] }
inertia.props[:users]   # direct prop access
inertia.flash           # => { notice: 'Created!' }
inertia.deferred_props  # => { default: [:analytics], slow: [:report] }

相关技能

  • 控制器模式 → inertia-rails-controllers(prop 类型、flash、PRG)
  • 表单流程 → inertia-rails-forms(提交、验证)
  • 延迟加载/共享 props → inertia-rails-pages(Deferred、usePage)

参考资料

必须——在编写 Minitest 测试(而非 RSpec)时阅读整个文件: references/minitest.md(约 40 行)——与上述 RSpec 匹配器等效的 Minitest 断言。

RSpec 项目不要加载 minitest.md——上述匹配器已足够。

评论

支持 Markdown