mirror of
https://github.com/gesellix/Bose-SoundTouch.git
synced 2026-08-18 08:36:13 +00:00
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>
73 lines
3.6 KiB
HTTP
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) : "");
|
|
})();
|
|
%} |