Package: chrome-aws-lambda Error: Navigation failed because browser has disconnected - aws-lambda

I'm using mocha, puppeteer, and running test cases in the AWS lambda. I'm opening multiple tabs in the browser using the below code.
browser = await chromium.puppeteer.launch({
args: chromium.args,
defaultViewport: chromium.defaultViewport,
executablePath: await chromium.executablePath,
headless: chromium.headless,
ignoreHTTPSErrors: true,
});
let browerTabs = Array.from({length: 50}).map(() => {
return openTab(browser)
})
const openTab = async (browser) => {
try{
url1 = process.env.URL || 'https://www.google.com/'
let page = await browser.newPage();
await page.goto(url1, { waitUntil: ["load", "networkidle2"] });
const content = await page.evaluate(() => document.body.innerHTML);
}catch(err) {
console.log("browser tab open error ==> ", err)
}
return content
}
If I'm opening 40 tabs it's working fine. But If I trying to open 50 tabs then I'm getting the below issue. RAM is not even 30% used. What could be the reason for this error?
Everything is fine in the local
at /var/task/node_modules/puppeteer-core/lib/cjs/puppeteer/common/LifecycleWatcher.js:51:147
at /var/task/node_modules/puppeteer-core/lib/cjs/vendor/mitt/src/index.js:47:62
at Array.map (<anonymous>)
at Object.emit (/var/task/node_modules/puppeteer-core/lib/cjs/vendor/mitt/src/index.js:47:43)
at CDPSession.emit (/var/task/node_modules/puppeteer-core/lib/cjs/puppeteer/common/EventEmitter.js:72:22)
at CDPSession._onClosed (/var/task/node_modules/puppeteer-core/lib/cjs/puppeteer/common/Connection.js:247:14)
at Connection._onClose (/var/task/node_modules/puppeteer-core/lib/cjs/puppeteer/common/Connection.js:128:21)
at WebSocket.<anonymous> (/var/task/node_modules/puppeteer-core/lib/cjs/puppeteer/common/WebSocketTransport.js:17:30)
at WebSocket.onClose (/var/task/node_modules/ws/lib/event-target.js:129:16)
at WebSocket.emit (events.js:315:20)

Related

Async await not working for function - create pdf document and then email it

const pdf = require('pdfkit')
const QR = require('qrcode')
const emailTickets = async (userEvent, tickets) => {
await createQRCodes(tickets)
await createTicketPDF(tickets, userEvent)
await sendGridEmail(emailDetails, true)
}
The problem seems to be that async/await isn't working properly for the createTicketPDF function.
When I run the above emailTickets function a blank pdf document is emailed. However, when I run it with the below setTimeOut, the pdf contains all the detail that I want.
const emailTickets = async (userEvent, tickets) => {
await createQRCodes(tickets)
await createTicketPDF(tickets, userEvent)
setTimeout(async() => {await sendGridEmail(emailDetails, true)}, 5000);
}
I would prefer a solution where the code waited for the createTicketPDF function to finish before calling the sendGridEmail function.
Below is the code for the createTicketPDF function:
const createTicketPDF = async (tickets, userEvent) => {
const doc = new pdf
doc.pipe(fs.createWriteStream(`./tickets/${tickets[0]._id}.pdf`))
await tickets.map(async(ticket, index)=> {
return(
await doc.fontSize(30),
await doc.text(userEvent.title),
await doc.fontSize(10),
await doc.moveDown(),
await doc.text(`Venue: ${userEvent.venue}, ${userEvent.address1} `),
await doc.moveDown(),
await doc.fontSize(20),
await doc.text(`Ticket ${index+1} of ${tickets.length}: ${ticket.ticketType}`),
await doc.image(`./qrCodes/${ticket._id}.png`, {
align: 'center',
valign: 'center'
}),
await doc.addPage()
)
})
doc.end()
}
I had a forEach loop in this function but replaced it with a map on learning that forEach loops don't work well with async await.
I have also tried using (const ticket of tickets){} but this didn't work either
VS code is suggesting that none of the awaits within the map do anything
For completeness, below is the createQRCodes. This function is working perfectly.
const createQRCodes = async (tickets) => {
let CreateQRCodes = tickets.map(ticket => {
return(
QR.toFile(`./qrCodes/${ticket._id}.png`, String([ticket._id, ticket.randomNumber, ticket.creationTime.getTime(), ticket.userEvent]))
)})
await Promise.all(CreateQRCodes)
}
Any ideas where I am going wrong
Twilio SendGrid developer evangelist here.
As far as I can tell from the documentation, PDFKit is a synchronous library. The only thing that is asynchronous is writing the PDF to disk. So your code should not need to await anything within the createTicketPDF function. You do need to listen for the stream to finish though, so you could return a promise that resolves when the stream is finished, like this:
const createTicketPDF = (tickets, userEvent) => {
const doc = new pdf
const stream = doc.pipe(fs.createWriteStream(`./tickets/${tickets[0]._id}.pdf`))
tickets.map((ticket, index)=> {
return(
doc.fontSize(30),
doc.text(userEvent.title),
doc.fontSize(10),
doc.moveDown(),
doc.text(`Venue: ${userEvent.venue}, ${userEvent.address1} `),
doc.moveDown(),
doc.fontSize(20),
doc.text(`Ticket ${index+1} of ${tickets.length}: ${ticket.ticketType}`),
doc.image(`./qrCodes/${ticket._id}.png`, {
align: 'center',
valign: 'center'
}),
doc.addPage()
)
})
doc.end()
const promise = new Promise((resolve) => {
stream.on("finish", () => {
resolve();
})
});
return promise;
}
const emailTickets = async (userEvent, tickets) => {
await createQRCodes(tickets)
await createTicketPDF(tickets, userEvent)
await sendGridEmail(emailDetails, true)
}

