diff --git a/src/server.ts b/src/server.ts index 179ed02..039fe95 100644 --- a/src/server.ts +++ b/src/server.ts @@ -25,7 +25,7 @@ const WSDL_FILE = path.resolve( function server( sonos: Sonos, bonobService: Service, - webAddress: string | "http://localhost:1234", + webAddress: string | "http://localhost:4534", musicService: MusicService, linkCodes: LinkCodes = new InMemoryLinkCodes() ): Express { @@ -58,8 +58,15 @@ function server( app.post("/register", (_, res) => { sonos.register(bonobService).then((success) => { - if (success) res.send("Yay"); - else res.send("boo hoo"); + if (success) { + res.render("success", { + message: `Successfully registered`, + }); + } else { + res.status(500).render("failure", { + message: `Registration failed!`, + }); + } }); }); @@ -79,7 +86,9 @@ function server( if (isSuccess(authResult)) { if (linkCodes.has(linkCode)) { linkCodes.associate(linkCode, authResult); - res.render("loginOK"); + res.render("success", { + message: `Login successful`, + }); } else { res.status(400).render("failure", { message: `Invalid linkCode!`, @@ -138,7 +147,7 @@ function server( .update(association.userId) .digest("hex"), }, - } + }, }; } else { throw { @@ -147,10 +156,10 @@ function server( faultstring: "Link Code not found retry...", detail: { ExceptionInfo: "NOT_LINKED_RETRY", - SonosError: "5" - } - } - } + SonosError: "5", + }, + }, + }; } }, getSessionId: ({ diff --git a/tests/builders.ts b/tests/builders.ts index ca0c658..eaa7c0c 100644 --- a/tests/builders.ts +++ b/tests/builders.ts @@ -7,8 +7,8 @@ const randomInt = (max: number) => Math.floor(Math.random() * max); const randomIpAddress = () => `127.0.${randomInt(255)}.${randomInt(255)}`; export const aService = (fields: Partial = {}): Service => ({ - name: `Test Music Service ${uuid()}`, sid: randomInt(500), + name: `Test Music Service ${uuid()}`, uri: "https://sonos-test.example.com/", secureUri: "https://sonos-test.example.com/", strings: { diff --git a/tests/index.test.ts b/tests/index.test.ts deleted file mode 100644 index cae9144..0000000 --- a/tests/index.test.ts +++ /dev/null @@ -1,122 +0,0 @@ -import request from "supertest"; -import makeServer from "../src/server"; -import { SONOS_DISABLED, Sonos, Device } from "../src/sonos"; - -import { aDevice, aService } from './builders'; -import { InMemoryMusicService } from "./in_memory_music_service"; - -describe("index", () => { - describe("when sonos integration is disabled", () => { - const server = makeServer(SONOS_DISABLED, aService(), 'http://localhost:1234', new InMemoryMusicService()); - - describe("devices list", () => { - it("should be empty", async () => { - const res = await request(server).get("/").send(); - - expect(res.status).toEqual(200); - expect(res.text).not.toMatch(/class=device/); - }); - }); - }); - - describe("when there are 2 devices and bonob is not registered", () => { - const service1 = aService({ - name: "s1", - sid: 1, - }); - const service2 = aService({ - name: "s2", - sid: 2, - }); - const service3 = aService({ - name: "s3", - sid: 3, - }); - const service4 = aService({ - name: "s4", - sid: 4, - }); - const missingBonobService = aService({ - name: "bonobMissing", - sid: 88 - }) - - const device1: Device = aDevice({ - name: "device1", - ip: "172.0.0.1", - port: 4301, - }); - - const device2: Device = aDevice({ - name: "device2", - ip: "172.0.0.2", - port: 4302, - }); - - const fakeSonos: Sonos = { - devices: () => Promise.resolve([device1, device2]), - services: () => Promise.resolve([service1, service2, service3, service4]), - register: () => Promise.resolve(false), - }; - - const server = makeServer(fakeSonos, missingBonobService, 'http://localhost:1234', new InMemoryMusicService()); - - 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\)/); - expect(res.text).toMatch(/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\)/); - expect(res.text).toMatch(/s2\s+\(2\)/); - expect(res.text).toMatch(/s3\s+\(3\)/); - 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(/No existing service registration/); - }); - }); - }); - - describe("when there are 2 devices and bonob is registered", () => { - const service1 = aService(); - - const service2 = aService(); - - const bonobService = aService({ - name: "bonobNotMissing", - sid: 99 - }) - - const fakeSonos: Sonos = { - devices: () => Promise.resolve([]), - services: () => Promise.resolve([service1, service2, bonobService]), - register: () => Promise.resolve(false), - }; - - const server = makeServer(fakeSonos, bonobService, 'http://localhost:1234', new InMemoryMusicService()); - - describe("registration status", () => { - it("should be registered", async () => { - const res = await request(server).get("/").send(); - expect(res.status).toEqual(200); - expect(res.text).toMatch(/Existing service config/); - }); - }); - }); -}); diff --git a/tests/scenarios.test.ts b/tests/scenarios.test.ts index aba1985..4a8ec52 100644 --- a/tests/scenarios.test.ts +++ b/tests/scenarios.test.ts @@ -57,7 +57,7 @@ class SonosDriver { .then(response => ({ expectSuccess: () => { expect(response.status).toEqual(200); - expect(response.text).toContain("Login Successful") + expect(response.text).toContain("Login successful") }, expectFailure: () => { expect(response.status).toEqual(403); @@ -95,7 +95,7 @@ describe("scenarios", () => { const username = "validuser"; const password = "validpassword"; - it("should successfully sign up", async () => { + it("should successfuly sign up", async () => { musicService.hasUser({ username, password }); await sonosDriver diff --git a/tests/server.test.ts b/tests/server.test.ts new file mode 100644 index 0000000..9294691 --- /dev/null +++ b/tests/server.test.ts @@ -0,0 +1,188 @@ +import request from "supertest"; +import makeServer from "../src/server"; +import { SONOS_DISABLED, Sonos, Device } from "../src/sonos"; + +import { aDevice, aService } from "./builders"; +import { InMemoryMusicService } from "./in_memory_music_service"; + +describe("server", () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe("/", () => { + describe("when sonos integration is disabled", () => { + const server = makeServer( + SONOS_DISABLED, + aService(), + "http://localhost:1234", + new InMemoryMusicService() + ); + + describe("devices list", () => { + it("should be empty", async () => { + const res = await request(server).get("/").send(); + + expect(res.status).toEqual(200); + expect(res.text).not.toMatch(/class=device/); + }); + }); + }); + + describe("when there are 2 devices and bonob is not registered", () => { + const service1 = aService({ + name: "s1", + sid: 1, + }); + const service2 = aService({ + name: "s2", + sid: 2, + }); + const service3 = aService({ + name: "s3", + sid: 3, + }); + const service4 = aService({ + name: "s4", + sid: 4, + }); + const missingBonobService = aService({ + name: "bonobMissing", + sid: 88, + }); + + const device1: Device = aDevice({ + name: "device1", + ip: "172.0.0.1", + port: 4301, + }); + + const device2: Device = aDevice({ + name: "device2", + ip: "172.0.0.2", + port: 4302, + }); + + const fakeSonos: Sonos = { + devices: () => Promise.resolve([device1, device2]), + services: () => + Promise.resolve([service1, service2, service3, service4]), + register: () => Promise.resolve(false), + }; + + const server = makeServer( + fakeSonos, + missingBonobService, + "http://localhost:1234", + new InMemoryMusicService() + ); + + 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\)/); + expect(res.text).toMatch(/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\)/); + expect(res.text).toMatch(/s2\s+\(2\)/); + expect(res.text).toMatch(/s3\s+\(3\)/); + 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(/No existing service registration/); + }); + }); + }); + + describe("when there are 2 devices and bonob is registered", () => { + const service1 = aService(); + + const service2 = aService(); + + const bonobService = aService({ + name: "bonobNotMissing", + sid: 99, + }); + + const fakeSonos: Sonos = { + devices: () => Promise.resolve([]), + services: () => Promise.resolve([service1, service2, bonobService]), + register: () => Promise.resolve(false), + }; + + const server = makeServer( + fakeSonos, + bonobService, + "http://localhost:1234", + new InMemoryMusicService() + ); + + describe("registration status", () => { + it("should be registered", async () => { + const res = await request(server).get("/").send(); + expect(res.status).toEqual(200); + expect(res.text).toMatch(/Existing service config/); + }); + }); + }); + }); + + describe("/register", () => { + const sonos = { + register: jest.fn(), + }; + const theService = aService({ + name: "We can all live a life of service", + sid: 999, + }); + const server = makeServer( + (sonos as unknown) as Sonos, + theService, + "http://localhost:1234", + new InMemoryMusicService() + ); + + describe("when is succesfull", () => { + it("should return a nice message", async () => { + sonos.register.mockResolvedValue(true); + + const res = await request(server).post("/register").send(); + + expect(res.status).toEqual(200); + expect(res.text).toMatch("Successfully registered"); + + expect(sonos.register.mock.calls.length).toEqual(1); + expect(sonos.register.mock.calls[0][0]).toBe(theService); + }); + }); + + describe("when is unsuccesfull", () => { + it("should return a failure message", async () => { + sonos.register.mockResolvedValue(false); + + const res = await request(server).post("/register").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); + }); + }); + }); +}); diff --git a/web/views/loginOK.eta b/web/views/loginOK.eta deleted file mode 100644 index 041121a..0000000 --- a/web/views/loginOK.eta +++ /dev/null @@ -1,5 +0,0 @@ -<% layout('./layout', { title: "Login Successful" }) %> - -
-

Login successful

-
\ No newline at end of file diff --git a/web/views/success.eta b/web/views/success.eta new file mode 100644 index 0000000..ecbc835 --- /dev/null +++ b/web/views/success.eta @@ -0,0 +1,5 @@ +<% layout('./layout', { title: "Yippee" }) %> + +
+

<%= it.message %>

+
\ No newline at end of file