mirror of
https://github.com/wkulhanek/bonob.git
synced 2025-12-21 17:33:29 +01:00
Ability to remove a bonob registration from sonos (#16)
This commit is contained in:
@@ -48,7 +48,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rm -Rf build",
|
"clean": "rm -Rf build",
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"dev": "BONOB_PORT=4000 BONOB_URL=http://$(hostname):4000 BONOB_SONOS_SERVICE_NAME=bonobDev BONOB_SONOS_DEVICE_DISCOVERY=false BONOB_SONOS_AUTO_REGISTER=false nodemon ./src/app.ts",
|
"dev": "BONOB_PORT=4000 BONOB_URL=http://$(hostname):4000 BONOB_SONOS_SERVICE_NAME=bonobDev BONOB_SONOS_DEVICE_DISCOVERY=true BONOB_SONOS_AUTO_REGISTER=false nodemon ./src/app.ts",
|
||||||
"register-dev": "ts-node ./src/register.ts http://$(hostname):4000",
|
"register-dev": "ts-node ./src/register.ts http://$(hostname):4000",
|
||||||
"test": "jest"
|
"test": "jest"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ import {
|
|||||||
PRESENTATION_MAP_ROUTE,
|
PRESENTATION_MAP_ROUTE,
|
||||||
SONOS_RECOMMENDED_IMAGE_SIZES,
|
SONOS_RECOMMENDED_IMAGE_SIZES,
|
||||||
LOGIN_ROUTE,
|
LOGIN_ROUTE,
|
||||||
REGISTER_ROUTE,
|
CREATE_REGISTRATION_ROUTE,
|
||||||
|
REMOVE_REGISTRATION_ROUTE
|
||||||
} from "./smapi";
|
} from "./smapi";
|
||||||
import { LinkCodes, InMemoryLinkCodes } from "./link_codes";
|
import { LinkCodes, InMemoryLinkCodes } from "./link_codes";
|
||||||
import { MusicService, isSuccess } from "./music_service";
|
import { MusicService, isSuccess } from "./music_service";
|
||||||
@@ -95,7 +96,8 @@ function server(
|
|||||||
services,
|
services,
|
||||||
bonobService: service,
|
bonobService: service,
|
||||||
registeredBonobService,
|
registeredBonobService,
|
||||||
registerRoute: bonobUrl.append({ pathname: REGISTER_ROUTE }).pathname(),
|
createRegistrationRoute: bonobUrl.append({ pathname: CREATE_REGISTRATION_ROUTE }).pathname(),
|
||||||
|
removeRegistrationRoute: bonobUrl.append({ pathname: REMOVE_REGISTRATION_ROUTE }).pathname(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -110,7 +112,7 @@ function server(
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post(REGISTER_ROUTE, (_, res) => {
|
app.post(CREATE_REGISTRATION_ROUTE, (_, res) => {
|
||||||
sonos.register(service).then((success) => {
|
sonos.register(service).then((success) => {
|
||||||
if (success) {
|
if (success) {
|
||||||
res.render("success", {
|
res.render("success", {
|
||||||
@@ -124,6 +126,20 @@ function server(
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.post(REMOVE_REGISTRATION_ROUTE, (_, res) => {
|
||||||
|
sonos.remove(service.sid).then((success) => {
|
||||||
|
if (success) {
|
||||||
|
res.render("success", {
|
||||||
|
message: `Successfully removed registration`,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
res.status(500).render("failure", {
|
||||||
|
message: `Failed to remove registration!`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
app.get(LOGIN_ROUTE, (req, res) => {
|
app.get(LOGIN_ROUTE, (req, res) => {
|
||||||
res.render("login", {
|
res.render("login", {
|
||||||
bonobService: service,
|
bonobService: service,
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ import { Clock } from "./clock";
|
|||||||
import { URLBuilder } from "./url_builder";
|
import { URLBuilder } from "./url_builder";
|
||||||
|
|
||||||
export const LOGIN_ROUTE = "/login";
|
export const LOGIN_ROUTE = "/login";
|
||||||
export const REGISTER_ROUTE = "/register";
|
export const CREATE_REGISTRATION_ROUTE = "/registration/add";
|
||||||
|
export const REMOVE_REGISTRATION_ROUTE = "/registration/remove";
|
||||||
export const SOAP_PATH = "/ws/sonos";
|
export const SOAP_PATH = "/ws/sonos";
|
||||||
export const STRINGS_ROUTE = "/sonos/strings.xml";
|
export const STRINGS_ROUTE = "/sonos/strings.xml";
|
||||||
export const PRESENTATION_MAP_ROUTE = "/sonos/presentationMap.xml";
|
export const PRESENTATION_MAP_ROUTE = "/sonos/presentationMap.xml";
|
||||||
|
|||||||
91
src/sonos.ts
91
src/sonos.ts
@@ -61,14 +61,14 @@ export const bonobService = (
|
|||||||
): Service => ({
|
): Service => ({
|
||||||
name,
|
name,
|
||||||
sid,
|
sid,
|
||||||
uri: bonobUrl.append({pathname: SOAP_PATH }).href(),
|
uri: bonobUrl.append({ pathname: SOAP_PATH }).href(),
|
||||||
secureUri: bonobUrl.append({pathname: SOAP_PATH }).href(),
|
secureUri: bonobUrl.append({ pathname: SOAP_PATH }).href(),
|
||||||
strings: {
|
strings: {
|
||||||
uri: bonobUrl.append({pathname: STRINGS_ROUTE }).href(),
|
uri: bonobUrl.append({ pathname: STRINGS_ROUTE }).href(),
|
||||||
version: PRESENTATION_AND_STRINGS_VERSION,
|
version: PRESENTATION_AND_STRINGS_VERSION,
|
||||||
},
|
},
|
||||||
presentation: {
|
presentation: {
|
||||||
uri: bonobUrl.append({pathname: PRESENTATION_MAP_ROUTE }).href(),
|
uri: bonobUrl.append({ pathname: PRESENTATION_MAP_ROUTE }).href(),
|
||||||
version: PRESENTATION_AND_STRINGS_VERSION,
|
version: PRESENTATION_AND_STRINGS_VERSION,
|
||||||
},
|
},
|
||||||
pollInterval: 1200,
|
pollInterval: 1200,
|
||||||
@@ -78,12 +78,14 @@ export const bonobService = (
|
|||||||
export interface Sonos {
|
export interface Sonos {
|
||||||
devices: () => Promise<Device[]>;
|
devices: () => Promise<Device[]>;
|
||||||
services: () => Promise<Service[]>;
|
services: () => Promise<Service[]>;
|
||||||
|
remove: (sid: number) => Promise<boolean>;
|
||||||
register: (service: Service) => Promise<boolean>;
|
register: (service: Service) => Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SONOS_DISABLED: Sonos = {
|
export const SONOS_DISABLED: Sonos = {
|
||||||
devices: () => Promise.resolve([]),
|
devices: () => Promise.resolve([]),
|
||||||
services: () => Promise.resolve([]),
|
services: () => Promise.resolve([]),
|
||||||
|
remove: (_: number) => Promise.resolve(true),
|
||||||
register: (_: Service) => Promise.resolve(true),
|
register: (_: Service) => Promise.resolve(true),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -111,6 +113,11 @@ export const asDevice = (sonosDevice: SonosDevice): Device => ({
|
|||||||
port: sonosDevice.Port,
|
port: sonosDevice.Port,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const asRemoveCustomdForm = (csrfToken: string, sid: number) => ({
|
||||||
|
csrfToken,
|
||||||
|
sid: `${sid}`
|
||||||
|
});
|
||||||
|
|
||||||
export const asCustomdForm = (csrfToken: string, service: Service) => ({
|
export const asCustomdForm = (csrfToken: string, service: Service) => ({
|
||||||
csrfToken,
|
csrfToken,
|
||||||
sid: `${service.sid}`,
|
sid: `${service.sid}`,
|
||||||
@@ -158,6 +165,44 @@ export function autoDiscoverySonos(sonosSeedHost?: string): Sonos {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const post = async (action: string, customdForm: (csrfToken: string) => any) => {
|
||||||
|
const anyDevice = await sonosDevices().then((devices) => head(devices));
|
||||||
|
|
||||||
|
if (!anyDevice) {
|
||||||
|
logger.warn("Failed to find a device to register with...");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
`${action} using sonos device ${anyDevice.Name} @ ${anyDevice.Host}`
|
||||||
|
);
|
||||||
|
|
||||||
|
const customd = `http://${anyDevice.Host}:${anyDevice.Port}/customsd`;
|
||||||
|
|
||||||
|
const csrfToken = await axios.get(customd).then((response) =>
|
||||||
|
parse(response.data)
|
||||||
|
.querySelectorAll("input")
|
||||||
|
.find((it) => it.getAttribute("name") == "csrfToken")
|
||||||
|
?.getAttribute("value")
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!csrfToken) {
|
||||||
|
logger.warn(
|
||||||
|
`Failed to find csrfToken at GET -> ${customd}, cannot ${action} service`
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const form = customdForm(csrfToken)
|
||||||
|
logger.info(`${action} with sonos @ ${customd}`, { form });
|
||||||
|
return axios
|
||||||
|
.post(customd, new URLSearchParams(qs.stringify(form)), {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((response) => response.status == 200);
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
devices: async () => sonosDevices().then((it) => it.map(asDevice)),
|
devices: async () => sonosDevices().then((it) => it.map(asDevice)),
|
||||||
|
|
||||||
@@ -170,43 +215,9 @@ export function autoDiscoverySonos(sonosSeedHost?: string): Sonos {
|
|||||||
)
|
)
|
||||||
.then((it) => it.map(asService)),
|
.then((it) => it.map(asService)),
|
||||||
|
|
||||||
register: async (service: Service) => {
|
remove: async (sid: number) => post("remove", (csrfToken) => asRemoveCustomdForm(csrfToken, sid)),
|
||||||
const anyDevice = await sonosDevices().then((devices) => head(devices));
|
|
||||||
|
|
||||||
if (!anyDevice) {
|
register: async (service: Service) => post("register", (csrfToken) => asCustomdForm(csrfToken, service)),
|
||||||
logger.warn("Failed to find a device to register with...");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info(
|
|
||||||
`Registering ${service.name}(SID:${service.sid}) with sonos device ${anyDevice.Name} @ ${anyDevice.Host}`
|
|
||||||
);
|
|
||||||
|
|
||||||
const customd = `http://${anyDevice.Host}:${anyDevice.Port}/customsd`;
|
|
||||||
|
|
||||||
const csrfToken = await axios.get(customd).then((response) =>
|
|
||||||
parse(response.data)
|
|
||||||
.querySelectorAll("input")
|
|
||||||
.find((it) => it.getAttribute("name") == "csrfToken")
|
|
||||||
?.getAttribute("value")
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!csrfToken) {
|
|
||||||
logger.warn(
|
|
||||||
`Failed to find csrfToken at GET -> ${customd}, cannot register service`
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const customdForm = asCustomdForm(csrfToken, service);
|
|
||||||
logger.info(`Registering with sonos @ ${customd}`, { customdForm });
|
|
||||||
return axios
|
|
||||||
.post(customd, new URLSearchParams(qs.stringify(customdForm)), {
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/x-www-form-urlencoded",
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then((response) => response.status == 200);
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -224,6 +224,7 @@ describe("server", () => {
|
|||||||
devices: () => Promise.resolve([device1, device2]),
|
devices: () => Promise.resolve([device1, device2]),
|
||||||
services: () =>
|
services: () =>
|
||||||
Promise.resolve([service1, service2, service3, service4]),
|
Promise.resolve([service1, service2, service3, service4]),
|
||||||
|
remove: () => Promise.resolve(false),
|
||||||
register: () => Promise.resolve(false),
|
register: () => Promise.resolve(false),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -285,6 +286,7 @@ describe("server", () => {
|
|||||||
const fakeSonos: Sonos = {
|
const fakeSonos: Sonos = {
|
||||||
devices: () => Promise.resolve([]),
|
devices: () => Promise.resolve([]),
|
||||||
services: () => Promise.resolve([service1, service2, bonobService]),
|
services: () => Promise.resolve([service1, service2, bonobService]),
|
||||||
|
remove: () => Promise.resolve(false),
|
||||||
register: () => Promise.resolve(false),
|
register: () => Promise.resolve(false),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -340,6 +342,7 @@ describe("server", () => {
|
|||||||
describe("/register", () => {
|
describe("/register", () => {
|
||||||
const sonos = {
|
const sonos = {
|
||||||
register: jest.fn(),
|
register: jest.fn(),
|
||||||
|
remove: jest.fn(),
|
||||||
};
|
};
|
||||||
const theService = aService({
|
const theService = aService({
|
||||||
name: "We can all live a life of service",
|
name: "We can all live a life of service",
|
||||||
@@ -352,35 +355,71 @@ describe("server", () => {
|
|||||||
new InMemoryMusicService()
|
new InMemoryMusicService()
|
||||||
);
|
);
|
||||||
|
|
||||||
describe("when is successful", () => {
|
describe("registering", () => {
|
||||||
it("should return a nice message", async () => {
|
describe("when is successful", () => {
|
||||||
sonos.register.mockResolvedValue(true);
|
it("should return a nice message", async () => {
|
||||||
|
sonos.register.mockResolvedValue(true);
|
||||||
|
|
||||||
const res = await request(server)
|
const res = await request(server)
|
||||||
.post(bonobUrl.append({ pathname: "/register" }).path())
|
.post(bonobUrl.append({ pathname: "/registration/add" }).path())
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).toEqual(200);
|
expect(res.status).toEqual(200);
|
||||||
expect(res.text).toMatch("Successfully registered");
|
expect(res.text).toMatch("Successfully registered");
|
||||||
|
|
||||||
expect(sonos.register.mock.calls.length).toEqual(1);
|
expect(sonos.register.mock.calls.length).toEqual(1);
|
||||||
expect(sonos.register.mock.calls[0][0]).toBe(theService);
|
expect(sonos.register.mock.calls[0][0]).toBe(theService);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when is unsuccessful", () => {
|
||||||
|
it("should return a failure message", async () => {
|
||||||
|
sonos.register.mockResolvedValue(false);
|
||||||
|
|
||||||
|
const res = await request(server)
|
||||||
|
.post(bonobUrl.append({ pathname: "/registration/add" }).path())
|
||||||
|
.send();
|
||||||
|
|
||||||
|
expect(res.status).toEqual(500);
|
||||||
|
expect(res.text).toMatch("Registration failed!");
|
||||||
|
|
||||||
|
expect(sonos.register.mock.calls.length).toEqual(1);
|
||||||
|
expect(sonos.register.mock.calls[0][0]).toBe(theService);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("when is unsuccessful", () => {
|
describe("removing a registration", () => {
|
||||||
it("should return a failure message", async () => {
|
describe("when is successful", () => {
|
||||||
sonos.register.mockResolvedValue(false);
|
it("should return a nice message", async () => {
|
||||||
|
sonos.remove.mockResolvedValue(true);
|
||||||
|
|
||||||
const res = await request(server)
|
const res = await request(server)
|
||||||
.post(bonobUrl.append({ pathname: "/register" }).path())
|
.post(bonobUrl.append({ pathname: "/registration/remove" }).path())
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
expect(res.status).toEqual(500);
|
expect(res.status).toEqual(200);
|
||||||
expect(res.text).toMatch("Registration failed!");
|
expect(res.text).toMatch("Successfully removed registration");
|
||||||
|
|
||||||
expect(sonos.register.mock.calls.length).toEqual(1);
|
expect(sonos.remove.mock.calls.length).toEqual(1);
|
||||||
expect(sonos.register.mock.calls[0][0]).toBe(theService);
|
expect(sonos.remove.mock.calls[0][0]).toBe(theService.sid);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when is unsuccessful", () => {
|
||||||
|
it("should return a failure message", async () => {
|
||||||
|
sonos.remove.mockResolvedValue(false);
|
||||||
|
|
||||||
|
const res = await request(server)
|
||||||
|
.post(bonobUrl.append({ pathname: "/registration/remove" }).path())
|
||||||
|
.send();
|
||||||
|
|
||||||
|
expect(res.status).toEqual(500);
|
||||||
|
expect(res.text).toMatch("Failed to remove registration!");
|
||||||
|
|
||||||
|
expect(sonos.remove.mock.calls.length).toEqual(1);
|
||||||
|
expect(sonos.remove.mock.calls[0][0]).toBe(theService.sid);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import sonos, {
|
|||||||
Service,
|
Service,
|
||||||
PRESENTATION_AND_STRINGS_VERSION,
|
PRESENTATION_AND_STRINGS_VERSION,
|
||||||
BONOB_CAPABILITIES,
|
BONOB_CAPABILITIES,
|
||||||
|
asRemoveCustomdForm,
|
||||||
} from "../src/sonos";
|
} from "../src/sonos";
|
||||||
|
|
||||||
import { aSonosDevice, aService } from "./builders";
|
import { aSonosDevice, aService } from "./builders";
|
||||||
@@ -259,6 +260,18 @@ describe("sonos", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("asRemoveCustomdForm", () => {
|
||||||
|
it("should return a form", () => {
|
||||||
|
const csrfToken = uuid();
|
||||||
|
const sid = 123;
|
||||||
|
|
||||||
|
expect(asRemoveCustomdForm(csrfToken, sid)).toEqual({
|
||||||
|
csrfToken,
|
||||||
|
sid: "123"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("when is disabled", () => {
|
describe("when is disabled", () => {
|
||||||
it("should return a disabled client", async () => {
|
it("should return a disabled client", async () => {
|
||||||
const disabled = sonos(false);
|
const disabled = sonos(false);
|
||||||
@@ -684,4 +697,170 @@ describe("sonos", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("removing a service", () => {
|
||||||
|
const device1 = aSonosDevice({
|
||||||
|
Name: "d1",
|
||||||
|
Host: "127.0.0.11",
|
||||||
|
Port: 111,
|
||||||
|
});
|
||||||
|
|
||||||
|
const device2 = aSonosDevice({
|
||||||
|
Name: "d2",
|
||||||
|
});
|
||||||
|
|
||||||
|
const POST_CONFIG = {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const sidToRemove = 333;
|
||||||
|
|
||||||
|
const mockGet = jest.fn();
|
||||||
|
const mockPost = jest.fn();
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
mockGet.mockClear();
|
||||||
|
mockPost.mockClear();
|
||||||
|
|
||||||
|
axios.get = mockGet;
|
||||||
|
axios.post = mockPost;
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when successful", () => {
|
||||||
|
it("should post the remove into the first found sonos device, returning true", async () => {
|
||||||
|
const sonosManager = {
|
||||||
|
InitializeWithDiscovery: jest.fn(),
|
||||||
|
Devices: [device1, device2],
|
||||||
|
};
|
||||||
|
|
||||||
|
mockSonosManagerConstructor.mockReturnValue(
|
||||||
|
(sonosManager as unknown) as SonosManager
|
||||||
|
);
|
||||||
|
sonosManager.InitializeWithDiscovery.mockResolvedValue(true);
|
||||||
|
|
||||||
|
const csrfToken = `csrfToken-${uuid()}`;
|
||||||
|
|
||||||
|
mockGet.mockResolvedValue({
|
||||||
|
status: 200,
|
||||||
|
data: `<html><input name='csrfToken' value='${csrfToken}'></html>`,
|
||||||
|
});
|
||||||
|
mockPost.mockResolvedValue({ status: 200, data: "" });
|
||||||
|
|
||||||
|
const result = await sonos().remove(sidToRemove);
|
||||||
|
|
||||||
|
expect(mockGet).toHaveBeenCalledWith(
|
||||||
|
`http://${device1.Host}:${device1.Port}/customsd`
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(mockPost).toHaveBeenCalledWith(
|
||||||
|
`http://${device1.Host}:${device1.Port}/customsd`,
|
||||||
|
new URLSearchParams(qs.stringify(asRemoveCustomdForm(csrfToken, sidToRemove))),
|
||||||
|
POST_CONFIG
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result).toEqual(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when cannot find any devices", () => {
|
||||||
|
it("should return false", async () => {
|
||||||
|
const sonosManager = {
|
||||||
|
InitializeWithDiscovery: jest.fn(),
|
||||||
|
Devices: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
mockSonosManagerConstructor.mockReturnValue(
|
||||||
|
(sonosManager as unknown) as SonosManager
|
||||||
|
);
|
||||||
|
sonosManager.InitializeWithDiscovery.mockResolvedValue(true);
|
||||||
|
|
||||||
|
const result = await sonos().remove(sidToRemove);
|
||||||
|
|
||||||
|
expect(mockGet).not.toHaveBeenCalled();
|
||||||
|
expect(mockPost).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
expect(result).toEqual(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when cannot get csrfToken", () => {
|
||||||
|
describe("when the token is missing", () => {
|
||||||
|
it("should return false", async () => {
|
||||||
|
const sonosManager = {
|
||||||
|
InitializeWithDiscovery: jest.fn(),
|
||||||
|
Devices: [device1, device2],
|
||||||
|
};
|
||||||
|
|
||||||
|
mockSonosManagerConstructor.mockReturnValue(
|
||||||
|
(sonosManager as unknown) as SonosManager
|
||||||
|
);
|
||||||
|
sonosManager.InitializeWithDiscovery.mockResolvedValue(true);
|
||||||
|
|
||||||
|
mockGet.mockResolvedValue({
|
||||||
|
status: 200,
|
||||||
|
data: `<html></html>`,
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await sonos().remove(sidToRemove);
|
||||||
|
|
||||||
|
expect(mockPost).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
expect(result).toEqual(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when the token call returns a non 200", () => {
|
||||||
|
it("should return false", async () => {
|
||||||
|
const sonosManager = {
|
||||||
|
InitializeWithDiscovery: jest.fn(),
|
||||||
|
Devices: [device1, device2],
|
||||||
|
};
|
||||||
|
|
||||||
|
mockSonosManagerConstructor.mockReturnValue(
|
||||||
|
(sonosManager as unknown) as SonosManager
|
||||||
|
);
|
||||||
|
sonosManager.InitializeWithDiscovery.mockResolvedValue(true);
|
||||||
|
|
||||||
|
mockGet.mockResolvedValue({
|
||||||
|
status: 400,
|
||||||
|
data: `<html></html>`,
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await sonos().remove(sidToRemove);
|
||||||
|
|
||||||
|
expect(mockPost).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
expect(result).toEqual(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when posting in the sid to delete fails", () => {
|
||||||
|
it("should return false", async () => {
|
||||||
|
const sonosManager = {
|
||||||
|
InitializeWithDiscovery: jest.fn(),
|
||||||
|
Devices: [device1, device2],
|
||||||
|
};
|
||||||
|
|
||||||
|
mockSonosManagerConstructor.mockReturnValue(
|
||||||
|
(sonosManager as unknown) as SonosManager
|
||||||
|
);
|
||||||
|
sonosManager.InitializeWithDiscovery.mockResolvedValue(true);
|
||||||
|
|
||||||
|
const csrfToken = `csrfToken-${uuid()}`;
|
||||||
|
|
||||||
|
mockGet.mockResolvedValue({
|
||||||
|
status: 200,
|
||||||
|
data: `<html><input name='csrfToken' value='${csrfToken}'></html>`,
|
||||||
|
});
|
||||||
|
mockPost.mockResolvedValue({ status: 500, data: "" });
|
||||||
|
|
||||||
|
const result = await sonos().remove(sidToRemove);
|
||||||
|
|
||||||
|
expect(result).toEqual(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -10,7 +10,8 @@
|
|||||||
<% } else { %>
|
<% } else { %>
|
||||||
<h3>No existing service registration</h3>
|
<h3>No existing service registration</h3>
|
||||||
<% } %>
|
<% } %>
|
||||||
<form action="<%= it.registerRoute %>" method="POST"><button>Re-register</button></form>
|
<form action="<%= it.createRegistrationRoute %>" method="POST"><button>Register</button></form>
|
||||||
|
<form action="<%= it.removeRegistrationRoute %>" method="POST"><button>Remove Registration</button></form>
|
||||||
<h2>Devices</h2>
|
<h2>Devices</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<% it.devices.forEach(function(d){ %>
|
<% it.devices.forEach(function(d){ %>
|
||||||
|
|||||||
Reference in New Issue
Block a user