Goal: Implement automated regression testing for EchoKit Chrome extension in CI/CD pipeline that blocks PR merges to develop unless all tests pass.
Current State:
tests/smoke_echokit.py) with 24 assertionsRecommended Solution: Multi-tiered approach combining headless-compatible tests with strategic use of headed mode in CI.
channel: 'chromium'new headless modeVerdict: Stick with Playwright - EchoKit already uses it, and it has the best modern extension support.
Chrome extensions with service workers have historically struggled in headless mode:
Option A: New Chromium Channel (Preferred)
context = playwright.chromium.launch_persistent_context(
user_data_dir,
channel='chromium', # Key: Uses newer headless implementation
args=[
'--disable-extensions-except=/path/to/extension',
'--load-extension=/path/to/extension'
]
)
✅ Works in CI
✅ No display server needed
✅ Official Playwright recommendation
Option B: Xvfb (Virtual Display Server)
- name: Run tests
run: xvfb-run -a python3 tests/smoke_echokit.py
✅ Works reliably
⚠️ Requires Linux (Ubuntu/Debian)
⚠️ Slightly slower than pure headless
Option C: GitHub Actions with Headed Mode
- uses: browser-actions/setup-chrome@latest
- run: python3 tests/smoke_echokit.py
env:
DISPLAY: ':99'
Requires additional setup but most reliable.
Following industry best practices (Chrome Extension Testing Guide 2026):
/\
/10\ E2E Tests (Playwright - Full browser)
/____\
/ \
/ 20% \ Integration Tests (API + State)
/__________\
/ \
/ 70% \ Unit Tests (Jest/Vitest - Fast)
/________________\
shared/app.js - UI state managementshared/matcher.js - Request matching logicshared/json-highlight.js - JSON formattingsmoke_echokit.py)Prevent “blank screen” bugs that slip through functional tests.
from percy import percy_snapshot
percy_snapshot(browser, "EchoKit Popup - Default State")
✅ Easy setup, hosted comparison
✅ Works in CI out of box
✅ PR comments with visual diffs
❌ Costs $249+/month for private repos
await page.screenshot(path='baseline.png')
assert compare_images('baseline.png', 'current.png', threshold=0.01)
✅ Free and self-hosted
✅ Full control over baselines
❌ Manual baseline management
❌ No automatic PR comments
Recommendation: Start with Playwright built-in visual comparison (free), evaluate Percy after 3 months if needed.
Objective: Get existing smoke tests running in CI
Tasks:
tests/smoke_echokit.py to use channel='chromium'.github/workflows/test.ymlsmoke job to passAcceptance Criteria:
developFiles to Modify:
tests/smoke_echokit.py (add channel=’chromium’).github/workflows/test.yml (remove if: false, update setup)BRANCH_PROTECTION_SETUP.md (document new rule)Objective: 70% test coverage with fast unit tests
Tasks:
shared/matcher.js - 20 test casesshared/app.js - state management testsshared/json-highlight.js - formatting testsNew Files:
tests/unit/matcher.test.jstests/unit/app.test.jsvitest.config.js.github/workflows/test.yml (add unit test step)Objective: Catch UI regressions automatically
Tasks:
tests/baselines/Implementation:
# In smoke_echokit.py
def test_popup_renders():
popup_page.goto(popup_url)
popup_page.wait_for_selector('[data-testid="echokit-app"]')
# Visual regression check
actual = popup_page.screenshot()
baseline = Path('tests/baselines/popup-default.png')
diff = compare_images(baseline, actual)
assert diff < 0.02, f"Visual diff {diff:.2%} exceeds threshold"
Objective: Test message passing and Chrome API interactions
Tasks:
tests/smoke_echokit.pyChange Required:
# Current (line ~100-120):
context = p.chromium.launch_persistent_context(
"",
headless=False, # ❌ Doesn't work in CI
args=[...]
)
# Updated:
context = p.chromium.launch_persistent_context(
"",
channel='chromium', # ✅ Enables headless extension support
headless=True, # ✅ Works in CI
args=[...]
)
.github/workflows/test.ymlRemove the if: false gate:
smoke:
runs-on: ubuntu-latest
if: false # ❌ Remove this line
Update to:
smoke:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: '3.11' }
- name: Install Playwright
run: |
pip install playwright
python -m playwright install chromium
- name: Run smoke tests
run: python3 tests/smoke_echokit.py
GitHub Settings → Branches → Branch protection rules:
Rule for develop:
Track these to measure testing effectiveness:
| Metric | Current | Target (1 month) |
|---|---|---|
| Tests passing in CI | 0% (disabled) | 100% |
| Test runtime in CI | N/A | < 2 minutes |
| PRs blocked by tests | 0 | All failing PRs |
| Blank screen bugs in prod | 1+ | 0 |
| Test coverage | ~5% (E2E only) | 40%+ (unit + E2E) |
| Time to debug failures | Hours | < 10 minutes |
Cause: Extension doesn’t have a service worker
Fix: Ensure manifest.json includes:
"background": {
"service_worker": "background.js"
}
Cause: Headless mode doesn’t support extensions (old headless)
Fix: Use channel: 'chromium' in launch config
Cause: CSP violations or missing resources Fix:
web_accessible_resourcesheadless: False locally to debugCause: Race conditions, timing issues Fix:
page.wait_for_selector() instead of time.sleep()timeout=10000 (10 seconds)context.wait_for_event('serviceworker')Cause: Branch protection not configured Fix: Enable required status checks in GitHub settings
To run tests locally:
# Install dependencies
pip install playwright
python -m playwright install chromium
# Run all tests
python3 tests/smoke_echokit.py
# Run with headed browser (for debugging)
HEADLESS=false python3 tests/smoke_echokit.py
To add a new test case:
# In tests/smoke_echokit.py
def step(name, ok, detail=''):
# ... existing code ...
# Add your test
resp = popup_page.evaluate("window.doFetch('/api/new-endpoint')")
step("NEW: New endpoint captured",
resp['status'] == 200 and 'expected_field' in resp['body'])
To update visual baselines (after intentional UI changes):
# Take new baseline screenshots
python3 tests/smoke_echokit.py --update-baselines
# Review changes
git diff tests/baselines/
# Commit new baselines
git add tests/baselines/
git commit -m "chore: update visual test baselines for new UI"
Q: Will this slow down our development velocity? A: Initially ~10 minutes to set up, then saves hours debugging production issues. Net positive after first week.
Q: What if tests are flaky? A: Start with deterministic tests (syntax, structure). Add E2E tests carefully with proper waits. Aim for <1% flake rate.
Q: Can we skip tests for hotfixes? A: No. Tests are especially important for hotfixes. Use feature flags to disable risky features instead.
Q: What about manual testing? A: Automated tests complement (not replace) manual testing. Still manually test before releases.
Q: How do we handle breaking changes to the test suite?
A: Update tests in same PR as code changes. Never merge broken tests to develop.
Last Updated: 2026-05-12
Document Owner: Development Team
Related Docs: AUTOMATED_TESTING.md, CONTRIBUTING.md, .github/workflows/test.yml