Skip to content

Commit d8934bb

Browse files
Copilotnetmindz
andcommitted
Add QEMU-based E2E testing infrastructure with Playwright
- 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 <[email protected]>
1 parent c0aa75c commit d8934bb

File tree

11 files changed

+738
-1
lines changed

11 files changed

+738
-1
lines changed

.github/scripts/run-qemu.sh

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#!/bin/bash
2+
# Run WLED firmware in QEMU ESP32
3+
# This script starts QEMU with the compiled firmware and enables network access
4+
5+
set -e
6+
7+
FIRMWARE_DIR="${1:-.pio/build/esp32dev}"
8+
QEMU_DIR="${2:-qemu-esp32}"
9+
HTTP_PORT="${3:-80}"
10+
11+
if [ ! -d "$FIRMWARE_DIR" ]; then
12+
echo "Error: Firmware directory not found: $FIRMWARE_DIR"
13+
exit 1
14+
fi
15+
16+
if [ ! -f "${QEMU_DIR}/qemu-system-xtensa" ]; then
17+
echo "Error: QEMU not found at ${QEMU_DIR}/qemu-system-xtensa"
18+
echo "Please run setup-qemu.sh first"
19+
exit 1
20+
fi
21+
22+
# Check for required firmware files
23+
BOOTLOADER="${FIRMWARE_DIR}/bootloader.bin"
24+
PARTITIONS="${FIRMWARE_DIR}/partitions.bin"
25+
FIRMWARE="${FIRMWARE_DIR}/firmware.bin"
26+
27+
if [ ! -f "$BOOTLOADER" ]; then
28+
echo "Error: Bootloader not found: $BOOTLOADER"
29+
exit 1
30+
fi
31+
32+
if [ ! -f "$FIRMWARE" ]; then
33+
echo "Error: Firmware not found: $FIRMWARE"
34+
exit 1
35+
fi
36+
37+
echo "Starting QEMU ESP32 with WLED firmware"
38+
echo "Firmware directory: $FIRMWARE_DIR"
39+
echo "HTTP will be accessible at: http://localhost:${HTTP_PORT}"
40+
41+
# Create a merged flash image as QEMU expects
42+
FLASH_IMAGE="/tmp/wled_flash.bin"
43+
echo "Creating flash image at $FLASH_IMAGE"
44+
45+
# Create a 4MB flash image (0x400000 bytes)
46+
dd if=/dev/zero of="$FLASH_IMAGE" bs=1M count=4 2>/dev/null
47+
48+
# Write bootloader at 0x1000
49+
if [ -f "$BOOTLOADER" ]; then
50+
dd if="$BOOTLOADER" of="$FLASH_IMAGE" bs=1 seek=$((0x1000)) conv=notrunc 2>/dev/null
51+
fi
52+
53+
# Write partitions at 0x8000
54+
if [ -f "$PARTITIONS" ]; then
55+
dd if="$PARTITIONS" of="$FLASH_IMAGE" bs=1 seek=$((0x8000)) conv=notrunc 2>/dev/null
56+
fi
57+
58+
# Write firmware at 0x10000
59+
dd if="$FIRMWARE" of="$FLASH_IMAGE" bs=1 seek=$((0x10000)) conv=notrunc 2>/dev/null
60+
61+
echo "Flash image created successfully"
62+
63+
# Run QEMU ESP32
64+
# Note: ESP32 in QEMU has limited peripheral support
65+
# Network configuration uses user-mode networking with port forwarding
66+
echo "Starting QEMU..."
67+
${QEMU_DIR}/qemu-system-xtensa \
68+
-nographic \
69+
-machine esp32 \
70+
-drive file=${FLASH_IMAGE},if=mtd,format=raw \
71+
-nic user,model=open_eth,hostfwd=tcp::${HTTP_PORT}-:80 \
72+
-serial mon:stdio &
73+
74+
QEMU_PID=$!
75+
echo "QEMU started with PID: $QEMU_PID"
76+
echo $QEMU_PID > qemu.pid
77+
78+
# Wait for QEMU to initialize
79+
echo "Waiting for QEMU to initialize (30 seconds)..."
80+
sleep 30
81+
82+
# Check if QEMU is still running
83+
if ! kill -0 $QEMU_PID 2>/dev/null; then
84+
echo "Error: QEMU process died"
85+
exit 1
86+
fi
87+
88+
echo "QEMU is running"
89+
echo "To stop QEMU: kill $QEMU_PID"
90+
echo "Or use: kill \$(cat qemu.pid)"
91+
92+
# Wait for QEMU process
93+
wait $QEMU_PID

