seleniumpython dropdown list div - python

i whould like to select the element "aout" for example on the folloing dropdown list with python selenium
<div class="questionDropdownContainer inlineBlock isActive" id="dob2_m">
<span class="questionDropdownPlaceholder" data-val="3" id="dateMonth" style="color: rgb(0, 0, 0);">mars</span>
<span class="iconDropdown inlineBlock valignMiddle"></span>
<div class="questionDropdownOptions ps-container ps-active-x ps-active-y isActiveSurveyDropDown" style="display: block; overflow: hidden;">
<span class="option-1-month" data-id="1">janvier</span>
<span class="option-1-month" data-id="2">février</span>
<span class="option-1-month selected" data-id="3">mars</span>
<span class="option-1-month" data-id="4">avril</span>
<span class="option-1-month" data-id="5">mai</span>
<span class="option-1-month" data-id="6">juin</span>
<span class="option-1-month" data-id="7">juillet</span>
<span class="option-1-month" data-id="8">août</span>
<span class="option-1-month" data-id="9">septembre</span>
<span class="option-1-month" data-id="10">octobre</span>
<span class="option-1-month" data-id="11">novembre</span>
<span class="option-1-month" data-id="12">décembre</span>
<div class="ps-scrollbar-x-rail" style="width: 120px; left: 0px; bottom: 3px;"><div class="ps-scrollbar-x" style="left: 0px; width: 110px;"></div></div><div class="ps-scrollbar-y-rail" style="top: 0px; height: 234px; right: 3px;"><div class="ps-scrollbar-y" style="top: 0px; height: 116px;"></div></div></div>
<input type="hidden" name="date_m" value="4">
</div>
When I try this code…
driver.find_element_by_id("dob2_m").click()
driver.find_element_by_id("dob2_m").find_element_by_xpath('//*[#data-id="8"]').click()
I get this error…
error script picture
How to do it ?
Help me please
Thank you

The error snippet clearly says the error occurs when webdriver tries to interact with element with class="option-1-day". But this element is not present in the code you have shared. So i assume, you are facing issue while trying to select date from dropdown.
1.Before clicking dropdown element, try to add wait statement
wait = WebDriverWait(driver, 10)
element = wait.until(EC.element_to_be_clickable((By.ID, 'someid')))
2. It will occur when the webelement you trying to click, located at end of dropdown. So it can only clickable once scrolling it down.
Actions action = new Actions(driver);
action.moveToElement(element);

Use select class for handling dropdown.
s1= Select(driver.find_element_by_id('id_of_your_element'))//in this case it would be dob2_m
s1.select_by_visible_text('janvier')
Ignore formatting using mobile to answer.
Option 2
Use javascriptexecutor to scroll and click on element
ele= self.web_driver.find_element_by_xpath('SOME_XPATH')
coordinates = ele.location_once_scrolled_into_view
self.web_driver.execute_script('window.scrollTo({}, {});'.format(coordinates['x'], coordinates

You have to use ActionChains.
When you call methods for actions on the ActionChains object, the actions are stored in a queue in the ActionChains object. When you call perform(), the events are fired in the order they are queued up.
More information.
Here is an example:
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.ui import Select
...#navigate to page
el=driver.find_element_by_id("bxFormPesquisa") #here I get the dropdown element
ActionChains(driver).click(el).perform()
select = Select(driver.find_element_by_name('bxFormPesquisa')) #again
select.select_by_visible_text('AL') #it is the text in dropdown list
#dropdown should be selected with value from line above

Related

Selenium webdriver can't find visible element

I have a problem with finding element on a webpage. It's a popup window with a confirmation [NO]/[YES]. Selenium can find a parent of a buttons but not a button itself.
Popup window view
HTML block of code:
<div tabindex="-1" role="alertdialog" style="position: fixed; height: auto; width: 300px; top: 188.5px; left: 800px; max-width: 100%;"
class="ui-dialog ui-dialog--notification ui-dialog--modern ui-widget ui-widget-content ui-front ui-dialog-buttons ui-draggable"
aria-describedby="ui-id-3" aria-labelledby="ui-id-4">
<div class="ui-dialog-titlebar ui-corner-all ui-widget-header ui-helper-clearfix ui-draggable-handle"></div>
<div class="ui-dialog-content ui-widget-content" style="width: auto; min-height: 0px; max-height: none; height: 32px;">
<div class="a-AlertMessage">
<div class="a-AlertMessage-body">
<div class="a-AlertMessage-details" id="ui-id-3">Czy chcesz wygenerować pozycje dla całej dostawy?</div>
</div>
</div>
</div>
<div class="ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"><div
class="ui-dialog-buttonset">
<button type="button" class="ui-button ui-corner-all ui-widget">Nie</button>
<button type="button" class="js-confirmBtn ui-button ui-corner-all ui-widget ui-button--hot">Tak</button>
</div>
</div>
</div>
Here is a code snippet that selenium can't find and gives an error 'Unable to locate element':
pop_up_yes_button = driver.find_element(By.XPATH, '//*[#id="t_PageBody"]/div[15]/div[3]/div/button[2]').click()
Parent is avaible for selenium without a problem:
driver.find_element(By.XPATH, '//*[#id="t_PageBody"]/div[15]')
I also tried WebDriverWait and ExpectedConditions but it gives TimeoutException:
WebDriverWait(driver, 15).until(EC.presence_of_element_located((By.XPATH, '//*[#id="t_PageBody"]/div[15]/div[3]/div/button[2]'))).click()
As you said that it is a popup window, it is very likely that the button is in an iFrame. You have to wait until the iFrame loads and then search the element again.
Luckily, selenium has a built in function for dealing with iFrames:
your_button = WebDriverWait(driver,
20).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,'//*[#id="t_PageBody"]/div[15]/div[3]/div/button[2]')))
your_button.click()
Don't just copy and paste this code, understand this thing and implement it.

