Skip to main content

Module testonly

Module testonly 

Source
Expand description

Shared synthetic corpora + per-journey fixtures for the worked-example journeys (J1–J9).

Hoisted here (from xtask, TUI-walkthrough spec §4.1) so ALL consumers share ONE source of truth: the xtask examples generator, and the btctax-tui / btctax-tui-edit screen-walkthrough emit tests. A plain pub module (like btctax_forms::testonly) — the corpora are tiny synthetic CSVs, and the generator’s generate() is a non-test fn, so they cannot be #[cfg(test)].

The CSV corpora carry explicit CRLF: committed .csv files are force-LF’d by .gitattributes and would break the Coinbase parser, so they live as string consts (a driver writes them to a tempdir at runtime). These bytes are byte-identical to their previous home in xtask/src/examples.rs — the examples_golden_matches_committed gate proves the move changed nothing.

Structs§

JourneyFixture
One journey’s synthetic input: the named corpus files a driver writes to a tempdir before import. The SAME fixture seeds both walkthrough capture halves (the editor emit test drives its flows; the viewer emit test re-seeds this corpus and replays the equivalent decisions via btctax-cli), so the two halves of a journey converge by construction on one source of truth (walkthrough spec §4.2).

Constants§

J1_CSV
J1 corpus: a single-buyer happy path — one Buy + one partial Sell in 2025.
J2_CSV
J2 corpus: an LT lot (2023) + an ST lot (2025) + a 2025 Send of 2 BTC donated to charity.
J3_CSV
J3 corpus: a Buy + a Receive (an inbound transfer with unknown basis → a hard blocker until classified).
J4_CSV
J4 corpus: two River staking-income deposits in 2025 (FMV resolved from the bundled dataset).
J5_CSV
J5 corpus: an LT lot + a higher-basis ST lot + a 2025 sell — a genuine changed-selection scenario (HIFO ≠ FIFO) so the optimizer has a tax-saving pick to propose.
J6_COINBASE_CSV
J6 Coinbase corpus: a cheap 2020 long-term lot, a small 2024 sale, and a 2024 charitable Send of 0.1 BTC (§170(e) donation ⇒ Form 8283). NOTE: HIFO reconstruction draws the 2024 sale from the higher-basis 2024 mining lot (not this 2020 lot) ⇒ it is SHORT-term (Schedule D Part I). Amounts kept small so the return stays clear of Form 6251’s Who-Must-File test (line 7 <= line 10).
J6_FULLRETURN_TOML
The committed full-return ReturnInputs (the kitchen_sink_household() oracle, TOML-serialized). J6 imports it via income import. The fixture lives in this crate (self-contained), so this is a SAME-crate include_str! — retiring the cross-crate include the xtask copy carried (M-5 exception).
J6_RIVER_CSV
J6 River corpus: one small 2024 business mining-income deposit (FMV from the bundled dataset). Kept modest deliberately: a corpus editor who enlarges the sale, income, or donation must keep the household on the computable side of Form 6251 line 7 <= line 10 (Who Must File condition 1), which is what refuses a return now — NOT the screening worksheet, which since v0.14.0 gates nothing.
J7_CSV
J7 corpus (UX-P1-7): a single 2024 Coinbase Receive of staking rewards — an unknown-basis inbound the single-event classify-inbound-income command values only from a hand-supplied --fmv.
J8_COINBASE_CSV
J8 Coinbase corpus (UX-P1-8): the matching inbound Receive of 0.10 BTC — the SAME coins landing at a second exchange, so the pair is a cross-wallet RELOCATE (not a same-wallet DROP).
J8_RIVER_CSV
J8 River corpus (UX-P1-8): a buy (to give the coins a basis) then a Withdrawal OUT of 0.10 BTC — the out-leg of a cross-exchange self-transfer whose in-leg lands on Coinbase below.
J9_CSV
J9 corpus (UX-P1-10): a cheap 2023 long-term lot (0.60) + a pricier 2024 lot (0.40), then a 2025 sale of only 0.50 — less than the combined holdings, so specific-lot identification is meaningful.
J10_CSV
J10 corpus — a household the AMT SCREEN flags but that owes no alternative minimum tax. One 2021 lot sold in 2024 for a $200,000 long-term gain; paired with J10_FULLRETURN_TOML’s $400,000 of wages it reaches $600,000 of AGI, which trips the Form 6251 screening worksheet (its line 11 = $466,700, over the $232,600 breakpoint). Before Form 6251 was computed, btctax REFUSED this return outright and wrote no forms at all.
J10_FULLRETURN_TOML
J10’s non-crypto side: MFJ, $400,000 of wages, the standard deduction, no Schedule A. Deliberately carries NO mortgage interest and NO capital-loss carryforward, so neither Form 6251 declaration (lines 3 and 2k) is live — the journey demonstrates the AMT computation, not the questions.

Functions§

