Jak zmusić Selenium WebDriver do kliknięcia elementu, który nie jest obecnie widoczny?

99

Używam API Selenium 2 Java z FirefoxDriver. Kiedy wypełniam formularz, na stronie są dodawane pola wyboru w zależności od danych wejściowych formularza.

Chciałbym zasymulować kliknięcie tych pól wyboru przy użyciu Selenium. Element jest widoczny i można go używać w zwykłej przeglądarce, ale selen zapewnia, że ​​elementy nie są widoczne.

"Element is not currently visible and so may not be interacted with"

Czy mogę zmusić selen do ignorowania niewidocznego stanu pierwiastków? Jak zmusić Selenium do interakcji z niewidocznym elementem?

djondal
źródło
Jakiej przeglądarki używasz? Nie możesz wchodzić w interakcje z elementami, które są wyłączone lub niewidoczne, ponieważ użytkownik końcowy nie mógłby wchodzić z nimi w interakcje. Jeśli chcesz, żebym spróbował zdiagnozować problem, musisz podać kod testowy i źródło strony.
Ardesco,

Odpowiedzi:

102

Selenium określa, czy element jest widoczny lub nie, według następujących kryteriów (użyj inspektora DOM, aby określić, jaki CSS ma zastosowanie do Twojego elementu, upewnij się, że spojrzysz na styl obliczeniowy):

  • widoczność! = ukryta
  • display! = none (jest również sprawdzany na każdym elemencie nadrzędnym)
  • krycie! = 0 (nie jest to zaznaczone dla kliknięcia elementu)
  • wysokość i szerokość są> 0
  • dla danych wejściowych typ atrybutu! = hidden

Twój element spełnia jedno z tych kryteriów. Jeśli nie masz możliwości zmiany stylu elementu, oto jak możesz to na siłę zrobić za pomocą javascript (zakładając WebDriver, skoro powiedziałeś Selenium2 API):

((JavascriptExecutor)driver).executeScript("arguments[0].checked = true;", inputElement);

Ale to nie uruchomi zdarzenia javascript, jeśli polegasz na zdarzeniu change dla tego wejścia, musisz je również uruchomić (na wiele sposobów, najłatwiej jest użyć dowolnej biblioteki javascript załadowanej na tej stronie).

Źródło kontroli widoczności -

https://github.com/SeleniumHQ/selenium/blob/master/javascript/atoms/dom.js#L577

Specyfikacja WebDriver, która to definiuje -

https://dvcs.w3.org/hg/webdriver/raw-file/tip/webdriver-spec.html#widl-WebElement-isDisplayed-boolean

lukeis
źródło
1
Czy masz źródło (lub link kanoniczny) dla listy warunków?
mjs
2
O ile potrafisz czytać Javascript, o widoczności decyduje metoda bot.dom.isShown: code.google.com/p/selenium/source/browse/trunk/javascript/atoms/ ...
lukeis
co to jest inputElement tutaj. Uruchamiam poniższy kod WebElement inputElement = driver.findElement (By.xpath (PASSWORD_PATH)); (Sterownik (JavascriptExecutor)) .executeScript ("arguments [0] .checked = true;", inputElement); Ale nie ma pomocy inputElement.sendKeys (hasło);
Deepak Goel
2
@NIleshSharma python ma metodę execute_script bezpośrednio w samym obiekcie sterownika: driver.execute_script (...)
lukeis
1
Link do źródła opublikowany przez @TunaBum został zmieniony na code.google.com/p/selenium/source/browse/javascript/atoms/ ...
Shepmaster
27

Czasami oznacza to, że na stronie znajduje się wiele elementów, które mają tę samą właściwość, według której szukasz, i „rozmawiasz z niewłaściwym”.

Jeśli Twojego elementu nie można jednoznacznie zidentyfikować za pomocą: id lub: name (lub: class), może to być trudne.

Czasami wyszukiwanie elementu przez: xpath pomoże, aw niektórych przypadkach nawet to nie jest praktyczne.

W takich przypadkach może być konieczne pobranie wszystkich elementów, które pasują do twoich kryteriów i odwołanie się do właściwego przez indeks. Jest brudny, ale działa.

Używam Selenium / Watir z aplikacji Ruby on Rails, więc w moim przypadku przykładem będzie:

browser = Watir::Browser.new(:firefox, :profile => "default")       
browser.goto("http://www.google.com/analytics")
# login
browser.divs(:text, "+ New Property").last.click

Mam nadzieję że to pomoże.

