How to click on a descendant li element with Selenium? - python

I am automating with selenium and reached a point where I click a drop down and there are 3 options and they are in a ul list, and each option is an li role. I am able to locate them and selenium can see them but selenium cannot click on them, it says it is not interactable.
Here is the code that is interacting with it.
browser.find_element(by=By.XPATH, value='//*[#id="ext4-ext-gen1136"]').click()
browser.find_element(by=By.CSS_SELECTOR, value='#boundlist-1078-listEl > ul > li:nth-child(3)').click()
(normally I use XPATH for everything but I figured I would try CSS Selector)
Here is the HTML code
<ul class="x4-list-plain"><li role="option" unselectable="on" class="x4-boundlist-item x4-boundlist-selected">Show Latest Event</li><li role="option" unselectable="on" class="x4-boundlist-item">Show All Events and Traces</li><li role="option" unselectable="on" class="x4-boundlist-item">Show All Events</li></ul>
<li role="option" unselectable="on" class="x4-boundlist-item x4-boundlist-selected">Show
Latest Event</li>
<li role="option" unselectable="on" class="x4-boundlist-item">Show All Events and
Traces</li>
<li role="option" unselectable="on" class="x4-boundlist-item">Show All Events</li>
I want to be able to select show all events and traces.

From your code trials as per the value of the id attribute i.e. ext4-ext-gen1136 it seems the element is a dynamic element.
To click on the <li> element with text as Show All Events you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following locator strategies:
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "ul.x4-list-plain li:nth-child(3)"))).click()
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//ul[#class='x4-list-plain']//li[#class='x4-boundlist-item' and text()='Show All Events']"))).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

I figured it out, I had to have the drop down open to click on them but the dropdown would immediately close when selenium clicked on it, all I had to do was make selenium click on it twice and that fixed the issue.

Related

Xpath Selenium- How to locate a element by the sub text

Hope you´re really fine and can help me with this short question.
I´m trying to locate the following object id=C39_W133_V136_thtmlb_button_27 but using the text that is located after an span (text = "Edit"). Please I tried different ways but didn´t work till now, any idea?
<a href="javascript:void(0)" class="th-bt th-bt-icontext-dis icon-font" tabindex="-1" oncontextmenu="return false;" ondragstart="return false;" id="C39_W133_V136_thtmlb_button_27">
::before
<img class="th-bt-img" src="/SAP/BC/BSP/SAP/thtmlb_styles/sap_skins/belize/images/1x1.png">
<span class="th-bt-span"><b class="th-bt-b">Edit</b></span>
<b class="th-bt-b">Edit</b>
</a>
In order to locate an element using text contained in an element, the only option is to use XPath.
//a[./b[.='Edit']]
^ Start at the top of the document and find an A tag
^ ...that has a descendant B tag
^ ...that contains the text 'Edit'
To locate the <a> element which have a descended <span> with text as Edit you need to induce WebDriverWait for the visibility_of_element_located() and you can use either of the following Locator Strategies:
Using XPATH:
element = WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//a[contains(#id, 'thtmlb_button')][.//b[text()='Edit']]")))
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

Click a button to display a text box in python selenium

I am trying to click a button which un-hides another text box. The button click changes the script from
<span id="incident.u_brand_edit" style="display: none;">
to
<span id="incident.u_brand_edit" style>
Following is the button HTML
<button class="btn btn-default btn-ref" type="button" aria-labelledby="incident.u_brand_title_text"
data-target="#incident\.u_brand" title="" tabindex="0" id="incident.u_brand_unlock"
data-type="glide_list_unlock" data-ref="incident.u_brand" data-auto-close="false"
data-placement="auto" style="margin-right: 5px;" list-read-only="false"
data-original-title="Unlock Brand"><span class="icon icon-locked" aria-hidden="true"></span></button>
I am trying to achieve this using the following code
driver.find_element_by_id("incident.u_brand_unlock").click()
Also tried this
driver.find_element_by_id("incident.u_brand_unlock").send_keys("\n")
The above codes are focusing on the button but it's not clicking and the text box is not unhiding to perform further operations.
Try to use the ActionChains class in your code like below -
# Import
from selenium.webdriver import ActionChains
wait = WebDriverWait(driver, 5)
action = ActionChains(driver)
Button_Click = wait.until(EC.element_to_be_clickable((By.ID, 'incident.u_brand_unlock')))
action.move_to_element(Button_Click).click().perform()
To click on the element you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following Locator Strategies:
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.btn.btn-default.btn-ref[id$='u_brand_unlock'][data-original-title='Unlock Brand']>span"))).click()
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[#class='btn btn-default btn-ref' and contains(#id, 'u_brand_unlock')][#data-original-title='Unlock Brand']/span"))).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
Found out the answer in this post . Had to remove the style attribute of the field I wanted to appear.

How can I get this html code's by xpath for using selenium on python?

I have an update button and in python, bot ı want to click this button but ı try many options but not working ı can't locate element by XPath. Please help me? Thanks for your help.
Note: I need to locate by using the text "Update" because a lot of buttons ı have on a webpage.
<span class="a-spacing-top-small">
<span class="a-button a-button-primary a-button-small sc-update-link" id="a-autoid-2">
<span class="a-button-inner">
<a href="javascript:void(0);" data-action="update" class="a-button-text" role="button" id="a-autoid-2-announce" style="">Update
<span class="aok-offscreen">Nike Academy 18 Rain Jacket Men's (Obsidian, M)</span>
</a>
</span>
</span>
</span>
This should work:
button = driver.find_element_by_xpath("//a[#data-action,'update']")
Where driver is your instance of driver.
The desired element is a JavaScript enabled element so to locate/click() on the element you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following Locator Strategies:
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "span.a-button.a-button-primary.a-button-small.sc-update-link[id^='a-autoid'] a.a-button-text[id$='announce']>span.aok-offscreen"))).click()
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//span[#class='a-button a-button-primary a-button-small sc-update-link' and starts-with(#id,'a-autoid')]//a[#class='a-button-text' and contains(#id,'announce')]/span[#class='aok-offscreen' and starts-with(., 'Nike Academy 18 Rain Jacket Men')]"))).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