.github/scripts/setup-qemu.sh

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/bin/bash
2+
# Setup QEMU ESP32 emulation environment
3+
# This script downloads and sets up QEMU for ESP32
4+
5+
set -e
6+
7+
QEMU_VERSION="esp-develop-20220919"
8+
QEMU_URL="https://github.com/espressif/qemu/releases/download/${QEMU_VERSION}/qemu-${QEMU_VERSION}-x86_64-linux-gnu.tar.xz"
9+
QEMU_DIR="qemu-esp32"
10+
11+
echo "Setting up QEMU ESP32..."
12+
13+
# Create directory for QEMU
14+
mkdir -p ${QEMU_DIR}
15+
16+
# Download QEMU ESP32 if not already present
17+
if [ ! -f "${QEMU_DIR}/qemu-system-xtensa" ]; then
18+
echo "Downloading QEMU ESP32 from ${QEMU_URL}..."
19+
wget -q ${QEMU_URL} -O qemu.tar.xz
20+
21+
echo "Extracting QEMU..."
22+
tar -xf qemu.tar.xz -C ${QEMU_DIR} --strip-components=1
23+
24+
# Cleanup
25+
rm qemu.tar.xz
26+
27+
echo "QEMU ESP32 installed successfully"
28+
else
29+
echo "QEMU ESP32 already installed"
30+
fi
31+
32+
# Make QEMU executable
33+
chmod +x ${QEMU_DIR}/qemu-system-xtensa
34+
35+
echo "QEMU ESP32 setup complete"
36+
echo "QEMU binary: ${QEMU_DIR}/qemu-system-xtensa"
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
name: QEMU E2E Testing
2+
3+
on:
4+
pull_request:
5+
branches: [ mdev, main ]
6+
push:
7+
branches: [ mdev, main ]
8+
workflow_dispatch:
9+
10+
jobs:
11+
# Job 1: Build firmware for QEMU testing
12+
build-firmware:
13+
name: Build ESP32 Firmware for QEMU
14+
runs-on: ubuntu-22.04
15+
steps:
16+
- uses: actions/checkout@v4
17+
18+
- name: Cache pip
19+
uses: actions/cache@v4
20+
with:
21+
path: ~/.cache/pip
22+
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
23+
restore-keys: |
24+
${{ runner.os }}-pip-
25+
26+
- name: Cache PlatformIO
27+
uses: actions/cache@v4
28+
with:
29+
path: ~/.platformio
30+
key: ${{ runner.os }}-pio-esp32dev-${{ hashFiles('**/platformio.ini') }}
31+
restore-keys: |
32+
${{ runner.os }}-pio-esp32dev-
33+
34+
- name: Set up Python
35+
uses: actions/setup-python@v5
36+
with:
37+
python-version: '3.9'
38+
39+
- name: Set up Node.js
40+
uses: actions/setup-node@v4
41+
with:
42+
node-version: '20'
43+
cache: 'npm'
44+
45+
- name: Install PlatformIO
46+
run: pip install -r requirements.txt
47+
48+
- name: Install Node.js dependencies
49+
run: npm ci
50+
51+
- name: Build Web UI
52+
run: npm run build
53+
54+
- name: Build ESP32 firmware
55+
run: pio run -e esp32dev
56+
57+
- name: Upload firmware artifacts
58+
uses: actions/upload-artifact@v4
59+
with:
60+
name: esp32-firmware
61+
path: .pio/build/esp32dev/
62+
retention-days: 1
63+
64+
# Job 2: Test with QEMU
65+
test-qemu:
66+
name: QEMU E2E Tests
67+
runs-on: ubuntu-22.04
68+
needs: build-firmware
69+
timeout-minutes: 45
70+
steps:
71+
- uses: actions/checkout@v4
72+
73+
- name: Set up Node.js
74+
uses: actions/setup-node@v4
75+
with:
76+
node-version: '20'
77+
cache: 'npm'
78+
79+
- name: Download firmware artifacts
80+
uses: actions/download-artifact@v4
81+
with:
82+
name: esp32-firmware
83+
path: .pio/build/esp32dev/
84+
85+
- name: Install Node.js dependencies
86+
run: npm ci
87+
88+
- name: Install Playwright Browsers
89+
run: npx playwright install --with-deps chromium
90+
91+
- name: Setup QEMU ESP32
92+
run: |
93+
bash .github/scripts/setup-qemu.sh
94+
95+
- name: Start QEMU with WLED firmware in background
96+
run: |
97+
chmod +x .github/scripts/run-qemu.sh
98+
bash .github/scripts/run-qemu.sh .pio/build/esp32dev qemu-esp32 80 > qemu-output.log 2>&1 &
99+
echo "Waiting for QEMU to start and WLED to boot..."
100+
sleep 45
101+
102+
- name: Check QEMU status
103+
run: |
104+
if [ -f qemu.pid ]; then
105+
QEMU_PID=$(cat qemu.pid)
106+
if kill -0 $QEMU_PID 2>/dev/null; then
107+
echo "QEMU is running (PID: $QEMU_PID)"
108+
else
109+
echo "QEMU process not running"
110+
cat qemu-output.log || true
111+
exit 1
112+
fi
113+
else
114+
echo "qemu.pid not found"
115+
cat qemu-output.log || true
116+
exit 1
117+
fi
118+
119+
- name: Test HTTP endpoint
120+
run: |
121+
echo "Testing if HTTP server is responding..."
122+
for i in {1..30}; do
123+
if curl -f -m 5 http://localhost/ > /dev/null 2>&1; then
124+
echo "HTTP server is responding!"
125+
exit 0
126+
fi
127+
echo "Attempt $i failed, waiting..."
128+
sleep 2
129+
done
130+
echo "HTTP server not responding after 60 seconds"
131+
cat qemu-output.log || true
132+
exit 1
133+
134+
- name: Run Playwright tests against QEMU
135+
env:
136+
WLED_BASE_URL: http://localhost
137+
run: npm run test:e2e
138+
continue-on-error: true
139+
140+
- name: Upload QEMU logs
141+
uses: actions/upload-artifact@v4
142+
if: always()
143+
with:
144+
name: qemu-logs
145+
path: qemu-output.log
146+
retention-days: 7
147+
148+
- name: Upload Playwright report
149+
uses: actions/upload-artifact@v4
150+
if: always()
151+
with:
152+
name: playwright-report-qemu
153+
path: playwright-report/
154+
retention-days: 7
155+
156+
- name: Stop QEMU
157+
if: always()
158+
run: |
159+
if [ -f qemu.pid ]; then
160+
QEMU_PID=$(cat qemu.pid)
161+
echo "Stopping QEMU (PID: $QEMU_PID)"
162+
kill $QEMU_PID || true
163+
sleep 2
164+
kill -9 $QEMU_PID 2>/dev/null || true
165+
fi

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,10 @@ compile_commands.json
2828
/wled00/wled00.ino.cpp
2929
/wled00/html_*.h
3030
_codeql_detected_source_root
31+
32+
# E2E Testing
33+
/playwright-report/
34+
/test-results/
35+
/playwright/.cache/
36+
qemu-esp32/
37+
qemu.pid

0 commit comments

Comments
 (0)