【问题标题】:Creating a shoulda matcher for links in view specs为视图规范中的链接创建一个应该匹配器
【发布时间】:2014-12-24 21:54:53
【问题描述】:

我可能在这里找错了树,但我正在尝试为 rails 视图规范构建一个应该匹配器。

现在我有一个看起来像这样的视图规范:

require 'rails_helper'

RSpec.describe 'layouts/_navigation', :type => :view do

  context 'everyone' do
    before :each do
      allow(view).to receive(:user_signed_in?).and_return(false)
      render
    end  

    it 'shows links to start reading' do
      expect(rendered).to have_link(I18n.t(:start_reading), :href => stories_path)
    end

    it 'shows links to home page' do
      expect(rendered).to have_link(I18n.t(:unknown_tales), root_path)
    end
  end
end

我希望能够将其替换为如下内容:

require 'rails_helper'

RSpec.describe 'layouts/_navigation', :type => :view do

  context 'everyone' do
    before :each do
      allow(view).to receive(:user_signed_in?).and_return(false)
      render
    end  


    it {should have_valid_link(I18n.t(:start_reading), stories_path)}
    it {should have_valid_link(I18n.t(:unknown_tales), root_path)}
  end
end

我对此进行了尝试,使用以下方法,但它不起作用:

RSpec::Matchers.define :have_valid_link do |title, path|
  description { "have valid link to #{path} on #{title}" }

  match do |rendered|
    expect(rendered).to have_link(title, :href => path)
  end

end

我不确定这是否不起作用,因为我做错了,或者如果匹配器从未设计用于处理视图。

谢谢

【问题讨论】:

    标签: ruby-on-rails rspec shoulda


    【解决方案1】:

    我对这个答案并不完全有信心,因为可能有替代/更简单的方法来解决这个问题,但这是我的理解:

    • 我认为这只是您在此处寻找的常规 RSpec“匹配器”。 shoulda 是一个包含一组特定匹配器的 gem。

    • 您需要通过subject 显式或隐式地将rendered 传递给您的匹配器。

    • 您的匹配器需要将渲染的字符串转换为 Capybara 节点才能使用 Capybara 匹配器,例如通过Capybara.string

    • match 方法应返回布尔值,而不是调用 expect

    综合起来,这给了你:

    require 'rails_helper'
    
    RSpec::Matchers.define :have_valid_link do |title, path|
      description { "have valid link to #{path} on #{title}" }
    
      match do |rendered|
        Capybara.string(rendered).has_link?(title, :href => path)
      end
    end
    
    RSpec.describe 'layouts/_navigation', :type => :view do
      context 'everyone' do
        subject { rendered }
    
        before :each do
          allow(view).to receive(:user_signed_in?).and_return(false)
          render
        end  
    
        it {should have_valid_link(I18n.t(:start_reading), stories_path)}
        it {should have_valid_link(I18n.t(:unknown_tales), root_path)}
      end
    end
    

    【讨论】:

    • 感谢您的回答,但它不起作用。我得到的错误是expected "everyone" to have valid link to /read on Start Reading,我认为这是因为rendered 的值是字符串everyone。也许还有另一种访问渲染视图的方法?
    • 您是否完全按照我在答案中指定的方式尝试了代码?如果你没有指定subject { rendered },你会得到你所看到的行为(即隐含的subject“每个人”)。
    • 对不起,我的错,我错过了subject { rendered } 行,添加并且它有效。你是明星,谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-26
    • 1970-01-01
    • 2020-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多