fix: Gast-Zugang-Sperre, veralteter Token, Doppel-Tap, Hinweistext (Branch-Review)
Behebt die Findings aus dem abschließenden Gesamt-Branch-Review für feature/youtube-gast-zugang, alle in einem Rutsch: - KRITISCH: Gast-Modus war eine Einbahnstraße — einmal "Als Gast fortfahren" getippt, war _AnmeldeDialog (einziger Baka-Login-Einstieg, auch für Melo-Cloud-Sync) dauerhaft unerreichbar. Neu: GastZugang.verwerfen() plus "Anmelden"-Knopf neben der Gast-Statuszeile in beiden Screens. - WICHTIG: zugriffOk prüfte den rohen gast.hatToken statt istGastModus — ein alter Gast-Token konnte den Auto-Login-Rückfallweg für Server-User verdecken. istGastModus wird jetzt vor zugriffOk berechnet und dort verwendet. - WICHTIG: CHANGELOG ergänzt — der Server-Endpunkt POST /api/guest-token fehlt noch (separates Vorhaben). - Doppel-Tap-Schutz für den Gast-Button in beiden Screens. - Widersprüchlicher Hinweistext im YT-Suche-Tab (verlangte Baka-Login direkt über dem Gast-Button) korrigiert. - Zwei Gast-Tests in youtube_search_screen_test.dart bekommen jetzt echtes gast:-Wiring in YtSearchService/YtDownloadService. - 2 neue Regressionstests fürs Anmelden-Escape-Hatch. Getestet: volle Suite grün (602 Tests, 1 skipped, 0 failed), flutter analyze ohne Befund. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CcDiyJdVRqh1TtJk5JiabX
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
b32f3198f8
commit
d20f01adee
@@ -5,8 +5,47 @@ Format angelehnt an [Keep a Changelog](https://keepachangelog.com/de/1.0.0/).
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### 🐛 Gast-Zugang: Fixe aus dem Branch-Abschluss-Review (2026-08-26)
|
||||||
|
|
||||||
|
- 🔓 **Gast-Modus war eine Einbahnstraße.** Einmal "Als Gast fortfahren"
|
||||||
|
angetippt, blieb `gast.hatToken` dauerhaft `true` (Token steckt im
|
||||||
|
Secure Storage, wird bei jedem App-Start wiederhergestellt) — und damit
|
||||||
|
war `_AnmeldeDialog`, der EINZIGE Einstieg in der App für die
|
||||||
|
Baka-Anmeldung (auch für den Melo-Cloud-Sync-Login!), unerreichbar.
|
||||||
|
Neu: `GastZugang.verwerfen()` verwirft den Token wieder, und ein
|
||||||
|
"Anmelden"-Knopf neben der Gast-Statuszeile (Download-Tab und
|
||||||
|
YT-Suche-Tab) ruft ihn auf.
|
||||||
|
- 🔀 **Ein alter Gast-Token hat den Auto-Login-Rückfallweg für
|
||||||
|
Server-User verdeckt.** `zugriffOk` prüfte bisher den rohen
|
||||||
|
`gast.hatToken` statt `istGastModus` — ein Gerät, das früher mal als
|
||||||
|
Gast lief und jetzt als Server-User mit fehlgeschlagenem Auto-Login
|
||||||
|
dasteht, bekam die Fehlermeldung dazu nie zu sehen und lud still über
|
||||||
|
den (limitierten) Gast-Pfad. `istGastModus` wird jetzt vor `zugriffOk`
|
||||||
|
berechnet und dort statt des rohen Tokens verwendet.
|
||||||
|
(`lib/downloads/downloads_screen.dart`,
|
||||||
|
`lib/downloads/youtube_search_screen.dart`)
|
||||||
|
- ⏱️ **Doppel-Tap auf "Als Gast fortfahren" konnte zwei Anfragen
|
||||||
|
gleichzeitig auslösen.** Beide Screens sperren den Button jetzt während
|
||||||
|
`holeToken()` läuft (`_gastLaeuft`).
|
||||||
|
- 📝 **Widersprüchlicher Hinweistext im YT-Suche-Tab behoben** — der Text
|
||||||
|
über dem Gast-Button verlangte fälschlich eine Baka-Anmeldung.
|
||||||
|
- ⚠️ **CHANGELOG ergänzt:** der Abschnitt zum Gast-Zugang unten macht jetzt
|
||||||
|
klar, dass die Server-Seite (`POST /api/guest-token`) noch fehlt.
|
||||||
|
- ✅ **Getestet:** 2 neue Regressionstests fürs "Anmelden"-Escape-Hatch
|
||||||
|
(`test/downloads/online_screen_test.dart`,
|
||||||
|
`test/downloads/youtube_search_screen_test.dart`), 2 bestehende Gast-Tests
|
||||||
|
im YT-Suche-Tab jetzt mit echtem `gast:`-Wiring in
|
||||||
|
`YtSearchService`/`YtDownloadService`. Volle Suite grün, `flutter
|
||||||
|
analyze` ohne Befund.
|
||||||
|
|
||||||
### 📺👤 YouTube-Gast-Zugang: bewusste Wahl + Tages-Zähler (Download-Tab + YT-Suche-Tab) (2026-08-26)
|
### 📺👤 YouTube-Gast-Zugang: bewusste Wahl + Tages-Zähler (Download-Tab + YT-Suche-Tab) (2026-08-26)
|
||||||
|
|
||||||
|
- ⚠️ **Braucht noch die Server-Seite.** Der neue Endpunkt `POST
|
||||||
|
/api/guest-token` und die Quota-Logik in `yt_proxy.py` existieren noch
|
||||||
|
nicht (separates Vorhaben, siehe
|
||||||
|
`docs/superpowers/specs/2026-08-26-youtube-guest-quota-design.md`). Bis
|
||||||
|
die Server-Seite steht, liefert der "Als Gast fortfahren"-Button
|
||||||
|
zuverlässig einen 404-Fehler.
|
||||||
- 👤 **Echte Gäste (kein Baka-Konto, kein Melo-Server) sehen jetzt zwei
|
- 👤 **Echte Gäste (kein Baka-Konto, kein Melo-Server) sehen jetzt zwei
|
||||||
Buttons** statt nur der Anmeldung: "Beim Baka-Konto anmelden" und neu
|
Buttons** statt nur der Anmeldung: "Beim Baka-Konto anmelden" und neu
|
||||||
"Als Gast fortfahren (5 Downloads/Tag)". Der Gast-Button holt sich per
|
"Als Gast fortfahren (5 Downloads/Tag)". Der Gast-Button holt sich per
|
||||||
|
|||||||
@@ -619,6 +619,9 @@ class _YouTubeBereichState extends State<_YouTubeBereich> {
|
|||||||
/// Fehlertext, falls das Holen des Gast-Tokens scheitert.
|
/// Fehlertext, falls das Holen des Gast-Tokens scheitert.
|
||||||
String? _gastFehler;
|
String? _gastFehler;
|
||||||
|
|
||||||
|
/// Verhindert Mehrfach-Anfragen bei schnellem Doppel-Antippen.
|
||||||
|
bool _gastLaeuft = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@@ -690,11 +693,18 @@ class _YouTubeBereichState extends State<_YouTubeBereich> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _alsGastFortfahren() async {
|
Future<void> _alsGastFortfahren() async {
|
||||||
|
if (_gastLaeuft) return;
|
||||||
final gast = context.read<GastZugang>();
|
final gast = context.read<GastZugang>();
|
||||||
setState(() => _gastFehler = null);
|
setState(() {
|
||||||
|
_gastFehler = null;
|
||||||
|
_gastLaeuft = true;
|
||||||
|
});
|
||||||
final fehler = await gast.holeToken();
|
final fehler = await gast.holeToken();
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
if (fehler != null) setState(() => _gastFehler = fehler);
|
setState(() {
|
||||||
|
_gastLaeuft = false;
|
||||||
|
if (fehler != null) _gastFehler = fehler;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _herunterladen() async {
|
Future<void> _herunterladen() async {
|
||||||
@@ -755,10 +765,10 @@ class _YouTubeBereichState extends State<_YouTubeBereich> {
|
|||||||
// Anmeldung nachweislich fehlgeschlagen ist, bleibt der manuelle Weg
|
// Anmeldung nachweislich fehlgeschlagen ist, bleibt der manuelle Weg
|
||||||
// als Rückfalloption sichtbar — sonst gäbe es keinen Weg mehr zurück.
|
// als Rückfalloption sichtbar — sonst gäbe es keinen Weg mehr zurück.
|
||||||
// Ein Gast-Token zählt ebenfalls als Zugang, nur mit Tages-Limit.
|
// Ein Gast-Token zählt ebenfalls als Zugang, nur mit Tages-Limit.
|
||||||
|
final istGastModus = !_serverUser && !auth.istAngemeldet && gast.hatToken;
|
||||||
final zugriffOk = auth.istAngemeldet ||
|
final zugriffOk = auth.istAngemeldet ||
|
||||||
(_serverUser && !_autoLoginFehlgeschlagen) ||
|
(_serverUser && !_autoLoginFehlgeschlagen) ||
|
||||||
gast.hatToken;
|
istGastModus;
|
||||||
final istGastModus = !_serverUser && !auth.istAngemeldet && gast.hatToken;
|
|
||||||
|
|
||||||
return ListView(
|
return ListView(
|
||||||
padding: const EdgeInsets.fromLTRB(16, 12, 16, 24),
|
padding: const EdgeInsets.fromLTRB(16, 12, 16, 24),
|
||||||
@@ -794,7 +804,7 @@ class _YouTubeBereichState extends State<_YouTubeBereich> {
|
|||||||
icon: const Icon(Icons.person_outline),
|
icon: const Icon(Icons.person_outline),
|
||||||
label: const Text('Als Gast fortfahren (5 Downloads/Tag)',
|
label: const Text('Als Gast fortfahren (5 Downloads/Tag)',
|
||||||
style: TextStyle(fontSize: 16)),
|
style: TextStyle(fontSize: 16)),
|
||||||
onPressed: _alsGastFortfahren,
|
onPressed: _gastLaeuft ? null : _alsGastFortfahren,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (_gastFehler != null) ...[
|
if (_gastFehler != null) ...[
|
||||||
@@ -834,6 +844,10 @@ class _YouTubeBereichState extends State<_YouTubeBereich> {
|
|||||||
style: const TextStyle(color: MeloTheme.text2, fontSize: 13),
|
style: const TextStyle(color: MeloTheme.text2, fontSize: 13),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: gast.verwerfen,
|
||||||
|
child: const Text('Anmelden'),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
|
|||||||
@@ -38,6 +38,9 @@ class _YoutubeSearchScreenState extends State<YoutubeSearchScreen> {
|
|||||||
/// Fehlertext, falls das Holen des Gast-Tokens scheitert.
|
/// Fehlertext, falls das Holen des Gast-Tokens scheitert.
|
||||||
String? _gastFehler;
|
String? _gastFehler;
|
||||||
|
|
||||||
|
/// Verhindert Mehrfach-Anfragen bei schnellem Doppel-Antippen.
|
||||||
|
bool _gastLaeuft = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@@ -56,11 +59,18 @@ class _YoutubeSearchScreenState extends State<YoutubeSearchScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _alsGastFortfahren() async {
|
Future<void> _alsGastFortfahren() async {
|
||||||
|
if (_gastLaeuft) return;
|
||||||
final gast = context.read<GastZugang>();
|
final gast = context.read<GastZugang>();
|
||||||
setState(() => _gastFehler = null);
|
setState(() {
|
||||||
|
_gastFehler = null;
|
||||||
|
_gastLaeuft = true;
|
||||||
|
});
|
||||||
final fehler = await gast.holeToken();
|
final fehler = await gast.holeToken();
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
if (fehler != null) setState(() => _gastFehler = fehler);
|
setState(() {
|
||||||
|
_gastLaeuft = false;
|
||||||
|
if (fehler != null) _gastFehler = fehler;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -81,10 +91,10 @@ class _YoutubeSearchScreenState extends State<YoutubeSearchScreen> {
|
|||||||
final auth = context.watch<BakaAuth>();
|
final auth = context.watch<BakaAuth>();
|
||||||
final gast = context.watch<GastZugang>();
|
final gast = context.watch<GastZugang>();
|
||||||
final suche = context.watch<YtSearchService>();
|
final suche = context.watch<YtSearchService>();
|
||||||
|
final istGastModus = !_serverUser && !auth.istAngemeldet && gast.hatToken;
|
||||||
final zugriffOk = auth.istAngemeldet ||
|
final zugriffOk = auth.istAngemeldet ||
|
||||||
(_serverUser && !_autoLoginFehlgeschlagen) ||
|
(_serverUser && !_autoLoginFehlgeschlagen) ||
|
||||||
gast.hatToken;
|
istGastModus;
|
||||||
final istGastModus = !_serverUser && !auth.istAngemeldet && gast.hatToken;
|
|
||||||
|
|
||||||
return SafeArea(
|
return SafeArea(
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -116,8 +126,12 @@ class _YoutubeSearchScreenState extends State<YoutubeSearchScreen> {
|
|||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
|
||||||
child: Text(
|
child: Text(
|
||||||
'Die Suche läuft über den Baka-Server. Dafür brauchst du '
|
_serverUser
|
||||||
'deine Baka-Anmeldung (siehe Download-Tab).',
|
? 'Die Suche läuft über den Baka-Server. Dafür brauchst '
|
||||||
|
'du deine Baka-Anmeldung (siehe Download-Tab).'
|
||||||
|
: 'Die Suche läuft über den Baka-Server. Melde dich mit '
|
||||||
|
'deinem Baka-Konto an (siehe Download-Tab) oder '
|
||||||
|
'nutze sie eingeschränkt als Gast.',
|
||||||
style: const TextStyle(color: MeloTheme.text2, fontSize: 13),
|
style: const TextStyle(color: MeloTheme.text2, fontSize: 13),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -131,7 +145,7 @@ class _YoutubeSearchScreenState extends State<YoutubeSearchScreen> {
|
|||||||
icon: const Icon(Icons.person_outline),
|
icon: const Icon(Icons.person_outline),
|
||||||
label: const Text('Als Gast fortfahren (5 Downloads/Tag)',
|
label: const Text('Als Gast fortfahren (5 Downloads/Tag)',
|
||||||
style: TextStyle(fontSize: 16)),
|
style: TextStyle(fontSize: 16)),
|
||||||
onPressed: _alsGastFortfahren,
|
onPressed: _gastLaeuft ? null : _alsGastFortfahren,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -148,11 +162,21 @@ class _YoutubeSearchScreenState extends State<YoutubeSearchScreen> {
|
|||||||
if (istGastModus)
|
if (istGastModus)
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
|
||||||
child: Text(
|
child: Row(
|
||||||
gast.verbleibend == null
|
children: [
|
||||||
? 'Als Gast unterwegs (5 Downloads/Tag)'
|
Expanded(
|
||||||
: 'Als Gast unterwegs — noch ${gast.verbleibend} von 5 heute',
|
child: Text(
|
||||||
style: const TextStyle(color: MeloTheme.text2, fontSize: 13),
|
gast.verbleibend == null
|
||||||
|
? 'Als Gast unterwegs (5 Downloads/Tag)'
|
||||||
|
: 'Als Gast unterwegs — noch ${gast.verbleibend} von 5 heute',
|
||||||
|
style: const TextStyle(color: MeloTheme.text2, fontSize: 13),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: gast.verwerfen,
|
||||||
|
child: const Text('Anmelden'),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (suche.laeuft) const LinearProgressIndicator(),
|
if (suche.laeuft) const LinearProgressIndicator(),
|
||||||
|
|||||||
@@ -79,4 +79,15 @@ class GastZugang extends ChangeNotifier {
|
|||||||
_verbleibend = n;
|
_verbleibend = n;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Verwirft den Gast-Zugang wieder — nötig, damit ein Gast doch noch zum
|
||||||
|
/// Baka-Konto wechseln kann. Ohne das wäre `_AnmeldeDialog` (der einzige
|
||||||
|
/// Einstieg in der App für Baka-Login, auch für den Melo-Cloud-Sync)
|
||||||
|
/// dauerhaft unerreichbar, sobald einmal ein Gast-Token besteht.
|
||||||
|
Future<void> verwerfen() async {
|
||||||
|
_token = null;
|
||||||
|
_verbleibend = null;
|
||||||
|
await _speicher.loeschen(_tokenKey);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -334,4 +334,32 @@ void main() {
|
|||||||
expect(find.text('Gast-Zugang fehlgeschlagen (500)'), findsOneWidget);
|
expect(find.text('Gast-Zugang fehlgeschlagen (500)'), findsOneWidget);
|
||||||
expect(find.text('YouTube-Adresse'), findsNothing);
|
expect(find.text('YouTube-Adresse'), findsNothing);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets(
|
||||||
|
'Anmelden im Gast-Modus verwirft den Gast-Token und zeigt wieder die '
|
||||||
|
'Wahl', (tester) async {
|
||||||
|
final auth = BakaAuth(
|
||||||
|
client: MockClient((_) async => http.Response('', 500)),
|
||||||
|
speicher: _MemorySpeicher());
|
||||||
|
final gast = GastZugang(
|
||||||
|
client: MockClient((_) async =>
|
||||||
|
http.Response(jsonEncode({'guest_token': 'g-1'}), 200)),
|
||||||
|
speicher: _MemorySpeicher(),
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
_wrap(auth, db: db, categories: categories, gast: gast));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
await tester.tap(find.text('Als Gast fortfahren (5 Downloads/Tag)'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(find.text('YouTube-Adresse'), findsOneWidget);
|
||||||
|
|
||||||
|
await tester.tap(find.text('Anmelden'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
expect(find.text('Beim Baka-Konto anmelden'), findsOneWidget);
|
||||||
|
expect(find.text('YouTube-Adresse'), findsNothing);
|
||||||
|
expect(gast.hatToken, isFalse);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ void main() {
|
|||||||
db: db, auth: auth, search: search, download: download));
|
db: db, auth: auth, search: search, download: download));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
expect(find.textContaining('Baka-Anmeldung'), findsOneWidget);
|
expect(find.textContaining('Baka-Server'), findsOneWidget);
|
||||||
expect(find.text('Nach Musikvideos suchen'), findsOneWidget);
|
expect(find.text('Nach Musikvideos suchen'), findsOneWidget);
|
||||||
|
|
||||||
await db.close();
|
await db.close();
|
||||||
@@ -191,11 +191,15 @@ void main() {
|
|||||||
final auth = BakaAuth(
|
final auth = BakaAuth(
|
||||||
client: MockClient((_) async => http.Response('', 500)),
|
client: MockClient((_) async => http.Response('', 500)),
|
||||||
speicher: _MemorySpeicher());
|
speicher: _MemorySpeicher());
|
||||||
final search = YtSearchService(auth: auth);
|
final gast = GastZugang(
|
||||||
final download = YtDownloadService(auth: auth);
|
client: MockClient((_) async => http.Response('', 500)),
|
||||||
|
speicher: _MemorySpeicher(),
|
||||||
|
);
|
||||||
|
final search = YtSearchService(auth: auth, gast: gast);
|
||||||
|
final download = YtDownloadService(auth: auth, gast: gast);
|
||||||
|
|
||||||
await tester.pumpWidget(_wrap(
|
await tester.pumpWidget(_wrap(
|
||||||
db: db, auth: auth, search: search, download: download));
|
db: db, auth: auth, search: search, download: download, gast: gast));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
@@ -208,6 +212,34 @@ void main() {
|
|||||||
'Als Gast fortfahren blendet den Baka-Hinweis aus und zeigt den Zähler',
|
'Als Gast fortfahren blendet den Baka-Hinweis aus und zeigt den Zähler',
|
||||||
(tester) async {
|
(tester) async {
|
||||||
final db = MeloDb(NativeDatabase.memory());
|
final db = MeloDb(NativeDatabase.memory());
|
||||||
|
final auth = BakaAuth(
|
||||||
|
client: MockClient((_) async => http.Response('', 500)),
|
||||||
|
speicher: _MemorySpeicher());
|
||||||
|
final gast = GastZugang(
|
||||||
|
client: MockClient((_) async =>
|
||||||
|
http.Response(jsonEncode({'guest_token': 'g-1'}), 200)),
|
||||||
|
speicher: _MemorySpeicher(),
|
||||||
|
);
|
||||||
|
final search = YtSearchService(auth: auth, gast: gast);
|
||||||
|
final download = YtDownloadService(auth: auth, gast: gast);
|
||||||
|
|
||||||
|
await tester.pumpWidget(_wrap(
|
||||||
|
db: db, auth: auth, search: search, download: download, gast: gast));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
await tester.tap(find.text('Als Gast fortfahren (5 Downloads/Tag)'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
expect(find.textContaining('Baka-Anmeldung'), findsNothing);
|
||||||
|
expect(find.text('Als Gast unterwegs (5 Downloads/Tag)'), findsOneWidget);
|
||||||
|
|
||||||
|
await db.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets(
|
||||||
|
'Anmelden im Gast-Modus verwirft den Gast-Token und zeigt wieder den '
|
||||||
|
'Hinweis', (tester) async {
|
||||||
|
final db = MeloDb(NativeDatabase.memory());
|
||||||
final auth = BakaAuth(
|
final auth = BakaAuth(
|
||||||
client: MockClient((_) async => http.Response('', 500)),
|
client: MockClient((_) async => http.Response('', 500)),
|
||||||
speicher: _MemorySpeicher());
|
speicher: _MemorySpeicher());
|
||||||
@@ -225,10 +257,14 @@ void main() {
|
|||||||
|
|
||||||
await tester.tap(find.text('Als Gast fortfahren (5 Downloads/Tag)'));
|
await tester.tap(find.text('Als Gast fortfahren (5 Downloads/Tag)'));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
expect(find.textContaining('Baka-Anmeldung'), findsNothing);
|
|
||||||
expect(find.text('Als Gast unterwegs (5 Downloads/Tag)'), findsOneWidget);
|
expect(find.text('Als Gast unterwegs (5 Downloads/Tag)'), findsOneWidget);
|
||||||
|
|
||||||
|
await tester.tap(find.text('Anmelden'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
expect(find.textContaining('Baka-Server'), findsOneWidget);
|
||||||
|
expect(gast.hatToken, isFalse);
|
||||||
|
|
||||||
await db.close();
|
await db.close();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user