Initial release
[websub-hub] / test / src / db / sqlite.js
1 /* eslint-disable sonarjs/no-identical-functions */
2 /* eslint-env mocha */
3 /* eslint-disable sonarjs/no-duplicate-string */
4 'use strict';
5
6 /* This provides implementation coverage, stubbing parts of better-sqlite3. */
7
8 const assert = require('assert');
9 // eslint-disable-next-line node/no-unpublished-require
10 const sinon = require('sinon');
11 const DBStub = require('../../stub-db');
12 const stubLogger = require('../../stub-logger');
13 const DB = require('../../../src/db/sqlite');
14 const DBErrors = require('../../../src/db/errors');
15 const common = require('../../../src/common');
16 const Config = require('../../../config');
17
18 const noExpectedException = 'did not receive expected exception';
19
20 describe('DatabaseSQLite', function () {
21 let db, options;
22 let dbCtx, claimant, claimTimeoutSeconds, callback, subscriptionId, topicId, verificationId;
23 let topicUrl, leaseSeconds, secret, httpRemoteAddr, httpFrom, retryDelays, wanted;
24 before(function () {
25 options = new Config('test');
26 options.db.connectionString = 'sqlite://:memory:';
27 db = new DB(stubLogger, options);
28 });
29 beforeEach(function () {
30 stubLogger._reset();
31 dbCtx = db.db;
32 claimant = '19af19b8-6be3-4a6f-8946-65f5f1ccc5d7';
33 claimTimeoutSeconds = 300;
34 subscriptionId = 'fbaf8f19-ed9c-4a21-89ae-98b7005e3bf6';
35 topicUrl = 'https://example.com/blog';
36 callback = 'https://example.com/callback?id=123';
37 topicId = 'c59d4bda-10ad-41d9-99df-4ce8bc331424';
38 verificationId = '55cd7748-d2d5-11eb-b355-0025905f714a';
39 retryDelays = [60];
40 leaseSeconds = 86400;
41 secret = 'secret';
42 httpRemoteAddr = '127.0.0.1';
43 httpFrom = 'user@example.com';
44 wanted = 5;
45 });
46 afterEach(function () {
47 sinon.restore();
48 });
49
50 // Ensure all interface methods are implemented
51 describe('Implementation', function () {
52 it('implements interface', async function () {
53 const results = await Promise.allSettled(DBStub._implementation.map(async (fn) => {
54 try {
55 // eslint-disable-next-line security/detect-object-injection
56 await db[fn](db.db);
57 } catch (e) {
58 assert(!(e instanceof DBErrors.NotImplemented), `${fn} not implemented`);
59 }
60 }));
61 const failures = results.filter((x) => x.status === 'rejected');
62 assert(!failures.length, failures.map((x) => {
63 x = x.reason.toString();
64 return x.slice(x.indexOf(': '));
65 }));
66 });
67 }); // Implementation
68
69 describe('_currentSchema', function () {
70 it('covers', async function () {
71 const version = { major: 1, minor: 0, patch: 0 };
72 sinon.stub(db.db, 'prepare').returns({
73 get: () => version,
74 });
75 const result = await db._currentSchema();
76 assert.deepStrictEqual(result, version);
77 });
78 }); // _currentSchema
79
80 describe('_closeConnection', function () {
81 it('success', async function () {
82 sinon.stub(db.db, 'close');
83 await db._closeConnection();
84 assert(db.db.close.called);
85 });
86 it('failure', async function () {
87 const expected = new Error();
88 sinon.stub(db.db, 'close').throws(expected);
89 try {
90 await db._closeConnection();
91 assert.fail(noExpectedException);
92 } catch (e) {
93 assert.deepStrictEqual(e, expected);
94 }
95 });
96 }); // _closeConnection
97
98 describe('_purgeTables', function () {
99 beforeEach(function () {
100 sinon.stub(db.db, 'prepare').returns({
101 run: sinon.stub(),
102 });
103 });
104 it('covers not really', async function () {
105 await db._purgeTables(false);
106 assert(!db.db.prepare.called);
107 });
108 it('success', async function () {
109 await db._purgeTables(true);
110 assert(db.db.prepare.called);
111 });
112 it('failure', async function () {
113 const expected = new Error();
114 db.db.prepare.restore();
115 sinon.stub(db.db, 'prepare').throws(expected);
116 try {
117 await db._purgeTables(true);
118 assert.fail(noExpectedException);
119 } catch (e) {
120 assert.deepStrictEqual(e, expected);
121 }
122 });
123 }); // _purgeTables
124
125 describe('_optimize', function () {
126 let origOAC;
127 beforeEach(function () {
128 origOAC = db.optimizeAfterChanges;
129 sinon.stub(db.statement._optimize, 'all');
130 sinon.stub(db.db, 'pragma');
131 });
132 this.afterEach(function () {
133 db.optimizeAfterChanges = origOAC;
134 });
135 it('covers', async function () {
136 db.optimizeAfterChanges = 10;
137 db.changesSinceLastOptimize = BigInt(20);
138 await db._optimize();
139 assert(db.db.pragma.called);
140 });
141 it('covers none', async function () {
142 db.optimizeAfterChanges = 0;
143 await db._optimize();
144 assert(!db.db.pragma.called);
145 });
146 it('covers not enough changes', async function () {
147 db.optimizeAfterChanges = 10;
148 db.changesSinceLastOptimize = BigInt(5);
149 await db._optimize();
150 assert(!db.db.pragma.called);
151 });
152 }); // _optimize
153
154 describe('_deOphidiate', function () {
155 it('covers non-array', function () {
156 const obj = {
157 'snake_case': 1,
158 };
159 const expected = {
160 snakeCase: 1,
161 };
162 const result = DB._deOphidiate(obj);
163 assert.deepStrictEqual(result, expected);
164 });
165 it('covers array', function () {
166 const rows = [
167 {
168 'snek_field': 'foo',
169 },
170 {
171 'snek_field': 'bar',
172 },
173 ];
174 const expected = [
175 {
176 snekField: 'foo',
177 },
178 {
179 snekField: 'bar',
180 },
181 ];
182 const result = DB._deOphidiate(rows);
183 assert.deepStrictEqual(result, expected);
184 });
185 }); // _deOphidiate
186
187 describe('_topicDataToNative', function () {
188 it('covers', function () {
189 const now = new Date();
190 const nowEpoch = now.getTime() / 1000;
191 const topic = {
192 isActive: 1,
193 isDeleted: 0,
194 created: nowEpoch,
195 lastPublish: nowEpoch,
196 contentFetchNextAttempt: nowEpoch,
197 contentUpdated: nowEpoch,
198 url: 'https://example.com/',
199 };
200 const expected = {
201 isActive: true,
202 isDeleted: false,
203 created: now,
204 lastPublish: now,
205 contentFetchNextAttempt: now,
206 contentUpdated: now,
207 url: topic.url,
208 }
209 const result = DB._topicDataToNative(topic);
210 assert.deepStrictEqual(result, expected);
211 });
212 it('covers empty', function () {
213 const topic = undefined;
214 const result = DB._topicDataToNative(topic);
215 assert.deepStrictEqual(result, topic);
216 });
217 }); // _topicDataToNative
218
219 describe('healthCheck', function () {
220 let origDb;
221 beforeEach(function () {
222 origDb = db.db;
223 });
224 afterEach(function () {
225 db.db = origDb;
226 });
227 it('covers', function () {
228 db.healthCheck();
229 });
230 it('covers failure', function () {
231 db.db = { open: false };
232 try {
233 db.healthCheck();
234 assert.fail(noExpectedException);
235 } catch (e) {
236 assert(e instanceof DBErrors.UnexpectedResult);
237 }
238 });
239 }); // healthCheck
240
241 describe('context', function () {
242 it('covers', async function () {
243 await db.context(common.nop);
244 });
245 }); // context
246
247 describe('transaction', function () {
248 it('covers', async function () {
249 await db.transaction(db.db, common.nop);
250 });
251 it('covers no context', async function () {
252 await db.transaction(undefined, common.nop);
253 });
254 }); // transaction
255
256 describe('authenticationSuccess', function () {
257 let identifier;
258 beforeEach(function () {
259 identifier = 'username';
260 });
261 it('success', async function() {
262 const dbResult = {
263 changes: 1,
264 lastInsertRowid: undefined,
265 };
266 sinon.stub(db.statement.authenticationSuccess, 'run').returns(dbResult);
267 await db.authenticationSuccess(dbCtx, identifier);
268 });
269 it('failure', async function () {
270 const dbResult = {
271 changes: 0,
272 lastInsertRowid: undefined,
273 };
274 sinon.stub(db.statement.authenticationSuccess, 'run').returns(dbResult);
275 try {
276 await db.authenticationSuccess(dbCtx, identifier);
277 assert.fail(noExpectedException);
278 } catch (e) {
279 assert(e instanceof DBErrors.UnexpectedResult);
280 }
281 });
282 }); // authenticationSuccess
283
284 describe('authenticationGet', function () {
285 let identifier, credential;
286 beforeEach(function () {
287 identifier = 'username';
288 credential = '$z$foo';
289 });
290 it('success', async function() {
291 const expected = {
292 identifier,
293 credential,
294 };
295 sinon.stub(db.statement.authenticationGet, 'get').returns(expected);
296 const result = await db.authenticationGet(dbCtx, identifier);
297 assert.deepStrictEqual(result, expected);
298 });
299 it('failure', async function () {
300 const expected = new Error();
301 sinon.stub(db.statement.authenticationGet, 'get').throws(expected);
302 try {
303 await db.authenticationGet(dbCtx, identifier);
304 assert.fail(noExpectedException);
305 } catch (e) {
306 assert.deepStrictEqual(e, expected);
307 }
308 });
309 }); // authenticationGet
310
311 describe('authenticationUpsert', function () {
312 let identifier, credential;
313 beforeEach(function () {
314 identifier = 'username';
315 credential = '$z$foo';
316 });
317 it('success', async function() {
318 const dbResult = {
319 changes: 1,
320 lastInsertRowid: undefined,
321 };
322 sinon.stub(db.statement.authenticationUpsert, 'run').returns(dbResult);
323 await db.authenticationUpsert(dbCtx, identifier, credential);
324 });
325 it('failure', async function () {
326 const dbResult = {
327 changes: 0,
328 lastInsertRowid: undefined,
329 };
330 sinon.stub(db.statement.authenticationUpsert, 'run').returns(dbResult);
331 try {
332 await db.authenticationUpsert(dbCtx, identifier, credential);
333 assert.fail(noExpectedException);
334 } catch (e) {
335 assert(e instanceof DBErrors.UnexpectedResult);
336 }
337 });
338 }); // authenticationUpsert
339
340 describe('subscriptionsByTopicId', function () {
341 it('success', async function () {
342 const expected = { count: 3 };
343 sinon.stub(db.statement.subscriptionsByTopicId, 'all').returns(expected);
344 const result = await db.subscriptionsByTopicId(dbCtx, topicUrl);
345 assert.deepStrictEqual(result, expected);
346 });
347 it('failure', async function () {
348 const expected = new Error();
349 sinon.stub(db.statement.subscriptionsByTopicId, 'all').throws(expected);
350 try {
351 await db.subscriptionsByTopicId(dbCtx, topicUrl);
352 assert.fail(noExpectedException);
353 } catch (e) {
354 assert.deepStrictEqual(e, expected);
355 }
356 });
357 }); // subscriptionsByTopicId
358
359 describe('subscriptionCountByTopicUrl', function () {
360 it('success', async function () {
361 const expected = { count: 3 };
362 sinon.stub(db.statement.subscriptionCountByTopicUrl, 'get').returns(expected);
363 const result = await db.subscriptionCountByTopicUrl(dbCtx, topicUrl);
364 assert.deepStrictEqual(result, expected);
365 });
366 it('failure', async function () {
367 const expected = new Error();
368 sinon.stub(db.statement.subscriptionCountByTopicUrl, 'get').throws(expected);
369 try {
370 await db.subscriptionCountByTopicUrl(dbCtx, topicUrl);
371 assert.fail(noExpectedException);
372 } catch (e) {
373 assert.deepStrictEqual(e, expected);
374 }
375 });
376 }); // subscriptionCountByTopicUrl
377
378 describe('subscriptionDelete', function () {
379 it('success', async function() {
380 const dbResult = {
381 changes: 1,
382 lastInsertRowid: undefined,
383 };
384 const expected = {
385 changes: 1,
386 lastInsertRowid: undefined,
387 };
388 sinon.stub(db.statement.subscriptionDelete, 'run').returns(dbResult);
389 const result = await db.subscriptionDelete(dbCtx, callback, topicId);
390 assert.deepStrictEqual(result, expected);
391 });
392 it('failure', async function () {
393 const dbResult = {
394 changes: 0,
395 lastInsertRowid: undefined,
396 };
397 sinon.stub(db.statement.subscriptionDelete, 'run').returns(dbResult);
398 try {
399 await db.subscriptionDelete(dbCtx, callback, topicId);
400 assert.fail(noExpectedException);
401 } catch (e) {
402 assert(e instanceof DBErrors.UnexpectedResult);
403 }
404 });
405 }); // subscriptionDelete
406
407 describe('subscriptionDeliveryClaim', function () {
408 it('success', async function() {
409 const dbAllResult = [
410 {
411 id: 'c2e254c5-aa6e-4a8f-b1a1-e474b07392bb',
412 },
413 ];
414 const dbRunResult = {
415 changes: 1,
416 lastInsertRowid: undefined,
417 };
418 const expected = ['c2e254c5-aa6e-4a8f-b1a1-e474b07392bb'];
419 sinon.stub(db.statement.subscriptionDeliveryNeeded, 'all').returns(dbAllResult);
420 sinon.stub(db.statement.subscriptionDeliveryClaimById, 'run').returns(dbRunResult);
421 const result = await db.subscriptionDeliveryClaim(dbCtx, wanted, claimTimeoutSeconds, claimant);
422 assert.deepStrictEqual(result, expected);
423 });
424 it('failure', async function () {
425 const dbAllResult = [
426 {
427 id: 'c2e254c5-aa6e-4a8f-b1a1-e474b07392bb',
428 },
429 ];
430 const dbRunResult = {
431 changes: 0,
432 lastInsertRowid: undefined,
433 };
434 sinon.stub(db.statement.subscriptionDeliveryNeeded, 'all').returns(dbAllResult);
435 sinon.stub(db.statement.subscriptionDeliveryClaimById, 'run').returns(dbRunResult);
436 try {
437 await db.subscriptionDeliveryClaim(dbCtx, wanted, claimTimeoutSeconds, claimant );
438 assert.fail(noExpectedException);
439 } catch (e) {
440 assert(e instanceof DBErrors.UnexpectedResult);
441 }
442 });
443 }); // subscriptionDeliveryClaim
444
445 describe('subscriptionDeliveryClaimById', function () {
446 it('success', async function() {
447 const dbResult = {
448 changes: 1,
449 lastInsertRowid: undefined,
450 };
451 sinon.stub(db.statement.subscriptionDeliveryClaimById, 'run').returns(dbResult);
452 const result = await db.subscriptionDeliveryClaimById(dbCtx, subscriptionId, claimTimeoutSeconds, claimant);
453 assert.deepStrictEqual(result, dbResult);
454 });
455 it('failure', async function () {
456 const dbResult = {
457 changes: 0,
458 lastInsertRowid: undefined,
459 };
460 sinon.stub(db.statement.subscriptionDeliveryClaimById, 'run').returns(dbResult);
461 try {
462 await db.subscriptionDeliveryClaimById(dbCtx, subscriptionId, claimTimeoutSeconds, claimant);
463 assert.fail(noExpectedException);
464 } catch (e) {
465 assert(e instanceof DBErrors.UnexpectedResult);
466 }
467 });
468 }); // subscriptionDeliveryClaimById
469
470 describe('subscriptionDeliveryComplete', function () {
471 it('success', async function() {
472 const dbResult = {
473 changes: 1,
474 };
475 sinon.stub(db.statement.subscriptionDeliverySuccess, 'run').returns(dbResult);
476 sinon.stub(db.statement.subscriptionDeliveryDone, 'run').returns(dbResult);
477 await db.subscriptionDeliveryComplete(dbCtx, callback, topicId);
478 });
479 it('failure', async function () {
480 const dbResult = {
481 changes: 0,
482 };
483 sinon.stub(db.statement.subscriptionDeliverySuccess, 'run').returns(dbResult);
484 sinon.stub(db.statement.subscriptionDeliveryDone, 'run').returns(dbResult);
485 try {
486 await db.subscriptionDeliveryComplete(dbCtx, callback, topicId);
487 assert.fail(noExpectedException);
488 } catch (e) {
489 assert(e instanceof DBErrors.UnexpectedResult);
490 }
491 });
492 it('second failure', async function () {
493 const dbResult0 = {
494 changes: 1,
495 };
496 const dbResult1 = {
497 changes: 0,
498 };
499 sinon.stub(db.statement.subscriptionDeliverySuccess, 'run').returns(dbResult0);
500 sinon.stub(db.statement.subscriptionDeliveryDone, 'run').returns(dbResult1);
501 try {
502 await db.subscriptionDeliveryComplete(dbCtx, callback, topicId);
503 assert.fail(noExpectedException);
504 } catch (e) {
505 assert(e instanceof DBErrors.UnexpectedResult);
506 }
507 });
508 }); // subscriptionDeliveryComplete
509
510 describe('subscriptionDeliveryGone', function () {
511 it('success', async function() {
512 const dbResult = {
513 changes: 1,
514 };
515 sinon.stub(db.statement.subscriptionDelete, 'run').returns(dbResult);
516 await db.subscriptionDeliveryGone(dbCtx, callback, topicId);
517 });
518 it('failure', async function () {
519 const dbResult = {
520 changes: 0,
521 };
522 sinon.stub(db.statement.subscriptionDelete, 'run').returns(dbResult);
523 try {
524 await db.subscriptionDeliveryGone(dbCtx, callback, topicId);
525 assert.fail(noExpectedException);
526 } catch (e) {
527 assert(e instanceof DBErrors.UnexpectedResult);
528 }
529 });
530 }); // subscriptionDeliveryGone
531
532 describe('subscriptionDeliveryIncomplete', function () {
533 it('success', async function() {
534 const dbGet = { deliveryAttemptsSinceSuccess: 0 };
535 const dbResult = {
536 changes: 1,
537 };
538 sinon.stub(db.statement.subscriptionDeliveryAttempts, 'get').returns(dbGet);
539 sinon.stub(db.statement.subscriptionDeliveryFailure, 'run').returns(dbResult);
540 sinon.stub(db.statement.subscriptionDeliveryDone, 'run').returns(dbResult);
541 await db.subscriptionDeliveryIncomplete(dbCtx, callback, topicId, retryDelays);
542 });
543 it('success covers default', async function() {
544 const dbGet = { deliveryAttemptsSinceSuccess: 0 };
545 const dbResult = {
546 changes: 1,
547 };
548 sinon.stub(db.statement.subscriptionDeliveryAttempts, 'get').returns(dbGet);
549 sinon.stub(db.statement.subscriptionDeliveryFailure, 'run').returns(dbResult);
550 sinon.stub(db.statement.subscriptionDeliveryDone, 'run').returns(dbResult);
551 await db.subscriptionDeliveryIncomplete(dbCtx, callback, topicId);
552 });
553 it('failure', async function () {
554 const dbGet = { deliveryAttemptsSinceSuccess: 0 };
555 const dbResult = {
556 changes: 0,
557 };
558 sinon.stub(db.statement.subscriptionDeliveryAttempts, 'get').returns(dbGet);
559 sinon.stub(db.statement.subscriptionDeliveryFailure, 'run').returns(dbResult);
560 sinon.stub(db.statement.subscriptionDeliveryDone, 'run').returns(dbResult);
561 try {
562 await db.subscriptionDeliveryIncomplete(dbCtx, callback, topicId, retryDelays);
563 assert.fail(noExpectedException);
564 } catch (e) {
565 assert(e instanceof DBErrors.UnexpectedResult);
566 }
567 });
568 it('second failure', async function () {
569 const dbGet = { deliveryAttemptsSinceSuccess: 0 };
570 const dbResult0 = {
571 changes: 1,
572 };
573 const dbResult1 = {
574 changes: 0,
575 };
576 sinon.stub(db.statement.subscriptionDeliveryAttempts, 'get').returns(dbGet);
577 sinon.stub(db.statement.subscriptionDeliveryFailure, 'run').returns(dbResult0);
578 sinon.stub(db.statement.subscriptionDeliveryDone, 'run').returns(dbResult1);
579 try {
580 await db.subscriptionDeliveryIncomplete(dbCtx, callback, topicId, retryDelays);
581 assert.fail(noExpectedException);
582 } catch (e) {
583 assert(e instanceof DBErrors.UnexpectedResult);
584 }
585 });
586 }); // subscriptionDeliveryIncomplete
587
588 describe('subscriptionGet', function () {
589 it('success', async function() {
590 const expected = {
591 id: subscriptionId,
592 };
593 sinon.stub(db.statement.subscriptionGet, 'get').returns(expected);
594 const result = await db.subscriptionGet(dbCtx, callback, topicId);
595 assert.deepStrictEqual(result, expected);
596 });
597 it('failure', async function () {
598 const expected = new Error();
599 sinon.stub(db.statement.subscriptionGet, 'get').throws(expected);
600 try {
601 await db.subscriptionGet(dbCtx, callback, topicId);
602 assert.fail(noExpectedException);
603 } catch (e) {
604 assert.deepStrictEqual(e, expected);
605 }
606 });
607 }); // subscriptionGet
608
609 describe('subscriptionGetById', function () {
610 it('success', async function() {
611 const expected = {
612 id: subscriptionId,
613 };
614 sinon.stub(db.statement.subscriptionGetById, 'get').returns(expected);
615 const result = await db.subscriptionGetById(dbCtx, subscriptionId);
616 assert.deepStrictEqual(result, expected);
617 });
618 it('failure', async function () {
619 const expected = new Error();
620 sinon.stub(db.statement.subscriptionGetById, 'get').throws(expected);
621 try {
622 await db.subscriptionGetById(dbCtx, subscriptionId);
623 assert.fail(noExpectedException);
624 } catch (e) {
625 assert.deepStrictEqual(e, expected);
626 }
627 });
628 }); // subscriptionGetById
629
630 describe('subscriptionUpdate', function () {
631 let data;
632 beforeEach(function () {
633 data = {
634 subscriptionId,
635 signatureAlgorithm: 'sha256',
636 };
637 });
638 it('success', async function() {
639 const dbResult = {
640 changes: 1,
641 lastInsertRowid: subscriptionId,
642 };
643 sinon.stub(db.statement.subscriptionUpdate, 'run').returns(dbResult);
644 await db.subscriptionUpdate(dbCtx, data);
645 });
646 it('failure', async function () {
647 const dbResult = {
648 changes: 0,
649 };
650 sinon.stub(db.statement.subscriptionUpdate, 'run').returns(dbResult);
651 try {
652 await db.subscriptionUpdate(dbCtx, data);
653 assert.fail(noExpectedException);
654 } catch (e) {
655 assert(e instanceof DBErrors.UnexpectedResult, e);
656 }
657 });
658 }); // subscriptionUpdate
659
660 describe('subscriptionUpsert', function () {
661 let data;
662 beforeEach(function () {
663 data = {
664 callback,
665 topicId,
666 leaseSeconds,
667 secret,
668 httpRemoteAddr,
669 httpFrom,
670 };
671 });
672 it('success', async function() {
673 const dbResult = {
674 changes: 1,
675 lastInsertRowid: subscriptionId,
676 };
677 const expected = {
678 changes: 1,
679 lastInsertRowid: subscriptionId,
680 };
681 sinon.stub(db.statement.subscriptionUpsert, 'run').returns(dbResult);
682 const result = await db.subscriptionUpsert(dbCtx, data);
683 assert.deepStrictEqual(result, expected);
684 });
685 it('failure', async function () {
686 const dbResult = {
687 changes: 0,
688 };
689 sinon.stub(db.statement.subscriptionUpsert, 'run').returns(dbResult);
690 try {
691 await db.subscriptionUpsert(dbCtx, data);
692 assert.fail(noExpectedException);
693 } catch (e) {
694 assert(e instanceof DBErrors.UnexpectedResult);
695 }
696 });
697 }); // subscriptionUpsert
698
699 describe('topicDeleted', function () {
700 it('success', async function () {
701 sinon.stub(db.statement.topicDeleted, 'run').returns({ changes: 1 });
702 await db.topicDeleted(dbCtx, { topicId });
703 });
704 it('failure', async function () {
705 sinon.stub(db.statement.topicDeleted, 'run').returns({ changes: 0 });
706 try {
707 await db.topicDeleted(dbCtx, { topicId });
708 assert.fail(noExpectedException);
709 } catch (e) {
710 assert(e instanceof DBErrors.UnexpectedResult);
711 }
712 });
713 }); // topicDeleted
714
715 describe('topicFetchClaim', function () {
716 it('success', async function() {
717 const dbAll = [{ id: topicId }];
718 const dbResult = {
719 changes: 1,
720 };
721 const expected = [topicId];
722 sinon.stub(db.statement.topicContentFetchNeeded, 'all').returns(dbAll);
723 sinon.stub(db.statement.topicContentFetchClaimById, 'run').returns(dbResult);
724 const result = await db.topicFetchClaim(dbCtx, wanted, claimTimeoutSeconds, claimant);
725 assert.deepStrictEqual(result, expected);
726 });
727 it('failure', async function () {
728 const dbAll = [{ id: topicId }];
729 const dbResult = {
730 changes: 0,
731 };
732 sinon.stub(db.statement.topicContentFetchNeeded, 'all').returns(dbAll);
733 sinon.stub(db.statement.topicContentFetchClaimById, 'run').returns(dbResult);
734 try {
735 await db.topicFetchClaim(dbCtx, wanted, claimTimeoutSeconds, claimant);
736 assert.fail(noExpectedException);
737 } catch (e) {
738 assert(e instanceof DBErrors.UnexpectedResult);
739 }
740 });
741 }); // topicFetchClaim
742
743 describe('topicFetchClaimById', function () {
744 it('success', async function() {
745 const expected = {
746 changes: 1,
747 lastInsertRowid: undefined,
748 };
749 sinon.stub(db.statement.topicContentFetchClaimById, 'run').returns(expected);
750 const result = await db.topicFetchClaimById(dbCtx, topicId, claimTimeoutSeconds, claimant);
751 assert.deepStrictEqual(result, expected);
752 });
753 it('failure', async function () {
754 const expected = {
755 changes: 0,
756 lastInsertRowid: undefined,
757 };
758 sinon.stub(db.statement.topicContentFetchClaimById, 'run').returns(expected);
759 try {
760 await db.topicFetchClaimById(dbCtx, topicId, claimTimeoutSeconds, claimant);
761 assert.fail(noExpectedException);
762 } catch (e) {
763 assert(e instanceof DBErrors.UnexpectedResult);
764 }
765 });
766 }); // topicFetchClaimById
767
768 describe('topicFetchComplete', function () {
769 it('success', async function() {
770 const dbResult = {
771 changes: 1,
772 lastInsertRowid: undefined,
773 };
774 sinon.stub(db.statement.topicAttemptsReset, 'run').returns(dbResult);
775 sinon.stub(db.statement.topicContentFetchDone, 'run').returns(dbResult);
776 await db.topicFetchComplete(dbCtx, topicId);
777 });
778 it('failure', async function () {
779 const dbResult = {
780 changes: 0,
781 lastInsertRowid: undefined,
782 };
783 sinon.stub(db.statement.topicAttemptsReset, 'run').returns(dbResult);
784 sinon.stub(db.statement.topicContentFetchDone, 'run').returns(dbResult);
785 try {
786 await db.topicFetchComplete(dbCtx, topicId);
787 assert.fail(noExpectedException);
788 } catch (e) {
789 assert(e instanceof DBErrors.UnexpectedResult);
790 }
791 });
792 it('second failure', async function () {
793 const dbResult0 = {
794 changes: 1,
795 lastInsertRowid: undefined,
796 };
797 const dbResult1 = {
798 changes: 0,
799 lastInsertRowid: undefined,
800 };
801 sinon.stub(db.statement.topicAttemptsReset, 'run').returns(dbResult0);
802 sinon.stub(db.statement.topicContentFetchDone, 'run').returns(dbResult1);
803 try {
804 await db.topicFetchComplete(dbCtx, topicId);
805 assert.fail(noExpectedException);
806 } catch (e) {
807 assert(e instanceof DBErrors.UnexpectedResult);
808 }
809 });
810 }); // topicFetchComplete
811
812 describe('topicFetchIncomplete', function () {
813 it('success', async function() {
814 const dbGet = { currentAttempt: 0 };
815 const dbResult0 = {
816 changes: 1,
817 lastInsertRowid: undefined,
818 };
819 const dbResult1 = {
820 changes: 1,
821 lastInsertRowid: undefined,
822 }
823 const expected = {
824 changes: 1,
825 lastInsertRowid: undefined,
826 };
827 sinon.stub(db.statement.topicAttempts, 'get').returns(dbGet);
828 sinon.stub(db.statement.topicAttemptsIncrement, 'run').returns(dbResult0);
829 sinon.stub(db.statement.topicContentFetchDone, 'run').returns(dbResult1);
830 const result = await db.topicFetchIncomplete(dbCtx, topicId, retryDelays);
831 assert.deepStrictEqual(result, expected);
832 });
833 it('covers defaults', async function() {
834 const dbGet = { currentAttempt: 0 };
835 const dbResult0 = {
836 changes: 1,
837 lastInsertRowid: undefined,
838 };
839 const dbResult1 = {
840 changes: 1,
841 lastInsertRowid: undefined,
842 }
843 const expected = {
844 changes: 1,
845 lastInsertRowid: undefined,
846 };
847 sinon.stub(db.statement.topicAttempts, 'get').returns(dbGet);
848 sinon.stub(db.statement.topicAttemptsIncrement, 'run').returns(dbResult0);
849 sinon.stub(db.statement.topicContentFetchDone, 'run').returns(dbResult1);
850 const result = await db.topicFetchIncomplete(dbCtx, topicId);
851 assert.deepStrictEqual(result, expected);
852 });
853 it('failure', async function () {
854 const dbGet = { currentAttempt: 0 };
855 const dbResult0 = {
856 changes: 1,
857 lastInsertRowid: undefined,
858 };
859 const dbResult1 = {
860 changes: 0,
861 lastInsertRowid: undefined,
862 }
863 sinon.stub(db.statement.topicAttempts, 'get').returns(dbGet);
864 sinon.stub(db.statement.topicAttemptsIncrement, 'run').returns(dbResult0);
865 sinon.stub(db.statement.topicContentFetchDone, 'run').returns(dbResult1);
866 try {
867 await db.topicFetchIncomplete(dbCtx, topicId, retryDelays);
868 assert.fail(noExpectedException);
869 } catch (e) {
870 assert(e instanceof DBErrors.UnexpectedResult);
871 }
872 });
873 it('second failure', async function () {
874 const dbGet = { currentAttempt: 0 };
875 const dbResult0 = {
876 changes: 0,
877 lastInsertRowid: undefined,
878 };
879 const dbResult1 = {
880 changes: 0,
881 lastInsertRowid: undefined,
882 }
883 sinon.stub(db.statement.topicAttempts, 'get').returns(dbGet);
884 sinon.stub(db.statement.topicAttemptsIncrement, 'run').returns(dbResult0);
885 sinon.stub(db.statement.topicContentFetchDone, 'run').returns(dbResult1);
886 try {
887 await db.topicFetchIncomplete(dbCtx, topicId, retryDelays);
888 assert.fail(noExpectedException);
889 } catch (e) {
890 assert(e instanceof DBErrors.UnexpectedResult);
891 }
892 });
893 }); // topicFetchIncomplete
894
895 describe('topicFetchRequested', function () {
896 it('success', async function() {
897 const dbResult = {
898 changes: 1,
899 lastInsertRowid: undefined,
900 };
901 const expected = {
902 changes: 1,
903 lastInsertRowid: undefined,
904 };
905 sinon.stub(db.statement.topicContentFetchRequested, 'run').returns(dbResult);
906 const result = await db.topicFetchRequested(dbCtx, topicId);
907 assert.deepStrictEqual(result, expected);
908 });
909 it('failure', async function () {
910 const dbResult = {
911 changes: 0,
912 lastInsertRowid: undefined,
913 };
914 sinon.stub(db.statement.topicContentFetchRequested, 'run').returns(dbResult);
915 try {
916 await db.topicFetchRequested(dbCtx, topicId);
917 assert.fail(noExpectedException);
918 } catch (e) {
919 assert(e instanceof DBErrors.UnexpectedResult);
920 }
921 });
922 }); // topicFetchRequested
923
924 describe('topicGetAll', function () {
925 it('success', async function() {
926 const expected = [{ id: topicId }];
927 sinon.stub(db.statement.topicGetInfoAll, 'all').returns(expected);
928 const result = await db.topicGetAll(dbCtx);
929 assert.deepStrictEqual(result, expected);
930 });
931 it('covers none', async function() {
932 const expected = undefined;
933 sinon.stub(db.statement.topicGetInfoAll, 'all').returns(expected);
934 const result = await db.topicGetAll(dbCtx);
935 assert.deepStrictEqual(result, expected);
936 });
937 it('failure', async function () {
938 const expected = new Error();
939 sinon.stub(db.statement.topicGetInfoAll, 'all').throws(expected);
940 try {
941 await db.topicGetAll(dbCtx);
942 assert.fail(noExpectedException);
943 } catch (e) {
944 assert.deepStrictEqual(e, expected);
945 }
946 });
947 }); // topicGetById
948
949 describe('topicGetById', function () {
950 it('success', async function() {
951 const expected = { id: topicId };
952 sinon.stub(db.statement.topicGetById, 'get').returns(expected);
953 const result = await db.topicGetById(dbCtx, topicId);
954 assert.deepStrictEqual(result, expected);
955 });
956 it('covers no defaults', async function () {
957 const expected = { id: topicId };
958 sinon.stub(db.statement.topicGetById, 'get').returns(expected);
959 const result = await db.topicGetById(dbCtx, topicId, false);
960 assert.deepStrictEqual(result, expected);
961 });
962 it('covers default', async function() {
963 const expected = undefined;
964 sinon.stub(db.statement.topicGetById, 'get').returns(expected);
965 const result = await db.topicGetById(dbCtx, topicId);
966 assert.deepStrictEqual(result, expected);
967 });
968 it('failure', async function () {
969 const expected = new Error();
970 sinon.stub(db.statement.topicGetById, 'get').throws(expected);
971 try {
972 await db.topicGetById(dbCtx, topicId);
973 assert.fail(noExpectedException);
974 } catch (e) {
975 assert.deepStrictEqual(e, expected);
976 }
977 });
978 }); // topicGetById
979
980 describe('topicGetByUrl', function () {
981 it('success', async function() {
982 const expected = [];
983 sinon.stub(db.statement.topicGetByUrl, 'get').returns(expected);
984 const result = await db.topicGetByUrl(dbCtx, topicUrl);
985 assert.deepStrictEqual(result, expected);
986 });
987 it('failure', async function () {
988 const expected = new Error();
989 sinon.stub(db.statement.topicGetByUrl, 'get').throws(expected);
990 try {
991 await db.topicGetByUrl(dbCtx, topicUrl);
992 assert.fail(noExpectedException);
993 } catch (e) {
994 assert.deepStrictEqual(e, expected);
995 }
996 });
997 }); // topicGetByUrl
998
999 describe('topicGetContentById', function () {
1000 it('success', async function() {
1001 const expected = { id: topicId };
1002 sinon.stub(db.statement.topicGetContentById, 'get').returns(expected);
1003 const result = await db.topicGetContentById(dbCtx, topicId);
1004 assert.deepStrictEqual(result, expected);
1005 });
1006 it('covers default', async function() {
1007 const expected = undefined;
1008 sinon.stub(db.statement.topicGetContentById, 'get').returns(expected);
1009 const result = await db.topicGetContentById(dbCtx, topicId);
1010 assert.deepStrictEqual(result, expected);
1011 });
1012 it('failure', async function () {
1013 const expected = new Error();
1014 sinon.stub(db.statement.topicGetContentById, 'get').throws(expected);
1015 try {
1016 await db.topicGetContentById(dbCtx, topicId);
1017 assert.fail(noExpectedException);
1018 } catch (e) {
1019 assert.deepStrictEqual(e, expected);
1020 }
1021 });
1022 }); // topicGetContentById
1023
1024 describe('topicSet', function () {
1025 let data;
1026 beforeEach(function () {
1027 data = {
1028 url: topicUrl,
1029 };
1030 });
1031 it('success', async function() {
1032 const dbResult = {
1033 changes: 1,
1034 lastInsertRowid: topicId,
1035 };
1036 const expected = {
1037 changes: 1,
1038 lastInsertRowid: topicId,
1039 };
1040 sinon.stub(db.statement.topicUpsert, 'run').returns(dbResult);
1041 const result = await db.topicSet(dbCtx, data);
1042 assert.deepStrictEqual(result, expected);
1043 });
1044 it('failure', async function () {
1045 const dbResult = {
1046 changes: 0,
1047 lastInsertRowid: undefined,
1048 };
1049 sinon.stub(db.statement.topicUpsert, 'run').returns(dbResult);
1050 try {
1051 await db.topicSet(dbCtx, data);
1052 assert.fail(noExpectedException);
1053 } catch (e) {
1054 assert(e instanceof DBErrors.UnexpectedResult);
1055 }
1056 });
1057 it('fails invalid value', async function () {
1058 sinon.stub(db.statement.topicUpsert, 'run');
1059 try {
1060 data.leaseSecondsPreferred = -100;
1061 await db.topicSet(dbCtx, data);
1062 assert.fail(noExpectedException);
1063 } catch (e) {
1064 assert(e instanceof DBErrors.DataValidation);
1065 }
1066 assert(!db.statement.topicUpsert.run.called);
1067 });
1068 it('fails invalid values', async function () {
1069 sinon.stub(db.statement.topicUpsert, 'run');
1070 try {
1071 data.leaseSecondsPreferred = 10;
1072 data.leaseSecondsMax = 100;
1073 data.leaseSecondsMin = 50;
1074 await db.topicSet(dbCtx, data);
1075 assert.fail(noExpectedException);
1076 } catch (e) {
1077 assert(e instanceof DBErrors.DataValidation);
1078 }
1079 assert(!db.statement.topicUpsert.run.called);
1080 });
1081 }); // topicSet
1082
1083 describe('topicSetContent', function () {
1084 let data;
1085 beforeEach(function () {
1086 data = {
1087 content: 'content',
1088 contentType: 'text/plain',
1089 contentHash: 'abc123',
1090 };
1091 });
1092 it('success', async function() {
1093 const dbResult = {
1094 changes: 1,
1095 lastInsertRowid: undefined,
1096 };
1097 const expected = {
1098 changes: 1,
1099 lastInsertRowid: undefined,
1100 };
1101 sinon.stub(db.statement.topicSetContent, 'run').returns(dbResult);
1102 const result = await db.topicSetContent(dbCtx, data);
1103 assert.deepStrictEqual(result, expected);
1104 });
1105 it('failure', async function () {
1106 const dbResult = {
1107 changes: 0,
1108 lastInsertRowid: undefined,
1109 };
1110 sinon.stub(db.statement.topicSetContent, 'run').returns(dbResult);
1111 try {
1112 await db.topicSetContent(dbCtx, data);
1113 assert.fail(noExpectedException);
1114 } catch (e) {
1115 assert(e instanceof DBErrors.UnexpectedResult);
1116 }
1117 });
1118 }); // topicSetContent
1119
1120 describe('topicUpdate', function () {
1121 let data;
1122 beforeEach(function () {
1123 data = {
1124 topicId,
1125 leaseSecondsPreferred: 9999,
1126 leaseSecondsMax: 99999,
1127 leaseSecondsMin: 999,
1128 publisherValidationUrl: null,
1129 contentHashAlgorithm: 'sha256',
1130 };
1131 });
1132 it('success', async function() {
1133 const dbResult = {
1134 changes: 1,
1135 lastInsertRowid: topicId,
1136 };
1137 sinon.stub(db.statement.topicUpdate, 'run').returns(dbResult);
1138 await db.topicUpdate(dbCtx, data);
1139 });
1140 it('failure', async function () {
1141 const dbResult = {
1142 changes: 0,
1143 lastInsertRowid: undefined,
1144 };
1145 sinon.stub(db.statement.topicUpdate, 'run').returns(dbResult);
1146 try {
1147 await db.topicUpdate(dbCtx, data);
1148 assert.fail(noExpectedException);
1149 } catch (e) {
1150 assert(e instanceof DBErrors.UnexpectedResult, e);
1151 }
1152 });
1153 it('fails invalid value', async function () {
1154 sinon.stub(db.statement.topicUpdate, 'run');
1155 try {
1156 data.leaseSecondsPreferred = -100;
1157 await db.topicUpdate(dbCtx, data);
1158 assert.fail(noExpectedException);
1159 } catch (e) {
1160 assert(e instanceof DBErrors.DataValidation, e);
1161 }
1162 assert(!db.statement.topicUpdate.run.called);
1163 });
1164 it('fails invalid values', async function () {
1165 sinon.stub(db.statement.topicUpdate, 'run');
1166 try {
1167 data.leaseSecondsPreferred = 10;
1168 data.leaseSecondsMax = 100;
1169 data.leaseSecondsMin = 50;
1170 await db.topicUpdate(dbCtx, data);
1171 assert.fail(noExpectedException);
1172 } catch (e) {
1173 assert(e instanceof DBErrors.DataValidation, e);
1174 }
1175 assert(!db.statement.topicUpdate.run.called);
1176 });
1177 }); // topicUpdate
1178
1179 describe('verificationClaim', function () {
1180 it('success', async function() {
1181 const dbAll = [{ id: verificationId }];
1182 const dbRun = {
1183 changes: 1,
1184 lastInsertRowid: undefined,
1185 };
1186 const expected = [verificationId];
1187 sinon.stub(db.statement.verificationNeeded, 'all').returns(dbAll);
1188 sinon.stub(db.statement.verificationClaimById, 'run').returns(dbRun);
1189 const result = await db.verificationClaim(dbCtx, wanted, claimTimeoutSeconds, claimant);
1190 assert.deepStrictEqual(result, expected);
1191 });
1192 it('failure', async function () {
1193 const dbAll = [{ id: verificationId }];
1194 const dbRun = {
1195 changes: 0,
1196 lastInsertRowid: undefined,
1197 };
1198 sinon.stub(db.statement.verificationNeeded, 'all').returns(dbAll);
1199 sinon.stub(db.statement.verificationClaimById, 'run').returns(dbRun);
1200 try {
1201 await db.verificationClaim(dbCtx, wanted, claimTimeoutSeconds, claimant);
1202 assert.fail(noExpectedException);
1203 } catch (e) {
1204 assert(e instanceof DBErrors.UnexpectedResult);
1205 }
1206 });
1207 }); // verificationClaim
1208
1209 describe('verificationClaimById', function () {
1210 it('success', async function() {
1211 const dbRun = {
1212 changes: 1,
1213 lastInsertRowid: undefined,
1214 };
1215 sinon.stub(db.statement.verificationClaimById, 'run').returns(dbRun);
1216 const result = await db.verificationClaimById(dbCtx, verificationId, claimTimeoutSeconds, claimant);
1217 assert.deepStrictEqual(result, dbRun);
1218 });
1219 it('failure', async function () {
1220 const dbRun = {
1221 changes: 0,
1222 lastInsertRowid: undefined,
1223 };
1224 sinon.stub(db.statement.verificationClaimById, 'run').returns(dbRun);
1225 try {
1226 await db.verificationClaimById(dbCtx, verificationId, claimTimeoutSeconds, claimant);
1227 assert.fail(noExpectedException);
1228 } catch (e) {
1229 assert(e instanceof DBErrors.UnexpectedResult);
1230 }
1231 });
1232 }); // verificationClaimById
1233
1234 describe('verificationComplete', function () {
1235 it('success', async function() {
1236 const dbResult = {
1237 changes: 1,
1238 lastInsertRowid: undefined,
1239 };
1240 sinon.stub(db.statement.verificationScrub, 'run').returns(dbResult);
1241 await db.verificationComplete(dbCtx, verificationId, callback, topicId);
1242 });
1243 it('failure', async function () {
1244 const dbResult = {
1245 changes: 0,
1246 lastInsertRowid: undefined,
1247 };
1248 sinon.stub(db.statement.verificationScrub, 'run').returns(dbResult);
1249 try {
1250 await db.verificationComplete(dbCtx, verificationId, callback, topicId);
1251 assert.fail(noExpectedException);
1252 } catch (e) {
1253 assert(e instanceof DBErrors.UnexpectedResult);
1254 }
1255 });
1256 }); // verificationComplete
1257
1258 describe('verificationGetById', function () {
1259 it('success', async function() {
1260 const dbOneOrNone = { id: verificationId, isPublisherValidated: 1 };
1261 const expected = { id: verificationId, isPublisherValidated: true };
1262 sinon.stub(db.statement.verificationGetById, 'get').returns(dbOneOrNone);
1263 const result = await db.verificationGetById(dbCtx, verificationId);
1264 assert.deepStrictEqual(result, expected);
1265 });
1266 it('failure', async function () {
1267 const expected = new Error();
1268 sinon.stub(db.statement.verificationGetById, 'get').throws(expected);
1269 try {
1270 await db.verificationGetById(dbCtx, verificationId);
1271 assert.fail(noExpectedException);
1272 } catch (e) {
1273 assert.deepStrictEqual(e, expected);
1274 }
1275 });
1276 }); // verificationGetById
1277
1278 describe('verificationIncomplete', function () {
1279 it('success', async function() {
1280 const dbOne = { attempts: 0 };
1281 const dbResult0 = {
1282 changes: 1,
1283 lastInsertRowid: undefined,
1284 };
1285 const dbResult1 = {
1286 changes: 1,
1287 lastInsertRowid: undefined,
1288 };
1289 sinon.stub(db.statement.verificationAttempts, 'get').returns(dbOne);
1290 sinon.stub(db.statement.verificationAttemptsIncrement, 'run').returns(dbResult0);
1291 sinon.stub(db.statement.verificationDone, 'run').returns(dbResult1);
1292 await db.verificationIncomplete(dbCtx, verificationId, retryDelays);
1293 });
1294 it('covers defaults', async function() {
1295 const dbOne = { attempts: 0 };
1296 const dbResult0 = {
1297 changes: 1,
1298 lastInsertRowid: undefined,
1299 };
1300 const dbResult1 = {
1301 changes: 1,
1302 lastInsertRowid: undefined,
1303 };
1304 sinon.stub(db.statement.verificationAttempts, 'get').returns(dbOne);
1305 sinon.stub(db.statement.verificationAttemptsIncrement, 'run').returns(dbResult0);
1306 sinon.stub(db.statement.verificationDone, 'run').returns(dbResult1);
1307 await db.verificationIncomplete(dbCtx, verificationId);
1308 });
1309 it('failure', async function () {
1310 const dbOne = { attempts: 0 };
1311 const dbResult0 = {
1312 changes: 0,
1313 lastInsertRowid: undefined,
1314 };
1315 const dbResult1 = {
1316 changes: 1,
1317 lastInsertRowid: undefined,
1318 };
1319 sinon.stub(db.statement.verificationAttempts, 'get').returns(dbOne);
1320 sinon.stub(db.statement.verificationAttemptsIncrement, 'run').returns(dbResult0);
1321 sinon.stub(db.statement.verificationDone, 'run').returns(dbResult1);
1322 try {
1323 await db.verificationIncomplete(dbCtx, verificationId, retryDelays);
1324 assert.fail(noExpectedException);
1325 } catch (e) {
1326 assert(e instanceof DBErrors.UnexpectedResult);
1327 }
1328 });
1329 it('second failure', async function () {
1330 const dbOne = { attempts: 0 };
1331 const dbResult0 = {
1332 changes: 1,
1333 lastInsertRowid: undefined,
1334 };
1335 const dbResult1 = {
1336 changes: 0,
1337 lastInsertRowid: undefined,
1338 };
1339 sinon.stub(db.statement.verificationAttempts, 'get').returns(dbOne);
1340 sinon.stub(db.statement.verificationAttemptsIncrement, 'run').returns(dbResult0);
1341 sinon.stub(db.statement.verificationDone, 'run').returns(dbResult1);
1342 try {
1343 await db.verificationIncomplete(dbCtx, verificationId, retryDelays);
1344 assert.fail(noExpectedException);
1345 } catch (e) {
1346 assert(e instanceof DBErrors.UnexpectedResult);
1347 }
1348 });
1349 }); // verificationIncomplete
1350
1351 describe('_verificationDataToEngine', function () {
1352 it('covers no data', function () {
1353 DB._verificationDataToEngine();
1354 });
1355 it('covers true', function () {
1356 const data = {
1357 isPublisherValidated: true,
1358 };
1359 DB._verificationDataToEngine(data);
1360 assert.strictEqual(data.isPublisherValidated, 1);
1361 });
1362 it('covers false', function () {
1363 const data = {
1364 isPublisherValidated: false,
1365 };
1366 DB._verificationDataToEngine(data);
1367 assert.strictEqual(data.isPublisherValidated, 0);
1368 });
1369 }) // _verificationDataToEngine
1370
1371 describe('verificationInsert', function () {
1372 let verification;
1373 beforeEach(function () {
1374 verification = {
1375 topicId,
1376 callback,
1377 mode: 'subscribe',
1378 isPublisherValidated: true,
1379 leaseSeconds: 86400,
1380 };
1381 });
1382 it('success', async function() {
1383 const dbResult = {
1384 changes: 1,
1385 lastInsertRowid: verificationId,
1386 };
1387 const expected = verificationId;
1388 sinon.stub(db.statement.verificationInsert, 'run').returns(dbResult);
1389 const result = await db.verificationInsert(dbCtx, verification);
1390 assert.deepStrictEqual(result, expected);
1391 });
1392 it('failure', async function () {
1393 const dbResult = {
1394 changes: 0,
1395 lastInsertRowid: undefined,
1396 };
1397 sinon.stub(db.statement.verificationInsert, 'run').returns(dbResult);
1398 try {
1399 await db.verificationInsert(dbCtx, verification);
1400 assert.fail(noExpectedException);
1401 } catch (e) {
1402 assert(e instanceof DBErrors.UnexpectedResult);
1403 }
1404 });
1405 it('fails validation', async function () {
1406 delete verification.leaseSeconds;
1407 try {
1408 await db.verificationInsert(dbCtx, verification);
1409 assert.fail(noExpectedException);
1410 } catch (e) {
1411 assert(e instanceof DBErrors.DataValidation);
1412 }
1413 });
1414 }); // verificationInsert
1415
1416 describe('verificationRelease', function () {
1417 it('success', async function() {
1418 const dbResult = {
1419 changes: 1,
1420 lastInsertRowid: undefined,
1421 };
1422 sinon.stub(db.statement.verificationDone, 'run').returns(dbResult);
1423 await db.verificationRelease(dbCtx, verificationId);
1424 });
1425 it('failure', async function () {
1426 const dbResult = {
1427 changes: 0,
1428 lastInsertRowid: undefined,
1429 };
1430 sinon.stub(db.statement.verificationDone, 'run').returns(dbResult);
1431 try {
1432 await db.verificationRelease(dbCtx, verificationId);
1433 assert.fail(noExpectedException);
1434 } catch (e) {
1435 assert(e instanceof DBErrors.UnexpectedResult);
1436 }
1437 });
1438 }); // verificationRelease
1439
1440 describe('verificationUpdate', function () {
1441 let data;
1442 beforeEach(function () {
1443 data = {
1444 mode: 'subscribe',
1445 isPublisherValidated: true,
1446 };
1447 });
1448 it('success', async function() {
1449 const dbResult = {
1450 changes: 1,
1451 lastInsertRowid: undefined,
1452 };
1453 sinon.stub(db.statement.verificationUpdate, 'run').returns(dbResult);
1454 await db.verificationUpdate(dbCtx, verificationId, data);
1455 });
1456 it('failure', async function () {
1457 const dbResult = {
1458 changes: 0,
1459 lastInsertRowid: undefined,
1460 }
1461 sinon.stub(db.statement.verificationUpdate, 'run').returns(dbResult);
1462 try {
1463 await db.verificationUpdate(dbCtx, verificationId, data);
1464 assert.fail(noExpectedException);
1465 } catch (e) {
1466 assert(e instanceof DBErrors.UnexpectedResult, e.name);
1467 }
1468 });
1469 it('fails validation', async function () {
1470 delete data.mode;
1471 try {
1472 await db.verificationUpdate(dbCtx, data);
1473 assert.fail(noExpectedException);
1474 } catch (e) {
1475 assert(e instanceof DBErrors.DataValidation);
1476 }
1477 });
1478 }); // verificationUpdate
1479
1480 describe('verificationValidated', function () {
1481 it('success', async function() {
1482 const dbResult = {
1483 changes: 1,
1484 lastInsertRowid: undefined,
1485 }
1486 sinon.stub(db.statement.verificationValidate, 'run').returns(dbResult);
1487 await db.verificationValidated(dbCtx, verificationId);
1488 });
1489 it('failure', async function () {
1490 const dbResult = {
1491 changes: 0,
1492 lastInsertRowid: undefined,
1493 }
1494 sinon.stub(db.statement.verificationValidate, 'run').returns(dbResult);
1495 try {
1496 await db.verificationValidated(dbCtx, verificationId);
1497 assert.fail(noExpectedException);
1498 } catch (e) {
1499 assert(e instanceof DBErrors.UnexpectedResult);
1500 }
1501 });
1502 }); // verificationValidated
1503
1504 }); // DatabasePostgres