How do I make selenium find an element whos Id changes

So I am automating with selenium and running into an issue where everytime I refresh a page, the element ID changes, no matter if I copy XPATH, CSS Selector, ID, they all have a number in them that changes.
so the code I'm using is simple, I just want to click the button which I can accomplish with
browser.find_element(by=By.CSS_SELECTOR, value='*VALUE HERE*').click()
But I don't know what to put as the value.
Here is the HTLM code
<a class="x4-tab x4-unselectable x4-box-item x4-tab-default x4-noicon x4-tab-noicon x4-tab-default-noicon x4-top x4-tab-top x4-tab-default-top x4-tab-after-title x4-active x4-tab-active x4-tab-default-active x4-top-active x4-tab-top-active x4-tab-default-top-active" hidefocus="on" unselectable="on" id="tab-1965" tabindex="0" data-ui-comp-name="wm-np-tab-wrkstn" style="right: auto; left: 66px; margin: 0px; top: 0px;">
<span id="tab-1965-btnWrap" role="presentation" class="x4-tab-wrap" unselectable="on">
<span id="tab-1965-btnEl" class="x4-tab-button" role="presentation">
<span id="tab-1965-btnInnerEl" class="x4-tab-inner x4-tab-inner-center"
unselectable="on">Workstations</span>
<span role="presentation" id="tab-1965-btnIconEl" class="x4-tab-icon-el " unselectable="on"
style="">
</span>
</span>
</span>
</a>
If you look at the HTML, anywhere you see that number 1965, that number will change if the page is refreshed. How do I make selenium find this element no matter what that number is?
Also, not sure if this matters but this is all in an iframe which I have selenium target by using
frame1 = browser.find_element(by=By.CLASS_NAME, value='defaultView')
browser.switch_to.frame(frame1)
Also, another problem is that HTML code is almost identical to other buttons, the only differences between the buttons is that number (that changes) and where is says "Workstations". Here is an example of another button that is next to it, this one is for servers.
<span id="tab-1964-btnWrap" role="presentation" class="x4-tab-wrap" unselectable="on">
<span id="tab-1964-btnEl" class="x4-tab-button" role="presentation">
<span id="tab-1964-btnInnerEl" class="x4-tab-inner x4-tab-inner-center"
unselectable="on">Servers</span>
<span role="presentation" id="tab-1964-btnIconEl" class="x4-tab-icon-el"
unselectable="on" style="">
</span>
</span>
</span>
</a>
You can use XPath for this:
browser.find_element(by=By.XPATH, value="//span[starts-with(#id, 'tab-') and contains(#id, '-btnEl')]").click()

Selenium + Python: Print the text attribute of an element

