How to upload a file with puppeteer and dropzone? - dropzone.js

I use puppeteer and I have a dropzone form.
I want to add a file from chrome headless to the dropzone form.
How can I do that?
Note:
The form contains some actions in some dropzone events (when added file).

Not sure if I understood the problem correctly, but try this:
const dropZoneInput = await page.$(inputID);
dropZoneInput.uploadFile(absolutePathToFile);

I have it working with puppeteer:
const fileInput = await page.$(
".{yourDropzoneClassName} input[type=file]"
);
await fileInput.uploadFile("path/to/file");

(async () => {
const browser = await puppeteer.launch({
headless: false,
ignoreDefaultArgs: true
});
const page = await browser.newPage();
await page.goto('https://react-dropzone.js.org/');
await page.waitForSelector('input[type=file]');
const fileInput = await page.$('#rsg-root > div > main > section > section:nth-child(3) > section > section:nth-child(1) > article > div:nth-child(2) > div.rsg--preview-60 > div > section > div > input[type=file]');
await fileInput.uploadFile("./test/playground.js");
///trigger event
await fileInput.evaluate(upload => upload.dispatchEvent(new Event('change', { bubbles: true })));
///
await page.close();
})();

Related

Puppeteer downloads blank PDF instead of the one expected, with content

I have to download a pdf, but it requires first to collect cookies, by visiting the page which hosts the PDF link.
I click the link but a blanc PDF is downloaded with same pages number as the expected one.
(async () => {
const browser = await puppeteer.launch({
dumpio: true,
headless: false,
devtools: true,// I want to see what's going on
})
const [page] = await browser.pages();
page.on('console', msg => console.log(msg.text()));
await page.goto(url_cookie, { waitUntil: ['domcontentloaded', 'networkidle0', 'load'] });
page._client.send('Page.setDownloadBehavior', { behavior: 'allow', downloadPath: './', });
page.once('response', async (response) => {
if (response.url() !== url_pdf) return;
console.log('resp', response.url());
});
const css = 'a[href="' + url + '"]';
await page.waitForSelector(css)
const eval = async css => {
const a = document.querySelector(css);
console.log(a)
return fetch(a.href, {
method: 'GET',
credentials: 'include',
}).then(r => r.text())
};
const txt = await page.evaluate(eval, [css]);
fs.writeFileSync('./test.pdf', txt,)
await page.close();
await browser.close();
})();

How to handle navigation of pages in Puppeteer UI Automation code

Here's the automation code for the web application for user name and password:
const puppeteer = require('puppeteer');
const expect = require('chai').expect;
describe("User Login",()=>{
let browser;
let page;
before(async function(){
browser = await puppeteer.launch({
headless:false,
slowMo:100
});
page = await browser.newPage();
await page.goto('https://www.test.com');
await page.waitForSelector('input[name=UserName]');
});
it("Successful login",async()=>{
await page.type('input[name=UserName]', 'test', {delay: 20});
await page.type('input[name=Password]', 'test', {delay: 20});
const button = await page.$('input[id=submitCredentials]');
await button.click();
//await page.waitForSelector('.item-group security-question');
});
after(async function(){
await browser.close();
})
});
Once the login is successful the application navigates to a different page, I cannot find a way to get the page object in puppeteer which I can use to validate if the login is successful or not. Any suggestions ?
I did find a solution to the problem at: Codota
Here's the modified code :
const puppeteer = require('puppeteer');
const expect = require('chai').expect;
describe("User Login",()=>{
let browser;
let page;
before(async function(){
browser = await puppeteer.launch({
headless:false,
slowMo:100
});
page = await browser.newPage();
await page.goto('https://www.test.com');
await page.waitForSelector('input[name=UserName]');
});
it("Successful login",async()=>{
await page.type('input[name=UserName]', 'test', {delay: 20});
await page.type('input[name=Password]', 'test', {delay: 20});
const button = await page.$('input[id=submitCredentials]');
const navigationPromise = page.waitForNavigation();
await button.click();
await navigationPromise;
await page.waitForSelector('div[class="item-group security-question"]');
const question = await page.$eval('input[id=QuestionId]', element => element.textContent);
expect(question).to.be.not.null;
});
after(async function(){
await browser.close();
})
});

Puppeteer screenshot with cursor icon

