Skip to content

Conversation

Copy link

Copilot AI commented Dec 25, 2025

Implements automated end-to-end testing of WLED web interface served from ESP32 firmware running in QEMU emulation, using Playwright to verify all pages load without JavaScript errors.

Implementation

QEMU ESP32 Emulation

  • Downloads official Espressif QEMU (esp-develop-20220919)
  • Creates merged flash image from bootloader, partitions, and firmware
  • Runs ESP32 firmware with network port forwarding (port 80)

Playwright Test Suite

  • Tests 17+ pages: index, 11 settings pages, utility pages (simple, welcome, update, liveview)
  • Verifies no uncaught JavaScript exceptions via pageerror event listeners
  • Checks page titles and basic UI element presence
  • Configured for QEMU's slower performance (45s test timeout, single worker)

CI Workflow (.github/workflows/qemu-e2e-test.yml)

  • Job 1: Builds web UI and compiles ESP32 firmware for esp32dev target
  • Job 2: Sets up QEMU, boots firmware, waits for HTTP server, runs Playwright tests
  • Uploads test reports and QEMU logs as artifacts

Test Example

test('index page loads without errors', async ({ page }) => {
  const pageErrors = [];
  page.on('pageerror', error => pageErrors.push(error.message));
  
  await page.goto('/index.htm');
  await page.waitForLoadState('load');
  
  expect(pageErrors).toHaveLength(0);
});

Files Added

  • .github/scripts/setup-qemu.sh - QEMU installation
  • .github/scripts/run-qemu.sh - Firmware execution in QEMU
  • .github/workflows/qemu-e2e-test.yml - CI workflow
  • e2e-tests/*.spec.js - Playwright test suites
  • playwright.config.js - Test configuration

QEMU Limitations

WiFi/peripherals are stubbed, network is user-mode only. Sufficient for verifying web UI loads and JavaScript executes without errors.

Next Steps

Workflow requires first-run approval to download external QEMU binary from Espressif. Framework ready for extending to JSON API endpoint validation and WebSocket testing.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • aircoookie.github.io
    • Triggering command: /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell --disable-field-trial-config --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=AcceptCHFrame,AvoidUnnecessaryBeforeUnloadCheckSync,DestroyProfileOnBrowserClose,DialMediaRouteProvider,GlobalMediaControls,HttpsUpgrades,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutoDeElevate,RenderD (dns block)
    • Triggering command: /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell --disable-field-trial-config --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=AcceptCHFrame,AvoidUnnecessaryBeforeUnloadCheckSync,DestroyProfileOnBrowserClose,DialMediaRouteProvider,GlobalMediaControls,HttpsUpgrades,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutoDeElevate,RenderD _TOKEN"; }; f (dns block)
    • Triggering command: /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell --disable-field-trial-config --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=AcceptCHFrame,AvoidUnnecessaryBeforeUnloadCheckSync,DestroyProfileOnBrowserClose,DialMediaRouteProvider,GlobalMediaControls,HttpsUpgrades,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutoDeElevate,RenderD ndor/bin/git (dns block)
  • api.registry.nm1.platformio.org
    • Triggering command: /home/REDACTED/.local/bin/pio pio run -e esp32dev (dns block)
  • api.registry.platformio.org
    • Triggering command: /home/REDACTED/.local/bin/pio pio run -e esp32dev (dns block)
  • collector.platformio.org
    • Triggering command: /home/REDACTED/.local/bin/pio pio run -e esp32dev (dns block)
  • https://storage.googleapis.com/chrome-for-testing-public/143.0.7499.4/linux64/chrome-headless-shell-linux64.zip
    • Triggering command: /usr/local/bin/node /usr/local/bin/node /home/REDACTED/work/WLED-MM/WLED-MM/node_modules/playwright-core/lib/server/registry/oopDownloadBrowserMain.js (http block)
  • https://storage.googleapis.com/chrome-for-testing-public/143.0.7499.4/linux64/chrome-linux64.zip
    • Triggering command: /usr/local/bin/node /usr/local/bin/node /home/REDACTED/work/WLED-MM/WLED-MM/node_modules/playwright-core/lib/server/registry/oopDownloadBrowserMain.js (http block)
  • img.shields.io
    • Triggering command: /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell --disable-field-trial-config --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=AcceptCHFrame,AvoidUnnecessaryBeforeUnloadCheckSync,DestroyProfileOnBrowserClose,DialMediaRouteProvider,GlobalMediaControls,HttpsUpgrades,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutoDeElevate,RenderD (dns block)
    • Triggering command: /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell --disable-field-trial-config --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=AcceptCHFrame,AvoidUnnecessaryBeforeUnloadCheckSync,DestroyProfileOnBrowserClose,DialMediaRouteProvider,GlobalMediaControls,HttpsUpgrades,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutoDeElevate,RenderD hrome-headless-shell-linux64/chrome-headless-shell (dns block)
    • Triggering command: /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell --disable-field-trial-config --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=AcceptCHFrame,AvoidUnnecessaryBeforeUnloadCheckSync,DestroyProfileOnBrowserClose,DialMediaRouteProvider,GlobalMediaControls,HttpsUpgrades,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutoDeElevate,RenderD mcli/run-script/lib/node-gyp-bin/node (dns block)
  • wled00
    • Triggering command: /usr/local/bin/node node tools/cdata.js (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>Verify basic operations in CI</issue_title>
<issue_description>Can we have a CI workflow that uses qemu to actually try running the application on a simulated esp32 and correct with playwright to navigate though the basic pages to confirm that every page loads without JavaScript errors?

We can then later extend with further playwright tests and confirmation of the JSON API

The default image creates a WiFi AP, however using an ethernet supported build might be more appropriate, but then qemu would also need to emulate that ethernet controller as well as the esp32 </issue_description>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@coderabbitai
Copy link

coderabbitai bot commented Dec 25, 2025

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI and others added 3 commits December 25, 2025 10:32
- Add Playwright dependency and test scripts
- Create E2E tests for index, settings, and other pages
- Add QEMU ESP32 setup and run scripts
- Create GitHub Actions workflow for QEMU testing
- Update tests to work with ESP32 backend (not static files)
- Configure proper timeouts for QEMU emulation

Co-authored-by: netmindz <442066+netmindz@users.noreply.github.com>
- Remove mock server (doesn't match requirements)
- Finalize QEMU ESP32 setup and run scripts
- Complete Playwright test suite for all pages
- Update GitHub Actions workflow for QEMU testing
- All pages served from actual ESP32 firmware in QEMU
- Tests verify no JavaScript errors on page load

Co-authored-by: netmindz <442066+netmindz@users.noreply.github.com>
Copilot AI changed the title [WIP] Add CI workflow to verify basic operations with esp32 Add QEMU-based E2E testing with Playwright to verify web UI loads without JavaScript errors Dec 25, 2025
Copilot AI requested a review from netmindz December 25, 2025 10:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Verify basic operations in CI

2 participants