Playlisten-Endpunkte fuer die einseitige Sicherung (ohne DELETE)
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
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/melo_cloud_service.dart';
|
||||
|
||||
class _MemorySpeicher implements TokenSpeicher {
|
||||
_MemorySpeicher(this.werte);
|
||||
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);
|
||||
}
|
||||
|
||||
Future<MeloCloudService> baue(
|
||||
Future<http.Response> Function(http.Request) antwort) async {
|
||||
final auth = BakaAuth(
|
||||
speicher: _MemorySpeicher({'baka_token': 'tok', 'baka_user': 'Baka'}),
|
||||
);
|
||||
await auth.laden();
|
||||
return MeloCloudService(auth: auth, client: MockClient(antwort));
|
||||
}
|
||||
|
||||
void main() {
|
||||
test('legePlaylistAn liefert die Server-ID', () async {
|
||||
final dienst = await baue((anfrage) async {
|
||||
expect(anfrage.method, 'POST');
|
||||
expect(anfrage.url.path, endsWith('/playlists'));
|
||||
expect(jsonDecode(anfrage.body), {'name': 'Road Trip'});
|
||||
// handle_playlist_create verpackt die ID unter „playlist" — genau so
|
||||
// antwortet der echte Server, und genau daran ist der Vertrag geknüpft.
|
||||
return http.Response(
|
||||
jsonEncode({
|
||||
'status': 'ok',
|
||||
'playlist': {'id': 7, 'name': 'Road Trip', 'song_count': 0}
|
||||
}),
|
||||
200,
|
||||
);
|
||||
});
|
||||
|
||||
expect(await dienst.legePlaylistAn('Road Trip'), '7');
|
||||
});
|
||||
|
||||
test('eine Antwort ohne playlist-Block ist ein Fehler', () async {
|
||||
// Die ID auf oberster Ebene zu suchen wäre der naheliegende Fehler; er
|
||||
// fiele am echten Server als „null" auf und sonst nirgends.
|
||||
final dienst = await baue(
|
||||
(_) async => http.Response(jsonEncode({'status': 'ok'}), 200));
|
||||
|
||||
expect(() => dienst.legePlaylistAn('Road Trip'),
|
||||
throwsA(isA<CloudException>()));
|
||||
});
|
||||
|
||||
test('ein Fehler im 200er-Körper wird geworfen', () async {
|
||||
final dienst = await baue((_) async =>
|
||||
http.Response(jsonEncode({'error': 'kein Name'}), 200));
|
||||
|
||||
expect(() => dienst.legePlaylistAn(''),
|
||||
throwsA(isA<CloudException>()));
|
||||
});
|
||||
|
||||
test('fuegePlaylistSongsHinzu meldet die Song-IDs', () async {
|
||||
Map<String, dynamic>? gesendet;
|
||||
final dienst = await baue((anfrage) async {
|
||||
expect(anfrage.url.path, endsWith('/playlists/7/songs'));
|
||||
gesendet = jsonDecode(anfrage.body) as Map<String, dynamic>;
|
||||
return http.Response(jsonEncode({'status': 'ok'}), 200);
|
||||
});
|
||||
|
||||
await dienst.fuegePlaylistSongsHinzu('7', ['c1', 'c2']);
|
||||
|
||||
expect(gesendet, {
|
||||
'song_ids': ['c1', 'c2']
|
||||
});
|
||||
});
|
||||
|
||||
test('entfernePlaylistSong benutzt DELETE auf dem Song-Pfad', () async {
|
||||
String? pfad;
|
||||
String? methode;
|
||||
final dienst = await baue((anfrage) async {
|
||||
pfad = anfrage.url.path;
|
||||
methode = anfrage.method;
|
||||
return http.Response(jsonEncode({'status': 'ok'}), 200);
|
||||
});
|
||||
|
||||
await dienst.entfernePlaylistSong('7', 'c1');
|
||||
|
||||
expect(methode, 'DELETE');
|
||||
expect(pfad, endsWith('/playlists/7/songs/c1'));
|
||||
});
|
||||
|
||||
test('setzePlaylistReihenfolge benutzt PUT auf /positions', () async {
|
||||
String? methode;
|
||||
Map<String, dynamic>? gesendet;
|
||||
final dienst = await baue((anfrage) async {
|
||||
methode = anfrage.method;
|
||||
expect(anfrage.url.path, endsWith('/playlists/7/positions'));
|
||||
gesendet = jsonDecode(anfrage.body) as Map<String, dynamic>;
|
||||
return http.Response(jsonEncode({'status': 'ok'}), 200);
|
||||
});
|
||||
|
||||
await dienst.setzePlaylistReihenfolge('7', ['c2', 'c1']);
|
||||
|
||||
expect(methode, 'PUT');
|
||||
// Der Router liest „positions", der Handler erwartet Paare. Unter
|
||||
// „song_ids" bekäme der Server eine leere Liste und antwortete stumm
|
||||
// „ok" — die Reihenfolge käme nie an, ohne jede Fehlermeldung.
|
||||
expect(gesendet, {
|
||||
'positions': [
|
||||
{'id': 'c2', 'position': 0},
|
||||
{'id': 'c1', 'position': 1},
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
test('playlisten liest Name und ID', () async {
|
||||
final dienst = await baue((_) async => http.Response(
|
||||
jsonEncode({
|
||||
'playlists': [
|
||||
{'id': 7, 'name': 'Road Trip'}
|
||||
]
|
||||
}),
|
||||
200,
|
||||
));
|
||||
|
||||
final listen = await dienst.playlisten();
|
||||
|
||||
expect(listen.single.id, '7');
|
||||
expect(listen.single.name, 'Road Trip');
|
||||
});
|
||||
|
||||
test('playlistSongs liefert die Song-IDs in Reihenfolge', () async {
|
||||
final dienst = await baue((_) async => http.Response(
|
||||
jsonEncode({
|
||||
'songs': [
|
||||
{'id': 'c1'},
|
||||
{'id': 'c2'},
|
||||
]
|
||||
}),
|
||||
200,
|
||||
));
|
||||
|
||||
expect(await dienst.playlistSongs('7'), ['c1', 'c2']);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user