How to get updated html after changing page element values using puppeteer? - node.js

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');

Related

Mongoose model deleteOne() only works with hard coded string

I have a strange error with mongoose deleteOne() function. Today I wanted to work on my project and got an error while deleting an item from a collection. It simply doesn't delete the document until I use a hardcoded parameter for the options object like this:
const { deletedCount } = await Model.deleteOne({symbol: 'hardcoded'})
// results in deletedCount = 1
But if I try to use a dynamic string like:
const test = 'dynamic'
const { deletedCount } = await Model.deleteOne({symbol: test})
// results in deletedCount = 0
It does no longer delete the document from my collection. The strange thing is yesterday it worked fine and deleted the item.
I tried one other thing I read regarding errors with deleteOne():
const { deletedCount } = await Model.deleteOne({symbol: JSON.stringifiy(symbol)})
But this doesn't work, too.
Does anyone have an idea what's going wrong?
I always default to using ids whenever possible to make sure there's no mistake in the data I am targeting with a given operation.
So in this case that would mean using findByIdAndDelete() instead.
If I don't know the id of the document I'm trying to delete, then only I'd use findOneAndDelete() or deleteOne(), as you have, with something other than an id to identify the document I'm looking for.
Are you certain that the key-value pair you're passing to the function exists in your database?
Problem solved. I accidentally added an additional space character at the end of the string. This is very strange because the error was there since the beginning of my project and yesterday it worked.
So for everyone who might have a similar problem:
I have a ejs template file where I render a html element like this:
<div id="<%= symbol %> ">
Then in my event handler for requesting the server to deleting one item from my list I use the id attribute as a request parameter in the body. In the route handler this parameter is passed to mongoose:
const { symbol } = req.body
const { deletedCount } = await Model.deleteOne({ symbol })
As I mentioned. In the template file after the last ejs seperator there is an addional space character that caused the error. I spotted this issue by making a copy of the monoogse query and than logged it to the console. There I could see the wrong condition parameter.

How to click element in Puppeteer using xPath

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')

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"

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)

Get ID of Selected List Item

I am trying to get the ID of a selected list item using JavaScript. Basically I am trying to get the ID using JavaScript and then in the same javascript redirect to a page with the selected ID in the querystring.
This is my javascript:
function GetID() {
var ctx = SP.ClientContext.get_current();
var items = SP.ListOperation.Selection.getSelectedItems(ctx);
window.location.href = "/_layouts/CustomApplicationPage/CustomApplicationPage.aspx?ID=" + items;
}
But the results I get in my querystring are:
CustomApplicationPage.aspx?ID=[object Object]
Does anyone know how to get the ID of the selected list item or point me to the correct method to use in JavaScript?
Thanks!
The issue is that items is a Dictionary type as described here:
http://msdn.microsoft.com/en-us/library/ff409526(v=office.14).aspx
Since you are only trying to get a single value back, you can likely get what you need by referencing the first value in the Dictionary.
window.location.href = "/_layouts/CustomApplicationPage/CustomApplicationPage.aspx?ID=" + items[0].id;

Resources