How to Click a button in an Iframe using puppeteer? - javascript

I'm new to puppeteer so dont know much about it. This is my code so far and everything works.
But I want it to click the login button on the page after it has put the text in the fields, but I cannot figure out how to do it for the life of me. I've tried many different things and none work. Any help with this would be awesome.
just incase you need it
https://server.nitrado.net/usa/rent-gameserver
(async () => {
console.log('launch browser');
const browser = await pup.launch({headless: false});
console.log('new page');
const page = await browser.newPage();
console.log('goto');
await page.setViewport({ width: 1920, height: 1080 });
await page.goto('https://server.nitrado.net/usa/rent-gameserver', { waitUntil: "networkidle2", timeout: 60000 });
await page.waitFor(5000);
console.log('extract login iframe');
var iframes = await page.frames();
var loginFrame = iframes.find(f => f.url().indexOf("oauth.nitrado.net") > -1);
await page.waitFor(5000);
console.log('evaluate iframe');
await loginFrame.evaluate(() => {
document.getElementById('username').value = 'test';
document.getElementById('password').value = '12345';
});
await page.waitFor(300000);
console.log('done');
await browser.close();
})()```

I tried a workaround entering the frame url, I'm not sure if this will help, but here goes the code (main.js):
const pup = require('puppeteer');
mainFunc = async function () {
return new Promise(async (resolve, reject) => { //Wrap de promise
var browser;
try {
//Wrap de tratamento de erros
const browser = await pup.launch({ headless: false });
const page = await browser.newPage();
//SELECTORS:
var userInputSel = '#username';
var passInputSel = '#password';
var loginBtnSel = '#auth_login_ws_header > form > button';
var myUser = "myusername"; //PUT YOUR USERNAME HERE!!!
var myPass = "MyPaSsWoRd123"; //PUT YOUR PASSWORD HERE!!!
await page.goto('https://server.nitrado.net/usa/rent-gameserver',
{ waitUntil: "networkidle2", timeout: 60000 });
await page.waitFor(5000);
console.log('extract login iframe');
var iframes = await page.frames();
var loginFrame = iframes.find(f => f.url().indexOf("oauth.nitrado.net") > -1);
console.log(loginFrame.url())
await page.goto(loginFrame.url(),
{ waitUntil: "networkidle2", timeout: 60000 });
await page.waitFor(5000);
console.log('evaluate iframe');
/*await loginFrame.evaluate(() => {
document.getElementById('username').value = 'test';
document.getElementById('password').value = '12345';
});*/
await page.waitForSelector(userInputSel);
await page.type(userInputSel, myUser);
await page.waitForSelector(passInputSel);
await page.type(passInputSel, myPass);
await page.waitForSelector(loginBtnSel);
await page.click(loginBtnSel);
await page.waitFor(300000);
console.log('done');
await browser.close();
} catch (e) {
if(browser!=undefined){
browser.close();//Close browser if error
}
return reject(e);
}
});//Wrap de promise
}
mainFunc();
This is a running version for you to test. Just type "node main". (of course you need puppeteer installed (npm i puppeteer))...

Related

Puppeteer timeouts in headless mode

I need to go to the UPS site, type in a tracking number, then get the data about that tracking number. I turned headless to false then the timeouts disappeared, turn it to true, and it will timeout or wait forever. I tried a number of different methods (any I could find), to mess around with the promises, but nothing helped.
const puppeteer = require('puppeteer');
var fs = require("fs").promises;
var Page = {};
var Browser = {};
async function printPage(){
console.log("printPage()");
await fs.writeFile("pagecontent_afterClick.txt", await Page.content());
const count = await Page.$$eval('#st_App_PkgStsMonthNum', divs => divs.length);
console.log(count);
const deliveredOn = await Page.$eval('#st_App_PkgStsMonthNum', el => el.textContent);
const deliveredToAddress = await Page.$eval('#stApp_txtAddress', el => el.textContent);
const deliveredToCountry = await Page.$eval('#stApp_txtCountry', el => el.textContent);
const deliveredBy = await Page.$eval('#stApp_valReceivedBy', el => el.textContent);
console.log("browser close");
await Browser.close();
}
async function start(){
console.log("start");
const browser = await puppeteer.launch({
headless: false
});
const page = await browser.newPage();
Page = page
Browser = browser
const navigationPromise = page.waitForNavigation({waitUntil: 'load'})
await navigationPromise;
await fs.writeFile("pagecontent_B4.txt", await page.content());
await page.type("#stApp_trackingNumber", "1Z0F1R740320306827");
const searchValue = await page.$eval('#stApp_trackingNumber', el => el.value);
console.log(searchValue);
const count = await page.$$eval('button#stApp_btnTrack.ups-cta.ups-cta_primary', divs => divs.length);
console.log(count);
try {
console.log("end waiting");
await Promise.all([
page.click('#stApp_btnTrack'),
page.waitForNavigation({waitUntil: 'networkidle2'})
]);
printPage();
} catch (e) {
if (e instanceof puppeteer.errors.TimeoutError) {
console.log("timeout");
printPage();
}
}
}
start();

Loop through pages to return all the product links

The goal is to obtain all product links from all pages in the pagination. So far I have managed to print information to the console with console.log (links). However, since I am completely new to this field and completely inexperienced, I have a problem how to pass some value back with the return command. return links.
With console.log(links) I get a warning: getLinks is not iterable
const puppeteer = require('puppeteer')
async function getLinks(){
const browser = await puppeteer.launch({headless: false, defaultViewport: null});
const page = await browser.newPage();
const url = "https://example.com/product-category?p=1&nidx"
await page.goto(url)
while(await page.$('.change-country-buttons > button:nth-child(1)')){
await page.waitForTimeout(2000);
await page.keyboard.press('ArrowDown');
await page.waitForSelector('.change-country-buttons');
await page.waitForTimeout(2000);
await page.click('.change-country-buttons > button:nth-child(1)');
await page.waitForTimeout(2000);
}
while(await page.$(".pagination .pagination--next")){
await page.waitForTimeout(2000);
await page.evaluate(() => {
document.querySelector(".pagination .pagination--next").scrollIntoView();
});
await page.waitForTimeout(1000);
await page.waitForSelector(".pagination .pagination--next")
await page.waitForTimeout(500);
await page.click('.pagination .pagination--next')
const links = await page.$$eval('.item__info > .mtc-link:nth-child(2)', (allAs) => { return allAs.map((a) => a.href) });
await page.waitForTimeout(1500);
console.log(links)
}
}
return links // Is returning links only form the first page and then the loop stops
I tried something with Promise.all () but it wasn't entirely clear to me how to do it.
Please help and be gentle as I am just starting to learn the basics
You need to create an array and push all the helmet links from each page onto it.
This tested successfully for me.
const puppeteer = require('puppeteer')
async function getLinks(){
const browser = await puppeteer.launch({headless: false, defaultViewport: null});
const page = await browser.newPage();
const url = "https://www.motocard.com/en/motorcycle-road-gear/helmets/precio_150-3200/full-face?p=1&nidx"
var all_links = [];
await page.goto(url);
while(await page.$('.change-country-buttons > button:nth-child(1)')){
await page.waitForTimeout(2000);
await page.keyboard.press('ArrowDown');
await page.waitForSelector('.change-country-buttons');
await page.waitForTimeout(2000);
await page.click('.change-country-buttons > button:nth-child(1)');
await page.waitForTimeout(2000);
}
while(await page.$(".pagination .pagination--next")){
await page.waitForTimeout(2000);
await page.evaluate(() => {
document.querySelector(".pagination .pagination--next").scrollIntoView();
});
await page.waitForTimeout(1000);
await page.waitForSelector(".pagination .pagination--next")
await page.waitForTimeout(500);
await page.click('.pagination .pagination--next')
const links = await page.$$eval('.item__info > .mtc-link:nth-child(2)', (allAs) => { return allAs.map((a) => a.href) });
await page.waitForTimeout(1500);
//console.log(links)
all_links.push(...links);
}
return all_links;
}
(async ()=>{
var links = await getLinks();
console.log('done');
console.log(links);
})();

How to fill out form in puppeteer

I'm having trouble signing in, when I open this page
https://www.nike.com.br/chuteira-nike-phantom-gt-elite-3d-unissex-153-169-171-316414?gridPosition=A1
It goes to another page, and I can't fill out the form, can someone help me fill out the login form?
(async () => {
try{
console.log("Started!")
const browser = await puppeteer.launch({
executablePathh:'/usr/bin/chromium', headless:false,
});
const page = await browser.newPage();
await page.setViewport({ width: 1920, height: 1080 });
await page.setRequestInterception(true);
const blockedResourceTypes = ["image", "bacon", "imageset", "font", "stylesheet", "texttrack", "csp_report"]
const blockedURLs = [
""
]
const allowedRequest = req => !blockedResourceTypes.includes(req.resourceType()) && !blockedURLs.includes(req.url())
page.on('request', (req) => {
if(allowedRequest(req)) {
req.continue();
}
else {
req.abort();
}
});
await page.goto('https://www.nike.com.br/chuteira-nike-phantom-gt-elite-3d-unissex-153-169-171-316414?gridPosition=A1', {
waitUntil: 'domcontentloaded', timeout:0});
await page.waitForXPath('//label[#for="tamanho__idM40F395"]', {
visible:true, timeout:0});
const tamanho = await page.$x('//label[#for="tamanho__idM40F395"]')
await tamanho[0].click('//label[#for="tamanho__idM40F395"]');
await page.waitForSelector('button#anchor-acessar-unite-oauth2') await page.click('button#anchor-acessar-unite-oauth2')
const iframe = wait.ForSelector('iframe#nike-unite-oauth2-iframe')
const frame = await iframe.contentFrame()
await frame.type('input[name="emailAddress"]', 'test#gmail.com')
await frame.type('input[name="password"]', 'pass')
await frame.click('input[value="ENTRAR"]')
They realized that if you run the script it will go to the login page and then I can't fill out the form
To login in a new page instead of an iframe, try to replace this:
await page.click('button#anchor-acessar-unite-oauth2')
const iframe = wait.ForSelector('iframe#nike-unite-oauth2-iframe')
const frame = await iframe.contentFrame()
await frame.type('input[name="emailAddress"]', 'test#gmail.com')
await frame.type('input[name="password"]', 'pass')
await frame.click('input[value="ENTRAR"]')
with this:
await Promise.all([
page.click('button#anchor-acessar-unite-oauth2'),
page.waitForNavigation(),
])
await page.waitForSelector('input[name="emailAddress"]')
await page.type('input[name="emailAddress"]', 'test#gmail.com')
await page.type('input[name="password"]', 'pass')
await page.click('input[value="ENTRAR"]')

No node found for selector in (Puppeteer Error)

This is the code I have given:
const puppeteer = require('puppeteer');
(async () => {
const baseUrl = 'example.com';
const browser = await puppeteer.launch({ headless: true});
const context = await browser.createIncognitoBrowserContext();
const page = await context.newPage();
function delay(time) {
return new Promise(function (resolve) {
setTimeout(resolve, time)
});
}
await page.goto(baseUrl);
await page.waitForSelector('[name="loginfmt"]');
await page.type('[name="loginfmt"]', 'abc#amazon.com');
await page.click('[type="submit"]');
delay(1000);
await page.authenticate({ username: `abc#amazon.com`, password: `abc#123` });
await page.click((`[data-row-id="111-222-333-444"]`));
await delay(1000);
await page.pdf(
{
path: "Z1.pdf",
printBackground: true,
width: '1300px',
height: '14200px'
}
)
browser.close();
})()
When inspected the page with document.querySelectorAll([data-row-id="111-222-333-444"]); it returned a NodeList array which consisted the details which I have been looking for.
However when tried the same via Puppeteer it terminates with an error saying "Error: No node found for selector: [data-row-id="111-222-333-444"]"
Tried using:
"const button= await page.$(([data-row-id="111-222-333-444"]);
button.click();"
I have been trying to fix this since a long time. It would be really helpful if I get a fix for this.
Try using this code:
const puppeteer = require('puppeteer');
(async () => {
const baseUrl = 'example.com';
const browser = await puppeteer.launch({ headless: true});
const context = await browser.createIncognitoBrowserContext();
const page = await context.newPage();
await page.goto(baseUrl);
await page.waitForSelector('[name="loginfmt"]');
await page.type('[name="loginfmt"]', 'abc#amazon.com');
await page.click('[type="submit"]');
await page.waitForTimeout(1000)
await page.authenticate({ username: `abc#amazon.com`, password: `abc#123` });
await page.waitForTimeout(5000)
await page.$(`[data-row-id="111-222-333-444"]`);
await page.click((`[data-row-id="111-222-333-444"]`));
await page.waitForTimeout(1000)
await page.pdf(
{
path: "Z1.pdf",
printBackground: true,
width: '1300px',
height: '14200px'
}
)
browser.close();
})()

How to write robust test with puppeteer and jest?

This is the test I wrote and my problem is, that I tried to build it as robust as possible and still, it sometimes works and sometimes it fails for reasons like shown below.
Maybe I am missing something I'd appreciate it if one of you could help me make the tests more robust.
Note: That I removed sensitive information from the code.
const { getStatement, portalLogin, getDeletableList } = require("./helper.js");
const user = { userName: "*****#*****.de", passWord: "*******" };
const puppeteer = require("puppeteer");
const headlessVal = false;
const webSiteUrlLogin = "https://... .de/dashboard";
const webSiteUrlMe = "https://... .de/me";
// elements with classes
const change_username_button = ".change-username-button";
const save_user_changes_btn = ".save-user-changes-btn";
// elements with ID's
const user_personal_title = "#user_personal_title";
// [happy path] 1 user changes #user_personal_title
test("[happy path] 1 user changes #user_personal_title", async () => {
//////// SETUP & LOGIN START /////////
const browser = await puppeteer.launch({
headless: headlessVal,
args: ["--window-size=1920,1080"],
defaultViewport: null,
});
// new browser window opens
const page = await browser.newPage();
// open specified url and waits for it to be loaded
await page.goto(webSiteUrlLogin, {
//wait until there are no more conections that traffic
waitUntil: "networkidle0",
});
await page.waitForNavigation({
waitUntil: "networkidle2",
});
const user_local = {
userName:
user.userName !== undefined ? user.userName : process.env.USERNAME,
passWord:
user.passWord !== undefined ? user.passWord : process.env.PASSWORD,
};
await page.waitForTimeout(500);
await page.evaluate((user_local) => {
<FUNCTION LOGIN>
}, user_local);
await page.waitForTimeout(600);
//////// SETUP & LOGIN DONE /////////
//////// TEST START /////////
getStatement({ msg: "[START]: 1.1 title: '' >'Prof'.", runlocally: true });
await page.waitForTimeout(650);
await page.goto(webSiteUrlMe, {
waitUntil: "networkidle0",
});
// 1 change #user_personal_title from '' >> 'Prof.'
console.log("1 change #user_personal_title from '' >> 'Prof.'");
await page.waitForTimeout(650);
await page.evaluate((user_personal_title) => {
document.querySelector(user_personal_title).value = "";
}, user_personal_title);
await page.type(user_personal_title, "Prof.");
let user_personal_title_val = await page.$eval(
user_personal_title,
(el) => el.value
);
expect(user_personal_title_val).toBe("Prof.");
await page.click(save_user_changes_btn);
await page.waitForNavigation({
//wait until there are no more conections that have traffic
waitUntil: "networkidle0",
});
user_personal_title_val = await page.$eval(
user_personal_title,
(el) => el.value
);
expect(user_personal_title_val).toBe("Prof.");
await page.waitForTimeout(650);
await page.evaluate(() => {
document.querySelector("#user_personal_title").value = "";
});
await page.click(save_user_changes_btn);
await page.waitForNavigation({
//wait until there are no more conections that have traffic
waitUntil: "networkidle0",
});
user_personal_title_val = await page.$eval(
user_personal_title,
(el) => el.value
);
expect(user_personal_title_val).toBe("");
////// TEST DONE //////////
await page.click(".sign-out");
await page.removeAllListeners();
await page.close();
await browser.close();
getStatement({ msg: "[ENDING]: 1.1 ", runlocally: true });
}, 12000);
Failing:
Evaluation failed: TypeError: Cannot set property 'value' of null
at __puppeteer_evaluation_script__:2:55
at ExecutionContext._evaluateInternal (node_modules/puppeteer/lib/cjs/puppeteer/common/ExecutionContext.js:217:19)
at ExecutionContext.evaluate (node_modules/puppeteer/lib/cjs/puppeteer/common/ExecutionContext.js:106:16)
at Object.<anonymous> (joyce_PORTAL/end-to-end/me.test.js:168:3)
The element you are selecting in document.querySelector(user_personal_title).value isn't available on page yet. You need to wait for your selector element to be available on page before you execute your page using waitForSelector(selector).
Simple POC is as following:
page.waitForSelector(user_personal_title)
.then(() => //evaluate your document.querySelector(user_personal_title).value code here
);
//or simply
await page.waitForSelector(user_personal_title)

Categories

Resources