- 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!
-
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. -
Consider running your tests in
slowMo
mode. This adds delay in miliseconds (at the time of writing, you may edit this property inPUPPETEER_OPTIONS
intest/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. -
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!! 😂 -
A potentially useful debugging tool is to add
puppeteer:mouse,puppeteer:keyboard
to yourDEBUG=
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.
- 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.
- Ditto for unnecessary
beforeEach
andafterEach
. If you can get away with performing an action once before and once after all tests, consider usingbefore
orafter
instead. For instance, you likely don't need to open a new page or new browser for every single test. - 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!
- Avoid hardcoding
waitFor
likepage.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.