I have a problem with getting elements by their selectors.
A page on which I struggle is: /. What I have succeded is to log in, but that was kind of a hack, because I used the fact, that the field I need to fill is already selected.
After typing in nick and going into lobby I want to click the button 'Create room'. Its selector: body > div > div > div > div > div.buttons > button:nth-child(3)
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
args: ['--no-sandbox'], headless: false, slowMo: 10
});
const page = await browser.newPage();
await page.goto('.html');
await page.keyboard.type(name);
await page.keyboard.press('Enter');
//at this point I am logged in.
let buttonSelector = 'body > div > div > div > div > div.buttons > button:nth-child(3)';
await page.waitForSelector('body > div > div');
await page.evaluate(() => {
document.querySelector(buttonSelector).click();
});
browser.close();
})();
after running such code I get error:
UnhandledPromiseRejectionWarning: Error: Evaluation failed: TypeError: Cannot read property 'click' of null
My initial approach was with: await page.click(buttonSelector); instead of page.evaluate but it also fails.
What frustrates my the most is the fact that when I run in Chromium console: document.querySelector(buttonSelector).click(); it works fine.
I have a problem with getting elements by their selectors.
A page on which I struggle is: http://html5.haxball./. What I have succeded is to log in, but that was kind of a hack, because I used the fact, that the field I need to fill is already selected.
After typing in nick and going into lobby I want to click the button 'Create room'. Its selector: body > div > div > div > div > div.buttons > button:nth-child(3)
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
args: ['--no-sandbox'], headless: false, slowMo: 10
});
const page = await browser.newPage();
await page.goto('http://html5.haxball./index.html');
await page.keyboard.type(name);
await page.keyboard.press('Enter');
//at this point I am logged in.
let buttonSelector = 'body > div > div > div > div > div.buttons > button:nth-child(3)';
await page.waitForSelector('body > div > div');
await page.evaluate(() => {
document.querySelector(buttonSelector).click();
});
browser.close();
})();
after running such code I get error:
UnhandledPromiseRejectionWarning: Error: Evaluation failed: TypeError: Cannot read property 'click' of null
My initial approach was with: await page.click(buttonSelector); instead of page.evaluate but it also fails.
What frustrates my the most is the fact that when I run in Chromium console: document.querySelector(buttonSelector).click(); it works fine.
Share Improve this question edited Jun 9, 2018 at 9:00 Artur Pschybysz asked Jan 26, 2018 at 19:59 Artur PschybyszArtur Pschybysz 3033 silver badges12 bronze badges1 Answer
Reset to default 4A few things to note:
- The selector you are using to retrieve the button is more plex than it needs to be. Try something simpler like:
'button[data-hook="create"]'
. The game is within an
iframe
, so you're better off callingdocument.querySelector
using theiframe
'sdocument
object as opposed to the containing window'sdocument
The function passed to
evaluate
is executed in a different context than where you are running your node script. For this reason, you have to explicitly pass variables from your node script to the window script otherwisebuttonSelector
will be undefined:
Making the changes above, your code will input your name and successfully click on "Create Room":
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
args: ['--no-sandbox'], headless: false, slowMo: 10
});
const page = await browser.newPage();
await page.goto('http://html5.haxball./index.html');
await page.keyboard.type('Chris');
await page.keyboard.press('Enter');
//at this point I am logged in.
let buttonSelector = 'button[data-hook="create"]';
await page.waitForSelector('body > div > div');
await page.evaluate((buttonSelector) => {
var frame = document.querySelector('iframe');
var frameDocument = frame.contentDocument;
frameDocument.querySelector(buttonSelector).click();
}, buttonSelector);
browser.close();
})();