19 votes

Comment puis-je tester le titre de la page avec Capybara 2.0 ?

Essayer de tester que la page contient <title>My Title</title> avec :

# 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

Message d'erreur :

 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.

Je sais que j'oublie quelque chose de douloureusement évident, mais je n'arrive pas à savoir ce que c'est ? Est-ce que <title> les balises ne sont plus considérées comme des "sélecteurs" ?!? Ou... ?!?

Editer (info débogueur) :

Si je descends dans le débogueur comme le suggère intelligemment @shioyama, il est clair que le page.body contient <title>My Title</title> . La même page.body qui contient <h2>Welcome to My Title Project</h2> et passe !

Il semble trouver le <title> ... </title> mais pas My Title en son sein. Mais il trouve My Title plus loin dans la page dans <a href=\"/\" class=\"brand\">My Title</a> et/ou dans <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. 
...

Que puis-je essayer d'autre dans le débogueur pour comprendre pourquoi have_selector ?('title', text : ...) échoue ?

Alors, quelle est la bonne façon de tester un titre dans Capybara 2.0 ?

35voto

Paul Fioravanti Points 5886

J'ai eu les mêmes problèmes lors de la mise à jour vers Capybara 2.0, et j'ai réussi à les résoudre en créant le matcheur RSpec personnalisé suivant en utilisant Capybara.string :

spec/support/utilities.rb

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

Maintenant, dans un fichier de spécification où subject { page } je peux l'utiliser :

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

En passant, la conversation sur cette question a été extrêmement utile pour me permettre de trouver cette réponse, alors merci !

Mise à jour 1 :

Si vous ne voulez pas créer un matcheur RSpec personnalisé, grâce à cette réponse de StackOverflow par l'utilisateur dimuch Je sais maintenant que vous pouvez appeler have_selector directement sur page.source (alias page.body ) pour tester les éléments DOM non visibles :

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

ou où subject { page } :

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

Mise à jour 2 :

À partir de Capybara 2.1, il existe des fonctions intégrées de have_title / has_title? ce qui rend inutile l'utilisation du matcheur RSpec personnalisé dans cette réponse. En outre, le its(:source) { ... } décrits dans la mise à jour 1 semblent ne pas fonctionner sous Capybara 2.1 ; j'ai confirmé que l'erreur est due à l'utilisation d'une méthode de test. have_title / has_title? fonctionnent comme prévu, il est donc probablement préférable d'utiliser la syntaxe suivante si vous prévoyez une mise à jour :

Lorsque subject { page } :

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

Lorsque vous utilisez expect à l'intérieur d'un it / scenario bloc :

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

3voto

elrick Points 516

Capybara 2.1 a modifié son support pour l'interrogation de l'élément title. Ainsi, l'utilisation d'un sélecteur have pour rechercher l'élément title dans l'en-tête du document html de cette façon échouera "page.should have_selector('title', :text => 'Some text'). D'après ce que j'ai compris, la méthode préférée dans la nouvelle API de capybara 2.1 est d'utiliser "page.should have_title('Some text')" pour rechercher l'élément titre.

3voto

ascar Points 367

J'ai rencontré le même problème lors de la mise à jour de capybara de la version 1.x à > 2.0

Le problème est que Capybara ignore le texte invisible dans ses correspondances. La manière la plus propre d'aborder ce problème est d'utiliser la fonction :visible => false option sur les trouveurs.

par exemple

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

Une autre option (globale) consiste à définir :

Capybara.ignore_hidden_elements = false

2voto

Tania Dadoun Points 1

Je n'ai rencontré ce problème qu'en utilisant 'shared_examples_for', peut-être à cause d'autres changements. J'ai également remarqué que lorsque je plaçais

<title>My Title</title>

dans le corps de la page (où il n'a pas sa place et ne sera pas rendu), le test a réussi. Ce n'est pas une bonne chose !

Ça a marché :

it{should have_title("My Title")}

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

1voto

shioyama Points 15314

Je vois deux problèmes possibles ici :

  1. El <title> est présent sur la page mais le texte My Title se trouve ailleurs dans la page, et non dans la balise. Cela expliquerait pourquoi les autres tests passent : il y a une balise <title> sur la page afin que have_selector('title') passe, et il y a le My Title le texte sur la page afin have_text(base_title) passe.
  2. El <title> contient le texte My Title ainsi que quelque chose d'autre, ce qui expliquerait aussi les résultats que vous voyez : il y a une <title> sur la page afin que have_selector('title') passe, et il y a le texte My Title donc le have_text(base_title) passe également, mais la text option dans have_selector est stricte, donc elle échouera si elle trouve une chaîne qui n'est pas exactement égale à My Title .

Vous pouvez vérifier la dernière de ces deux possibilités à l'aide du sélecteur xpath : should have_xpath("//title[contains(.,'#{base_title}')]") . Si cela passe, alors vous avez probablement des espaces ou des retours à la ligne autour de votre texte de titre qui provoquent des erreurs. have_selector (je pensais qu'il les ignorait, mais je peux me tromper).

J'espère que cela vous aidera.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X