W tym artykule pokażę Wam krótkie case study, w którym uporamy się z ElementNotInteractableException. Zobaczycie nie tylko jak sobie poradzić z tym błędem, ale także dowiecie się:
- Jak sprawdzić, czy jakiś problem można rozwiązać… Czekaniem. I jak to zrobić?
- Co zrobić, gdy metoda getText() nie działa?
Ogólnie pokażę Wam test, w którym wiele mogło pójść nie tak, ale można sobie z nim poradzić.
Uwaga!
W artykule celowo nie podaję adresu strony na której prezentuję przykłady. Pokazuję tu sposób rozwiązywania problemów, który przyda Wam się nie tylko w przypadku tej konkretnej aplikacji i scenariusza testowego.
Pamiętajcie, by nie uruchamiać testów automatycznych na stronach, które nie są do tego przeznaczone i które nie wyraziły na to zgody.
Scenariusz testowy
Załóżmy, że chcemy, aby Selenium dodało plik na stronie do uploadu plików. Następnie Selenium musi sprawdzić, czy plik został pomyślnie dodany, np. poprzez pobranie wyświetlonej na stronie nazwy pliku.
Żeby dodać plik, Selenium musi kliknąć poniższy przycisk Add files:

Następnie trzeba poczekać, aż plik się wgra. Zobaczymy wtedy takie okno:

Żeby zobaczyć nazwę pliku, trzeba kliknąć w Download Link. Zobaczymy wtedy nasz obrazek oraz nazwę pliku, na którą zrobimy asercję.

Wydaje się proste? No to teraz przejdźmy do kodowania.
Automatyzacja
Napiszmy taki test w Selenium w Javie:
Trochę czekania musiałam tam powrzucać, bo nie wszystkie elementy są od razu dostępne. No to odpalmy test i zobaczmy, czy nic nie wybuchnie.

Dostaliśmy ElementNotInteractableException. Taki wyjątek poleci wtedy, kiedy Selenium uważa, że nie możemy wejść w interakcję z elementem. Jednym z powodów takiego zachowania może być fakt, że element jest już na stronie, ale nie jest jeszcze gotowy na to, żeby na przykład w niego klikać. W naszym przypadku błąd leci dokładnie w tej linijce:
Czyli tam, gdzie chcemy kliknąć w link do pobrania pliku.
Debugowanie
Pierwszą rzeczą, którą robię w takiej sytuacji, jest ustawienie w testach breakpointa na linijce, która wywołuje błąd. Następnie odpalam testy w trybie debugowania, czekam chwilę na tym breakpoincie i puszczam testy dalej. Jeżeli test przejdzie bez problemów przez ten krok, na którym jest breakpoint, to oznacza, że potrzebujemy na coś poczekać.

Dokładnie tak jest w tej sytuacji. Test przeszedł “na zielono”, czyli trzeba na coś poczekać. Nie ma sensu czekać na ten element jako taki, bo wiemy, że został znaleziony. Jest po prostu w stanie nie pozwalającym na interakcję. W ExpectedConditions nie mamy co prawda nic w stylu “poczekaj, aż element będzie gotowy na interakcję z nim”, ale mamy elementToBeClickable. Powinno wystarczyć.
I owszem, wystarczyło. Test rzeczywiście przeszedł przez ten krok, ale nadal zwraca błąd, tylko gdzieś indziej.

Wysypała nam się asercja. Twierdzi, że nazwa pliku nie jest taka, jak oczekiwana.

Szybki rzut oka na stronę temu przeczy, więc albo przeoczyłam, że ten element znajduje się w jakiejś ramce, albo źle zbudowałam lokator, albo znowu muszę na coś poczekać.
Lokator jest dobry, ramki ani innego shadow DOM tam nie ma, więc przetestujmy znowu to czekanie. Ustawiam breakpointa na linijkę w której wyszukuję element i pobieram tekst, a następnie robię to samo co w przypadku poprzedniego błędu: odpalam test w trybie debugowania, czekam chwilkę na tym kroku, po czym pozwalam testowi lecieć dalej.
I… nie pomogło. Niezależnie od tego jak długo poczekam, nadal dostaję ten sam błąd. Jak zatem pobrać tekst z elementu, jeżeli metoda getText() zawodzi? Spróbujmy użyć getDOMProperty(”innerText”):
I już wszystko śmiga. Ten sposób zadziała w Selenium 4, natomiast w Selenium 3 podobny efekt powinniśmy osiągnąć za pomocą metody getAttribute().
Oczywiście wolałabym, żeby zadziałała metoda getText() z Selenium, ale jak nie działa to zawsze macie właśnie taką alternatywę.
Zapanuj nad kodem z ExpectedConditions
ElementNotInteractableException to częsty błąd, z którym jeśli jeszcze nie mieliście do czynienia, to z pewnością w końcu będziecie mieć. 😉 Na szczęście znacie już skuteczne sposoby jak ten błąd ogarnąć.
Warto pamiętać, że czasami najlepszym rozwiązaniem jest po prostu zaczekać, aż dany element stanie się interaktywny. Możecie też skorzystać z innych metod oferowanych przez ExpectedConditions, opisanych ładnie w dokumentacji pod tym linkiem, aby sprawdzić, czy element jest gotowy do interakcji.
A jeśli znacie inne sztuczki na ElementNotInteractableException, albo chcielibyście przeczytać case study na jakiś inny, konkretny temat, to zawsze możecie dać znać tutaj.