We are using puppeteers page.screenshot function (https://devdocs.io/puppeteer/index#pagescreenshotoptions) but the resulting captured image doesn't show the current mouse cursor icon. Is there a way to tell puppeteer to include the mouse cursor icon in the captured screenshot?
install-mouse-helper.js
You can use install-mouse-helper.js to inject a box in the page that moves with the mouse in Puppeteer and is visible in screenshots:
const puppeteer = require('puppeteer');
const {installMouseHelper} = require('./install-mouse-helper');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await installMouseHelper(page); // Install Mouse Helper
await page.goto('https://example.com/');
await page.mouse.move(100, 200);
await page.mouse.down();
await page.mouse.move(500, 250);
await page.screenshot({
path: 'example.png',
});
await browser.close();
})();

Failed to launch chrome! spawn ...node_modules/puppeteer/.../chrome ENOENT TROUBLESHOOTING when using Puppeteer

I was trying to build a quick lambda that prints a pdf with a specific url, but I get this error: Failed to launch chrome! spawn ...node_modules/puppeteer/.../chrome ... TROUBLESHOOTING
Methods mentioned here : https://github.com/GoogleChrome/puppeteer/issues/807#issuecomment-366529860 did not help me.
The code I'm using:
const browser = await puppeteer.launch({
headless: true,
executablePath: '../../node_modules/puppeteer/.local-chromium/linux-624487/chrome-linux/chrome',
args: ['--no-sandbox', '--disable-setuid-sandbox'],
});
try {
const result = await exports.run(browser);
callback(null, result);
} catch (e) {
callback(e);
}
...
exports.run = async (browser) => {
// implement here
// this is sample
const page = await browser.newPage();
await page.goto('https://www.google.com', {
waitUntil: ['domcontentloaded', 'networkidle0']
});
console.log((await page.content()).slice(0, 500));
await page.type('#lst-ib', 'aaaaa');
// avoid to timeout waitForNavigation() after click()
await Promise.all([
// avoid to
// 'Cannot find context with specified id undefined' for localStorage
page.waitForNavigation(),
page.click('[name=btnK]'),
]);
// cookie and localStorage
await page.setCookie({
name: 'name',
value: 'cookieValue'
});
console.log(await page.cookies());
console.log(await page.evaluate(() => {
localStorage.setItem('name', 'localStorageValue');
return localStorage.getItem('name');
}));
const result = await page.pdf({
path: 'hn.pdf',
format: 'A4'
});
console.log(` typeof : ${typeof result}, pdf: ${result}`);
await page.close();
return 'done';
};
check this path =>
\node_modules\puppeteer.local-chromium\win32-818858\chrome-win
you will notice chrome.exe will not exist, now got back one step =>
*\node_modules\puppeteer.local-chromium*
you will find zip file "chrome-win" extract it and move it int to =>
\node_modules\puppeteer.local-chromium\win32-818858
Now you may check it will work.

Puppeteer, looping through links selected by xpath

