You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Capybara测试Turbo删除链接时出现No route matches [DELETE] "/"错误

问题描述

在使用Capybara测试Turbo删除链接时,触发ActionController::RoutingError: No route matches [DELETE] "/"错误,但在系统测试外该功能正常运行。

相关代码

删除链接(ERB)

<%= link_to "delete", client, data: {
          "turbo-method": :delete,
          "turbo-confirm": "Are you sure?" } %>

系统测试代码(Minitest + Capybara)

test "delete client" do
    accept_confirm do
      first("ul.clients li#client-#{@client.id} span.client-controls a").click
    end
    assert_selector "div.alert-success", text: "Client is deleted!"
  end

ClientsController#destroy方法

def destroy
    get_client.destroy
    flash[:success] = "Client is deleted!"
    redirect_to root_url
  end

  private

    def get_client
      Client.find(params[:id])
    end

环境与异常细节

  • 环境:Rails 7、capybara(3.37.1)、selenium-webdriver(4.1.0)、minitest(5.15.0)
  • 排查发现:链接的href属性为正确的客户端路径(如/clients/123);查看test.log显示,DELETE /clients/xxx请求执行正常,删除完成后重定向到根路径,但随后发起了DELETE "/"请求导致路由错误。
  • 已知Capybara曾存在Turbo方法支持问题,但该问题已通过commit cc451e77修复。
问题原因与解决方法

原因分析

问题核心在于Turbo的重定向逻辑与Capybara的accept_confirm方法存在冲突:

  1. 正常流程中,点击Turbo删除链接后,前端触发确认弹窗,确认后发送DELETE请求到目标路径;服务器处理完成后返回重定向,Turbo会以GET方法请求根路径。
  2. 但测试中使用accept_confirm时,Capybara的内部逻辑会在确认弹窗后额外触发一次点击事件。此时页面正处于重定向过程中,原删除链接可能已不存在,或Capybara误定位到根路径的元素,导致错误发送DELETE "/"请求。
  3. 另外,Turbo对302重定向会默认沿用原请求方法,若Capybara页面状态未正确重置,也可能导致方法上下文残留,引发错误请求。

解决方法

方法1:移除accept_confirm,让Turbo处理确认弹窗

Turbo的turbo-confirm是前端原生处理的确认逻辑,无需依赖Capybara的accept_confirm。直接简化测试代码:

test "delete client" do
  first("ul.clients li#client-#{@client.id} span.client-controls a").click
  assert_selector "div.alert-success", text: "Client is deleted!"
end

若弹窗未自动确认,可在测试文件开头或setup方法中添加配置:

Capybara.automatic_confirm = true

方法2:精确定位元素,避免误点击

改用find方法更精准定位删除链接,减少误触概率:

test "delete client" do
  find("li#client-#{@client.id} a", text: "delete").click
  assert_selector "div.alert-success", text: "Client is deleted!"
end

方法3:重定向时指定status: :see_other

在控制器中修改重定向代码,使用303 See Other状态码强制Turbo以GET方法发起重定向请求:

def destroy
  get_client.destroy
  flash[:success] = "Client is deleted!"
  redirect_to root_url, status: :see_other
end

Rails 7默认重定向状态码为302,Turbo会尝试沿用原请求方法;而303状态码符合RESTful规范,明确要求后续请求使用GET,从根源避免方法上下文残留问题。

内容的提问来源于stack exchange,提问作者fpiskur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 15:10:43