Skip to content

test: support + edit-data cubits (+34 tests)#330

Merged
TaprootFreak merged 1 commit into
developfrom
test/support-and-settings-cubits
May 15, 2026
Merged

test: support + edit-data cubits (+34 tests)#330
TaprootFreak merged 1 commit into
developfrom
test/support-and-settings-cubits

Conversation

@TaprootFreak
Copy link
Copy Markdown
Contributor

Summary

Stage 7 of the coverage push. Adds 34 unit tests for the remaining support cubits and three settings-user-data edit cubits.

Cubit under test Test file Cases
`support/cubits/support_chat/support_chat_cubit.dart` `test/screens/support/cubits/support_chat_cubit_test.dart` 6
`support/cubits/support_create_ticket/support_create_ticket_cubit.dart` `test/screens/support/cubits/support_create_ticket_cubit_test.dart` 9
`settings_user_data/subpages/edit_name/cubit/settings_edit_name_cubit.dart` `test/screens/settings_user_data/subpages/settings_edit_name_cubit_test.dart` 8
`settings_user_data/subpages/edit_phone_number/cubit/settings_edit_phone_number_cubit.dart` `test/screens/settings_user_data/subpages/settings_edit_phone_number_cubit_test.dart` 3
`settings_user_data/subpages/edit_address/cubit/settings_edit_address_cubit.dart` `test/screens/settings_user_data/subpages/settings_edit_address_cubit_test.dart` 8

What each file covers

  • support_chat_cubit: Loaded with the mapped ticket; Error on `getTicket` throw; `sendMessage` no-op when not in Loaded state and for whitespace-only input; happy-path posts the message + re-fetches the ticket (2 `getTicket` calls verified); service failure resets `isSending=false` while keeping Loaded.
  • support_create_ticket_cubit: initial state; `selectType` resets reason to `.other`; `selectReason` preserves type; `updateMessage` field-only; `canSubmit` gate matrix (type-null / reason-null / empty / whitespace / submitting → all false); `submit` no-op when not submittable; happy-path forwards type + reason + the mapped `name` for both `bugReport` and `genericIssue` (pins the `_getTicketName` switch); failure captures the error.
  • settings_edit_name_cubit: Ready URL, Pending on `inReview`, Failure on API throw, Failure on missing URL, `refresh` recovers; `submitName` no-op when not Ready, posts the form payload + emits Success, Failure on `setData` throw.
  • settings_edit_phone_number_cubit: initial state; happy-path emits `[Submitting, Success]` and forwards `{'phone': N}`; service throw yields `[Submitting, Failure]` with the error message.
  • settings_edit_address_cubit: same shape as edit_name plus two address-specific pins — the nested payload (`address.country.id`) and `houseNumber` is omitted from the payload when empty.

Notes

  • Cubits that fire work in their constructor (`support_chat`, `settings_edit_name`, `settings_edit_address`) use `stream.firstWhere` to await the final state instead of `blocTest`'s sequence-based expect — same pattern as test: bank-account + price services, contact + tickets cubits (+23 tests) #329, with a one-line comment in each test file header.
  • `SupportCreateTicketState.copyWith` uses `?? this.x`, so `copyWith(selectedType: null)` does not clear the field. The `canSubmit` matrix builds the failing variants as fresh state objects to avoid that footgun, and the rationale is on the test.

Excluded (and why)

  • `settings_user_data_cubit.dart` — touches three services + country lookups + multi-path KYC step status; will be covered in a follow-up alongside hook tests.
  • `settings_tax_report_cubit.dart` — uses `getTemporaryDirectory()` + real `File` IO; needs path_provider platform-channel plumbing or a refactor.
  • `dashboard` blocs, `create_wallet` cubit, `restore_wallet_cubit` — left for the next stage.
  • `dfx_kyc_service` — covered indirectly via the edit cubits in this PR; a dedicated test of its surface would overlap heavily with test(kyc): add Phase 0 cubit unit tests for BitBox-gated KYC flow #319's KYC cubit tests.

Test plan

  • `flutter analyze` on all five new files — clean
  • `flutter test` — 34 / 34 passing locally
  • CI green

Stage 7 of the coverage push.

- support_chat_cubit (6): Loaded with the mapped ticket, Error on
  getTicket throw, sendMessage no-op when not in Loaded state and
  for whitespace-only input, happy path posts + re-fetches ticket,
  service failure resets isSending=false
