Security assistant chat as the front page (Nox-style, WebLLM on device, grounded in the Devseis knowledge base, Run audit from chat); phone check moved to phone.html
f1bdfc3 verified Download mobile/test/e2e.cjs from Devseis/Arx: direct link, hf CLI and curl.
- Browser
- Download file 4.02 kB
-
https://huggingface.co/spaces/Devseis/Arx/resolve/main/mobile/test/e2e.cjs
- Command line
-
hf download hf://spaces/Devseis/Arx/mobile/test/e2e.cjs
-
curl -L -o e2e.cjs https://huggingface.co/spaces/Devseis/Arx/resolve/main/mobile/test/e2e.cjs
4.02 kB
| // End-to-end test of the phone check in a phone-sized Electron window with a phone user agent. | |
| // Usage: (serve the repo root on :8765) npx electron mobile/test/e2e.cjs <ios|android> <out.json> | |
| const { app, BrowserWindow } = require('electron'); | |
| const fs = require('node:fs'); | |
| const UA = { | |
| ios: 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1', | |
| android: 'Mozilla/5.0 (Linux; Android 15; Pixel 8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Mobile Safari/537.36', | |
| }; | |
| const [os, out] = process.argv.slice(-2); | |
| const PICK = `(() => { | |
| const box = document.getElementById('q-answers'); | |
| const buttons = [...box.querySelectorAll('button')]; | |
| const cont = buttons.find(b => b.textContent === 'Continue'); | |
| const text = box.querySelector('input[type=text]'), month = box.querySelector('input[type=month]'); | |
| const multi = box.querySelectorAll('input[type=checkbox]'); | |
| if (text) { if (!text.value) text.value = '${os === 'ios' ? '26.0.1' : '15'}'; cont.click(); return 'version'; } | |
| if (month) { month.value = '2026-06'; cont.click(); return 'month'; } | |
| if (multi.length) { multi[0].checked = true; multi[7].checked = true; cont.click(); return 'ai'; } | |
| (buttons.length > 2 ? buttons[1] : buttons[0]).click(); return 'choice'; | |
| })()`; | |
| if (!process.env.AI) app.disableHardwareAcceleration(); // AI=1: keep the GPU for WebLLM | |
| if (process.env.AI) app.commandLine.appendSwitch('enable-unsafe-webgpu'); | |
| app.whenReady().then(async () => { | |
| const win = new BrowserWindow({ show: false, width: 390, height: 844 }); | |
| win.webContents.setUserAgent(UA[os]); | |
| win.webContents.on('console-message', (e, level, message) => { if (level >= 2) console.log('[page]', message); }); | |
| const js = code => win.webContents.executeJavaScript(code); | |
| const until = async (code, ms = 60000) => { const t = Date.now(); while (!(await js(code))) { if (Date.now() - t > ms) throw new Error(`timeout: ${code}`); await new Promise(r => setTimeout(r, 200)); } }; | |
| try { | |
| await win.webContents.session.clearCache(); | |
| await win.loadURL(`${process.env.BASE_URL || 'http://127.0.0.1:8765/'}phone.html?test`); | |
| await until(`!document.getElementById('start').disabled`); | |
| const device = await js(`document.getElementById('device-card').innerText`); | |
| await js(`document.getElementById('start').click()`); | |
| await js(`document.getElementById('use-ai').checked = ${Boolean(process.env.AI)}; document.getElementById('consent-ok').click()`); | |
| let asked = []; | |
| for (let i = 0; i < 60; i++) { | |
| const inQuestions = await js(`!document.getElementById('s-question').classList.contains('hidden')`); | |
| if (!inQuestions) break; | |
| const q = await js(`document.getElementById('q-text').textContent`); | |
| asked.push(q); | |
| // Pick a mix of answers: the version as detected (or typed), a month, two AI apps, otherwise the 2nd option. | |
| await js(PICK); | |
| await new Promise(r => setTimeout(r, 50)); | |
| } | |
| await until(`!document.getElementById('s-done').classList.contains('hidden')`, process.env.AI ? 3600000 : 120000); | |
| const chip = await js(`document.getElementById('model-chip').textContent`); | |
| const evidence = await js(`window.__devseisState.report.evidenceText`); | |
| const result = await js(`document.getElementById('result').innerText`); | |
| const pdfSize = await js(`window.__devseisMakePdf().then(b => b.size)`); | |
| console.log('handoff:', await js(`(document.getElementById('ask-assistant')||{}).href + ' stored=' + !!localStorage.getItem('devseis.lastAudit')`)); | |
| const html = await js(`window.__devseisState.report.html`); | |
| fs.writeFileSync(out, evidence); | |
| fs.writeFileSync(out.replace(/\.json$/, '.html'), html); | |
| console.log(JSON.stringify({ os, device, model: chip, questions: asked.length, pdfBytes: pdfSize, result: result.slice(0, 900) }, null, 1)); | |
| } catch (error) { | |
| console.error('E2E FAILED:', error.message); | |
| process.exitCode = 1; | |
| } | |
| app.quit(); | |
| }); | |