Click a button inside <span> using Python Selenium - python

I am trying to click on download button. The HTML Code for the button is as below:
<a class="x-btn toolbar-menu x-unselectable x-box-item x-toolbar-item x-btn-transparent-medium" style="padding: 0px 5px; right: auto; left: 1121px; margin: 0px; top: 0px;" hidefocus="on" unselectable="on" id="toolbarbutton-1054" tabindex="-1" data-qtip="<b>Export</b><br/>Export your report into a CSV file." componentid="toolbarbutton-1054">
<span id="toolbarbutton-1054-btnWrap" data-ref="btnWrap" role="presentation" unselectable="on" style="" class="x-btn-wrap x-btn-wrap-transparent-medium ">
<span id="toolbarbutton-1054-btnEl" data-ref="btnEl" role="presentation" unselectable="on" style="" class="x-btn-button x-btn-button-transparent-medium x-btn-no-text x-btn-icon x-btn-icon-left x-btn-button-center ">
<span id="toolbarbutton-1054-btnIconEl" data-ref="btnIconEl" role="presentation" unselectable="on" class="x-btn-icon-el x-btn-icon-el-transparent-medium sdc-icon-export " style=""> </span>
<span id="toolbarbutton-1054-btnInnerEl" data-ref="btnInnerEl" unselectable="on" class="x-btn-inner x-btn-inner-transparent-medium">
</span>
</span>
</span>
</a>
I tried this :
driver.find_element(By.ID , "toolbarbutton-1054-btnEl").click()
Getting an error: selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable
When I try below command it does not give error and element is recognizable. It's just that I cannot click on it.
driver.find_element(By.ID , "toolbarbutton-1054-btnEl")

Hey you can use the below code
class_element= driver.find_element_by_class('x-btn toolbar-menu x-unselectable x-box-item x-toolbar-item x-btn-transparent-medium')
class_element.click()
and also you can use driver.find_element_by_xpath('xpath here')

Actually, Span does not have a clickable feature.
Please execute the following javascript code using python selenium:
document.getElementById('toolbarbutton-1054-btnEl').click();
I don't know how to execute javascript code using python selenium but it will work.
I used it with C# Selenium.

In Python it should work with the following code:
s=driver.find_element(By.ID , "toolbarbutton-1054-btnEl")
driver.execute_script("arguments[0].click();",s)
I used the link below for my reference:
https://www.tutorialspoint.com/running-javascript-in-selenium-using-python

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 )

How to get text inside nested span using Selenium (Python)?

How to get all texts with class jss160:
<div class="jss157 red">
<img class="jss158" src="/static/media/e18d9.png" alt="Izimu">
<span style="margin: 0px 3px; font-size: 10px;">:</span>
<span>
<span>
<span class="jss159">ご質問</span>
<span class="jss160">質問</span>
</span>
<span>
<span class="jss159">答え</span>
<span class="jss160 answer">絶対に。</span>
</span>
</span>
</div>
My goal is to get all texts inside jss160 class. for this code my output is 質問
With Selenium you could do the following:
browser.find_element_by_css_selector("span.jss160").text
To understand this better, try to play with the CSS selector, for example with simple code like this with lxml.html and cssselect installed:
import lxml.html
tree = lxml.html.fromstring("""<div class="jss157 red">
<img class="jss158" src="/static/media/e18d9.png" alt="Izimu">
<span style="margin: 0px 3px; font-size: 10px;">:</span>
<span>
<span>
<span class="jss159">ご質問</span>
<span class="jss160">質問</span>
</span>
<span>
<span class="jss159">答え</span>
<span class="jss160 answer">絶対に。</span>
</span>
</span>
</div>""")
tree.cssselect("span[class='jss160']")[0].text
# '質問'
IIUC, You are using selenium webdriver
You can get elements with class jss160 using
element = driver.find_elements_by_class_name("jss160");
and get text using
element.text

Unable to check Checkbox

I am trying to check the checkbox but i am getting following error
selenium.common.exceptions.NoSuchElementException: Message: no such
element: Unable to locate element: {"method":"xpath","selector":"//mat-
checkbox[#id='mat-checkbox-1']/label/div"}
I tried selecting using id, css-selector and xpath but keep on getting error.
reg_date_checkbox = self.browser.find_element_by_xpath("//matcheckbox[#id='mat-checkbox-1']/label/div")
reg_date_checkbox.location_once_scrolled_into_view
reg_date_checkbox.click()
The HTML of checkbox is
<div _ngcontent-fep-c23="" class="last-date my-12 ng-star-inserted" fxlayout="column" style="flex-direction: column; box-sizing: border-box; display: flex;">
<mat-checkbox _ngcontent-fep-c23="" class="mat-checkbox mat-accent ng-untouched ng-pristine ng-valid" formcontrolname="deadline_enabled" id="mat-checkbox-1">
<label class="mat-checkbox-layout" for="mat-checkbox-1-input">
<div class="mat-checkbox-inner-container">
<input class="mat-checkbox-input cdk-visually-hidden" type="checkbox" id="mat-checkbox-1-input" tabindex="0" aria-checked="false">
<div class="mat-checkbox-ripple mat-ripple" matripple="">
<div class="mat-ripple-element mat-checkbox-persistent-ripple"></div>
</div>
<div class="mat-checkbox-frame"></div>
<div class="mat-checkbox-background">
<svg xml:space="preserve" class="mat-checkbox-checkmark" focusable="false" version="1.1" viewBox="0 0 24 24">
<path class="mat-checkbox-checkmark-path" d="M4.1,12.7 9,17.6 20.3,6.3" fill="none" stroke="white"></path>
</svg>
<div class="mat-checkbox-mixedmark"></div>
</div>
</div><span class="mat-checkbox-label"><span style="display:none"> </span>The event has a registration deadline</span>
</label>
</mat-checkbox>
<!---->
You are probably trying to click on the element which is NOT of type 'checkbox'. I see there is an input with type checkbox. Please try below mentioned code
reg_date_checkbox = self.browser.find_element_by_xpath("//input[#id='mat-checkbox-1-input']")
reg_date_checkbox.click()
Additionally if you wish you perform uncheck you can look for input element's aria-checked property to be true before performing a click.
You are using this xpath //matcheckbox[#id='mat-checkbox-1']/label/div , it should be //mat-checkbox[#id='mat-checkbox-1']/label/div , there's a - in between, you are missing that.
Still you can try with this css selector :
div.mat-checkbox-inner-container input[class^='mat-checkbox-input'][id^='mat-checkbox']
There may be chances that the checkbox is in iframe, if it is the case then first switch to frame and then try to click on check box.
You could try this:
element = self.browser.find_element_by_css("input#mat-checkbox-1-input")
element.click()

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.

Categories

Resources