ranktrackerpro
źródło
dodanie id do elementu dom naprawiło to dla mnie
naoru
Miałem ten sam problem i wyregulowałem XPath, aby mógł wyróżnić unikalny element.
JohnL
Miałem ten sam problem. Zmieniono wywołanie findElements () w celu liczenia dopasowań i był jeszcze jeden pasujący element. Dzięki!
Baran
Tyle dla mnie. ZAWSZE upewnij się, że kryteria wyboru są wystarczająco specyficzne dla elementu, z którym myślisz, że wchodzisz w interakcję. Wiele razy miałem do czynienia z dwoma elementami, z których jeden jest ukryty i daje mi ten błąd.
Chris
14

Miałem podobny problem, ale był związany z niewidocznym elementem w widoku. Zrobiłem zrzut ekranu i zdałem sobie sprawę, że okno przeglądarki jest zbyt wąskie i element nie jest widoczny. Zrobiłem jedno z tych i zadziałało:

driver.maximize_window()

Zobacz: WebDriver.maximize_window ()

mynameistechno
źródło
7

Lub możesz użyć klasy działania Selenium do symulacji interakcji użytkownika - na przykład

    WebDriver = new FirefoxDriver();

    WebElement menu = driver.findElement(By.xpath("")); // the triger event element

    Actions build = new Actions(driver); // heare you state ActionBuider
    build.moveToElement(menu).build().perform(); // Here you perform hover mouse over the needed elemnt to triger the visibility of the hidden
    WebElement m2m= driver.findElement(By.xpath(""));//the previous non visible element
    m2m.click();
fil mihaylov
źródło
7

Jest też inny przypadek, w którym widoczny element zostanie rozpoznany jako niewidoczny:

  • Kiedy element jest przekształcany w CSS
  • Kiedy element nadrzędny elementu jest przekształcany w CSS

Aby sprawdzić, czy element, z którym nie chcesz wchodzić w interakcje, jest przekształcony w CSS, na CHROME zrób to:

  1. otwarty inspektor
  2. Znajdź interesujący element (lub bardziej prawdopodobnie jego element nadrzędny, przypuszczalnie element div)
  3. Wybierz kartę „Obliczone”
  4. jeśli jest parametr: webkit-transform: matrix (...) oznacza to, że element jest transformowany CSS i może nie być rozpoznawany przez selenium 2 jako widoczny element
justnpT
źródło
5

Niewidzialność może również wynikać z czasu, w którym element ma się powoli pojawiać. W takim przypadku pomocne może być zmuszenie przeglądarki do trochę czasu.

Zobacz na przykład pytanie o pozwolenie WebDriverowi na czekanie, aż pojawi się element .

avandeursen
źródło
2

Miałem ten sam problem z selenem 2 w Internet Explorerze 9, ale moja poprawka jest naprawdę dziwna. Nie udało mi się kliknąć wejść w moim formularzu -> powtórzenia selenu, ich nie widać.

Wystąpiło, gdy moja forma miała zakrzywione cienie -> http://www.paulund.co.uk/creating-different-css3-box-shadows-effects : w konkretnym „Effect no. 2”

Nie mam pojęcia, dlaczego i jak to rozwiązanie pseudoelementowe zatrzymało testy selenu, ale dla mnie działa.

Agoreddah
źródło
2

Nie możesz wymusić dostępu / zmiany elementu, do którego użytkownik normalnie nie ma dostępu, ponieważ Selenium jest zaprojektowane tak, aby naśladować interakcję użytkownika.

Jeśli wystąpi ten błąd, sprawdź, czy:

  • element jest widoczny w Twoim okienku ekranu, spróbuj zmaksymalizować bieżące okno, z którego korzysta webdriver (np. maximize()w node.js , maximize_window()w Pythonie),
  • Twój element nie pojawia się dwukrotnie (pod tym samym selektorem) i wybierasz niewłaściwy,
  • jeśli Twój element jest ukryty, zastanów się nad jego widocznością,
  • jeśli chcesz uzyskać dostęp / zmienić wartość ukrytego elementu pomimo ograniczenia, użyj do tego Javascript (np. executeScript()w node.js , execute_script()w Pythonie).
kenorb
źródło
1
Nie miałem pojęcia, że ​​Selenium jest tak surowe. Wydaje się, że tak naprawdę nie jest to narzędzie do automatyzacji w ogólnym sensie, a raczej narzędzie do zautomatyzowanej interakcji z użytkownikiem. Wydaje mi się, że to trochę sensowne. Dzięki za wytłumaczenie!
Daniel Lidström
1

Po prostu rozwiązuję ten błąd podczas używania kapibary w projekcie ror dodając:

Capybara.ignore_elements = true

do features/support/env.rb.

Zernel
źródło
1

Po prostu rozwiązuję ten błąd, czekając na właściwość wyświetlania elementu

