Skip to content

test(ci): repair CI breakages introduced by #461#471

Merged
TaprootFreak merged 3 commits into
developfrom
fix/ci-after-pr461
May 20, 2026
Merged

test(ci): repair CI breakages introduced by #461#471
TaprootFreak merged 3 commits into
developfrom
fix/ci-after-pr461

Conversation

@TaprootFreak
Copy link
Copy Markdown
Contributor

Summary

develop CI is red after #461 merged: Run flutter test --coverage reports 1342 tests passed, 17 failed. All 17 are direct consequences of the new wiring shipped by #461 — they did not surface locally because Flutter's test runner parallelises per file and GetIt's singleton state leaks across files differently than on CI.

This PR repairs the test suite without touching any production code.

Failure groups & fixes

1. PaymentInfoError variant count drifted (1 test)

test/packages/service/dfx/models/payment/buy_sell_dtos_test.dart pins the enum to "four documented variants". #461 added bitboxDisconnected (now five) but did not update the pinning test.

→ Change hasLength(4)hasLength(5), add bitboxDisconnected to the asserted set, rename the test description.

2. MockAppStore.ensureUnlocked not stubbed (9 + 1 tests)

#461 added await appStore.ensureUnlocked() to RealUnitSellPaymentInfoService.confirmPayment and the SettingsSeedCubit._loadSeed() path. Tests using _MockAppStore/MockAppStore without stubbing ensureUnlocked got null back from mocktail and threw TypeError: type 'Null' is not a subtype of type 'Future<void>'.

Affected:

  • test/packages/service/dfx/real_unit_sell_payment_info_service_validation_test.dart (9 confirmPayment validation guard tests)
  • test/screens/settings_seed/settings_seed_page_test.dart (1 page test)

→ Add when(() => appStore.ensureUnlocked()).thenAnswer((_) async {}); to each setUp.

3. Page tests don't register DfxKycService (4 tests)

#461 added DfxKycService as a cubit dependency for ensureSignatureFor. The existing create_wallet_page_test and restore_wallet_page_test only register WalletService in setUpAll, so BlocProvider(create:) fails with Bad state: GetIt: Object/factory with type DfxKycService is not registered when the cubit is first read.

→ Add MockDfxKycService and register it in setupDependencyInjection of both files.

4. settings_seed_cubit_test race on slow CI (1 test)

toggleShowSeed flips showSeed and keeps seed unchanged relies on wait: const Duration(milliseconds: 10) between act and verify. The async _loadSeed() chain (ensureUnlocked → seed emit) takes longer than 10 ms on CI, so the toggle races with the post-_loadSeed emit and showSeed ends up false instead of true.

→ Replace the static wait: with an explicit await c.stream.firstWhere((s) => s.seed.isNotEmpty) inside act so the test only toggles after _loadSeed has settled. Same fix on the sibling "toggleShowSeed twice" test.

5. bitbox_credentials_test queue test relabels error (1 test)

queue continues after a sign throws (slot released in finally) expects the original Exception('first sign explodes') to surface. #461's new _runOrThrowDisconnect wrapper probes manager.devices on a thrown sign and relabels the error as BitboxNotConnectedException if the device list is empty. The mock did not stub devices, so it defaulted to null_deviceLost() returned true → the original exception got relabelled.

→ Add a one-line stub when(() => manager.devices).thenAnswer((_) async => [_FakeDevice()]) so the disconnect probe returns "still connected" and the original exception survives.

Verification

  • Local repro of CI: flutter test --coverage matches the CI's failure profile (1342 / 17) on develop.
  • Post-fix expected on CI: 1359 / 0.
  • No production code touched.

Why this needs to land fast

