Skip to content

Instantly share code, notes, and snippets.

@sojungko
Last active February 2, 2018 21:57
Show Gist options
  • Save sojungko/9c74db2587d2fe21fdb70bfbc9413a5e to your computer and use it in GitHub Desktop.
Save sojungko/9c74db2587d2fe21fdb70bfbc9413a5e to your computer and use it in GitHub Desktop.
Helpful Tips for Writing Puppeteer-powered Integration Tests

Suggested Steps

  1. Ensure you have the following env variables in your local repo:
CHROME_HEADLESS=false
CHROME_EXECUTABLE=default

CHROME_HEADLESS=false will disable headless mode, enabling you to see browser action as it unfolds. This is obviously very helpful for debugging purposes. Without these environment variables, you will not be able to run any integration tests because puppeteer looks for these when launching Chromium!

  1. Make sure to set the proper viewport for the device you are testing. For desktop, { width: 2560, height: 1440 } is suggested. Viewport will sometimes make or break your tests because the default puppeteer viewport { width: 800, height: 600 } may conceal some of the key elements the browser must be able to see to interact with it. Not having the appropriate viewport may result in errors like these.

  2. Consider running your tests in slowMo mode. This adds delay in miliseconds (at the time of writing, you may edit this property in PUPPETEER_OPTIONS in test/options.js). This will help you troubleshoot why some of your tests may be failing. Common reasons for failing tests include not choosing the right selector to wait for or failing to designate an element your test needs to wait for before proceeding. Another common reason is unnecessarily waiting for an element that already exists in the DOM. This will result in a timeout.

  3. If all tests pass in slowMo, you will have to ensure that they do at 0 miliseconds delay, too. This is going to be another monster to tackle! You will likely discover that you aren't waiting for an element when you need to or didn't pick the right element to wait for, or are unnecessarily waiting for an element that already exists in the DOM. Good luck!! 😂

  4. A potentially useful debugging tool is to add puppeteer:mouse,puppeteer:keyboard to your DEBUG= env variable, which will log all puppeteer action. Taken from puppeteer documentation:

 env DEBUG="puppeteer:*" node script.js

 # Debug output can be enabled/disabled by namespace
 env DEBUG="puppeteer:*,-puppeteer:protocol" node script.js # everything BUT protocol messages
 env DEBUG="puppeteer:session" node script.js # protocol session messages (protocol messages to targets)
 env DEBUG="puppeteer:mouse,puppeteer:keyboard" node script.js # only Mouse and Keyboard API calls

 # Protocol traffic can be rather noisy. This example filters out all Network domain messages
 env DEBUG="puppeteer:*" env DEBUG_COLORS=true node script.js 2>&1 | grep -v '"Network'

I suggest just logging the mouse and keyboard actions because puppeteer traffic can be quite heavy.

Other General Tips

  1. Avoid unnecessary or repetitive navigation you don't actually need. This will slow down test speed and could cause timeout when our remote bot runs it. If you need to test a navigation behavior, only do so once unless otherwise necessary.
  2. Ditto for unnecessary beforeEach and afterEach. If you can get away with performing an action once before and once after all tests, consider using before or after instead. For instance, you likely don't need to open a new page or new browser for every single test.
  3. Make sure to close the browser after you've opened it e.g
after(async function () {
  await browser.close()
})

Not doing so may cause memory leaks or eat up CPU!

  1. Avoid hardcoding waitFor like page.waitFor(500) because you can’t rely on the network speed when the bot run these tests. Try to always use a specific selector. An exception to this rule is when the UI does not update along with the DOM. For instance, when a user edits his/her name, the name may not be updated immediately in the UI, likely because we are not waiting for the server response to update it. In this case, you may have to resort to a hard-coded wait, but a more robust solution would be to update the UI only after you've received a server response that confirms the name was updated.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment