test(http-client): cover the group delete lifecycle (refs #451)

create_group.http now captures the new group id from the Location header into
{{groupId}}; delete_group.http then completes the lifecycle by removing that
group (DELETE /group/{groupId} -> 200 with <status>) and exercises the no-id,
account-level teardown form a speaker sends on factory reset
(DELETE /group/ -> 200). Inserted after get_group.http, before device teardown.

make test-http-client: 59 requests, 0 failed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Tobias Gesellchen
2026-06-06 19:11:24 +02:00
co-authored by Claude Opus 4.8
parent 603765b644
commit 41fccd6f1c
4 changed files with 50 additions and 2 deletions
+2 -2
View File
@@ -42,8 +42,8 @@ Legend: ✅ covered · ⬜ gap · 〰️ partial (some status/variant uncovered)
| GET | `/streaming/account/{a}/device/{d}/recents` | 200 | `get_recents.http` | ✅ |
| POST | `/streaming/account/{a}/source` | 200 | `set_preset_5.http` | ✅ |
| POST | `/streaming/account/{a}/group/` | 201 | `create_group.http` | ✅ |
| DELETE | `/streaming/account/{a}/group/` | 405 | (method-not-allowed edge) | ⬜ |
| DELETE | `/streaming/account/{a}/group/{id}` | 200 | | |
| DELETE | `/streaming/account/{a}/group/` | 200 | `delete_group.http` | ✅ (account-level teardown) |
| DELETE | `/streaming/account/{a}/group/{id}` | 200 | `delete_group.http` | |
| GET | `/streaming/device/{d}/streaming_token` | 200 | `get_streaming_token.http` | ✅ |
| GET | `/streaming/software/update/account/{a}` | 200 | `get_software_update.http` | ✅ |
| GET | `/streaming/sourceproviders` | 200 | `get_sourceproviders.http` | ✅ |
@@ -63,4 +63,11 @@ Accept: application/vnd.bose.streaming-v1.2+xml
const roles = group.getElementsByTagName("groupRole");
client.assert(roles.length === 2, "Response should contain exactly 2 <groupRole> entries, got " + roles.length);
});
// Capture the new group id (last path segment of the Location header) so the
// delete-group lifecycle step (delete_group.http) can remove this group.
(function () {
const loc = response.headers.valueOf("Location");
client.global.set("groupId", loc ? loc.substring(loc.lastIndexOf("/") + 1) : "");
})();
%}
@@ -0,0 +1,40 @@
### DELETE /streaming/account/{accountId}/group/{groupId} (remove a specific group)
###
### Completes the group lifecycle: create_group.http created the group and
### captured its id into {{groupId}}; this removes that group
### (HandleMargeDeleteGroup -> 200 with a <status> body). Runs after get_group.http
### and before the device teardown so the group exists when we delete it.
DELETE {{host}}/streaming/account/{{accountId}}/group/{{groupId}}
Content-Type: application/vnd.bose.streaming-v1.2+xml
Authorization: Bearer {{token}}
User-Agent: Bose_Lisa/27.0.6
Accept: application/vnd.bose.streaming-v1.2+xml
> {%
client.test("Group deleted (200)", function () {
client.assert(response.status === 200, "Response status is not 200, got " + response.status);
client.assert(response.contentType.mimeType === "application/vnd.bose.streaming-v1.2+xml",
"Expected application/vnd.bose.streaming-v1.2+xml, got '" + response.contentType.mimeType + "'");
});
client.test("Response body confirms deletion", function () {
client.assert(response.body.getElementsByTagName("status").length > 0,
"Response should contain a <status> element");
});
%}
### DELETE /streaming/account/{accountId}/group/ (account-level teardown, no id)
###
### The no-id, trailing-slash form a speaker sends to clear all of an account's
### groups (e.g. during a factory reset). HandleMargeDeleteAccountGroups -> 200.
DELETE {{host}}/streaming/account/{{accountId}}/group/
Content-Type: application/vnd.bose.streaming-v1.2+xml
Authorization: Bearer {{token}}
User-Agent: Bose_Lisa/27.0.6
Accept: application/vnd.bose.streaming-v1.2+xml
> {%
client.test("Account-level group teardown (200)", function () {
client.assert(response.status === 200, "Response status is not 200, got " + response.status);
});
%}