Click on a checkbox element using python and selenium - python

I am trying to automate loading and configuring a web page.
On this page I am trying to check the state of the checkbox and then click on a it if its unchecked.
HTML code for the page:
<fieldset id="wireless-24" class="left" style="display: block;">
<div class="legend-edit text-orphan">
<legend>2.4 GHz network</legend><span>|</span><span id="edit-wireless-24"><a id="editWireless24Link" href="http://192.168.0.1/ui/1.0.99.162351/dynamic/home.html#">Edit</a></span>
</div>
<div class="row toggle-edit">
<label style="width: 126px;">Network:</label>
<label id="w-radio-enabled-text-24">Disabled</label> <!-- code sets the text to either Enabled or Disabled -->
<div class="cell" id="w-enabled-span-24">
<div class="check-item" style="">
<div><input type="checkbox" id="w-enabled-24" name="radio.band24.settings.isEnabled" class="ui-helper-hidden-accessible"><span class="ui-checkbox"></span></div>
<div><label for="w-enabled-24" class="ui-checkbox">Enabled</label></div>
</div>
</div>
</div>
Network is the field I am trying to click on. I am using selenium and python.
I tried the following:
browser.find_element_by_id("w-radio-enabled-text-24").send_keys("Enabled")
browser.find_element_by_text("Network").click()

Firstly, you are trying to send_keys to label tag, what is wrong. You can send_keys to input tag or equivalent. Secondly, you are trying to click on the label, what from my perspective also not effective. I believe you want something like this:
checkbox = driver.find_element_by_id('w-enabled-24') # locate checkbox
if not checkbox.is_selected(): # check if checkbox is already selected
checkbox.click() # if not, click on it
Also I would add WebDriverWait, to make sure, that element is visible and ready to be clicked like this:
checkbox = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, "w-enabled-24")))
this will wait at least 10 seconds until checkbox will be clickable. The full code would be like this:
checkbox = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, "w-enabled-24")))
if not checkbox.is_selected():
checkbox.click()
Note: you have to add some imports:
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By
More information about WebDriverWait you will find here.

Related

Selenium click button with <a> tag - intercepted exception

I am trying to click a button on a website in Python using Selenium. The html for the button I want looks like this:
<a onclick="exportGridExcel()"><span class="accordion-download"><i class="fa fa-file-excel-o" title="Download Excel" aria-hidden="true"></i></span></a>
A more expanded version of the html is:
<div class="lang-switch-wrapper lang-switch-inverse-wrapper">
<div class="lang-switch">
<ul>
<li class="dropdown">
<a href="#" class="dropdown-toggle lang-lable" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
<span class=" hidden-xs">English</span>
<span class="hidden-lg hidden-md hidden-sm">EN</span>
<img src="/etc/designs/wbrrdesign/clientlibs-wbrredsign/img/angle-down-gray.svg" alt="dropdown"></a>
<ul class="dropdown-menu dropdown-item">
<li>Español</li>
</ul>
</li>
</ul>
</div>
</div>
Then some other stuff before going to the button group and button I want:
<div class="button-group">
<button onclick="onModifyQuery()" type="button" class="btn">Modify Query</button>
<a onclick="exportGridExcel()"><span class="accordion-download"><i class="fa fa-file-excel-o" title="Download Excel" aria-hidden="true"></i></span></a>
<a title="Undo to column removal" onclick="restoreColumn()" class="toggle-btn primary-light-blue-btn"><i class="fa fa-circle-o-notch" aria-hidden="true"></i></a>
</div>
Part of my confusion is inexperience with this html with multiple classes and "i class".
EDIT:
If I try something like:
WebDriverWait(driver,300).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "a[onclick='exportGridExcel()']"))).click()
Then I get the error:
ElementClickInterceptedException: element click intercepted: Element <a onclick="exportGridExcel()">...</a> is not clickable at point (772, 11). Other element would receive the click: <div class="lang-switch-wrapper lang-switch-inverse-wrapper">...</div>
The problem is that your page is automatically scrolled up and the excel download button is probably hidden by the top banner that contains the language selector. When Selenium tries to click on the excel download button, it finds the language selector instead.
I would suggest you to scroll the page up till the whole data table is visible
You can use something like this. Press HOME key to go to top of the page
from selenium.webdriver.common.keys import Keys
...
...
element = WebDriverWait(driver,300).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "a[onclick='exportGridExcel()']")))
element.send_keys(Keys.CONTROL + Keys.HOME)
element.click()
Ideally clicking on the element <a onclick="exportGridExcel()"> as per your code trials inducing WebDriverWait for the elementToBeClickable() should have worked.
However, there seems to be a decendant <span>. So you can use either of the following locator strategies:
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "a[onclick^='exportGridExcel'] > span.accordion-download"))).click()
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//a[starts-with(#onclick, 'exportGridExcel')]/span[#class='accordion-download']"))).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
In another approach you can also use JavascriptExecutor as follows:
Using CSS_SELECTOR:
element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "a[onclick^='exportGridExcel'] > span.accordion-download")))
driver.execute_script("arguments[0].click();", element)
Using XPATH:
element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//a[starts-with(#onclick, 'exportGridExcel')]/span[#class='accordion-download']")))
driver.execute_script("arguments[0].click();", element)

