Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
e7af4b2
Initial plan
Copilot Dec 27, 2025
75b148e
Add Wokwi ESP32 simulation testing with Playwright
Copilot Dec 27, 2025
f8f82ea
Update package-lock.json with Playwright dependencies
Copilot Dec 27, 2025
34e5ca3
Improve Wokwi workflow: better logging, error handling, and CommonJS …
Copilot Dec 27, 2025
1a66a9a
Add WOKWI_CLI_TOKEN environment variable to workflow
Copilot Dec 28, 2025
685c75d
Fix wokwi-cli invocation to use current directory instead of diagram.…
Copilot Dec 28, 2025
ae0b312
Export WOKWI_CLI_TOKEN before running simulator script
Copilot Dec 28, 2025
9c0bb96
Add debug step to verify WOKWI_CLI_TOKEN is set before running simulator
Copilot Dec 28, 2025
e2abadc
Rename cdata-test.js to wokwi-test.js to avoid conflict with mdev branch
Copilot Jan 1, 2026
603322a
Merge branch 'mdev' into copilot/verify-wokwi-ci-integration
softhack007 Jan 1, 2026
2c2c590
post-merge fixup
softhack007 Jan 1, 2026
d1a4530
Fix npm test to avoid running Playwright tests with Node test runner
Copilot Jan 1, 2026
9597449
adding [env:esp32_V4_wokwi_debug]
softhack007 Jan 1, 2026
915b766
Switch to esp32_V4_wokwi_debug build and improve debug output collection
Copilot Jan 1, 2026
ebe23c3
Add boot validation scenarios for quick firmware testing
Copilot Jan 1, 2026
6f3c788
Handle WebSocket connection errors gracefully in boot validation
Copilot Jan 1, 2026
be458e3
Fix Wokwi CLI path issue in boot validation step
Copilot Jan 1, 2026
2a36ce6
fix outout redirection in CI script
softhack007 Jan 1, 2026
ac9d3f8
try with tee
softhack007 Jan 1, 2026
45f225c
Revert "try with tee"
softhack007 Jan 1, 2026
fb80167
Add required 'name' field to Wokwi scenario files
Copilot Jan 1, 2026
135ac80
Fix scenario step key: use 'wait' instead of 'sleep'
Copilot Jan 1, 2026
c4584a5
Fix scenario step key: use 'delay' with time units instead of 'wait'
Copilot Jan 1, 2026
326a7e3
Fix README.md scenario example to use correct Wokwi format
Copilot Jan 2, 2026
6ccf8a1
Optimize CI workflow: move Playwright install after boot check and co…
Copilot Jan 2, 2026
9fceaf0
Add firmware verification before boot check scenario
Copilot Jan 2, 2026
41e442c
Enable serial monitor in diagram.json and add firmware verification
Copilot Jan 2, 2026
4011ec3
wokwi: connect serial monitor, additional gdbServerPort
softhack007 Jan 2, 2026
665beca
Fix JSON syntax error in diagram.json - remove trailing comma
Copilot Jan 2, 2026
1edd268
Add bootloader and partitions support for ESP32 filesystem
Copilot Jan 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
250 changes: 250 additions & 0 deletions .github/workflows/wokwi-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
name: Wokwi ESP32 Simulation Test

on:
push:
branches: [ "mdev", "copilot/**" ]
pull_request:
branches: [ "mdev" ]
workflow_dispatch:

jobs:
wokwi-test:
name: Test WLED with Wokwi Simulator
runs-on: ubuntu-22.04

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Cache pip
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-

- name: Cache PlatformIO
uses: actions/cache@v4
with:
path: ~/.platformio
key: ${{ runner.os }}-pio-esp32_V4_wokwi_debug

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.9'

- name: Install PlatformIO
run: pip install -r requirements.txt

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

- name: Install Node.js dependencies
run: npm ci

- name: Build web UI
run: npm run build

- name: Build firmware for ESP32
env:
WLED_RELEASE: True
run: pio run -e esp32_V4_wokwi_debug