How get id from dynamic button ? (Python)

I have this xpath element who change dynamically, and i like to click on it, how i can do it?
//*[#id="/api/services/61_ellipsis"]
The button HTML is:
<button type="button" class="v-btn v-btn--flat v-btn--icon v-btn--round theme--light v-size--default" id="/api/services/33_ellipsis">
<span class="v-btn__content">
<i aria-hidden="true" class="v-icon notranslate mdi mdi-dots-vertical theme--light">
</i>
</span>
</button>
The desired element is a dynamic 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 CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.v-btn.v-btn--flat.v-btn--icon.v-btn--round.theme--light.v-size--default[id^='/api/services/'] > span.v-btn__content > i.v-icon.notranslate.mdi.mdi-dots-vertical.theme--light"))).click()
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[#class='v-btn v-btn--flat v-btn--icon v-btn--round theme--light v-size--default' and starts-with(#id, '/api/services/')]/span[#class='v-btn__content']/i[#class='v-icon notranslate mdi mdi-dots-vertical theme--light']"))).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 ID changes dynamically, you cannot use the exact ID to get the element, but a contains query might work
Query on any element that contains api/services in the ID:
//*[contains(#id, 'api/services')]
Query on the button without any ID info. Has inner span and i elements:
//button[span/i]
Query on button element that contains api/services in the ID, and also has inner span and i elements:
//button[span/i and contains(#id, 'api/services')]
To save the ID, you want to find the element then get it's ID attribute:
buttonId = driver.find_element_by_xpath("//button[span/i and contains(#id, 'api/services')]").get_attribute("id")

How do I cycle through these elements using selenium in python and get the XPATH value in return?

I want to be able to cycle through this table's tabs and return the XPATHs and tab names.
I am using the python selenium webdriver.
This is the main container containing all the tabs from which i want the data
When i enter the website into selenium webdriver, i want it to first find this chart_table_container.
<div id="chart_table_container" class="tab_container ui-tabs ui-corner-all ui-widget ui-widget-content">
<ul class="tabs ui-tabs-nav ui-corner-all ui-helper-reset ui-helper-clearfix ui-widget-header" role="tablist">
Then I want it to cycle through the 3 tabs below, sometimes there might be more than 3. and the XPATH might be different, so I want to automate that.
Is there a way to cycle through the tabs below and return the XPATHs (//*[#id="ui-id-3"]) and also the name of the tabs (First Order) into a dictionary?
This is an example of one tabs
<li role="tab" tabindex="0" class="ui-tabs-tab ui-corner-top ui-state-default ui-tab ui-tabs-active ui-state-active" aria-controls="chart_wrapper_datatable_first_order" aria-labelledby="ui-id-3" aria-selected="true" aria-expanded="true">
First Order</li>
This is another tab
<li role="tab" tabindex="-1" class="ui-tabs-tab ui-corner-top ui-state-default ui-tab" aria-controls="chart_wrapper_datatable_second_order" aria-labelledby="ui-id-4" aria-selected="false" aria-expanded="false">
Second Order</li>
This is anothertab
<li role="tab" tabindex="-1" class="ui-tabs-tab ui-corner-top ui-state-default ui-tab" aria-controls="chart_wrapper_datatable_third_order" aria-labelledby="ui-id-5" aria-selected="false" aria-expanded="false">
Third Order</li>
Does selenium have the capacity to do this? I looked through the documentation but I only found ways to search for the actual tabs using the XPATHs not find all the XPATHs at once.
just try this:
tabs = driver.find_elements_by_xpath('.//li[#role= "tab"]/a')
tabs = [[a.get_attribute("innerHTML"), "//*[#id=" + "".join(a.get_attribute("id")) + "]"] for a in tabs ]
If li classes is always the same, change xpath to [#class= "li class"] or [#role= "tab" and #class= "li class"]
To print the table names such as First Order, Second Order, Third Order, etc you have to induce WebDriverWait for the visibility_of_all_elements_located() and you can use either of the following Locator Strategies:
Using CSS_SELECTOR:
print([my_elem.get_attribute("innerHTML") for my_elem in WebDriverWait(driver, 5).until(EC.visibility_of_all_elements_located((By.CSS_SELECTOR, "div#chart_table_container>ul.ui-tabs-nav li>a.ui-tabs-anchor[id^='ui-id-']")))])
Using XPATH:
print([my_elem.get_attribute("innerHTML") for my_elem in WebDriverWait(driver, 5).until(EC.visibility_of_all_elements_located((By.XPATH, "//div[#id='chart_table_container']/ul[contains(#class, 'ui-tabs-nav')]//li/a[#class='ui-tabs-anchor' and starts-with(#id, 'ui-id-')]")))])
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

Categories

Resources