Подтвердить что ты не робот

Как проверить заголовок страницы с 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=\"&#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. 
...

Что еще я могу попробовать в отладчике выяснить, почему has_selector? ('title', text:...) не работает?

Итак, каков правильный способ проверить заголовок в Capybara 2.0?

4b9b3361

Ответ 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)