Selenium findElement(By.CSS_SELECTOR) - python

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.

Related

Clicking a button with Selenium button

I'm trying to click on "Agree" button on this website https://www.soccerstats.com/matches.asp?matchday=1# but it didn't work for me using this code:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
import time
s=Service("C:/Users/dhias/OneDrive/Bureau/stgg/chromedriver.exe")
driver=webdriver.Chrome(service=s)
driver.get("https://www.soccerstats.com/matches.asp?matchday=1#")
driver.maximize_window()
time.sleep(1)
driver.find_element(By.CLASS_NAME," css-47sehv").click()
the css-47sehv is the class name of the button and here is a picture of the button The blue button
Though the element AGREE contains the classname css-47sehv, the value looks dynamic and may change in a short interval or once the application gets restarted.
Solution
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:
driver.get("https://www.soccerstats.com/matches.asp?matchday=1#")
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button[mode='primary']"))).click()
Using XPATH:
driver.get("https://www.soccerstats.com/matches.asp?matchday=1#")
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[#mode='primary' and text()='AGREE']"))).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 have to make sure of following:
1-use explicitly Wait to wait the button to/Till appear
try:
element=WebDriverWait(driver,10).until(
EC.presence_of_element_located((By.ID, "AgreeButton"))
)
finally:
driver.quit()
2-Click on the button with correct Xpath:
driver.find_element(By.XPATH,"//button[text()='AGREE']").click()
3-If simple click doesn't work you can use JavaScript and perform methods to click.
Try using this
driver.find_element_by_class_name('css-47sehv').click()
on place of
driver.find_element(By.CLASS_NAME," css-47sehv").click()
To click on AGREE button use the following xpath to identify the element and click.
//button[text()='AGREE']
Code:
driver.find_element(By.XPATH,"//button[text()='AGREE']").click()
Or Use following css selector.
driver.find_element(By.CSS_SELECTOR,"button.css-47sehv").click()

How to interact with button based on text using Selenium and Python

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

Click on ember.js enabled element using Selenium

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.

How do I make Selenium Python click on a button element?

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

How to click on angular dropdown menu in Selenium

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('****')

Categories