UI Testing with Puppeteer by Dario Kondratiuk

UI Testing with Puppeteer by Dario Kondratiuk

Author:Dario Kondratiuk
Language: eng
Format: epub
Publisher: Packt Publishing
Published: 2021-03-10T00:00:00+00:00


Variable scopes in Puppeteer

As you can see, the name didn't get to the alert. For us as developers, the big issue is that the code looks good. If you look at the code, the code is perfect. It's not very different from our previous examples. But something works differently there. Once you understand this, you will be able to answer lots of questions on Stack Overflow.

First, the signature of page.evaluate is page.evaluate(pageFunction[, ...args]), where pageFunction can be a string or a function. The second argument is an optional list of values to pass to pageFunction.

You can pass expressions as strings to the evaluate function. An expression is a statement like the ones you can write inside the DevTools console. For instance, a simple string returning the URL property of the document object:

console.log(await page.evaluate('document.URL'));

page.evaluate will send the expression document.URL to the browser and the browser will evaluate it. Once the browser evaluates the expression, it will send that back to Puppeteer, and page.evaluate will return the result. In this case, about:blank.

Expressions are perfect when you want to evaluate simple expressions. But you could accomplish the same result using a JavaScript function:

console.log(await page.evaluate(() => document.URL));

As you can see, passing an expression is more straightforward, but you will be able to write more complex code using functions, and, no less important, you will get the autocomplete features of your code editor.

The key concept here is that page.evaluate will send the expression to the browser. How can Puppeteer send a function to the browser? It will serialize it. As I mentioned before, functions are first-class citizens in JavaScript, which means that you can call toString() to function inside a variable. Let's try that out:

console.log((() => alert('Hello ' + name)).toString());

This will print the function as a string value in the console:

() => alert('Hello ' + name)

If Puppeteer takes that function, converts it to a string using toString, and sends it to the browser, the value of the name variable will be lost in the process.

When you send a function to be evaluated inside the browser context, you need to make sure that all the values the function uses are already in the browser or are being passed as an argument. This is how we can fix our code:

const browser = await puppeteer.launch({headless: false, defaultViewport: null});

const page = await browser.newPage();

const name = 'world';

await page.evaluate((n) => alert('Hello ' + n), name);

browser.close();

As we can see, we are passing the name variable as part of the args argument of evaluate. Now Puppeteer knows that it has to serialize that function and also send args. The browser will now be able to execute that function, passing those arguments.

Tip

Notice that I renamed the variable name to n. It's not required, but this practice will help you avoid these kinds of scope mistakes. Now you, and your IDE, know that the n variable being used in the alert function is an argument being passed to that function.

This evaluate function is available not only in the page and frame classes but also in the JSHandle and ElementHandle classes.



Download



Copyright Disclaimer:
This site does not store any files on its server. We only index and link to content provided by other sites. Please contact the content providers to delete copyright contents if any and email us, we'll remove relevant links or contents immediately.