1

I have this code:

driver.switch_to.window(window_after)

try:
    myElem = WebDriverWait(driver, delay).until(EC.presence_of_element_located((By.NAME, '_eventId_confirmed')))
    print ("Page 2 is ready!")
except TimeoutException:
    print ("Loading took too much time!")

btn = driver.find_element_by_name('_eventId_confirmed')

btn.click()

as you can see I first switch window and then check for an element, get that element (a button) and finally try to click on said button. This works maybe 2 out of 3 times but ever so often does it fail with this error message

selenium.common.exceptions.ElementNotInteractableException: Message: Element <button class="btn" name="_eventId_confirmed"> could not be scrolled into view

When visually looking at the flow when it is executing everything seems fine (my first guess was that the window switch didn't work as expected) and the browser ends up in the expected state where I am able to manually click this button. Interestingly enough, there is no timeout or similar when this error occurs, it happens instantly during execution.

Any ideas what's going on here?

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
d-b
  • 695
  • 3
  • 14
  • 43

3 Answers3

2

As your final step is to invoke click() on the desired element, so instead of using the expected_conditions as presence_of_element_located() you need to use element_to_be_clickable() as follows:

try:
    myElem = WebDriverWait(driver, delay).until(EC.element_to_be_clickable((By.NAME, '_eventId_confirmed')))
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • Just a doubt, when the element is not clickable after opening the page, would the condition `element_to_be_clickable` make sense ? Because it would never be clickable if we don't scroll it into view and the condition `element_to_be_clickable` might give a timeout exception. – Sameer Arora Mar 19 '19 at 05:55
  • Well, _element_to_be_clickable()_ does scrolls by default by a certain limit. Let me know the execution status. – undetected Selenium Mar 19 '19 at 05:56
  • Can't check the OP website but i have also got ElementNotClickable exception in the past and i solved it using javascript click. Not very sure that the selenium wait for element to be clickable would scroll the element. – Sameer Arora Mar 19 '19 at 06:15
  • @SameerArora OP is using the _Python_ clients, so jumping straight away to use javascript _click()_ would be against all best practices. You need to explore the `expected_conditions` properly. If you are _not very sure that the selenium wait for element to be clickable would scroll the element_ you need to read the documentation properly once again. – undetected Selenium Mar 19 '19 at 06:20
  • Yes, i have checked the official documentation of selenium and have checked SO as well. And there also its written that either it will return `true` or it will throw TimeoutException. References: https://www.seleniumhq.org/docs/04_webdriver_advanced.jsp#explicit-and-implicit-waits and https://stackoverflow.com/questions/38327049/check-if-element-is-clickable-in-selenium-java and that's why i asked you for your thought process behind this. – Sameer Arora Mar 19 '19 at 06:32
  • By _documentation_ I meant the _API docs_ and the _source code_ and nothing less. – undetected Selenium Mar 19 '19 at 06:38
  • 1
    Yes, studied the code now, there is not scrolling involved in the method. The method and its subsequent methods are checking for its visibility by using `isDisplayed()` – Sameer Arora Mar 19 '19 at 07:23
2

This problem usually arises when the element you are trying to click is present on the page but it is not fully visible and the point where selenium tries to click is not visible.
In this case, you can use javascript to click on the element, which actually operates directly on the html structure of the page.
You can use it like:

element = driver.find_element_by_name("_eventId_confirmed")
driver.execute_script("arguments[0].click();", element)
Sameer Arora
  • 4,439
  • 3
  • 10
  • 20
1

Here are the 2 options.

Using selenium location_once_scrolled_into_view method:

btn.location_once_scrolled_into_view

Using Javascript:

driver.execute_script("arguments[0].scrollIntoView();",btn)

Sample Code:

url = "https://stackoverflow.com/questions/55228646/python-selenium-cant-sometimes-scroll-element-into-view/55228932?    noredirect=1#comment97192621_55228932"
driver.get(url)
element = driver.find_element_by_xpath("//a[.='Contact Us']")
element.location_once_scrolled_into_view
time.sleep(1)
driver.find_element_by_xpath("//p[.='active']").location_once_scrolled_into_view
driver.execute_script("arguments[0].scrollIntoView();",element)
supputuri
  • 13,644
  • 2
  • 21
  • 39
  • Thank you. I think I understand the JS snippet but the Selenium example sounds very counterintutive? – d-b Mar 18 '19 at 19:49
  • Hmm, IntelliJ/PyCharm displays a warning `Statement seems to have no effect less... (⌘F1) Inspection info: This inspection detects statements without any effect.`? – d-b Mar 18 '19 at 19:51
  • Not sure why you are getting that message. I am able to run the sample script without issue. Added the script in the answer above for your reference. – supputuri Mar 18 '19 at 20:04
  • I would strongly recommend the second solution. See the [source code](https://seleniumhq.github.io/selenium/docs/api/py/_modules/selenium/webdriver/remote/webelement.html#WebElement.location_once_scrolled_into_viewlocation_once_scrolled_into_view) for the first. For one thing, the first sentence of the comment describing the method reads: “THIS PROPERTY MAY CHANGE WITHOUT WARNING.” They don’t provide any more details than that and I’m not sure exactly what changes they are referring to but that doesn’t sound good. Second, all that function does is execute its own (more complicated) Javascript. – C. Peck Mar 19 '19 at 02:58