diff --git a/.github/workflows/handbook-build-check.yaml b/.github/workflows/handbook-build-check.yaml
index f0db79181..89c0547d7 100644
--- a/.github/workflows/handbook-build-check.yaml
+++ b/.github/workflows/handbook-build-check.yaml
@@ -96,8 +96,8 @@ jobs:
set -euo pipefail
bash scripts/assemble-handbook-screenshots.sh /tmp/handbook-shots
count=$(ls -1 /tmp/handbook-shots/*.png | wc -l | tr -d ' ')
- if [ "$count" != "299" ]; then
- echo "expected 299 screenshots, got $count" >&2
+ if [ "$count" != "301" ]; then
+ echo "expected 301 screenshots, got $count" >&2
exit 1
fi
@@ -177,10 +177,10 @@ jobs:
exit 1
fi
- # Spot-check handbook screenshots assembled from Goldens (299 PNGs).
+ # Spot-check handbook screenshots assembled from Goldens (301 PNGs).
# Mix of original 01-61 slots, later Golden batches, and referral
# baselines so a regression in any range surfaces here.
- for name in 01-welcome 11-dashboard 26-terms 35-dashboard-with-balance 46-buy-kyc-required 52-sell-unknown-error 53-buy-payment-details 61-kyc-registration-tax-tin-error 62-welcome-page-android 219-settings-security-page-default 268-phone-number-field-default 269-dashboard-insider-unlocked 270-handbook-persona-dca 275-handbook-persona-exit-1j 276-referral-overview 282-referral-payout-row 283-referral-terms-readonly 287-kyc-registration-referral-recognized 288-transaction-history-referral-payout 289-dashboard-referral-entry-and-payout 290-kyc-registration-referral-promo; do
+ for name in 01-welcome 11-dashboard 26-terms 35-dashboard-with-balance 46-buy-kyc-required 52-sell-unknown-error 53-buy-payment-details 61-kyc-registration-tax-tin-error 62-welcome-page-android 219-settings-security-page-default 268-phone-number-field-default 269-dashboard-insider-unlocked 270-handbook-persona-dca 275-handbook-persona-exit-1j 276-referral-overview 282-referral-payout-row 283-referral-terms-readonly 287-kyc-registration-referral-recognized 288-transaction-history-referral-payout 289-dashboard-referral-entry-and-payout 290-kyc-registration-referral-promo 291-referral-bind-error-invalid 292-referral-bind-error-already-registered; do
# Auth is checked before the file exists: a missing PNG also
# returns 401, so HTTP status cannot prove assembly. Look on disk.
if ! docker exec handbook test -f "/usr/share/nginx/html/screenshots/${name}.png"; then
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 6fd25f0c7..58765c8ca 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -248,7 +248,7 @@ The app supports three wallet modes (`software`, `bitbox`, `debug`) with differe
```bash
rg "^//\s*@no-integration-test:" lib/
```
-- Visual-regression Goldens under `test/goldens/screens/` and `test/goldens/widgets/` are also the source of the 299 screenshots served at `handbook.realunit.app`. When you add a handbook page, you MUST add a matching Golden test AND a row in the mapping table at `scripts/assemble-handbook-screenshots.sh` — the handbook will not pick up a Maestro-captured PNG anymore. The `Handbook Build Check` workflow on every PR runs the assembly script and fails loudly if a mapped Golden is missing.
+- Visual-regression Goldens under `test/goldens/screens/` and `test/goldens/widgets/` are also the source of the 301 screenshots served at `handbook.realunit.app`. When you add a handbook page, you MUST add a matching Golden test AND a row in the mapping table at `scripts/assemble-handbook-screenshots.sh` — the handbook will not pick up a Maestro-captured PNG anymore. The `Handbook Build Check` workflow on every PR runs the assembly script and fails loudly if a mapped Golden is missing.
- Why: single source of truth — a UI regression that breaks a Golden also breaks the handbook image before either ships; eliminates the previous "two pipelines, two truths" problem.
- See: [`docs/visual-regression-tests.md`](docs/visual-regression-tests.md) section "Handbook screenshots are sourced from Goldens".
diff --git a/assets/languages/strings_de.arb b/assets/languages/strings_de.arb
index 0ece64c72..36da5d176 100644
--- a/assets/languages/strings_de.arb
+++ b/assets/languages/strings_de.arb
@@ -268,45 +268,48 @@
"receiver": "Empfänger",
"recoveryWords": "Wiederherstellungs-Wörter",
"recoveryWordsInvalid": "Wiederherstellungs-Wörter ungültig",
- "referralAlreadyBound": "Du hast bereits einen Einladungs- oder Promo-Code eingelöst.",
- "referralAlreadyRegistered": "Diese Einladung gilt nur für neue Kundinnen und Kunden.",
+ "referralAlreadyBound": "Sie haben bereits einen Einladungs- oder Promo-Code eingelöst.",
+ "referralAlreadyBoundTitle": "Bereits ein Code eingelöst",
+ "referralAlreadyRegistered": "Einladungs- und Promo-Codes müssen vor dem ersten REALU-Kauf eingelöst werden.",
+ "referralAlreadyRegisteredTitle": "Nur für neue Kundinnen und Kunden",
"referralChfAtSharePrice": "≈ ${chf} zum ${label}",
"referralCodeChecking": "Code wird geprüft…",
- "referralCodeDescription": "Optional. Über den Einladungslink wird der Code automatisch übernommen; hier kannst du ihn auch manuell eingeben.",
- "referralCodeHeading": "Hast du einen Empfehlungscode?",
+ "referralCodeDescription": "Optional. Über den Einladungslink wird der Code automatisch übernommen; hier können Sie ihn auch manuell eingeben.",
+ "referralCodeHeading": "Haben Sie einen Empfehlungscode?",
"referralCodeHint": "Einladungs- oder Promo-Code",
"referralCodeInvalid": "Dieser Code ist ungültig oder abgelaufen.",
"referralCodeInvalidTitle": "Link ungültig oder abgelaufen",
"referralCodeOptional": "Einladungs- oder Promo-Code (optional)",
"referralCodeSpent": "Dieser Einladungs- oder Promo-Code wurde bereits verwendet.",
"referralCodeSpentTitle": "Code bereits eingelöst",
- "referralCodeUnavailable": "Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.",
+ "referralCodeUnavailable": "Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.",
"referralCopied": "Kopiert",
"referralCopyInviteLink": "Einladungslink kopieren",
"referralCreateInvite": "Einladungslink erstellen",
- "referralCreateInviteDescription": "Gib den Vornamen der Person ein, die du einladen möchtest.",
+ "referralCreateInviteDescription": "Geben Sie den Vornamen der Person ein, die Sie einladen möchten.",
"referralCreating": "Einladung wird erstellt…",
"referralGuestName": "Name der eingeladenen Person",
"referralGuestNameRequired": "Bitte den Vornamen der eingeladenen Person eingeben.",
- "referralInviteRecognized": "Einladung von ${inviter} erkannt. ${inviter} erhält seine Prämie automatisch, sobald du verifiziert bist und deinen ersten Kauf abgeschlossen hast.",
+ "referralInviteRecognized": "Einladung von ${inviter} erkannt. ${inviter} erhält seine Prämie automatisch, sobald Sie verifiziert sind und Ihren ersten Kauf abgeschlossen haben.",
"referralInvitesLoading": "Offene Einladungen werden geladen…",
"referralInviteUrlLabel": "Persönlicher Einladungslink",
"referralLoading": "Empfehlungen werden geladen…",
"referralNotEligible": "Das Empfehlungsprogramm steht verifizierten Aktionären mit dem erforderlichen Bestand zur Verfügung.",
"referralOpenInvitesExpire": "Offene Einladungen verfallen nach 3 Monaten.",
"referralOverviewHint": "20 REALU pro Weiterempfehlung, sobald der erste Kauf erfolgreich abgewickelt ist.",
- "referralOverviewTitle": "Deine Empfehlungen",
+ "referralOverviewTitle": "Ihre Empfehlungen",
"referralPayout": "Empfehlungsprämie",
"referralPayoutChf": "CHF ${chf} zum Zeitpunkt der Gutschrift",
"referralPromoTitle": "Aktion",
"referralQuarterCap": "In diesem Quartal sind keine weiteren Prämien möglich.",
"referrals": "Empfehlungen",
- "referralSelfReferral": "Du kannst deine eigene Einladung nicht einlösen.",
+ "referralSelfReferral": "Sie können Ihre eigene Einladung nicht einlösen.",
+ "referralSelfReferralTitle": "Eigene Einladung",
"referralShareInviteLink": "Einladungslink versenden",
"referralSharePrice": "Aktienkurs",
"referralShareText": "Hey ${guestName}, ${hostName} lädt dich ein zu RealUnit: ${url}",
"referralShareTextNoName": "${hostName} lädt dich ein zu RealUnit: ${url}",
- "referralsSubtitle": "Erhalte 20 REALU pro Weiterempfehlung",
+ "referralsSubtitle": "Erhalten Sie 20 REALU pro Weiterempfehlung",
"referralStatusCredited": "Gutgeschrieben",
"referralStatusOpen": "Offen",
"referralTermsAccepting": "Teilnahmebedingungen werden akzeptiert…",
@@ -315,8 +318,8 @@
"referralTermsRequired": "Bitte zuerst die Teilnahmebedingungen akzeptieren.",
"referralTermsTitle": "Teilnahmebedingungen Referral-Programm",
"referralTotalReceived": "Insgesamt erhalten",
- "referralYourInvite": "Deine Einladung",
- "referralYourInviteFor": "Deine Einladung für ${guestName}",
+ "referralYourInvite": "Ihre Einladung",
+ "referralYourInviteFor": "Ihre Einladung für ${guestName}",
"refresh": "Aktualisieren",
"registerAccountType": "Kontotyp",
"registerCitizenship": "Staatsangehörigkeit",
diff --git a/assets/languages/strings_en.arb b/assets/languages/strings_en.arb
index 9e75b8cda..4d5578e31 100644
--- a/assets/languages/strings_en.arb
+++ b/assets/languages/strings_en.arb
@@ -269,7 +269,9 @@
"recoveryWords": "recovery words",
"recoveryWordsInvalid": "Recovery words invalid",
"referralAlreadyBound": "You have already applied an invite or promo code.",
- "referralAlreadyRegistered": "This invitation is only for new customers.",
+ "referralAlreadyBoundTitle": "Code already applied",
+ "referralAlreadyRegistered": "Invite and promo codes must be applied before the first REALU purchase.",
+ "referralAlreadyRegisteredTitle": "Only for new customers",
"referralChfAtSharePrice": "≈ ${chf} at ${label}",
"referralCodeChecking": "Checking code…",
"referralCodeDescription": "Optional. The invite link fills this automatically; you can also enter the code here.",
@@ -302,6 +304,7 @@
"referralQuarterCap": "No further prizes can be credited this quarter.",
"referrals": "Referrals",
"referralSelfReferral": "You cannot apply your own invitation.",
+ "referralSelfReferralTitle": "Your own invitation",
"referralShareInviteLink": "Share invite link",
"referralSharePrice": "Share price",
"referralShareText": "Hey ${guestName}, ${hostName} is inviting you to RealUnit: ${url}",
diff --git a/docs/handbook/README.md b/docs/handbook/README.md
index fd77e22d8..2bc7b928b 100644
--- a/docs/handbook/README.md
+++ b/docs/handbook/README.md
@@ -21,7 +21,7 @@ deployten Image (`handbook.realunit.app`).
## Screenshots regenerieren
-Es gibt keinen separaten Regeneration-Schritt: Die 299 Handbook-Screenshots
+Es gibt keinen separaten Regeneration-Schritt: Die 301 Handbook-Screenshots
sind direkt die Golden-Baselines unter `test/goldens/` (gemappt in
`scripts/assemble-handbook-screenshots.sh`). Eine UI-Änderung an einer der
gemappten Pages produziert beim `flutter test test/goldens` einen Diff —
diff --git a/docs/handbook/de/index.html b/docs/handbook/de/index.html
index eab666c43..5b3d12c18 100644
--- a/docs/handbook/de/index.html
+++ b/docs/handbook/de/index.html
@@ -1186,14 +1186,14 @@
RealUnit Wallet — Handbook
📱 App: RealUnit Wallet (Flutter)
📂 Code:
RealUnitCH/app
- 🧪 Tests: 350 Visual-Regression Goldens (299 davon im Handbook) · 26 Tier-3 Smoke-Flows
+ 🧪 Tests: 355 Visual-Regression Goldens (301 davon im Handbook) · 26 Tier-3 Smoke-Flows
Single Source of Truth
- Die 299 App-Screenshots dieser Seite sind Goldens aus
+ Die 301 App-Screenshots dieser Seite sind Goldens aus
test/goldens/{screens,widgets}/<feature>/goldens/macos/<file>.png.
Welcher Golden welcher Handbook-Slot ist, definiert die Mapping-Tabelle in
scripts/assemble-handbook-screenshots.sh. Der Docker-Build
@@ -1233,7 +1233,7 @@
Single Source of Truth
Pipeline: Page-Edit → flutter test --update-goldens test/goldens/
auf dem self-hosted Runner (Hardware-Determinismus) → neue Baseline committen →
handbook-deploy.yaml baut das Docker-Image aus dem gepushten Branch
- und assembliert die 299 Slots aus test/goldens/ → Push auf
+ und assembliert die 301 Slots aus test/goldens/ → Push auf
staging deployt das Handbook-Image nach Produktion, via
Cloudflare Tunnel.
@@ -11025,7 +11025,7 @@ REmpfehlungen & Promo-Code
Verifizierte Aktionäre mit mindestens 70 REALU im Wallet (geprüft bei
der Einladung und bei der Qualifikation) sehen auf dem Dashboard
- die Karte Empfehlungen («Erhalte 20 REALU pro Weiterempfehlung»)
+ die Karte Empfehlungen («Erhalten Sie 20 REALU pro Weiterempfehlung»)
und denselben Einstieg in den Einstellungen. Sichtbarkeit, Mindestbestand
und Auszahlung entscheidet die DFX API; die App rendert
eligible 1:1. Die Prämie von 20 REALU wird dem Empfehler
@@ -11100,10 +11100,14 @@
REmpfehlungen & Promo-Code
Deeplink-Stash stehen. Ein abgelehnter Bind (4xx) zeigt einmal einen
Dialog: Titel Code bereits eingelöst mit Body Dieser Einladungs- oder
Promo-Code wurde bereits verwendet. (Einlösungslimit erreicht);
- Titel Link ungültig oder abgelaufen für die übrigen Fälle
- Du hast bereits einen Einladungs- oder Promo-Code eingelöst.
- (ein Code pro Konto) oder Diese Einladung gilt nur für neue Kundinnen
- und Kunden. (Eingabe nur vor dem ersten REALU-Kauf).
+ Titel Bereits ein Code eingelöst mit Body
+ Sie haben bereits einen Einladungs- oder Promo-Code eingelöst.
+ (ein Code pro Konto); Titel Nur für neue Kundinnen und Kunden
+ mit Body Einladungs- und Promo-Codes müssen vor dem ersten
+ REALU-Kauf eingelöst werden. (Eingabe nur vor dem ersten Kauf);
+ Titel Eigene Einladung bei Selbst-Einlösung;
+ Titel Link ungültig oder abgelaufen nur für unbekannte oder
+ abgelaufene Codes.
Promo-Codes legt RealUnit unter app.dfx.swiss/realunit an: je Code
ein Gültigkeitsfenster, ein Mindestkauf (Default 200 REALU) und ein
Einlösungslimit als Anzahl Einlösungen (Pflichtfeld, ganze Zahl ab 1,
@@ -11187,7 +11191,8 @@ REmpfehlungen & Promo-Code
TB nach Annahme (`283`), Namenseingabe (`284`), Einstellungen-Karte
(`285`), Rechtliche Dokumente letzter Eintrag (`286`), Einladung
erkannt (`287`), Historie mit Prämie (`288`), Dashboard-Einstieg
- (`289`), Promo-Aktionstext (`290`).
+ (`289`), Promo-Aktionstext (`290`), Bind-Overlay ungültig (`291`),
+ Bind-Overlay nur für neue Kundinnen (`292`).
@@ -11238,7 +11243,7 @@
REmpfehlungen & Promo-Code
/>
- Karte Empfehlungen mit «Erhalte 20 REALU pro Weiterempfehlung»,
+ Karte Empfehlungen mit «Erhalten Sie 20 REALU pro Weiterempfehlung»,
nur wenn die API eligible setzt.
@@ -11359,7 +11364,7 @@ REmpfehlungen & Promo-Code
Einstieg «Empfehlungen» in den Einstellungen, nur wenn die API
- eligible setzt. Kartentext «Erhalte 20 REALU pro
+ eligible setzt. Kartentext «Erhalten Sie 20 REALU pro
Weiterempfehlung».
@@ -11412,8 +11417,6 @@ REmpfehlungen & Promo-Code
Historie: Prämie mit ganzer Anzahl (20 REALU), Datum und
Frankenwert, fixiert im Zeitpunkt der Gutschrift (TB Ziff. 6).
- Im Golden liegt die Prämie ausserhalb des angezeigten Datumsfilters
- (Testdaten).
@@ -11429,7 +11432,7 @@
REmpfehlungen & Promo-Code
/>
- Einstieg «Empfehlungen» («Erhalte 20 REALU pro
+ Einstieg «Empfehlungen» («Erhalten Sie 20 REALU pro
Weiterempfehlung») und Prämie in den letzten Transaktionen.
@@ -11450,6 +11453,46 @@ REmpfehlungen & Promo-Code
Aktionstext in einem eigenen Fenster (Schließen oder Tippen daneben).
+
+
+
+

+
+
+ Nach einem Bind-4xx für unbekannten oder abgelaufenen Code:
+ Overlay auf dem Dashboard, Titel Link ungültig oder abgelaufen,
+ Body Dieser Code ist ungültig oder abgelaufen.,
+ Schließen mit Tastaturfokus, nicht per Barrier schliessbar.
+ API-Codes EXPIRED / NOT_FOUND.
+
+
+
+
+
+

+
+
+ Nach einem Bind-4xx, weil das Konto schon einen REALU-Kauf hat:
+ derselbe Overlay, Titel Nur für neue Kundinnen und Kunden,
+ Body Einladungs- und Promo-Codes müssen vor dem ersten REALU-Kauf
+ eingelöst werden. — nicht «Link ungültig».
+ API-Code ALREADY_REGISTERED.
+
+
diff --git a/docs/referral-programme.md b/docs/referral-programme.md
index b554e305b..0c3447533 100644
--- a/docs/referral-programme.md
+++ b/docs/referral-programme.md
@@ -293,7 +293,7 @@ row.
tile is one name (REALU, CHF at the current share price, Aktienkurs).
Open invites show the personalised share text (API copyText 1:1,
otherwise the localised template) and can be copied and shared again,
- including when the guest name is blank («Deine Einladung», share text
+ including when the guest name is blank («Ihre Einladung», share text
without «Hey ,»);
credited names stay hidden. Copy and share behave as after create.
With no open-invite rows and no list error, Create is keyboard-focused.
@@ -429,8 +429,12 @@ row.
Close is keyboard-focused. The boot and deeplink bind dialogs stay modal.
A 4xx bind (stacking, self-referral,
spent) shows the matching copy once (spent: «Code bereits eingelöst»;
- self-referral / already-bound / already-registered have their own
- sentence; unknown/expired stay «Link ungültig oder abgelaufen»). Close
+ already-registered: «Nur für neue Kundinnen und Kunden»;
+ already-bound: «Bereits ein Code eingelöst»;
+ self-referral: «Eigene Einladung»;
+ unknown/expired stay «Link ungültig oder abgelaufen»).
+ Handbook slots `291` (expired/unknown) and `292` (already-registered)
+ are the dashboard overlay goldens. Close
is focused, not barrier-dismissible.
If the navigator is not attached yet (dashboard boot bind), the promo,
invalid, or unavailable dialog is shown on the next frame instead of
diff --git a/docs/screens.md b/docs/screens.md
index 01640199f..2f5adea2d 100644
--- a/docs/screens.md
+++ b/docs/screens.md
@@ -48,7 +48,7 @@ Column meaning:
| PIN & lock | `VerifyPinPage` | `pinGate` | `/pinGate` | `17`, `76`, `77`, `78`, `79`, `80`, `81`, `82`, `83`, `84`, `85`, `88` |
| PIN & lock | `SetupPinPage` | `setupPin` | `/setupPin` | `08`, `09`, `10`, `73`, `74`, `75` |
| PIN & lock | `VerifyPinPage` | `verifyPin` | `/verifyPin` | `86`, `87` |
-| Dashboard & trading | `DashboardPage` | `dashboard` | `/dashboard` | `35`, `89`, `90`, `91`, `92`, `93`, `94`, `289` |
+| Dashboard & trading | `DashboardPage` | `dashboard` | `/dashboard` | `35`, `89`, `90`, `91`, `92`, `93`, `94`, `289`, `291`, `292` |
| Dashboard & trading | `TransactionHistoryPage` | `transactionHistory` | `/dashboard/transactionHistory` | `36`, `95`, `96`, `97`, `98`, `99`, `100`, `288` |
| Dashboard & trading | `BuyPage` | `buy` | `/buy` | `44`, `45`, `46`, `47`, `48`, `103`, `104`, `105`, `106`, `107`, `108`, `109`, `110`, `111`, `112`, `113` |
| Dashboard & trading | `BuyPaymentDetailsPage` | `buyPaymentDetails` | `/buyPaymentDetails` | `53`, `114`, `115`, `116`, `117` |
@@ -125,8 +125,10 @@ Column meaning:
81 screens — 47 routed (`GoRoute`) + 34 non-routed. The table also carries
two shared-widget baselines (`PhoneNumberField`, `ReferralPayoutTransactionRow`),
which are not screens.
-Referral surfaces have Golden baselines (`276`–`290`); the handbook
-documents the programme in `#spec-referral`.
+Referral surfaces have Golden baselines (`276`–`292`); the handbook
+documents the programme in `#spec-referral`. Overlay slots `291` and `292`
+are listed on `DashboardPage` (the host screen), not as a second shared-widget
+row.
## Notes
@@ -145,7 +147,7 @@ documents the programme in `#spec-referral`.
`243`–`245`. `SetupPinPage` also backs the `settingsChangePin` route
(`/settings/security/changePin`) via a second constructor; that reuse has no
separate Golden and is not given its own row.
-- **Handbook numbering.** Each of the 299 handbook slots is a Visual-Regression
+- **Handbook numbering.** Each of the 301 handbook slots is a Visual-Regression
Golden under `test/goldens/`, mapped to its handbook position by
`scripts/assemble-handbook-screenshots.sh`. A parallel Tier-3 Maestro flow
(`.maestro/handbook/NN-*.yaml`) covers navigation/tap-routing smoke for the
diff --git a/docs/visual-regression-tests.md b/docs/visual-regression-tests.md
index 6db160578..a43d1d01f 100644
--- a/docs/visual-regression-tests.md
+++ b/docs/visual-regression-tests.md
@@ -1,7 +1,7 @@
# Visual Regression Tests
Pixel-exact baseline tests for every page in the app. 81 `lib/screens/**/*_page.dart`
-files mapped to 350 Golden PNGs under `test/goldens/` (`screens/` and `widgets/`) (page renderings
+files mapped to 355 Golden PNGs under `test/goldens/` (`screens/` and `widgets/`) (page renderings
plus state variants: Buy/Sell error banners, KYC loading/failure, Dashboard
with-balance, RestoreWallet valid/invalid, Legal-Disclaimer steps, etc.),
validated on each PR by the `Visual Regression` job (required status check
@@ -191,7 +191,7 @@ public repos are free even for macOS minutes.
## Handbook screenshots are sourced from Goldens
-The 299 PNGs the handbook serves at `handbook.realunit.app/screenshots/`
+The 301 PNGs the handbook serves at `handbook.realunit.app/screenshots/`
are assembled from the Golden baselines at docker-build time. One
Golden → one handbook page, via the explicit mapping in
`scripts/assemble-handbook-screenshots.sh`. The handbook does **not**
@@ -231,7 +231,7 @@ that directory into `/usr/share/nginx/html/screenshots/`.
Golden file.
4. Open the PR. The `Handbook Build Check` workflow runs
`docker build` and a container smoke (`/healthz` + auth gate +
- spot-checks selected mapped screenshots via `docker exec test -f`; the full set is gated by the assemble step (`expected 299`)). A missing Golden surfaces here
+ spot-checks selected mapped screenshots via `docker exec test -f`; the full set is gated by the assemble step (`expected 301`)). A missing Golden surfaces here
as a missing-source error from the assembly script before docker
even spins up.
diff --git a/lib/screens/referral/referral_bind_error_dialog.dart b/lib/screens/referral/referral_bind_error_dialog.dart
new file mode 100644
index 000000000..52cf30651
--- /dev/null
+++ b/lib/screens/referral/referral_bind_error_dialog.dart
@@ -0,0 +1,32 @@
+import 'package:flutter/material.dart';
+import 'package:realunit_wallet/generated/i18n.dart';
+import 'package:realunit_wallet/screens/referral/referral_error_message.dart';
+import 'package:realunit_wallet/styles/colors.dart';
+
+/// Bind-error overlay after `POST /v1/realunit/referral/bind` returns 4xx.
+///
+/// Title and body come from [localizedReferralErrorTitle] /
+/// [localizedReferralError] so goldens and the live dashboard share one widget.
+class ReferralBindErrorDialog extends StatelessWidget {
+ final String token;
+
+ const ReferralBindErrorDialog({super.key, required this.token});
+
+ @override
+ Widget build(BuildContext context) {
+ final style = Theme.of(context).textTheme.bodyMedium?.copyWith(
+ color: RealUnitColors.status.red600,
+ );
+ return AlertDialog(
+ title: Text(localizedReferralErrorTitle(context, token), style: style),
+ content: Text(localizedReferralError(context, token), style: style),
+ actions: [
+ TextButton(
+ autofocus: true,
+ onPressed: () => Navigator.of(context).maybePop(),
+ child: Text(S.of(context).close),
+ ),
+ ],
+ );
+ }
+}
diff --git a/lib/screens/referral/referral_error_message.dart b/lib/screens/referral/referral_error_message.dart
index 5e5b37267..96ee8ee58 100644
--- a/lib/screens/referral/referral_error_message.dart
+++ b/lib/screens/referral/referral_error_message.dart
@@ -100,5 +100,14 @@ String localizedReferralErrorTitle(BuildContext context, String message) {
if (message == referralSpentMessage) {
return S.of(context).referralCodeSpentTitle;
}
+ if (message == referralAlreadyRegisteredMessage) {
+ return S.of(context).referralAlreadyRegisteredTitle;
+ }
+ if (message == referralAlreadyBoundMessage) {
+ return S.of(context).referralAlreadyBoundTitle;
+ }
+ if (message == referralSelfReferralMessage) {
+ return S.of(context).referralSelfReferralTitle;
+ }
return S.of(context).referralCodeInvalidTitle;
}
diff --git a/lib/setup/routing/referral_bind.dart b/lib/setup/routing/referral_bind.dart
index cbe13bdd8..812b5150d 100644
--- a/lib/setup/routing/referral_bind.dart
+++ b/lib/setup/routing/referral_bind.dart
@@ -9,11 +9,11 @@ import 'package:realunit_wallet/packages/service/dfx/models/referral/dto/referra
import 'package:realunit_wallet/packages/service/dfx/real_unit_referral_service.dart';
import 'package:realunit_wallet/packages/service/dfx/referral_lookup_status.dart';
import 'package:realunit_wallet/screens/pin/bloc/auth/pin_auth_cubit.dart';
+import 'package:realunit_wallet/screens/referral/referral_bind_error_dialog.dart';
import 'package:realunit_wallet/screens/referral/referral_error_message.dart';
import 'package:realunit_wallet/setup/di.dart';
import 'package:realunit_wallet/setup/routing/effective_location.dart';
import 'package:realunit_wallet/setup/routing/referral_pending_code.dart';
-import 'package:realunit_wallet/styles/colors.dart';
import 'package:realunit_wallet/widgets/buttons/app_filled_button.dart';
bool _bindInFlight = false;
@@ -323,27 +323,7 @@ Future _showInvalidBindDialog(GoRouter router, Object error) {
await showDialog(
context: ctx,
barrierDismissible: false,
- builder: (dialogContext) => AlertDialog(
- title: Text(
- localizedReferralErrorTitle(dialogContext, token),
- style: Theme.of(dialogContext).textTheme.bodyMedium?.copyWith(
- color: RealUnitColors.status.red600,
- ),
- ),
- content: Text(
- localizedReferralError(dialogContext, token),
- style: Theme.of(dialogContext).textTheme.bodyMedium?.copyWith(
- color: RealUnitColors.status.red600,
- ),
- ),
- actions: [
- TextButton(
- autofocus: true,
- onPressed: () => Navigator.of(dialogContext).pop(),
- child: Text(S.of(dialogContext).close),
- ),
- ],
- ),
+ builder: (dialogContext) => ReferralBindErrorDialog(token: token),
);
});
}
diff --git a/scripts/assemble-handbook-screenshots.sh b/scripts/assemble-handbook-screenshots.sh
index f1a3dbae3..73aee07fd 100755
--- a/scripts/assemble-handbook-screenshots.sh
+++ b/scripts/assemble-handbook-screenshots.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
#
-# Assemble the 299 handbook screenshots from the visual-regression Golden
+# Assemble the 301 handbook screenshots from the visual-regression Golden
# baselines. The flat `NN-name.png` output layout matches what
# docs/handbook/de/index.html links to (`
`
# — the relative path resolves to `docs/handbook/screenshots/NN-name.png`).
@@ -322,7 +322,7 @@ MAPPING=(
"273-handbook-persona-mix=screens/dashboard/goldens/macos/handbook_persona_mix.png"
"274-handbook-persona-scale=screens/dashboard/goldens/macos/handbook_persona_scale.png"
"275-handbook-persona-exit-1j=screens/dashboard/goldens/macos/handbook_persona_exit_1j.png"
- # 276–290: referral/promo goldens. No matching .maestro/handbook flow —
+ # 276–292: referral/promo goldens. No matching .maestro/handbook flow —
# eligibility (KYC 30 + 70 REALU) is not reachable in the 01–26 chain.
"276-referral-overview=screens/referral/goldens/macos/referral_overview_page_default.png"
"277-kyc-registration-referral=screens/kyc/goldens/macos/kyc_registration_referral_step_default.png"
@@ -339,6 +339,8 @@ MAPPING=(
"288-transaction-history-referral-payout=screens/transaction_history/goldens/macos/transaction_history_page_referral_payout.png"
"289-dashboard-referral-entry-and-payout=screens/dashboard/goldens/macos/dashboard_referral_entry_and_payout.png"
"290-kyc-registration-referral-promo=screens/kyc/goldens/macos/kyc_registration_referral_step_promo.png"
+ "291-referral-bind-error-invalid=screens/referral/goldens/macos/referral_bind_error_invalid.png"
+ "292-referral-bind-error-already-registered=screens/referral/goldens/macos/referral_bind_error_already_registered.png"
)
missing=()
diff --git a/scripts/run-handbook-flows.sh b/scripts/run-handbook-flows.sh
index e5f7b02de..0e1a62f94 100755
--- a/scripts/run-handbook-flows.sh
+++ b/scripts/run-handbook-flows.sh
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
#
# Tier-3 navigation smoke for the 26 .maestro/handbook/*.yaml flows
-# (01-welcome … 26-terms). Handbook pages 276–290 (referral/promo) are
+# (01-welcome … 26-terms). Handbook pages 276–292 (referral/promo) are
# golden-mapped in assemble-handbook-screenshots.sh and are not Maestro
# flows: the sequential onboarding chain cannot reach an eligible
# Empfehler (KYC Level 30 + 70 REALU).
diff --git a/test/goldens/screens/dashboard/goldens/macos/dashboard_referral_entry_and_payout.png b/test/goldens/screens/dashboard/goldens/macos/dashboard_referral_entry_and_payout.png
index f21ec2c87..48ff23577 100644
Binary files a/test/goldens/screens/dashboard/goldens/macos/dashboard_referral_entry_and_payout.png and b/test/goldens/screens/dashboard/goldens/macos/dashboard_referral_entry_and_payout.png differ
diff --git a/test/goldens/screens/kyc/goldens/macos/kyc_registration_referral_step_default.png b/test/goldens/screens/kyc/goldens/macos/kyc_registration_referral_step_default.png
index c862c948d..d407603c5 100644
Binary files a/test/goldens/screens/kyc/goldens/macos/kyc_registration_referral_step_default.png and b/test/goldens/screens/kyc/goldens/macos/kyc_registration_referral_step_default.png differ
diff --git a/test/goldens/screens/kyc/goldens/macos/kyc_registration_referral_step_invalid.png b/test/goldens/screens/kyc/goldens/macos/kyc_registration_referral_step_invalid.png
index ae9f2313a..0e7fc95aa 100644
Binary files a/test/goldens/screens/kyc/goldens/macos/kyc_registration_referral_step_invalid.png and b/test/goldens/screens/kyc/goldens/macos/kyc_registration_referral_step_invalid.png differ
diff --git a/test/goldens/screens/kyc/goldens/macos/kyc_registration_referral_step_loading.png b/test/goldens/screens/kyc/goldens/macos/kyc_registration_referral_step_loading.png
index bfcf6eb0e..bf44f3c08 100644
Binary files a/test/goldens/screens/kyc/goldens/macos/kyc_registration_referral_step_loading.png and b/test/goldens/screens/kyc/goldens/macos/kyc_registration_referral_step_loading.png differ
diff --git a/test/goldens/screens/kyc/goldens/macos/kyc_registration_referral_step_promo.png b/test/goldens/screens/kyc/goldens/macos/kyc_registration_referral_step_promo.png
index 2f433ad8d..6c2425b10 100644
Binary files a/test/goldens/screens/kyc/goldens/macos/kyc_registration_referral_step_promo.png and b/test/goldens/screens/kyc/goldens/macos/kyc_registration_referral_step_promo.png differ
diff --git a/test/goldens/screens/kyc/goldens/macos/kyc_registration_referral_step_recognized.png b/test/goldens/screens/kyc/goldens/macos/kyc_registration_referral_step_recognized.png
index aee87b520..6577461aa 100644
Binary files a/test/goldens/screens/kyc/goldens/macos/kyc_registration_referral_step_recognized.png and b/test/goldens/screens/kyc/goldens/macos/kyc_registration_referral_step_recognized.png differ
diff --git a/test/goldens/screens/kyc/goldens/macos/kyc_registration_referral_step_spent.png b/test/goldens/screens/kyc/goldens/macos/kyc_registration_referral_step_spent.png
index f3095e562..b69db0380 100644
Binary files a/test/goldens/screens/kyc/goldens/macos/kyc_registration_referral_step_spent.png and b/test/goldens/screens/kyc/goldens/macos/kyc_registration_referral_step_spent.png differ
diff --git a/test/goldens/screens/kyc/goldens/macos/kyc_registration_referral_step_unavailable.png b/test/goldens/screens/kyc/goldens/macos/kyc_registration_referral_step_unavailable.png
index 661fd83de..564db0b65 100644
Binary files a/test/goldens/screens/kyc/goldens/macos/kyc_registration_referral_step_unavailable.png and b/test/goldens/screens/kyc/goldens/macos/kyc_registration_referral_step_unavailable.png differ
diff --git a/test/goldens/screens/referral/goldens/macos/referral_bind_error_already_bound.png b/test/goldens/screens/referral/goldens/macos/referral_bind_error_already_bound.png
new file mode 100644
index 000000000..3b1bbefed
Binary files /dev/null and b/test/goldens/screens/referral/goldens/macos/referral_bind_error_already_bound.png differ
diff --git a/test/goldens/screens/referral/goldens/macos/referral_bind_error_already_registered.png b/test/goldens/screens/referral/goldens/macos/referral_bind_error_already_registered.png
new file mode 100644
index 000000000..ebd1cda90
Binary files /dev/null and b/test/goldens/screens/referral/goldens/macos/referral_bind_error_already_registered.png differ
diff --git a/test/goldens/screens/referral/goldens/macos/referral_bind_error_invalid.png b/test/goldens/screens/referral/goldens/macos/referral_bind_error_invalid.png
new file mode 100644
index 000000000..b48faf354
Binary files /dev/null and b/test/goldens/screens/referral/goldens/macos/referral_bind_error_invalid.png differ
diff --git a/test/goldens/screens/referral/goldens/macos/referral_bind_error_self_referral.png b/test/goldens/screens/referral/goldens/macos/referral_bind_error_self_referral.png
new file mode 100644
index 000000000..4ea83d502
Binary files /dev/null and b/test/goldens/screens/referral/goldens/macos/referral_bind_error_self_referral.png differ
diff --git a/test/goldens/screens/referral/goldens/macos/referral_bind_error_spent.png b/test/goldens/screens/referral/goldens/macos/referral_bind_error_spent.png
new file mode 100644
index 000000000..4e82e569d
Binary files /dev/null and b/test/goldens/screens/referral/goldens/macos/referral_bind_error_spent.png differ
diff --git a/test/goldens/screens/referral/goldens/macos/referral_create_page_creating.png b/test/goldens/screens/referral/goldens/macos/referral_create_page_creating.png
index beec17dd3..602fdfedb 100644
Binary files a/test/goldens/screens/referral/goldens/macos/referral_create_page_creating.png and b/test/goldens/screens/referral/goldens/macos/referral_create_page_creating.png differ
diff --git a/test/goldens/screens/referral/goldens/macos/referral_create_page_error.png b/test/goldens/screens/referral/goldens/macos/referral_create_page_error.png
index cb3c4b368..28441eb65 100644
Binary files a/test/goldens/screens/referral/goldens/macos/referral_create_page_error.png and b/test/goldens/screens/referral/goldens/macos/referral_create_page_error.png differ
diff --git a/test/goldens/screens/referral/goldens/macos/referral_create_page_invite_created.png b/test/goldens/screens/referral/goldens/macos/referral_create_page_invite_created.png
index 1aae8e992..6de5a8d32 100644
Binary files a/test/goldens/screens/referral/goldens/macos/referral_create_page_invite_created.png and b/test/goldens/screens/referral/goldens/macos/referral_create_page_invite_created.png differ
diff --git a/test/goldens/screens/referral/goldens/macos/referral_create_page_name_entry.png b/test/goldens/screens/referral/goldens/macos/referral_create_page_name_entry.png
index d9fe23231..e02a2eb90 100644
Binary files a/test/goldens/screens/referral/goldens/macos/referral_create_page_name_entry.png and b/test/goldens/screens/referral/goldens/macos/referral_create_page_name_entry.png differ
diff --git a/test/goldens/screens/referral/goldens/macos/referral_create_page_quota.png b/test/goldens/screens/referral/goldens/macos/referral_create_page_quota.png
index d2196d159..915299824 100644
Binary files a/test/goldens/screens/referral/goldens/macos/referral_create_page_quota.png and b/test/goldens/screens/referral/goldens/macos/referral_create_page_quota.png differ
diff --git a/test/goldens/screens/referral/goldens/macos/referral_entry_card_eligible.png b/test/goldens/screens/referral/goldens/macos/referral_entry_card_eligible.png
index 9f256aeb2..462feecde 100644
Binary files a/test/goldens/screens/referral/goldens/macos/referral_entry_card_eligible.png and b/test/goldens/screens/referral/goldens/macos/referral_entry_card_eligible.png differ
diff --git a/test/goldens/screens/referral/goldens/macos/referral_gate_failure.png b/test/goldens/screens/referral/goldens/macos/referral_gate_failure.png
index 1d7fe088e..bb9205adc 100644
Binary files a/test/goldens/screens/referral/goldens/macos/referral_gate_failure.png and b/test/goldens/screens/referral/goldens/macos/referral_gate_failure.png differ
diff --git a/test/goldens/screens/referral/goldens/macos/referral_overview_page_default.png b/test/goldens/screens/referral/goldens/macos/referral_overview_page_default.png
index 559700e02..a2cd3e1ae 100644
Binary files a/test/goldens/screens/referral/goldens/macos/referral_overview_page_default.png and b/test/goldens/screens/referral/goldens/macos/referral_overview_page_default.png differ
diff --git a/test/goldens/screens/referral/goldens/macos/referral_overview_page_empty.png b/test/goldens/screens/referral/goldens/macos/referral_overview_page_empty.png
index eb1e70c35..765b01293 100644
Binary files a/test/goldens/screens/referral/goldens/macos/referral_overview_page_empty.png and b/test/goldens/screens/referral/goldens/macos/referral_overview_page_empty.png differ
diff --git a/test/goldens/screens/referral/goldens/macos/referral_overview_page_failure.png b/test/goldens/screens/referral/goldens/macos/referral_overview_page_failure.png
index 91d98b8fb..deedc3d2c 100644
Binary files a/test/goldens/screens/referral/goldens/macos/referral_overview_page_failure.png and b/test/goldens/screens/referral/goldens/macos/referral_overview_page_failure.png differ
diff --git a/test/goldens/screens/referral/goldens/macos/referral_overview_page_invites_error.png b/test/goldens/screens/referral/goldens/macos/referral_overview_page_invites_error.png
index 7096ef2bb..8b720a339 100644
Binary files a/test/goldens/screens/referral/goldens/macos/referral_overview_page_invites_error.png and b/test/goldens/screens/referral/goldens/macos/referral_overview_page_invites_error.png differ
diff --git a/test/goldens/screens/referral/goldens/macos/referral_overview_page_loading.png b/test/goldens/screens/referral/goldens/macos/referral_overview_page_loading.png
index 6a0a6d34f..210501469 100644
Binary files a/test/goldens/screens/referral/goldens/macos/referral_overview_page_loading.png and b/test/goldens/screens/referral/goldens/macos/referral_overview_page_loading.png differ
diff --git a/test/goldens/screens/referral/goldens/macos/referral_terms_page_error.png b/test/goldens/screens/referral/goldens/macos/referral_terms_page_error.png
index 446bad251..b3c0afae7 100644
Binary files a/test/goldens/screens/referral/goldens/macos/referral_terms_page_error.png and b/test/goldens/screens/referral/goldens/macos/referral_terms_page_error.png differ
diff --git a/test/goldens/screens/referral/referral_bind_error_dialog_golden_test.dart b/test/goldens/screens/referral/referral_bind_error_dialog_golden_test.dart
new file mode 100644
index 000000000..fe4953f9b
--- /dev/null
+++ b/test/goldens/screens/referral/referral_bind_error_dialog_golden_test.dart
@@ -0,0 +1,191 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:bloc_test/bloc_test.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:get_it/get_it.dart';
+import 'package:mocktail/mocktail.dart';
+import 'package:realunit_wallet/models/balance.dart';
+import 'package:realunit_wallet/models/portfolio_value_point.dart';
+import 'package:realunit_wallet/models/price_point.dart';
+import 'package:realunit_wallet/models/transaction.dart';
+import 'package:realunit_wallet/packages/config/api_config.dart';
+import 'package:realunit_wallet/packages/repository/transaction_repository.dart';
+import 'package:realunit_wallet/packages/service/app_store.dart';
+import 'package:realunit_wallet/packages/service/dfx/models/transactions/dto/transactions_dto.dart';
+import 'package:realunit_wallet/packages/service/dfx/real_unit_pdf_service.dart';
+import 'package:realunit_wallet/packages/service/dfx/real_unit_referral_service.dart';
+import 'package:realunit_wallet/packages/utils/default_assets.dart';
+import 'package:realunit_wallet/screens/dashboard/bloc/balance_cubit.dart';
+import 'package:realunit_wallet/screens/dashboard/bloc/dashboard_bloc.dart';
+import 'package:realunit_wallet/screens/dashboard/bloc/pending_transactions_cubit.dart';
+import 'package:realunit_wallet/screens/dashboard/dashboard_page.dart';
+import 'package:realunit_wallet/screens/referral/referral_bind_error_dialog.dart';
+import 'package:realunit_wallet/screens/referral/referral_error_message.dart';
+import 'package:realunit_wallet/screens/settings/bloc/settings_bloc.dart';
+import 'package:realunit_wallet/styles/currency.dart';
+
+import '../../../helper/helper.dart';
+
+class _MockTransactionRepository extends Mock implements TransactionRepository {}
+
+class _MockRealUnitPdfService extends Mock implements RealUnitPdfService {}
+
+class _MockApiConfig extends Mock implements ApiConfig {}
+
+class _MockDashboardBloc extends MockBloc
+ implements DashboardBloc {}
+
+class _MockBalanceCubit extends MockCubit implements BalanceCubit {}
+
+class _MockPendingTransactionsCubit extends MockCubit>
+ implements PendingTransactionsCubit {}
+
+void main() {
+ const walletAddress = '0xcabd3f4b10a7089986e708d19140bfc98e5880c0';
+ const counterparty = '0x1234567890abcdef1234567890abcdef12345678';
+
+ late _MockDashboardBloc dashboardBloc;
+ late _MockBalanceCubit balanceCubit;
+ late _MockPendingTransactionsCubit pendingTxCubit;
+ late MockSettingsBloc settingsBloc;
+ final transactionRepository = _MockTransactionRepository();
+
+ final priceChart = [
+ PricePoint(asset: realUnitAsset, price: BigInt.from(148), time: DateTime.utc(2025, 11)),
+ PricePoint(asset: realUnitAsset, price: BigInt.from(150), time: DateTime.utc(2025, 12)),
+ PricePoint(asset: realUnitAsset, price: BigInt.from(149), time: DateTime.utc(2026, 1)),
+ PricePoint(asset: realUnitAsset, price: BigInt.from(152), time: DateTime.utc(2026, 2)),
+ PricePoint(asset: realUnitAsset, price: BigInt.from(151), time: DateTime.utc(2026, 3)),
+ PricePoint(asset: realUnitAsset, price: BigInt.from(155), time: DateTime.utc(2026, 4)),
+ PricePoint(asset: realUnitAsset, price: BigInt.from(153), time: DateTime.utc(2026, 5)),
+ ];
+
+ final portfolioHistory = [
+ PortfolioValuePoint(value: BigInt.from(14800), balance: BigInt.from(100), time: DateTime.utc(2025, 11)),
+ PortfolioValuePoint(value: BigInt.from(15000), balance: BigInt.from(100), time: DateTime.utc(2025, 12)),
+ PortfolioValuePoint(value: BigInt.from(14900), balance: BigInt.from(100), time: DateTime.utc(2026, 1)),
+ PortfolioValuePoint(value: BigInt.from(15200), balance: BigInt.from(100), time: DateTime.utc(2026, 2)),
+ PortfolioValuePoint(value: BigInt.from(15100), balance: BigInt.from(100), time: DateTime.utc(2026, 3)),
+ PortfolioValuePoint(value: BigInt.from(15500), balance: BigInt.from(100), time: DateTime.utc(2026, 4)),
+ PortfolioValuePoint(value: BigInt.from(15300), balance: BigInt.from(100), time: DateTime.utc(2026, 5)),
+ ];
+
+ final recentBuy = Transaction(
+ height: 200,
+ txId: '0xrecent1',
+ chainId: 1,
+ senderAddress: counterparty,
+ receiverAddress: walletAddress,
+ amount: BigInt.from(99),
+ asset: realUnitAsset,
+ type: TransactionTypes.tokenTransfer,
+ note: null,
+ data: null,
+ timestamp: DateTime.utc(2026, 8, 14, 10, 26),
+ );
+
+ setUpAll(() {
+ final getIt = GetIt.instance;
+ final apiConfig = _MockApiConfig();
+ final appStore = MockAppStore();
+ when(() => apiConfig.asset).thenReturn(realUnitAsset);
+ when(() => appStore.apiConfig).thenReturn(apiConfig);
+ when(() => appStore.primaryAddress).thenReturn(walletAddress);
+ getIt.registerSingleton(appStore);
+ getIt.registerSingleton(_MockRealUnitPdfService());
+ getIt.registerSingleton(transactionRepository);
+ getIt.registerSingleton(
+ MockRealUnitReferralService(),
+ );
+ });
+
+ tearDownAll(() async => GetIt.instance.reset());
+
+ setUp(() {
+ dashboardBloc = _MockDashboardBloc();
+ balanceCubit = _MockBalanceCubit();
+ pendingTxCubit = _MockPendingTransactionsCubit();
+ settingsBloc = MockSettingsBloc();
+
+ when(() => dashboardBloc.state).thenReturn(
+ DashboardState(
+ price: BigInt.from(138),
+ priceChart: priceChart,
+ portfolioHistory: portfolioHistory,
+ currency: Currency.chf,
+ ),
+ );
+ when(() => balanceCubit.state).thenReturn(
+ Balance(
+ chainId: realUnitAsset.chainId,
+ contractAddress: realUnitAsset.address,
+ walletAddress: walletAddress,
+ balance: BigInt.from(99),
+ asset: realUnitAsset,
+ ),
+ );
+ when(() => balanceCubit.asset).thenReturn(realUnitAsset);
+ when(() => pendingTxCubit.state).thenReturn(const []);
+ when(() => settingsBloc.state).thenReturn(const SettingsState());
+ when(() => transactionRepository.watchTransactionsOfAssets(any(), any(), any()))
+ .thenAnswer((_) => Stream.value([recentBuy]));
+ });
+
+ Widget dashboard() => MultiBlocProvider(
+ providers: [
+ BlocProvider.value(value: settingsBloc),
+ BlocProvider.value(value: dashboardBloc),
+ BlocProvider.value(value: balanceCubit),
+ BlocProvider.value(value: pendingTxCubit),
+ ],
+ child: const DashboardView(),
+ );
+
+ Widget overlay(String token) => wrapForGolden(
+ Stack(
+ fit: StackFit.expand,
+ children: [
+ dashboard(),
+ const ModalBarrier(dismissible: false, color: Colors.black54),
+ Center(child: ReferralBindErrorDialog(token: token)),
+ ],
+ ),
+ );
+
+ group('$ReferralBindErrorDialog', () {
+ goldenTest(
+ 'invalid or expired on the live dashboard',
+ fileName: 'referral_bind_error_invalid',
+ constraints: phoneConstraints,
+ builder: () => overlay(referralInvalidMessage),
+ );
+
+ goldenTest(
+ 'already registered (first RealUnit purchase done)',
+ fileName: 'referral_bind_error_already_registered',
+ constraints: phoneConstraints,
+ builder: () => overlay(referralAlreadyRegisteredMessage),
+ );
+
+ goldenTest(
+ 'already bound',
+ fileName: 'referral_bind_error_already_bound',
+ constraints: phoneConstraints,
+ builder: () => overlay(referralAlreadyBoundMessage),
+ );
+
+ goldenTest(
+ 'self-referral',
+ fileName: 'referral_bind_error_self_referral',
+ constraints: phoneConstraints,
+ builder: () => overlay(referralSelfReferralMessage),
+ );
+
+ goldenTest(
+ 'spent',
+ fileName: 'referral_bind_error_spent',
+ constraints: phoneConstraints,
+ builder: () => overlay(referralSpentMessage),
+ );
+ });
+}
diff --git a/test/goldens/screens/settings/goldens/macos/settings_page_referral_eligible.png b/test/goldens/screens/settings/goldens/macos/settings_page_referral_eligible.png
index ae9c3a331..7d8a1b3fe 100644
Binary files a/test/goldens/screens/settings/goldens/macos/settings_page_referral_eligible.png and b/test/goldens/screens/settings/goldens/macos/settings_page_referral_eligible.png differ
diff --git a/test/goldens/screens/transaction_history/goldens/macos/transaction_history_page_referral_payout.png b/test/goldens/screens/transaction_history/goldens/macos/transaction_history_page_referral_payout.png
index 4a958014f..b9bcb60fb 100644
Binary files a/test/goldens/screens/transaction_history/goldens/macos/transaction_history_page_referral_payout.png and b/test/goldens/screens/transaction_history/goldens/macos/transaction_history_page_referral_payout.png differ
diff --git a/test/goldens/screens/transaction_history/transaction_history_states_golden_test.dart b/test/goldens/screens/transaction_history/transaction_history_states_golden_test.dart
index 71c1aa331..cf58bb97a 100644
--- a/test/goldens/screens/transaction_history/transaction_history_states_golden_test.dart
+++ b/test/goldens/screens/transaction_history/transaction_history_states_golden_test.dart
@@ -174,7 +174,8 @@ void main() {
type: TransactionTypes.referralPayout,
note: '',
data: '246.50',
- timestamp: DateTime.utc(2026, 8, 24, 10),
+ // Prize date must fall inside the pinned clock's default filter window.
+ timestamp: DateTime.utc(2026, 5, 20, 10),
);
return withClock(pinnedClock, () {
when(() => filterCubit.state).thenReturn(
diff --git a/test/screens/kyc/steps/registration/widgets/referral_code_field_test.dart b/test/screens/kyc/steps/registration/widgets/referral_code_field_test.dart
index a9c1bb645..d76f59c81 100644
--- a/test/screens/kyc/steps/registration/widgets/referral_code_field_test.dart
+++ b/test/screens/kyc/steps/registration/widgets/referral_code_field_test.dart
@@ -139,7 +139,7 @@ void main() {
await tester.pump();
await tester.pump(const Duration(milliseconds: 500));
- expect(find.text('Hast du einen Empfehlungscode?'), findsOneWidget);
+ expect(find.text('Haben Sie einen Empfehlungscode?'), findsOneWidget);
final field = tester.widget(find.byType(TextField));
expect(field.enableIMEPersonalizedLearning, isFalse);
expect(find.textContaining('Einladung von Björn erkannt'), findsOneWidget);
@@ -418,7 +418,7 @@ void main() {
);
expect(
find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
findsOneWidget,
);
@@ -426,7 +426,7 @@ void main() {
_isLiveRegion(
tester,
find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
),
isTrue,
@@ -532,7 +532,7 @@ void main() {
expect(calls, 2);
expect(
find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
findsOneWidget,
);
@@ -1324,7 +1324,7 @@ void main() {
findsNothing,
);
expect(
- find.text('Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.'),
+ find.text('Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.'),
findsOneWidget,
);
expect(ctrl.text, 'AB12');
@@ -1344,7 +1344,7 @@ void main() {
await tester.pump(const Duration(seconds: 15));
expect(find.text('Code wird geprüft…'), findsNothing);
expect(
- find.text('Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.'),
+ find.text('Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.'),
findsOneWidget,
);
expect(find.text('Wiederholen'), findsOneWidget);
diff --git a/test/screens/referral/flows/referral_create_invite_flow_test.dart b/test/screens/referral/flows/referral_create_invite_flow_test.dart
index 7214a7e5a..974ca6aad 100644
--- a/test/screens/referral/flows/referral_create_invite_flow_test.dart
+++ b/test/screens/referral/flows/referral_create_invite_flow_test.dart
@@ -110,7 +110,7 @@ void main() {
await pumpCreate(tester);
await tester.pump();
- expect(find.text('Deine Einladung für Alice'), findsOneWidget);
+ expect(find.text('Ihre Einladung für Alice'), findsOneWidget);
expect(find.text('Persönlicher Einladungslink'), findsOneWidget);
});
}
diff --git a/test/screens/referral/flows/referral_entry_card_flow_test.dart b/test/screens/referral/flows/referral_entry_card_flow_test.dart
index 52dbb0f20..0cd48117c 100644
--- a/test/screens/referral/flows/referral_entry_card_flow_test.dart
+++ b/test/screens/referral/flows/referral_entry_card_flow_test.dart
@@ -80,7 +80,7 @@ void main() {
await tester.pumpAndSettle();
expect(find.text('Empfehlungen'), findsOneWidget);
- expect(find.text('Erhalte 20 REALU pro Weiterempfehlung'), findsOneWidget);
+ expect(find.text('Erhalten Sie 20 REALU pro Weiterempfehlung'), findsOneWidget);
});
testWidgets('taps the Einstiegskarte through to the referral route', (tester) async {
diff --git a/test/screens/referral/flows/referral_overview_flow_test.dart b/test/screens/referral/flows/referral_overview_flow_test.dart
index b59c19a77..86ae7f62a 100644
--- a/test/screens/referral/flows/referral_overview_flow_test.dart
+++ b/test/screens/referral/flows/referral_overview_flow_test.dart
@@ -130,7 +130,7 @@ void main() {
expect(find.text('INSGESAMT ERHALTEN'), findsOneWidget);
expect(find.text('40 REALU'), findsOneWidget);
expect(find.textContaining('Aktienkurs'), findsOneWidget);
- expect(find.text('Deine Einladung für AliceShouldNotAppear'), findsOneWidget);
+ expect(find.text('Ihre Einladung für AliceShouldNotAppear'), findsOneWidget);
expect(find.text('BobShouldNotAppear'), findsNothing);
});
diff --git a/test/screens/referral/referral_create_page_test.dart b/test/screens/referral/referral_create_page_test.dart
index 97f05214f..22ac759cb 100644
--- a/test/screens/referral/referral_create_page_test.dart
+++ b/test/screens/referral/referral_create_page_test.dart
@@ -74,7 +74,7 @@ void main() {
await pumpCreateView(tester);
await tester.pump();
- expect(find.text('Deine Einladung für Alice'), findsOneWidget);
+ expect(find.text('Ihre Einladung für Alice'), findsOneWidget);
expect(find.text('Persönlicher Einladungslink'), findsOneWidget);
expect(
find.text(
@@ -114,8 +114,8 @@ void main() {
await pumpCreateView(tester);
await tester.pump();
- expect(find.text('Deine Einladung'), findsOneWidget);
- expect(find.textContaining('Deine Einladung für'), findsNothing);
+ expect(find.text('Ihre Einladung'), findsOneWidget);
+ expect(find.textContaining('Ihre Einladung für'), findsNothing);
expect(find.text('Hey ,'), findsNothing);
expect(
find.text('RealUnit lädt dich ein zu RealUnit: https://realunit.app/invite/AB12CD'),
@@ -283,7 +283,7 @@ void main() {
expect(
find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
findsOneWidget,
);
@@ -291,7 +291,7 @@ void main() {
tester
.widget(
find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
)
.style
@@ -301,7 +301,7 @@ void main() {
expect(
find.ancestor(
of: find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
matching: find.byWidgetPredicate(
(widget) => widget is Semantics && widget.properties.liveRegion == true,
diff --git a/test/screens/referral/referral_entry_card_test.dart b/test/screens/referral/referral_entry_card_test.dart
index c9a5741f7..966bd0325 100644
--- a/test/screens/referral/referral_entry_card_test.dart
+++ b/test/screens/referral/referral_entry_card_test.dart
@@ -80,7 +80,7 @@ void main() {
await tester.pump();
expect(find.text('Empfehlungen'), findsNothing);
- expect(find.text('Erhalte 20 REALU pro Weiterempfehlung'), findsNothing);
+ expect(find.text('Erhalten Sie 20 REALU pro Weiterempfehlung'), findsNothing);
});
testWidgets('resume reloads the gate and can open the card', (tester) async {
@@ -115,7 +115,7 @@ void main() {
await tester.pumpAndSettle();
expect(find.text('Empfehlungen'), findsOneWidget);
- expect(find.text('Erhalte 20 REALU pro Weiterempfehlung'), findsOneWidget);
+ expect(find.text('Erhalten Sie 20 REALU pro Weiterempfehlung'), findsOneWidget);
});
testWidgets('popping back to this route reloads the gate', (tester) async {
@@ -216,7 +216,7 @@ void main() {
await tester.pump(const Duration(milliseconds: 25));
await tester.pump();
expect(find.text('Empfehlungen'), findsOneWidget);
- expect(find.text('Erhalte 20 REALU pro Weiterempfehlung'), findsOneWidget);
+ expect(find.text('Erhalten Sie 20 REALU pro Weiterempfehlung'), findsOneWidget);
});
testWidgets('does not poll when the API gate is closed', (tester) async {
@@ -336,7 +336,7 @@ void main() {
await tester.pumpAndSettle();
expect(find.text('Empfehlungen'), findsOneWidget);
- expect(find.text('Erhalte 20 REALU pro Weiterempfehlung'), findsOneWidget);
+ expect(find.text('Erhalten Sie 20 REALU pro Weiterempfehlung'), findsOneWidget);
expect(
find.descendant(
of: find.byType(ReferralEntryCard),
diff --git a/test/screens/referral/referral_error_message_test.dart b/test/screens/referral/referral_error_message_test.dart
index fdee5765d..02d544ac2 100644
--- a/test/screens/referral/referral_error_message_test.dart
+++ b/test/screens/referral/referral_error_message_test.dart
@@ -203,6 +203,7 @@ void main() {
late String unknown;
late String quota;
late String spentTitle;
+ late String alreadyRegisteredTitle;
await tester.pumpWidget(
MaterialApp(
locale: const Locale('de'),
@@ -221,6 +222,10 @@ void main() {
context,
referralSpentMessage,
);
+ alreadyRegisteredTitle = localizedReferralErrorTitle(
+ context,
+ referralAlreadyRegisteredMessage,
+ );
return const SizedBox.shrink();
},
),
@@ -229,7 +234,7 @@ void main() {
expect(
unknown,
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
);
expect(unknown, isNot('nope'));
expect(
@@ -237,6 +242,8 @@ void main() {
'In diesem Quartal sind keine weiteren Prämien möglich.',
);
expect(spentTitle, 'Code bereits eingelöst');
+ expect(alreadyRegisteredTitle, 'Nur für neue Kundinnen und Kunden');
+ expect(alreadyRegisteredTitle, isNot('Link ungültig oder abgelaufen'));
});
testWidgets('maps remaining tokens to localized DE copy', (tester) async {
@@ -301,7 +308,7 @@ void main() {
expect(
unavailable,
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
);
expect(
notEligible,
@@ -321,15 +328,15 @@ void main() {
);
expect(
selfReferral,
- 'Du kannst deine eigene Einladung nicht einlösen.',
+ 'Sie können Ihre eigene Einladung nicht einlösen.',
);
expect(
alreadyBound,
- 'Du hast bereits einen Einladungs- oder Promo-Code eingelöst.',
+ 'Sie haben bereits einen Einladungs- oder Promo-Code eingelöst.',
);
expect(
alreadyRegistered,
- 'Diese Einladung gilt nur für neue Kundinnen und Kunden.',
+ 'Einladungs- und Promo-Codes müssen vor dem ersten REALU-Kauf eingelöst werden.',
);
expect(invalid, 'Dieser Code ist ungültig oder abgelaufen.');
expect(invalidTitle, 'Link ungültig oder abgelaufen');
diff --git a/test/screens/referral/referral_overview_page_test.dart b/test/screens/referral/referral_overview_page_test.dart
index 53efa6d9d..88f02f4ac 100644
--- a/test/screens/referral/referral_overview_page_test.dart
+++ b/test/screens/referral/referral_overview_page_test.dart
@@ -137,11 +137,11 @@ void main() {
),
findsOneWidget,
);
- expect(find.text('Deine Empfehlungen'), findsOneWidget);
+ expect(find.text('Ihre Empfehlungen'), findsOneWidget);
expect(find.text('INSGESAMT ERHALTEN'), findsOneWidget);
expect(find.textContaining('Aktienkurs'), findsOneWidget);
expect(find.text('Offene Einladungen verfallen nach 3 Monaten.'), findsOneWidget);
- expect(find.text('Deine Einladung für AliceShouldNotAppear'), findsOneWidget);
+ expect(find.text('Ihre Einladung für AliceShouldNotAppear'), findsOneWidget);
expect(find.text('Persönlicher Einladungslink'), findsOneWidget);
expect(
find.text(
@@ -410,8 +410,8 @@ void main() {
);
await tester.pump();
- expect(find.text('Deine Einladung'), findsOneWidget);
- expect(find.textContaining('Deine Einladung für'), findsNothing);
+ expect(find.text('Ihre Einladung'), findsOneWidget);
+ expect(find.textContaining('Ihre Einladung für'), findsNothing);
expect(find.text('Einladungslink kopieren'), findsOneWidget);
expect(find.text('Hey ,'), findsNothing);
expect(
@@ -481,7 +481,7 @@ void main() {
);
await tester.pump();
- expect(find.text('Deine Einladung'), findsNWidgets(2));
+ expect(find.text('Ihre Einladung'), findsNWidgets(2));
expect(find.text('Einladungslink kopieren'), findsNWidgets(2));
},
);
@@ -768,7 +768,7 @@ void main() {
),
);
await tester.pump();
- await tester.tap(find.text('Deine Empfehlungen'));
+ await tester.tap(find.text('Ihre Empfehlungen'));
await tester.pumpAndSettle();
expect(find.text('tb'), findsOneWidget);
});
@@ -1027,14 +1027,14 @@ void main() {
expect(
find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
findsOneWidget,
);
expect(
find.ancestor(
of: find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
matching: find.byWidgetPredicate(
(widget) => widget is Semantics && widget.properties.liveRegion == true,
@@ -1120,11 +1120,11 @@ void main() {
expect(
find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
findsOneWidget,
);
- expect(find.textContaining('Deine Einladung für Alice'), findsOneWidget);
+ expect(find.textContaining('Ihre Einladung für Alice'), findsOneWidget);
expect(find.text('Wiederholen'), findsOneWidget);
expect(
tester
@@ -1194,7 +1194,7 @@ void main() {
expect(
find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
findsOneWidget,
);
@@ -1275,7 +1275,7 @@ void main() {
expect(
find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
findsOneWidget,
);
@@ -1291,7 +1291,7 @@ void main() {
expect(
find.ancestor(
of: find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
matching: find.byWidgetPredicate(
(widget) => widget is Semantics && widget.properties.liveRegion == true,
@@ -1337,7 +1337,7 @@ void main() {
expect(
find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
findsOneWidget,
);
@@ -1345,7 +1345,7 @@ void main() {
tester
.widget(
find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
)
.style
@@ -1355,7 +1355,7 @@ void main() {
expect(
find.ancestor(
of: find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
matching: find.byWidgetPredicate(
(widget) => widget is Semantics && widget.properties.liveRegion == true,
@@ -1413,7 +1413,7 @@ void main() {
expect(
find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
findsOneWidget,
);
diff --git a/test/screens/referral/referral_page_test.dart b/test/screens/referral/referral_page_test.dart
index 33cd87a98..ecc9896a5 100644
--- a/test/screens/referral/referral_page_test.dart
+++ b/test/screens/referral/referral_page_test.dart
@@ -188,7 +188,7 @@ void main() {
expect(
find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
findsOneWidget,
);
@@ -196,7 +196,7 @@ void main() {
tester
.widget(
find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
)
.style
@@ -206,7 +206,7 @@ void main() {
expect(
find.ancestor(
of: find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
matching: find.byWidgetPredicate(
(widget) =>
@@ -237,7 +237,7 @@ void main() {
expect(
find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
findsOneWidget,
);
@@ -259,7 +259,7 @@ void main() {
expect(find.text('nope'), findsNothing);
expect(
find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
findsOneWidget,
);
@@ -283,7 +283,7 @@ void main() {
),
);
- expect(find.text('Deine Empfehlungen'), findsOneWidget);
+ expect(find.text('Ihre Empfehlungen'), findsOneWidget);
expect(find.text('Einladungslink erstellen'), findsOneWidget);
});
@@ -396,7 +396,7 @@ void main() {
await tester.pump();
await tester.pump();
- expect(find.text('Deine Empfehlungen'), findsOneWidget);
+ expect(find.text('Ihre Empfehlungen'), findsOneWidget);
});
testWidgets('accepting terms from the accepting state opens create-invite', (
diff --git a/test/screens/referral/referral_terms_page_test.dart b/test/screens/referral/referral_terms_page_test.dart
index e62d6c865..82366eb3a 100644
--- a/test/screens/referral/referral_terms_page_test.dart
+++ b/test/screens/referral/referral_terms_page_test.dart
@@ -194,13 +194,13 @@ void main() {
await tester.pump();
expect(
- find.text('Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.'),
+ find.text('Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.'),
findsOneWidget,
);
expect(
find.ancestor(
of: find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
matching: find.byWidgetPredicate(
(widget) => widget is Semantics && widget.properties.liveRegion == true,
@@ -310,7 +310,7 @@ void main() {
expect(
find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
findsOneWidget,
);
diff --git a/test/screens/settings/settings_referral_entry_test.dart b/test/screens/settings/settings_referral_entry_test.dart
index d252e29bc..99d4ebc3b 100644
--- a/test/screens/settings/settings_referral_entry_test.dart
+++ b/test/screens/settings/settings_referral_entry_test.dart
@@ -64,7 +64,7 @@ void main() {
await tester.pumpAndSettle();
expect(find.text('Empfehlungen'), findsOneWidget);
- expect(find.text('Erhalte 20 REALU pro Weiterempfehlung'), findsOneWidget);
+ expect(find.text('Erhalten Sie 20 REALU pro Weiterempfehlung'), findsOneWidget);
expect(
find.ancestor(
of: find.byIcon(Icons.card_giftcard_outlined),
@@ -106,6 +106,6 @@ void main() {
await tester.pump();
expect(find.text('Empfehlungen'), findsNothing);
- expect(find.text('Erhalte 20 REALU pro Weiterempfehlung'), findsNothing);
+ expect(find.text('Erhalten Sie 20 REALU pro Weiterempfehlung'), findsNothing);
});
}
diff --git a/test/setup/routing/referral_bind_test.dart b/test/setup/routing/referral_bind_test.dart
index 2f3695aea..629f95681 100644
--- a/test/setup/routing/referral_bind_test.dart
+++ b/test/setup/routing/referral_bind_test.dart
@@ -205,20 +205,20 @@ void main() {
await tester.pump();
await tester.pump();
- expect(find.text('Link ungültig oder abgelaufen'), findsOneWidget);
+ expect(find.text('Bereits ein Code eingelöst'), findsOneWidget);
expect(
- find.text('Du hast bereits einen Einladungs- oder Promo-Code eingelöst.'),
+ find.text('Sie haben bereits einen Einladungs- oder Promo-Code eingelöst.'),
findsOneWidget,
);
expect(
- tester.widget(find.text('Link ungültig oder abgelaufen')).style?.color,
+ tester.widget(find.text('Bereits ein Code eingelöst')).style?.color,
RealUnitColors.status.red600,
);
expect(
tester
.widget(
find.text(
- 'Du hast bereits einen Einladungs- oder Promo-Code eingelöst.',
+ 'Sie haben bereits einen Einladungs- oder Promo-Code eingelöst.',
),
)
.style
@@ -228,7 +228,7 @@ void main() {
await tester.tapAt(const Offset(2, 2));
await tester.pump();
expect(
- find.text('Du hast bereits einen Einladungs- oder Promo-Code eingelöst.'),
+ find.text('Sie haben bereits einen Einladungs- oder Promo-Code eingelöst.'),
findsOneWidget,
);
expect(
@@ -547,7 +547,7 @@ void main() {
expect(
find.text(
- 'Einladung von Björn erkannt. Björn erhält seine Prämie automatisch, sobald du verifiziert bist und deinen ersten Kauf abgeschlossen hast.',
+ 'Einladung von Björn erkannt. Björn erhält seine Prämie automatisch, sobald Sie verifiziert sind und Ihren ersten Kauf abgeschlossen haben.',
),
findsOneWidget,
);
@@ -716,7 +716,7 @@ void main() {
);
await bindPendingReferralCode(router);
- expect(find.text('Link ungültig oder abgelaufen'), findsNothing);
+ expect(find.text('Bereits ein Code eingelöst'), findsNothing);
await tester.pumpWidget(
MaterialApp.router(
@@ -734,7 +734,7 @@ void main() {
);
await tester.pump();
- expect(find.text('Link ungültig oder abgelaufen'), findsOneWidget);
+ expect(find.text('Bereits ein Code eingelöst'), findsOneWidget);
expect(
tester.widget(find.widgetWithText(TextButton, 'Schließen')).autofocus,
isTrue,
@@ -775,7 +775,7 @@ void main() {
expect(
find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
findsOneWidget,
);
@@ -791,7 +791,7 @@ void main() {
await tester.pump();
expect(
find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
findsOneWidget,
);
@@ -837,7 +837,7 @@ void main() {
expect(
find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
findsOneWidget,
);
@@ -883,7 +883,7 @@ void main() {
expect(
find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
findsOneWidget,
);
@@ -933,7 +933,7 @@ void main() {
expect(
find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
findsOneWidget,
);
@@ -944,7 +944,7 @@ void main() {
expect(
find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
findsNothing,
);
@@ -997,7 +997,7 @@ void main() {
expect(
find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
findsOneWidget,
);
@@ -1018,7 +1018,7 @@ void main() {
await pending;
expect(
find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
findsNothing,
);
@@ -1064,7 +1064,7 @@ void main() {
expect(
find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
findsOneWidget,
);
@@ -1129,7 +1129,7 @@ void main() {
expect(await peekPendingReferralCode(), 'NEWER1');
expect(
find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
findsOneWidget,
);
@@ -1184,7 +1184,7 @@ void main() {
await tester.pump();
await tester.pump();
- expect(find.text('Link ungültig oder abgelaufen'), findsOneWidget);
+ expect(find.text('Bereits ein Code eingelöst'), findsOneWidget);
expect(await peekPendingReferralCode(), isNull);
await tester.tap(find.text('Schließen'));
await tester.pumpAndSettle();
@@ -1209,7 +1209,7 @@ void main() {
expect(
find.text(
- 'Wir konnten den Code gerade nicht prüfen. Bitte versuche es später erneut.',
+ 'Wir konnten den Code gerade nicht prüfen. Bitte versuchen Sie es später erneut.',
),
findsNothing,
);
@@ -1312,7 +1312,7 @@ void main() {
await tester.pump();
await tester.pump();
- expect(find.text('Link ungültig oder abgelaufen'), findsOneWidget);
+ expect(find.text('Bereits ein Code eingelöst'), findsOneWidget);
expect(calls, 2);
await tester.tap(find.text('Schließen'));
await tester.pumpAndSettle();