Product.rb
class Product < ApplicationRecord
validates :name, presence: true, uniqueness: true
end
Product_spec.rb
require 'rails_helper'
require 'capybara/rspec'
RSpec.feature "Create Product", :type => :feature do
scenario "User creates a duplicate product" do
visit "/products/new"
fill_in "Name", :with => "My Widget"
click_button "Create"
#expect(page).to have_content("Name has already been taken")
#expect(flash[:notice]).to have_content("Name has already been taken")
expect(flash[:alert]).to match(/Name has already been taken/)
end
scenario "User creates a invalid product" do
visit "/products/new"
fill_in "Name", :with => ""
click_button "Create"
expect(flash[:alert]).to have_text("Name can't be blank.")
end
end
如何捕获Flash中引发的错误消息?我尝试了所有类似于has_content,包含等等
答案 0 :(得分:2)
您无法访问测试中的flash
对象,只能访问页面上显示的内容。因此你应该这样做
expect(page).to have_content("Name has already been taken")
或者如果您想检查文本是否出现在页面中的正确位置,并假设它出现在ID为“flash”的元素内,您可以这样做
expect(find('#flash')).to have_content("Name has already been taken")
您实际上并未在测试中显示已创建的另一个产品会与您正在创建的产品发生冲突,这可能就是您的测试失败的原因吗?
顺便说一句,假设您使用的RSpec.feature
别名是Capybara提供的别名,它在使用时已经设置了type: :feature
元数据,因此您无需另外指定它。
答案 1 :(得分:0)
如何捕获Flash中引发的错误消息?
flash只是一个存储在会话存储中的哈希。执行flash.alert('Oh no')
不会引发异常,也无法捕获。
您只是测试错了
功能规范是端到端规范,您实际向rails服务器发出http请求,然后将响应提供给Web浏览器模拟器。
这意味着您的规范和响应请求的rails代码在完全不同的进程中运行。所以你无法访问flash哈希。这与控制器测试不同,它会伪造整个请求,并允许您撬动rails应用程序。
相反,您在功能规范中测试的是从用户角度来看的应用程序。
require 'rails_helper'
require 'capybara/rspec'
RSpec.feature "Product creation" do
after(:each) do
Product.destroy_all
end
scenario "when a user creates a duplicate product" do
product = Product.create(name: "My Widget")
visit "/products/new"
fill_in "Name", with: product.name
click_button "Create"
expect(page).to have_content("Name has already been taken")
end
scenario "when a user creates a product without a name" do
visit "/products/new"
fill_in "Name", with: ""
click_button "Create"
expect(page).to have_content("Name can't be blank.")
end
end