test(screens): cover screen cubits/blocs (+37 tests)#327
Merged
Conversation
Adds bloc_test specs for five screen-level cubits/blocs that previously only had widget-level coverage. - legal_disclaimer_cubit (7): initial state, nextStep advance, full walk to last step, onComplete callback on last step, no-op without callback, previousStep, no-op at step 0 - validate_seed_cubit (7): initial state, checkSeedLength (12 valid / short / unknown word / extra whitespace), validateSeed (valid / invalid) - transaction_history_filter_cubit (6): repo stream subscription, default 1-year window, stream-driven population, date-window filter, inclusive boundaries, filter re-application on subsequent emissions - verify_seed_cubit (6): random ascending word indices, debug-mode pre-fill, canVerify, updateWord trims/lowercases + clears error, verify success marks current wallet, verify failure flags error - setup_pin_cubit (11): initial state, addDigit append / 6-digit cap, deleteDigit / no-op on empty, create→confirm transition, matching pin persists salt + hash and emits isComplete (real PBKDF2 on compute-isolate shim), mismatching pin resets + flags mismatch, reset, isBiometricAvailable + enableBiometrics passthrough The matching-pin test exercises a real 600k-iteration PBKDF2 hash via `compute()`; on the Flutter-test isolate shim it takes ~12s. Generous timeout in the test reflects this.
3 tasks
TaprootFreak
added a commit
that referenced
this pull request
May 15, 2026
## Summary Stage 5 of the coverage push. Adds 32 unit tests for the PIN unlock cubit and three previously-untested DFX backend services. mocktail mocks for AppStore + repository boundaries; \`http.testing.MockClient\` for the HTTP surface. | File under test | Test file | Cases | | --- | --- | --- | | \`lib/screens/pin/bloc/verify_pin/verify_pin_cubit.dart\` | \`test/screens/pin/verify_pin_cubit_test.dart\` | 18 | | \`lib/packages/service/dfx/dfx_country_service.dart\` | \`test/packages/service/dfx/dfx_country_service_test.dart\` | 5 | | \`lib/packages/service/dfx/dfx_blockchain_api_service.dart\` | \`test/packages/service/dfx/dfx_blockchain_api_service_test.dart\` | 5 | | \`lib/packages/service/dfx/dfx_faucet_service.dart\` | \`test/packages/service/dfx/dfx_faucet_service_test.dart\` | 4 | ## What each file covers - **verify_pin_cubit:** initial state; \`addDigit\` / \`deleteDigit\` including no-ops at boundaries + while \`VerifyPinTemporarilyLocked\` / \`VerifyPinLocked\`; correct pin resets lockout and emits \`VerifyPinSuccess\` (real 600k-iter PBKDF2 via \`compute()\`); wrong-pin first-attempt path; \`enableLockout: false\` never persists attempts; 5th wrong attempt triggers a 1-minute temporary lockout; reaching \`permanentLockoutThreshold\` emits \`VerifyPinLocked\` and skips the temporary-lockout write; \`onLockExpired\` preserves \`failedAttempts\`; \`checkBiometricAvailability\` for the in-window / expired / threshold / success / fail / unavailable branches. - **dfx_country_service:** list mapping from the DTO + cache (single fetch even on repeated reads), non-200 throws, case-insensitive symbol lookup, unknown-symbol error, public \`cachedCountries\` field is populated post-fetch. - **dfx_blockchain_api_service:** POST shape (address + Bearer JWT + chain name + asset id), testnet flips \`blockchain\` to \`'Sepolia'\`, empty balances list returns \`0.0\`, 201 acceptance in addition to 200, \`ApiException\` on non-2xx with the JSON body. - **dfx_faucet_service:** POST + Bearer JWT to \`/v1/faucet\`, 201 acceptance, \`ApiException\` on non-2xx, **documents** the current behaviour of sending the literal string \`'Bearer null'\` when no auth token is set — useful as a regression marker if/when the service grows a guard. ## Notes - The verify-pin happy-path test exercises a real PBKDF2 (600k iterations) via \`compute()\`. On the Flutter-test isolate shim this takes a few seconds; the test uses a 30 s timeout, same approach as in PR #327's setup_pin test. - \`MockClient\` lets us stub \`AppStore.httpClient\` without giving the service its own real \`http.Client\`; the production code is unchanged. ## Excluded (and why) - \`dfx_kyc_service\`, \`real_unit_registration_service\` — overlap with the KYC cubits that #319 already covers; want to avoid a stack on top of that work mid-review. - \`real_unit_account_service\`, \`transaction_history_service\` — hit \`appStore.wallet.currentAccount.primaryAddress.address.hexEip55\`, which needs a real \`SoftwareWallet\` plumbed through the mock. Doable but more setup than the surface justifies; will be covered in a follow-up alongside hook tests. - \`dfx_brokerbot_service\`, \`real_unit_sell_payment_info_service\` — possibly touched by #321 (dashboard buy/sell auth). Hold to avoid review-time conflicts. - \`biometric_service\`, \`price_service\` — same constraints documented in #326. ## Test plan - [x] \`flutter analyze\` on the four new files — clean - [x] \`flutter test\` — 32 / 32 passing locally - [ ] CI green
3 tasks
TaprootFreak
added a commit
that referenced
this pull request
May 15, 2026
…21 tests) (#331) ## Summary Stage 8 of the coverage push. Adds 21 unit tests across five previously-untested cubits. | Cubit under test | Test file | Cases | | --- | --- | --- | | \`create_wallet/bloc/create_wallet_cubit.dart\` | \`test/screens/create_wallet/create_wallet_cubit_test.dart\` | 4 | | \`restore_wallet/cubit/restore_wallet/restore_wallet_cubit.dart\` | \`test/screens/restore_wallet/restore_wallet_cubit_test.dart\` | 3 | | \`debug_auth/cubit/debug_auth_cubit.dart\` | \`test/screens/debug_auth/debug_auth_cubit_test.dart\` | 7 | | \`dashboard/bloc/balance_cubit.dart\` | \`test/screens/dashboard/balance_cubit_test.dart\` | 4 | | \`dashboard/bloc/pending_transactions_cubit.dart\` | \`test/screens/dashboard/pending_transactions_cubit_test.dart\` | 3 | ## What each file covers - **create_wallet_cubit:** initial hides the seed + has no wallet, \`createWallet\` stores the new \`SoftwareWallet\` (pinning the \`'Obi-Wallet-Kenobi'\` default name), \`toggleShowSeed\` flips and returns to hidden after two toggles, \`toggleShowSeed\` preserves the wallet field. - **restore_wallet_cubit:** initial state, \`restoreWallet\` canonicalises mixed whitespace (\` x y \` → \`x y\`) before delegating to \`WalletService.restoreWallet\`, the interim \`isLoading=true\` state is observable. - **debug_auth_cubit:** seeds \`address\` + \`savedSignature\` from the service; empty-address fallback when service has none; \`fetchSignMessage\` success + error; \`authenticate\` success + uses-state-address + error. - **balance_cubit:** initial zero-balance state shape \`(chain, contract, wallet, asset)\`; subscribes to \`BalanceRepository.watchBalance\` on init; emits each pushed balance through the stream; \`close()\` cancels the subscription cleanly. - **pending_transactions_cubit:** initial empty list; emits fetched list on construction; falls back to empty list (not state-error) when the service throws. ## Excluded (and why) - **dashboard_bloc** + transaction-history sub-cubits + portfolio/price chart cubits — pull in multiple services or larger event-driven flows; would dwarf this PR. - **transaction_history_receipt_cubit** / **settings_tax_report_cubit** — both use \`getTemporaryDirectory()\` + real \`File\` IO; needs path_provider platform-channel plumbing. - **sell_***, **sell_bitbox_***, **hardware_connect_bitbox_*** — Bitbox-coupled or DFX-sell-flow-coupled; held back to avoid review conflicts with #321 area. - **transaction_history_filter_cubit** — already covered by #327. ## Test plan - [x] \`flutter analyze\` on the five new files — clean - [x] \`flutter test\` — 21 / 21 passing locally - [ ] CI green
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
Stage 4 of the coverage push. Adds bloc_test specs for five screen-level cubits/blocs that previously only had widget-level coverage. All run in pure Dart (no widget pumping); mocktail for the service / repository / SoftwareWallet boundaries.
What each file covers
Notes
Excluded (and why)
Test plan