/**
 * The native update check must be hard-capped.
 *
 * The bug it prevents: electron-updater's checkForUpdates has no timeout of its
 * own, and it caches its in-flight check promise. If one check's feed request
 * stalls (opens but never responds), the promise never settles, runCheck never
 * leaves 'checking', and every LATER check returns the same hung promise. The
 * badge then spins on 'checking' forever with nothing logged, which is worse
 * than an error: it looks like the app is working when it is not. A hard cap in
 * runCheck is the only thing that forces a terminal state.
 *
 * Source-string checks, because updater.ts imports electron and cannot be loaded
 * in a plain test; deleting the cap must not pass silently.
 */
const test = require('node:test');
const assert = require('node:assert/strict');
const { readFileSync } = require('node:fs');
const { join } = require('node:path');
const read = (rel) => readFileSync(join(__dirname, '..', rel), 'utf8');

test('runCheck wraps the native check in a timeout, not a bare await', () => {
  const src = read('src/main/updater.ts');
  const runCheck = src.slice(src.indexOf('async function runCheck'), src.indexOf('async function runCheck') + 900);
  assert.ok(/withTimeout\(/.test(runCheck),
    'runCheck must wrap the native check in withTimeout; a bare '
    + 'await autoUpdater.checkForUpdates() can hang forever and freeze the badge');
  assert.ok(/CHECK_TIMEOUT_MS/.test(runCheck),
    'the wrap must use the timeout constant, not an unbounded await');
  assert.ok(!/const result = await autoUpdater\.checkForUpdates\(\);/.test(runCheck),
    'the un-capped await must be gone, or the timeout is dead code beside it');
});

test('the timeout constant is finite, positive, and sane', () => {
  const src = read('src/main/updater.ts');
  const m = src.match(/const CHECK_TIMEOUT_MS = ([0-9_]+);/);
  assert.ok(m, 'CHECK_TIMEOUT_MS must be defined');
  const ms = Number(m[1].replace(/_/g, ''));
  assert.ok(Number.isFinite(ms) && ms > 0 && ms <= 120000,
    'the cap must be finite and sane (0 < ms <= 120s), or it is not really a cap');
});

test('withTimeout arms a rejecting timer and clears it on settle', () => {
  const src = read('src/main/updater.ts');
  const wt = src.slice(src.indexOf('function withTimeout'), src.indexOf('function withTimeout') + 500);
  assert.ok(/setTimeout\(/.test(wt) && /reject\(/.test(wt),
    'withTimeout must arm a timer that rejects, or a hung check is never cut off');
  assert.ok(/clearTimeout\(/.test(wt),
    'it must clear the timer on settle, or a slow-but-successful check leaks a handle');
});