I would like to navigate through a website, find an element and print it.
Python version: 3.10; Selenium Webdriver: Firefox; IDE: PyCharm 2021.3.2 (CE);
OS: Fedora 35 VM
I am able to navigate to the appropriate page where the text is generated in a drop down menu.
When I locate the element by CSS Selector and attempt to print it, the output does print the text "None".
I would like it to print the Plan Name which in this case is "Dual Complete Plan 1".
The element is not always present so I also need to catch any exceptions.
The relevant HTML code of the element I am trying to print:
<span class="OSFillParent" data-expression="" style="font-size: 12px; margin-top: 5px;">Dual Complete Plan 1</span>
More of the HTML code of the element I am trying to print (element I am trying to capture is below the fourth div):
<td data-header="Plan Name">
<div id="b8-b40-l1_0-132_0-$b2" class="OSBlockWidget" data-block="Content.AccordionItem">
<div id="b8-b40-l1_0-132_0-b2-SectionItem" class="section-expandable open is--open small-accordion" data-container="" data-expanded="true" aria-expanded="true" aria-disabled="false" role="tab">
<div id="b8-b40-l1_0-132_0-b2-TitleWrapper" class="section-expandable-title" data-container="" style="cursor: pointer;" role+"button" aria-hidden="false" aria-expanmded="true" tabindex="0" aria-controls="b8-b40-l1_0-132_0-b2-Content" EVENT FLEX
<div id="b8-b40-l1_0-132_0-b2-Title" class="dividers full-width">
<span class="OSFillParent" data-expression="" style="font-size: 12px; margin-top: 5px;">Dual Complete Plan 1</span>
</div>
<div class="section-expandable-icon" data-container="" aria-hidden="true"
::after
</div>
</div>
<div id="b8-b40-l1_0-132_0-b2-ContentWrapper" class="section-expandable-content no-padding is--expanded" data-container="" tabindex="0" aria-hidden="false" aria-labelledby="b8-b40-l1_0-132_0-b2-TitleWrapper">
<div id="b8-b40-l1_0-132_0-b2-Content" role="tabpanel">
<a data-link="" href="https://www.communityplan.com" target="_blank" title="Click for more information"> EVENT
<span class="OSFillParent" data-expression="" style="font-size: 12px;">www.CommunityPlan.com</span>
</a>
<span class="OSFillParent" data-expression="" style="font-size: 12px:">Phone Number: 8005224700</span>
</div>
</div>
</div>
</div>
</td>
My relevant Selenium code:
# Find the Plan Name & if present set it to the variable "Advantage"
try:
Advantage = (WebDriverWait(driver, 5).until(
EC.presence_of_element_located((By.CSS_SELECTOR, "#b8-b40-l1_0-132_0-b2-Title > span:nth-child(1)"))).get_attribute("value"))
except:
pass
print('\033[91;46m', Advantage, '\033[0m')
I expect the output to be "Dual Complete Plan 1", which is what I see on the screen and in the HTML. Instead I get the following:
None
Apparently the "Advantage" variable is being set to "None".
Why?
I can see the text "Dual Complete Plan 1" that I want to print in the HTML code above.
What am I doing wrong?
I feel like I need a primer on "get attribute"?
To get the text Dual Complete Plan 1 you need to use
element.text
or
element.get_attribute("innerHTML")
or
element.get_attribute("textContent")
Instead of presence_of_element_located() use visibility_of_element_located()
and following css selector to identify
div[id*='Title'] > span.OSFillParent
Or
div.dividers.full-width > span.OSFillParent
Code:
try:
Advantage = WebDriverWait(driver, 5).until(
EC.visibility_of_element_located((By.CSS_SELECTOR, "div[id*='Title'] > span.OSFillParent"))).text
except:
pass
print(Advantage )

Clicking on Javascript tab using Selenium and Python without unique class id or element name

