Ao contrário do que a resposta atualmente aceita sugere, não há nada específico para o PhantomJS quando se trata da diferença entre fazer o WebDriver clicar e fazê-lo em JavaScript.
A diferença
A diferença essencial entre os dois métodos é comum a todos os navegadores e pode ser explicada de maneira bem simples:
WebDriver: quando o WebDriver faz o clique, ele tenta da melhor maneira possível simular o que acontece quando um usuário real usa o navegador. Suponha que você tenha um elemento A, que é um botão que diz "Clique em mim", e um elemento B, que é um div
elemento que é transparente, mas tem suas dimensões e zIndex
configurações para cobrir completamente A. Então você diz ao WebDriver para clicar em A. O WebDriver irá simule o clique para que B receba o clique primeiro . Por quê? Como B cobre A e se um usuário tentasse clicar em A, B receberia o evento primeiro. A possibilidade de A obter o evento de clique ou não depende de como B lida com o evento. De qualquer forma, o comportamento do WebDriver nesse caso é o mesmo de quando um usuário real tenta clicar em A.
JavaScript: Agora, suponha que você use JavaScript para fazer isso A.click()
. Esse método de clicar não reproduz o que realmente acontece quando o usuário tenta clicar em A. O JavaScript envia o click
evento diretamente para A e B não recebe nenhum evento.
Por que um clique em JavaScript funciona quando um clique no WebDriver não funciona?
Como mencionei acima, o WebDriver tentará simular da melhor maneira possível o que acontece quando um usuário real está usando um navegador. O fato é que o DOM pode conter elementos com os quais um usuário não pode interagir e o WebDriver não permitirá que você clique nesses elementos. Além do caso sobreposto que mencionei, isso também implica que elementos invisíveis não podem ser clicados. Um caso comum que vejo nas perguntas de estouro de pilha é alguém que está tentando interagir com um elemento da GUI que já existe no DOM, mas só fica visível quando outro elemento foi manipulado. Às vezes isso acontece com os menus suspensos: você precisa primeiro clicar no botão para abrir o menu suspenso antes que um item de menu possa ser selecionado. Se alguém tentar clicar no item de menu antes que o menu seja visível,Se a pessoa tentar fazê-lo com JavaScript, funcionará porque o evento é entregue diretamente ao elemento, independentemente da visibilidade.
Quando você deve usar JavaScript para clicar?
Se você estiver usando o Selenium para testar um aplicativo , minha resposta a esta pergunta é "quase nunca". Em geral, seu teste Selenium deve reproduzir o que um usuário faria com o navegador. Tomando o exemplo do menu suspenso: um teste deve clicar no botão que abre o menu suspenso primeiro e depois clicar no item de menu. Se houver um problema com a GUI porque o botão está invisível ou o botão falha em mostrar os itens de menu ou algo semelhante, seu teste falhará e você detectará o erro. Se você usar o JavaScript para clicar, não poderá detectar esses erros através de testes automatizados.
Digo "quase nunca" porque pode haver exceções em que faz sentido usar JavaScript. Eles devem ser muito raros, no entanto.
Se você estiver usando o Selenium para sites de raspagem , não é tão crítico tentar reproduzir o comportamento do usuário. Portanto, usar o JavaScript para ignorar a GUI é um problema menor.
click
ousendKeys
funcionaram - mas nem sempre. Não houve problema de localização ou outra exceção, o caso de teste simplesmente não avançou mais. O registro mostrou que a ação foi executada. Às vezes, o usoAction
ajudou. Se eu clicar no elemento manualmente (depois que o caso de teste parou), tudo funcionou bem. Então, mudamos para JS bruto nessas ocasiões. Não trabalho com o AngularJS há dois anos, então as coisas podem melhorar agora.O clique executado pelo driver tenta simular o comportamento de um usuário real o mais próximo possível, enquanto o JavaScript
HTMLElement.click()
executa a ação padrão para oclick
evento, mesmo que o elemento não seja interativo.As diferenças são:
O driver garante que o elemento seja visível rolando-o para a visualização e verifica se o elemento é interativo .
O driver irá gerar um erro:
disabled
étrue
)pointer-events
énone
)Um JavaScript
HTMLElement.click()
sempre executará a ação padrão ou, na melhor das hipóteses, falhará silenciosamente se o elemento estiver desativado.Espera-se que o driver coloque o elemento em foco, se ele puder ser focalizado .
Um JavaScript
HTMLElement.click()
não.Espera-se que o driver emita todos os eventos (remoção do mouse, remoção do mouse, mouse, clique, ...) como um usuário real.
Um JavaScript
HTMLElement.click()
emite apenas oclick
evento. A página pode confiar nesses eventos extras e pode se comportar de maneira diferente se eles não forem emitidos.Estes são os eventos emitidos pelo driver para um clique no Chrome:
E este é o evento emitido com uma injeção de JavaScript:
O evento emitido por um JavaScript
.click()
não é confiável e a ação padrão não pode ser invocada:https://developer.mozilla.org/en/docs/Web/API/Event/isTrusted
https://googlechrome.github.io/samples/event-istrusted/index.html
Observe que alguns dos drivers ainda estão gerando eventos não confiáveis. Este é o caso do PhantomJS a partir da versão 2.1.
O evento emitido por um JavaScript
.click()
não possui as coordenadas do clique .As propriedades
clientX, clientY, screenX, screenY, layerX, layerY
estão definidas como0
. A página pode confiar neles e se comportar de maneira diferente.Pode ser bom usar um JavaScript
.click()
para descartar alguns dados, mas não está em um contexto de teste. Isso anula o objetivo do teste, pois não simula o comportamento de um usuário. Portanto, se o clique do driver falhar, é provável que um usuário real também não consiga executar o mesmo clique nas mesmas condições.O elemento de destino ainda não é visível / interativo devido a um atraso ou a um efeito de transição.
Alguns exemplos :
https://developer.mozilla.org/fr/docs/Web (menu suspenso de navegação) http://materializecss.com/side-nav.html (barra lateral suspensa)
Soluções alternativas:
Adicione um garçom para aguardar a visibilidade, um tamanho mínimo ou uma posição estável:
Tente clicar até que seja bem-sucedido:
Adicione um atraso correspondente à duração da animação / transição:
O elemento de destino acaba coberto por um elemento flutuante uma vez rolado na visualização:
O driver rola automaticamente o elemento na visualização para torná-lo visível. Se a página contiver um elemento flutuante / fixo (menu, anúncios, rodapé, notificação, política de cookies ..), o elemento poderá acabar coberto e não será mais visível / interativo.
Exemplo: https://twitter.com/?lang=en
Soluções alternativas:
Defina o tamanho da janela como maior para evitar a rolagem ou o elemento flutuante.
Passe o
Y
mouse sobre o elemento com um deslocamento negativo e clique nele:Role o elemento até o centro da janela antes do clique:
Oculte o elemento flutuante se não puder ser evitado:
fonte
NOTA: vamos chamar 'clique' é clique do usuário final. 'js click' é clique via JS
Existem 2 casos para que isso aconteça:
I. Se você estiver usando o PhamtomJS
Então este é o comportamento conhecido mais comum de
PhantomJS
. Alguns elementos às vezes não são clicáveis, por exemplo<div>
. Isso ocorre porque oPhantomJS
original foi criado para simular o mecanismo dos navegadores (como HTML + CSS inicial -> computação CSS -> renderização). Mas isso não significa que você interaja com o usuário final (visualizando, clicando, arrastando). Portanto,PhamtomJS
é apenas parcialmente suportado pela interação dos usuários finais.POR QUE JS CLICA TRABALHO? Quanto aos cliques, todos são cliques médios. É como uma arma com 1 cano e 2 gatilhos . Um da viewport, um da JS. Como
PhamtomJS
ótimo na simulação do mecanismo do navegador, um clique em JS deve funcionar perfeitamente.II O manipulador de eventos de "click" foi vinculado no período incorreto.
Por exemplo, temos um
<div>
-> Fazemos alguns cálculos
-> então ligamos o evento click ao
<div>
.-> Além disso, com alguma codificação incorreta do angular (por exemplo, não manipulando o ciclo do osciloscópio corretamente)
Podemos acabar com o mesmo resultado. O clique não funcionará, porque o WebdriverJS está tentando clicar no elemento quando ele não possui um manipulador de eventos de clique.
POR QUE JS CLICA TRABALHO? O clique em Js é como injetar js diretamente no navegador. Possível de 2 maneiras,
O punho é através do console do devtools (sim, o WebdriverJS se comunica com o console do devtools).
O segundo é injetar uma
<script>
tag diretamente no HTML.Para cada navegador, o comportamento será diferente. Mas, independentemente disso, esses métodos são mais complicados do que clicar no botão. O Click está usando o que já existe (clique do usuário final), o js click está passando pelo backdoor.
E para js, o clique parecerá uma tarefa assíncrona. Isso está relacionado a um tópico meio complexo de ' tarefa assíncrona do navegador e agendamento de tarefas da CPU ' (leia-a há algum tempo, não é possível encontrar o artigo novamente). Em resumo, isso resultará principalmente porque o js click precisará aguardar um ciclo de agendamento de tarefas da CPU e será executado um pouco mais devagar após a ligação do evento click. (Você pode conhecer esse caso quando encontrar o elemento algumas vezes clicável, outras vezes não.)
=> Como mencionado acima, ambos significam um propósito, mas sobre o uso de qual entrada:
=> Para desempenho, é difícil dizer porque se baseia em navegadores. Mas geralmente:
=> Desvantagens:
PS se você estiver procurando por uma solução.
browser.wait()
( verifique isso para obter mais informações )(Quero abreviar, mas acabou mal. Qualquer coisa relacionada à teoria é complicada de explicar ...)
fonte