Files
Bose-SoundTouch/tests/integration/http-client/create_group.http
T
Tobias GesellchenandClaude Opus 4.8 41fccd6f1c 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>
2026-06-06 19:11:24 +02:00

73 lines
3.6 KiB
HTTP

### POST /streaming/account/{{accountId}}/group/ (Create Stereo Pair via Marge)
###
### Replays the exact shape a SoundTouch 10 master sends when it forwards the
### addGroup payload to its configured Marge server while forming a stereo pair
### (issue #252). Notable properties of the wire contract this exercises:
###
### * URL has a trailing slash ("/group/", not "/group").
### * <groupRole> elements have no <ipAddress>.
### * No <senderIPAddress> (this is the master-bound payload).
### * No numeric group <id> attribute and no <status> on the request.
### * Content-Type is the vendor-specific media type.
###
### The speaker retries this POST every 15 s while in AddingMaster state; if
### AfterTouch doesn't accept it, the group never completes and reverts to
### NoGroup after a timeout.
POST {{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
<?xml version="1.0" encoding="UTF-8" ?>
<group>
<masterDeviceId>{{deviceId}}</masterDeviceId>
<name>TEST</name>
<roles>
<groupRole>
<deviceId>{{deviceId}}</deviceId>
<role>LEFT</role>
</groupRole>
<groupRole>
<deviceId>{{macAddress2}}</deviceId>
<role>RIGHT</role>
</groupRole>
</roles>
</group>
> {%
client.test("Group created successfully", function() {
client.assert(response.status === 201, "Response status should be 201 Created, got " + response.status);
client.assert(response.contentType.mimeType === "application/vnd.bose.streaming-v1.2+xml",
"Response Content-Type should be application/vnd.bose.streaming-v1.2+xml, got '" + response.contentType.mimeType + "'");
client.assert(response.headers.valueOf("Location") !== null,
"Response should include a Location header pointing to the new group");
client.assert(response.headers.valueOf("Location").includes("/account/" + client.variables.environment.get("accountId") + "/group/"),
"Location header should reference the new group under the account, got '" + response.headers.valueOf("Location") + "'");
});
client.test("Response body echoes the requested group", function() {
const doc = response.body;
const group = doc.getElementsByTagName("group")[0];
client.assert(group !== undefined, "Response body should contain <group>");
const master = group.getElementsByTagName("masterDeviceId")[0];
client.assert(master !== undefined, "Response body should contain <masterDeviceId>");
client.assert(master.textContent === client.variables.environment.get("deviceId"),
"masterDeviceId should match the request, got '" + master.textContent + "'");
const name = group.getElementsByTagName("name")[0];
client.assert(name !== undefined, "Response body should contain <name>");
client.assert(name.textContent === "TEST", "name should match the requested 'TEST', got '" + name.textContent + "'");
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) : "");
})();
%}