bursa / client / test / banks.test.mjs
 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
// The remembered-banks list behind the boot reopen: a successful open records
// its token, a reload redials every recorded token, and nothing else touches
// the list. The bug this pins: store/remember-bank! existed — docstring,
// dedup, the works — with ZERO call sites, so no connection was ever recorded
// and every reload showed every bank as never-connected. Verified live, in a
// v8 browser, by the key simply not being there. Recording is now tied to the
// open's own settled value (lib/banks), where this suite can hold it.

import test from "node:test";
import assert from "node:assert/strict";
import * as L from "../test-dist/testlib.js";

const KEY = "bursa-test:banks";

/** The storage seam lib/banks takes — what js/localStorage is to the store. */
function fakeStorage() {
  const m = new Map();
  return {
    getItem: (k) => (m.has(k) ? m.get(k) : null),
    setItem: (k, v) => { m.set(k, String(v)); },
  };
}

test("a successful open records the token — exactly once", async () => {
  const s = fakeStorage();
  const out = await L.recordBankOnOpen(s, KEY, "tok", Promise.resolve(null));
  assert.equal(out, null, "the settled value passes through");
  assert.deepEqual([...L.recordedBanks(s, KEY)], ["tok"]);
  // the boot reopen redials through the same recording path — by design
  await L.recordBankOnOpen(s, KEY, "tok", Promise.resolve(null));
  assert.deepEqual([...L.recordedBanks(s, KEY)], ["tok"], "double-open stays deduped");
});

test("a refused open records nothing — the catalog key stays the caller's", async () => {
  const s = fakeStorage();
  const out = await L.recordBankOnOpen(s, KEY, "tok", Promise.resolve("err.bank.open"));
  assert.equal(out, "err.bank.open");
  assert.deepEqual([...L.recordedBanks(s, KEY)], []);
});

test("a rejecting open records nothing and the rejection passes through", async () => {
  const s = fakeStorage();
  await assert.rejects(
    L.recordBankOnOpen(s, KEY, "tok", Promise.reject(new Error("boom"))),
  );
  assert.deepEqual([...L.recordedBanks(s, KEY)], []);
});

test("reopen dials exactly what was recorded, and one dead bank stops nothing", async () => {
  const s = fakeStorage();
  await L.recordBankOnOpen(s, KEY, "b1", Promise.resolve(null));
  await L.recordBankOnOpen(s, KEY, "b2", Promise.resolve(null));
  const dialed = [];
  L.reopenBanks(s, KEY, (token) => {
    dialed.push(token);
    // the first remembered bank will not open today — the second still must
    return token === "b1" ? Promise.reject(new Error("down")) : Promise.resolve(null);
  });
  assert.deepEqual(dialed, ["b1", "b2"]);
});

test("a device that cannot read its history boots as a fresh one", async () => {
  const s = fakeStorage();
  s.setItem(KEY, "not json");
  assert.deepEqual([...L.recordedBanks(s, KEY)], []);
  const throwing = {
    getItem: () => { throw new Error("denied"); },
    setItem: () => { throw new Error("denied"); },
  };
  assert.deepEqual([...L.recordedBanks(throwing, KEY)], []);
  // storage refusing to WRITE is non-fatal too: the open's verdict still lands
  const out = await L.recordBankOnOpen(throwing, KEY, "tok", Promise.resolve(null));
  assert.equal(out, null);
});

static mirror of HEAD · about · clone: git clone https://git.ardegazu.ro/bursa.git