Puppeteer screenshot with cursor icon - image

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();
})();

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();
})
});

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: cannot render pdf with images stored locally

I cannot get images stored locally to be rendered in generated pdf with Puppeteer, but external images for which I specify a url work.
In particular, in the sample code below, rendering the page in test_html1 works, while rendering the test_html2 does not work.
(async () => {
const browser = await puppeteer.launch({ args: ['--no-sandbox'] });
const page = await browser.newPage();
const test_html1 = `<html><h3>Hello world!</h3><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/Google_2015_logo.svg/1024px-Google_2015_logo.svg.png"></html>`;
// const test_html2 = `<html><h3>Hello world!</h3><img src="file:///home/cristina/Documents/logo.jpg"></html>`;
await page.goto(`data:text/html,${test_html}`, { waitUntil: 'networkidle0' });
await page.pdf({ path: `${this.outputPath}/test-puppeteer.pdf`,
format: 'A4', landscape: !data.isPortrait,
margin: { top: '0.5cm', right: '1cm', bottom: '0.8cm', left: '1cm' }, printBackground: true });
await browser.close();
})();
Result with test_html1:
Result with test_html2:
My questions:
Does Puppeteer work with absolute img paths?
If yes, am I specifying the path correctly? Or is there something else I am doing wrong?
Solved on Puppeteer GitHub: https://github.com/GoogleChrome/puppeteer/issues/1643
Basically, it doesn't work because, as a security measure against malicious websites, access to local images is blocked.
function base64_encode(file) {
var bitmap = fs.readFileSync(file);
return new Buffer(bitmap).toString('base64');
}
img.src = 'data:image/png;base64,' + base64_encode(imagePath);
You can use above function it's render very fast.

How to upload a file with puppeteer and dropzone?

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();
})();

Resources