- support_create_ticket_cubit (9): initial state; selectType resets
  reason to .other; selectReason preserves type; updateMessage
  field-only; canSubmit gate matrix (4 failing variants); submit
  no-op when canSubmit=false; submit happy-path forwards type +
  reason + the mapped name (bugReport/genericIssue branches); submit
  failure captures the error
- settings_edit_name_cubit (8): Ready URL, Pending on inReview,
  Failure on API throw, Failure on missing URL, refresh recovers,
  submitName no-op when not Ready, submitName posts form payload
  + emits Success, submitName Failure on setData throw
- settings_edit_phone_number_cubit (3): initial Initial; happy path
  emits [Submitting, Success] and forwards {'phone': N}; service throw
  yields [Submitting, Failure]
- settings_edit_address_cubit (8): Ready URL, Pending, Failure on
  throw, Failure on missing URL, submit no-op when not Ready, submit
  payload shape (nested address with country.id), houseNumber omitted
  when empty, Failure on setData throw
@TaprootFreak TaprootFreak marked this pull request as ready for review May 15, 2026 09:00
@TaprootFreak TaprootFreak merged commit e43c0b0 into develop May 15, 2026
1 check passed
@TaprootFreak TaprootFreak deleted the test/support-and-settings-cubits branch May 15, 2026 09:01
TaprootFreak added a commit that referenced this pull request May 15, 2026
…ts) (#336)

## Summary
Stage 12 of the coverage push. Covers the previously-deferred
\`settings_user_data_cubit\` (3-service coordination + Country lookups)
and the read-side of \`transaction_history_service\`.

| File under test | Test file | Cases |
| --- | --- | --- |
| \`lib/screens/settings_user_data/cubit/settings_user_data_cubit.dart\`
| \`test/screens/settings_user_data/settings_user_data_cubit_test.dart\`
| 6 |
| \`lib/packages/service/transaction_history_service.dart\`
(\`fetchPendingTransactions\` only) |
\`test/packages/service/transaction_history_service_test.dart\` | 6 |

## What each file covers
- **settings_user_data_cubit:** the cubit fans out to
\`RealUnitWalletService.getWalletStatus\` and
\`DfxKycService.getKycStatus\` in parallel, then either falls back to
\`getUser\` (when userData is missing) or runs two more
\`getCountryBySymbol\` lookups. Tests pin:
- Full Success when userData is present (with nationality +
addressCountry country lookups resolved to distinct \`Country\`
instances).
- \`pendingSteps\` only contains the three change steps
(name/address/phone) that are in \`inReview\` — other inReview steps
(e.g. \`contactData\`) are ignored.
- \`userData == null\` + \`getUser\` returns mail → \`Success(email)\`,
no country lookups happen.
- \`userData == null\` + \`getUser\` throws → \`Success()\` with both
userData and email null.
- Failure when \`getWalletStatus\` throws (the \`Future.wait\`
propagation).
- Failure when \`getCountryBySymbol\` throws on a userData with a
country code.
- **transaction_history_service.fetchPendingTransactions:** no auth
token short-circuits to \`[]\` without any HTTP call (verified via a
MockClient that records calls); GET shape with the Bearer JWT to
\`/v1/transaction/detail\`; non-200 returns \`[]\` (does not throw —
intentional UX); filters out \`Completed\`/\`Failed\`/\`Returned\`
(\`isPending=false\` per the enum extension); filters out transactions
whose \`sourceAccount\` / \`targetAccount\` don't match the current
wallet; wallet-match is **case-insensitive** (covers the lower-casing on
both sides).

## Notes
- \`RealUnitUserDataDto.type\` must use \`'HUMAN'\` / \`'CORPORATION'\`
(the jsonName values of \`RegistrationUserType\`), not a friendly label
— \`fromName\` throws \`StateError\` otherwise.
- Mocktail's \`stream.firstWhere\` pattern is reused for the cubit
(constructor fires \`getUserData\` synchronously, so we can't use
\`blocTest\`'s sequence model reliably here — same as #329, #330, #333).

## Excluded (and why)
- \`transaction_history_service.apiBasedSync\` — writes through
\`TransactionRepository.insertDfxTransaction\`/\`updateTransaction\` and
depends on \`AppStore.primaryAddress\` + \`apiConfig.asset.chainId\`.
Doable but adds repository mock plumbing for a method that's almost
entirely orchestration; will be its own focused PR.
- Buy / sell cubits — still held while #321 (dashboard buy actions) and
#332 (bitbox sign hardening) are open.

## Test plan
- [x] \`flutter analyze\` on the two new files — clean
- [x] \`flutter test\` — 12 / 12 passing locally
- [ ] CI green
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant