test(folio): pin that a commit stays in the window until Home reads it

The interaction that keeps a stale Home card list from ever banking counts
the budget has already forgotten: a submit lands on the ledger, so the
reading that resets the window is a whole action later and the submit is
still in it. Characterization, not a regression: no code changed and it
cannot go red first.
This commit is contained in:
pj committed 2026-08-15 23:02:37 +05:30
1 parent 21a020de74
commit 4027aa1e44
1 file changed
+43
@@ -107,6 +107,7 @@ function run(steps: { route: string | null; cards: CardReading[]; lastAction: un
const idle = { kind: "Tap", on: "testTag:AccountCard" }; const idle = { kind: "Tap", on: "testTag:AccountCard" };
const doubleSubmit = { kind: "DoubleTap", on: "testTag:AddTransactionScreen > testTag:TxnSubmit" }; const doubleSubmit = { kind: "DoubleTap", on: "testTag:AddTransactionScreen > testTag:TxnSubmit" };
const submit = { kind: "Tap", on: "testTag:AddTransactionScreen > testTag:TxnSubmit" };
test("an un-laid-out Home no longer kills the counting invariant", () => { test("an un-laid-out Home no longer kills the counting invariant", () => {
const trace = run([ const trace = run([
@@ -157,3 +158,45 @@ test("an un-laid-out Home does not close the counting window", () => {
true, true,
); );
}); });
// What keeps a healthy submit from ever arriving as a rise nobody paid for. The
// reading banked here also resets the submit window, so a Home card list drawn
// before the store caught up with a commit would bank stale counts, start the
// next window empty, and leave the rise turning up with no budget to cover it.
// The app cannot put that frame in front of the spec: submit() pops one entry,
// so a commit lands back on the ledger it came from and the first Home reading
// is a whole action later, with the submit still in the window when the rise
// does show up.
test("a submit landing on the ledger is still in the window when Home reads it", () => {
const trace = run([
{ route: "home", cards: [card("Checking", 0, "3")], lastAction: idle },
{ route: "ledger", cards: [], lastAction: submit },
{ route: "home", cards: [card("Checking", 5000, "4")], lastAction: idle },
]);
assert.equal(trace[2]?.submits, 1);
assert.equal(
committedTransactionsExceedSubmits({
countsBefore: trace[1]?.counts ?? null,
countsAfter: trace[2]?.counts ?? null,
submitsInWindow: trace[2]?.submits ?? 0,
}),
false,
);
});
test("and a double submit down that same path still convicts", () => {
const trace = run([
{ route: "home", cards: [card("Checking", 0, "3")], lastAction: idle },
{ route: "ledger", cards: [], lastAction: doubleSubmit },
{ route: "home", cards: [card("Checking", 10000, "5")], lastAction: idle },
]);
assert.equal(trace[2]?.submits, 1);
assert.equal(
committedTransactionsExceedSubmits({
countsBefore: trace[1]?.counts ?? null,
countsAfter: trace[2]?.counts ?? null,
submitsInWindow: trace[2]?.submits ?? 0,
}),
true,
);
});