Acabando com matchers ambíguos no Capybara 2.0
Leia em 1 minuto
O Capybara 2.0 saiu há pouco tempo e com ele vieram algumas mudanças que afetam diretamente o modo como devemos referenciar os elementos da página.
É muito comum, por exemplo, termos um link para a página de login no header e no footer. Veja o exemplo abaixo:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Awesome Site!</title>
</head>
<body>
<header>
<h1>Awesome Site!</h1>
<a href="/login">Log in</a>
</header>
<!-- content -->
<footer>
<a href="/login">Log in</a>
</footer>
</body>
</html>
Na Capybara 1, você poderia referenciar este link sem ter que definir o contexto. Um simples click_link "Log in"
já era suficiente. No Capybara 2.0 isso não é mais possível. Se você tentar fazer isso irá receber uma exceção dizendo que o seu matcher é ambíguo.
Failure/Error: click_link("Log in")
Capybara::Ambiguous:
Ambiguous match, found 2 elements matching link "Log in"
Agora é preciso que você seja específico quanto ao elemento que deseja utilizar. Neste caso, a solução mais recomendada é usar o método within
, definindo o contexto de seleção do elemento.
within("header") do
click_link "Log in"
end
Embora esta sugestão funcione, ela traz dois problemas. O primeiro é que você irá, provavelmente, duplicar este código em mais de um lugar e todos nós sabemos que duplicar código quase sempre não é uma boa ideia. O outro problema é que seu teste terá um ruído desnecessário que, dependendo do contexto, pode torná-lo muito mais difícil de ler e entender.
Minha sugestão, neste caso, é criar helpers que irão fazer isso por você. Assim você acaba com os problemas que citei acima.
Primeiro, crie um arquivo chamado “spec/support/feature_helpers.rb”. Neste arquivo nós iremos criar um módulo com helpers que iremos utilizar no grupo de features. Em vez usar o método within
, nós iremos usar o método find
, que retorna um contexto onde podemos buscar os elementos que precisamos.
module FeatureHelpers
def main_header
find("header")
end
end
RSpec.configure do |config|
config.include FeatureHelpers, :type => :feature
end
A maior vantagem de se criar um método como esse é que o seletor está totalmente encapsulado. Se você precisar mudar o contexto por algum motivo, basta alterar em um único lugar!
Agora, basta alterar o nosso teste para usar este contexto.
main_header.click_link "Log in"
Você pode usar esta técnica sempre que perceber que está fazendo muitas coisas durante os testes.