Puppeteer: TypeError: page.waitForXpath is not a function

I am using this code. Output of the code always shows TypeError: page.waitForXpath is not a function. Puppeteer version: 8.0.0 and puppeteer-xpath version: 0.1.0 I have also used this command to upgrade: npm install https://github.com/GoogleChrome/puppeteer/ but that does not work. Here is my code:
const { expect } = require('chai');
const puppeteer = require('puppeteer');
var browser, page;
before(async () => {
browser = await puppeteer.launch({
headless: false,
defaultViewport: null,
devtools: false,
args: [
"--disable-web-security",
"--disable-features=IsolateOrigins,site-per-process",
"--window-size=1920,1080"
]
});
page = await browser.newPage();
})
describe("Search to google", async () => {
it("write something to searchbar", async () => {
await page.goto("https://www.google.com");
let searchBarSelector = '[name=q]';
await page.waitForSelector(searchBarSelector);
let [searchBarElement] = await page.$$(searchBarSelector);
await searchBarElement.type("JavaScript Tutorial");
// await page.type(searchBarSelector,"JavaScript Tutorial");
await page.keyboard.press("Enter");
let imageXpath = "//a[contains(text(),'Images')]";
await page.waitForXpath(imageXpath);
let imageTextElement = await page.$x(imageXpath);
expect(imageTextElement != null).equals(true);
})
})
after(async () => {
await browser.close();
})
Output:
You just have a typo: it is page.waitForXPath(), not page.waitForXpath().
See page.waitForXPath(xpath[, options]) in the docs.

Webdriverio wait until visible

I'm using webdriverio and need to wait for an element to be in the viewport
So I tried
browser.waitUntil(async () => {
const b = await link.isDisplayedInViewport()
return b;
}, 5000, 'expected to be visible after 5s');
But somehow waitUntil wants a boolean not a Promise<boolean>
How can I fix this?
Update:
I use WebdriverIO in a NodeJs app as follows
const { remote } = require('webdriverio');
(async () => {
const browser = await remote({
logLevel: 'error',
path: '/',
capabilities: {
browserName: 'chrome'
}
});
await browser.url('https://example.com');
const link = await browser.$('.special-link');
const ok = await browser.waitUntil(async () => {
const b = await link.isDisplayedInViewport()
return b;
}, 5000, 'expected to be visible after 5s');
await link.click();
const title = await browser.getTitle();
console.log('Title was: ' + title);
await browser.deleteSession();
})().catch((e) => console.error(e));
source
In the options is don't see anything about with or without async/await. Furthermore I don't use a testing framework!
Sorry for the late answer. But if you are still looking for a solution, Please try this if you want to avoid aync/await
get link() { return browser.element('.special-link'); }
browser.waitUntil(() => this.link.isVisibleWithinViewport(), 20000, 'link not visible')
const elementWaitingToBeDisplayed = $("some element locators")
elementWaitingToBeDisplayed.waitForDisplayed(10000, false)
If you set the second argument of elementWaitingToBeDisplayed.waitForDisplayed to true it waits for the opposite.

Why Headless Chrome, Puppeteer running on Lambda gives error on every page.click(), but locally fine?

I am running Lambda function using Puppeteer. I would like to click on different HTML elements. When I run the code locally it works fine and it clicks, but when I run it on Lambda I am getting :
Error: Node is either not visible or not an HTMLElement
I have set :
const browser = await puppeteerLambda.getBrowser({ headless: true, slowMo: 100, args: ['--no-sandbox', '--disable-setuid-sandbox', '--single-process', '--start-fullscreen', '--window-size=1413,749']});
await page.setViewport({ width: 1413, height: 749 });
let path = actions.path;
await page.waitFor(1000);
clicker = await page.$(path);
try {
await clicker.hover();
await clicker.click();
await page.waitFor(1500);
} catch (e) {
console.log('path click error', e);
await mailer.mailError(jobName, e);
}
I think it should be available to see the html element with this viewport.
Also I can extract innerText of the click elements. I can click them locally.
Any ideas?
This fixed it:
clicker = await page.$(path);
try {
await page.evaluate((el) => {
return el.click()
}, clicker);
await page.waitFor(1500);
} catch (e) {
console.log('click error', e);
}
It's probably bug in Puppeteer that can't be done await clicker.click(). Also you can always check their documentation.

react native parsing Lottie file into state?

I am trying to implement Lottie animation into my app, i am using expo SDK,
so i followed the documentation on expo,
_loadAnimationAsync = async () => {
let result = await fetch(
'https://cdn.rawgit.com/airbnb/lottie-react-native/635163550b9689529bfffb77e489e4174516f1c0/example/animations/Watermelon.json'
);
this.setState(
{ animation: JSON.parse(result._bodyText) },
this._playAnimation
);
};
i got an [Unhandled promise rejection: SyntaxError: JSON Parse error: Unexpected identifier "undefined"].
is it result ._bodyText who is empty or undefined ??
I just meet the same issue and fixed.
modify _loadAnimationAsync should get it work.
_loadAnimationAsync = async () => {
let result = await fetch(
'https://cdn.rawgit.com/airbnb/lottie-react-native/635163550b9689529bfffb77e489e4174516f1c0/example/animations/Watermelon.json'
)
.then(data => {
return data.json();
})
.catch(error => {
console.error(error);
});
this.setState({ animation: result }, this._playAnimation);
};
I also start a pr for this issue if you are interested. here

Resources