I have a python script where I need to click a button. My function is as follows:
def inviteuser():
invitebutton.click()
time.sleep(2.5)
addressbox = driver.find_element_by_xpath('/html/body/div[9]/div/div/div[2]/div/div[1]/div/div/div/div/div[3]/div/div/div[1]')
time.sleep(2.5)
addressbox.send_keys(email)
time.sleep(2.5)
sendbutton = driver.find_element_by_xpath('/html/body/div[8]/div/div/div[3]/div[2]')
sendbutton.click()
When running the script at the button clicking part, I get this message:
selenium.common.exceptions.ElementClickInterceptedException: Message: Element <div class="c-sk-modal_footer_actions"> is not clickable at point (834,677) because another element <div class="ReactModal__Overlay ReactModal__Overlay--after-open c-popover c-popover--z_above_fs c-popover--fade"> obscures it
I tried searching for that div, but the search in the browser could not find it.
I also tried
driver.find_element_by_css_selector('.c-button .c-button--primary .c-button--medium').click()
HTML code of the items
<div class="c-sk-modal_footer_actions">
<button class="c-button c-button--primary c-button--medium c-button--disabled" data-qa="invite-to-workspace-modal-invite-form-send-button" type="button" aria-disabled="true">
"Send"
::after
</button>
</div>
If it helps at all, this is for the invite people box in slack admin portal
EDIT:
So I basically figured out the issue but can't figure out how to fix the issue...
So just using the variable sys.argv[1] puts in the email address, but I need to either press space bar , comma, or enter key after. I can get it to work if I specify what the variable email is (email = "test#test.com" then confirm = " ") and adding a second line addressbox.send_keys(confirm) but if I make the variable what I need it to be so it's called from powershell (sys.argv[1]) It doesn't work. It's like it removes what I entered and only puts what's in the variable "confirm"
Try the execute script method which can have a better chance when getting that error. Also you could use implicitly wait instead of time waits to be more effecient.
driver.implicitly_wait(5)
addressbox = driver.find_element_by_xpath('/html/body/div[9]/div/div/div[2]/div/div[1]/div/div/div/div/div[3]/div/div/div[1]')
driver.execute_script("arguments[0].click();", addressbox)
Generally <div> elements aren't clickable. Presumably you need to crosscheck if the following element is your desired element:
<div class="c-sk-modal_footer_actions">
Where as, the element from your second attempt:
<div class="c-button c-button--primary c-button--medium...">
looks as a perfect clickable candidate.
Solution
The desired element is a React element, so to click() on the element you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following locator strategies:
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".c-button.c-button--primary.c-button--medium"))).click()
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//*[#class='c-button c-button--primary c-button--medium']"))).click()
Note: You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
Related
I want to use the click() function of selenium on these buttons in the following manner(the first two clicks):
For reference the 1st button I want to click and its code:
2nd button with its code:
I tried using
driver.find_element(By.XPATH,"//button[contains(#type,\"button\")]").click()
on the first button (the "X" mark) but it didn't work and got this error:
selenium.common.exceptions.ElementClickInterceptedException: Message: element click intercepted: Element <button type="button" class="el-button yellowBtn el-button--default">...</button> is not clickable at point (606, 507). Other element would receive the click: <img src="https://d2g38dx0j6xqav.cloudfront.net/online/img/app-inner/popup.png" alt="" style="width: 100%;">
If I somehow get it to click the first button then getting it to click the second button will be much easier.
selenium.common.exceptions.ElementClickInterceptedException: Message: element click intercepted
Above exception implies that the element you are trying to action upon isn't clickable, as some other element is overshadowing it.
Try by inducing wait(see below):
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH,"Your XPath expression here"))).click()
if the above doesn't work, try using execute_script() method(see below):
driver.execute_script("arguments[0].click();", WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "Your XPath expression here"))))
Required imports statements:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
I think you should wait until the element is visible in the modal dialog box. U can use both the Explicit and Implicit waits methods for the above problem.
Always read exception and/or error messages carefully to see what you can learn about the problem. In this case, it tells you exactly what happened. I reformatted and shortened it to make it more readable.
ElementClickInterceptedException:
Message: element click intercepted: Element <button...> is not clickable.
Other element would receive the click: <img...>
Selenium is telling you that it tried to click the BUTTON but the click was intercepted (it never got clicked because there was another element covering it). The element that got clicked instead was an IMG.
Without seeing the full HTML of the page it's hard to say but your BUTTON locator looks pretty generic and there's a good chance that you clicked a different BUTTON than you intended. I would use the locator below instead to click on the I tag.
wait = WebDriverWait(driver, 10)
close_icon = (By.CSS_SELECTOR, "i.el-dialog__close")
wait.until(EC.element_to_be_clickable(close_icon)).click() # click the close icon
wait.until(EC.invisibility_of_element_located(close_icon)) # wait for the close icon to disappear indicating the dialog is fully closed
# continue script
If that still doesn't work, you will probably need to use a JS click. If you are writing UI tests, then you should avoid JS clicks unless no other solution can be found because it allows the script to do things that a user can't. If you aren't writing tests, then it likely doesn't matter.
wait = WebDriverWait(driver, 10)
close_icon = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "i.el-dialog__close")))
driver.execute_script("arguments[0].click()", close_icon)
# continue script
You desired element is:
But your line of code:
driver.find_element(By.XPATH,"//button[contains(#type,\"button\")]").click()
is attempting to click on:
<button type="button" class="el-button yellowBtn el-button--default">...</button>
which isn't the desired element and still the click attempt is intercepted by:
<img src="https://d2g38dx0j6xqav.cloudfront.net/online/img/app-inner/popup.png" alt="" style="width: 100%;">
Solution
To click element you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following locator strategies:
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.el-dialog__headerbtn[aria-label='Close'] > i.el-dialog__close.el-icon.el-icon-close"))).click()
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[#class='el-dialog__headerbtn' and #aria-label='Close']/i[#class='el-dialog__close el-icon el-icon-close']"))).click()
Note: You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
Im not sure if that was quite the best title but Im not sure how else to describe it, I am trying to use selenium to automate 2fa on a website so all I need to do is anwser the phone call and the script will take care of the rest however the button I am trying to get selenium to click keeps showing up as unable to locate even though its always in the same place and never changes here is my code in python
callMe = driver.find_element('xpath', '//*[#id="auth_methods"]/fieldset/div[2]/button')
callMe.click()
sleep(25)
this is one of three buttons that all have the same element information besides the xpaths here are all 3 button elements I am trying to grab the second one
<button tabindex="2" type="submit" class="positive auth-button"><!-- -->Send Me a Push </button>
<button tabindex="2" type="submit" class="positive auth-button"><!-- -->Call Me </button>
<button tabindex="2" type="submit" class="positive auth-button"><!-- -->Text Me </button>
I am not sure how else I can locate the second button besides using the xpath but that is not working and I dont know if I can or how I can search for the button based off the text that is inside it.
Did you try with By ?
from selenium.webdriver.common.by import By
callMe = driver.find_element(By.XPATH, '//*[#id="auth_methods"]/fieldset/div[2]/button')
Try using By.cssselector, get the css selector of the main body html for the button you want.
callMe = driver.find_element(By.css_selector, 'selectorofbodyhtml')
callme.click()
Try below xpath
//button[starts-with(text(),'Call Me')]
The desired element Call Me is a dynamic element, so to click on it you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following locator strategies:
Using XPATH and contains():
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[contains(., 'Call Me')]"))).click()
Using XPATH and starts-with():
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[starts-with(., 'Call Me')]"))).click()
Note: You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
I'm trying to pull a specific number out of a div class in Python Selenium but can't figure out how to do it. I'd want to get the "post_parent" ID 947630 as long as it matches the "post_name" number starting 09007.
I'm looking to do this across multiple "post_name" classes, so I'd feed it something like this: search_text = "0900766b80090cb6", but there will be multiple in the future so it has to read the "post_name" first then pull the "post_parent" if that makes sense.
Appreciate any advice anyone has to offer.
<div class="hidden" id="inline_947631">
<div class="post_title">Interface Converter</div>
<div class="post_name">0900766b80090cb6</div>
<div class="post_author">28</div>
<div class="comment_status">closed</div>
<div class="ping_status">closed</div>
<div class="_status">inherit</div>
<div class="jj">06</div>
<div class="mm">07</div>
<div class="aa">2001</div>
<div class="hh">15</div>
<div class="mn">44</div>
<div class="ss">17</div>
<div class="post_password"></div>
<div class="post_parent">947630</div>
<div class="page_template">default</div>
<div class="tags_input" id="rs-language-code_947631">de</div>
</div>
If you see <div class="post_name">0900766b80090cb6</div> this and <div class="post_parent">947630</div> are siblings nodes to each other.
You can use xpath -> following-sibling like this:
Code:
search_text = "0900766b80090cb6"
post_parent_num = driver.find_element(By.XPATH, f"//div[#class='post_name' and text()='{search_text}']//following-sibling::div[#class='post_parent']").text
print(post_parent_num)
or Using ExplicitWait:
search_text = "0900766b80090cb6"
post_parent_num = WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, f"//div[#class='post_name' and text()='{search_text}']//following-sibling::div[#class='post_parent']"))).get_attribute('innerText')
print(post_parent_num)
Imports:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
Update:
NoSuchElementException:
Please check in the dev tools (Google chrome) if we have unique entry in HTML-DOM or not.
xpath that you should check :
//div[#class='post_name' and text()='0900766b80090cb6']//following-sibling::div[#class='post_parent']
Steps to check:
Press F12 in Chrome -> go to element section -> do a CTRL + F -> then paste the xpath and see, if your desired element is getting highlighted with 1/1 matching node.
If this is unique //div[#class='post_name' and text()='0900766b80090cb6']//following-sibling::div[#class='post_parent'] then you need to check for the below conditions as well.
Check if it's in any iframe/frame/frameset.
Solution: switch to iframe/frame/frameset first and then interact with this web element.
Check if it's in any shadow-root.
Solution: Use driver.execute_script('return document.querySelector to have returned a web element and then operates accordingly.
Make sure that the element is rendered properly before interacting with it. Put some hardcoded delay or Explicit wait and try again.
Solution: time.sleep(5) or
WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//div[#class='post_name' and text()='0900766b80090cb6']//following-sibling::div[#class='post_parent']"))).text
If you have redirected to a new tab/ or new windows and you have not switched to that particular new tab/new window, otherwise you will likely get NoSuchElement exception.
Solution: switch to the relevant window/tab first.
If you have switched to an iframe and the new desired element is not in the same iframe context then first switch to default content and then interact with it.
Solution: switch to default content and then switch to respective iframe.
I don't see any specific relation between "post_parent" ID 947630 and "post_name" number starting 09007. Moreover, the parent <div> is having class="hidden".
However, to pull the specific number you can use either of the following locator strategies:
Using css_selector:
print(driver.find_element(By.CSS_SELECTOR, "div[id^='inline'] div.post_parent").text)
Using xpath:
print(driver.find_element(By.XPATH, "//div[starts-with(#id, 'inline_')]//div[#class='post_parent']").text)
Ideally you need to induce WebDriverWait for the presence_of_element_located() and you can use either of the following locator strategies:
Using CSS_SELECTOR:
print(WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.CSS_SELECTOR, "div[id^='inline'] div.post_parent"))).text)
Using XPATH:
print(WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.XPATH, "//div[starts-with(#id, 'inline_')]//div[#class='post_parent']"))).text)
Note: You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
You can create a method and use the following xpath to get the post_parent text based on post_name text.
def getPostPatent(postname):
element=driver.find_element(By.XPATH,"//div[#class='post_name' and starts-with(text(),'{}')]/following-sibling::div[#class='post_parent']".format(postname))
print(element.get_attribute("textContent"))
getPostPatent('09007')
This will return value if it is matches the text starts-with('09007')
It seems parent class is hidden you need to use textContent to get the value.
I have been trying to make this clickable and I just cannot understand what I am doing wrong.
I am also trying to induce webdriverwait, so that it is clicked when it appears.
This is my code so far:
def order(k):
driver = webdriver.Chrome(os.getcwd()+"\\webdriver\\chromedriver.exe")
driver.get("website.com/login-to-checkout")
driver.find_element_by_id('i0116').send_keys(k["email"])
driver.find_element_by_id('i0118').send_keys(k["password"])
driver.find_element_by_id('idSIButton9').click()
delay()
#sign in button
driver.find_element_by_id('idSIButton9').click()
#Button below I cant get to be clicked
with webdriver.Chrome() as driver:
wait = WebDriverWait(driver, 7)
wait.until(presence_of_element_located((By.CSS_SELECTOR, "#ember1053")))
driver.find_element(By.id, "ember1053").click()
this is the source code for the button that I am trying to make clickable:
<div id="ember1037" class="btn-group m-b-lg m-t-lg order-call-to-action ember-view"><!----> <!--biBehavior 80 means place order Place Order-->
<button aria-live="polite" type="button" tabindex="0" data-m="{"aN":"shoppingCart","cN":"PlaceOrder","bhvr":80}" id="ember1053" class="btn theme-default btn-primary cli-purchase ember-view"><!----> Place order
</button></div>
The desired element is an Ember.js element and the value of the id attribute of the <button> will keep changing dynamically, every time you access the AUT(Application Under Test). Hence to click() on the element you have to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following Locator Strategies:
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.btn.theme-default.btn-primary.cli-purchase.ember-view[id^='ember'][type='button'][aria-live='polite']"))).click()
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[#class='btn theme-default btn-primary cli-purchase ember-view' and starts-with(#id,'ember')][contains(., 'Place order') and #aria-live='polite']"))).click()
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
References
You can find a couple of relevant detailed discussions in:
Selenium - Finding element based on ember
Ember dropdown selenium xpath
This may help but I've had issues with webdriver not clicking on a button when I use the id to find it.
The work around I've found is using the xpath instead of the id.
Like this, it's worth a try.
driver.find_element_by_xpath("""//*[#id="submit-button"]""").click()
Here are all the parts of the element I am trying to click according to 'Inspect':
<div class="ui-dialog-buttonpane ui-widget-content ui-helper-clearfix">
::before
<div class="ui-dialog-buttonset">
<button type="button" class="done ui-button ui-corner-all ui-widget">
Done</button>
</div>
::after
</div>
When I want to click it, I assume it is on the ::before part as it is showing and clickable. In the code, I make sure to scroll and wait two seconds before clicking to make sure that the button is visible and yet I get:
selenium.common.exceptions.ElementNotVisibleException: Message: element not interactable
But I don't understand how it's not interactable. When I hover over it in the inspector, everything in <button>...</button> highlights, so the button I want to click must be in there, right?
Here are few things that I have tried:
browser.find_element_by_css_selector('button[type=button]').click()
browser.find_elements_by_xpath("//*[contains(text(), 'Done')]").click()
# The above returns a list for some reason?
browser.find_elements_by_css_selector('done.ui-button.ui-corner-all.ui-widget')
I wish I could remember all that I tried, but regardless I hope someone can help me.
To click on the element as the desired element is a dynamic element you have to induce WebDriverWait for the element to be clickable and you can use either of the following solutions:
Using CSS_SELECTOR:
WebDriverWait(browser, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.ui-dialog-buttonpane.ui-widget-content.ui-helper-clearfix"))).click()
Using XPATH:
WebDriverWait(browser, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[#class='ui-dialog-buttonpane ui-widget-content ui-helper-clearfix']"))).click()
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
You can find a detailed discussion in selenium.common.exceptions.ElementNotVisibleException: Message: element not interactable using Selenium
When you use .find_elements (note the plural) it will return a list instead of a single element like .find_element (singular) does. Have you tried
browser.find_element_by_xpath("//button[.='Done']")
If you get a len() on these .find_elements calls... is it 1? I'm wondering if there isn't more than one button that matches the locators you are using and the first isn't visible but you want the second or third, etc.
You can use ActionChains to move to element
from selenium.webdriver.common.action_chains import ActionChains
element = driver.find_elements_by_css_selector("div.ui-dialog-buttonpane.ui-widget-content.ui-helper-clearfix")
actions = ActionChains(driver)
actions.move_to_element(element).perform()
or u can scroll till element is in view using scrollIntoView():
driver.execute_script("arguments[0].scrollIntoView();", element)