banca / client / test / README.md
  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
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
# tests

`npm test` runs, in order:

1. `clojure -M:cljfmt check src` — the formatting gate, config in
   `client/.cljfmt.edn`. It is the FIRST link of the `test` script rather than a
   `pretest` hook on purpose: an npm lifecycle hook is skipped outright under
   `ignore-scripts=true`, which is a gate that passes by not running.
2. `npm run check:app` — compiles the `:app` build (the one that actually
   ships to a browser) into a throwaway `target/check-app`, so the gate costs
   nothing but a compile and writes nothing into `dist/`.

   This link exists because of a real defect: the scaffold vendors
   `lib/mailbox.cljs` from chat, that file requires `promesa.core`,
   `banca.fx` and `banca.wire` — and the scaffold shipped none of them. The
   `:app` build therefore did not compile from day zero, and **the whole suite
   was green the entire time**, because step 3 builds only `:testlib`. A gate
   that never compiles what ships is a gate that passes by not looking. If you
   add a namespace to a build that the tests do not exercise, add it here too.
3. `shadow-cljs release testlib` — the `:testlib` ESM build. Everything below
   asserts against `test-dist/testlib.js`, never against `src/`: a vector that
   reads the source pins the source rather than what ships.
4. `TZ=UTC node --test test/*.test.mjs`.

Note the unquoted glob: `node --test 'test/*.test.mjs'` and `node --test test/`
both misbehave on some node versions. Point it at files, unquoted.

## The suites

**`source-hygiene.test.mjs`** — a source lint over `src/banca`, for the CLJS
traps that each shipped a bug in this suite: a local or a `defn` shadowing a core
macro/var, a `#js {}` or `js-obj` literal with pairs (key order silently becomes
hash order at nine pairs), a sibling form dedented below the one above it (the
paren-depth error that took chat and board down in production), an interop call
whose target is a function literal, the JS façade freeze, and the raw-HTML
surface as an exact budget. Every check carries a probe beside it that runs the
detector over code which *does* offend. Its header records which of chat's
checks were kept, adapted and dropped on the way into this repo, and why.

It scans **this repo's** namespaces only. The shared rooms core
(`ardegazu.rooms.*`) comes off the classpath from `ardegazu-rooms-kit` and is
linted there, by that repo's copy of this file.

**`protocol.test.mjs`** — BANK/1's op union: the key order of every builder
(against a table written by `independent.mjs`'s own hand-written builders, so the
two must agree with each other rather than with themselves), and a 44-row
validator reject table with the non-vacuity probe that every unmutated sample
validates.

**`order.test.mjs`** — the wallet-kit seam. banca transcribes wallet-kit's
preimage assembly and shape grammar because that kit is unreleased and cannot be
sha-pinned; this checks the transcription against wallet-kit's **own published**
golden vector and against a by-hand canonical-JSON template.

**`receipts.test.mjs`** — the double-signed portable receipt, including the
honest asymmetry: a banker can ack with a wrong-but-well-formed `bsig`, the fold
still calls the payment final, and the exported receipt does not verify. Both
halves are asserted.

**`fold.test.mjs`** — the settlement fold, 28 hand-computed scenarios plus the
order-independence property over three fixed insertion permutations of every one
of them.

## Methodology, and it is not optional

**A vector generated from the implementation it pins proves nothing.**
`test/vectors/independent.mjs` imports nothing from `test-dist/`: canonical JSON
is re-implemented from its spec sentence, the two preimages are written out as
literal templates a reader can check character by character, Ed25519 comes from
`@noble/curves` and SHA-256 from `node:crypto`. Every fold expectation in
`fold.json` is **hand-computed** and written as a literal beside an `input_desc`
sentence a reader can check by adding up four numbers.

That is not ceremony. The by-hand receipt template was wrong on its first draft —
it dropped `po.sig` from the preimage — and wallet-kit's published string is what
settled which side was right. A fixture recorded from the implementation would
have been green and wrong.

**Probe every gate by deliberately breaking what it guards.** An unprobed gate is
a claim, not a check. `dev/docs/CLJS.md` — "Test-harness notes", "Crypto and wire
compatibility", "Gates: write them, then try to break them" — is the canon.

## Regenerating the vectors

```
node test/vectors/build-vectors.mjs
```

Run it **deliberately**, never as part of `npm test`. It rewrites
`order.json`, `receipts.json` and `fold.json` from `independent.mjs` and the
hand-written expectations inside the generator. If a scenario's expectation is
wrong, the fixture is the claim and the implementation is the thing on trial —
change the expectation only when you have worked out on paper why it was wrong.

`test/vectors/facade.json` has **no** generator on purpose. Changing the façade
is a decision, not a refresh: the failing `deepEqual` prints the whole diff, and
a change you meant to make is applied by editing the file to match, reading every
moved line as you go.

## Still to add

- **`test/orbit-address.test.mjs`**, if you care that bank addresses are
  deterministic. It boots the real stack, which needs the libdatachannel native
  addon — that is what `scripts/ensure-native.mjs` is for; re-add it as the
  `pretest` step (and note the point above about `ignore-scripts`).
- **An i18n placeholder test** once there is a UI: every `(t "key" {…})` call
  site must supply exactly the placeholders its English string uses. board's
  `source-hygiene.test.mjs` has the canon copy; board shipped a raw `{cur}` on
  every returning user's screen for want of it.

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