docs: add features matrix + 100% test-coverage rule#322
Merged
Conversation
Document every user-facing function, its activation status, and the tests that cover it. Adopts the zkCoins-style coverage contract (100% on the activated surface, CI-enforced, branch-protected) as the target state. Honest about the current gap: the rule is aspirational until the coverage infrastructure (CI lcov gate, branch protection, build-time gating) lands. The roadmap section lists exactly what is missing. Cross-references the three open PRs that close the largest gaps (#319, #320, #321) and ties the feature matrix to the 4-tier testing model in #314.
This was referenced May 14, 2026
TaprootFreak
added a commit
that referenced
this pull request
May 15, 2026
) ## Summary Adds 38 unit tests across six previously-untested files in `lib/packages/utils/` and `lib/packages/wallet/`. Each spec lives in the mirror path under `test/` per the project convention. | File under test | Test file | Cases | | --- | --- | --- | | `lib/packages/utils/fast_hash.dart` | `test/packages/utils/fast_hash_test.dart` | 5 | | `lib/packages/utils/jwt_decoder.dart` | `test/packages/utils/jwt_decoder_test.dart` | 7 | | `lib/packages/wallet/payment_uri.dart` | `test/packages/wallet/payment_uri_test.dart` | 4 | | `lib/packages/wallet/wallet_account.dart` | `test/packages/wallet/wallet_account_test.dart` | 7 | | `lib/packages/wallet/wallet.dart` | `test/packages/wallet/wallet_test.dart` | 11 | | `lib/packages/wallet/eip7702_signer.dart` | `test/packages/wallet/eip7702_signer_test.dart` | 4 | ## What each file covers - **fast_hash:** FNV-1a determinism, distinct inputs differ, ordering matters, unicode safety, empty-string offset basis. - **jwt_decoder:** well-formed payload parsing, segment-count errors, non-map payload rejection, all three valid base64url padding lengths, illegal length-mod-4 rejection. - **payment_uri:** empty-amount short form, dotted and comma-locale amounts, preservation of decimal precision. - **wallet_account:** BIP-44 derivation path format, deterministic Hardhat account #0 address from the standard test mnemonic, distinct indices, signMessage shape + determinism + sensitivity to addressIndex. - **wallet:** `SoftwareWallet` walletType + primary/current account identity + `selectAccount` semantics + id/name mutability; `DebugWallet` sign refusal. - **eip7702_signer:** hardware-credential refusal (BitBox cannot sign EIP-7702), software-credential signing, signature determinism, nonce-sensitivity. ## Why Stage 2 of the coverage push tracked in the README features matrix ([#322](#322)). These six files are pure-Dart with no platform dependencies, so they were the cheapest meaningful coverage win available — no service mocks, no widget rendering, no merge-conflict risk with the three in-flight test PRs ([#319](#319), [#320](#320), [#321](#321)). ## Test plan - [x] `flutter analyze` clean on all six new test files (locally on Flutter 3.38.5) - [x] `flutter test test/packages/utils/ test/packages/wallet/` — 38 / 38 passing - [ ] CI green on this branch - [ ] Spot-check: coverage artifact from #323 (once that lands) shows non-zero coverage on the six files above
TaprootFreak
added a commit
that referenced
this pull request
May 15, 2026
## Summary Adds `flutter test --coverage` to the existing PR workflow and uploads the (filtered) `lcov.info` as a CI artifact. - `flutter test --coverage` replaces the plain `flutter test` invocation - `coverage/lcov.info` is filtered with `lcov --remove` to drop generated files (`lib/generated/**`) and `lib/main.dart` so the artifact reflects only the activated surface - The filtered report is uploaded as artifact `coverage-lcov` on every run (`if: always()`) - `lcov --summary` prints to the CI log so contributors can eyeball the line/function/branch numbers without downloading the artifact ## Why Step 1 of the coverage infrastructure roadmap documented in PR #322. Without measurement, the 100% rule is unverifiable; with measurement but no threshold, this PR is safe to merge today and lays the foundation for the threshold gate in a follow-up. ## What this PR is _not_ - Does **not** enforce any threshold. The build still passes regardless of coverage %. Hard-gating below 100% would block every open PR today (current coverage ratio ≈ 10%). - Does **not** add any new tests. - Does **not** change which files exist in `test/`. ## Test plan - [ ] CI run completes green - [ ] `coverage-lcov` artifact is present on the PR's checks page - [ ] `lcov --summary` line of the CI log shows non-zero coverage on `lib/packages/**` - [ ] Filtered report excludes `lib/generated/**`
TaprootFreak
added a commit
that referenced
this pull request
May 23, 2026
- fake_async example: add bitbox_flutter.dart import and inline the pairedServiceSync idiom so the snippet is copy-paste compilable - platform-coupled section: real-plugin counterpart is Tier 2/3, not Tier 1/2 (Tier 1 is FakeBitboxCredentials by definition); add the CONTRIBUTING.md footnote-165 caveat that the annotation is the documenting form today - README: PRs #319/#320/#321/#322/#323 are all merged since 2026-05-15; replace "in flight"/"landing in"/"extended in" with "added via" / "have closed" / "partially covered after"
TaprootFreak
added a commit
that referenced
this pull request
May 23, 2026
Tier-1 integration tests stitching SellBitboxCubit → FakeBitboxCredentials boundary → real RealUnitSellPaymentInfoService → MockClient. The cubit and the service are both real production code; only the BitBox transport and the HTTP wire are stubbed. This pins: * happy path — full swap+deposit ceremony emits two BitBox signs and the correct broadcast order/wire-shape (unsignedTx + r/s/v padding). Regression class: silently double-signing on the device or swapping leg order. * cancel mid-swap — FakeBitboxBehavior.cancel propagates as SigningCancelledException all the way to SellBitboxError instead of being silently accepted as a successful sign (PR #322 bug class). * disconnect — BitboxNotConnectedException is caught EXPLICITLY by the cubit's typed catch and emits SellBitboxBitboxRequired, not a generic Error state. Regression class: re-pair screen replaced by raw error string (PR #341). * malformed signature — FormatException from a frame-desync hits the generic catch and surfaces as SellBitboxError, NOT mis-classified as a BitBox disconnect (would mask sig bugs as UX disconnect prompts). * deposit-retry — transient 5xx on the deposit broadcast lands the cubit in SellBitboxDepositRetry with both signed envelopes preserved; the user does not have to re-sign on the device. Regression class: funds-at-risk loss of the already-signed swap (PR #338).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Replace the bare README with a full project-overview document modelled on the
zk-coins/appREADME. Adds:develop. Defensive code is exempted via// coverage:ignore-*. Branch protection enforces.lib/packages/**+ everycubits//bloc/directory underlib/screens/<feature>/. Widget files render-tested viatestWidgetsonly.--coveragestep, lcov threshold gate, branch protection, build-time feature flags, inline ignore annotations).mvp/defer/planned), and the tests that currently cover it.mvpfeatures still below 100%, with links to the in-flight PRs (#319, #320, #321) that close them.Why
The repo has no source of truth for "what does this wallet actually do" or "what is its test-coverage commitment". Tests in
test/exist but are unbound to features — a reviewer cannot tell at a glance whether a feature added in a PR has the required coverage. This document closes that gap.The coverage rule deliberately mirrors
zk-coins/appexactly (same wording, same scope shape) so that reviewers familiar with one project transfer their expectations to the other. The 4-tier testing model is owned by #314; this README references it but does not duplicate it.What this PR is not
flutter test --coverageinto CI. That is item 1 of the roadmap and will land in a follow-up.Until the roadmap items land, the rule is aspirational, explicitly noted as such in the README, and not yet a merge blocker.
Test plan
widget-tagged row points at an existing*_test.dartfile intest/