Wbrew temu, co sugeruje obecnie akceptowana odpowiedź , PhantomJS nie ma nic szczególnego, jeśli chodzi o różnicę między wykonaniem kliknięcia przez WebDriver a zrobieniem tego w JavaScript.
Różnica
Zasadnicza różnica między tymi dwiema metodami jest wspólna dla wszystkich przeglądarek i można ją wyjaśnić w prosty sposób:
WebDriver: Kiedy WebDriver wykonuje kliknięcie, stara się możliwie najlepiej zasymulować, co się dzieje, gdy prawdziwy użytkownik korzysta z przeglądarki. Załóżmy, że masz element A, który jest przyciskiem z napisem „Kliknij mnie” i element B, który jest div
elementem przezroczystym, ale ma swoje wymiary i jest zIndex
ustawiony tak, że całkowicie zakrywa A. Następnie mówisz WebDriverowi, aby kliknął A. WebDriver to zasymuluj kliknięcie, tak aby B jako pierwszy otrzymał kliknięcie . Czemu? Ponieważ B obejmuje A, a jeśli użytkownik próbowałby kliknąć A, B najpierw otrzyma zdarzenie. To, czy A ostatecznie otrzyma zdarzenie kliknięcia, zależy od tego, jak B obsłuży to zdarzenie. W każdym razie zachowanie w przypadku WebDriver w tym przypadku jest takie samo, jak w przypadku, gdy prawdziwy użytkownik próbuje kliknąć A.
JavaScript: Teraz załóżmy, że używasz JavaScript do zrobienia A.click()
. Ta metoda klikania nie odtwarza tego, co naprawdę dzieje się, gdy użytkownik próbuje kliknąć A. JavaScript wysyła click
zdarzenie bezpośrednio do A, a B nie otrzyma żadnego zdarzenia.
Dlaczego kliknięcie JavaScript działa, gdy kliknięcie WebDriver nie?
Jak wspomniałem powyżej, WebDriver postara się jak najlepiej zasymulować to, co dzieje się, gdy prawdziwy użytkownik korzysta z przeglądarki. Faktem jest, że DOM może zawierać elementy, z którymi użytkownik nie może wchodzić w interakcje, a WebDriver nie pozwoli na kliknięcie tych elementów. Oprócz wspomnianego przeze mnie przypadku nakładania się oznacza to również, że niewidoczne elementy nie mogą być klikane. Typowy przypadek, który widzę w pytaniach Stack Overflow, to ktoś, kto próbuje wejść w interakcję z elementem GUI, który już istnieje w DOM, ale staje się widoczny tylko wtedy, gdy jakiś inny element został zmanipulowany. Zdarza się to czasami w przypadku menu rozwijanych: musisz najpierw kliknąć przycisk, aby wyświetlić menu rozwijane, zanim będzie można wybrać element menu. Jeśli ktoś spróbuje kliknąć element menu, zanim menu zostanie wyświetlone,Jeśli dana osoba spróbuje to zrobić za pomocą JavaScript, zadziała, ponieważ zdarzenie jest dostarczane bezpośrednio do elementu, niezależnie od widoczności.
Kiedy należy używać JavaScript do klikania?
Jeśli używasz Selenium do testowania aplikacji , moja odpowiedź na to pytanie brzmi „prawie nigdy”. Ogólnie rzecz biorąc, test Selenium powinien odtwarzać to, co użytkownik zrobiłby z przeglądarką. Na przykładzie menu rozwijanego: test powinien najpierw kliknąć przycisk, który powoduje wyświetlenie listy rozwijanej, a następnie kliknąć pozycję menu. Jeśli wystąpi problem z graficznym interfejsem użytkownika, ponieważ przycisk jest niewidoczny lub przycisk nie wyświetla elementów menu lub coś podobnego, test zakończy się niepowodzeniem i wykryjesz błąd. Jeśli używasz JavaScript do klikania, nie będziesz w stanie wykryć tych błędów za pomocą testów automatycznych.
Mówię „prawie nigdy”, ponieważ mogą istnieć wyjątki, w których użycie JavaScript ma sens. Powinny być jednak bardzo rzadkie.
Jeśli używasz Selenium do skrobania witryn , próba odtworzenia zachowania użytkownika nie jest tak krytyczna. Więc użycie JavaScript do ominięcia GUI jest mniejszym problemem.
click
lubsendKeys
działały - ale nie zawsze. Nie było problemu z lokalizacją ani innego wyjątku, przypadek testowy po prostu nie posunął się dalej. Rejestrowanie wykazało, że akcja została wykonana. Czasami użycieAction
pomogło. Gdybym kliknął element ręcznie (po zatrzymaniu przypadku testowego), wszystko działało dobrze. W takich przypadkach przerzucaliśmy się na surowy JS. Nie pracowałem z AngularJS przez ostatnie 2 lata, więc teraz może być lepiej.Kliknięcie wykonane przez sterownik próbuje zasymulować zachowanie prawdziwego użytkownika tak blisko, jak to możliwe, podczas gdy JavaScript
HTMLElement.click()
wykonuje domyślną akcję dlaclick
zdarzenia, nawet jeśli element nie jest interaktywny.Różnice są następujące:
Sterownik zapewnia, że element jest widoczny , przewijając go do widoku i sprawdza, czy element jest interaktywny .
Sterownik zgłosi błąd:
disabled
totrue
)pointer-events
jestnone
)JavaScript
HTMLElement.click()
zawsze wykona domyślną akcję lub w najlepszym przypadku po cichu zawiedzie, jeśli element jest wyłączony.Oczekuje się, że kierowca wyostrzy element, jeśli można go ustawić .
JavaScript
HTMLElement.click()
nie będzie.Oczekuje się, że sterownik będzie emitował wszystkie zdarzenia (przesunięcie myszy, przesunięcie myszy, przesunięcie myszy, kliknięcie, ...) tak jak prawdziwy użytkownik.
JavaScript
HTMLElement.click()
emituje tylkoclick
zdarzenie. Strona może polegać na tych dodatkowych zdarzeniach i zachowywać się inaczej, jeśli nie są emitowane.Oto zdarzenia emitowane przez sterownik po kliknięciu w przeglądarce Chrome:
A oto zdarzenie emitowane przez wstrzyknięcie JavaScript:
Zdarzenie emitowane przez JavaScript
.click()
nie jest zaufane i nie można wywołać domyślnej akcji:https://developer.mozilla.org/en/docs/Web/API/Event/isTrusted
https://googlechrome.github.io/samples/event-istrusted/index.html
Zwróć uwagę, że niektóre sterowniki nadal generują niezaufane zdarzenia. Tak jest w przypadku PhantomJS od wersji 2.1.
Zdarzenie emitowane przez JavaScript
.click()
nie ma współrzędnych kliknięcia .Właściwości
clientX, clientY, screenX, screenY, layerX, layerY
są ustawione na0
. Strona może na nich polegać i zachowywać się inaczej.Może być w porządku użycie JavaScript
.click()
do zgarniania niektórych danych, ale nie jest to w kontekście testowym. Niweczy cel testu, ponieważ nie symuluje zachowania użytkownika. Tak więc, jeśli kliknięcie ze sterownika nie powiedzie się, prawdziwy użytkownik najprawdopodobniej również nie wykona tego samego kliknięcia w tych samych warunkach.Docelowy element nie jest jeszcze widoczny / interaktywny z powodu opóźnienia lub efektu przejścia.
Kilka przykładów :
https://developer.mozilla.org/fr/docs/Web (rozwijane menu nawigacji) http://materializecss.com/side-nav.html (rozwijany pasek boczny)
Obejścia:
Dodaj kelnera, aby czekał na widoczność, minimalny rozmiar lub stałą pozycję:
Ponów próbę kliknięcia, aż się powiedzie:
Dodaj opóźnienie pasujące do czasu trwania animacji / przejścia:
Docelowy element kończy się przykryty elementem pływającym po przewinięciu do widoku:
Sterownik automatycznie przewija element do widoku, aby był widoczny. Jeśli strona zawiera element pływający / przyklejony (menu, reklamy, stopka, powiadomienie, polityka dotycząca plików cookie…), element może zostać zakryty i nie będzie już widoczny / interaktywny.
Przykład: https://twitter.com/?lang=en
Obejścia:
Ustaw większy rozmiar okna, aby uniknąć przewijania lub pływającego elementu.
Najedź na element z ujemnym
Y
przesunięciem, a następnie kliknij go:Przed kliknięciem przewiń element do środka okna:
Ukryj element pływający, jeśli nie można tego uniknąć:
źródło
UWAGA: nazwijmy „kliknięciem” kliknięciem użytkownika końcowego. „js click” to kliknięcie przez JS
Istnieją 2 przypadki, w których może się to zdarzyć:
I. Jeśli używasz PhamtomJS
W takim razie jest to najczęstsze znane zachowanie
PhantomJS
. Na przykład niektóre elementy czasami nie są klikalne<div>
. Dzieje się tak, ponieważPhantomJS
został stworzony do symulacji silnika przeglądarek (jak początkowy HTML + CSS -> obliczeniowy CSS -> renderowanie). Ale nie oznacza to interakcji jako sposobu użytkownika końcowego (przeglądanie, klikanie, przeciąganie). DlategoPhamtomJS
jest tylko częściowo wspierany przez interakcję z użytkownikiem końcowym.DLACZEGO JS CLICK DZIAŁA? Jeśli chodzi o jedno kliknięcie, wszystkie oznaczają kliknięcie średnie. Jest jak pistolet z 1 lufą i 2 spustami . Jeden z widoku, jeden z JS. Ponieważ
PhamtomJS
świetnie symuluje silnik przeglądarki, kliknięcie JS powinno działać idealnie.II. Program obsługi zdarzenia „kliknięcie” musiał się wiązać w złym okresie.
Na przykład otrzymaliśmy plik
<div>
-> Wykonujemy obliczenia
-> wtedy łączymy zdarzenie kliknięcia z plikiem
<div>
.-> Plus z pewnym złym kodowaniem kąta (np. Niewłaściwa obsługa cyklu lunety)
Możemy otrzymać ten sam rezultat. Kliknięcie nie zadziała, ponieważ WebdriverJS próbuje kliknąć element, gdy nie ma on obsługi zdarzenia kliknięcia.
DLACZEGO JS CLICK DZIAŁA? Js click jest jak wstrzyknięcie js bezpośrednio do przeglądarki. Możliwe na 2 sposoby,
Pięść jest za pośrednictwem konsoli DevTools (tak, WebdriverJS ma komunikować się z konsolą DevTools').
Drugi jest wstrzyknąć
<script>
tagu bezpośrednio w HTML.Zachowanie będzie inne dla każdej przeglądarki. Ale niezależnie od tego, te metody są bardziej skomplikowane niż kliknięcie przycisku. Kliknięcie wykorzystuje to, co już tam jest (klikają użytkownicy końcowi), kliknięcie js przechodzi przez tylne drzwi.
W przypadku js kliknięcie będzie wyglądać jak zadanie asynchroniczne. Jest to związane z dość złożonym tematem „ asynchroniczne zadanie przeglądarki i planowanie zadań procesora ” (przeczytaj go chwilę wstecz, nie mogę znaleźć artykułu ponownie). Krótko mówiąc, będzie to głównie skutkować tym, że js click będzie musiało czekać na cykl planowania zadań procesora i będzie działać nieco wolniej po powiązaniu zdarzenia click. (Możesz znać ten przypadek, gdy znalazłeś element, który czasami można kliknąć, a czasem nie).
=> Jak wspomniano powyżej, oba mają na celu jeden cel, ale o używaniu którego wejścia:
=> Jeśli chodzi o wydajność, trudno powiedzieć, ponieważ opiera się na przeglądarkach. Ale ogólnie:
=> Wady:
PS jeśli szukasz rozwiązania.
browser.wait()
( sprawdź to, aby uzyskać więcej informacji )(Chcę, żeby to było krótkie, ale skończyło się źle. Wszystko, co dotyczy teorii, jest trudne do wyjaśnienia ...)
źródło