Advanced
PercyScript uses Google Puppeteer—a Node library that provides a high-level API to control headless Chrome—as the driver for the browser.
More complex interactions
You can use any of the Puppeteer Page API with the PercyScript page
object for more complex interactions.
Show the browser as it's running
You can pass the headless: false
option to PercyScript
, which will turn off Chrome headless mode and show you the Chrome instance as it runs the script.
const options = {headless: false};
PercyScript.run(async (page, percySnapshot) => {
// ...
}, options);
Tip: you can pass any of the Puppeteer launch options to the options
argument.
Mocking network requests
Testing pages with dynamic data can cause diffs when the data changes between snapshots. One way to stop that from happening is by intercepting the network request and sending a mocked response instead. To do this, we'll make use of Puppeteers request interception API. At the very top of your PercyScript run
function, you'll want to set page.setRequestInterception
to true:
PercyScript.run(async (page, percySnapshot) => {
await page.setRequestInterception(true);
// ...
});
It's important to do this before visiting URL you want to snapshot.
Once that's done you're ready to start mocking any of the URLs the visited page requests. This is done by adding an page.on('request')
event listener:
PercyScript.run(async (page, percySnapshot) => {
await page.setRequestInterception(true);
// Listen to each page request
page.on("request", request => {
// Find the request you want to mock out
if (request.url().includes("/v1/your-api-endpoint")) {
// TODO
} else {
// We must tell puppeteer to let normal requests happen:
request.continue();
}
});
await page.goto("https://example.com");
});
Now that we're listening to each request the page makes and picking the request that we want to mock, it's time to actually respond with our fake data. This is done by using Puppeteers respond
API:
PercyScript.run(async (page, percySnapshot) => {
await page.setRequestInterception(true);
// Listen to each page request
page.on("request", request => {
// Find the request you want to mock out
if (request.url().includes("/v1/your-api-endpoint")) {
request.respond({
status: 200,
contentType: "application/json; charset=utf-8",
// The mocked data you want to return
body: JSON.stringify({ foo: "bar" })
});
} else {
// We must tell puppeteer to let normal requests happen:
request.continue();
}
});
await page.goto("https://example.com");
await percySnapshot('home page')
});
Now you can run your snapshots with mocked data that you control for the tests! No more diffs related to changing data. 🎉 This can get pretty lengthy with a few mocks, so it's common to pull this setup out into a helper function like so:
async function setupMocks(page) {
await page.setRequestInterception(true);
// Listen to each page request
page.on("request", request => {
// Find the request you want to mock out
if (request.url().includes("/v1/your-api-endpoint")) {
request.respond({
status: 200,
contentType: "application/json; charset=utf-8",
// The mocked data you want to return
body: JSON.stringify({ foo: "bar" })
});
} else {
// We must tell puppeteer to let normal requests happen:
request.continue();
}
});
}
PercyScript.run(async (page, percySnapshot) => {
await setupMocks(page);
await page.goto("https://example.com");
});
Updated about 4 years ago