// The /fingerprint wizard's scanner-availability logic. app.js is a browser // IIFE, so it is loaded in a vm sandbox with stubbed browser globals and its // Vue options are exercised directly (no Vue runtime needed). import test from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs'; import vm from 'node:vm'; const SRC = fs.readFileSync(new URL('../public/assets/fp/app.js', import.meta.url), 'utf8'); function loadApp() { let options = null; let socket = null; const els = {}; const document = { getElementById(id) { return (els[id] ||= { textContent: '', attrs: {}, setAttribute(k, v) { this.attrs[k] = v; }, getAttribute(k) { return this.attrs[k]; }, }); }, }; const sandbox = { window: { __SESSION__: { agentUrl: 'http://127.0.0.1:9000', domains: [] }, location: { href: '' }, }, document, Vue: class Vue { static config = {}; constructor(o) { options = o; } }, io() { socket = { handlers: {}, on(e, cb) { this.handlers[e] = cb; return this; } }; return socket; }, setInterval: () => 0, setTimeout: () => 0, clearTimeout: () => {}, console, }; vm.runInNewContext(SRC, sandbox); return { get options() { return options; }, get socket() { return socket; }, getElement: (id) => document.getElementById(id), }; } function makeVm(app) { const o = app.options; const inst = Object.assign({}, o.data); for (const [k, fn] of Object.entries(o.methods)) inst[k] = fn.bind(inst); for (const [k, fn] of Object.entries(o.computed)) { Object.defineProperty(inst, k, { get: fn.bind(inst), configurable: true }); } inst.$forceUpdate = () => {}; inst.loadSession(); inst.connectAgent(); return inst; } test('disconnected agent blocks capture and warns', () => { const vmInst = makeVm(loadApp()); assert.equal(vmInst.captureReady, false); assert.equal(vmInst.scannerNotice.title, 'Capture agent offline'); }); test('available:false blocks capture and warns; true re-enables', () => { const app = loadApp(); const vmInst = makeVm(app); const h = app.socket.handlers; h.connect(); h['fprint-device-status']({ available: false, device: '' }); assert.equal(vmInst.captureReady, false); assert.equal(vmInst.scannerNotice.title, 'Scanner not connected'); h['fprint-device-status']({ available: true, device: 'Digital Persona U.are.U' }); assert.equal(vmInst.captureReady, true); assert.equal(vmInst.scannerNotice, null); assert.equal(vmInst.agent.device, 'Digital Persona U.are.U'); }); test('unknown availability (old agent) does not block capture', () => { const app = loadApp(); const vmInst = makeVm(app); app.socket.handlers.connect(); assert.equal(vmInst.agent.available, null); assert.equal(vmInst.captureReady, true); assert.equal(vmInst.scannerNotice, null); }); test('status tag reflects offline, connected, no-scanner and ready', () => { const app = loadApp(); const vmInst = makeVm(app); const h = app.socket.handlers; const el = app.getElement('agent-status'); vmInst.renderAgentTag(); assert.equal(el.textContent, 'Agent offline'); assert.equal(el.getAttribute('type'), 'red'); h.connect(); assert.equal(el.textContent, 'Agent connected'); h['agent-hello']({ version: 'abc123', captureAgentId: 'aid' }); assert.equal(el.getAttribute('title'), 'fpagent abc123'); h['fprint-device-status']({ available: false }); assert.equal(el.textContent, 'Scanner not connected'); assert.equal(el.getAttribute('type'), 'red'); h['fprint-device-status']({ available: true, device: 'U.are.U 4500' }); assert.equal(el.textContent, 'Agent ready'); assert.equal(el.getAttribute('type'), 'green'); assert.match(el.getAttribute('title'), /abc123/); assert.match(el.getAttribute('title'), /U\.are\.U 4500/); }); test('capture is refused when no reader is attached', () => { const app = loadApp(); const vmInst = makeVm(app); const h = app.socket.handlers; h.connect(); h['fprint-device-status']({ available: false }); vmInst.domain = 'uc'; vmInst.reference = 'UC/1'; vmInst.capture('right-thumb'); assert.equal(vmInst.capturing, null); assert.equal(vmInst.notif.show, true); }); test('disconnect clears availability', () => { const app = loadApp(); const vmInst = makeVm(app); const h = app.socket.handlers; h.connect(); h['fprint-device-status']({ available: true, device: 'U.are.U' }); h.disconnect(); assert.equal(vmInst.agent.connected, false); assert.equal(vmInst.agent.available, null); assert.equal(vmInst.agent.device, ''); assert.equal(vmInst.captureReady, false); });