Selenium, python: How to click on the dropdown element and select an option in this case (dynamic html page)?

I am using Selenium and Python to try to click on an element (1) on a page and then click on a value that pops up (2) when I click on the element. See pictures below. You need a user account to access the web page so I try to describe my issue as best as I can.
The web page is using dynamic html so elements or attributes of elements can come and go on the page depending on what you click/hover etc. But here is the html for the element when nothing is clicked or hovered.
<div class="sc-evcquM bKiprl">
<div class="sc-fYOAOY ZfWGj">
<div class="MuiFormControl-root sc-cRgdMP cLaBkn MuiFormControl-fullWidth">
<div
class="MuiAutocomplete-root MuiAutocomplete-hasPopupIcon"
role="combobox"
aria-expanded="false"
name="icd_code"
data-testid="autocomplete-icd_code"
>
<div
class="MuiFormControl-root MuiTextField-root MuiFormControl-fullWidth"
>
<label
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-outlined"
data-shrink="false"
for="autocomplete-icd_code"
id="autocomplete-icd_code-label"
>Diagnoskod</label
>
<div
class="MuiInputBase-root MuiOutlinedInput-root MuiAutocomplete-inputRoot MuiInputBase-fullWidth MuiInputBase-formControl MuiInputBase-adornedEnd MuiOutlinedInput-adornedEnd"
>
<input
aria-invalid="false"
autocomplete="off"
id="autocomplete-icd_code"
type="text"
class="MuiInputBase-input MuiOutlinedInput-input MuiAutocomplete-input MuiAutocomplete-inputFocused MuiInputBase-inputAdornedEnd MuiOutlinedInput-inputAdornedEnd"
aria-autocomplete="list"
autocapitalize="none"
spellcheck="false"
value=""
/>
<div class="MuiAutocomplete-endAdornment">
<button
class="MuiButtonBase-root MuiIconButton-root MuiAutocomplete-popupIndicator"
tabindex="-1"
type="button"
aria-label="Open"
title="Open"
style=""
>
<span class="MuiIconButton-label"
><svg
class="MuiSvgIcon-root"
focusable="false"
viewBox="0 0 24 24"
aria-hidden="true"
>
<path d="M7 10l5 5 5-5z"></path></svg
></span>
</button>
</div>
<fieldset
aria-hidden="true"
class="jss9 MuiOutlinedInput-notchedOutline"
>
<legend class="jss11"><span>Diagnoskod</span></legend>
</fieldset>
</div>
</div>
</div>
</div>
</div>
</div>
I try to click on the dropdown button (anchored to the right of the field).
When I click the "dropdown" button (it is not actually a dropdown with select elements) the html changes to this:
As I hover over the first value in the dropdown list an attribute and value of aria-activedescendent=autocomplete-icd_code-option-0 is added to the element input element. When I hover over the second option the value of the attribute changes to autocomplete-icd_code-option-1 and so on.
The dropdown options are not element itself as far as I know. Because I can't found them with the inspector tool. As soon as I press the inspector tool the drop down menu disappears, so they are not visible in the html source.
Here is my relevant code:
import tkinter as tk
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver import Firefox
from selenium.webdriver.common.by import By
class MainApp(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.parent = parent
self.driver = Firefox() #the url needs a login so I can't give you that.
#XPATH BY LOCATORS
patient_notes_to_sign_icd_code = (By.XPATH, "//div[#name='icd_code']//button")
patient_notes_to_sign_icd_code2 = (By.XPATH, "//input[#id='autocomplete-icd_code']")
#Try 1
self.click(patient_notes_to_sign_icd_code)
#Try 2.
icd_el = self.get_element(patient_notes_to_sign_icd_code2)
self.driver.execute_script("arguments[0].setAttribute('aria-activedescendent', 'autocomplete-icd_code-option-0');", icd_el)
def click(self, by_locator):
"""Clicks on the element"""
self.wait = WebDriverWait(self.driver, 5)
self.wait.until(EC.element_to_be_clickable(by_locator)).click()
def send_keys(self, by_locator, value):
"""clear field and send keys to the element"""
self.wait = WebDriverWait(self.driver, 5)
self.wait.until(EC.presence_of_element_located(by_locator)).clear()
def main():
root = tk.Tk()
app = MainApp(root)
app.pack()
root.mainloop()
if __name__ == "__main__":
main()
Try 1 gives me the following error:
selenium.common.exceptions.ElementClickInterceptedException: Message: Element <button class="MuiButtonBase-root MuiIconButton-root MuiAutocomplete-popupIndicator" type="button"> is not clickable at point (1197,1603) because another element <div id="menu-" class="MuiPopover-root"> obscures it
I can't neither find the the element <div id="menu-" class="MuiPopover-root"> with the inspector tool.
Try 2 changes the attribute and value but it will not select the actual corresponding option in the list.
How can I achieve to click on the dropdown button and then click on a dropdown option using Selenium? Help very much appreciated.

How to click available button which refuses the click?

I'm working on automation of one website. My problem is that the button which is visible in my selenium (simply prints out) stopped working after recent update. Eventho I can see it, I cannot click it. I've noticed that it has started to have dynamic id selector, but class stays stable. What that can be ? Is there any other way to click it ?
<div>
<div>
<div class="pull-left middle-col-4">
<!---->
</div>
<div class="pull-left middle-col-4">
<!---->
</div>
</div>
<button tabindex="-1" id="exit-button-ZpyYaHCdmZ5jnmaamGhjaJjFcsVrmJOUcZWVaZlsaGlolpOaZg" class="btn btn-inverse btn-large pull-right">Wyjście</button>
</div>
To Click on the button induce WebDriverWait and element_to_be_clickable() And following locator strategy.
By Css Selector:
WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"button.btn.btn-inverse.btn-large.pull-right"))).click()
By Xpath:
WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.XPATH,"//button[#class='btn btn-inverse btn-large pull-right' and starts-with(#id,'exit-button-')][text()='Wyjście']"))).click()
You need to import followings to execute above code.
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
Please find below solution to click exit button if id is dynamic
1. Xpath and contains method
button=driver.find_element_by_xpath("//button[contains(text(), 'Wyjście')]")
button.click()
2. Class name
element = driver.find_element_by_class_name("btn btn-inverse btn-large pull-right")
element.click()

