How to click element in Puppeteer using xPath - node.js

I want to click on an element without using css selectors.
await page.click()
uses selectors to identify the element.
So how can I do something like this?
await page.click('/*[#id="toc"]/ul/li[1]/a')

First I had to get the element by using
await page.$x('<xPath>')
It returns an array with elements. To click I had to choose the first element in the array.
const elements = await page.$x('<xPath>')
await elements[0].click()

You can use the xpath prefix with puppeteer 19 and newer
await page.click('xpath/' + xpathExpression)
e.g.
await page.click('xpath//*[#id="toc"]/ul/li[1]/a')

Related

Playwright test library - parent element for selector

please, how to get a parent element for a text selector by the Playwright E2E library.
Is better to modify the selector (it is string by something like >> //:parent) or evaluate the selector and then call the DOM element?
(The selector content is unknown)
Thank you.
You can call .$ to start searching from the element:
const elem = await page.$(anySelector)
const parent = await elem.$('xpath=..')
Doc: https://playwright.dev/docs/api/class-elementhandle#elementhandleselector
Using the new Locator you can do:
const elementParent = await page.locator(`${childSelector} >> xpath=..`)
https://playwright.dev/docs/api/class-locator
https://playwright.dev/docs/selectors#xpath-selectors

How to click an element with Selenium webdriver javascript?

I am testing, and I have to click on elements, but it sometimes click, sometimes not. I tried some solutions, but there is no one, which always clicks.
Is there any solution to click an element, which always works?
I tried these codes:
1:
await driver.findElement(By.id("u_0_a")).click();
2:
var element = await driver.findElement(By.id("u_0_a"));
await element.click();
3:
await driver.executeScript("document.getElementById('u_0_a').click()");
I use selenium with node.js, javascript, chrome driver.
Try using:
var element = await driver.findElement(By.id("u_0_a"));
await driver.executeScript("arguments[0].click();", element)
Hope this helps!
Try using TryUntil. I hope this works. The below code is in C#
Browser.TryUntil(() => { }, () => Browser.FindElement(By.id("u_0_a")).Exists(), TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(120));
Browser.FindElement(By.id("u_0_a")).Click();
Thank you for your help. The problem was not in my code. The problem was with the https://www.facebook.com/ .
Because facebook, is changing the ID, and sometimes it was the login button sometimes a gender custom button. :/
Please try sleep before you handle the click operation.
Example as below:
await driver.sleep(2000)
await driver.findElement(By.xpath('element path')).click()

What's the expected behavior of puppeteer's ElementHandle.getProperty()?

Puppeteer 1.0.0-post. The getProperty() method seems somewhat magical. For example, if your page contains:
link
Then this will return not a relative but an absolute URL:
const propertyHandle = await elementHandle.getProperty('href');
const href = await propertyHandle.jsonValue();
// href is 'https://localhost:8080/foo/bar.html'
On the other hand, if you were to do the more roundabout:
const hrefHandle = await page.evaluateHandle(element => element.getAttribute('href'), elementHandle);
const href = await hrefHandle.jsonValue();
// href is '/foo/bar.html'
As far as I can tell, the puppeteer documentation doesn't mention this behavior of getProperty()?
It gets uglier, for instance if you want to get the style attribute of an element. It looks like puppeteer's getProperty() actually tries to parse the style in some way, which parsing is buggy/incomplete. The only way to get the raw text is with the roundabout call to evaluateHandle(...).
Is this an intended feature and simply a documentation bug? Or is it just, outright, a puppeteer bug?
Thanks.
See HTML - attributes vs properties for difference between HTML attributes and DOM properties.
You can easily see the difference without Puppeteer, too. For example, on this page:
document.getElementById('nav-questions').href
// returns "https://stackoverflow.com/questions"
document.getElementById('nav-questions').getAttribute('href')
// returns "/questions"

How to get updated html after changing page element values using puppeteer?

I'm at a loss. I'm typing into an input element on the page using this:
await page.type('#username', 'test');
Then I'd like to retrieve the newly updated, which I'm trying using this:
let html = await page.content();
But the username field does not include the word 'test' in it - it is empty. If I take a screenshot, it has the word 'test' in it. What am I missing?
Typing in an <input> element updates the value property but leaves the value attribute unchanged. This is why you don't see the text in the rendered HTML.
To get the value property:
await page.type('#username', 'test');
let value = await page.$('#username').getProperty('value');

nightmare.js trying to click on link based on anchor text

I'm trying to use nightmare, in node js to click on links based on the text inside the anchor text of the link.
Here's some example code:
var Nightmare = require('nightmare');
var nightmare = Nightmare({show: true})
nightmare
.goto('https://www.wikipedia.org/')
.inject('js', 'C:/users/myname/desktop/nodejs/node_modules/jquery/dist/jquery.js')
.wait(500)
var selector = 'a';
nightmare
.evaluate(function (selector) {
// now we're executing inside the browser scope.
return document.querySelector(selector).innerText;
}, selector) // <-- that's how you pass parameters from Node scope to browser scope
.end()
.then(function(result) {
console.log(result)
})
I'm really unclear on why the inner text of all tags are not returning? I thought I could maybe do an if statement in the .evalution method, so that it would restrict the link to be clicked on to "English" for instance.
Any idea how to click on links based on the link text?
As far as I know, there is no way to select a DOM element solely on what it contains. You'll either need to select all of the anchors (like you're doing now) and filter to what you want based on innerText then issue click events directly, or you could inject jQuery and use :contains and $.click() to issue the click.
Also, if you want all of the text from the tags, you'll likely want to use document.querySelectorAll().
As an example to get all of the text:
.evaluate(function (selector) {
return document.querySelectorAll(selector)
.map(element => element.innerText);
}, selector)

Resources