DOM Capybara 测试中的遍历

DOM traversal in Capybara testing

快速总结:为什么水豚找不到 .admin-edit class?

所以,我建立了一个网站,其中有已发表和未发表的文章,访客只能看到已发表的文章,而管理员可以看到所有内容。登录是通过设计处理的,一个简单的 erb 表达式确定是否显示文章或 'published'.

我在我的文章控制器的索引操作上列出文章,并渲染一个部分来显示文章。

<% if article.published %>
  <dl class="individual-article">
    <dt><%= article.title %> 
      <% if current_user.try(:admin) %>
        | <span class="admin-edit"><%= link_to 'Edit', edit_article_path(article) %></span>
    <% end %><br> 
    <span class="article-tags">
        <%= raw article.tags.map(&:name).map { |t| link_to t, tag_path(t) }.join(', ') %></span>
    </dt>
    <dd><%= truncate(article.body.html_safe, length: 200) %>
        <%= link_to 'more', article_path(article) %>
    </dd>
  </dl>
<% end %>

这按预期工作,但我无法正确测试它。特别是,如果用户是管理员,则期望找到 'Edit' 时 returns 为 false。

这是我的 sign_in_spec:

require 'rails_helper'

RSpec.describe "SignIns", type: :request do

describe "the sign in path" do
  let(:user)        { FactoryGirl.create(:user)      }
  let(:admin)       { FactoryGirl.create(:admin)     }
  let(:article)     { FactoryGirl.create(:article)   }
  let(:published)   { FactoryGirl.create(:published) }

  it "lets a valid user login and redirects to main page" do
    visit '/users/sign_in' 
    fill_in 'user_email',    :with => admin.email
    fill_in 'user_password', :with => admin.password 
    click_button 'Log in'
    expect(current_path).to eq '/'
    expect(page).to have_css('span.admin-edit')
  end
end  

这是我的文章工厂:

FactoryGirl.define do
  factory :article do
    title 'Title'
    body  'Content'

  factory :published do 
    published true 
  end
end 

这是我的用户工厂:

FactoryGirl.define do 

  factory :user do 
    email 'user@gmail.com'
    password 'password'

    factory :admin do 
      admin true 
    end
  end
end

这是错误:

1) SignIns the sign in path lets a valid user login and redirects to main page
 Failure/Error: expect(page).to have_css('span.admin-edit')
   expected #has_css?("span.admin-edit") to return true, got false
 # ./spec/requests/sign_ins_spec.rb:18:in `block (3 levels) in <top (required)>'

我试过以下方法:

  1. 如果 rspec 对多个 classes
  2. 有问题,则删除多余的文章
  3. 将have_css更改为have_selector并选择锚标签
  4. 从 html 正文中抽取整个 DOM 根 ...
  5. 通过以具有管理员权限的用户身份手动登录来检查它是否在规范之外工作 -> 它确实如此。
  6. 尝试删除未发表文章与已发表文章的区别,但仍然失败。
  7. 尝试删除 erb 条件以检查文章是否在视图中发布但仍然失败。
  8. 尝试确保它不是通过 ajax 加载(在 will_paginate 中有备份)但失败了。

我做错了什么?

编辑

如果我避免使用 FactoryGirl 导入,它现在可以工作了:

@article = Article.create(title: 'Title', body: 'body', published: true)

而不是

let(:published) { FactoryGirl.create(:published) }

不知道为什么。

RSpec 延迟分配 let 变量,因此在您显示页面时,已发布和未发布的文章都不存在。您需要使用 let!before 或以其他方式确保在显示页面之前创建对象。