// Real-DOM (jsdom) test of the two new Tools sections. The HTML is the actual // server-rendered /partials/tools, and the payloads are the real API's, so a // renamed field or a changed shape fails this rather than passing quietly. const http = require('http'); const { JSDOM, VirtualConsole } = require('jsdom'); const BASE = process.env.BASE || 'http://localhost:5000'; const get = p => new Promise((res, rej) => http.get(BASE + p, r => { let d = ''; r.on('data', c => d += c); r.on('end', () => res(d)); }).on('error', rej)); (async () => { const partial = await get('/partials/tools'); const bridge = JSON.parse(await get('/api/v3/integrations/mqtt-bridge')); const apps = JSON.parse(await get('/api/v3/starlark/editor/apps')); const errs = []; const vc = new VirtualConsole(); vc.on('jsdomError', e => errs.push(String(e.message || e).split('\n')[0])); // Controllable fetch: serve the real payloads, and let tests swap in others. let editorStatus = { status: 'success', data: { running: false } }; let bridgePayload = bridge; let onPut = null; const stubFetch = (url, opts) => { const u = String(url); if (onPut && opts && opts.method === 'PUT') onPut(JSON.parse(opts.body)); let body = { status: 'success', data: {} }; if (u.includes('/integrations/mqtt-bridge')) body = bridgePayload; else if (u.includes('/starlark/editor/status')) body = editorStatus; else if (u.includes('/starlark/editor/apps')) body = apps; return Promise.resolve({ ok: true, status: 200, json: () => Promise.resolve(body) }); }; // runScripts:'dangerously' so the partial's own