Neuer GastZugang-Service für den anonymen YouTube-Gast-Zugang
Analog zu BakaAuth, aber ohne Passwort: holt/speichert einen geräte-gebundenen Gast-Token vom neuen /api/guest-token-Endpunkt (siehe docs/superpowers/specs/2026-08-26-youtube-guest-quota-design.md). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_$(uuidgen | cut -d- -f1)
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
eee94467a0
commit
2e14256ded
@@ -0,0 +1,120 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:http/testing.dart';
|
||||
import 'package:melo/services/baka_auth.dart';
|
||||
import 'package:melo/services/gast_zugang.dart';
|
||||
|
||||
class _MemorySpeicher implements TokenSpeicher {
|
||||
final Map<String, String> werte = {};
|
||||
@override
|
||||
Future<String?> lesen(String key) async => werte[key];
|
||||
@override
|
||||
Future<void> schreiben(String key, String wert) async => werte[key] = wert;
|
||||
@override
|
||||
Future<void> loeschen(String key) async => werte.remove(key);
|
||||
}
|
||||
|
||||
void main() {
|
||||
test('Ohne Token ist gastHeader leer', () {
|
||||
final gast = GastZugang(
|
||||
client: MockClient((_) async => http.Response('', 500)),
|
||||
speicher: _MemorySpeicher(),
|
||||
);
|
||||
|
||||
expect(gast.hatToken, isFalse);
|
||||
expect(gast.gastHeader, isEmpty);
|
||||
});
|
||||
|
||||
test('holeToken() speichert den Token bei Erfolg', () async {
|
||||
final speicher = _MemorySpeicher();
|
||||
final gast = GastZugang(
|
||||
client: MockClient(
|
||||
(_) async => http.Response(jsonEncode({'guest_token': 'g-1'}), 200)),
|
||||
speicher: speicher,
|
||||
);
|
||||
|
||||
final fehler = await gast.holeToken();
|
||||
|
||||
expect(fehler, isNull);
|
||||
expect(gast.hatToken, isTrue);
|
||||
expect(gast.gastHeader, {'X-Guest-Token': 'g-1'});
|
||||
expect(speicher.werte['guest_token'], 'g-1');
|
||||
});
|
||||
|
||||
test('holeToken() meldet einen Fehler bei einer toten Verbindung',
|
||||
() async {
|
||||
final gast = GastZugang(
|
||||
client: MockClient((_) async => throw Exception('down')),
|
||||
speicher: _MemorySpeicher(),
|
||||
);
|
||||
|
||||
final fehler = await gast.holeToken();
|
||||
|
||||
expect(fehler, 'Proxy nicht erreichbar');
|
||||
expect(gast.hatToken, isFalse);
|
||||
});
|
||||
|
||||
test('holeToken() meldet einen Fehler bei einem Server-Fehlerstatus',
|
||||
() async {
|
||||
final gast = GastZugang(
|
||||
client: MockClient((_) async => http.Response('', 500)),
|
||||
speicher: _MemorySpeicher(),
|
||||
);
|
||||
|
||||
final fehler = await gast.holeToken();
|
||||
|
||||
expect(fehler, 'Gast-Zugang fehlgeschlagen (500)');
|
||||
expect(gast.hatToken, isFalse);
|
||||
});
|
||||
|
||||
test('holeToken() meldet einen Fehler bei unlesbarer Antwort', () async {
|
||||
final gast = GastZugang(
|
||||
client: MockClient((_) async => http.Response('nicht json', 200)),
|
||||
speicher: _MemorySpeicher(),
|
||||
);
|
||||
|
||||
final fehler = await gast.holeToken();
|
||||
|
||||
expect(fehler, 'Proxy antwortet unverständlich (200)');
|
||||
expect(gast.hatToken, isFalse);
|
||||
});
|
||||
|
||||
test('holeToken() meldet einen Fehler ohne guest_token-Feld', () async {
|
||||
final gast = GastZugang(
|
||||
client: MockClient((_) async => http.Response(jsonEncode({}), 200)),
|
||||
speicher: _MemorySpeicher(),
|
||||
);
|
||||
|
||||
final fehler = await gast.holeToken();
|
||||
|
||||
expect(fehler, 'Proxy hat keinen Gast-Token geliefert');
|
||||
expect(gast.hatToken, isFalse);
|
||||
});
|
||||
|
||||
test('laden() stellt einen gespeicherten Gast-Token wieder her', () async {
|
||||
final speicher = _MemorySpeicher();
|
||||
speicher.werte['guest_token'] = 'g-alt';
|
||||
final gast = GastZugang(
|
||||
client: MockClient((_) async => http.Response('', 500)),
|
||||
speicher: speicher,
|
||||
);
|
||||
|
||||
await gast.laden();
|
||||
|
||||
expect(gast.hatToken, isTrue);
|
||||
expect(gast.gastHeader, {'X-Guest-Token': 'g-alt'});
|
||||
});
|
||||
|
||||
test('merkeVerbleibend übernimmt den zuletzt gemeldeten Stand', () {
|
||||
final gast = GastZugang(
|
||||
client: MockClient((_) async => http.Response('', 500)),
|
||||
speicher: _MemorySpeicher(),
|
||||
);
|
||||
|
||||
gast.merkeVerbleibend(3);
|
||||
|
||||
expect(gast.verbleibend, 3);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user