develop CI is currently red, which blocks the auto-tag + release pipelines and propagates to any PR (e.g. #466) that runs against this branch. All seven changes are scoped to test/ only.

Test plan

  • flutter analyze — clean
  • flutter test --coverage — green (1359/0)
  • CI on this PR — green

After #461 merged, CI showed 17 test failures that did not surface locally
due to test-ordering / parallelisation differences. All 17 were direct
consequences of the new wiring shipped in #461.

Concrete fixes:

- buy_sell_dtos_test: PaymentInfoError variant count 4 → 5 + add
  bitboxDisconnected to the asserted set. #461 added the variant but
  did not update the pinning test.

- real_unit_sell_payment_info_service_validation_test: confirmPayment now
  calls appStore.ensureUnlocked() before reading credentials. Stub the
  call on _MockAppStore so mocktail returns Future<void> instead of null.

- settings_seed_page_test: SettingsSeedPage builds a real SettingsSeedCubit
  via BlocProvider(create:), which calls ensureUnlocked() before reading
  the seed. Stub it on the shared MockAppStore.

- settings_seed_cubit_test: replace the static wait: 10 ms in the two
  toggleShowSeed blocTests with an explicit stream wait so the
  _loadSeed() promotion settles before toggleShowSeed runs. The 10 ms
  budget races on slow CI runners.

- create_wallet_page_test, restore_wallet_page_test: register
  MockDfxKycService in setUpAll. #461 added DfxKycService as a cubit
  dependency for ensureSignatureFor; without registration BlocProvider
  fails when the cubit is first read.

- bitbox_credentials_test (queue continues after a sign throws): stub
  manager.devices to a non-empty list so _runOrThrowDisconnect's
  disconnect-probe returns false and the original Exception survives
  instead of being relabelled BitboxNotConnectedException.
@TaprootFreak TaprootFreak marked this pull request as ready for review May 20, 2026 14:58
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 20, 2026

BitBox02 simulator check

Host: linux/amd64 — Started: 2026-05-20T17:18:13Z — Duration: 660ms

Firmware: bitbox02-multi-v9.26.1-simulator1.0.0-linux-amd64

Scenario Result Duration Detail
pair_and_device_info 40ms
restore_simulator_mnemonic 18ms
root_fingerprint_deterministic 0ms
eth_address_mainnet 42ms
eth_address_polygon_multibyte_v 41ms
eth_sign_message_ascii 50ms
eth_sign_message_boundary_1024 43ms
eth_sign_legacy_polygon_multibyte_v 42ms
eth_sign_eip1559_mainnet 41ms
eth_sign_typed_data_kyc_multipage 45ms
eth_sign_typed_data_non_ascii_rejected 1ms
btc_xpub_zpub_mainnet 42ms
btc_address_p2wpkh_mainnet 42ms
btc_address_p2tr_taproot 41ms
btc_sign_message_mainnet 43ms

Summary: 15 total · 15 passed · 0 failed

@TaprootFreak TaprootFreak marked this pull request as draft May 20, 2026 14:59
bitbox_flutter.dart re-exports BitboxManager so the explicit
bitbox_manager.dart import is redundant. flutter analyze (CI version)
flags this as unnecessary_import; locally a slightly older analyzer let
it through.
@TaprootFreak TaprootFreak marked this pull request as ready for review May 20, 2026 15:05
…ender assert

#461 changed SettingsSeedCubit from constructor-arg SoftwareWallet to
async appStore + ensureUnlocked + _loadSeed. Initial state became
SettingsSeedState('') with the seed only arriving after _loadSeed
emitted. The first render of SettingsSeedView feeds that empty string
into MnemonicReadOnlyField, whose constructor asserts
seedWords.length == 12 — debug builds crash the screen on open,
release builds would hit out-of-bounds in elementAt.

Fix: seed the initial state from appStore.wallet when it's already a
SoftwareWallet (the common case — software-wallet users land here from
settings). _loadSeed still runs to cover the view-wallet case and to
preserve the ensureUnlocked() invocation; the redundant emit for
already-loaded software wallets is suppressed.

Test impact:
- initial-state test no longer needs stream.firstWhere — the seed is
  there synchronously; a Duration.zero microtask drain is enough to
  observe the ensureUnlocked() call.
- toggleShowSeed blocTests no longer need to wait for the async load.
@TaprootFreak TaprootFreak merged commit de8df6c into develop May 20, 2026
2 checks passed
@TaprootFreak TaprootFreak deleted the fix/ci-after-pr461 branch May 20, 2026 17:20
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