Cannot click on radio button in fieldset - python

I am using python with selenium to automate some process but I am having problems to click a radio button. This is the situation:
Code:
<div class="cart">
<form method="post" id="pmntFrm" name="chsPmntRt" action="/cart" class="form-validate">
<fieldset>
<div class="payment-field">
<input onchange="load('payment', 1)" type="radio" name="paymentmethod_id" id="payment_id_1" value="123">
<label for="payment_id_1" class="">
//foo
</label>
<input onchange="load('payment', 2)" type="radio" name="paymentmethod_id" id="payment_id_2" value="456">
<label for="payment_id_2" class="">
//foo
</label>
</div>
</fieldset>
</form>
</div>
I have tried click on it using:
driver.find_element_by_xpath(".//input[#type='radio' and #value='1']").click()
and I receive this error Message=Message: element not interactable
Also I read in other thread that maybe the problem is that the fieldset is in a different but is not.
I really apreciate if someone can help me with this topic.
Thank you and have a nice day!

To wait for the element to be clickable induce a webdriver wait and then click. Also don't use . it's for child elements not root driver.
wait = WebDriverWait(driver, 10)
wait.until(EC.element_to_be_clickable((By.XPATH,"//input[#type='radio' and #value='1']"))).click()
Or the label
wait.until(EC.element_to_be_clickable((By.XPATH,"//label[#for='payment_id_1']"))).click()
Import
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

Related

python selenium checkbox nested label and input

I'm trying to get a checkmark on "Minutes (1993-Present)" from the federal reserve's document filter page with selenium.
https://www.federalreserve.gov/monetarypolicy/materials/
This is my code. I have tried the following ways, I keep get "Message: no such element: Unable to locate element: Unable to locate element"
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver import ActionChains
import time
PATH = "C:\Program Files (x86)\chromedriver.exe"
driver = webdriver.Chrome(PATH)
driver.get("https://www.federalreserve.gov/monetarypolicy/materials/")
link = driver.find_element_by_xpath('//*[#id="article"]/app-root/div/ng-component/div[1]/div/div/form/app-doc-types/div[2]/div/div/div[7]/label/input').click()
link = driver.find_element_by_xpath("//div[#class='form-group']/div/div[7]/label/input[contains(text(), 'Minutes (1993-Present)')]").click()
link = driver.find_element_by_css_selector('div.form-group div:nth-child(7) label input').click()
I sliced some parts of the HTML below.
<app-doc-types><div class="eventSearch__label">
<p class="form-control-static">
<strong><legend class="ng-binding">Type:</legend></strong>
</p>
</div>
<div class="eventSearch__inputs">
<div class="form-group">
<div class="row">
<div class="col-lg-6">
<label>
<input type="checkbox" class="ng-untouched ng-pristine ng-valid">
Agendas
</label>
</div><div class="col-lg-6">
<label>
<input type="checkbox" class="ng-untouched ng-pristine ng-valid">
Beige Books/Redbooks
</label>
</div><div class="col-lg-6">
<label>
<input type="checkbox" class="ng-untouched ng-pristine ng-valid">
Bluebooks
</label>
</div><div class="col-lg-6">
<label>
<input type="checkbox" class="ng-untouched ng-pristine ng-valid">
Chairman's FOMC Press Conferences
</label>
</div><div class="col-lg-6">
<label>
<input type="checkbox" class="ng-untouched ng-pristine ng-valid">
Greenbooks
</label>
</div><div class="col-lg-6">
<label>
<input type="checkbox" class="ng-untouched ng-pristine ng-valid">
Memos
</label>
</div><div class="col-lg-6">
<label>
<input type="checkbox" class="ng-valid ng-dirty ng-touched">
Minutes (1993-Present)
</label>
</div><!---->
</div>
</div>
</div>
</app-doc-types>
It takes some time for website to load. I added time.sleep(2) after opening the webpage with driver.
Your first XPath should work, however it's extremely dependent on the structure of the page, therefore it may not work due to a little modification in the HTML structure of the page.
Second XPath won't work, and actually you do not need to add text() check to the end of your path. This should work:
//div[#class='form-group']/div/div[7]/label/input
CSS Selector path should work, however your css path can be easily simplified. Check my solution below:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver import ActionChains
import time
driver = webdriver.Chrome()
driver.get("https://www.federalreserve.gov/monetarypolicy/materials/")
time.sleep(2)
link = driver.find_element_by_css_selector('.col-lg-6:nth-of-type(7) input').click()
Alternatively, you can use an explicit wait.
driver.get("https://www.federalreserve.gov/monetarypolicy/materials/")
element = WebDriverWait(driver , 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR , '.col-lg-6:nth-of-type(7) input')))
element.click()
you can use playwright
import asyncio
from playwright.async_api import async_playwright
async def run(playwright):
chromium = playwright.chromium # or "firefox" or "webkit".
browser = await chromium.launch()
page = await browser.new_page()
await page.goto("https://www.federalreserve.gov/monetarypolicy/materials/")
await page.click('xpath=/html/body/div[3]/div[2]/div[2]/app-root/div/ng-component/div[1]/div/div/form/app-doc-types/div[2]/div/div/div[7]/label/input')
await browser.close()
async def main():
async with async_playwright() as playwright:
await run(playwright)
asyncio.run(main())

