diff options
| author | Your Name <you@example.com> | 2026-05-19 04:21:14 +0530 |
|---|---|---|
| committer | Your Name <you@example.com> | 2026-05-19 04:21:14 +0530 |
| commit | aa58b47996083f36e3587b8e10f9bbb681610491 (patch) | |
| tree | 4c845da2ee4b217a2c77deea3b10dd8d288d1b09 /tests/integration | |
| parent | 9f7dd94029c8dc12117494548f5f32221a729307 (diff) | |
feat: web-based WiFi setup via captive portal, portrait-only display
- Remove touchscreen WiFi setup (touch.c, keyboard.c, wifi_setup.c from build)
- Remove offscreen buffer and landscape rotation from axs15231b driver
- Add /setup HTML page with WiFi scan/connect via captive portal
- Add /wifi/scan, /wifi/connect, /wifi/status HTTP endpoints
- Display shows SETUP_PENDING (QR + SSID + setup URL) when unconfigured
- Display shows ERROR with setup URL when upstream is down
- All 101 unit tests pass, builds and flashes to Board C
Diffstat (limited to 'tests/integration')
| -rw-r--r-- | tests/integration/wifi_setup.mjs | 74 |
1 files changed, 74 insertions, 0 deletions
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 @@ | |||
| 1 | import { execSync } from 'child_process'; | ||
| 2 | |||
| 3 | const IP = process.env.TOLLGATE_IP || '10.192.45.1'; | ||
| 4 | |||
| 5 | console.log(`\n=== WiFi Setup Integration Test ===`); | ||
| 6 | console.log(`Portal IP: ${IP}\n`); | ||
| 7 | |||
| 8 | let passed = 0, failed = 0; | ||
| 9 | function assert(cond, msg) { | ||
| 10 | if (cond) { console.log(` PASS: ${msg}`); passed++; } | ||
| 11 | else { console.log(` FAIL: ${msg}`); failed++; } | ||
| 12 | } | ||
| 13 | |||
| 14 | function run(cmd) { | ||
| 15 | try { return execSync(cmd, { encoding: 'utf8', timeout: 15000 }); } | ||
| 16 | catch { return null; } | ||
| 17 | } | ||
| 18 | |||
| 19 | function fetchJSON(path) { | ||
| 20 | const result = run(`curl -s --connect-timeout 5 http://${IP}${path}`); | ||
| 21 | if (!result) return null; | ||
| 22 | try { return JSON.parse(result); } | ||
| 23 | catch { return null; } | ||
| 24 | } | ||
| 25 | |||
| 26 | // 1. /setup page returns HTML (or redirects if already configured) | ||
| 27 | const setupPage = run(`curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 http://${IP}/setup`); | ||
| 28 | assert(setupPage === '200' || setupPage === '302', `/setup returns 200 or 302 (got ${setupPage})`); | ||
| 29 | |||
| 30 | // 2. /wifi/status endpoint works | ||
| 31 | const status = fetchJSON('/wifi/status'); | ||
| 32 | assert(status !== null, '/wifi/status returns JSON'); | ||
| 33 | assert(typeof status.connected === 'boolean', '/wifi/status has connected field'); | ||
| 34 | |||
| 35 | // 3. /wifi/scan endpoint returns array | ||
| 36 | console.log('\n (wifi/scan may take a few seconds...)'); | ||
| 37 | const scanResult = run(`curl -s --connect-timeout 15 --max-time 15 http://${IP}/wifi/scan`); | ||
| 38 | let scanData = null; | ||
| 39 | if (scanResult) { | ||
| 40 | try { scanData = JSON.parse(scanResult); } catch {} | ||
| 41 | } | ||
| 42 | assert(scanData !== null, '/wifi/scan returns JSON'); | ||
| 43 | if (scanData && Array.isArray(scanData)) { | ||
| 44 | assert(scanData.length >= 0, `/wifi/scan returns array (${scanData.length} APs)`); | ||
| 45 | if (scanData.length > 0) { | ||
| 46 | const ap = scanData[0]; | ||
| 47 | assert(ap.ssid !== undefined, 'AP has ssid field'); | ||
| 48 | assert(ap.rssi !== undefined, 'AP has rssi field'); | ||
| 49 | assert(ap.secured !== undefined, 'AP has secured field'); | ||
| 50 | console.log(` First AP: "${ap.ssid}" (${ap.rssi} dBm, ${ap.secured ? 'secured' : 'open'})`); | ||
| 51 | } | ||
| 52 | } | ||
| 53 | |||
| 54 | // 4. /wifi/connect rejects invalid JSON | ||
| 55 | const badConnect = run(`curl -s -X POST -d 'not json' --connect-timeout 5 http://${IP}/wifi/connect`); | ||
| 56 | assert(badConnect !== null, '/wifi/connect responds to bad request'); | ||
| 57 | if (badConnect) { | ||
| 58 | try { | ||
| 59 | const err = JSON.parse(badConnect); | ||
| 60 | assert(err.ok === false, '/wifi/connect returns ok:false for bad request'); | ||
| 61 | } catch {} | ||
| 62 | } | ||
| 63 | |||
| 64 | // 5. /wifi/connect rejects missing ssid | ||
| 65 | const noSsid = run(`curl -s -X POST -H 'Content-Type: application/json' -d '{}' --connect-timeout 5 http://${IP}/wifi/connect`); | ||
| 66 | if (noSsid) { | ||
| 67 | try { | ||
| 68 | const err = JSON.parse(noSsid); | ||
| 69 | assert(err.ok === false && err.error, '/wifi/connect returns error for missing ssid'); | ||
| 70 | } catch {} | ||
| 71 | } | ||
| 72 | |||
| 73 | console.log(`\n=== Results: ${passed} passed, ${failed} failed ===`); | ||
| 74 | process.exit(failed > 0 ? 1 : 0); | ||