waitFor() { element.displayed }
Suat Keskin
źródło
Ze wszystkich odpowiedzi na tej stronie, właśnie to rozwiązało mój problem z oknem dialogowym Bootstrap Modal. Dzięki @Suat Keskin!
alastairs
1

Dostaję się do wyjątku ElementNotVisibleException używając selenu do testów funkcjonalnych na stronie django z glifami bootstrap jako linkami w szablonach, jak:

<a href="{% url 'item-add' %}"><span class="glyphicon glyphicon-plus text-danger"></span></a>

Podczas moich testów funkcjonalnych styl bootstrap nie jest ładowany, wtedy próba kliknięcia takich linków spowoduje zgłoszenie wyjątku ElementNotVisibleException. Udaje mi się je kliknąć, dodając spację w tagu, na przykład:

<a href="{% url 'item-add' %}"><span class="glyphicon glyphicon-plus text-danger">&nbsp;</span></a>
jean pierre huart
źródło
1

Na tej stronie jest wiele dobrych odpowiedzi.

  1. Zwykle zaczynam od maximize.window (), właściwie robię to w fabryce sterownika lub gdziekolwiek inicjalizujesz sterownik. Jest to wykonywane domyślnie - zawsze.
  2. Zwykle jest to oczekiwanie na element z powodu opóźnienia javascript.

Oba są omówione w różnych szczegółach powyżej. Odpowiedź, której nie widziałem, to ScrollToElement. Wygląda na to, że przetwarzasz listę elementów, podczas gdy tworzysz więcej elementów, pól wyboru. Może to spowodować przeniesienie elementów na liście poza widoczną stronę. Czasami można zobaczyć element gołym okiem, ale po prostu nie można go kliknąć. Podczas przetwarzania list czasami trzeba przerwać przewijanie.

  • Ustaw punkt przerwania i sprawdź, czy używany element znajduje się na krawędzi okna, u góry / u dołu po prawej / lewej stronie. Czasami, gdy tak jest, nie możesz dostać się do niego przez selen, ale możesz ręcznie kliknąć myszą.

Ponieważ natknąłem się na to, utworzyłem PageScroll.java i umieściłem tam moje skrypty przewijania. Oto kilka metod z tej klasy:

public static void scrollToTop(WebDriver driver) {
      ((JavascriptExecutor) driver)
        .executeScript("window.scrollTo(0,0)");
    }

    public static void scrollToBottom(WebDriver driver) {
      ((JavascriptExecutor) driver)
        .executeScript("window.scrollTo(0, document.body.scrollHeight)");
    }

    public static void scrollToElementTop(WebDriver driver, WebElement element) {
      ((JavascriptExecutor) driver).executeScript(
        "arguments[0].scrollIntoView(true);", element);
    }

    public static void scrollToElementBottom(WebDriver driver, WebElement element) {
      ((JavascriptExecutor) driver).executeScript(
        "arguments[0].scrollIntoView(false);", element);
    }

zobacz Przewijanie elementu do widoku za pomocą Selenium, aby uzyskać więcej przykładów

mancocapac
źródło
0

Przyjęta odpowiedź zadziałała dla mnie. Poniżej znajduje się kod, aby znaleźć element nadrzędny, który sprawia, że ​​Selenium uważa, że ​​jest niewidoczny.

function getStyles(element){
	
	computedStyle = window.getComputedStyle(element);

	if(computedStyle.opacity === 0
	|| computedStyle.display === "none"
	|| computedStyle.visibility === "hidden"
	|| (computedStyle.height < 0 && computedStyle.height < 0)
	|| element.type === "hidden") {
		console.log("Found an element that Selenium will consider to not be visible")
		console.log(element);
		console.log("opacity: " + computedStyle.opacity);
		console.log("display: " + computedStyle.display);
		console.log("visibility: " + computedStyle.visibility);
		console.log("height: " + computedStyle.height);
		console.log("width: " + computedStyle.width);
	}

	if(element.parentElement){
		getStyles(element.parentElement);
	}
}

getStyles(document.getElementById('REPLACE WITH THE ID OF THE ELEMENT YOU THINK IS VISIBLE BUT SELENIUM CAN NOT FIND'));

starmer
źródło
0

Aby dodać tutaj moje ziarno piasku: jeśli element znajduje się za stałym elementem div, zostanie uznany za niewidoczny i nie będzie można go kliknąć; zdarzyło mi się to niedawno i rozwiązałem to, wykonując skrypt zgodnie z powyższymi zaleceniami, który robi:

document.evaluate("<xpath locator for element to be clicked>", document, null, XPathResult.ANY_TYPE, null).iterateNext().click()", locator);
Fernando Gabrieli
źródło
Co to jest lokalizator?
Anjana