Fix: Cloud-Playlists lassen sich nicht löschen (DELETE statt POST)

deletePlaylist() schickte ein POST auf /api/v1/cloud/playlists. Der Server
unterscheidet dort nach Methode (POST = anlegen, DELETE = löschen), also
landete das Löschen im Anlegen-Handler, scheiterte an der leeren
Namensprüfung und lieferte HTTP 200 mit `status: error` zurück.

Zusätzlich wurde der Rückgabewert in cloud_screen.dart ignoriert: die UI
meldete "Playlist gelöscht", während die Playlist auf dem Server bestehen
blieb und beim nächsten Sync wieder auftauchte.

- cloud_service.dart: DELETE mit id im Body, Fehler werden geloggt
- cloud_screen.dart: Rückgabewert auswerten statt pauschal Erfolg melden
- cloud_service_test.dart: 3 Regressionstests (Methode ist DELETE, id im
  Body, status != ok → false, Netzwerkfehler → false)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Hermes (Server)
2026-08-14 23:48:26 +02:00
co-authored by Claude Opus 5
parent 8f9ed1ff53
commit 22238138e8
3 changed files with 66 additions and 5 deletions
+39
View File
@@ -355,4 +355,43 @@ void main() {
expect(await cloud401.globalList(), isEmpty);
});
});
// Regression: deletePlaylist schickte ein POST auf /playlists. Der Server
// unterscheidet dort nach Methode (POST = anlegen, DELETE = löschen), also
// landete das Löschen im Anlegen-Handler, scheiterte an der leeren
// Namensprüfung und lieferte HTTP 200 mit `status: error`. Die UI meldete
// trotzdem Erfolg, die Playlist blieb bestehen.
group('deletePlaylist', () {
test('nutzt DELETE (nicht POST) und sendet die id im Body', () async {
String? methode;
String? body;
final cloud = CloudService(
client: MockClient((req) async {
methode = req.method;
body = req.body;
return jsonOk({'status': 'ok'});
}),
);
expect(await cloud.deletePlaylist(42), isTrue);
expect(methode, 'DELETE');
expect(jsonDecode(body!)['id'], 42);
});
test('status != ok → false (meldet keinen falschen Erfolg)', () async {
final cloud = CloudService(
client: MockClient(
(req) async => jsonOk({'status': 'error', 'error': 'Name erforderlich'})),
);
expect(await cloud.deletePlaylist(42), isFalse);
});
test('Netzwerkfehler → false (kein Crash)', () async {
final cloud = CloudService(
client: MockClient(
(req) async => throw http.ClientException('offline')),
);
expect(await cloud.deletePlaylist(42), isFalse);
});
});
}