web-dev-qa-db-fra.com

Comment affirmer le nombre d'éléments en utilisant Capybara avec un message d'erreur correct?

Je sais qu'à Capybara, vous pouvez faire quelque chose comme ça:

page.should have_css("ol li", :count => 2)

Cependant, en supposant que la page n'a par exemple qu'un seul élément correspondant, l'erreur n'est pas très descriptive:

  1) initial page load shows greetings
 Failure/Error: page.should have_css("ol li", :count => 2)
 expected css "ol li" to return something

Au lieu de ce message d'erreur plutôt obscur, existe-t-il un moyen d'écrire l'assertion de telle manière que la sortie d'erreur serait quelque chose comme 'Lors de la correspondance avec' ol li ', attendu: 2, trouvé: 1'. De toute évidence, je pourrais moi-même créer une logique personnalisée pour un tel comportement - je demande s'il existe un moyen de le faire "prêt à l'emploi"?

Pour ce que ça vaut, j'utilise le pilote Selenium et RSpec.

80
merryprankster

J'aime beaucoup mieux ça.

expect(page).to have_selector('input', count: 12)

https://github.com/jnicklas/capybara/blob/415e2db70d3b19b46a4d3d0fe62f50400f9d2b61/spec/rspec/matchers_spec.rb

169
pandaPowder

Eh bien, comme il semble qu'il n'y ait pas de support prêt à l'emploi, j'ai écrit ce matcher personnalisé:

RSpec::Matchers.define :match_exactly do |expected_match_count, selector|
    match do |context|
        matching = context.all(selector)
        @matched = matching.size
        @matched == expected_match_count
    end

    failure_message_for_should do
        "expected '#{selector}' to match exactly #{expected_match_count} elements, but matched #{@matched}"
    end

    failure_message_for_should_not do
        "expected '#{selector}' to NOT match exactly #{expected_match_count} elements, but it did"
    end
end

Maintenant, vous pouvez faire des choses comme:

describe "initial page load", :type => :request do
    it "has 12 inputs" do
        visit "/"
        page.should match_exactly(12, "input")
    end
end

et obtenez une sortie comme:

  1) initial page load has 12 inputs
     Failure/Error: page.should match_exactly(12, "input")
       expected 'input' to match exactly 12 elements, but matched 13

Il fait l'affaire pour l'instant, je vais chercher à faire cette partie de Capybara.

22
merryprankster

Je pense que ce qui suit est plus simple, donne une sortie assez claire et élimine le besoin d'un matcher personnalisé.

page.all("ol li").count.should eql(2)

Cela s'imprime ensuite en cas d'erreur:

      expected: 2
       got: 3

  (compared using eql?)
  (RSpec::Expectations::ExpectationNotMetError)
14
Richard

Edit: Comme l'a souligné @ThomasWalpole, l'utilisation de all désactive l'attente/nouvelle tentative de Capybara, donc la réponse ci-dessus par @pandaPower est bien meilleure.

Que dis-tu de ça?

  within('ol') do
    expect( all('.opportunity_title_wrap').count ).to eq(2)
  end
9
Constant Meiring

La meilleure pratique actuelle (9/2/2013) recommandée par Capybara est la suivante ( source ):

page.assert_selector('p#foo', :count => 4)

3
acconrad