diff --git a/src/server.ts b/src/server.ts index c83609d..3692ded 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,20 +1,23 @@ import express, { Express } from "express"; import * as Eta from "eta"; -import { Sonos, servicesFrom } from "./sonos"; +import { Sonos, servicesFrom, registrationStatus } from "./sonos"; function server(sonos: Sonos): Express { const app = express(); - app.use(express.static("./web/public")); + app.use(express.static("./web/public")); app.engine("eta", Eta.renderFile); + app.set("view engine", "eta"); app.set("views", "./web/views"); app.get("/", (_, res) => { sonos.devices().then(devices => { + const services = servicesFrom(devices) res.render("index", { devices, - services: servicesFrom(devices), + services, + registration: registrationStatus(services) }) }) }); diff --git a/src/sonos.ts b/src/sonos.ts index 2b38451..a987166 100644 --- a/src/sonos.ts +++ b/src/sonos.ts @@ -16,6 +16,13 @@ export type Service = { id: number; }; +export type BonobRegistrationStatus = 'registered' | 'not-registered' + +export const BONOB_SERVICE: Service = { + name: "bonob", + id: 245 +} + export interface Sonos { devices: () => Promise; } @@ -34,6 +41,14 @@ export const servicesFrom = (devices: Device[]) => "name" ); +export const registrationStatus = (services: Service[]): BonobRegistrationStatus => { + if(services.find(s => s.id == BONOB_SERVICE.id) != undefined) { + return "registered" + } else { + return "not-registered" + } +} + export const asDevice = (sonosDevice: SonosDevice): Promise => sonosDevice.MusicServicesService.ListAndParseAvailableServices().then( (services) => ({ diff --git a/tests/index.test.ts b/tests/index.test.ts index 4e1bea9..f43dfd6 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -1,6 +1,6 @@ import request from "supertest"; import makeServer from "../src/server"; -import { SONOS_DISABLED, Sonos, Device } from "../src/sonos"; +import { SONOS_DISABLED, Sonos, Device, BONOB_SERVICE } from "../src/sonos"; describe("index", () => { describe("when sonos integration is disabled", () => { @@ -16,42 +16,41 @@ describe("index", () => { }); }); - const device1 : Device = { - name: "device1", - group: "group1", - ip: "172.0.0.1", - port: 4301, - services: [ - { - name: "s1", - id: 1, - }, - { - name: "s2", - id: 2, - }, - ], - }; + describe("when there are 2 devices and bonob is not registered", () => { + const device1 : Device = { + name: "device1", + group: "group1", + ip: "172.0.0.1", + port: 4301, + services: [ + { + name: "s1", + id: 1, + }, + { + name: "s2", + id: 2, + }, + ], + }; + + const device2: Device = { + name: "device2", + group: "group2", + ip: "172.0.0.2", + port: 4302, + services: [ + { + name: "s3", + id: 3, + }, + { + name: "s4", + id: 4, + }, + ], + } - const device2: Device = { - name: "device2", - group: "group2", - ip: "172.0.0.2", - port: 4302, - services: [ - { - name: "s3", - id: 3, - }, - { - name: "s4", - id: 4, - }, - ], - } - - - describe("when sonos integration is enabled", () => { const fakeSonos: Sonos = { devices: () =>Promise.resolve([device1, device2]), }; @@ -61,7 +60,7 @@ describe("index", () => { describe("devices list", () => { it("should contain the devices returned from sonos", async () => { const res = await request(server).get("/").send(); - + expect(res.status).toEqual(200); expect(res.text).toMatch( /device1\s+\(172.0.0.1:4301\)/ @@ -70,10 +69,12 @@ describe("index", () => { /device2\s+\(172.0.0.2:4302\)/ ); }); - + }); + + describe("services", () => { it("should contain a list of services returned from sonos", async () => { const res = await request(server).get("/").send(); - + expect(res.status).toEqual(200); expect(res.text).toMatch(/Services\s+4/); expect(res.text).toMatch(/s1\s+\(1\)/); @@ -82,5 +83,69 @@ describe("index", () => { expect(res.text).toMatch(/s4\s+\(4\)/); }); }); + + describe("registration status", () => { + it("should be not-registered", async () => { + const res = await request(server).get("/").send(); + expect(res.status).toEqual(200); + expect(res.text).toMatch( + /Not registered/ + ); + }) + }); + }); + + describe("when there are 2 devices and bonob is registered", () => { + const device1 : Device = { + name: "device1", + group: "group1", + ip: "172.0.0.1", + port: 4301, + services: [ + { + name: "s1", + id: 1, + }, + { + name: "s2", + id: 2, + }, + BONOB_SERVICE + ], + }; + + const device2: Device = { + name: "device2", + group: "group2", + ip: "172.0.0.2", + port: 4302, + services: [ + { + name: "s1", + id: 1, + }, + { + name: "s4", + id: 4, + }, + BONOB_SERVICE + ], + } + + const fakeSonos: Sonos = { + devices: () =>Promise.resolve([device1, device2]), + }; + + const server = makeServer(fakeSonos); + + describe("registration status", () => { + it("should be registered", async () => { + const res = await request(server).get("/").send(); + expect(res.status).toEqual(200); + expect(res.text).toMatch( + /Registered/ + ); + }) + }); }); }); diff --git a/tests/sonos.test.ts b/tests/sonos.test.ts index 41da03d..92da265 100644 --- a/tests/sonos.test.ts +++ b/tests/sonos.test.ts @@ -1,12 +1,19 @@ import { SonosManager, SonosDevice } from "@svrooij/sonos"; import { MusicServicesService } from "@svrooij/sonos/lib/services"; -import { shuffle } from 'underscore'; +import { shuffle } from "underscore"; jest.mock("@svrooij/sonos"); import { AMAZON_MUSIC, APPLE_MUSIC, AUDIBLE } from "./music_services"; -import sonos, { SONOS_DISABLED, asDevice, Device, servicesFrom } from "../src/sonos"; +import sonos, { + SONOS_DISABLED, + asDevice, + Device, + servicesFrom, + registrationStatus, + BONOB_SERVICE, +} from "../src/sonos"; const mockSonosManagerConstructor = >SonosManager; @@ -15,6 +22,28 @@ describe("sonos", () => { mockSonosManagerConstructor.mockClear(); }); + describe("bonobRegistrationStatus", () => { + describe("when bonob is registered", () => { + it("should return 'registered'", () => { + expect( + registrationStatus([ + { id: 1, name: "not bonob" }, + BONOB_SERVICE, + { id: 2, name: "also not bonob" }, + ]) + ).toBe("registered"); + }); + }); + + describe("when bonob is not registered", () => { + it("should return not-registered", () => { + expect(registrationStatus([{ id: 1, name: "not bonob" }])).toBe( + "not-registered" + ); + }); + }); + }); + describe("asDevice", () => { it("should convert", async () => { const musicServicesService = { @@ -71,12 +100,19 @@ describe("sonos", () => { const service4 = { id: 4, name: "A" }; const d1 = someDevice({ services: shuffle([service1, service2]) }); - const d2 = someDevice({ services: shuffle([service1, service2, service3]) }); + const d2 = someDevice({ + services: shuffle([service1, service2, service3]), + }); const d3 = someDevice({ services: shuffle([service4]) }); const devices: Device[] = [d1, d2, d3]; - expect(servicesFrom(devices)).toEqual([service4, service2, service3, service1]) + expect(servicesFrom(devices)).toEqual([ + service4, + service2, + service3, + service1, + ]); }); }); diff --git a/web/views/index.eta b/web/views/index.eta index b5916b2..be8eba3 100644 --- a/web/views/index.eta +++ b/web/views/index.eta @@ -2,6 +2,11 @@

bonob

+ <% if(it.registration == "registered") { %> +

Registered

+ <% } else if(it.registration == "not-registered") { %> +

Not registered

+ <% } %>

Devices

    <% it.devices.forEach(function(d){ %>