I'm using Selenium for testing. I want to click on an element. The element is very much clickable and visible, but it happens that the middle point of the element is obscured, causing the error.
Here is a MCVE:
HTML code (link to demo):
<style>
button {
width: 90vw;
height: 90vh;
position: fixed;
top: 5vh;
left: 5vw;
}
.cover {
background: grey;
opacity: 0.3;
width: 80vw;
height: 80vh;
position: fixed;
top: 10vh;
left: 10vw;
}
</style>
<button onclick="alert('hi');">
Click me!
</button>
<div class="cover">
I'm in the way!
</div>
Python selenium code:
from selenium import webdriver
driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get("https://blissfulpreciouslanservers--five-nine.repl.co/")
button = driver.find_element_by_tag_name("button")
button.click()
Result:
selenium.common.exceptions.ElementClickInterceptedException: Message: element click intercepted: Element <button onclick="alert('hi');">...</button> is not clickable at point (451, 450). Other element would receive the click: <div class="cover">...</div>
This seems like a rather sad limitation of Selenium. The button is clickable, just not at all points. I don't want to have to fiddle with scrolling and coordinates.
There are many similar questions about the exception in general, e.g:
Can not click on a Element: ElementClickInterceptedException in Splinter / Selenium
Selenium can't click element because other element obscures it
Element not clickable since another element obscures it in python
However the questions are never specifically about an element that is only partially obscured, so I haven't managed to find a proper answer to my own question. The answers to other questions generally fall into these categories:
Wait until the element is clickable. Doesn't apply here.
Use action chains, e.g. ActionChains(driver).move_to_element(button).click().perform(). This doesn't help because .move_to_element() moves to the middle of the element.
Use JavaScript to perform the click. It seems like I might have to resort to this, but it's very unsatisfactory. I still want to validate that the element is clickable at least somewhere and not bypass all checks.
Have you tried to add a class to your button and then search for the class? For example:
<button class="btn" onclick="alert('hi');">
Click me!
</button>
Then use the following to find and click on that button:
driver.findElement(By.className("btn")).click();
similar to this stack overflow response by alecxe
Related
I am trying to have selenium click on the next page button at this site after clicking the submit button and getting pages of results: https://elibrary.ferc.gov/eLibrary/search
I have tried countless ways to have selenium click on this button. The html code for the next page button on the results page is here:
<button class="mat-paginator-navigation-next mat-icon-button" mat-icon-button="" type="button" aria-describedby="cdk-describedby-message-8" cdk-describedby-host="" aria-label="Next page" style="touch-action: none; user-select: none; -webkit-user-drag: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);"><span class="mat-button-wrapper"><svg class="mat-paginator-icon" focusable="false" viewBox="0 0 24 24"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"></path></svg></span><div class="mat-button-ripple mat-ripple mat-button-ripple-round" matripple=""></div><div class="mat-button-focus-overlay"></div></button>
I've tried the following:
link = driver.find_element_by_xpath('//*[#id="rsltToolbar"]/mat-paginator/div/div/div[2]/button[2]')
link.click()
But the code does not work. Hopefully this is the button that needs to be clicked! I've tried by css selector, class_name, by javascript etc. to no avail. Any help much appreciated.
link = driver.find_element_by_classname("mat-paginator-navigation-next")
should work fine
# (tested in js console with)
document.querySelector(".mat-paginator-navigation-next").click()
you might have to just add a delay (ie its probably not clickable initially(or clicking it too soon just does nothing)) I think you can wait for it to be clickable somehow
driver.findElement(By.id("submit")).click();
Thread.sleep(4000);
driver.findElement(By.xpath("//*[#id='rsltToolbar']/mat-paginator/div/div/div[2]/button[2]")).click();
XPath you have tried is working just need to add delay after you click "Search" on page"https://elibrary.ferc.gov/eLibrary/search"
I have the following website where I want to click on the button "SKIP THIS AD" that popup after waiting x seconds.
My code is as follows:
import selenium
from selenium import webdriver
driver = webdriver.Chrome()
driver.get('http://festyy.com/wpixmC')
sleep(10)
driver.find_element_by_xpath('/html/body/div[3]/div[1]/span[5]').click()
However, when I inspect the element I don't see a connected link to be clicked. In addition, I get
ElementClickInterceptedException: Message: element click intercepted: Element <span class="skip-btn
show" id="skip_button" style="cursor: pointer">...</span> is not clickable at point (765, 31). Other
element would receive the click: <div style="position: absolute; top: 0px; left: 0px; width: 869px;
height: 556px; z-index: 2147483647; pointer-events: auto;"></div>
Somehow it seems that everything is redirected to the larger class? How can I overcome this? When I try to copy the xpath I get also only the following: /div
Thanks in advance
It seems that the error that you receive ('element click intercepted') is due to the fact that there is a div that is placed on page load, that takes up the whole page, preventing Selenium from clicking on the skip button.
Therefore you have to remove that div first and then run this:
driver.find_element_by_xpath('/html/body/div[3]/div[1]/span[5]').click()
You can remove the div by running some JavaScript code as follows:
driver.execute_script("""
var badDivSelector = document.evaluate('/html/body/div[7]',
document.documentElement, null, XPathResult.FIRST_ORDERED_NODE_TYPE,
null);
if (badDivSelector) {
var badDiv = badDivSelector.singleNodeValue;
badDiv.parentNode.removeChild(badDiv);
}
""")
The code above finds the full page div (identified by xpath) and removes it from the page.
Your final code should look something like this:
import selenium
from selenium import webdriver
from time import sleep
driver = webdriver.Chrome()
driver.get('http://festyy.com/wpixmC')
sleep(10)
driver.execute_script("""
var badDivSelector = document.evaluate('/html/body/div[7]',
document.documentElement, null, XPathResult.FIRST_ORDERED_NODE_TYPE,
null)
if (badDivSelector) {
var badDiv = badDivSelector.singleNodeValue;
badDiv.parentNode.removeChild(badDiv);
}
""")
driver.find_element_by_xpath('/html/body/div[3]/div[1]/span[5]').click()
....
I want to click on a check box after I load up a page, but I get the error message below:
selenium.common.exceptions.ElementClickInterceptedException: Message: element click intercepted: Element <img class="checkboximage" src="/images/nav/ns_x.gif" alt=""> is not clickable at point (843, 7). Other element would receive the click: <a class="ns-help" onclick="nlPopupHelp('EDIT_TRAN_CUSTINVC');" tabindex="0" onkeypress="(event.keyCode == 13 || event.charCode == 32) && nlPopupHelp('EDIT_TRAN_CUSTINVC');">...</a>
This is what I have right now: I've tried several other methods before this
collectionsbox = driver.find_element(By.CSS_SELECTOR,"#custbody_in_collections_fs_inp")
driver.execute_script("arguments[0].scrollIntoView(true)", collectionsbox)
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//span[#id='custbody_in_collections_fs']//img[#class='checkboximage']"))).click()
collectionsbox.click() #USUALLY FAILS RIGHT HERE
savebutton = driver.find_element(By.XPATH,"//input[#id='btn_multibutton_submitter']")
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[#id='btn_multibutton_submitter']"))).click()
driver.execute_script("arguments[0].scrollIntoView(true)", savebutton)
savebutton.click()
time.sleep(2)
driver.switch_to.alert.accept()
I've tried the EC method, waited several seconds, scroll down to view the element. I've even used Xpath, ID, and CSS.
<input onclick="setEventCancelBubble(event); this.isvalid=(nlapiValidateField(null,'custbody_in_collections')); if (this.isvalid) {setWindowChanged(window, true);nlapiFieldChanged(null,'custbody_in_collections');;} else if ( window.loadcomplete && !document.page_is_resetting ) {setFormValue(this, !this.checked);}" aria-labelledby="custbody_in_collections_fs_lbl" onchange="NLCheckboxOnChange(this); " onkeypress="NLCheckboxOnKeyPress(event); return true;" name="custbody_in_collections" id="custbody_in_collections_fs_inp" type="checkbox" value="T" class="checkbox" style="">
<input type="hidden" name="custbody_in_collections_send" style="">
<img class="checkboximage" src="/images/nav/ns_x.gif" alt="" style="">
All I need is click the checkbox and click save up top.
Seems like another element on the DOM is unintentionally hiding the element you are trying to click. You can try executing Javascript for the click instead. This usually resolves the issue for me.
Instead of collectionsbox.click() #USUALLY FAILS RIGHT HERE, you can replace with:
driver.execute_script("arguments[0].click();", collectionsbox)
To address element is not clickable at point (x, y) error. We can follow below approaches to resolve this issue
Solution
1. Action Class
WebElement element = driver.findElement(By.id("yourelement ID"));
Actions actions = new Actions(driver);
actions.moveToElement(element).click().build().perform();
2. Element not getting clicked as it is not within Viewport
use JavascriptExecutor to get element within the Viewport:
checkBox=WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.XPATH,"yourelement Xpath")))
ActionChains(driver).move_to_element(checkBox).click(checkBox).perform()
I am trying to make click for this element,
but getting error like
>> ElementClickInterceptedException: Message: element click intercepted: Element is not clickable at point (271, 705)
element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, '//*[#action="/battle/"]/div/input[2]')))
element.click();
This is not helping also getting timeoutexception. I think element kinda covered
with:
[driver.find_element_by_xpath('//[#action="/battle/"]/div/input[2]').click()]
<form action="/battle/" method="post" name="4416" id="4416" onsubmit="get('/battle/', '', this); disableSubmitButton(this); return false;"><div class="battleView" style="float:left; width:65%;"><h3 class="heading-maroon no-right-border-rad margin-right-2">Attack Results</h3><table cellpadding="0" cellspacing="0" style="width: 80%; text-align: center; margin: 0 auto;">
...
</tbody></table><input type="hidden" class="button-maroon button-small" name="action" value="attack">
<input type="submit" class="button-maroon button-small" value=" Attack .. "></div>
</form>
It looks like it's showing the X/Y coordinates (271,705) in the error message. I'd try a macro product like AppRobotic to look up the X/Y coordinates of elements that you have issues finding with XPATH, moving the mouse, or sending keystroke TABS, and clicking it. A simple example:
import win32com.client
x = win32com.client.Dispatch("AppRobotic.API")
from selenium import webdriver
# navigate to Yahoo
driver = webdriver.Firefox()
driver.get('https://www.yahoo.com')
# sleep 1 second
x.Wait(1000)
link = driver.find_element_by_link_text('Mail')
if len(link) > 0
link[0].click()
else
x.Wait(3000)
# use UI Item Explorer to get X,Y coordinates of Mail box
x.MoveCursor(271,705)
# click inside Search box
x.MouseLeftClick
# could also try tabbing over and pressing Enter
x.Type("{TAB}")
x.Type("{ENTER}")
Another idea is to try scrolling to the element with Selenium first:
from selenium.webdriver.common.action_chains import ActionChains
element = driver.find_element_by_xpath('//[#action="/battle/"]/div/input[2]')
actionchains = ActionChains(driver)
actionchains.move_to_element(element).perform()
I'm getting TimeoutException when using this code to get the fill in the CardNum textbox with a number
CardNUM = WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.XPATH, '//*[#id="number"]')))
CardNUM.send_keys(cardNum)
Xpath is taken directly from right clicking and inspecting the textbox and copying the XPATH for the block
<input autocomplete="cc-number" id="number" name="number" type="tel" aria-describedby="error-for-number" data-current-field="number" class="input-placeholder-color--lvl-30" placeholder="Card number" style="color: rgb(151, 151, 151); font-family: "Helvetica Neue"; padding: 0.94em 0.8em; transition: padding 0.2s ease-out;">
Is there something else I need to do to be able to fill in the box, for example is the text box hidden and is there some manipulation that I would need to do beforehand to be able to find the text box?
Most likely the element is inside an IFRAME, especially since it seems to be a credit card number. The payment portion of payment pages are typically in an IFRAME for security. Try switching to the IFRAME first then your code should work.