水豚RSpec,水豚:redirect_to在创建/发布规格中不起作用

时间:2018-08-21 10:34:59

标签: ruby-on-rails selenium rspec capybara

我根据其feature_spec设置了一个简单的控制器:

stamps_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

specs / requests / stamps_request_spec.rb

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

根据the capybara docs

  

水豚会自动跟随所有重定向,并提交与按钮关联的表单。

但这在测试中不会发生,而是会引发错误:

  

预期:“ / stamps / 1

     

得到:“ /印章”

结果显而易见:它成功创建了图章,但无法重定向到新图章。我也使用binding.pry确认了这一点。

为什么水豚不会按照文档中的说明进行重定向?


侧注:

  1. 如果我使用普通驱动程序而不是js,它甚至会失败
  2. 我研究了很多SO问题和文档,没有发现有用的东西。我无法掌握的一种潜在尝试是answer with no specifics of how to implement it
  3. 我的配置:

support / capybara.rb

require 'capybara/rails'
require 'capybara/rspec'

Capybara.server = :puma
Capybara.register_driver :selenium do |app|
  Capybara::Selenium::Driver.new(app, browser: :firefox, marionette: true)
end

Capybara.javascript_driver = :selenium

RSpec.configure do |config|
  config.include Capybara::DSL
end

spec_helper.rb

ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../config/environment', __dir__)
require 'rspec/rails'
require 'factory_bot_rails'
require 'pundit/matchers'

Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }

RSpec.configure do |config|
  # .
  # unrelated stuff
  # .
end

3 个答案:

答案 0 :(得分:1)

问题可能是提交表单后current_path会花费一些时间。如果将sleep(x)放在expect(current_path)之前,您的代码将起作用。

相反,您应该使用具有所谓“等待行为”的方法,例如has_current_path?have_current_pathassert_current_path

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

expect(page.has_current_path?(stamp_path(Stamp.first.id))).to eq true

答案 1 :(得分:1)

您的测试中存在许多问题。

首先,Capybara并不是要在request规范-https://relishapp.com/rspec/rspec-rails/docs/request-specs/request-spec中使用,而应与功能/系统测试一起使用。修复问题后,您不再需要将Capybara包含在每个RSpec测试中,而应从配置中删除config.include Capybara::DSL(当您需要capybara/rspec时,应将Capybara包含在测试类型中)在-https://github.com/teamcapybara/capybara/blob/master/lib/capybara/rspec.rb#L10

第二,不能保证click_button等待它触发的任何操作完成。因此,您需要等待可视页面更改,然后再尝试访问由该操作创建的任何数据库对象(从技术上讲,您实际上根本不应该在功能规格中进行直接的数据库访问,但是如果要...)

  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

第三,如@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_and_open_screenshot来查看您的控制器实际执行的操作-实际上,在创建过程中会引发错误,导致您的应用重定向到/ stamps并显示错误消息(也暗示您的测试数据库实际上没有在测试之间重置,或者您显示的工厂正在创建嵌套记录等)。

更新:重新读取您的控制器代码后,我注意到您正在向redirect_to传递201状态代码。 201实际上不会进行重定向-来自redirect_to文档-https://api.rubyonrails.org/classes/ActionController/Redirecting.html#method-i-redirect_to

  

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

答案 2 :(得分:0)

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

testlist= ['brioche','sandwich','bread,','shrimp,','peeled,','tail','fan','attached,','butter','dill','shallot','Equipment:','cups']