Clicking radio button Selenium/Python

I am creating a Linkedin job scraper in order of most recent, but I am finding it really difficult to target the 'Most recent' radio button as shown below.
So far, the 'Most relevant' menu is clicked on, but will not click on 'Most recent'. Help would be appreciated I can't seem to figure this one out :/
Code snippet
driver.get('https://uk.linkedin.com/jobs/bioinformatics-jobs?position=1&pageNum=0')
driver.implicitly_wait(10)
driver.find_element_by_class_name('collapsible-dropdown').click() # Clicks 'sort-by' menu.
driver.find_element_by_xpath('//*[#id="sortBy-0"]').click() # Error!
HTML
<button aria-expanded="true" aria-label="Sort By filter. Most relevant filter is currently applied. Clicking this button displays all Sort By filter options." class="filter-button filter-button--selected dropdown-to-modal__button collapsible-dropdown__button" data-tracking-control-name="public_jobs_sortBy" type="button">
Most relevant
<icon class="filter-button__icon"></icon>
</button>
<div class="collapsible-dropdown__list no-focus-ring" tabindex="-1">
<!-- -->
<fieldset class="filter-values-container">
<legend class="filter-values-container__legend sr-only">Sort By filter options</legend>
<div class="filter-values-container__filter-values">
<div class="filter-values-container__filter-value">
<input checked="" form="jserp-filters" id="sortBy-0" name="sortBy" type="radio" value="R"/>
<label for="sortBy-0">
Most relevant
</label>
</div>
<div class="filter-values-container__filter-value">
<input form="jserp-filters" id="sortBy-1" name="sortBy" type="radio" value="DD"/>
<label for="sortBy-1">
Most recent
</label>
</div>
</div>
</fieldset>
<button aria-label="Apply filters" class="filter__submit-button" data-tracking-control-name="public_jobs_sortBy" form="jserp-filters" type="submit">
Done
</button>
</div>
<div class="filter-values-container__filter-value">
<input id="sortBy-1" form="jserp-filters" name="sortBy" value="DD" type="radio">
<label for="sortBy-1">
Most recent
</label>
</div>
</div>
</fieldset>
<button class="filter__submit-button" aria-label="Apply filters" form="jserp-filters" data-tracking-control-name="public_jobs_sortBy" type="submit">
Done
</button>
</div>
try this
driver.find_element_by_xpath('//*[#id="jserp-filters"]/ul/li[1]/div/div/div/fieldset/div/div[2]').click()
your xpath was incomplete
Things to be noted down :
You need Explicit waits.
JS intervention.
Reliable locators.
Prefer CSS over Xpath.
Code :-
driver = webdriver.Chrome(driver_path)
driver.maximize_window()
driver.get("https://uk.linkedin.com/jobs/bioinformatics-jobs?position=1&pageNum=0")
WebDriverWait(driver,20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.collapsible-dropdown>button[data-tracking-control-name='public_jobs_sortBy']"))).click()
driver.execute_script("arguments[0].click();", driver.find_element_by_css_selector("input[value='DD']"))
Imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

Dropdown menus in python / selenium

Trying to autofill a form using python and selenium. Dropdown menu html is:
<select id="typeOfTeacher" class="chosen-select-no-single ng-untouched ng-dirty ng-valid-parse ng-valid ng-valid-required" required="" ng-class="{ 'has-error' : positionDetailForm.typeOfTeacher.$invalid && !positionDetailForm.typeOfTeacher.$pristine }" ng-change="vm.setRequired()" tabindex="-1" ng-model="vm.data.typeOfTeacher" name="typeOfTeacher" data-placeholder="Select" style="display: none;">
<option value="" disabled="" selected="">Select</option>
<option class="ng-binding ng-scope" value="1" ng-repeat="teacherType in vm.teacherTypes">No position at the moment</option>
<option class="ng-binding ng-scope" value="2" ng-repeat="teacherType in vm.teacherTypes">Supply</option>
<option class="ng-binding ng-scope" value="3" ng-repeat="teacherType in vm.teacherTypes">Permanent</option>
</select>
Python code is:
elem = Select(browser.find_element_by_id('typeOfTeacher'))
elem.select_by_value("1")
Error is "element is not currently visible and may not be interacted with".
I have not used the python Select method, but I would guess that the error message means that the menu is not being opened, and therefore an element in the menu is still hidden and cannot be interacted with.
Try something like this:
element = driver.find_element_by_id('typeOfTeacher').click()
driver.find_element_by_css_selector("[value=\"1\"]").click()
This would work
element = driver.find_element_by_id('typeOfTeacher').click()
element.find_element_by_xpath(".//option[#value='1']").click()
It looks like timing issue. You should try using Waits.
I would suggest you, use WebDriverWait to wait until dropdown visible before interaction as below :-
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
element = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.ID, "typeOfTeacher")))
select = Select(element)
select.select_by_value("1")