j1
The nine journey fixtures, keyed by the same corpus filenames the examples journeys use.
j2
j3
j4
j5
j6
j7
j8
J8 — the PoC journey: a cross-exchange self-transfer (River Withdrawal out → Coinbase Receive in).
j9
seed_j1_with_profile
Seed J1 (single buyer: one Buy + one partial Sell, no transfers → no reconciliation) and set the 2025 tax profile its walkthrough VIEWER needs for the Tax tab to compute — single filer, $100k ordinary income, mirroring the J1 worked example’s tax-profile step. The viewer half then only opens + reads.
seed_j2_donated
Seed J2’s fully post-decision state — the outbound reclassified as a donation, the Form 8283 appraiser/donee details recorded (Section B complete), and a 2025 profile so the viewer’s Tax tab computes the charitable-deduction line. The walkthrough’s VIEWER renders Forms (the two 8283 rows) + Tax. Made-date threaded from the caller.
seed_j2_reclassified
Seed J2 with the outbound Send reclassified as a §170(e) charitable DONATION (FMV $217,992.34 = 2 BTC × the contribution-date close, donee “Habitat for Humanity”) — but WITHOUT the Form 8283 appraiser/donee details yet. This is the state the walkthrough’s d (set-donation-details) EDITOR frame drives from (the details form still empty). Made-date threaded from the caller.
seed_j3_self_transfer
Seed J3 (an unknown-basis inbound Receive → a hard blocker) classified as a SELF-TRANSFER of the filer’s own coins returning — non-taxable, carrying a supplied basis ($19,000) and acquisition date (2024-11-01, so the holding period runs from then). The post-classify state the VIEWER renders (Holdings). The editor half seeds only the raw import and drives the classify. Made-date threaded from the caller.
seed_j4_reclassified
Seed J4 (two River staking receipts) with a 2025 profile AND both receipts reclassified as a trade or business (--business true --kind staking) — the post-reclassify state the walkthrough’s VIEWER half renders (Income now on Schedule C/SE; Tax shows the self-employment tax). The editor half drives the reclassify itself, so it seeds only the raw import (seed_journey(&j4())). Made-date pinned for determinism. Refs embed the ms-timestamp of each receipt (not wall-clock).
seed_j5_elected
Seed J5 (an LT lot $30k + a higher-basis ST lot $80k + a 2025 sale $50k) with a 2025 profile AND a standing FIFO election — but NOT the optimizer’s accept. This is the state the walkthrough’s z (optimize-accept) EDITOR frames drive from: the optimizer proposes swapping to the ST lot to realize a loss. The election made-date is hardcoded 2025-01-01 (the engine blocks effective_from before the made-date, so a later threaded now would trip MethodElectionBackdated).
seed_j5_optimized
Seed J5’s post-accept state — the FIFO election PLUS the optimizer’s proposed lot pick accepted (the whole sale moved onto the short-term opt-buy-st lot to realize a loss). The walkthrough’s VIEWER renders the resulting Disposals (ST loss) + Tax (§1211 deduction + carryforward). now is the accept made-date — MUST be ≤ the 2025-06-01 sale so the selection is Contemporaneous; the caller passes the same instant the editor frames pin.
seed_j6_full
Seed J6 — a COMPLETE Form 1040 (the kitchen-sink MFJ household). Combines the crypto reconciliation (mining income → a trade or business; the 0.10 BTC Send → a §170(e) donation with Form 8283 details) with the non-crypto household imported from the committed kitchen_sink_household() TOML. This is the state BOTH walkthrough halves render: the editor half opens the tax-inputs authoring form (T) over these committed inputs; the viewer shows Forms (the crypto forms) + Tax (the merged MFJ return). No raw tax-profile — the full-return inputs take precedence and build_snapshot derives the MFJ profile from them. Made-date threaded from the caller.
seed_j7_income
Seed J7 (a single off-exchange Receive with no market price → a hard unknown-basis blocker) classified as staking INCOME with a hand-supplied FMV ($3,300), plus a 2024 profile — the post-classify state the walkthrough’s VIEWER renders (Income + Tax). The editor half seeds only the raw import and drives the classify. Made-date threaded from the caller (matches the depicted editor session’s clock).
seed_j8_relocated
Seed J8 and apply its RELOCATE self-transfer (river out → coinbase in) — the post-match state the walkthrough’s VIEWER half renders (BALANCED). Refs are J8’s deterministic event refs; RELOCATE routes to link_transfer (out → in), the same decision the editor’s confirm modal makes.
seed_j9_selected
Seed J9 (a cheap 2023 LT lot 0.60 + a pricier 2024 lot 0.40, then a 2025 sale of 0.50 — less than the combined holdings, so specific-lot identification is meaningful) with the whole 0.50 IDENTIFIED against the cheap long-term lot-a (a deliberate per-disposal specific identification). The post-selection state the walkthrough’s VIEWER renders (Disposals drawing from lot-a; Compliance now satisfied). The editor half seeds only the raw import and drives the select-lots flow. Made-date threaded from the caller (the identification is contemporaneous — before/at the sale).
seed_journey
Init a vault at dir/vault.pgp and import the journey fx’s corpus via the REAL adapter ingest.