Ruby on rails RSpec,Capybara:将_重定向到不在创建/发布规范中工作

Ruby on rails RSpec,Capybara:将_重定向到不在创建/发布规范中工作,ruby-on-rails,selenium,rspec,capybara,Ruby On Rails,Selenium,Rspec,Capybara,我设置了一个简单的控制器,其功能符合规格: stamps\u controller.rb class StampsController < ApplicationController def new @stamp = Stamp.new end def create @stamp = Stamp.new(stamp_params) if @stamp.save redirect_to(stamp_url(@stamp.id), statu

我设置了一个简单的控制器,其功能符合规格:

stamps\u controller.rb

class StampsController < ApplicationController
  def new
    @stamp = Stamp.new
  end

  def create
    @stamp = Stamp.new(stamp_params)

    if @stamp.save
      redirect_to(stamp_url(@stamp.id), status: 201)
    else
      render 'new'
    end
  end

  def show
    @stamp = Stamp.find(params[:id])
  end

  private

  def stamp_params
    params.require(:stamp).permit(::percentage)
  end
end
RSpec.describe 'stamp requests', type: :request do
  describe 'stamp creation', js: true do
    before do
      FactoryBot.create_list(:domain, 2)
      FactoryBot.create_list(:label, 2)
    end

    it 'allows users to create new stamps' do
      visit new_stamp_path
      expect(page).to have_content('Percentage')

      find('#stamp_percentage').set('20')

      click_button 'Create'

      expect(current_path).to eq(stamp_path(Stamp.first.id))
    end
  end
end
根据:

Capybara会自动执行任何重定向,并提交与按钮关联的表单

但这不会在测试中发生,而是抛出一个错误:

预期:“/stamps/1”

得到:“/邮票”

结果很明显:它成功地创建了戳记,但未能重定向到新戳记。我还通过使用
binding.pry
确认了这一点

为什么水豚不按照文档中描述的重定向?
旁注:

  • 如果我使用普通驱动程序而不是js,它甚至会失败
  • 我研究了很多这样的问题和文档,没有发现任何有用的东西。一个我无法理解的潜在尝试是一个
  • 我的配置:
  • 支持/capybara.rb

    spec_helper.rb


    问题可能是提交表单后,
    current\u path
    需要一段时间才能更改。如果将
    sleep(x)
    放在
    expect(current\u path)
    之前,则代码可以工作

    相反,您应该使用具有所谓“等待行为”的方法,例如
    具有当前路径
    具有当前路径
    断言当前路径

    expect(page).to have_current_path(stamp_path(Stamp.first.id))
    


    问题可能是提交表单后,
    current\u path
    需要一段时间才能更改。如果将
    sleep(x)
    放在
    expect(current\u path)
    之前,则代码可以工作

    相反,您应该使用具有所谓“等待行为”的方法,例如
    具有当前路径
    具有当前路径
    断言当前路径

    expect(page).to have_current_path(stamp_path(Stamp.first.id))
    


    您的测试中有许多问题

    首先,Capybara不应用于
    请求
    规范中,而应用于功能/系统测试。一旦您确定不再需要将Capybara包括在每个RSpec测试中,并应从您的配置中删除
    config.include Capybara::DSL
    (当您需要
    capybara/rspec
    时,它会将capybara包含在测试类型中,它应该包含在-)

    其次,
    单击按钮
    不保证等待它触发的任何操作完成。因此,在尝试访问该操作创建的任何数据库对象之前,您需要等待可视页面更改(从技术上讲,您根本不应该在特性规范中直接访问数据库,但如果您打算…)

    第三,正如@chumakoff所指出的,您不应该对Capybara使用静态匹配器,而应该使用Capybara提供的匹配器

      click_button 'Create' 
      expect(page).to have_text('Stamp created!') # Whatever message is shown after creation
      expect(page).to have_path(stamp_path(Stamp.first.id))
    
    最后,你应该查看你的
    test.log
    ,并使用
    save_和_open_屏幕截图查看你的控制器实际做了什么-实际上,在创建时出现了一个错误,导致你的应用程序重定向到/stamps并显示错误消息(这也意味着您的测试数据库实际上没有在测试之间重置,或者您显示的工厂正在创建嵌套记录,等等)

    更新:重新阅读控制器代码后,我注意到您正在将201状态代码传递到
    重定向到
    201
    实际上不会执行重定向-从
    重定向到
    文档-

    请注意,状态代码必须是3xx HTTP代码,否则将导致重定向 不会发生


    您的测试中有许多问题

    首先,Capybara不应用于
    请求
    规范中,而应用于功能/系统测试。一旦您确定不再需要将Capybara包括在每个RSpec测试中,并应从您的配置中删除
    config.include Capybara::DSL
    (当您需要
    capybara/rspec
    时,它会将capybara包含在测试类型中,它应该包含在-)

    其次,
    单击按钮
    不保证等待它触发的任何操作完成。因此,在尝试访问该操作创建的任何数据库对象之前,您需要等待可视页面更改(从技术上讲,您根本不应该在特性规范中直接访问数据库,但如果您打算…)

    第三,正如@chumakoff所指出的,您不应该对Capybara使用静态匹配器,而应该使用Capybara提供的匹配器

      click_button 'Create' 
      expect(page).to have_text('Stamp created!') # Whatever message is shown after creation
      expect(page).to have_path(stamp_path(Stamp.first.id))
    
    最后,你应该查看你的
    test.log
    ,并使用
    save_和_open_屏幕截图查看你的控制器实际做了什么-实际上,在创建时出现了一个错误,导致你的应用程序重定向到/stamps并显示错误消息(这也意味着您的测试数据库实际上没有在测试之间重置,或者您显示的工厂正在创建嵌套记录,等等)

    更新:重新阅读控制器代码后,我注意到您正在将201状态代码传递到
    重定向到
    201
    实际上不会执行重定向-从
    重定向到
    文档-

    请注意,状态代码必须是3xx HTTP代码,否则将导致重定向 不会发生


    对于其他来到这里的人,另一个可能的解决方案是增加您的等待时间。无论是全局还是每次单击

    #全球
    Capybara.default\u max\u wait\u time=5
    #每次点击
    查找(“我的按钮”)。单击(等待:5)
    
    对于其他任何来到这里的人,另一个可能的解决方案是增加您的等待时间。无论是全局还是每次单击

    #全球
    Capybara.default\u max\u wait\u time=5
    #每次点击
    查找(“我的按钮”)。单击(等待:5)
    
    您是否尝试过
    expect(第页)。拥有当前路径(stamp\u path(stamp.first.id))
    ?您是否尝试过
    expect(第页)。拥有当前路径(stamp\u path(stamp.first.id))
    ?感谢您详尽的回答。关于1,我很高兴地从
      click_button 'Create' 
      expect(page).to have_text('Stamp created!') # Whatever message is shown after creation
      # Now you can safely access the DB for the created stamp
    
      click_button 'Create' 
      expect(page).to have_text('Stamp created!') # Whatever message is shown after creation
      expect(page).to have_path(stamp_path(Stamp.first.id))