// node modules/test/test-predictor-store-auth.js // F6 (2026-11-09): the predictor store is an auth-gated /spaces//_data path, but _wdConfig() // returns user:''/pass:'' whenever the saved WebDAV config has no credentials — so every page load // made a guaranteed-401 request (measured 107 in one day) and the console reported it as an error. // No credentials must mean no request. const fs = require('fs'); const path = require('path'); const SRC = process.env.PRED_SRC || path.join(__dirname, '..', 'core', 'module-predictor.js'); const src = fs.readFileSync(SRC, 'utf8'); let pass = 0, fail = 0; const ok = (name, cond, detail) => { if (cond) { pass++; console.log('ok ' + name); } else { fail++; console.log('FAIL ' + name + (detail !== undefined ? ' — ' + detail : '')); } }; function load(localStore) { const store = Object.assign({}, localStore); global.localStorage = { getItem: (k) => (k in store ? store[k] : null), setItem: (k, v) => { store[k] = String(v); }, removeItem: (k) => { delete store[k]; }, }; global.window = global; global.setTimeout = global.setTimeout; const Mod = new Function(src + '\nreturn PredictorModule;')(); const m = new Mod(); m.terminal = { print: () => {}, fs: { readFile: () => '{}', fsReadJSON: () => null, fsWriteJSON: () => true, readDir: () => [], mkdirRecursive: () => true, }, }; return m; } (async () => { const cfgNoCreds = JSON.stringify({ url: 'https://webx11.duckdns.org/spaces/agando', user: '', password: '' }); const cfgWithCreds = JSON.stringify({ url: 'https://webx11.duckdns.org/spaces/agando', user: 'agando', password: 'pw' }); // ---- 1. no credentials → zero requests, both directions ---- let calls = 0; global.fetch = () => { calls++; return Promise.resolve({ ok: true, status: 200, json: async () => ({}) }); }; let m = load({ webx11_webdav_config: cfgNoCreds }); const pulled = await m._pullFromServer(true); const pushed = await m._pushToServer(); ok('pull without credentials returns false', pulled === false); ok('push without credentials returns false', pushed === false); ok('no fetch was made without credentials', calls === 0, 'calls=' + calls); ok('store mode names the reason', /no credentials/.test(m._storeMode), m._storeMode); // ---- 2. credentials present → still talks to the server ---- calls = 0; let sawAuth = null; global.fetch = (url, opts) => { calls++; sawAuth = opts && opts.headers && opts.headers.Authorization; return Promise.resolve({ ok: true, status: 200, json: async () => ({ dataPoints: [], accuracy: { total: 0 } }) }); }; m = load({ webx11_webdav_config: cfgWithCreds }); await m._pullFromServer(true); ok('pull with credentials reaches the server', calls === 1, 'calls=' + calls); ok('pull sends an Authorization header', /^Basic /.test(String(sawAuth)), String(sawAuth)); ok('store mode becomes server', m._storeMode === 'server', m._storeMode); // ---- 3. no config at all → no request (unchanged behaviour) ---- calls = 0; global.fetch = () => { calls++; return Promise.resolve({ ok: true, status: 200 }); }; m = load({}); await m._pullFromServer(true); await m._pushToServer(); ok('no config still makes no request', calls === 0, 'calls=' + calls); console.log('\ntest-predictor-store-auth: ' + pass + ' passed, ' + fail + ' failed'); process.exit(fail ? 1 : 0); })().catch((e) => { console.error('HARNESS ERROR', e); process.exit(2); });