I have this HTML element code which I am currently struggling to figure out to use it for clicking on the tab that says Problem. As the "Problem" doesnt have a unique classname or element ID, I am unable to figure how to send a Click().
I have tried to check if z-index can be used as index(assumed) and used below line of code
browser.switch_to_frame(a[3])
but it seems I am wrong.
HTML code as below
<div class="TabsViewPort" style="position: relative; overflow: hidden; width: 896px; height: 22px; float: left;">
<div style="overflow: visible; float: left; width: 897px; top: 0px; left: 0px;">
<dl class="OuterOuterTab">
<dd class="OuterTab" artabid="955000038" arwindowid="0" style="top: 1px; z-index: 1; left: 0px; visibility: inherit; display: block;"><span class="TabLeftRounded"> </span>
<span class="Tab">My Profile
</span>
<span class="TabRight"> </span>
</dd>
<dd class="OuterTabSelected" artabid="600000203" arwindowid="0" style="top: 1px; z-index: 3; left: 63px; visibility: inherit; display: block;"><span class="TabLeft"> </span>
<span class="Tab">Approval
</span>
<span class="TabRight"> </span>
</dd>
<dd class="OuterTab" artabid="536870915" arwindowid="0" style="top: 1px; z-index: 1; left: 409px; visibility: inherit; display: block;"><span class="TabLeft"> </span>
<span class="Tab">Problem
</span>
<span class="TabRight"> </span>
</dd>
</dl>
</div>
</div>
The element with text as Problem is a JavaScript enabled element so to click() on the element you have to induce WebDriverWait for the element to be clickable and you can use either of the following solutions:
Using XPATH A:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[#class='TabsViewPort']//dl[#class='OuterOuterTab']//dd[#class='OuterTab']//a[#class='btn f1' and text()='Problem']"))).click()
Using XPATH B (shortened):
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//a[#class='btn f1' and text()='Problem']"))).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
If the element present inside an iframe then you need to switch to iframe first to access the element.
You can Use following method to frame_to_be_available_and_switch_to_it()
By locator ID
WebDriverWait(driver,10).until(EC.frame_to_be_available_and_switch_to_it((By.ID,"id of the iframe")))
OR
By locator NAME
WebDriverWait(driver,10).until(EC.frame_to_be_available_and_switch_to_it((By.NAME,"name of the iframe")))
Once You have switched to iframe you can access the element using following xpath
To click on the element Induce WebDriverWait and element_to_be_clickable()
WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.XPATH,"//span[#class='Tab']//a[text()='Problem']"))).click()
You need to import following 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
Hope this will help.
please find below xpath to click on third TAB
(//span[#class="Tab"])[3]/a

Use selenium to write in and run a code cell in jupyterlab

I would like to test a patched implementation of juptyerlab. I was hoping to use selenium to execute "hello world" in a code cell. So far I can log in and create a new notebook:
from selenium import webdriver
driver = webdriver.Firefox()
# assume jupyterlab is running and serving on localhost at port 8888
driver.get("http://localhost:8888")
elem = driver.find_element_by_id("password_input")
password = ""
elem.send_keys(password)
elem = driver.find_element_by_id("login_submit")
elem.click()
elem = driver.find_element_by_css_selector(".jp-Launcher-cwd+ .jp-Launcher-section .jp-LauncherCard")
elem.click()
This creates a new notebook, but now I'm stuck at the point of entering some code in a cell and running it. If I view the page source I don't see any html elements for the cells. But if I enter print("test") in a cell, then driver.page_source contains this (it's pretty nested in other stuff I've omitted too):
<div class="CodeMirror cm-s-jupyter CodeMirror-wrap jp-mod-readOnly">
<div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 0px;">
<textarea
style="position: absolute; bottom: -1em; padding: 0px; width: 1px; height: 1em; outline: currentcolor none medium;"
autocorrect="off" autocapitalize="off"
spellcheck="false" tabindex="0"
wrap="off"></textarea></div>
<div class="CodeMirror-vscrollbar" tabindex="-1"
cm-not-content="true"
style="display: block; bottom: 0px;">
<div style="min-width: 1px; height: 33px;"></div>
</div>
<div class="CodeMirror-hscrollbar" tabindex="-1"
cm-not-content="true">
<div style="height: 100%; min-height: 1px; width: 0px;"></div>
</div>
<div class="CodeMirror-scrollbar-filler"
cm-not-content="true"></div>
<div class="CodeMirror-gutter-filler"
cm-not-content="true"></div>
<div class="CodeMirror-scroll" tabindex="-1" draggable="true">
<div class="CodeMirror-sizer"
style="margin-left: 0px; padding-right: 0px; padding-bottom: 0px;">
<div style="position: relative;">
<div class="CodeMirror-lines" role="presentation">
<div style="position: relative; outline: currentcolor none medium;"
role="presentation">
<div class="CodeMirror-measure">
<pre><span>xxxxxxxxxx</span></pre>
</div>
<div class="CodeMirror-measure">
<pre class="CodeMirror-line"
role="presentation"><span
role="presentation"><span
class="cm-builtin">print</span>(<span
class="cm-string">"test"</span>)</span></pre>
</div>
<div style="position: relative; z-index: 1;"></div>
<div class="CodeMirror-cursors"></div>
<div class="CodeMirror-code"
role="presentation"></div>
</div>
</div>
</div>
</div>
<div style="position: absolute; height: 30px; width: 1px; border-bottom: 0px solid transparent;"></div>
<div class="CodeMirror-gutters"
style="display: none;"></div>
</div>
</div>
I can see where the text for print("text") is (i.e. the deepest nested elements in the above html snippet), but I can't figure out which element here I would be able to send text to or send keys to.
I came across robotframework-jupyterlibrary and it has some clues such as this and this . From those links I see
${JLAB CSS ACTIVE INPUT} ${JLAB CSS ACTIVE CELL} .CodeMirror
and
Add and Run JupyterLab Code Cell
[Arguments] ${code}=print("hello world")
[Documentation] Add a ``code`` cell to the currently active notebook and run it.
Click Element css:${JLAB CSS NB TOOLBAR} ${JLAB CSS ICON ADD}
Sleep 0.1s
${cell} = Get WebElement css:${JLAB CSS ACTIVE INPUT}
Click Element ${cell}
Set CodeMirror Value ${JLAB CSS ACTIVE INPUT} ${code}
Run Current JupyterLab Code Cell
Click Element ${cell}
which makes me think if I select the .CodeMirror element, then I just need to figure out what Get WebElement does in that weird language and how to do it in selenium.
Any ideas?
I've also tried (based on https://stackoverflow.com/a/48723135/1011724 and https://stackoverflow.com/a/50279295/1011724):
from selenium.webdriver.common.action_chains import ActionChains
actions = action_chains.ActionChains(driver)
textarea = driver.find_elements_by_css_selector('.CodeMirror textarea')[0] # tried for [0], [1] ,[2] and [3] which is all of them.
actions.move_to_element(textarea).click().send_keys("testing...").perform()
but I keep getting the error
selenium.common.exceptions.WebDriverException: Message: TypeError: rect is undefined
Code below tested with Chrome, Firefox and jupyterlab latest versions:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
wait = WebDriverWait(driver, 10)
driver.get("http://localhost:8888")
token = "0107216930d05db8a7c36ad6a73573dd5349c3dd56fee852"
wait.until(EC.element_to_be_clickable((By.ID, "password_input"))).send_keys(token, Keys.ENTER)
# wait for "Python 3" Notebook menu or CodeMirror element if already launched.
wait.until(EC.presence_of_element_located(
(By.CSS_SELECTOR, "[title='Python 3'][data-category='Notebook'], .jp-Notebook .CodeMirror")))
# if "Python 3" Notebook menu found click to open new Notebook
if len(driver.find_elements_by_css_selector("[title='Python 3'][data-category='Notebook']")) > 0:
driver.find_element_by_css_selector("[title='Python 3'][data-category='Notebook']").click()
# wait for CodeMirror and click to focus
code_mirror = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, ".jp-Notebook .CodeMirror")))
code_mirror.click()
code_mirror.find_element_by_tag_name("textarea").send_keys("print('Hello World!')")
driver.find_element_by_css_selector("[data-icon='run']").click()
output = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".jp-OutputArea-output")))
print(output.text)
assert output.text.strip() == "Hello World!"
driver.quit()
To Open Jupyter-Notebook:
Either Open a command window and navigate to the repository folder or Open anaconda-command-prompt window and simply execute
jupyter notebook --NotebookApp.token='' --NotebookApp.password=''
After loading notebook using driver.get("http://localhost:8888"), Here is the most tricky part, that how to select a Dynamically changing object. Visit Reference: Dynamically Changing IDs.
By using find_element_by_xpath
By using find_element_by_css_selector
These both will give you the same selection-point but it would be better to use Xpath which is more convenient technique. You can move forward like this;
import time
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
driver = webdriver.Chrome('chromedriver.exe')
wait = WebDriverWait(driver, 20)
driver.maximize_window()
website_url = "http://localhost:8888/"
driver.get(website_url)
# Using Xpath
# I prefer using xpath, because it is simple to understand
# and if you want to dynamically enter data into fields, it would be an awesome approach
driver.find_element_by_xpath("//div[#id='new-buttons']").click()
if len(driver.find_elements_by_xpath("//div[#id='new-buttons']//li[#id='kernel-python3']")) > 0:
time.sleep(3)
driver.find_element_by_xpath("//div[#id='new-buttons']//li[#id='kernel-python3']").click()
driver.find_element_by_xpath('//div[#class="cell code_cell rendered selected"]').click()
# Using css_selector
#driver.find_element_by_css_selector("#notebook-container > div").click()
command = 'print("Hello World!")'
#a = driver.find_element_by_css_selector("#notebook-container > div > div.input > div.inner_cell >"
# "div.input_area > div > div:nth-child(1) > textarea")
time.sleep(3)
# To select Note-Book text-area and place command in it.
a = driver.find_element_by_xpath('//div[#class="input_area"]//textarea').click().send_keys(command)
# To run the Code in Selected Cell
time.sleep(3)
driver.find_element_by_xpath("//button[#title='Run']").click()
print("Test is done.")

Categories

Resources