Selenium with Python: First instance of the element is identified but the next occurance is ElementNotVisibleException

I have the following Selenium Test for Python/Django application:
class EmailRecordsTest(StaticLiveServerTestCase):
def test_can_store_email_and_retrieve_it_later(self):
self.browser.get(self.live_server_url)
emailbox = self.browser.find_element_by_xpath("//form[#class='pma-subscribe-form']/input[1]")
self.assertEqual(emailbox.get_attribute("placeholder"), 'Enter your Email')
print("tested until here")
print("The placeholder: ", emailbox.get_attribute("placeholder"))
print(emailbox)
emailbox.send_keys('vio#mesmerizing.com')
First occurance of emailbox is clearly identified as seen from the print runs and assert Equal for placeholder. The last instance of emailbox.send_keys throws following error:
selenium.common.exceptions.ElementNotVisibleException: Message:
Element is not currently visible and so may not be interacted with
Cannot find why the same element become Not Visible when using with send_keys.
The Html code being tested is as below:
<!-- Start footer -->
<footer id="pma-footer">
<!-- start footer top -->
<div class="pma-footer-top">
<div class="container">
<div class="pma-footer-top-area">
<div class="row">
<div class="col-lg-3 col-md-3 col-sm-3">
<div class="pma-footer-widget">
<h4>News letter</h4>
<p>Get latest update, news & offers</p>
<form class="pma-subscribe-form">
<input id="subscribe-email" type="email" placeholder="Enter your Email">
<button class="btn btn-danger btn-md" type="submit">Subscribe!</button>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- end footer top -->
Kindly help.
Actually find_element returns element which would be present on the DOM no matter it's visible or not and you can get attribute of this element as well but send_keys does an action on element and selenium does action only visible element, So you need to be sure before doing action on element that it's visible using WebDriverWait as below :-
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 10)
emailbox = wait.until(EC.visibility_of_element_located((By.ID, "subscribe-email")))
#do your all stuff before send keys
# now use send_keys
emailbox.send_keys('vio#mesmerizing.com')
Edited :- If you are still unable to interact with element try using execute_script() to set value as below :-
emailbox = wait.until(EC.presence_of_element_located((By.ID, "subscribe-email")))
#do your all stuff before send keys
# now use execute_script
driver.execute_script("arguments[0].value = 'vio#mesmerizing.com'", emailbox)
Another option which worked in this case is that you scroll to the specific element (which was at the bottom of the page)and then use send_keys it works.
emailbox = self.browser.find_element_by_xpath("//form[#class='mu-subscribe-form']/input[1]")
self.browser.execute_script("window.scrollTo(0, document.body.scrollHeight);")
emailbox.send_keys('vio#mesmerizing.com')

