19

尝试测试该页面包含<title>My Title</title>

# spec/features/reports_spec.rb
require 'spec_helper'

feature "Archive Management" do
  subject { page }

  describe "Index Page" do
    before(:all) { 10.times { FactoryGirl.create(:randomreport) } }
    after(:all) { Report.delete_all }

    describe "when no search terms present" do
      before { visit reports_path }

      it { should have_selector('title', text: 'My Title') } # <= Fails w/Capybara 2.0
      it { should have_selector('title') }                   # <= passes
      it { should have_text('My Title') }                    # <= passes
      it { should have_selector('h2', text: "Welcome") }     # <= passes
    end
  end
end

错误信息:

 Failure/Error: it { should have_selector('title', text: base_title) }
 Capybara::ExpectationNotMet:
   expected to find css "title" with text "My Title" but there were no matches. Also found "", which matched the selector but not all filters.

我知道我忽略了痛苦的显而易见但无法弄清楚它是什么?<title>标签不再被视为“选择器”吗?!?或者...?!?

编辑(调试器信息)

如果我按照@shioyama 的巧妙建议下拉到调试器中,很明显 page.body 包含<title>My Title</title>. 包含<h2>Welcome to My Title Project</h2>和传递的同一个 page.body!

它似乎找到了<title>...</title>标签,但不在My Title其中。但它确实My Title稍后会在页面内<a href=\"/\" class=\"brand\">My Title</a>和/或内找到<h2>Welcome to The My Title Project</h2>

(rdb:1) p page
#<Capybara::Session>
(rdb:1) p page.body
"<!DOCTYPE html>\n<html>\n<head>\n<title>My Title</title>\n
<meta content='research, report, technology' name='keywords'>\n<meta 
content='Some Project' name='description'>\n<link href=\"/assets/application.css\"
...
</head>\n<body>\n<header class='navbar navbar-fixed-top 
navbar-inverse'>\n<div class='navbar-inner'>\n<div class='container'>\n
<a href=\"/\" class=\"brand\">My Title</a>\n<div class='pull-right'>\n
<ul class='nav'>\n<li><a href=\"/about\">About</a></li>\n<li><a href=\"/help\">Help</a>
</li>\n</ul>\n<form accept-charset=\"UTF-8\" action=\"/reports\" 
class=\"navbar-search\" method=\"get\"><div style=\"margin:0;padding:0;display:inline\">
<input name=\"utf8\" type=\"hidden\" value=\"&#x2713;\" /></div>\n
<input class=\"search-query\" id=\"query\" name=\"query\" 
placeholder=\"Search\" type=\"text\" />\n</form>\n\n</div>\n</div>\n</div>\n</header>\n\n
<div class='container'>\n<div class='hero-unit center'>\n<h1>My Title</h1>\n
<h2>Welcome to The My Title Project</h2>\n<p>Lorem ipsum dolor sit amet, consectetur 
adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. 
...

我还能在调试器中尝试什么来找出为什么 have_selector?('title', text: ...) 失败了?

那么,在 Capybara 2.0 中测试标题的正确方法是什么?

4

6 回答 6

35

当我升级到 Capybara 2.0 时,我遇到了同样的问题,并通过使用以下自定义 RSpec 匹配器设法解决了这些问题Capybara.string

规范/支持/实用程序.rb

RSpec::Matchers::define :have_title do |text|
  match do |page|
    Capybara.string(page.body).has_selector?('title', text: text)
  end
end

现在,在一个规范文件中subject { page },我可以使用:

it { should have_title("My Title") }
it { should_not have_title("My Title") }

顺便说一句,关于这个问题的对话对我得到这个答案非常有帮助,所以谢谢!

更新1:

如果您不想创建自定义 RSpec 匹配器,感谢用户dimuch提供的StackOverflow 答案,我现在知道您可以直接调用(aliased ) 来测试不可见的 DOM 元素:have_selectorpage.sourcepage.body

it "should show the correct title" do
  page.source.should have_selector('title', text: 'My Title')
end

或在哪里subject { page }

its(:source) { should have_selector('title', text: 'My Title') }

更新 2:

从 Capybara 2.1 开始,有内置的have_title/has_title?匹配器,在这个答案中不需要自定义 RSpec 匹配器。此外,its(:source) { ... }更新 1 中描述的测试似乎在 Capybara 2.1 下被破坏了;我已经确认have_title/has_title?按预期工作,因此如果您打算升级,最好使用以下语法:

什么时候subject { page }

it { should have_title("My Title") }
it { should_not have_title("My Title") }

在/块中使用expect语法时:itscenario

expect(page).to have_title("My Title")
expect(page).to_not have_title("My Title")
于 2012-12-07T01:49:16.577 回答
3

Capybara 2.1 更改了对查询标题元素的支持。因此,使用 have selector in 以这种方式查询 html 文档头部的标题元素将失败“page.should have_selector('title', :text => 'Some text')。据我了解首选方法在 capybara 2.1 中,新 API 是使用“page.should have_title('Some text')”来查询 title 元素应该可以工作。

于 2013-05-01T00:40:56.827 回答
3

我在将 capybara 从 1.x 版本升级到 > 2.0 时遇到了同样的问题

问题是 Capybara 忽略了匹配器中的不可见文本。解决此问题的最简单方法是使用:visible => false查找器上的选项。

例如

it { should have_selector('title', text: 'My Title', visible: false) }

另一个(全局)选项是设置:

Capybara.ignore_hidden_elements = false

于 2014-09-14T16:07:11.317 回答
2

我只有在使用“shared_examples_for”时才遇到这个问题,可能是因为其他变化。我还注意到,当我放置

<title>My Title</title>
在页面正文中(它不属于并且不会呈现的地方),测试通过了。不是什么好事!

这有效:

it{should have_title("My Title")}

(水豚 2.1.0,launchy 2.3.0,nokogiri 1.5.9,rspec 2.13)

于 2013-05-13T16:04:49.357 回答
1

我在这里看到两个可能的问题:

  1. <title>标签存在于页面上,但文本位于页面的My Title其他位置,而不是标签内。这可以解释为什么其他测试通过了:<title>页面上有一个标签所以have_selector('title')通过了,页面My Title上有文本所以have_text(base_title)通过了。
  2. <title>标签包含文本My Title以及其他内容,这也可以解释您看到的结果:<title>页面上有一个标签所以have_selector('title')通过,并且有文本My Title所以have_text(base_title)也通过,但是text选项have_selector是严格的,因此它将如果它找到一个不完全相等的字符串,则失败My Title

您可以使用 xpath 选择器检查这两种可能性中的后者:should have_xpath("//title[contains(.,'#{base_title}')]"). 如果通过了,那么您的标题文本周围可能有一些空格或换行符,它们have_selector会出错(我认为它忽略了这些,但我可能是错的)。

希望有帮助。

于 2012-11-26T23:08:15.277 回答
0

我知道这已经有一个公认的答案,但是对于它的价值,您可以用更少的代码行执行以下操作:

title = first("head title").native.text
expect(title).to == "What you expect it to match"

这允许访问本机驱动程序元素;此外,由于 Capybara 2.0 忽略了不可见的文本(除了浏览器之外,标题是不可见的),您需要这个(或类似的解决方法)来满足这种情况。(见https://github.com/jnicklas/capybara/issues/863

于 2013-04-15T14:50:30.267 回答