I am trying to use python selenium to automate some report generating on a website, however I am struggling to identify the element I need to click on the page due to the javascript. In firefox there is a DOM Event icon when I inspect the element. I have tried alot of variations including xpath etc but no luck.
<account-groups ng-if="EventsList.ToggleService.accountGroup();">
<button class="btn-default" ng-disabled="AccountGroupsCtrl.isDisabled()" ng-click="AccountGroupsCtrl.toggleFlyout()">
</button>
</account-groups>
EDIT For anyone viewing this the issue was because I had not switched frames using driver.switch_to.frame('frame_name'). Once this step is carried out the rest of the solutions below worked in identifying the elements. Thanks
As per the HTML you have shared it is not clear if the WebElement is a Dropdown. However as the desired element is an Angular element to invoke click() on the element you need to induce WebDriverWait and you can use either of the following solutions:
CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.btn-default[ng-click^='AccountGroupsCtrl']"))).click()
XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[#class='btn-default' and starts-with(#ng-click,'AccountGroupsCtrl')]"))).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 use following code for selecting from dropdown.
from selenium.webdriver.support.ui import Select
select = Select(driver.find_element_by_id('*****'))
select.select_by_visible_text('****')
Related
I have this button on the page:
<button type="submit" class="sc-pjTqr dzmlqP">Continue</button>`
I checked the documentation and StackOverflow answers and it seems to me that the solution should be:
continue = driver.find_element(By.CSS_SELECTOR,"button.sc-pjTqr.dzmlqP")
But does not work.
I searched for solutions, but I didn't understand. Why?
The classnames i.e. sc-pjTqr, dzmlqP are dynamically generated and is bound to chage sooner/later. They may change next time you access the application afresh or even while next application startup. So can't be used in locators.
Solution
To identify the element with text as Continue you can use the following locator strategy:
Using xpath:
continue = driver.find_element(By.XPATH, "//button[text()='Continue']")
Ideally to identify the clickable element you need to induce WebDriverWait for the element_to_be_clickable() and you can use the following locator strategy:
Using XPATH:
continue = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[text()='Continue']")))
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
The OP doesn't confirm the url where this button lives, so I can test the solution:
button = WebDriverWait(browser, 20).until(EC.element_to_be_clickable((By.CLASS_NAME, "sc-pjTqr")))
There are other ways as well.
I'm trying to click buttons based on their text (using selenium). e.g., for the following HTML tag:
<span class="MuiTab-wrapper jss483">Options</span>
I've tried:
driver.find_elements_by_xpath("//*[contains(text(), 'Options')]").click()
However, Selenium can't find any element with the text: "Options".
Any ideas?
Please check in the dev tools (Google chrome) if we have unique entry in HTML DOM or not.
xpath that you should check :
//*[contains(text(), 'Options')]
or
//span[contains(text(), 'Options')]
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.
There are 4 ways to click in Selenium.
Code trial 1 :
time.sleep(5)
driver.find_element_by_xpath("//span[contains(text(), 'Options')]").click()
Code trial 2 :
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//span[contains(text(), 'Options')]"))).click()
Code trial 3 :
time.sleep(5)
button = driver.find_element_by_xpath("//span[contains(text(), 'Options')]")
driver.execute_script("arguments[0].click();", button)
Code trial 4 :
time.sleep(5)
button = driver.find_element_by_xpath("//span[contains(text(), 'Options')]")
ActionChains(driver).move_to_element(button).click().perform()
Imports:
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
Also, find_elements returns a list, change that to find_element you should be good to go ahead.
or else use list index to point web element.
elems = driver.find_elements_by_xpath("//*[contains(text(), 'Options')]")
elems[0].click()
This is not recommended way.
You are using find_elements_by_xpath method. It will give you a list of web elements, not a single web element. So you can not apply .click() on the result of
driver.find_elements_by_xpath("//*[contains(text(), 'Options')]")
You should use find_element_by_xpath instead so your code will be
driver.find_element_by_xpath("//*[contains(text(), 'Options')]").click()
or clicking on the first result (or any other) from the web elements list returner, as following
driver.find_elements_by_xpath("//*[contains(text(), 'Options')]")[0].click()
Also possibly you need to add some delay / wait to let the element be loaded before accessing it.
Or maybe you need to scroll that element into the view.
Or maybe the element is inside an iframe...
To click on the element with text as Options you can use either of the following Locator Strategies:
Using xpath:
driver.find_element(By.XPATH, "//span[contains(#class, 'MuiTab-wrapper') and contains(., 'Options')]").click()
The desired element is a JavaScript enabled element, so ideally, 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 XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//span[contains(#class, 'MuiTab-wrapper') and contains(., 'Options')]"))).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 am trying to click on the following button on a linkedin page using selenium:
<button id="ember607" class="share-actions__primary-action artdeco-button artdeco-button--2 artdeco-button--primary ember-view" data-control-name="share.post"><!---->
<span class="artdeco-button__text">
Post
</span></button>
I have tried to use:
driver.find_element_by_id, but the id of the button seems to keep changing number
driver.find_element_by_xpath, but this contains the button number, so also fails
driver.find_element_by_class_name('share-actions__primary-action artdeco-button artdeco-button--2 artdeco-button--primary ember-view'), this fails even though the class name is correct ?
Basically, all methods generate the same error message:
Exception has occurred: NoSuchElementException
Message: no such element: Unable to locate element:{[*the_error_is_here*]}
I have also tried the xpath contains() method, but this does not find the button.
What would be the correct way to click on this button please ?
I am using python version 3.9 on windows with driver = webdriver.Chrome
The element is an Ember.js enabled element. So to click() on the element with text as Post you can use either of the following Locator Strategies:
Using css_selector:
driver.find_element_by_css_selector("button.share-actions__primary-action[data-control-name='share.post']>span.artdeco-button__text").click()
Using xpath:
driver.find_element_by_xpath("//button[contains(#class, 'share-actions__primary-action') and #data-control-name='share.post']/span[#class='artdeco-button__text' and contains(., 'Post')]").click()
Ideally, 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, "button.share-actions__primary-action[data-control-name='share.post']>span.artdeco-button__text"))).click()
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[contains(#class, 'share-actions__primary-action') and #data-control-name='share.post']/span[contains(., 'Post')]"))).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
Automate Ember.js application using Selenium when object properties are changed at run-time
Ember: Best practices with Selenium to make integration tests in browser
Ember dropdown selenium xpath
Sometimes there are problems with buttons that are not clickable at the moment.
Try this:
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
wait = WebDriverWait(driver, 10)
button = wait.until(EC.element_to_be_clickable((By.XPATH, '[YOUR X_PATH TO THE BUTTON]')))
driver.execute_script("arguments[0].click()", button)
It's not the cleanest way to click any Button with selenium, but for me this method works mostly everytime.
//button[#class="share-actions__primary-action artdeco-button artdeco-button--2 artdeco-button--primary ember-view"].
Or
//button[contains(#id,'ember')]
Find the span with Post and click it's button tag.
//span[contains(text(), 'Post')]/parent::button
By xpath this should work:
//button/span[contains(text(), "Post")]
Combine it with a wait for the element:
button = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, "//button/span[contains(text(), "Post")]"))
)
The problem with your by class selectors is the multiple class names. See this question: How to get elements with multiple classes for more details on how to overcome that.
So I just started using Selenium for Python and I am trying to click on a button element that is buried into a few div elements; I've tried so many things but nothing works. Everything in the code works besides the last part which is waiting for the button to be clickable and then clicking it. I would greatly appreciate some help here, thanks. :)
HTML:
Code trials:
Error stacktrace:
To click on **Maybe Later** button.
Induce WebDriverWait() and element_to_be_clickable() and following XPATH or CSS Selector.
XPATH:
WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.XPATH,"//div[#class='modal-footer']//button[#Class='btn btn-danger x' and text()='Maybe Later']"))).click()
CSS Selector:
WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"div.modal-footer button.btn.btn-danger.x[style='danger']"))).click()
You need to import following libraries.
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
css selectors will become your best friend,
you should always look to add as many attributes as possible
maybe_later_css = 'button[class="btn btn-danger"]'
# type str, '<tag-name>[<attribute-name> = <attribute-value>]'
driver.find_element_by_css_selector(maybe_later_css).click()
follow this format for all elements, its superior and works as expected every time
the only complication is when there exists multiple buttons with them same class name, in which case you should find a different attribute to fill the [] brackets
The element with text as Maybe Later is within a Modal Dialog Box so to locate and 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, "div.modal-footer#eFooter button.btn.btn-danger.x[style='danger']"))).click()
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[#class='modal-footer' and #id='eFooter']//button[#class='btn btn-danger x' and #style='danger']"))).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 using selenium python and have tried more than a dozen ways to find a clickable link element from a span tag but have been unsuccessful. I've tried using xpath, by link text, partial link text, and other suggestions researched.
The last 3 attempts using:
browser.find_element_by_link_text("Web Time Clock-Eastern").click()
element = browser.find_element_by_partial_link_text('Clock-Eastern')
browser.wait.until(EC.element_to_be_clickable((By.XPATH, '//a[#span]/html/body/div[6]/div[1]/div[1]/div[1]/div/div/div[4]/div[2]button'))).click()
I've provided image of the inspected element html below:
I expect to locate an element I can pass click method to open corresponding web page.
To click() the 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(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.cardLinks a[href*='php/timeclock/WEB'] > span"))).click()
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[#class='cardLinks']//a[contains(#href, 'php/timeclock/WEB')]/span[text()='Web Time Clock-Eastern']"))).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
Try the below xpath.
//span[normalize-space(.)='Web Time Clock-Eastern']/parent::a
One of the main reasons for using XPath is when you don’t have a suitable id or name attribute for the element you wish to locate.
browser.find_element_by_xpath("//div[#class='cardLinks']/div/a").click()