How to fix "Element not interactable" Selenium error in Python?

I was trying to click a popup button and my code shows the error:
"selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable".
I have searched but could not find the solution which works for me with the popup buttons.
Image for clicking show 10 rows and displaying the pop-up boxThe attached image is the desired result and 'Show 10 rows' is behind it and lightly seen.
I have this in my HTML code and need to click on the button.
<div class="table-responsive">
<ul class="nav nav-tabs">
<li class="active"><a data-toggle="tab" id="loadsur" href="#Section" aria-expanded="true">LoadSurvey</a></li>
</ul>
<div class="container-fluid">
<div class="row">
<div class="col-md-12" style="margin-left: -10px;">
<div class="table-responsive">
<div id="myDataTable25_wrapper" class="dataTables_wrapper no-footer"><div class="dt-buttons">
<button class="dt-button buttons-csv buttons-html5" tabindex="0" aria-controls="myDataTable25">
<span>Csv</span></button>
<button class="dt-button buttons-excel buttons-html5" tabindex="0" aria-controls="myDataTable25">
<span>Excel</span></button>
<button class="dt-button buttons-collection buttons-page-length" tabindex="0" aria-controls="myDataTable25" aria-haspopup="true">
<span>Show 10 rows</span></button>
</div>
</div>
</div>
</div>
</div>
In Python I tried this:
def single_meter(i=0):
browser=webdriver.Chrome('C:\Webdrivers\chromedriver.exe')
for row in range (5,10):
browser.get('http://#link'+consumer_ID+'?reportrange=21%2F07%2F2018-25%2F08%2F2019')
Show10 = find_element_by_xpath("//button[#class='dt-button buttons-collection buttons-page-length']//span[contains(text(),'Show 10 rows')]")
Show10.click()
I expect to click this button which causes a popup button to appear.
It might be in an iframe.
Try first to find the iframe and switch to it.
browser = webdriver.Chrome()
browser.get("http:/link")
frame_id = 'frame'
wait = WebDriverWait(browser, 10)
wait.until(EC.frame_to_be_available_and_switch_to_it((By.ID, frame_id)))
Then try clicking on the button.
Show10 = wait.until(expected_conditions.element_to_be_clickable((By.XPATH, "//button[#class='dt-button buttons-collection buttons-page-length']//span[contains(text(),'Show 10 rows')]")))
Show10.click()
I got a solution to this problem. The error was with the link in the xpath. I later copied and pasted from the html and the code now looks this:
Show10 = find_element_by_xpath("//*[#id='myDataTable2_wrapper']/div[1]/button[7]/span")
Show10.click()
And it works fine. Thank all for your help.
Change the xpath with :
//button[#class='dt-button buttons-collection buttons-page-length']//span[contains(text(),'Show 10 rows')]
Try use WebDriverWait for make sure the element exist, and add expected_conditions until the element clickable.
Import this :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions
Try this :
wait = WebDriverWait(singlemeter, 10)
Show10 = wait.until(expected_conditions.element_to_be_clickable((By.XPATH, "//button[#class='dt-button buttons-collection buttons-page-length']//span[contains(text(),'Show 10 rows')]")))
Show10.click()
Or use ActionChains, import this :
from selenium.webdriver import ActionChains
Try this :
ActionChains(singlemeter).move_to_element(Show10).click(Show10).perform()

