Как проверить заголовок страницы с Capybara 2.0?
Попытка проверить, что страница содержит <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>
. Тот же page.body, который содержит <h2>Welcome to 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=\"✓\" /></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.
...
Что еще я могу попробовать в отладчике выяснить, почему has_selector? ('title', text:...) не работает?
Итак, каков правильный способ проверить заголовок в Capybara 2.0?
Ответы
Ответ 1
У меня были те же проблемы, когда я обновился до Capybara 2.0 и смог их решить, создав следующий пользовательский сопоставитель RSpec, используя Capybara.string
:
спецификации/поддержка/utilities.rb
RSpec::Matchers::define :have_title do |text|
match do |page|
Capybara.string(page.body).has_selector?('title', text: text)
end
end
Теперь, в spec файле, где subject { page }
, я могу использовать:
it { should have_title("My Title") }
it { should_not have_title("My Title") }
В стороне, разговор по этому вопросу был чрезвычайно полезен, когда я получил ответ, так что спасибо!
Обновление 1:
Если вы не хотите создавать пользовательский сопоставитель RSpec, fooobar.com/questions/274246/... пользователем dimuch Теперь я знаю, что вы можете называть have_selector
непосредственно на page.source
(aliased page.body
), чтобы проверить, видимые элементы DOM:
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
в блоке it
/scenario
:
expect(page).to have_title("My Title")
expect(page).to_not have_title("My Title")
Ответ 2
Capybara 2.1 изменил свою поддержку запроса элемента title. Таким образом, использование селектора для запроса элемента заголовка в заголовке html doc таким образом завершится неудачей "page.should have_selector (" title ",: text = > " Some text "). Из того, что я понимаю, предпочтительный метод в capybara 2.1 новый API должен использовать" page.should have_title ( "Some text" )", чтобы запросить элемент заголовка, должен работать.
Ответ 3
Я столкнулся с той же проблемой при обновлении capybara с версии 1.x до > 2.0
Проблема в том, что Capybara игнорирует невидимый текст в своих помощниках. Самый чистый способ решить эту проблему - использовать опцию :visible => false
на искателях.
например.
it { should have_selector('title', text: 'My Title', visible: false) }
Другой (глобальный) вариант заключается в установке:
Capybara.ignore_hidden_elements = false
Ответ 4
У меня была эта проблема только при использовании 'shared_examples_for', возможно, из-за других изменений. Я также заметил, что когда я разместил
<title>My Title</title>
в теле страницы (где он не принадлежит и не будет рендерить), тест прошел. Нехорошо!
Это сработало:
it{should have_title("My Title")}
(capybara 2.1.0,
launchy 2.3.0,
nokogiri 1.5.9,
rspec 2.13)
Ответ 5
Здесь я вижу две возможные проблемы:
- Тег
<title>
присутствует на странице, но текст My Title
находится где-то еще на странице, а не в теге. Это объясняет, почему проходят другие тесты: на странице есть тег <title>
, поэтому have_selector('title')
проходит, и на странице есть текст My Title
, поэтому have_text(base_title)
проходит.
- Тег
<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
вверх (я думал, что он проигнорировал их, но я мог ошибаться).
Надеюсь, что это поможет.
Ответ 6
Я знаю, что это уже принятый ответ, но для чего он стоит, вы можете сделать следующее, в меньших строках кода:
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)