I'm new to puppeteer (and not so great at javascript in general) and am trying to write some basic functionality to:
Get all the links from an XPath
Loop through and click those links
Screenshot and save the HTML of the page
Go back, screenshot and save the HTML of the records page to be save in the same directory of the others and start the process over
The error I get is:
Evaluation failed: DOMException: Failed to execute 'querySelector' on 'Document': '0' is not a valid selector
Here's the code I have:
I'm fairly confident all the code works, except for the issues i'm having getting the right things to click on with my XPath. The website I'm getting these from is:
https://hrlb.oregon.gov/bspa/licenseelookup/searchdir.asp?searchby=lastname&searchfor=a&stateselect=none&Submit=Search
code:
const records = await page.$x('//table[2]//tr[td[a]]//td[1]/a');
let int = 0;
for (let record in records) {
await Promise.all([
page.waitForNavigation(),
page.click(record)
]);
await Promise.all([makeDirectory('screenshots/item'+int), makeDirectory('screenshots/item'+int+'/base'), makeDirectory('screenshots/item'+int+'/record')]);
let recordPath = "screenshots/item"+int+"/record/record.html";
let basePath = "screenshots/item"+int+"/base/base.html";
page.screenshot({path: "screenshots/item"+int+"/record/record.png", fullPage: true});
let recordBody = await page.evaluate(() => document.body.innerHTML);
await saveHtml(recordPath, recordBody);
await Promise.all([
page.waitForNavigation(),
page.goBack()
]);
await page.screenshot({path: "screenshots/item"+int+"/base/base.png", fullPage: true});
let baseBody = await page.evaluate(() => document.body.innerHTML);
await saveHtml(basePath, baseBody);
int++;
console.log(record);
}
async function makeDirectory(path) {
mkdirp(path, function(err) {
if (err) throw err;
});
};
async function saveHtml(path, html) {
await fs.writeFile(path, html, (err) => {
if (err) throw err;
});
};
Note: I'm required to use XPath :(
Updated 6/25/18
This now gives me all the links from the xpath selector. Which i then iterate over and just use a page.goto, to go to the correct site.
const linksXPath = '//table[2]//tr[td[a]]//td[1]/a';
const links = await page.evaluate((selector) => {
let results = [];
let query = document.evaluate(selector,
document,
null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (let i=0, length=query.snapshotLength; i<length; ++i) {
results.push(query.snapshotItem(i).href);
}
return results;
}, linksXPath);
I think it is your selector that is the issue.
I believe your selector for the table should be:
"body > table > tbody > tr:nth-child(2) > td > table > tbody > tr:nth-child(1) > td > table.bodytext > tbody"
The easiest way to get the right selector for a page is to use the Chrome Dev Tools.
Inspect the page, and go to the "Elements" tab. From there, you should see all of the HTML elements. Right click on the one you want (I went for <tbody> so you can iterate through the <tr> elements.) and choose copy > copy selector.
My code is now doing what I need it to do, however I wish there was a simpler way of doing this. Also, you'll see as I iterate over the links, i'm using a page.goto function to go there. I still don't know of a way to use page.click. I would have to use the xpath to get all the td's and then click on them, but i was never able to get that to work. So here is the working product:
const puppeteer = require('puppeteer');
const fs = require('fs');
const mkdirp = require('mkdirp');
async function run() {
const pageToClick = 'body > table > tbody > tr:nth-child(3) > td > table > tbody > tr > td > form > table > tbody > tr:nth-child(3) > td > div > input[type="submit"]';
const select = 'body > table > tbody > tr:nth-child(3) > td > table > tbody > tr > td > form > table > tbody > tr:nth-child(1) > td:nth-child(2) > select';
const inputField = 'body > table > tbody > tr:nth-child(3) > td > table > tbody > tr > td > form > table > tbody > tr:nth-child(2) > td:nth-child(2) > input[type="text"]:nth-child(1)';
const linksXPath = '//table[2]//tr[td[a]]//td[1]/a';
const browser = await puppeteer.launch({
headless: true
});
const page = await browser.newPage();
await page.goto('https://hrlb.oregon.gov/bspa/licenseelookup/');
await page.select(select, 'lastname');
await page.focus(inputField);
await page.keyboard.type('a');
await Promise.all([
page.waitForNavigation(),
page.click(pageToClick)
]);
const links = await page.evaluate((selector) => {
let results = [];
let query = document.evaluate(selector,
document,
null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (let i=0, length=query.snapshotLength; i<length; ++i) {
results.push(query.snapshotItem(i).href);
}
return results;
}, linksXPath);
const basePic = await page.screenshot({fullPage: true});
let baseBody = await page.evaluate(() => document.body.innerHTML);
let int = 0;
for (i = 0; i < links.length; i++) {
await Promise.all([
page.waitForNavigation(),
page.goto(links[i])
]);
await Promise.all([makeDirectory('screenshots/item'+int), makeDirectory('screenshots/item'+int+'/base'), makeDirectory('screenshots/item'+int+'/record')]);
let recordPath = "screenshots/item"+int+"/record/record.html";
let basePath = "screenshots/item"+int+"/base/base.html";
let basePicPath = "screenshots/item"+int+"/base/base.png";
await page.screenshot({path: "screenshots/item"+int+"/record/record.png", fullPage: true});
let recordBody = await page.evaluate(() => document.body.innerHTML);
await saveFile(recordPath, recordBody);
await Promise.all([
page.waitForNavigation(),
page.goBack()
]);
await saveFile(basePath, baseBody);
await saveFile(basePicPath, basePic);
int++;
}
await page.close();
await browser.close();
}
async function makeDirectory(path) {
mkdirp(path, function(err) {
if (err) throw err;
});
};
async function saveFile(path, html) {
await fs.writeFile(path, html, (err) => {
if (err) throw err;
});
};
run();

Resources