UI tests with Puppeteer on GitHub Actions
Running end-to-end UI tests with Puppeteer on every push or pull request — and capturing screenshots as artifacts — lets you catch regressions early and debug failures without reproducing them locally. In this article, we’ll use your existing test script and GitHub Actions workflow to:
- Show the Puppeteer test
2. Walk through the GitHub Actions YAML
3. Explain how artifacts (screenshots) are uploaded
4. Verify and view results in the GitHub UI
Prerequisites
A GitHub repository containing:
Your Puppeteer test in tests/example.test.js
A workflow file at .github/workflows/puppeteer.yml
Node.js 18+ (installed locally for development)
A GitHub Actions–enabled repo (no extra setup required)
1. Your Puppeteer Test
Place this file at tests/example.test.js:
// tests/example.test.js
const puppeteer = require('puppeteer');
(async () => {
// Launch headless Chromium without sandbox (required on GitHub runners)
const browser = await puppeteer.launch({
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
const page = await browser.newPage();
// Navigate and capture a full-page screenshot
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
await page.screenshot({ path: 'example.png', fullPage: true });
console.log('✅ Screenshot saved as example.png');
await browser.close();
})();
Tip: The — no-sandbox flags are necessary on Ubuntu runners where unprivileged user namespaces are disabled.
2. GitHub Actions Workflow
Create a file at .github/workflows/puppeteer.yml with the following content:
name: Puppeteer CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
# 1. Check out your code
- name: Checkout repository
uses: actions/checkout@v4
# 2. Install Node.js 18
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
# 3. Install npm dependencies
- name: Install dependencies
run: npm i --no-package-lock
# 4. Install system libs Puppeteer's Chromium needs
- name: Install Puppeteer dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
libx11-6 libxcomposite1 libxcursor1 libxdamage1 libxext6 \
libxfixes3 libxi6 libxtst6 libnss3 libglib2.0-0 libgtk-3-0t64 \
libasound2t64 libxrandr2 libpangocairo-1.0-0 libatk1.0-0 \
libatk-bridge2.0-0 libcups2 libdbus-1-3 libdrm2 libgbm1 \
libgdk-pixbuf2.0-0
# 5. Run the Puppeteer test
- name: Run Puppeteer test
run: npm test
# 6. Upload screenshot as an artifact
- name: Upload screenshot artifact
if: success()
uses: actions/upload-artifact@v4
with:
name: example-screenshot
path: example.png
What each step does
Checkout repository
Fetches your code so the runner can access both the workflow and the test files.
Set up Node.js
Installs Node.js 18 and enables caching if you enable cache: ‘npm’ later.
Install dependencies
Runs npm i — no-package-lock per your preference — no lock file gets created or used.
Install Puppeteer system libs
Puppeteer’s bundled Chromium needs several GTK, X11, and audio libraries on Linux.
Run the test
Executes npm test, which should be configured in your package.json as
{ "scripts": { "test": "node tests/example.test.js" } }
Upload artifact
If the test succeeds, example.png is archived and attached to the workflow run.
3. Viewing Artifacts
After a push or PR, open the Actions tab in your GitHub repo.
Select the latest Puppeteer CI run.
In the Artifacts section, click example-screenshot to download a ZIP containing example.png.
Open the PNG to see exactly what the page looked like in CI.
Capturing artifacts on success means you have a record of your “known good” output to compare against future failures.
4. Debugging Tips
- Test failures: If npm test errors out, the workflow will stop before uploading. To capture screenshots even on failure, change the upload step’s condition to if: success() || failure().
- Slow CI installs: Consider adding actions/cache@v4 to cache your node_modules (you’d need to reintroduce package-lock.json).
- Local validation: Run your test locally with node tests/example.test.js to ensure no environment-specific issues.
Conclusion
Integrating Puppeteer into GitHub Actions with artifact uploads gives you automated UI validation plus visual proof of what ran in CI. You’ll catch layout regressions, script errors, or unexpected redirects — complete with screenshots you can download directly from the GitHub UI. With this setup in place, every push to main and every pull request will automatically produce both pass/fail feedback and the artifacts you need to diagnose issues.
I have created a project on GitHub and added the code here.
Also, I have kept the job in public in case you guys want to check the implementation here.
Feel free to hit clap if you like the content. Happy Automation Testing :) Cheers. 👏