Selenium Python dropdown menu - python

I'm a bit new to selenium. I'm trying to select values from a drop-down menu using selenium in python, but for this website it does not seem to work.
Any ideas on how it can be done?
HTML code of dropdown:
<div id="dropdown-breakdown-select" class="drop-down drop-down--open">
<div class="drop-down__selected drop-down__selected--open ">Geographical breakdown</div>
<ul class="dropdown-list" tabindex="1" style="height: 246px;
display: block; overflow-y: hidden; outline: none;">
<li style="font-weight: normal;">Geographical breakdown</li>
<li style="font-weight: normal;">Rating</li>
<li style="font-weight: normal;">Maturity</li>
<li style="font-weight: normal;">Benchmark breakdown</li>
<li style="font-weight: normal;">Risk currency</li>
<li style="font-weight: normal;">Active currency risk</li>
<li style="font-weight: normal;">Active duration risk</li>
</ul>
</div>
Screenshot of dropdown:
Drop down from this page: Web link

Find element by css selector (#breakdown-select-wrapper .drop-down__selected) and click on it.
After that, iterate over lis (#dropdown-breakdown-select li) and find the one you are looking for by text.
Finally, click on it.

Because your drop down is a CSS dropdown, not native dropdown, you can't use Select class.
def choose_breakdown(option):
// click to make option list visible
driver
.find_element_by_css_selector(
"div#dropdown-breakdown-select > div.drop-down__selected"
).click()
// choose option by given option text
driver
.find_element_by_xpath(
"//div[#id='dropdown-breakdown-select']/ul/li[.='" + option + "']"
).click()

Related

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 )

Can selenium find_element_by_xpath in outlook online?

I'm having trouble finding elements by xpath or id inside of outlook's online html. I'm using selenium and python. Here is what I've wrote.
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import NoSuchElementException #imports
browser = webdriver.Chrome('C:\\Users\\...')
browser.get('https://www.office.com/...') #setup
#then some code to sign into outlook online
browser.find_element_by_xpath('//*[#id="_ariaId_64"]/div/div/div[1]')
browser.find_element_by_xpath('//*[#id="MailFolderPane.FavoritesFolders"]/div[19]')
browser.find_element_by_id('_ariaId_68') #attempts to find an element in outlook
this is the element I'm trying to access. I would post the entire html, but there is just so much. I'm brand new to all things code so go easy on me :)
<div>
<div id="_ariaId_68" aria-expanded="false" draggable="true" dropzone="string:text/plain">
<div autoid="_n_R" class="_n_44 canShowFavoritesAction" role="treeitem" aria-expanded="false" aria-labelledby="_ariaId_68.folder _ariaId_68.ucount" aria-haspopup="true" tabindex="-1">
<div class="_n_S3 nowrap border-color-transparent _n_X3" style="padding-left: 4px;">
<div class="_n_V3 _n_54">
<span autoid="_n_S" class="_n_W3 ms-font-m ms-fwt-sl _n_Y3" id="_ariaId_68.folder" title="Sent Items">Sent Items</span>
<div class="_n_24 ms-bg-color-neutralLighter"> <span autoid="_n_T" class="ms-font-m _n_Z3 ms-fwt-sb ms-fcl-tp" aria-hidden="true"></span> </div>
<span class="ms-font-s ms-fcl-ns" aria-hidden="true" aria-expanded="false" aria-haspopup="true" tabindex="-1"> </span> <button autoid="_n_U" type="button" class="_n_34 ms-fwt-r ms-fcl-ns o365button hidden" style="display: none;" tabindex="-1"></button> <span style="display: none;" aria-hidden="true"></span>
</div>
<div class="_n_14 hidden"><button autoid="_n_V" type="button" class="_n_04 firefoxFavorite o365button" title="Remove from Favorites" aria-labelledby="_ariaId_69"><span class="_fc_3 owaimg ms-Icon--star ms-icon-font-size-18 ms-fcl-ns-b"> </span><span class="_fc_4 o365buttonLabel _fc_2" id="_ariaId_69" style="display: none;"></span></button></div>
</div>
</div>
</div>
</div>
Assuming you're trying to find the SENT ITEMS's - web element.
The SENT ITEM link does not seem to be the visible area [when you have more sub folders inside Inbox, this usually happens] and hence you first make a scroll to view to the element before performing anything on the element.
Here are the options to bring the element to visible area
Try with following xpath
//span[#title='Sent Items']

How to find selector for "new" button? Do I need to use Switch frames?

<div id="crmMasthead" tabindex="-1">
<div id="crmTopBar" class="ms-crm-TopBarContainer ms-crm-TopBarContainerGlobal newNavBarMode">
<div id="crmAppMessageBar" class="crmAppMessageBar" style="display: none; height: 0px;">
<div id="crmRibbonManager" currentribbonelement="commandContainer15" style="height: 62px; display: block; visibility: visible;">
<div id="commandContainer15" style="display: inline;">
<ul class="ms-crm-CommandBar-Menu" role="application">
<li id="ewrb_importfile|NoRelationship|HomePageGrid|Mscrm.HomepageGrid.ewrb_importfile.NewRecord" class="ms-crm-CommandBarItem ms-crm-CommandBar-Menu ms-crm-CommandBar-Button" tabindex="-1" title="New Create a new Import File record." command="ewrb_importfile|NoRelationship|HomePageGrid|Mscrm.NewRecordFromGrid" style="white-space: pre-line; display: inline-block;">
<span class="ms-crm-CommandBar-Button ms-crm-Menu-Label-Hovered" tabindex="-1" style="max-width:200px">
<a class="ms-crm-Menu-Label" tabindex="0" onclick="return false">
<img class="ms-crm-ImageStrip-New_16 ms-crm-commandbar-image16by16" tabindex="-1" src="/_imgs/imagestrips/transparent_spacer.gif" style="vertical-align:top"/>
<span class="ms-crm-CommandBar-Menu" tabindex="-1" style="max-width:150px" command="ewrb_importfile|NoRelationship|HomePageGrid|Mscrm.NewRecordFromGrid"> New </span>
<div class="ms-crm-div-NotVisible"> Create a new Import File record. </div>
</a>
</span>
</li>
The Xpath Shows me like this:
.//*[#id='ewrb_importfile|NoRelationship|HomePageGrid|Mscrm.HomepageGrid.ewrb_importfile.NewRecord']/span/a
and If i use this, Selenium doesn't click the button
First try to remove "."(dot) from your xpath and check it if it works.
Secondly, try to write the xpath yourself. For this a node, try this one:
//a[#class="ms-crm-Menu-Label"]
You should check it if the part of html that you share is inside an iframe node or not. Otherwise, you should share more. With the current part that you shared, it is not possible to say that if it is inside an iframe or not.
Also, it can be a good idea to check the visibility of the button. The last thing: do you receive any error message. If yes, share it.

Multi-select buttons in Selenium(Python)

As part of automation testing, I'm trying to figure out what is the best way to access a multi-select button in my company website. This button is not design in the popular way and it causes me problems using Select library. Here is how it looks like:
<div class="select-options options-overflow drop-select-link" style="position: absolute; top: 373px; left: 492px; width: 53px;">
<div class="drop-holder">
<div class="drop-list" style="height: 100px; overflow-x: hidden; overflow-y: auto;">
<ul>
<li class="jcfcalc" rel="0">
<a href="#">
<span>USD</span>
</a>
</li>
<li class="option-even jcfcalc" rel="1">
<a href="#">
<span>EUR</span>
</a>
</li>
</ul>
</div>
</div>
</div>
What you see here is a multi-select button which displayed different kind of currencies. I want to be able to choose currencies in a wise way - something like Select library. However, Select library doesn't fit to my code.
Is there a library that I'm not aware of? or would I have to do it with XPaths?
Select() couldn't be used with buttons. Any buttons! It could be used with select/option elements only!
In your case you can simply use link text to select required element (which is link, not the button) as
driver.find_element_by_link_text("EUR")
driver.find_element_by_link_text("USD")

Categories

Resources