- name: Install Wokwi CLI
run: |
curl -L https://wokwi.com/ci/install.sh | sh
echo "Wokwi CLI installed to: $HOME/.wokwi-ci/bin/"
ls -la "$HOME/.wokwi-ci/bin/" || echo "Directory not found"
export PATH="$HOME/.wokwi-ci/bin:$PATH"
wokwi-cli --version || echo "Warning: wokwi-cli not accessible"

- name: Prepare firmware for Wokwi
run: ./test/wokwi/prepare-firmware.sh esp32_V4_wokwi_debug

- name: Debug - Verify token is set
run: |
if [ -z "$WOKWI_CLI_TOKEN" ]; then
echo "❌ ERROR: WOKWI_CLI_TOKEN is not set"
echo "Please configure WOKWI_CLI_TOKEN as a repository secret"
exit 1
else
echo "✅ WOKWI_CLI_TOKEN is set (length: ${#WOKWI_CLI_TOKEN} characters)"
fi
env:
WOKWI_CLI_TOKEN: ${{ secrets.WOKWI_CLI_TOKEN }}

- name: Quick boot validation with scenario
working-directory: test/wokwi
env:
WOKWI_CLI_TOKEN: ${{ secrets.WOKWI_CLI_TOKEN }}
run: |
# Create log directory
mkdir -p logs

# Add Wokwi CLI to PATH for this step
export PATH="$HOME/.wokwi-ci/bin:$PATH"

# Verify firmware files exist
echo "Checking for firmware files..."
if [ ! -f "firmware.bin" ]; then
echo "❌ ERROR: firmware.bin not found in $(pwd)"
echo "Available files:"
ls -la
exit 1
fi
echo "✅ firmware.bin found ($(du -h firmware.bin | cut -f1))"

if [ -f "firmware.elf" ]; then
echo "✅ firmware.elf found ($(du -h firmware.elf | cut -f1))"
else
echo "⚠️ firmware.elf not found (optional for simulation)"
fi

# Verify firmware can be read and has valid ESP32 header
echo ""
echo "Firmware file details:"
ls -lh firmware.bin firmware.elf 2>/dev/null || true
echo ""
echo "Firmware.bin first 64 bytes (hex):"
hexdump -C firmware.bin | head -4 || echo "Cannot read firmware.bin"
echo "Note: ESP32 firmware should start with magic byte 0xe9"

echo ""
echo "Running quick boot check scenario (15 seconds)..."
echo "Wokwi CLI location: $(which wokwi-cli || echo 'NOT FOUND')"
echo "Wokwi CLI version:"
wokwi-cli --version || echo "Warning: Could not get version"
echo ""

# Run boot check with increased timeout to account for startup time
# Using 30 second timeout for a 15 second scenario to allow for network delays
# Capture serial output (stdout) and Wokwi CLI diagnostics (stderr) separately
if wokwi-cli --timeout 30000 --scenario scenarios/boot-check.yaml . > logs/boot-check-serial.log 2>logs/boot-check.log; then
echo "✅ Boot check passed - firmware boots without crashes"
echo ""
echo "=== Boot check serial output (last 50 lines) ==="
tail -50 logs/boot-check-serial.log
echo ""
echo "=== Boot check CLI log (last 50 lines) ==="
tail -50 logs/boot-check.log
else
EXIT_CODE=$?
echo "❌ Boot check failed with exit code $EXIT_CODE"
echo ""
echo "=== Boot check CLI log ==="
cat logs/boot-check.log
echo ""
echo "=== Boot check serial output ==="
cat logs/boot-check-serial.log

# Check if it's a WebSocket connection error (code 1006)
if grep -q "code 1006" logs/boot-check.log || grep -q "Connection.*closed" logs/boot-check.log; then
echo ""
echo "⚠️ WebSocket connection error detected (code 1006)"
echo "This is typically a transient network issue with Wokwi's API."
echo "The workflow will continue with the full simulation test."
echo "If this persists, check Wokwi service status or network connectivity."
# Don't fail - this might be a transient issue
else
# Other errors should fail the build
exit 1
fi
fi

- name: Install Playwright browsers
run: npx playwright install --with-deps chromium

