From 899016795c389151e6b486ec470653f5688e5c5f Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 20 May 2026 02:14:45 +0530 Subject: feat: merge display-fix — touch driver, keyboard, WiFi setup UI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Squash-merge of feature/display-fix (27 commits): - AXS15231B touch driver with coordinate parsing (touch.c/h) - On-screen keyboard with layout/hit detection (keyboard.c/h) - WiFi setup state machine + config_add_wifi (wifi_setup.c/h) - Web-based WiFi setup via captive portal - Display rotation fix (stride=480), color fixes, DMA byte-swap - WiFi QR code on BOOT and ERROR screens - ERROR state transition after WiFi retries exhausted - Unit tests: test_touch, test_keyboard, test_wifi_setup - Integration test: wifi_setup.mjs - E2E test: wifi-setup.spec.mjs - Per-board hardware locks for flash targets Conflicts resolved: took master for config/cvm/api/main (more current), took display-fix for display/axs15231b (newer fixes). --- tests/integration/wifi_setup.mjs | 74 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 tests/integration/wifi_setup.mjs (limited to 'tests/integration') diff --git a/tests/integration/wifi_setup.mjs b/tests/integration/wifi_setup.mjs new file mode 100644 index 0000000..a991ba5 --- /dev/null +++ b/tests/integration/wifi_setup.mjs @@ -0,0 +1,74 @@ +import { execSync } from 'child_process'; + +const IP = process.env.TOLLGATE_IP || '10.192.45.1'; + +console.log(`\n=== WiFi Setup Integration Test ===`); +console.log(`Portal IP: ${IP}\n`); + +let passed = 0, failed = 0; +function assert(cond, msg) { + if (cond) { console.log(` PASS: ${msg}`); passed++; } + else { console.log(` FAIL: ${msg}`); failed++; } +} + +function run(cmd) { + try { return execSync(cmd, { encoding: 'utf8', timeout: 15000 }); } + catch { return null; } +} + +function fetchJSON(path) { + const result = run(`curl -s --connect-timeout 5 http://${IP}${path}`); + if (!result) return null; + try { return JSON.parse(result); } + catch { return null; } +} + +// 1. /setup page returns HTML (or redirects if already configured) +const setupPage = run(`curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 http://${IP}/setup`); +assert(setupPage === '200' || setupPage === '302', `/setup returns 200 or 302 (got ${setupPage})`); + +// 2. /wifi/status endpoint works +const status = fetchJSON('/wifi/status'); +assert(status !== null, '/wifi/status returns JSON'); +assert(typeof status.connected === 'boolean', '/wifi/status has connected field'); + +// 3. /wifi/scan endpoint returns array +console.log('\n (wifi/scan may take a few seconds...)'); +const scanResult = run(`curl -s --connect-timeout 15 --max-time 15 http://${IP}/wifi/scan`); +let scanData = null; +if (scanResult) { + try { scanData = JSON.parse(scanResult); } catch {} +} +assert(scanData !== null, '/wifi/scan returns JSON'); +if (scanData && Array.isArray(scanData)) { + assert(scanData.length >= 0, `/wifi/scan returns array (${scanData.length} APs)`); + if (scanData.length > 0) { + const ap = scanData[0]; + assert(ap.ssid !== undefined, 'AP has ssid field'); + assert(ap.rssi !== undefined, 'AP has rssi field'); + assert(ap.secured !== undefined, 'AP has secured field'); + console.log(` First AP: "${ap.ssid}" (${ap.rssi} dBm, ${ap.secured ? 'secured' : 'open'})`); + } +} + +// 4. /wifi/connect rejects invalid JSON +const badConnect = run(`curl -s -X POST -d 'not json' --connect-timeout 5 http://${IP}/wifi/connect`); +assert(badConnect !== null, '/wifi/connect responds to bad request'); +if (badConnect) { + try { + const err = JSON.parse(badConnect); + assert(err.ok === false, '/wifi/connect returns ok:false for bad request'); + } catch {} +} + +// 5. /wifi/connect rejects missing ssid +const noSsid = run(`curl -s -X POST -H 'Content-Type: application/json' -d '{}' --connect-timeout 5 http://${IP}/wifi/connect`); +if (noSsid) { + try { + const err = JSON.parse(noSsid); + assert(err.ok === false && err.error, '/wifi/connect returns error for missing ssid'); + } catch {} +} + +console.log(`\n=== Results: ${passed} passed, ${failed} failed ===`); +process.exit(failed > 0 ? 1 : 0); -- cgit v1.2.3