test(balance): cross-cutting integration tests (#144) #152

Merged
maximus merged 4 commits from issue-144-bilan-6 into main 2026-04-26 13:25:38 +00:00

4 commits

Author SHA1 Message Date
le king fu
5274e51907 chore: CHANGELOG entry for cross-cutting tests
All checks were successful
PR Check / rust (push) Successful in 22m44s
PR Check / frontend (push) Successful in 2m23s
Bilingual entry under [Unreleased] documenting the integration test
suite added for Issue #144: end-to-end happy path, currency lock,
priced-kind tolerance safety, computeAccountReturn wiring, three Rust
migration-on-seeded-DB scenarios, and the source-level non-regression
test on the inlined transfer icon.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 16:54:04 -04:00
le king fu
5a54d37de5 test(transactions): add non-regression test for inline transfer icon
Source-level structural test on `TransactionTable.tsx` to lock down the
inlined transfer icon contract introduced in #142. Without RTL or jsdom
in the dev-deps, the test reads the component source and asserts:

  - the icon is gated by `linkedTransfersByTxId?.has(row.id)`,
  - optional-chaining short-circuits cleanly when the prop is omitted
    (zero-impact on pre-#142 callers),
  - the prop is declared OPTIONAL on the component interface,
  - the `Link2` glyph comes from lucide-react,
  - tooltip + aria-label go through `transactions.transferIcon.*` i18n
    keys,
  - the row's description cell layout (truncate span + title) stays
    shared between linked and non-linked rows.

Catches the specific regression vectors: someone removing the gate,
renaming the prop, or breaking the optional-chaining pattern that
guarantees the page renders identically when no transfers are linked.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 16:53:59 -04:00
le king fu
50fe0ab1ac test(balance): add migration v9 integration on seeded DB
Three new Rust integration tests applied at the bottom of `lib.rs`'s
`#[cfg(test)] mod tests`. They exercise the realistic upgrade path: a v1
profile DB with imported transactions + categories already there gets the
v9 migration applied on top.

`migration_v9_preserves_existing_transactions_on_seeded_db` asserts no
row loss / data mutation after the migration runs. Spot-checks one
amount preserved verbatim and that the v9 seeded categories coexist with
the v1 categories table.

`integration_link_unlink_transfer_roundtrip_on_seeded_db` walks link →
joined-view read → blocked deletion (FK RESTRICT) → unlink → allowed
deletion → orphan-row sanity check. Covers the FK chain end-to-end on
real (non-stub) transaction ids.

`integration_modified_dietz_inputs_read_back_correctly_on_seeded_db`
mirrors the exact SQL used by `balance_commands.rs::read_value_at_or_before`
and `read_cash_flows`, asserting the snapshot-endpoint lookups and the
period-bounded JOINed cash flows return the expected shapes when run
against a seeded v1+v9 DB.

`integration_v9_preserves_v1_categories_and_keywords` verifies the
`categories.id` and `balance_categories.id` namespaces are independent
(same numeric id allowed on each table without collision).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 16:53:50 -04:00
le king fu
9adfb85d84 test(balance): add cross-cutting integration tests
End-to-end happy path through the full Bilan stack: account → priced
category → priced snapshot → linked transfer → return. Drives every
service against the existing in-memory FakeDb harness used by
category-migration tests so SQL shape (table names + parameters) can be
asserted alongside service outputs.

Currency lock: USD / EUR / GBP / JPY / AUD all rejected up-front by the
service with a typed `currency_unsupported` code, no DB hit. The CAD
default is verified to land in the INSERT params explicitly.

Priced-kind safety: a snapshot save with one out-of-tolerance line must
NOT clear pre-existing lines (the DELETE is gated behind the validation
loop). A drift just within ε is accepted unchanged.

computeAccountReturn wiring: malformed dates are rejected client-side
without invoking the Rust command; missing active profile yields a typed
`transfer_active_profile_unknown`; partial-period payloads are forwarded
unchanged (null fields preserved).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 16:53:36 -04:00