Como afirmar o número de elementos usando Capivara com a mensagem de erro adequada?

86

Eu sei que na Capivara você pode fazer algo assim:

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

No entanto, supondo que a página tenha, por exemplo, apenas um elemento correspondente, o erro não é muito descritivo:

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

Em vez dessa mensagem de erro um tanto obscura, há uma maneira de escrever a declaração de forma que a saída de erro seja algo como 'Ao combinar' ol li ', esperado: 2, encontrado: 1'. Obviamente, eu poderia fazer uma lógica personalizada para esse tipo de comportamento - estou perguntando se há uma maneira de fazer isso 'fora da caixa'?

Pelo que vale a pena, estou usando o driver Selenium e RSpec.

alegre príncipe
fonte
Só para as pessoas saberem, "page.should have_css (" ol li ",: count => 2)" foi implementado em capivara. Acho que é altamente utilizável com escopos: within ("ol.users-list") do page.should have_css ('li',: count => 3) end
rafaelkin
@rafaelkin, só para esclarecer: a capivara agora relata, por exemplo, a incompatibilidade no elemento conta com mais detalhes? Faz um tempo que não acompanho a capivara, mas o problema na época, quando fiz a pergunta, era sobre o formato da mensagem de erro, não que page.should have_css("ol li", :count => 2)já não tivesse sido implementado.
Merryprankster,
pessoal, tenho a sensação de que a resposta atualmente aceita (= minha) não é mais a melhor, mas não tenho tempo (não trabalho mais com Ruby) para avaliar qual das soluções sugeridas é a melhor. Vou mudar a resposta aceita para a de Richard apenas porque inclui a saída da afirmação que aborda a questão original.
merryprankster,

Respostas:

22

Bem, como parece que não há suporte pronto para uso, escrevi este matcher personalizado:

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

Agora, você pode fazer coisas como:

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

e obter resultados como:

  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

Por enquanto, funciona. Vou tentar fazer essa parte da Capivara.

alegre príncipe
fonte
Parece que consertar isso em Capivara não é simples: github.com/jnicklas/capybara/issues/331
merryprankster
14

Acho que o seguinte é mais simples, fornece uma saída bastante clara e elimina a necessidade de um combinador personalizado.

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

Em seguida, isso imprime em erro:

      expected: 2
       got: 3

  (compared using eql?)
  (RSpec::Expectations::ExpectationNotMetError)
Richard
fonte
9
Isso não espera que a expectativa se torne realidade, por exemplo, quando ainda há solicitações Ajax pendentes.
Clemens Helm
9

Edit: Como apontado por @ThomasWalpole, usar alldesabilita a espera / nova tentativa do Capivara, então a resposta acima por @pandaPower é muito melhor.

Que tal agora?

  within('ol') do
    expect( all('.opportunity_title_wrap').count ).to eq(2)
  end
Constant Meiring
fonte
2
Isso anula completamente a espera / nova tentativa de Capivaras e nunca deve ser uma solução recomendada.
Thomas Walpole
@ThomasWalpole Não tenho certeza do que você está falando. Como a busca por um elemento dentro de outro elemento afeta de alguma forma a espera / nova tentativa na Capivara?
Constant Meiring
2
@ConstantMeiring Não é o within, ele está chamando .countos resultados alldisso desativa a espera / nova tentativa. Ao chamar countos resultados de all(para o qual uma "matriz" vazia é um retorno válido), você converte para um inteiro e o compara. Se essa comparação falhar, a expectativa falha. Se, em vez disso, você passar a opção de contagem para um dos combinadores de Capivara, a capivara irá esperar / tentar encontrar o seletor especificado até que a opção de contagem corresponda (ou Capybara.default_max_wait_time expira).
Thomas Walpole
4

A melhor prática atual (02/09/2013) recomendada pela Capivara é a seguinte ( fonte ):

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

Acconrad
fonte
-4

A resposta de @pandaPower é muito boa, mas a sintaxe foi um pouco diferente para mim:

expect(page).to have_selector('.views-row', :count => 30)
usuario
fonte
5
Usar foguetes de hash não se qualifica como "sintaxe diferente".
estreia em
2
Não sou um desenvolvedor de ruby ​​e não percebi que as duas sintaxes eram equivalentes. TBH: Não tenho certeza se justifica uma votação negativa. É uma alternativa válida. Para quem não tem experiência em Ruby, pode não parecer óbvio. Não foi para mim.
Nick