Click on outer element with inner element with specific text in Puppeteer - node.js

How can I click on an outer element that contains a span with specific text via puppeteer?
For example I have the following HTML code:
<div role="button">
<div>
<span>
<span>OK</span>
</span>
</div>
</div>
And I would like to click on the most outer element (role = button). In order to click on the span with the Ok text I would do the next thing:
const [button] = await page.$x("//span[contains(., 'Ok')]");
if (button) {
await button.click();
}
But how can I click on the outer element using this text identifier?

You can use the descendant expression to query for child elements. Quote from the link:
The descendant axis indicates all of the children of the context node, and all of their children, and so forth.
Your XPath expression then looks like this:
//div[#role='button' and descendant::span[contains(., 'Ok')]]
Depending on your use case you might also want to check out this information about the difference of contains(text(), ...) and contains(., ...).

Related

Selenium Can't Find Element Returning None or []

im having trouble accessing element, here is my code:
driver.get(url)
desc = driver.find_elements_by_xpath('//p[#class="somethingcss xxx"]')
and im trying to use another method like this
desc = driver.find_elements_by_class_name('somethingcss xxx')
the element i try to find like this
<div data-testid="descContainer">
<div class="abc1123">
<h2 class="xxx">The Description<span data-tid="prodTitle">The Description</span></h2>
<p data-id="paragraphxx" class="somethingcss xxx">sometext here
<br>text
<br>
<br>text
<br> and several text with
<br> tag below
</p>
</div>
<!--and another div tag below-->
i want to extract tag p inside div class="abc1123", but it doesn't return any result, only return [] when i try to get_attribute or extract it to text.
When i try extract another element using this method with another class, it works perfectly.
Does anyone know why I can't access these elements?
Try the following css selector to locate p tag.
print(driver.find_element_by_css_selector("p[data-id^='paragraph'][class^='somethingcss']").text)
OR Use get_attribute("textContent")
print(driver.find_element_by_css_selector("p[data-id^='paragraph'][class^='somethingcss']").get_attribute("textContent"))

how to select class name from button of span using css selector in below code as follows and have received an error

how to select class name from button of span using css selector in below code as follows and have received an error.
<span class="input-group-btn-vertical">
<button class="btn btn-white bootstrap-touchspin-up " type="button">+</button>
<button class="btn btn-white bootstrap-touchspin-down " type="button">-</button>
</span>
this.demoTestBailrafting = function (browser) {
browser
.url('https://www.phptravels.net/')
.waitForElementVisible('body', 500)
.assert.title('PHPTRAVELS | Travel Technology Partner')
/*trying to select first element in button tag of span class*/
.click('span[class=input-group-btn-vertical]>button[1]')
.pause(500)
.end()
};
ERROR: Unable to locate element:
"span[class=input-group-btn-vertical]>button[1]"
using: css selector
Assuming you want to get the class attribute from both of the buttons below the span -- not sure what language you are using here. But you should be able to use the getAttribute function on WebElement object.
List<IWebElement> buttons = driver.findElements(By.XPath("//span[#class='input-group-btn-vertical']/button"));
foreach(IWebElement button in buttons)
{
// this is the class name
string className = button.getAttribute("class");
}
Your click method
.click('span[class=input-group-btn-vertical]>button[1]')
is apparently expecting a CSS selector based on the error message
ERROR: Unable to locate element: "span[class=input-group-btn-vertical]>button[1]" using: css selector
^^^^^^^^^^^^^^^^^^^
The index [1] that you have in your CSS selector isn't valid. It's also not needed here since you are looking for the first element and Selenium will always act on the first element unless you otherwise specify. Also, to make your CSS selector more CSS-like (and more flexible), you should change it to
span.input-group-btn-vertical > button
^ this dot indicates a class name follows
^ I removed the [1] since it's not needed
See if that works now.

How can i click the third href link?

<ul id='pairSublinksLevel1' class='arial_14 bold newBigTabs'>...<ul>
<ul id='pairSublinksLevel2' class='arial_12 newBigTabs'>
<li>...</li>
<li>...</li>
<li>
<a href='/equities/...'> last data </a> #<-- HERE
</li>
<li>...</li>
Question is how can i get click third li tag ??
In my code
xpath = "//ul[#id='pairSublinksLevel2']"
element = driver.find_element_by_xpath(xpath)
actions = element.find_element_by_css_selector('a').click()
code works partially. but i want to click third li tag.
The code keeps clicking on the second tag.
Try
driver.find_element_by_xpath("//ul[#id='pairSublinksLevel2']/li[3]/a").click()
EDIT:
Thanks #DebanjanB for suggestion:
When you get the element with xpath //ul[#id='pairSublinksLevel2'] and search for a tag in its child elements, then it will return the first match(In your case, it could be inside second li tag). So you can use indexing as given above to get the specific numbered match. Please note that such indexing starts from 1 not 0.
As per the HTML you have shared you can use either of the following solutions:
Using link_text:
driver.find_element_by_link_text("last data").click()
Using partial_link_text:
driver.find_element_by_partial_link_text("last data").click()
Using css_selector:
driver.find_element_by_css_selector("ul.newBigTabs#pairSublinksLevel2 a[href*='equities']").click()
Using xpath:
driver.find_element_by_xpath("//ul[#class='arial_12 newBigTabs' and #id='pairSublinksLevel2']//a[contains(#href,'equities') and contains(.,'last data')]").click()
Reference: Official locator strategies for the webdriver

New Line is replaced by a single space in rich:tree

I have Lists of messages in a <div> as:
<div id="abc" class="icon111" title="#{collection.message}" />
This <div> is included in the JSF Rich-tree.
When switchType="ajax" for rich:tree the messages before expanding the tree is displaying properly, but once tree is expanded, all the messages are coming in one line(new line is replaced with the single space).
If I change the switchType="server/client" it will work, but it will impact in the performance of my project so I have to go with ajax only.
Is there anyway to display the messages in different lines?
While adding messages in java keep some Separator add list of messages to div title , but when mouseover div call JS , inside JS function Split the messages to next line with Regular expression
<div id="**abc**" class="icon111" title="#{collection.message}" onmouceover="showTitle('#{collection.message}','**abc**');/>
function showTitle(value,id){
var divContent = jQuery("#" + id);
var newTitle=value.replace(/#/g, '\n');
divContent.attr('title', newTitle);
}
Div id should dynamic , because Rich tree will take same div for all the hierarchy in the tree

jquery / cheerio: how to select multiple elements?

I need to parse some markup similar to this one, from an html page:
<a href="#">
<i class="icon-location"></i>London
</a>
I need to get London.
I did try something like (using cheerio):
$('a', 'i[class="icon-location"]').text();
or
$('a > i[class="icon-location"]').text();
without success...
I'd like to avoid methods like next(), since the expression should be passed to a method which just extracts the text from the selector.
What expression should I use (if it's feasible) ?
There's a solution, which is pretty unusual, but it works :
$("#foo")
.clone() //clone the element
.children() //select all the children
.remove() //remove all the children
.end() //again go back to selected element
.text();
Demo : https://jsfiddle.net/2r19xvep/
Or, you could surround your value by a new tag so you just select it:
<i class="icon-location"></i><span class="whatever">London</span>
Then
$('.whatever').text();
$('a').text();
will get text as 'London'.
$("a .icon-location").map(function(){
return $(this).text()
}).get();

Resources