Skip to content

Commit b6d046a

Browse files
committed
added tests for discovery
1 parent 9aaf2d0 commit b6d046a

4 files changed

Lines changed: 160 additions & 9 deletions

File tree

build/lib/discovery.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ function discoverGateway(timeout = 10000) {
1313
let timer;
1414
return new Promise((resolve, reject) => {
1515
const mdnsBrowser = bonjour.findOne({ type: "coap", protocol: "udp" }, (service) => {
16-
if (!service || !service.txt || !service.name.startsWith("gw-"))
16+
if (!service || !service.txt || !service.name || !service.name.startsWith("gw-"))
1717
return;
1818
if (timer != null)
1919
clearTimeout(timer);

src/lib/discovery.test.ts

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
// tslint:disable:no-console
2+
// tslint:disable:no-unused-expression
3+
// tslint:disable:variable-name
4+
5+
import { assert, expect, should, use } from "chai";
6+
import { SinonFakeTimers, spy, stub, useFakeTimers } from "sinon";
7+
import * as sinonChai from "sinon-chai";
8+
9+
// enable the should interface with sinon
10+
should();
11+
use(sinonChai);
12+
13+
let findOneCalled: DeferredPromise<void>;
14+
let findOneCallback: (service: any) => void;
15+
const fakeBrowser = {
16+
start: stub(),
17+
stop: stub(),
18+
};
19+
const fakeBonjour = {
20+
findOne: stub()
21+
// remember the given callback
22+
.callsFake((opts, cb) => {
23+
findOneCallback = cb;
24+
if (findOneCalled != null) findOneCalled.resolve();
25+
return fakeBrowser;
26+
}),
27+
};
28+
const fakeBonjourPackage = stub().returns(fakeBonjour);
29+
30+
// stub out the bonjour package for discovery
31+
import * as proxyquire from "proxyquire";
32+
import { createDeferredPromise, DeferredPromise } from "./defer-promise";
33+
import { wait } from "./promises";
34+
const { discoverGateway, DiscoveredGateway } = proxyquire("./discovery", {
35+
bonjour: fakeBonjourPackage,
36+
});
37+
38+
describe("lib/discovery => ", () => {
39+
40+
let clock: SinonFakeTimers;
41+
beforeEach(() => {
42+
clock = useFakeTimers();
43+
});
44+
45+
afterEach(() => {
46+
fakeBonjourPackage.resetHistory();
47+
fakeBonjour.findOne.resetHistory();
48+
fakeBrowser.start.resetHistory();
49+
fakeBrowser.stop.resetHistory();
50+
51+
clock.restore();
52+
});
53+
54+
it("discoverGateway lazily creates a bonjour instance", () => {
55+
discoverGateway(false);
56+
fakeBonjourPackage.should.have.been.calledOnce;
57+
discoverGateway(false);
58+
fakeBonjourPackage.should.have.been.calledOnce;
59+
});
60+
61+
it("discoverGateway creates an mDNS browser and starts the discovery", () => {
62+
discoverGateway(false);
63+
fakeBonjour.findOne.should.have.been.calledOnce;
64+
fakeBrowser.start.should.have.been.calledOnce;
65+
});
66+
67+
it("without a service response, discoverGateway() should fulfill with null after the default timeout has elapsed", (done) => {
68+
const timeout = 10000;
69+
70+
const leSpy = spy();
71+
discoverGateway().then(leSpy);
72+
wait(timeout - 1).then(() => {
73+
leSpy.should.not.have.been.called;
74+
wait(1).then(() => {
75+
leSpy.should.have.been.calledWith(null);
76+
done();
77+
});
78+
clock.tick(1);
79+
});
80+
clock.tick(timeout - 1);
81+
});
82+
83+
it("without a service response, discoverGateway(timeout) should fulfill with null after the passed timeout has elapsed", (done) => {
84+
const timeout = 5000;
85+
86+
const leSpy = spy();
87+
discoverGateway(timeout).then(leSpy);
88+
wait(timeout - 1).then(() => {
89+
leSpy.should.not.have.been.called;
90+
wait(1).then(() => {
91+
leSpy.should.have.been.calledWith(null);
92+
done();
93+
});
94+
clock.tick(1);
95+
});
96+
clock.tick(timeout - 1);
97+
});
98+
99+
it("without a service response, discoverGateway should never fulfill with the timeout disabled", (done) => {
100+
const spy1 = spy();
101+
const spy2 = spy();
102+
const oneDay = 1000 * 3600 * 24;
103+
104+
discoverGateway(false).then(spy1);
105+
wait(oneDay).then(() => {
106+
spy1.should.not.have.been.called;
107+
108+
discoverGateway(-1).then(spy2);
109+
wait(oneDay).then(() => {
110+
spy2.should.not.have.been.called;
111+
done();
112+
});
113+
clock.tick(oneDay);
114+
});
115+
clock.tick(oneDay);
116+
});
117+
118+
it("discoverGateway should check the received responses if they represent a tradfri gateway", (done) => {
119+
const leSpy = spy();
120+
findOneCalled = createDeferredPromise();
121+
const retVal = discoverGateway(false);
122+
retVal.then(leSpy);
123+
124+
// wait until we have a findOne callback
125+
findOneCalled.then(() => {
126+
// no service response
127+
findOneCallback(null);
128+
leSpy.should.not.have.been.called;
129+
130+
// service response without txt property
131+
findOneCallback({});
132+
leSpy.should.not.have.been.called;
133+
134+
// service response without name property
135+
findOneCallback({ txt: "foo" });
136+
leSpy.should.not.have.been.called;
137+
138+
// service response with wrong name property
139+
findOneCallback({ txt: "foo", name: "wrong" });
140+
leSpy.should.not.have.been.called;
141+
142+
// correct service response
143+
findOneCallback({
144+
name: "gw-abcdef123456",
145+
txt: { version: "1.2.3" },
146+
addresses: ["localhost"],
147+
});
148+
retVal.should.become({
149+
name: "gw-abcdef123456",
150+
version: "1.2.3",
151+
addresses: ["localhost"],
152+
}).then(() => done());
153+
});
154+
});
155+
156+
});

src/lib/discovery.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export interface DiscoveredGateway {
99

1010
/**
1111
* Auto-discover a tradfri gateway on the network.
12-
* @param timeout (optional) Time in milliseconds to wait for a response. Default 10000.
12+
* @param timeout (optional) Time in milliseconds to wait for a response. Default 10000.
1313
* Pass false or a negative number to explicitly wait forever.
1414
*/
1515
export function discoverGateway(timeout: number | false = 10000): Promise<DiscoveredGateway> {
@@ -20,7 +20,7 @@ export function discoverGateway(timeout: number | false = 10000): Promise<Discov
2020
const mdnsBrowser = bonjour.findOne(
2121
{ type: "coap", protocol: "udp" },
2222
(service: any) => {
23-
if (!service || !service.txt || !service.name.startsWith("gw-")) return;
23+
if (!service || !service.txt || !service.name || !service.name.startsWith("gw-")) return;
2424

2525
if (timer != null) clearTimeout(timer);
2626
const foundDevice = {
@@ -38,7 +38,7 @@ export function discoverGateway(timeout: number | false = 10000): Promise<Discov
3838
resolve(null);
3939
}, timeout);
4040
}
41-
41+
4242
mdnsBrowser.start();
4343
});
4444
}

test/mocks.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,6 @@
44

55
import { assert, expect, should, use } from "chai";
66
import { spy, stub } from "sinon";
7-
import * as sinonChai from "sinon-chai";
8-
9-
// enable the should interface with sinon
10-
should();
11-
use(sinonChai);
127

138
import { CoapClient as coap, CoapResponse } from "node-coap-client";
149
import { ContentFormats } from "node-coap-client/build/ContentFormats";

0 commit comments

Comments
 (0)