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)>'
我试过以下方法:
- 如果 rspec 对多个 classes
有问题,则删除多余的文章
- 将have_css更改为have_selector并选择锚标签
- 从 html 正文中抽取整个 DOM 根 ...
- 通过以具有管理员权限的用户身份手动登录来检查它是否在规范之外工作 -> 它确实如此。
- 尝试删除未发表文章与已发表文章的区别,但仍然失败。
- 尝试删除 erb 条件以检查文章是否在视图中发布但仍然失败。
- 尝试确保它不是通过 ajax 加载(在 will_paginate 中有备份)但失败了。
我做错了什么?
编辑
如果我避免使用 FactoryGirl 导入,它现在可以工作了:
@article = Article.create(title: 'Title', body: 'body', published: true)
而不是
let(:published) { FactoryGirl.create(:published) }
不知道为什么。
RSpec 延迟分配 let
变量,因此在您显示页面时,已发布和未发布的文章都不存在。您需要使用 let!
或 before
或以其他方式确保在显示页面之前创建对象。
快速总结:为什么水豚找不到 .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)>'
我试过以下方法:
- 如果 rspec 对多个 classes 有问题,则删除多余的文章
- 将have_css更改为have_selector并选择锚标签
- 从 html 正文中抽取整个 DOM 根 ...
- 通过以具有管理员权限的用户身份手动登录来检查它是否在规范之外工作 -> 它确实如此。
- 尝试删除未发表文章与已发表文章的区别,但仍然失败。
- 尝试删除 erb 条件以检查文章是否在视图中发布但仍然失败。
- 尝试确保它不是通过 ajax 加载(在 will_paginate 中有备份)但失败了。
我做错了什么?
编辑
如果我避免使用 FactoryGirl 导入,它现在可以工作了:
@article = Article.create(title: 'Title', body: 'body', published: true)
而不是
let(:published) { FactoryGirl.create(:published) }
不知道为什么。
RSpec 延迟分配 let
变量,因此在您显示页面时,已发布和未发布的文章都不存在。您需要使用 let!
或 before
或以其他方式确保在显示页面之前创建对象。