@@ -11,8 +11,8 @@ import { TradfriClient } from "./tradfri-client";
1111import { ContentFormats } from "node-coap-client/build/ContentFormats" ;
1212import { MessageCode , MessageCodes } from "node-coap-client/build/Message" ;
1313import * as sinonChai from "sinon-chai" ;
14- import { createEmptyAccessoryResponse , createNetworkMock , createResponse , createRGBBulb , createErrorResponse } from "../test/mocks" ;
15- import { Accessory , Light , TradfriError , TradfriErrorCodes } from "./" ;
14+ import { createEmptyAccessoryResponse , createErrorResponse , createNetworkMock , createResponse , createRGBBulb } from "../test/mocks" ;
15+ import { Accessory , AccessoryTypes , Light , TradfriError , TradfriErrorCodes } from "./" ;
1616import { createDeferredPromise , DeferredPromise } from "./lib/defer-promise" ;
1717import { padStart } from "./lib/strings" ;
1818
@@ -25,7 +25,7 @@ function assertPayload(actual: any, expected: {}) {
2525 expect ( JSON . parse ( actual . toString ( ) ) ) . to . deep . equal ( expected ) ;
2626}
2727
28- describe ( "tradfri-client => surrounding functionality => " , ( ) => {
28+ describe ( "tradfri-client => infrastructure => " , ( ) => {
2929
3030 // Setup the mock
3131 const {
@@ -125,6 +125,33 @@ describe("tradfri-client => surrounding functionality => ", () => {
125125
126126 } ) ;
127127
128+ describe ( "ping =>" , ( ) => {
129+ it ( "should call coap.ping for the coap host" , ( ) => {
130+ tradfri . ping ( ) ;
131+ fakeCoap . ping . should . have . been . called ;
132+ } ) ;
133+
134+ it ( "should pass the correct arguments" , ( ) => {
135+ tradfri . ping ( ) ;
136+ fakeCoap . ping . should . have . been . calledWithExactly ( "coaps://localhost:5684/" , undefined ) ;
137+ fakeCoap . ping . resetHistory ( ) ;
138+
139+ tradfri . ping ( 500 ) ;
140+ fakeCoap . ping . should . have . been . calledWithExactly ( "coaps://localhost:5684/" , 500 ) ;
141+ fakeCoap . ping . resetHistory ( ) ;
142+ } ) ;
143+
144+ it ( "should pass through the returned promise" , async ( ) => {
145+ fakeCoap . ping . returns ( Promise . resolve ( true ) ) ;
146+ await tradfri . ping ( ) . should . become ( true ) ;
147+
148+ fakeCoap . ping . returns ( Promise . resolve ( false ) ) ;
149+ await tradfri . ping ( ) . should . become ( false ) ;
150+
151+ fakeCoap . ping . resetBehavior ( ) ;
152+ } ) ;
153+ } ) ;
154+
128155} ) ;
129156
130157describe ( "tradfri-client => observing resources => " , ( ) => {
@@ -158,9 +185,17 @@ describe("tradfri-client => observing resources => ", () => {
158185 fakeCoap . observe . should . not . have . been . called ;
159186 } ) ;
160187
161- it ( "calling it again with an absolute path should also not call coap.observe" , async ( ) => {
188+ it ( "calling it again with similar paths pointing to the same resource should also not call coap.observe" , async ( ) => {
162189 const cb = spy ( ) ;
163- await tradfri . observeResource ( "coaps://localhost:5684/15001" , cb ) ;
190+ await Promise . all (
191+ [
192+ "coaps://localhost:5684/15001" ,
193+ "coaps://localhost:5684/15001/" ,
194+ "/15001" ,
195+ "/15001/" ,
196+ "15001/" ,
197+ ] . map ( path => tradfri . observeResource ( path , cb ) ) ,
198+ ) ;
164199 fakeCoap . observe . should . not . have . been . called ;
165200 } ) ;
166201
@@ -313,7 +348,6 @@ describe("tradfri-client => observing devices => ", () => {
313348 } ) ;
314349 }
315350
316-
317351 } ) ;
318352
319353 describe ( "stopObservingDevices => " , ( ) => {
@@ -327,6 +361,29 @@ describe("tradfri-client => observing devices => ", () => {
327361 } ) ;
328362 } ) ;
329363
364+ describe ( "observeDevices (with errors) => " , ( ) => {
365+ it ( "should be rejected when one of the device callbacks receives an invalid response" , async ( ) => {
366+
367+ // the error spy has to be used our chai fails our test
368+ const errorSpy = spy ( ) ;
369+ tradfri . on ( "error" , errorSpy ) ;
370+
371+ const devicesPromise = tradfri . observeDevices ( ) ;
372+ const devices = [ 65536 ] ;
373+ await callbacks . observeDevices ( createResponse ( devices ) ) ;
374+
375+ // we intercepted the device_callback, so we need to manually call it
376+ // now for the following tests to work
377+ await callbacks . observeDevice [ 65536 ] ( createErrorResponse ( MessageCodes . clientError . forbidden ) ) ;
378+
379+ errorSpy . should . have . been . called ;
380+ tradfri . removeAllListeners ( ) ;
381+
382+ // now the deferred promise should have been rejected
383+ await devicesPromise . should . be . rejectedWith ( "could not be observed" ) ;
384+ } ) ;
385+ } ) ;
386+
330387} ) ;
331388
332389describe ( "tradfri-client => updating resources => " , ( ) => {
@@ -370,7 +427,7 @@ describe("tradfri-client => updating resources => ", () => {
370427 light = lightAccessory . lightList [ 0 ] ;
371428 }
372429
373- describe ( "updateResource => " , ( ) => {
430+ describe ( "updateDevice => " , ( ) => {
374431
375432 beforeEach ( resetDeviceInfrastructure ) ;
376433
@@ -394,6 +451,20 @@ describe("tradfri-client => updating resources => ", () => {
394451 } ] ,
395452 } ) ;
396453 } ) ;
454+
455+ it ( "calling it with a non-observed device should throw" , ( ) => {
456+ const nonExisting = lightAccessory . clone ( ) ;
457+ nonExisting . instanceId = 12345 ;
458+ expect ( ( ) => tradfri . updateDevice ( nonExisting ) ) . to . throw ( "is not known" ) ;
459+ } ) ;
460+ } ) ;
461+
462+ describe ( "operateLight => " , ( ) => {
463+ it ( "should throw when called with a non-light accessory" , ( ) => {
464+ const notALight = new Accessory ( ) ;
465+ notALight . type = AccessoryTypes . remote ;
466+ expect ( ( ) => tradfri . operateLight ( notALight , { } ) ) . to . throw ( "must be a lightbulb" ) ;
467+ } ) ;
397468 } ) ;
398469
399470} ) ;
@@ -453,5 +524,43 @@ describe("tradfri-client => custom requests => ", () => {
453524 actualResponse . code . should . equal ( response . code . toString ( ) ) ;
454525 actualResponse . payload . should . deep . equal ( responsePayload ) ;
455526 } ) ;
527+
528+ it ( "responses with content-format 0 or without one should be parsed as a string" , async ( ) => {
529+ const expected = "HALLO" ;
530+ const stringResponse = createResponse ( expected , undefined , ContentFormats . text_plain ) ;
531+
532+ fakeCoap . request . returns ( Promise . resolve ( stringResponse ) ) ;
533+ await tradfri . request ( null , null ) . should . be . fulfilled . then (
534+ resp => expect ( resp . payload ) . to . be . a ( "string" ) . and . equal ( expected ) ,
535+ ) ;
536+
537+ stringResponse . format = null ;
538+ fakeCoap . request . returns ( Promise . resolve ( stringResponse ) ) ;
539+ await tradfri . request ( null , null ) . should . be . fulfilled . then (
540+ resp => expect ( resp . payload ) . to . be . a ( "string" ) . and . equal ( expected ) ,
541+ ) ;
542+
543+ fakeCoap . request . resetBehavior ( ) ;
544+ } ) ;
545+
546+ it ( "responses with any other content format should pass the raw Buffer through" , async ( ) => {
547+ for ( const contentFormat of [
548+ ContentFormats . application_octetStream ,
549+ ContentFormats . application_exi ,
550+ ContentFormats . application_linkFormat ,
551+ ContentFormats . application_xml ,
552+ ] ) {
553+ const expected = Buffer . from ( "unknown" ) ;
554+ const jsonResponse = createResponse ( expected , undefined , ContentFormats . application_octetStream ) ;
555+
556+ fakeCoap . request . returns ( Promise . resolve ( jsonResponse ) ) ;
557+ await tradfri . request ( null , null ) . should . be . fulfilled . then (
558+ resp => expect ( resp . payload ) . to . be . an . instanceof ( Buffer )
559+ . and . deep . equal ( expected ) ,
560+ ) ;
561+
562+ fakeCoap . request . resetBehavior ( ) ;
563+ }
564+ } ) ;
456565 } ) ;
457566} ) ;
0 commit comments