I have this error "element not interactable" When I try to click a drop down list with selenium. However in debug mode, when I inspect ( press F12 ) before the break points and I continue to run then the test is passed. So my question is Why the elements can be clicked and what should I do to prevent the situation again. Many thanks!
You have to add wait / delay before accessing the elements to let the elements be fully loaded on the page before accessing them.
The simplest way is to add hardcoded sleep, like
time.sleep(5)
The better way is to use explicit way implemented by expected conditions.
Few things to note down,
Always launch browser in full screen mode.
driver.maximize_window()
this code should be written before driver.get()
Whenever you get element not interactable, try to use action chains to click or send_keys :
something like this :-
from selenium.webdriver.common.action_chains import ActionChains
action = ActionChains(driver)
action.move_to_element('your web element here').click().perform()
Make sure that using Selenium, the desired web element should be in Selenium view port.
in order to resolve this, you may have to scroll down to let Selenium know where exactly the element is.
Related
We are waiting for a button identified by xpath to be clickable with:
ExpectedConditions.elementToBeClickable()
and then execute click on this button in Selenium.
We then get an error that:
another element would receive the click at position (x, y).
It is possible that this button is moving around slightly on the page during page loading as other buttons next to it are loading.
Why would Selenium report that the button is clickable and then not be able to click it? I understand that's what this condition is for. This execution happens in the same line.
How could we solve this problem?
Imagine that you want to interact with a button and that button is in middle of the page.
Case1:
You do not open the browser in full-screen mode through an automation script.
Then its position will not be in the middle of the page.
you can solve this issue by just introducing
driver.maximize_window()
Case2:
Maybe in the automation script, some pop up or ads shows up and that really hides the button in the background. In this case, you will likely encounter another element would receive the click at position (x, y).
Solution: You should determine what kind of pop up/Alert/ads they are and handle them separately then only you should interact with the intended button.
Case3:
It could also occur cause you might have open (let's say calendar to select a start/end date) and then because of that web elements that are just under the calendar view won't be accessible to selenium and only the Calendar view will get the click. [This should answer your query]
In General, I use actions class or JS to inject js code in the selenium script.
If you are using Selenium with Python then you can use
Use ActionChains:
ActionChains(driver).move_to_element(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "CSS here")))).click().perform()
Use execute_script:
wait = WebDriverWait(driver, 20)
button= wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "CSS here")))
driver.execute_script("arguments[0].click();", button)
In Python you'd need the below imports as well:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
Using ExpectedConditions.elementToBeClickable() allows our code to halt program execution, or freeze the thread, until the condition we pass it resolves. The condition is called with a certain frequency until the timeout of the wait is elapsed. This means that for as long as the condition returns a falsy value, it will keep trying and waiting. Thus Explicit waits allows us to wait for a condition to occur which inturn synchronises the state between the browser and its DOM Tree, and the WebDriver script.
Even with ExpectedConditions.elementToBeClickable() there can be instances while invoking click() on the desired element you may face either of the following errors:
Element ... is not clickable at point (415, 697). Other element would receive the click: <div class="cc-content">...</div>
or
WebDriverException: Element is not clickable at point (36, 72). Other element would receive the click
Reason and Solution
There can be numerous reasons for this error to occur and a couple of them and their remediation are as follows:
Though the element is within the Viewport but may be hidden behind the cookie banner. In such cases you have to accept the cookie consent before you interact with the desired element as follows:
new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("cookieConsentXpath"))).click();
new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("elementXpath"))).click();
The element may be clickable but behind a loader. In such cases you have to wait for the loader to disappear before you interact with the desired element as follows:
new WebDriverWait(driver, 20).until(ExpectedConditions.invisibilityOfElementLocated(By.cssSelector("loader_cssSelector")));
new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.cssSelector("element_cssSelector"))).click();
I have an app made with Quasar. I make e2e tests with python selenium using firefox. I log in and then would like to logout. To perform this I need as usually click on profile icon to show the menu and select Logout.
The issue is that whatever I tried the menu doesn't appear. The code looks as follows.
#pytest.mark.nondestructive
def test_must_login_and_logout_properly(logged_in_selenium, wait):
driver = logged_in_selenium
avatar = wait.until(EC.presence_of_element_located((By.XPATH, '//header//img[#alt="Profile image"]/ancestor::button/parent::span')))
# "natively" via selenium
ActionChains(driver).pause(1).move_to_element(avatar).click().perform()
# via javascript
driver.execute_script('document.evaluate(\'//header//img[#alt="Profile image"]/ancestor::button/parent::span\', document).iterateNext().dispatchEvent(new Event("click"))')
The above code doesn't work UNTIL I really click this element with the mouse. By putting time.sleep(10) at first line in test function and click. After that any method via avatar.click() or execute_script(...) works fine.
I also have an option to use PyAutoGUI to find the avatar on the screen and perform that click, but I don't like this variant.
-- UPDATE
I found out why it behaves like this, but still don't know how to work this around. Initially (after page load) click event handler is not attached to //header//img[#alt="Profile image"]/ancestor::button/parent::span element. It only appears after manual click in this area.
Any ideas?
You didn't share a link to this page, so I can only guess.
I would try to:
Wait for element visibility, not just existance.
Try to remove click from ActionChains action.
Add a short delay between moving to the element and click on it..
Still not sure, but possibly this will work
avatar = wait.until(EC.visibility_of_element_located((By.XPATH, '//header//img[#alt="Profile image"]/ancestor::button/parent::span')))
ActionChains(driver).pause(1).move_to_element(avatar).perform()
time.sleep(0.2)
avatar.click()
UPD
Try this:
wait.until(EC.visibility_of_element_located((By.XPATH, "//div[#class='q-avatar']"))).click()
wait.until(EC.visibility_of_element_located((By.XPATH, "//div[text()='Logout']"))).click()
Eventually it was necessary to click the element twice. Due to maybe Quasar implementation detail.
#pytest.mark.nondestructive
def test_must_login_and_logout_properly(logged_in_selenium, wait):
driver = logged_in_selenium
avatar = wait.until(EC.visibility_of_element_located((By.XPATH, '//header//img[#alt="Profile image"]/ancestor::button/parent::span')))
ActionChains(driver).pause(1).move_to_element(avatar).click().pause(0.5).click().perform()
wait.until(EC.visibility_of_element_located((By.XPATH, "//div[text()='Logout']"))).click()
wait.until(EC.visibility_of_element_located((By.XPATH, '//div[text()="You have logged out"]')))
I have an element in a table. I want to check if the element is clickable or not.
I dont want to wait for it to be clickable. I just want to check if it is clickable.
Please help.
if it is enabled and visible to selenium then it should be clickable, shouldn't it be ?
Now if there is any pre condition i.e if you select I agree button then only you can click on Okay button. Those things are exception for this answer.
isDisplayed() Method in Selenium
The isDisplayed() method is used to check whether an element is displayed on a web page or not.
driver.findElement(By.locatorType(“path”)).isDisplayed();
isEnabled() Method in Selenium
isEnabled() method is used to check if the web element is enabled or disabled within the web page.
driver.findElement(By.locatorType(“path”)).isEnabled();
You can use a try/except like this
from selenium.common.exceptions import ElementNotInteractableException
driver.implicitly_wait(0)
try:
element.click()
except ElementNotInteractableException:
# TODO: put something here
I am trying to go to the below URL
https://twitter.com/explore
Enter HBO Max in the text box which I locate using
By.cssSelector("input[placeholder='Search Twitter']")
and then I want to select the HBO Max option that appears in the dropdown. My locator for the element to be selected is
By.xpath("//div[#role='option']//li/div/div[2]")
Sometimes the element gets clicked and I go to the new page, sometimes not. I have in my framework waited for the element to be clickable using WebDriverWait. The element is both visible and enabled because I print these values before I click the element.
Additional debugging steps performed -
Click using JavaScript seems to have the same behavior.
I believe I am using the right locator because the mouse event gets generated for this element.
Thread.Sleep seems to work suggesting that perhaps a timing issue
Any inputs would be great.
try:
myElem = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, 'ID')))
print("Page is ready!")
except TimeoutException:
print("Loading took too much time!")
Try this !
what it does : It wait until the specific element of the site is loaded. If it takes more time than specified will just give you an output as "loading took too.........."
You can modify the time required to wait.
I need to click on the dynamically generated element using Selenium WebDriver (Java API).
I'm waiting for this element to appear with WebDriverWait and then clicking on it. This click succeeds but the following click on the different static element freezes the whole test. Here is the code:
webDriver.get(alfrescoURL + "/share/page/create-document");
WebDriverWait wait = new WebDriverWait(webDriver, 10);
WebElement documentTypeList = webDriver.findElement(By.id("template_x002e_create-document_x002e_create-document_x0023_default_documenttype-selected-form-button-button"));
documentTypeList.click();
WebElement listItem = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.id("yui-gen100")));
listItem.click();
// Choosing to create in new project
WebElement projectLink = webDriver.findElement(By.id("template_x002e_create-document_x002e_create-document_x0023_default_projecttype-entry1"));
projectLink.click();
documentTypeList.click() opens a drop-down list, listItem.click() chooses an item, projectLink.click() makes a choice in the group of radiobuttons. Test silently freezes on projectLink.click(). It looks like this click() infinitly waits for page reloading that happens by some reason while it shouldn't. (Disappearing of the list after choosing an item is made by javascript that doesn't make any AJAX requests.)
I think there is something about click() blocking i don't understand. It says in it's javadoc that it attempts to block only if it causes a page to load. Nevertheless here i get a block for some reason.
If i insert a thread sleep before projectLink.click() then test works fine. It agrees with a hypothesis that i get a infinite block on click().
Thanks in advance.
I've run into this before where the test runs faster than the drop down can contract and can't click the following element. Instead of using arbitrary sleeps (although in rare cases they are necessary), can you put in a wait for a class change in the drop down?
For example, if I want to wait for the drop down to contract before moving on, I'll wait for the class of the select to change from "active" to "closed". This, of course, assumes your HTML has these dynamic classes in place.
Another possibility is to set an implicit wait, giving yourself enough padding for instances like these:
driver.manage().timeouts().implicitlyWait(1000, TimeUnit.MILLISECONDS);
I would suggest that you try other click options too:
a) Actions#click()
b) Javascript click()
If any of those click works then it means the issue is with the selenium's WebElement Click method which needs to be reported.