I wonder why my second console.log() not logs anything to the console...
describe('Puppeteer', () => {
it('Does not log', () => {
(async () => {
console.log('This logs'); // <- works
const browser = await puppeteer.launch({
headless: true,
args: [
'--incognito'
]
});
await console.log('This does not log'); // <- Does not work
console.log('This does not log too'); // <- This neither
const page = await browser.newPage();
await page.goto('....');
....
expect(a < b)
.toEqual(true);
browser.close();
})();
});
});
Is there any reason why that does not log?
Solution: This does not work because you are running the block instantly. Make sure to pass a function which is not self executing.
A example of self executing function is (()=>{})(). This prevents the test from resolving properly.
Here is the cleaned up code:
const puppeteer = require('puppeteer');
const assert = require('assert');
describe('Puppeteer', () => {
it('Does log', async () => { // <== PASS THE FUNCTION HERE
const browser = await puppeteer.launch({args: ['--incognito']});
console.log('This logs now');
const page = await browser.newPage();
await page.goto('https://example.org');
const title = await page.title();
assert.equal(title, 'Example Domain');
console.log('This logs too');
await browser.close();
})
});
Result:
The question has jest instead of mocha. Here is the code for jest and result. Which is almost same except following line,
// assert.equal(title, 'Example Domain');
expect(title).toEqual('Example Domain');
Result:
Optionally if you want to stack the logs together, you can pass --verbose=false when running jest.
Related
im currently trying to catch an error occured by injected script.
what ive done
const path = require('path');
const puppeteer = require('puppeteer');
describe('Test page', () => {
it('should fail on script error', async () => {
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
await page.addScriptTag({ path: path.join(__dirname, 'test.js') });
await browser.close();
});
});
my test.js
console.log(qwerty)
i need to work with scenario where my spec handles loaded script errors. Ive tried to watch for window errors within evaluate block const error = await page.evaluate(() => window.onerror = () => console.log('error')) but seems no results, also tried to catch this errors from puppeteer page like
page.on('pageerror', function(err) {
console.log(err);
});
i feel like im digging in a wrong context
Puppeteer version: 9.0.0
Platform / OS version: google cloud functions
Node.js version: 14
const puppeteer = require('puppeteer')
exports.MyFunc = function MyFunc(req, res) {
MyFunc(req, res);
async function MyFunc(req, res) {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await getSearchResults();
async function getSearchResults() {
const url = `https://abc.redacted.com/search?q=${query}&f=&orderBy=${sort_by}&skip=0&take=10`;
console.log(url);
await page.goto(url, { waitUntil: "domcontentloaded" });
console.log("Page downloaded"); // It console logs till here
const getResults = await page.evaluate(() => {
let items = [];
const results = document.querySelectorAll(
"#mainArea > router-view > ma-serp > div > div.results > div > compose > div > div.results > ma-card"
);
console.log(results);
for (let result of results) {
console.log(result.querySelector("span")?.innerText ?? "");
items.push({ title: result.querySelector("span")?.innerText ?? "", })
};
return items;
});
const data = getResults;
res.status(200).json(data); // just getting {}
await browser.close();
}
}
}
IDK why but page.evaluate() doesn't console log anything and doesn't return anything to node environment. From three days I'm trying different solutions on stack overflow and GitHub issues but no success until now.
I've also tried promise.resolve() when returning from page.evaluate but that doesn't work either.
When you run page.evaluate() you are actually operating within the browser context, not Node. So console.log outputs to the browser context and you will not see anything in your Node console.
Here is a workaround to get the browser context to output to the node console:
const page = await browser.newPage();
page.on('console', consoleObj => console.log(consoleObj.text()));
Reference: Puppeteer log inside page.evaluate
If I 'goto' a web page that contains async code, it is not executed and I don't understand why. Can anyone please help?
Node:
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('http://127.0.0.1:8080/?code=ABC123&id=1', {
waitUntil: 'networkidle0',
});
await page.screenshot({ path: 'example.png' });
await browser.close();
})();
web page:
onmount = () => {
const params = new URLSearchParams(document.location.search);
const code = params.get('code');
// above lines are executed
// the code below is never executed
// search is an async function (not shown for brevity)
search(code).then(result => document.getElementById('title').textContent = result.title);
};
You could use page.waitForFunction to listen to the expected result of the original function. Like this, you can make sure the next step (page.screenshot) will happen only after the onmount promise is resolved in the app.
For this purpose, you could declare the value of the code= URL parameter on the top so you could compare its value later on passing it to the waitForFunction method as an argument.
await page.waitForFunction(codeValue => document.querySelector('#title').textContent == codeValue, {}, codeValue);
Example:
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
const codeValue = 'ABC123';
await page.goto(`http://127.0.0.1:8080/?code=${codeValue}&id=1`, {
waitUntil: 'networkidle0',
});
await page.waitForFunction(codeValue => document.querySelector('#title').textContent == codeValue, {}, codeValue);
await page.screenshot({ path: 'example.png' });
await browser.close();
})();
const puppeteer = require('puppeteer');
const init = async () => {
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
// login
let login = async () => {
console.log('login init');
await page.goto(HOME_PAGE);
await page.type($clientID, CLIENT_ID);
await page.type($userName, USER_NAME);
await page.type($password, PASSWORD);
await page.click($submitBtn);
await page.waitFor(WAIT_SEC);
await page.goto(SCHEDULE_PAGE);
console.log('login end');
}
// look for schedule
let setStartDate = async () => {
console.log('start init');
await page.waitFor(3000);
await page.click('#selfsched_startDate_dtInput', { clickCount: 3 });
await page.keyboard.press('Backspace');
await page.type($startDate, START_DATE);
console.log('start end');
}
let setEndDate = async () => {
console.log('end init');
await page.click($endDate, { clickCount: 3 });
await page.keyboard.press('Backspace');
await page.type($endDate, END_DATE);
await page.keyboard.press('Enter');
console.log('end end');
}
let confirmSchedule = async () => {
console.log('confirm init');
await page.waitFor(WAIT_SEC);
await page.click($confirmBtn);
console.log('confirm end');
}
let steps = [
login(),
setStartDate(),
setEndDate(),
confirmSchedule()
];
await Promise.all(steps);
console.log('im finishing');
browser.close();
}
init()
.then(values => {
console.log('success');
})
.catch(err => {
});
Whenever my code gets to the setStartDate function nothing happens. I've added console.log messages but they're not coming in sequential order as i thought they would. I thought Promise.all() waits for everything in order..... also my knowledge in async / promises / await is not the greatest :) Thanks for the help
order of console logs im getting
login init
start init
end init
confirm init
login end
I thought Promise.all() waits for everything in order
This is basically the opposite of what Promise.all does:
There is no implied ordering in the execution of the array of Promises given. On some computers, they may be executed in parallel, or in some sense concurrently, while on others they may be executed serially. For this reason, there must be no dependency in any Promise on the order of execution of the Promises.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
You should just await your functions in order:
await login()
await setStartDate()
await setEndDate()
await confirmSchedule()
I want to generate two separate report for a single test case. For that, I am using browser.getCapabitities method in the test by which I am getting the browser name and version.
Now, when I use this variable at the end of the spec description, the value is undefined. The browserNameforSpec is getting value before describe. Only when I use this value at the end of the spec, it shows undefined. I am not able to get the reason why this happens. Is there any way to change the name of this spec description before test started.
My code is
let capsPromise = browser.getCapabilities();
let browserNameforSpec;
capsPromise.then(function(caps) {
console.log(caps);
let browserName = caps.get('browserName');
let browserVersion = caps.get('version');
browserNameforSpec = browserName + '-' + browserVersion + '-';
console.log(browserNameforSpec);
});
describe( '0030 Test for login' + browserNameforSpec, function () { // this.browserNameforSpec value is undefined
// 1.
it('Navigate to the login page', async () => {
await navigate.to.the(loginPage);
});
// 2
it('Click onto language button', async() => {
await click.onto(languageButton);
await expect(languageDropdown.isDisplayed());
});
// 3
it('English Language is selected', async() => {
await click.onto(englishLanguage);
await expect(languageButton.getText()).toBe('English');
});
// 4.
it('Correct user name is written into email field', async() => {
await usernameField.click();
await enter(correctUsername, into(usernameField));
});
// 5.
it('Correct password is written into password field', async() => {
await passwordField.click().then(function () {
passwordField.clear();
enter(correctPassword, into(passwordField));
})
});
// 6.
it('Login button is clicked and home page is opened', async() => {
await click.onto(loginButton);
});
});
Add the below code in your onPrepare()
browser.getCapabilities().then(function (cap) {
browser.browserName = cap.caps_.browserName;
});
You call in your test as below
describe( '0030 Test for login' + browser.browserName, function () {
// 1.
it('Navigate to the login page', async () => {
await navigate.to.the(loginPage);
});
Hope it helps you..
Issue is :
1. You are using this.browserNameforSpec which will be undefined as the function context gets changed, You have declared browserNameforSpec as a variable which is directly available in all function but you are calling on this)
2. browser.getCapabilities() returning an instance of Promise that's why the execution flow is different. First it is executing this function and the describe(). But. they need to be called in sync manner.
Below code is using another .then for executing it in a sequential manner. Try to use below code :
let capsPromise = browser.getCapabilities();
let browserNameforSpec;
capsPromise
.then(function(caps) {
console.log(caps);
let browserName = caps.get('browserName');
let browserVersion = caps.get('version');
browserNameforSpec = browserName + '-' + browserVersion + '-';
console.log(browserNameforSpec);
})
.then(function() {
describe( '0030 Test for login' + browserNameforSpec, function () {
// 1.
it('Navigate to the login page', async () => {
await navigate.to.the(loginPage);
});
// 2
it('Click onto language button', async() => {
await click.onto(languageButton);
await expect(languageDropdown.isDisplayed());
});
// 3
it('English Language is selected', async() => {
await click.onto(englishLanguage);
await expect(languageButton.getText()).toBe('English');
});
// 4.
it('Correct user name is written into email field', async() => {
await usernameField.click();
await enter(correctUsername, into(usernameField));
});
// 5.
it('Correct password is written into password field', async() => {
await passwordField.click().then(function () {
passwordField.clear();
enter(correctPassword, into(passwordField));
})
});
// 6.
it('Login button is clicked and home page is opened', async() => {
await click.onto(loginButton);
});
});
});