Ruby-on-rails 如何使用 Capybara 2.0 测试页面标题?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13573525/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 21:05:18  来源:igfitidea点击:

How can I test the page title with Capybara 2.0?

ruby-on-railsrspeccapybara

提问by Meltemi

Trying to test that page contains <title>My Title</title>with:

尝试测试该页面包含<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

Error message:

错误信息:

 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.

I know I'm overlooking the painfully obvious but can't figure out what it is? Are <title>tags no longer considered 'selectors'?!? Or...?!?

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

Edit (debugger info):

编辑(调试器信息)

If I drop down into the debugger as cleverly suggested by @shioyama it is clear that the page.body contains <title>My Title</title>. The same page.body that contains <h2>Welcome to My Title Project</h2>and passes!

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

It appears to find the <title>...</title>tag but not My Titlewithin it. But it does find My Titlelater in the page within <a href=\"/\" class=\"brand\">My Title</a>and/or in <h2>Welcome to The My Title Project</h2>:

它似乎找到了<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. 
...

What else could I try in the debugger to figure out why have_selector?('title', text: ...) is failing?

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

So, what is the proper way to test for a title in Capybara 2.0?

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

回答by Paul Fioravanti

I had the same issues when I upgraded to Capybara 2.0, and managed to solve them by creating the following custom RSpec matcher using Capybara.string:

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

spec/support/utilities.rb

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

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

Now, in a spec file where subject { page }, I can use:

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

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

As an aside, the conversation on this question was extremely helpful in getting me to this answer, so thank you!

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

Update 1:

更新 1:

If you don't want to create a custom RSpec matcher, thanks to this StackOverflow answerby user dimuchI now know that you can call have_selectordirectly on page.source(aliased page.body) to test for non-visible DOM elements:

如果您不想创建自定义 RSpec 匹配器,多亏了用户dimuchStackOverflow 上的回答,我现在知道您可以直接调用(别名)来测试不可见的 DOM 元素:have_selectorpage.sourcepage.body

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

or where subject { page }:

或哪里subject { page }

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

Update 2:

更新 2:

From Capybara 2.1, there are built-in have_title/has_title?matchers, negating the need for the custom RSpec matcher in this answer. Furthermore, the its(:source) { ... }tests described in Update 1 seem to break under Capybara 2.1; I've confirmed the have_title/has_title?work as expected, so it's probably best to go with the following syntax if you plan on upgrading:

从 Capybara 2.1 开始,有内置have_title/has_title?匹配器,无需在此答案中使用自定义 RSpec 匹配器。此外,its(:source) { ... }更新 1 中描述的测试在 Capybara 2.1 下似乎会中断;我已经确认have_title/has_title?正常工作,因此如果您计划升级,最好使用以下语法:

When subject { page }:

什么时候subject { page }

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

When using expectsyntax within an it/scenarioblock:

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

expect(page).to have_title("My Title")
expect(page).to_not have_title("My Title")

回答by elrick

Capybara 2.1 changed its support for querying the title element. So using have selector in to query for the title element in the head of the html doc in this fashion will fail "page.should have_selector('title', :text => 'Some text'). From what i understand the preferred method in capybara 2.1 new API is to use "page.should have_title('Some text')" to query the title element should work.

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

回答by dfherr

i ran into the same issue when upgrading capybara from version 1.x to > 2.0

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

The problem is that Capybara ignores invisible text in its matchers. The cleanest way to address this issue is to use the :visible => falseoption on finders.

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

e.g.

例如

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

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

Another (global) option is to set:

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

Capybara.ignore_hidden_elements = false

Capybara.ignore_hidden_elements = false

回答by Noddinoff

I had this problem only when using 'shared_examples_for', maybe because of other changes. I also noticed that when I placed

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

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

This worked:

这有效:

it{should have_title("My Title")}

(capybara 2.1.0, launchy 2.3.0, nokogiri 1.5.9, rspec 2.13)

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

回答by Chris Salzberg

I see two possible issues here:

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

  1. The <title>tag is present on the page but the text My Titleis somewhere else on the page, not within the tag. That would explain why the other tests pass: there is a <title>tag on the page so have_selector('title')passes, and there is the My Titletext on the page so have_text(base_title)passes.
  2. The <title>tag contains the text My Titleas well as something else, which would also explain the results you see: there is a <title>tag on the page so have_selector('title')passes, and there is the text My Titleso the have_text(base_title)also passes, however the textoption in have_selectoris strict, therefore it will fail if it finds a string which does not exactly equal My Title.
  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

You can check the latter of these two possibilities using the xpath selector: should have_xpath("//title[contains(.,'#{base_title}')]"). If that passes, then you probably have some whitespace or newlines around your title text which are tripping have_selectorup (I thought it ignored those, but I could be wrong).

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

Hope that helps.

希望有帮助。

回答by Steve Tipton

I know this has an accepted answer already, but for what it's worth, you can do the following, in less lines of code:

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

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

This allows access to the native driver element; further, since Capybara 2.0 ignores invisible text (title is invisible except to the browser), you would need this (or a similar workaround) to satisfy this case. (See https://github.com/jnicklas/capybara/issues/863)

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