使用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方法存在冲突:
- 正常流程中,点击Turbo删除链接后,前端触发确认弹窗,确认后发送
DELETE请求到目标路径;服务器处理完成后返回重定向,Turbo会以GET方法请求根路径。 - 但测试中使用
accept_confirm时,Capybara的内部逻辑会在确认弹窗后额外触发一次点击事件。此时页面正处于重定向过程中,原删除链接可能已不存在,或Capybara误定位到根路径的元素,导致错误发送DELETE "/"请求。 - 另外,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
相关产品推荐
相关产品推荐