Unable to click on element with link in selenium python

I am trying to interact with a sign out button but I just can't seem to click on it using link text or xpath.
I have tried following these answers with no luck:
Why Cant I Click an Element in Selenium?
Unable to click link using selenium webdriver in python
Here is my code:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from xatu.tests.base import login
from xatu.tests.bagon import BagonBaseTestCase
class BasicTestCase(BagonBaseTestCase):
#login
def test_logout(self):
self._wait_until_id_presents("quotes-form")
WebDriverWait(self, 10).until(
EC.presence_of_element_located((By.XPATH, "//a[#href='/login/clear']/i")))
self.browser.find_element_by_xpath("//a[#href='/login/clear']/i").click()
self.implicitly_wait(2)
self._title_check("Login")
The first line under test_logout calls a function that waits for a certain element to appear on the webpage so I can see that the page has been loaded. Then I try to click the sign out button.
This is the HTML(element is at class="btn" href="/login/clear"):
<div class="navbar navbar-fixed-top screen-only">
<div class="navbar-inner">
<div class="container-fluid">
<a class="btn btn-navbar" data-target=".nav-collapse" data-toggle="collapse">
<a class="brand" href="/">
<div class="nav-collapse collapse">
<ul class="nav">
<p class="pull-right" style="margin-top: 4px; margin-left: 4px;">
<a class="btn" href="/login/clear">
<i class="icon-off"/>
Sign out
</a>
</p>
<p class="navbar-text pull-right"> Logged-in as D. V. Lauper </p>
</div>
<!--/.nav-collapse -->
</div>
</div>
</div>
When I try finding by link_text, the element can't be found. Running this code gives me a stacktrace error saying:
ElementNotVisibleException: Message: Element is not currently visible and so may not be interacted with
Edit: I've tried Saifur's answer and updated my code to his answer but now I get: AttributeError: 'BasicTestCase' object has no attribute 'find_element'. I've tried changing "self" to "self.browser" as an argument in WebDriverWait() but I would then get my original error.
Use explicit wait and relativexpath
like //a[#href='/login/clear']/i
from xatu.tests.base import login
from xatu.tests.bagon import BagonBaseTestCase
class BasicTestCase(BagonBaseTestCase):
#login
def test_logout(self):
self._wait_until_id_presents("quotes-form")
WebDriverWait(self, 10).until(
EC.presence_of_element_located((By.XPATH, "//a[#href='/login/clear']/i")))
self.browser.find_element_by_xpath("//a[#href='/login/clear']/i").click()
self.browser.implicitly_wait(2)
self._title_check("Login")
You need an explicit wait. See docs. Example code:
element = WebDriverWait(driver, 30).until(EC.visibility_of_element_located((By.XPATH,'//a[#href="/login/clear"]')))
And then just click the element.
element.click()
Note I added my answer b/c -- in my tests at least -- you don't need to worry about the italics tag. That's for the text, not the button -- and you're not clicking the text. So find By.XPATH and select a unique attribute (i.e., the href in this case and very likley not the class attr), and then click your element.
EDIT:
please try this line:
element = WebDriverWait(self.browser, 30).until(EC.visibility_of_element_located((By.XPATH,'//a[#class="btn" and #href="/login/clear"]')))

Categories