Skip to content

Golden state coverage: 175 sichtbare UI-Zustände ohne Baseline (43 % State-Coverage) #816

Description

@TaprootFreak

State-/Varianten-Coverage-Audit (2026-07-12, staging @ dd3d3fc)

Page-Ebene ist praktisch komplett (62/63 Pages haben ≥1 Golden). Dieses Issue trackt die Varianten-/State-Ebene: die real sichtbaren UI-Zustände je Page (aus Cubit/Bloc-Code abgeleitet) gegen die vorhandenen Golden-Varianten.

Gesamt: 136/311 sichtbare Zustände abgedeckt (43 %). 175 offen über 44 Pages.

Typ-Verteilung der Lücken

Typ Anzahl
Gefüllter Inhalt / Content-Variante 40
Loading/In-Flight 35
Fehler-Snackbar/Overlay (transient) 32
Overlay/Sheet/Dropdown offen 27
Fehler-/Failure-State 15
Validierungsfehler (inline) 11
Success-State 8
Empty/Leerzustand 7

Umsetzungshinweise

  • Nicht jeder Zustand ist gleich wertvoll: transiente Snackbars und In-Button-Spinner deckt kein Team lückenlos per Golden ab — hier bewusst priorisieren statt stur 100 %. Höchster Wert: gefüllte Content-Varianten, Empty-States, Fehler-Vollbild-Views, Overlays/Sheets (eigenständiges, stabiles Layout).
  • Golden-Muster: pumpBeforeTest/pumpOnce zum Einfrieren von Spinnern (s. bestehende loading-Goldens); Länderdaten via Fixture (test/helper/country_fixture.dart, s. fix(form): render the country dropdown instead of erroring #806/test(country): migrate remaining mocktail country stubs to the fixture #807), NICHT mocktail.
  • Pro Themenblock ein PR; Goldens deterministisch auf dem CI-Runner-äquivalenten Toolchain generieren (Doppellauf-Check).
  • Große Brocken: sell_page/sell_bitbox_page (je 13 Zustände — kompletter mehrstufiger Swap-/Deposit-Flow ungolden), settings_user_data (8), verify_pin (8), kyc_financial_data_questions (7 Fragetyp-Varianten), kyc_registration_page (7 Wizard-/Overlay-Zustände).

Vollständige Fehlliste pro Page

sell_page.dart — 13 offen
  • Bankkonto ausgewählt: IBAN im Dropdown-Feld statt Hint, Sell-Button aktiv (onPressed gesetzt)
    sell_bank_account_field.dart:89-104 (initialValue: selected); sell_button.dart:128-140 (aktiver Button bei bankAccount!=null && amount nicht leer)
  • SellPaymentInfoFailure(unknown/generisch): rote Snackbar mit Fehlermeldung
    sell_button.dart:58-66 (ScaffoldMessenger.showSnackBar mit state.message)
  • SellPaymentInfoFailure(priceSourceUnavailable): Snackbar 'Preisanbieter nicht verfügbar'
    sell_button.dart:47-56
  • SellPaymentInfoFailure(bitboxDisconnected): BitBox-Reconnect-Bottom-Sheet über der Page
    sell_button.dart:34-45 (showBitboxReconnectSheet)
  • Sellable-Currencies-Load-Fehler: rote Snackbar 'settingsCurrencyLoadFailed' + Currency-Picker deaktiviert
    sell_converter.dart:48-68 (Fehlerpfad + Snackbar), sell_converter.dart:243-246 (enabled=false, Key sell-currency-picker-disabled)
  • Currency-Picker-Popup offen: PopupMenu mit sellable Währungen (Code + Name)
    sell_converter.dart:242-277 (PopupMenuButton itemBuilder)
  • SellConfirmSheet (Bottom-Sheet nach PaymentInfo-Success, Software-Wallet): Review-Karte REALU/Betrag/Empfänger-IBAN + Confirm-Button idle
    sell_button.dart:72-78 (showModalBottomSheet); sell_confirm_sheet.dart:53-178
  • SellConfirmSheet: Confirm-Button im Loading-Zustand (SellConfirmLoading)
    sell_confirm_sheet.dart:167-175
  • SellConfirmSheet: SellConfirmFailure → rote Snackbar mit Fehlertext
    sell_confirm_sheet.dart:41-48
  • SellExecutedSheet (Erfolgs-Bottom-Sheet nach bestätigtem Verkauf): Check-Icon, 'sellSuccess'-Texte, Close-Button
    sell_button.dart:79-87; sell_executed_sheet.dart:12-63
  • SellAddBankAccountSheet (Bottom-Sheet bei 0 Konten): Formular IBAN + optionales Label + Next-Button
    sell_bank_account_field.dart:142-150 (Sheet statt Selection-Page bei accounts.isEmpty); sell_add_bank_account_sheet.dart:40-206
  • SellAddBankAccountSheet: Validierungsfehler (IBAN fehlt/ungültig — roter Rahmen + Fehlertext unter dem Feld)
    sell_add_bank_account_sheet.dart:101-111 (error borders), 118-124 (validator ibanRequired/ibanInvalid)
  • SellAddBankAccountSheet: SellBankAccountsAddFailure → rote Snackbar 'Error: …' (Sheet schließt gleichzeitig)
    sell_add_bank_account_sheet.dart:29-38
sell_bitbox_page.dart — 13 offen
  • SellBitboxWaitingForEth: Hourglass-Icon, Headline + Beschreibung, disabled Next-Button
    sell_bitbox_eth_step.dart:29-56
  • SellBitboxEthReady: Check-Icon, 'ETH ready'-Texte, aktiver Next-Button
    sell_bitbox_eth_step.dart:58-85
  • SellBitboxBitboxRequired: leerer Step-Inhalt (EthStep fällt auf SizedBox.shrink) + BitBox-Reconnect-Sheet als Overlay
    sell_bitbox_page.dart:48-54 (Listener zeigt Sheet); sell_bitbox_eth_step.dart:87 (shrink)
  • SellBitboxPreparingSwap (Step 2 aktiv): nur Spinner, Progress-Balken 2/3
    sell_bitbox_swap_step.dart:19-24; sell_bitbox_page.dart:181-186 (stepIndex 1)
  • SellBitboxAwaitingSwapConfirm: Swap-Karte From (REALU) / To (≈ ZCHF) + Beschreibung + Confirm-Button
    sell_bitbox_swap_step.dart:25-71
  • SellBitboxSwapping: Spinner + 'Swapping'-Text
    sell_bitbox_swap_step.dart:72-85
  • SellBitboxAwaitingDepositConfirm (Step 3 aktiv): Deposit-Karte ZCHF-Betrag / truncated Deposit-Adresse + Confirm-Button
    sell_bitbox_deposit_step.dart:18-64, 142-145 (_truncateAddress)
  • SellBitboxDepositing: Spinner + 'Depositing'-Text
    sell_bitbox_deposit_step.dart:65-80
  • SellBitboxRetryingDeposit: gleiches Spinner-Layout, aber 'Retrying'-Text
    sell_bitbox_deposit_step.dart:65-80 (Textauswahl Zeile 71-75)
  • SellBitboxDepositRetry (broadcastTxHash == null): rotes Error-Icon + 'Deposit retry'-Titel/-Beschreibung + Retry-Button
    sell_bitbox_deposit_step.dart:81-110 (confirmOnly=false-Zweig)
  • SellBitboxDepositRetry (broadcastTxHash != null): Confirm-Retry-Textvariante (Deposit ist on-chain, nur Bestätigung offen)
    sell_bitbox_deposit_step.dart:83 (confirmOnly), 89-99 (andere Titel/Beschreibung)
  • SellBitboxError: rote Snackbar mit Fehlertext, Step-Inhalt leer, Progress-Balken springt auf Step 1 zurück
    sell_bitbox_page.dart:55-62 (Snackbar), 120 (SizedBox.shrink), 185 (_ => 0)
  • SellBitboxSuccess: nicht-dismissibles Erfolgs-Bottom-Sheet (Check-Icon, sellSuccess-Texte, Close)
    sell_bitbox_page.dart:63-68, 123-179 (_showSuccessSheet)
verify_pin_page.dart — 8 offen
  • appLock-Variante mit 'PIN vergessen?'-Button unter dem Pad (bottom-Widget statt Spacer)
    verify_pin_page.dart:43-47,228,283-313
  • Failure (rote Dots + Fehlertext pinVerifyFailed, Pad aktiv)
    verify_pin_page.dart:106,157,182; verify_pin_state.dart:74-79
  • Temporarily locked (rote Dots, Countdown-Text pinVerifyLockedTemporarily, Pad deaktiviert)
    verify_pin_page.dart:104,168-173,211; verify_pin_cubit.dart:254-273
  • Permanently locked (rote Dots, Text pinVerifyLocked, Pad deaktiviert)
    verify_pin_page.dart:104,174,211; verify_pin_state.dart:94-99
  • Unverifiable, appLock-Variante (Text pinVerifyUnverifiable + 'PIN vergessen?'-Button)
    verify_pin_page.dart:179-181,228
  • Biometrie-Hint 'notEnrolled' (eigener Hinweistext pinVerifyBiometricHintNotEnrolled)
    verify_pin_page.dart:264; verify_pin_state.dart:29-30
  • Biometrie-Hint 'unavailable' (eigener Hinweistext pinVerifyBiometricHintUnavailable)
    verify_pin_page.dart:265; verify_pin_state.dart:32-34
  • Overlay: ForgotPinBottomSheet (Titel, Beschreibung, Close-/Reset-Buttons)
    verify_pin_page.dart:294-298; forgot_pin_bottom_sheet.dart:12-76
settings_user_data_page.dart — 8 offen
  • Success mit userData + Edit-Buttons (capabilities.canEditName/canEditPhone/canEditAddress=true)
    settings_user_data_page.dart:72-81,96-105,114-123 (onEdit nur bei Capability); IconButton.filledTonal settings_user_data_page.dart:255-259
  • Success mit pendingSteps → Badge 'Change in review' bei Name/Adresse
    settings_user_data_page.dart:69-71,111-113; pendingSteps-Berechnung settings_user_data_cubit.dart:60-65
  • Success ohne birthday (Birthday-Zeile fehlt)
    settings_user_data_page.dart:83-87 (Zeile nur wenn birthday!=null); Parsing '' → null settings_user_data_cubit.dart:75-76
  • Success userData==null, email!=null → nur E-Mail-Zeile
    settings_user_data_page.dart:130-139; emittiert wenn realUnitUserDataDto==null (settings_user_data_cubit.dart:55-58)
  • Success userData==null, email==null → 'No user data is stored for this wallet.' zentriert
    settings_user_data_page.dart:140-142
  • Loading (CupertinoActivityIndicator zentriert)
    settings_user_data_page.dart:143-145; emittiert zu Beginn jedes getUserData (settings_user_data_cubit.dart:42)
  • BitboxDisconnected → Titel/Beschreibung/Reconnect-Button (_BitboxDisconnectedView)
    settings_user_data_page.dart:146-148,161-199; BitboxNotConnectedException settings_user_data_cubit.dart:100-101
  • Failure → 'An error occurred while loading user data.' zentriert
    settings_user_data_page.dart:149-151; settings_user_data_cubit.dart:102-104
kyc_registration_page.dart — 7 offen
  • Address-Step aktiv (AppBar-Titel 'Residence', PageView auf Seite 2)
    kyc_registration_page.dart:150-164,265-273; kyc_registration_step_state.dart:26-27
  • Tax-Step aktiv (AppBar-Titel 'Tax residence', PageView auf Seite 3)
    kyc_registration_page.dart:275-289; kyc_registration_step_state.dart:28-29
  • Vorbefülltes Formular (initialUserData!=null: Name/Telefon/Geburtstag/Adresse gesetzt, Länder nach Lookup aufgelöst)
    kyc_registration_page.dart:106-118,121-143; Routing: kyc_page_manager.dart:70
  • Submit-Loading-Overlay (weißes Vollflächen-Overlay mit CupertinoActivityIndicator über dem PageView)
    kyc_registration_page.dart:230-242 (KycRegistrationSubmitLoading)
  • Fehler-Snackbar bei Submit-Failure (registrationFailed bzw. signingCancelled, roter Hintergrund)
    kyc_registration_page.dart:191-201 (KycRegistrationSubmitFailure)
  • forwardingFailed-Snackbar nach erfolgreichem Submit
    kyc_registration_page.dart:182-189 (Success mit RegistrationStatus.forwardingFailed)
  • Bitbox-Required-BottomSheet (modales ConnectBitboxPage-Sheet über der Registration)
    kyc_registration_page.dart:202-217 (KycRegistrationSubmitBitboxRequired)
kyc_financial_data_questions_page.dart — 7 offen
  • Checkbox-Frage (QuestionType.checkbox): CheckboxListTile statt TextField
    kyc_financial_data_questions_page.dart:149-158 + kyc_question_checkbox_widget.dart:19-28
  • Single-Choice-Frage: RadioGroup mit ListTiles
    kyc_financial_data_questions_page.dart:159-165 + kyc_question_single_choice_widget.dart:18-31
  • Multiple-Choice-Frage: CheckboxListTile-Liste
    kyc_financial_data_questions_page.dart:166-172 + kyc_question_multiple_choice_widget.dart:21
  • Link-Beschreibung (key 'tnc' / 'notification_of_changes'): blau, unterstrichen, tappbar
    kyc_financial_data_questions_page.dart:110-134
  • Frage ohne Beschreibung: Beschreibungszeile entfällt
    kyc_financial_data_questions_page.dart:78-80 (if description != null)
  • Antwort vorhanden (hasAnswer=true): Button enabled
    kyc_financial_data_questions_page.dart:89-91 (onPressed nur bei hasAnswer)
  • nicht-letzte Frage: Button-Label 'Next' statt 'Complete' + Fortschritt 'x/y'
    kyc_financial_data_questions_page.dart:92-94 + 54-60; Default-Golden zeigt wegen 1-Fragen-Fixture nur die 'Complete'-Variante
kyc_nationality_page.dart — 6 offen
  • submit loading (KycNationalityLoading): Next-Button-Spinner
    kyc_nationality_page.dart:81
  • submit failure: roter Snackbar 'setNationalityFailed()'
    kyc_nationality_page.dart:51-57
  • CountryField lädt: Spinner im Feld statt Dropdown
    country_field.dart:58-68 (ConnectionState.waiting → _StatusField mit CupertinoActivityIndicator)
  • CountryField Ladefehler: roter Text 'countriesLoadFailed' + Retry-Button im Feld
    country_field.dart:70-87
  • Dropdown geöffnet (Länderliste als Overlay)
    country_field.dart:102-109 (DropdownField mit DropdownMenuItems); analoges dropdown_open-Golden existiert nur für kyc_registration_address_step
  • Validierungsfehler bei leerer Auswahl: Validator liefert leeren String → nur roter Rahmen, kein Fehlertext
    country_field.dart:108 (validator: value == null ? '' : null)
connect_bitbox_page.dart — 6 offen
  • Default, iOS-Textvariante (connectBitboxContentIos statt connectBitboxContent)
    connect_bitbox_view.dart:188-190 (DeviceInfo.instance.isIOS, device_info.dart:12)
  • BitboxPairing: bitbox_connected.svg, 'Pairing-Code prüfen'-Text + Spinner, KEINE Buttons
    connect_bitbox_view.dart:107-123
  • BitboxNotInitialized: eigener Titel connectBitboxNotInitializedTitle, Hinweistext, Retry- + Cancel-Button
    connect_bitbox_view.dart:124-137; Cubit emittiert bei Firmware-Status 'uninitialized' (connect_bitbox_cubit.dart:190-194)
  • BitboxCapturingSignature: Titel connectBitboxSignatureCapturingTitle + Spinner, keine Buttons
    connect_bitbox_view.dart:138-154; Cubit-Pfad connect_bitbox_cubit.dart:268-283
  • BitboxConnected: Titel 'Verbunden', bitbox_connected.svg, nur Confirm-Button (kein Cancel)
    connect_bitbox_view.dart:171-182
  • Snackbar 'connectBitboxFailed' beim Übergang nach BitboxNotConnected (Verbindungs-/Pairing-Fehler)
    connect_bitbox_view.dart:35-43 (BlocListener); ausgelöst z. B. connect_bitbox_cubit.dart:149,200,257
buy_page.dart — 5 offen
  • Confirm läuft: Kauf-CTA im Loading-Zustand (Spinner im Button, BuyConfirmLoading)
    buy_confirm_button.dart:82 (state: .loading) + app_filled_button.dart:31,66 (_loadingButton mit CupertinoActivityIndicator)
  • Confirm fehlgeschlagen: Snackbar (3 Textvarianten: aktionariat / amountTooLow / unknown)
    buy_confirm_button.dart:64-73 (BuyConfirmFailure → ScaffoldMessenger.showSnackBar); Fehlertypen buy_confirm_state.dart:3
  • Failure bitboxDisconnected: Info-Block "BitBox getrennt" + Reconnect-Button
    payment_information.dart:35-39 + payment_action_button.dart:122-138; Zustand real erreichbar (BitboxNotConnectedException aus dfx_auth_service/bitbox_credentials, gefangen in buy_payment_info_cubit.dart:89-90)
  • Währungs-Picker-Popup offen: PopupMenuButton-Overlay mit buyable-Währungsliste (Code + Name pro Eintrag)
    payment_converter.dart:126-161 (itemBuilder über _buyable)
  • Währungsliste-Ladefehler: rote Snackbar "Currency load failed" + deaktivierter Picker (_loadFailed)
    payment_converter.dart:46-67 (onError → Snackbar mit status.red600) + :127-130 (enabled: false)
kyc_2fa_page.dart — 5 offen
  • verify loading (Kyc2FaVerifyLoading): Next-Button-Spinner
    kyc_2fa_page.dart:136
  • resend loading (Kyc2FaLoading): Resend-Textbutton disabled mit Label 'Sending...'
    kyc_2fa_page.dart:148-156
  • verify failure: roter Snackbar 'twoFaWrongCode: '
    kyc_2fa_page.dart:66-73
  • request-code failure: roter Snackbar 'twoFaSendCodeFailed: '
    kyc_2fa_page.dart:78-87
  • Formular-Validierungsfehler: Fehlertext unter dem Code-Feld (leer / keine Ziffern / !=6 Stellen)
    kyc_2fa_page.dart:116-128 (hideErrorText: false, drei Validator-Meldungen)
settings_security_page.dart — 5 offen
  • Biometrie unterstützt + deaktiviert (Switch AUS)
    settings_security_page.dart:124-125 — Switch rendert value=state.biometricEnabled; bei false visuell distinkter Off-Zustand
  • Biometrie nicht unterstützt (Toggle-Zeile komplett ausgeblendet, nur Change-PIN-Zeile)
    settings_security_page.dart:64 — if (state.biometricSupported) blendet die gesamte SettingOption aus; Default-State des Cubits ist supported=false (settings_security_state.dart:24)
  • isBusy: CupertinoActivityIndicator ersetzt den Switch während Enable/Disable-Roundtrip
    settings_security_page.dart:116-121 (_BiometricTrailing: if isBusy → Spinner); Cubit emittiert isBusy=true in toggleBiometrics (settings_security_cubit.dart:37)
  • Fehler-SnackBar rot 'Biometric unlock failed' (Overlay)
    settings_security_page.dart:50-56 — BlocConsumer.listener bei state.error != null; ausgelöst durch SettingsSecurityError.biometricEnableFailed (settings_security_cubit.dart:49,62)
  • Erfolgs-SnackBar grün 'PIN geändert' nach Rückkehr aus Change-PIN-Flow (Overlay)
    settings_security_page.dart:94-102 — _onPinChanged zeigt SnackBar auf dem ScaffoldMessenger dieser Page nach context.pop()
verify_seed_page.dart — 5 offen
  • Fehler: falsche Wörter (hasError=true) — roter Input-Border + roter Error-Button 'verifySeedInvalid'
    lib/screens/verify_seed/widgets/verify_seed_input_field.dart:44 (border rot bei hasError) + verify_seed_button.dart:21-26 (AppFilledButton state:.error, rot, app_filled_button.dart:123-151)
  • isVerifying: Commit läuft — Loading-Button (halbtransparent blau mit Spinner)
    lib/screens/verify_seed/widgets/verify_seed_button.dart:34-38 + cubit/verify_seed_cubit.dart:94 (emit isVerifying:true vor commitGeneratedWallet)
  • isVerified: Erfolg — grüner Success-Button mit Check-Icon, 2s sichtbar vor Navigation
    lib/screens/verify_seed/widgets/verify_seed_button.dart:27-33 + verify_seed_page.dart:61-77 (Listener wartet 2 Sekunden vor LoadWalletEvent)
  • commitFailed: Persistierung fehlgeschlagen — idle Retry-Button mit Refresh-Icon und Fehler-Label
    lib/screens/verify_seed/widgets/verify_seed_button.dart:40-49 + cubit/verify_seed_cubit.dart:117-129 (catch-Branch emittiert commitFailed:true)
  • wordIndices leer: SizedBox.shrink (leerer Scaffold)
    lib/screens/verify_seed/verify_seed_page.dart:128-129; praktisch unerreichbar, da _initVerification synchron im Cubit-Konstruktor emittiert (verify_seed_cubit.dart:17-18, 28-53)
debug_auth_page.dart — 5 offen
  • signMessage gesetzt: Divider + 'Sign Message'-Label + kopierbare Message-Box (neutral100) + Signaturfeld + Authenticate-FilledButton
    debug_auth_view.dart:66-111
  • errorMessage gesetzt: rote Fehlerbox (red600, 10% Alpha-Hintergrund) unter dem Formular
    debug_auth_view.dart:112-125; emittiert in debug_auth_cubit.dart:25,35
  • isLoading beim Authentifizieren: AppFilledButton im .loading-Zustand (CupertinoActivityIndicator im Button), signMessage-Sektion sichtbar
    debug_auth_view.dart:104-105; app_filled_button.dart:31,66,81
  • isLoading beim Sign-Message-Fetch: 'Sign-Message holen'-TextButton disabled (onPressed null → Theme-Disabled-Färbung)
    debug_auth_view.dart:59-63; app_text_button.dart:21-22 (kein eigener Loading-Look, nur Flutter-Default-Disabled)
  • Snackbar 'in Zwischenablage kopiert' (grüner Hintergrund) nach Tap auf die Message-Box
    debug_auth_view.dart:74-85
dashboard_page.dart — 5 offen
  • Preis + Preischart geladen: realer Preistext statt '--.--', Chart-Kurve mit Gradient und Y-Achsen-Labels, MAX-Periode selektiert
    dashboard_price_widget.dart:82 (price==0 ? '--.--' : formatFixed), price_chart.dart:78-100 (Kurve nur bei visibleSpots), price_chart_cubit.dart:31-118
  • Portfolio-Chart-Header-Variante (portfolioHistory nicht leer): 'Portfolioentwicklung' + aktueller Wert + Perioden-Differenz '+x.xx CHF | +x.xx%' + PortfolioChart ersetzt Preis-Widget
    dashboard_page.dart:112-118, dashboard_portfolio_chart_widget.dart:46-160
  • Pending-Transaktionen-Sektion sichtbar: 'Ausstehende Transaktionen'-Label + weiße Box mit PendingTransactionRows (Spinner-Icon)
    dashboard_pending_transactions.dart:32-57 (nur bei nicht-leerer Liste), eingebunden in beiden Balance-Zweigen dashboard_page.dart:142 und :157
  • Letzte-Transaktionen-Sektion sichtbar: 'Letzte Transaktionen' + bis zu 3 TransactionRows (Buy/Sell-Icon, +/−Betrag) + 'Transaktionsverlauf'-Button
    dashboard_transaction_history.dart:44-81 (SizedBox.shrink bei leerer Liste), Limit 3 in dashboard_transaction_history_cubit.dart:14
  • hideAmounts aktiv: Beträge in Bestand-Box/Transaktionszeilen als '*.' maskiert
    hide_amount_text.dart:38-40 (SettingsState.hideAmounts), genutzt via cash_holding_box.dart:73 und transaction_row.dart:100
transaction_history_page.dart — 5 offen
  • Liste mit Transaktionen: TransactionHistoryRows (Buy '+' vs. Sell '−' Icon/Vorzeichen, Datum, Betrag, Download-Icon je Zeile) + aktiver blauer PDF-Button
    transaction_history_page.dart:98-103, transaction_history_row.dart:64-161, transaction_history_download_button.dart:81-101
  • Beleg-Generierung pro Zeile lädt: 12px-Spinner ersetzt Download-Icon der Zeile (TransactionHistoryReceiptLoading)
    transaction_history_row.dart:135-146, transaction_history_receipt_state.dart:14-16
  • Multi-Beleg-PDF lädt: blauer 44×44-Container mit CircularProgressIndicator ersetzt PDF-Button (TransactionHistoryMultiReceiptLoading)
    transaction_history_download_button.dart:67-80, transaction_history_multi_receipt_state.dart:14-16
  • Fehler-Snackbar (rot) bei Beleg-Generierungsfehler (Einzel- wie Multi-Beleg)
    transaction_history_row.dart:52-59 und transaction_history_download_button.dart:39-46 (SnackBar mit status.red600)
  • Datums-Picker-Dialog (Material showDatePicker) beim Tap auf Anfangs-/Enddatum-Feld
    date_picker_field.dart:67-73 → lib/widgets/date_picker.dart:22 (showDatePicker), eingebunden transaction_history_page.dart:66-92
kyc_link_wallet_page.dart — 4 offen
  • submitting (KycLinkWalletSubmitting): Submit-Button-Spinner, Button disabled
    kyc_link_wallet_page.dart:93-96 + 140-143
  • success (KycLinkWalletSuccess): zentrierter Spinner (transienter Frame vor checkKyc-Navigation)
    kyc_link_wallet_page.dart:107
  • failure (KycLinkWalletFailure): zentrierter Spinner (Fallback-Zweig) + roter Snackbar 'registrationFailed'
    kyc_link_wallet_page.dart:59-66 (Snackbar) + 108 (Failure fällt in den KycLinkWalletState()-Spinner-Zweig)
  • userData==null: defensive Fehlerseite mit kycFailure-Text + Refresh-Button (_LinkWalletMissingUserDataPage)
    kyc_link_wallet_page.dart:28-31 + 180-210
settings_edit_name_page.dart — 4 offen
  • Submitting: identisches Formular, Save-Button mit Lade-Spinner
    settings_edit_name_page.dart:79,136 (state is SettingsEditNameSubmitting → AppFilledButton .loading)
  • Formular mit Validierungsfehlern (leere Felder, Swiss-Payment-Text-Fehler, fehlender Dateinachweis)
    settings_edit_name_page.dart:100-104,111-115,124-129 (Validatoren liefern ''/Fehlertext nach _onSubmit, settings_edit_name_page.dart:157-160)
  • FilePickerField mit ausgewaehlter Datei (Dateiname sichtbar)
    settings_edit_name_page.dart:117-123 (_selectedFile gesetzt nach ImagePickerSheet)
  • Success: gruene SnackBar 'Change submitted successfully' + pop(true)
    settings_edit_name_page.dart:51-61 (BlocConsumer-Listener)
settings_edit_address_page.dart — 4 offen
  • Submitting: Save-Button mit Lade-Spinner
    settings_edit_address_page.dart:84,199
  • Formular mit Validierungsfehlern (Pflichtfelder leer, Swiss-Payment-Text, fehlender Nachweis)
    settings_edit_address_page.dart:113-117,151-155,166-170,187-192; Trigger _onSubmit settings_edit_address_page.dart:220-224
  • CountryField mit gewaehltem Land / FilePickerField mit Datei
    settings_edit_address_page.dart:175-193 (Golden zeigt leeres CountryField und leeren FilePicker)
  • Success: gruene SnackBar + pop(true)
    settings_edit_address_page.dart:56-65
restore_wallet_view.dart — 4 offen
  • complete: 12 gültige BIP39-Wörter eingegeben — okker Border, AKTIVIERTER Next-Button
    lib/screens/restore_wallet/cubit/validate_seed/validate_seed_cubit.dart:13-20 (checkSeedLength emittiert complete) + restore_wallet_button.dart:59-64 (onPressed nur bei complete gesetzt)
  • valid + Restore in-flight (isLoading=true): okker Border + Loading-Button
    lib/screens/restore_wallet/widgets/restore_wallet_input_field.dart:27-30 (valid+isLoading→okker) + restore_wallet_button.dart:49-52 (Loading-Button) + restore_wallet_cubit.dart:21 (emit isLoading:true)
  • valid + Restore erfolgreich (wallet!=null): grüne Border + grüner Success-Button mit Check, 2s sichtbar vor Navigation
    lib/screens/restore_wallet/widgets/restore_wallet_button.dart:31-37 + restore_wallet_view.dart:40-48 (Listener wartet 2 Sekunden vor LoadWalletEvent) + restore_wallet_input_field.dart:27-30 (valid+!isLoading→grün)
  • valid + Restore fehlgeschlagen (hasError=true): grüne Border + idle Retry-Button mit Refresh-Icon 'restoreWalletFailed'
    lib/screens/restore_wallet/widgets/restore_wallet_button.dart:41-48 + cubit/restore_wallet/restore_wallet_cubit.dart:45-57 (catch-Branch, issue #657 P1 B1)
support_chat_page.dart — 4 offen
  • Error (zentrierter roher Fehlermeldungs-Text)
    lib/screens/support/subpages/support_chat_page.dart:57-59
  • Loaded, offenes Ticket: Nachrichtenliste (Kunden-Bubble blau rechts, Support-Bubble grau links mit 'Support'-Label, Zeitstempel) + aktives Eingabefeld mit Send-Icon
    lib/screens/support/subpages/support_chat_page.dart:60-87; widgets/support_chat_message_bubble.dart:15-75; widgets/support_chat_message_input_field.dart:41-77
  • Loaded, offenes Ticket, isSending=true: TextField disabled + CupertinoActivityIndicator statt Send-Icon
    lib/screens/support/widgets/support_chat_message_input_field.dart:55,69-73; SupportChatLoaded.isSending support_chat_state.dart:21
  • Loaded, geschlossenes Ticket: graues 'Ticket geschlossen'-Banner ersetzt das Eingabefeld
    lib/screens/support/widgets/support_chat_message_input_field.dart:22-39 (if !isTicketOpen); support_chat_page.dart:76
support_create_ticket_page.dart — 4 offen
  • Ausgefüllt: Typ-Tag selektiert (hervorgehoben) + Nachricht vorhanden → Send-Button enabled
    lib/screens/support/subpages/support_create_ticket_page.dart:102-103 (selected), :147-149 (canSubmit → onPressed)
  • isSubmitting: Send-Button im Loading-Zustand (Spinner)
    lib/screens/support/subpages/support_create_ticket_page.dart:146 (state.isSubmitting → .loading)
  • Success-Snackbar (grün, 'Ticket erstellt') beim Pop zurück
    lib/screens/support/subpages/support_create_ticket_page.dart:39-47 (listener, RealUnitColors.green, danach context.pop)
  • Error-Snackbar (rot, roher Fehlertext), Formular bleibt sichtbar
    lib/screens/support/subpages/support_create_ticket_page.dart:48-55 (status.red600)
buy_payment_details_page.dart — 3 offen
  • Mit QR verfügbar, Tab "Details" aktiv: TabSelector-Zeile (Details/QR-Code) über der Karte sichtbar
    payment_details_card.dart:45-64 (if (hasQrCode) TabSelector)
  • Mit QR, Tab "QR-Code" gewählt: QR-Rendering statt Detail-Liste (2 Untervarianten: SVG-String via SvgPicture vs. QrImageView)
    payment_details_card.dart:119-136 (switch auf PaymentInfoOptions.qrCode, Verzweigung paymentRequest.contains('<svg'))
  • Zahlungszweck-Zeile ausgeblendet (purposeOfPayment leer)
    payment_details_card.dart:82-86 (if (purposeOfPayment.isNotEmpty))
sell_bank_account_selection_page.dart — 3 offen
  • Liste mit aktiven Konten: brand200-Karten mit Label (bzw. 'ohne Label'), formatierter IBAN und Delete-IconButton
    sell_bank_account_selection_page.dart:74-90; sell_bank_account_list_item.dart:22-81 (isActive-Zweig)
  • Deaktiviertes Konto in der Liste: graue neutral200-Karte, Text 'deactivated', abgedunkelte IBAN, Delete-Button unsichtbar (Platz erhalten)
    sell_bank_account_list_item.dart:21-27 (Farbe/onTap), 42-48 ('deactivated'-Label), 60-64 (Visibility visible:false, maintainSize)
  • SellAddBankAccountSheet-Overlay (auch von dieser Page via 'Konto hinzufügen' erreichbar)
    sell_bank_account_selection_page.dart:108-119
kyc_email_page.dart — 3 offen
  • Fehler-Snackbar 'E-Mail stimmt nicht überein' (emailDoesNotMatch, roter Hintergrund)
    kyc_email_page.dart:60-69; kyc_email_step_state.dart:27-37
  • Fehler-Snackbar unbekannter Fehler (KycEmailStepError.unknown, Backend-Message)
    kyc_email_page.dart:60-69
  • Inline-Validierungsfehler unter dem E-Mail-Feld (leer → registerEmailRequired, ungültig → registerEmailInvalid; hideErrorText:false → sichtbarer Fehlertext)
    kyc_email_page.dart:108-117
kyc_email_verification_page.dart — 3 offen
  • Loading — Button im Spinner-Zustand (Software-Wallet, ohne Bitbox-Hinweis)
    kyc_email_verification_page.dart:81,91-97 (KycEmailVerificationLoading → .loading)
  • Loading mit Bitbox-Hinweistext (isLoading && isBitbox → zusätzlicher Sign-Hint unter dem Button)
    kyc_email_verification_page.dart:82-87,98-105
  • Fehler-Snackbar 'Verifikation fehlgeschlagen' (roter Hintergrund)
    kyc_email_verification_page.dart:35-42 (KycEmailVerificationFailure)
kyc_ident_page.dart — 3 offen
  • loading (KycIdentLoading): Next-Button im Spinner-Zustand
    kyc_ident_page.dart:122 (state is KycIdentLoading ? .loading : .idle)
  • failure finallyRejected: Next-Button dauerhaft disabled + roter Snackbar 'identityCheckFinallyFailed'
    kyc_ident_page.dart:113-119 (disabled Button) + kyc_ident_page.dart:47-56 (Snackbar)
  • failure error/sonstige: roter Snackbar-Overlay mit Fehlermeldung, Body wie idle
    kyc_ident_page.dart:57-75 (zwei Snackbar-Varianten: mit errorMessage / generisch)
settings_edit_phone_number_page.dart — 3 offen
  • Submitting: Save-Button mit Lade-Spinner
    settings_edit_phone_number_page.dart:54,86
  • Failure: roter Inline-Fehlertext unter dem Telefonfeld
    settings_edit_phone_number_page.dart:74-80 (state is SettingsEditPhoneNumberFailure → Text in error-Farbe); settings_edit_phone_number_cubit.dart:19-20
  • Success: gruene SnackBar + pop(true)
    settings_edit_phone_number_page.dart:42-51
support_tickets_page.dart — 3 offen
  • Loading (zentrierter CupertinoActivityIndicator)
    lib/screens/support/subpages/support_tickets_page.dart:40-42
  • Error (zentrierter roher Fehlermeldungs-Text)
    lib/screens/support/subpages/support_tickets_page.dart:43-45; SupportTicketsError support_tickets_state.dart:28-35
  • Loaded mit Tickets (OutlinedTile-Liste: grüner Punkt=offen / grauer Punkt=geschlossen, Name, Datum, Chevron)
    lib/screens/support/subpages/support_tickets_page.dart:49-79 (Status-Punkt :63-65)
support_email_capture_page.dart — 3 offen
  • Inline-Validierungsfehler unter dem E-Mail-Feld (leer → 'erforderlich', ungültig → 'ungültig'; hideErrorText:false)
    lib/screens/support/subpages/support_email_capture_page.dart:110-119,129 (validate() im onPressed)
  • Failure-Snackbar (rot; 2 Textvarianten: mergeRequested-Spezialtext vs. generische Fehlermeldung)
    lib/screens/support/subpages/support_email_capture_page.dart:75-85; SupportEmailCaptureError support_email_capture_state.dart:22-35
  • Parameter-Variante: Buy-Flow-Einstieg mit abweichendem Beschreibungstext (description-Extra)
    lib/screens/support/subpages/support_email_capture_page.dart:14-18,101; Aufrufer lib/screens/buy/widgets/payment_action_button.dart:107-110 (buyPrimaryEmailRequiredCaptureDescription); Route lib/setup/routing/router_config.dart:323
kyc_registration_personal_step.dart — 2 offen
  • Validierungsfehler nach 'Next' mit leeren/ungültigen Feldern (rote Error-Borders; Fehlertext via hideErrorText=true unterdrückt, bei swissPaymentTextInvalid ohne sichtbaren Text)
    kyc_registration_personal_step.dart:73-77,87-91,111-115; labeled_text_field.dart:65-80 (errorBorder rot, errorStyle fontSize 0)
  • Weitere Dropdown-Overlays offen (Accounttyp, Geburtstag Tag/Monat/Jahr, Telefon-Prefix)
    kyc_registration_personal_step.dart:50-61,96-101; birthday_field.dart:85-127; phone_number_field.dart:16-17
kyc_financial_data_page.dart — 2 offen
  • submit failure (KycFinancialDataSubmitFailure): Questions-Page bleibt stehen + roter Snackbar-Overlay mit Fehlermeldung
    kyc_financial_data_page.dart:43-58 (SubmitFailure ist LoadedSuccess-Subtyp, Snackbar via Listener)
  • initial / submit success: leeres Scaffold (Fallback-Zweig)
    kyc_financial_data_page.dart:66 ((_) => const Scaffold())
settings_page.dart — 2 offen
  • Release-Build-Variante: Network-Tile ausgeblendet (das, was Prod-User real sehen)
    settings_page.dart:57 (if (kDebugMode))
  • Overlay: Wallet-Logout-Bottom-Sheet, Checkbox angehakt (grüne Checkbox, Reset-Button enabled)
    settings_confirm_logout_wallet_sheet.dart:84-93 (activeColor green, value isChecked), :120-125 (Reset enabled nur bei isChecked)
settings_currencies_page.dart — 2 offen
  • Loading: zentrierter CupertinoActivityIndicator
    settings_currencies_page.dart:61-63 (if (!snapshot.hasData))
  • Fehler: _ErrorView mit Icon, Titel, Beschreibung und Retry-Button
    settings_currencies_page.dart:46-60 (snapshot.hasError → _ErrorView, Key 'settings-currencies-error'), :96-142 (_ErrorView-Layout)
settings_languages_page.dart — 2 offen
  • Loading: zentrierter CupertinoActivityIndicator
    settings_languages_page.dart:57-58 (if (!snapshot.hasData))
  • Fehler: _LanguageErrorView mit Icon, Titel, Beschreibung und Retry-Button
    settings_languages_page.dart:42-55 (snapshot.hasError → _LanguageErrorView, Key 'settings-languages-error'), :91-137 (Layout)
setup_pin_page.dart — 2 offen
  • Confirm-Modus mit Mismatch (rote Dots + Fehlertext pinConfirmFailed)
    setup_pin_page.dart:135-151 (wrongPin: state.mismatch, Visibility bei mismatch); setup_pin_cubit.dart:72-79
  • Confirm-Modus mit storeFailed (Fehlertext pinSaveFailed nach Hash-/Keychain-Fehler)
    setup_pin_page.dart:137-145; setup_pin_cubit.dart:94-99
settings_tax_report_page.dart — 2 offen
  • Failure: rote SnackBar mit Fehlermeldung (Overlay)
    settings_tax_report_page.dart:38-45 — BlocListener zeigt SnackBar bei SettingsTaxReportFailure
  • Datums-Picker-Overlay (Material-Dialog auf Android/sonst, Cupertino-Modal-Sheet auf iOS)
    settings_tax_report_page.dart:69-78 (DatePickerField) + date_picker_field.dart:67-76 + date_picker.dart:13-28 (Plattform-Weiche via DeviceInfo.isIOS)
web_view_page.dart — 2 offen
  • Default: transparente AppBar mit Back-Pfeil + Titel, InAppWebView-Body
    web_view_page.dart:30-61; Route /webView (router_config.dart:348-350)
  • showExternalBrowserButton=true: zusätzliches open_in_new-Icon rechts in der AppBar
    web_view_page.dart:48-58; real genutzt in legal_document_page.dart:133
legal_document_page.dart — 2 offen
  • Markdown geladen MIT PDF-Footer-Button ('Original-PDF', secondary Button unten)
    lib/screens/legal/subpages/legal_document_page.dart:121-140; real erreichbar über Registrierungsvereinbarung (lib/packages/config/legal_documents_config.dart:82-87 setzt pdfUrls)
  • Lade-Fehler-View (error_outline-Icon, Titel, Beschreibung, Retry-Button)
    lib/screens/legal/subpages/legal_document_page.dart:98,150-184 (_loadFailed → _buildError)
kyc_registration_address_step.dart — 1 offen
  • Validierungsfehler nach 'Next' mit leeren/ungültigen Feldern (rote Error-Borders auf allen Textfeldern + Country-Dropdown)
    kyc_registration_address_step.dart:55-59,68-72,93-97,108-112,126-131; country_field.dart:108
settings_network_page.dart — 1 offen
  • Umschalten läuft: getappter Modus zeigt kleinen CircularProgressIndicator statt Check
    settings_network_page.dart:36-44 (isLoading → SizedBox 14x14 mit CircularProgressIndicator), :52-56 (setLoading beim Tap, loadingFinished via BlocConsumer-Listener :24)
settings_seed_page.dart — 1 offen
  • Seed lädt: CupertinoActivityIndicator statt Seed-Karte (View-Wallet noch nicht entsperrt, wordCount != 12)
    settings_seed_view.dart:97-99 — Spinner solange seed nicht 12 Wörter hat; Cubit startet mit leerem Seed bei SoftwareViewWallet (settings_seed_cubit.dart:23-26), laut Kommentar der Default-Produktionszustand nach #461
create_wallet_view.dart — 1 offen
  • Loading: Seed-Generierung läuft (wallet==null), zentrierter CupertinoActivityIndicator
    lib/screens/create_wallet/create_wallet_view.dart:94-96 (Fallback-Branch wenn state.wallet==null); real sichtbar beim Öffnen und nach jedem App-hidden-Zyklus (create_wallet_cubit.dart:68-83 _dropMnemonic + Re-Generate)
bitbox_address_recovery_page.dart — 1 offen
  • BitboxPairing / BitboxNotInitialized / BitboxCapturingSignature / BitboxConnected (geteilte View)
    connect_bitbox_view.dart:107-182
receive_page.dart — 1 offen
  • Vollseiten-Variante (isBottomSheet=false, die tatsächlich geroutete): AppBar mit Zurück-Pfeil, keine Handlebars, kein Top-Spacing
    receive_page.dart:19-28 (AppBar-Zweig), lib/setup/routing/router_config.dart:210 (Route '/receive' baut ReceivePage(isBottomSheet: false))

Ergänzt #547 (dort ging es um Pages ohne jedes Golden — jetzt erledigt bis auf web_view); dieses Issue ist die feinere State-Ebene. Audit-Methode: 12 parallele Bereichs-Agenten, read-only, Zustände mit datei:zeile-Beleg.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions