• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

suculent / thinx-device-api / #252646768

01 Nov 2025 03:31PM UTC coverage: 46.298% (-25.7%) from 71.971%
#252646768

push

suculent
testing upgraded mqtt package

1123 of 3470 branches covered (32.36%)

Branch coverage included in aggregate %.

5324 of 10455 relevant lines covered (50.92%)

4.07 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

29.32
/spec/jasmine/ZZ-RouterDeviceAPISpec.js
1
/* Router integration test only; does not have to cover full unit functionality. */
2

3
const THiNX = require("../../thinx-core.js");
1✔
4

5
let chai = require('chai');
1✔
6
var expect = require('chai').expect;
1✔
7
let chaiHttp = require('chai-http');
1✔
8
var envi = require("../_envi.json");
1✔
9
chai.use(chaiHttp);
1✔
10

11
let thx;
12

13
describe("Device API (noauth)", function () {
1✔
14

15
    beforeAll((done) => {
1✔
16
        console.log(`🚸 [chai] >>> running Device API (noauth) spec`);
1✔
17
        thx = new THiNX();
1✔
18
        thx.init(() => {
1✔
19
            done();
×
20
        });
21
    });
22

23
    it("POST /device/register A", function (done) {
1✔
24
        chai.request(thx.app)
×
25
            .post('/device/register')
26
            .send()
27
            .end((err, res) => {
28
                console.log("🚸 [chai] POST /device/register A response:", res.text);
×
29
                expect(res.status).to.equal(400);
×
30
                //expect(res.text).to.be.a('string');
31
                done();
×
32
            });
33
    }, 30000);
34

35
    it("POST /device/register B", function (done) {
1✔
36
        chai.request(thx.app)
×
37
            .post('/device/register')
38
            .send({ registration: {} })
39
            .end((err, res) => {
40
                console.log("🚸 [chai] POST /device/register B response:", res.text);
×
41
                expect(res.status).to.equal(400);
×
42
                //expect(res.text).to.be.a('string');
43
                done();
×
44
            });
45
    }, 30000);
46

47
    // must be fully mocked or run after build completes
48
    it("POST /device/firmware", function (done) {
1✔
49
        chai.request(thx.app)
×
50
            .post('/device/firmware')
51
            .send({})
52
            .end((err, res) => {
53
                expect(res.status).to.equal(200);
×
54
                expect(res.text).to.be.a('string');
×
55
                //{"success":false,"response":"missing_mac"}
56
                done();
×
57
            });
58
    }, 30000);
59

60
    it("POST /device/firmware OTT request", function (done) {
1✔
61
        chai.request(thx.app)
×
62
            .post('/device/firmware')
63
            .send({ use: "ott"})
64
            .end((err, res) => {
65
                console.log("🚸 [chai] POST /device/firmware OTT request", res.text, res.status);
×
66
                expect(res.status).to.equal(200);
×
67
                expect(res.text).to.be.a('string');
×
68
                //{"success":false,"response":"missing_mac"}
69
                done();
×
70
            });
71
    }, 30000);
72

73
    it("POST /device/addpush", function (done) {
1✔
74
        chai.request(thx.app)
×
75
            .post('/device/addpush')
76
            .send({ push: "31b1f6bf498d7cec463ff2588aca59a52df6f880e60e8d4d6bcda0d8e6e87823" })
77
            .end((err, res) => {
78
                console.log("🚸 [chai] device add Push registration", res.text, res.status);
×
79
                expect(res.status).to.equal(403);
×
80
                //expect(res.text).to.be.a('string');
81
                done();
×
82
            });
83
    }, 30000);
84

85

86

87
    // POST /api/device/envs
88
    it("POST /api/device/envs", function (done) {
1✔
89
        chai.request(thx.app)
×
90
            .post('/api/device/envs')
91
            .send({})
92
            .end((err, res) => {
93
                expect(res.status).to.equal(401);
×
94
                done();
×
95
            });
96
    }, 30000);
97

98
    it("POST /api/device/detail", function (done) {
1✔
99
        chai.request(thx.app)
×
100
            .post('/api/device/detail')
101
            .send({})
102
            .end((err, res) => {
103
                expect(res.status).to.equal(401);
×
104
                done();
×
105
            });
106
    }, 30000);
107

108
    it("POST /api/device/edit", function (done) {
1✔
109
        chai.request(thx.app)
×
110
            .post('/api/device/edit')
111
            .send({ changes: { alias: "edited-alias" } })
112
            .end((err, res) => {
113
                expect(res.status).to.equal(401);
×
114
                done();
×
115
            });
116
    }, 30000);
117

118
    it("GET /device/firmware", function (done) {
1✔
119
        chai.request(thx.app)
×
120
            .get('/device/firmware?ott=foo')
121
            .end((err, res) => {
122
                expect(res.status).to.equal(200);
×
123
                expect(res.text).to.be.a('string');
×
124
                expect(res.text).to.equal('OTT_UPDATE_NOT_FOUND');
×
125
                done();
×
126
            });
127
    }, 30000);
128
});
129

130
//
131
// Authenticated (requires JWT login and creating valid API Key as well for /device/ requests)
132
//
133

134
describe("Device + API (JWT+Key)", function () {
1✔
135

136
    let agent;
137
    let jwt = null;
1✔
138
    let ak = null;
1✔
139

140
    beforeAll((done) => {
1✔
141
        console.log(`🚸 [chai] >>> running Device + API (JWT+Key) spec`);
1✔
142
        agent = chai.request.agent(thx.app);
1✔
143
        agent
1✔
144
            .post('/api/login')
145
            .send({ username: 'dynamic', password: 'dynamic', remember: false })
146
            .then(function (res) {
147
                expect(res).to.have.cookie('x-thx-core');
1✔
148
                let body = JSON.parse(res.text);
×
149
                jwt = 'Bearer ' + body.access_token;
×
150

151

152
                agent
×
153
                    .post('/api/user/apikey')
154
                    .set('Authorization', jwt)
155
                    .send({
156
                        'alias': 'mock-apikey-alias'
157
                    })
158
                    .end((err, res) => {
159
                        //  {"success":true,"api_key":"9b7bd4f4eacf63d8453b32dbe982eea1fb8bbc4fc8e3bcccf2fc998f96138629","hash":"0a920b2e99a917a04d7961a28b49d05524d10cd8bdc2356c026cfc1c280ca22c"}
160
                        console.log("🚸 [chai] POST /api/user/apikey (authenticated), response...");
×
161
                        expect(res.status).to.equal(200);
×
162
                        let j = JSON.parse(res.text);
×
163
                        expect(j.success).to.equal(true);
×
164
                        expect(j.response.api_key).to.be.a('string');
×
165
                        expect(j.response.hash).to.be.a('string');
×
166
                        ak = j.response.hash;
×
167
                        console.log("[spec] saving apikey's hash (3) for device testing", j.response.hash);
×
168
                        done();
×
169
                    });
170
            })
171
            .catch((e) => { console.log(e); });
1✔
172
    });
173

174
    afterAll((done) => {
1✔
175
        agent.close();
1✔
176
        console.log(`🚸 [chai] <<< completed Device + API (JWT+Key) spec`);
1✔
177
        done();
1✔
178
    });
179

180
    var JRS6 = {
1✔
181
        mac: "66:66:66:66:66:66",
182
        firmware: "ZZ-RouterDeviceApiSpec.js",
183
        version: "1.0.0",
184
        alias: "test-device-6-dynamic",
185
        owner: envi.dynamic.owner,
186
        platform: "arduino"
187
      };
188

189
    it("POST /device/register (jwt, invalid body)", function (done) {
1✔
190
        chai.request(thx.app)
×
191
            .post('/device/register')
192
            .set('Authentication', ak)
193
            .send({ registration: {} })
194
            .end((err, res) => {
195
                expect(res.status).to.equal(400);
×
196
                expect(res.text).to.be.a('string');
×
197
                let j = JSON.parse(res.text);
×
198
                expect(j.success).to.equal(false);
×
199
                done();
×
200
            });
201
    }, 30000);
202

203
    it("POST /device/register (jwt, valid) 6", function (done) {
1✔
204

205
        chai.request(thx.app)
×
206
          .post('/device/register')
207
          .set('Authentication', ak)
208
          .send({ registration: JRS6 })
209
          .end((err, res) => {
210
            console.log("🚸 [chai] POST /device/register (jwt, valid) 6 response:", res.text);
×
211
            expect(res.status).to.equal(200);
×
212
            let r = JSON.parse(res.text);
×
213
            console.log("🚸 [chai] POST /device/register (jwt, valid) 6 response:", JSON.stringify(r));
×
214
            JRS6.udid = r.registration.udid;
×
215
            expect(res.text).to.be.a('string');
×
216
            done();
×
217
          });
218
      }, 30000);
219

220
    // must be fully mocked or run after build completes
221
    it("POST /device/firmware (jwt, invalid)", function (done) {
1✔
222
        chai.request(thx.app)
×
223
            .post('/device/firmware')
224
            .set('Authentication', ak)
225
            .send({})
226
            .end((err, res) => {
227
                expect(res.status).to.equal(200);
×
228
                expect(res.text).to.be.a('string');
×
229
                //{"success":false,"response":"missing_mac"}
230
                done();
×
231
            });
232
    }, 30000);
233

234
    it("POST /device/addpush (jwt, invalid)", function (done) {
1✔
235
        chai.request(thx.app)
×
236
            .post('/device/addpush')
237
            .set('Authentication', ak)
238
            .send({})
239
            .end((err, res) => {
240
                expect(res.status).to.equal(200);
×
241
                //expect(res.text).to.be.a('string');
242
                done();
×
243
            });
244
    }, 30000);
245

246
    it("POST /device/addpush (jwt, valid)", function (done) {
1✔
247
        chai.request(thx.app)
×
248
            .post('/device/addpush')
249
            .set('Authentication', ak)
250
            .send({ push: "31b1f6bf498d7cec463ff2588aca59a52df6f880e60e8d4d6bcda0d8e6e87823", udid: envi.udid })
251
            .end((err, res) => {
252
                console.log("🚸 [chai] POST /device/addpush (jwt, valid)", res.status, res.text);
×
253
                expect(res.status).to.equal(200);
×
254
                //expect(res.text).to.equal('false'); // in case of no error
255
                done();
×
256
            });
257
    }, 30000);
258

259
    it("GET /device/firmware (ak, invalid)", function (done) {
1✔
260
        chai.request(thx.app)
×
261
            .get('/device/firmware?ott=foo')
262
            .end((err, res) => {
263
                console.log("🚸 [chai] GET /device/firmware (ak, invalid)", res.status, res.text);
×
264
                expect(res.status).to.equal(200);
×
265
                expect(res.text).to.be.a('string');
×
266
                expect(res.text).to.equal('OTT_UPDATE_NOT_FOUND');
×
267
                done();
×
268
            });
269
    }, 30000);
270

271
    it("GET /device/firmware (ak, none)", function (done) {
1✔
272
        chai.request(thx.app)
×
273
            .get('/device/firmware')
274
            .set('Authentication', ak)
275
            .end((err, res) => {
276
                console.log("🚸 [chai] GET /device/firmware (ak, none)", res.status, res.text);
×
277
                expect(res.status).to.equal(200);
×
278
                expect(res.text).to.be.a('string');
×
279
                expect(res.text).to.equal('{"success":false,"response":"OTT_MISSING"}');
×
280
                done();
×
281
            });
282
    }, 30000);
283

284
    it("GET /device/firmware (ak, valid)", function (done) {
1✔
285
        chai.request(thx.app)
×
286
            .get('/device/firmware?ott=foo')
287
            .set('Authentication', ak)
288
            .end((err, res) => {
289
                console.log("🚸 [chai] GET /device/firmware (ak, valid)", res.status, res.text);
×
290
                expect(res.status).to.equal(200);
×
291
                expect(res.text).to.be.a('string');
×
292
                expect(res.text).to.equal('OTT_UPDATE_NOT_FOUND');
×
293
                done();
×
294
            });
295
    }, 30000);
296

297
    // Device Control API
298

299
    it("POST /api/device/envs (jwt, invalid)", function (done) {
1✔
300
        chai.request(thx.app)
×
301
            .post('/api/device/envs')
302
            .set('Authorization', jwt)
303
            .send({})
304
            .end((err, res) => {
305
                console.log("🚸 [chai] POST /api/device/envs (jwt, invalid) response:", res.text, " status:", res.status);
×
306
                //expect(res.status).to.equal(200);
307
                //expect(res.text).to.be.a('string');
308
                done();
×
309
            });
310
    }, 30000);
311

312
    it("POST /api/device/envs (jwt, valid)", function (done) {
1✔
313
        chai.request(thx.app)
×
314
            .post('/api/device/envs')
315
            .set('Authorization', jwt)
316
            .send({ udid: JRS6.udid })
317
            .end((err, res) => {
318
                console.log("🚸 [chai] POST /api/device/envs (jwt, valid) response:", res.text, " status:", res.status);
×
319
                //expect(res.status).to.equal(200);
320
                //expect(res.text).to.be.a('string');
321
                done();
×
322
            });
323
    }, 30000);
324

325
    it("POST /api/device/detail (jwt, invalid)", function (done) {
1✔
326
        chai.request(thx.app)
×
327
            .post('/api/device/detail')
328
            .set('Authorization', jwt)
329
            .send({})
330
            .end((err, res) => {
331
                expect(res.status).to.equal(400);
×
332
                //expect(res.text).to.be.a('string');
333
                done();
×
334
            });
335
    }, 30000);
336

337
    it("POST /api/device/detail (jwt, valid)", function (done) {
1✔
338
        chai.request(thx.app)
×
339
            .post('/api/device/detail')
340
            .set('Authorization', jwt)
341
            .send({ udid: JRS6.udid })
342
            .end((err, res) => {
343
                expect(res.status).to.equal(200);
×
344
                expect(res.text).to.be.a('string');
×
345
                done();
×
346
            });
347
    }, 30000);
348

349
    it("POST /api/device/edit (jwt, invalid)", function (done) {
1✔
350
        chai.request(thx.app)
×
351
            .post('/api/device/edit')
352
            .set('Authentication', ak)
353
            .send({ changes: { alias: "edited-alias" } })
354
            .end((err, res) => {
355
                console.log("🚸 [chai] POST /api/device/edit (jwt, invalid) response:", res.text, "status", res.status);
×
356
                //expect(res.status).to.equal(401);
357
                done();
×
358
            });
359
    }, 30000);
360

361
    it("POST /api/device/edit (jwt, valid)", function (done) {
1✔
362
        chai.request(thx.app)
×
363
            .post('/api/device/edit')
364
            .set('Authentication', ak)
365
            .send({ changes: { alias: "edited-alias" }, udid: JRS6.udid })
366
            .end((err, res) => {
367
                console.log("🚸 [chai] POST /api/device/edit (jwt, valid) response:", res.text, " status:", res.status);
×
368
                //expect(res.status).to.equal(200);
369
                //expect(res.text).to.be.a('string');
370
                done();
×
371
            });
372
    }, 30000);
373

374
    //
375
    // Authenticated (Session)
376
    //
377

378
    it("POST /api/device/envs (session, invalid)", function (done) {
1✔
379
        agent
×
380
            .post('/api/device/envs')
381
            .send({})
382
            .end((err, res) => {
383
                console.log("🚸 [chai] POST /api/device/envs (session, invalid) response:", res.text, " status:", res.status);
×
384
                //expect(res.status).to.equal(401);
385
                done();
×
386
            });
387
    }, 30000);
388

389
    it("POST /api/device/envs (session, valid)", function (done) {
1✔
390
        agent
×
391
            .post('/api/device/envs')
392
            .send({ udid: envi.udid })
393
            .end((err, res) => {
394
                console.log("🚸 [chai] POST /api/device/envs (session, valid) response:", res.text, " status:", res.status);
×
395
                //expect(res.status).to.equal(200);
396
                //expect(res.text).to.be.a('string');
397
                done();
×
398
            });
399
    }, 30000);
400

401
    it("POST /api/device/envs (session, valid, no-such-device) 2", function (done) {
1✔
402
        agent
×
403
            .post('/api/device/envs')
404
            .send({ udid: envi.dynamic.udid })
405
            .end((err, res) => {
406
                console.log("🚸 [chai] POST /api/device/envs (session, valid) 2 response:", res.text, " status:", res.status);
×
407
                //expect(res.status).to.equal(200);
408
                //expect(res.text).to.be.a('string');
409
                done();
×
410
            });
411
    }, 30000);
412

413
    it("POST /api/device/detail (session, valid)", function (done) {
1✔
414
        agent
×
415
            .post('/api/device/detail')
416
            .send({})
417
            .end((err, res) => {
418
                console.log("🚸 [chai] POST /api/device/detail (session, valid) response:", res.text, " status:", res.status);
×
419
                //expect(res.status).to.equal(200);
420
                //expect(res.text).to.be.a('string');
421
                done();
×
422
            });
423
    }, 30000);
424

425
    it("POST /api/device/detail (session, dynamic)", function (done) {
1✔
426
        agent
×
427
            .post('/api/device/detail')
428
            .send({ udid: envi.dynamic.udid })
429
            .end((err, res) => {
430
                expect(res.status).to.equal(401);
×
431
                expect(res.text).to.be.a('string');
×
432
                done();
×
433
            });
434
    }, 30000);
435

436
    it("POST /api/device/detail (session, udid) 2", function (done) {
1✔
437
        agent
×
438
            .post('/api/device/detail')
439
            .send({ udid: envi.udid })
440
            .end((err, res) => {
441
                console.log("🚸 [chai] POST /api/device/detail (session, udid) 2 response:", res.text, " status:", res.status);
×
442
                done();
×
443
            });
444
    }, 30000);
445

446
    it("POST /api/device/edit (session, invalid)", function (done) {
1✔
447
        agent
×
448
            .post('/api/device/edit')
449
            .send({ changes: { alias: "edited-alias" } })
450
            .end((err, res) => {
451
                console.log("🚸 [chai] POST /api/device/edit (session, invalid) response:", res.text, " status:", res.status);
×
452
                done();
×
453
            });
454
    }, 30000);
455

456
    it("POST /api/device/edit (session, valid)", function (done) {
1✔
457
        agent
×
458
            .post('/api/device/edit')
459
            .send({ changes: { alias: "edited-alias" }, udid: JRS6.udid })
460
            .end((err, res) => {
461
                console.log("🚸 [chai] POST /api/device/edit (session, valid) response:", res.text, " status:", res.status);
×
462
                //expect(res.status).to.equal(200);
463
                //expect(res.text).to.be.a('string');
464
                done();
×
465
            });
466
    }, 30000);
467

468
    
469

470

471
});
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc