aboutsummaryrefslogtreecommitdiff
path: root/modules/test/test-predictor-store-auth.js
blob: 6c37812b6119672cc91ac5579dc2b1673cc2361f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
// node modules/test/test-predictor-store-auth.js
// F6 (2026-11-09): the predictor store is an auth-gated /spaces/<user>/_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); });