- name: Start Wokwi simulator in background
env:
WOKWI_CLI_TOKEN: ${{ secrets.WOKWI_CLI_TOKEN }}
run: |
cd test/wokwi
# Create log directory
mkdir -p logs

# Export the token so it's available to child processes
export WOKWI_CLI_TOKEN

# Start simulator in background with a 180 second timeout
# Wokwi CLI outputs to stderr, serial output goes to stdout
WOKWI_TIMEOUT=300 ./run-simulator.sh >logs/serial.log 2>&1 &
WOKWI_PID=$!
echo "WOKWI_PID=$WOKWI_PID" >> $GITHUB_ENV
echo "Started Wokwi simulator with PID $WOKWI_PID"

# Wait for simulator to start and web server to be ready
echo "Waiting for WLED web server to be ready..."
max_wait=240
elapsed=0
while [ $elapsed -lt $max_wait ]; do
if curl -s -f http://localhost:8080 > /dev/null 2>&1; then
echo "✅ Web server is ready after $elapsed seconds!"
break
fi
if ! kill -0 $WOKWI_PID 2>/dev/null; then
echo "❌ Error: Wokwi simulator process died"
echo ""
echo "=== Last 100 lines of Wokwi CLI log ==="
tail -100 logs/wokwi.log || true
echo ""
echo "=== Last 100 lines of Serial output ==="
tail -100 logs/serial.log || true
exit 1
fi
echo "Still waiting... ($elapsed seconds)"
sleep 5
elapsed=$((elapsed + 5))
done

if [ $elapsed -ge $max_wait ]; then
echo "❌ Error: Web server did not start within $max_wait seconds"
echo ""
echo "=== Last 100 lines of Wokwi CLI log ==="
tail -100 logs/wokwi.log || true
echo ""
echo "=== Last 100 lines of Serial output ==="
tail -100 logs/serial.log || true
kill $WOKWI_PID || true
exit 1
fi

echo "WLED is ready for testing!"
echo ""
echo "=== First 50 lines of Serial output ==="
head -50 logs/serial.log || true

- name: Run Playwright tests
run: npm run test:wokwi
env:
CI: true

- name: Upload Playwright report
uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 7

- name: Stop Wokwi simulator
if: always()
run: |
if [ ! -z "$WOKWI_PID" ]; then
kill $WOKWI_PID || true
fi

- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: wokwi-test-results
path: |
test/wokwi/logs/
test-results/
playwright-report/
retention-days: 7
14 changes: 14 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,17 @@ compile_commands.json
/wled00/wled00.ino.cpp
/wled00/html_*.h
_codeql_detected_source_root

# Playwright and test artifacts
/test-results/
/playwright-report/
/playwright/.cache/

# Wokwi runtime files
/test/wokwi/firmware.bin
/test/wokwi/firmware.elf
/test/wokwi/bootloader.bin
/test/wokwi/partitions.bin
/test/wokwi/.wokwi/
/test/wokwi/logs/

60 changes: 60 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 7 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
},
"scripts": {
"build": "node tools/cdata.js",
"test": "node --test",
"dev": "nodemon -e js,html,htm,css,png,jpg,gif,ico,js -w tools/ -w wled00/data/ -x node tools/cdata.js"
"test": "node --test tools/cdata-test.js",
"dev": "nodemon -e js,html,htm,css,png,jpg,gif,ico,js -w tools/ -w wled00/data/ -x node tools/cdata.js",
"test:cdata": "node tools/cdata-test.js",
"test:wokwi-cdata": "node tools/wokwi-test.js",
"test:wokwi": "playwright test test/playwright/wokwi-basic.spec.js"
},
"repository": {
"type": "git",
Expand All @@ -26,7 +29,8 @@
"clean-css": "^5.3.3",
"html-minifier-terser": "^7.2.0",
"web-resource-inliner": "^7.0.0",
"nodemon": "^3.1.9"
"nodemon": "^3.1.9",
"@playwright/test": "^1.40.0"
},
"engines": {
"node": ">=20.0.0"
Expand Down
Loading
Loading