Selenium Python. Click on radio-button does not any affect

First of all sorry for my english.
I have a page with radio-buttons.
Here is the html code of the button I want to click.
<label class="radio-button__radio radio-button__radio_side_right radio-button__radio_next-for-pressed_yes" for="uniq13988671">
<input id="uniq13988671" class="radio-button__control" type="radio" value="1000">
<span class="radio-button__text">все</span>
</label>
my python script with selennium:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver import ActionChains as ac
driver = webdriver.Firefox()
driver.get("url_with_elements")
driver.implicitly_wait(20)
my_button = driver.find_element_by_css_selector("input[value='1000']")
ac(driver).move_to_element(my_button).perform()
my_button.click()
This button should reload the page with all elements (at least 1000) but it doesn't work.
Ther's no any errors and element respond on method .get_attribute('id')
>>> my_button.get_attribute('id')
u'uniq13988671'
here is full html code of row with radio-buttons:
<td class="b-layout-table__cell">
<div class="b-banners-per-page i-bem b-banners-per-page_js_inited" onclick="return {"b-banners-per-page":{"urlObject":{"hash":"","query":{"cmd":"setPageSize","subcmd":"showCamp","cid":"8868621","ulogin":"*mylogin*"},"file":"main.NWluTm99mAw1N.pl","directory":"/registered/","path":"/registered/main.NWluTm99mAw1N.pl","relative":"/registered/main.NWluTm99mAw1N.pl","port":"","host":"direct.yandex.ru","password":"","user":"","userInfo":"","authority":"direct.yandex.ru","protocol":"https","source":"https://direct.yandex.ru/registered/main.NWluTm99mAw1N.pl"},"optimalBannersOnPage":20}}">
<span class="b-banners-per-page__title">Объявлений на странице: </span>
<div class="b-banners-per-page__buttons">
<span class="radio-button radio-button_size_s radio-button_theme_normal i-bem radio-button_js_inited" onclick="return {"radio-button":{}}">
<label class="radio-button__radio radio-button__radio_side_left" for="uniq13988675">
<label class="radio-button__radio radio-button__radio_checked_yes radio-button__radio_pressed_yes" for="uniq13988674">
<label class="radio-button__radio radio-button__radio_next-for-pressed_yes" for="uniq13988673">
<label class="radio-button__radio" for="uniq13988672">
<label class="radio-button__radio radio-button__radio_side_right" for="uniq13988671">
<input id="uniq13988671" class="radio-button__control" type="radio" value="1000">
<span class="radio-button__text">все</span>
</label>
</span>
</div>
</div>
</td>
Here's the image of how it looks like "step by step"
http://i.imgur.com/LYqKyqx.png
I'm looking at other questions but they don't help me.
Thanks for any help.
ADD: If i use Selenium IDE addon for firefox. this button clicked fine.
If need more info - please ask.
I've handle my problem use construction like that:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver import ActionChains as ac
driver = webdriver.Firefox()
driver.get("url_with_elements")
driver.implicitly_wait(20)
# my_button = driver.find_element_by_css_selector("input[value='1000']")
button_parent = driver.find_element_by_xpath("//td[2]/div/div/span/label[5]")
ac(driver).move_to_element(button_parent).perform()
button_parent.click()
ac(driver).send_keys(Keys.SPACE).perform()

Categories

Resources