auth cleanups
[urlittler] / test / src / db / sqlite / index.js
1 'use strict';
2
3 const assert = require('node:assert');
4 const sinon = require('sinon');
5 const DBErrors = require('../../../../src/db/errors');
6
7 const noExpectedException = 'did not get expected exception';
8
9 describe('SQLiteDatabase', function () {
10 const SQLiteDatabase = require('../../../../src/db/sqlite');
11 let db, logger, options, dbCtx;
12
13 beforeEach(function () {
14 logger = {
15 debug: sinon.stub(),
16 info: sinon.stub(),
17 error: sinon.stub(),
18 };
19 options = {};
20 db = new SQLiteDatabase(logger, options);
21 dbCtx = undefined;
22 });
23
24 describe('context', function () {
25 it('covers', async function () {
26 const fn = sinon.stub();
27 await db.context(fn);
28 assert(fn.called);
29 });
30 }); // context
31
32 describe('transaction', function () {
33 it('covers', async function () {
34 const fn = sinon.stub();
35 await db.transaction(dbCtx, fn);
36 assert(fn.called);
37 });
38 it('covers rollback', async function () {
39 const fn = sinon.stub();
40 fn.throws(new Error('rollback'));
41 try {
42 await db.transaction(dbCtx, fn);
43 assert.fail(noExpectedException);
44 } catch (e) {
45 assert.strictEqual(e.message, 'rollback', noExpectedException);
46 }
47 });
48 }); // transaction
49
50 describe('getAuthById', function () {
51 let id;
52 beforeEach(function () {
53 sinon.stub(db.statement.getAuthById, 'get');
54 });
55
56 it('stubbed success', async function () {
57 const expected = {
58 id: 'id',
59 secret: 'secret',
60 password: 'password',
61 };
62 id = 'id';
63 db.statement.getAuthById.get.returns(expected);
64 const result = await db.getAuthById(dbCtx, id);
65 assert.deepStrictEqual(result, expected);
66 });
67 it('stubbed failure', async function () {
68 const expectedExeption = new Error('blah');
69 id = 'id';
70 db.statement.getAuthById.get.throws(expectedExeption);
71 try {
72 await db.getAuthById(dbCtx, id);
73 assert.fail(noExpectedException);
74 } catch (e) {
75 assert.deepStrictEqual(e, expectedExeption, noExpectedException);
76 }
77 });
78 }); // getAuthById
79
80 describe('upsertAuth', function () {
81 let id, secret, credential;
82 beforeEach(function () {
83 sinon.stub(db.statement.insertAuth, 'run').returns({ changes: 1n, lastInsertRowid: 123n });
84 sinon.stub(db.statement.updateAuth, 'run').returns({ changes: 1n, lastInsertRowid: 123n });
85 });
86 it('stubbed insert success', async function () {
87 await db.upsertAuth(dbCtx, id, secret, credential);
88 });
89 it('stubbed update success', async function () {
90 db.statement.insertAuth.run.throws({ code: 'SQLITE_CONSTRAINT_UNIQUE' });
91 await db.upsertAuth(dbCtx, id, secret, credential);
92 });
93 it('covers error', async function () {
94 const expectedException = new Error('blah');
95 db.statement.insertAuth.run.throws(expectedException);
96 try {
97 await db.upsertAuth(dbCtx, id, secret, credential);
98 assert.fail(noExpectedException);
99 } catch (e) {
100 assert.deepStrictEqual(e, expectedException, noExpectedException);
101 }
102 });
103 it('covers unexpected error', async function () {
104 const expectedException = DBErrors.UnexpectedResult;
105 const returns = {
106 changes: 0n,
107 lastInsertRowid: undefined,
108 };
109 db.statement.insertAuth.run.returns(returns);
110 try {
111 await db.upsertAuth(dbCtx, id, secret, credential);
112 assert.fail(noExpectedException);
113 } catch (e) {
114 assert(e instanceof expectedException, noExpectedException);
115 }
116 });
117 }); // upsertAuth
118
119 describe('insertLink', function () {
120 let id, url, authToken;
121 beforeEach(function () {
122 sinon.stub(db.statement.insertLink, 'run');
123 sinon.stub(db.statement.updateLink, 'run');
124 });
125
126 it('stubbed insert success', async function () {
127 const info = {
128 changes: BigInt(1),
129 lastInsertRowid: BigInt(123),
130 };
131 id = 'id';
132 db.statement.insertLink.run.returns(info);
133 const expected = {
134 changes: 1,
135 lastInsertRowid: 123,
136 };
137 const result = await db.insertLink(dbCtx, id, url, authToken);
138 assert.deepStrictEqual(result, expected);
139 });
140 it('stubbed update success', async function () {
141 const info = {
142 changes: BigInt(1),
143 lastInsertRowid: BigInt(123),
144 };
145 id = 'id';
146 db.statement.insertLink.run.throws({ code: 'SQLITE_CONSTRAINT_UNIQUE' });
147 db.statement.updateLink.run.returns(info);
148 const expected = {
149 changes: 1,
150 lastInsertRowid: 123,
151 };
152 const result = await db.insertLink(dbCtx, id, url, authToken);
153 assert.deepStrictEqual(result, expected);
154 });
155 it('stubbed failure', async function () {
156 const expectedExeption = new Error('blah');
157 id = 'id';
158 db.statement.insertLink.run.throws(expectedExeption);
159 try {
160 await db.insertLink(dbCtx, id, url, authToken);
161 assert.fail(noExpectedException);
162 } catch (e) {
163 assert.deepStrictEqual(e, expectedExeption, noExpectedException);
164 }
165 });
166 it('stubbed unexpected failure', async function () {
167 const expectedException = DBErrors.UnexpectedResult;
168 const returns = {
169 changes: 0,
170 lastInsertRowid: undefined,
171 };
172 id = 'id';
173 db.statement.insertLink.run.returns(returns);
174 try {
175 await db.insertLink(dbCtx, id, url, authToken);
176 assert.fail(noExpectedException);
177 } catch (e) {
178 assert(e instanceof expectedException);
179 }
180 });
181 }); // insertLink
182
183 describe('getLinkById', function () {
184 let id;
185
186 beforeEach(function () {
187 sinon.stub(db.statement.getLinkById, 'get');
188 });
189
190 it('stubbed success', async function () {
191 const returns = {
192 id: 'id',
193 isSpecial: false,
194 url: 'url',
195 created: 0,
196 expires: 0,
197 'auth_token': 'abc',
198 'last_access': 0,
199 accesses: 0,
200 };
201 const expected = {
202 id: 'id',
203 isSpecial: false,
204 url: 'url',
205 created: 0,
206 expires: 0,
207 authToken: 'abc',
208 lastAccess: 0,
209 accesses: 0,
210 };
211 id = 'id';
212 db.statement.getLinkById.get.returns(returns);
213 const result = await db.getLinkById(dbCtx, id);
214 assert.deepStrictEqual(result, expected);
215 });
216 it('stubbed failure', async function () {
217 const expectedExeption = new Error('blah');
218 id = 'id';
219 db.statement.getLinkById.get.throws(expectedExeption);
220 try {
221 await db.getLinkById(dbCtx, id);
222 assert.fail(noExpectedException);
223 } catch (e) {
224 assert.deepStrictEqual(e, expectedExeption, noExpectedException);
225 }
226 });
227 }); // getLinkById
228
229 describe('getLinkByUrl', function () {
230 let url;
231
232 beforeEach(function () {
233 sinon.stub(db.statement.getLinkByUrl, 'get');
234 });
235
236 it('stubbed success', async function () {
237 const returns = {
238 id: 'id',
239 isSpecial: false,
240 url: 'url',
241 created: 0,
242 expires: 123,
243 'auth_token': 'abc',
244 'last_access': 0,
245 accesses: 0,
246 };
247 const expected = {
248 id: 'id',
249 isSpecial: false,
250 url: 'url',
251 created: 0,
252 expires: 123,
253 authToken: 'abc',
254 lastAccess: 0,
255 accesses: 0,
256 };
257 url = 'url';
258 db.statement.getLinkByUrl.get.returns(returns);
259 const result = await db.getLinkByUrl(dbCtx, url);
260 assert.deepStrictEqual(result, expected);
261 });
262 it('stubbed failure', async function () {
263 const expectedExeption = new Error('blah');
264 url = 'url';
265 db.statement.getLinkByUrl.get.throws(expectedExeption);
266 try {
267 await db.getLinkByUrl(dbCtx, url);
268 assert.fail(noExpectedException);
269 } catch (e) {
270 assert.deepStrictEqual(e, expectedExeption, noExpectedException);
271 }
272 });
273 }); // getLinkByUrl
274
275 describe('accessLink', function () {
276 let id;
277
278 beforeEach(function () {
279 sinon.stub(db.statement.getLinkById, 'get');
280 sinon.stub(db.statement.incrementLinkAccess, 'run');
281 });
282
283 it('stubbed exists success', async function () {
284 const returns = {
285 id: 'id',
286 isSpecial: false,
287 url: 'url',
288 created: 0,
289 expires: 0,
290 'auth_token': 'abc',
291 'last_access': 0,
292 accesses: 0,
293 };
294 const expected = {
295 id: 'id',
296 isSpecial: false,
297 url: 'url',
298 created: 0,
299 expires: 0,
300 authToken: 'abc',
301 lastAccess: 0,
302 accesses: 0,
303 };
304 id = 'id';
305 db.statement.getLinkById.get.returns(returns);
306 db.statement.incrementLinkAccess.run.returns({ changes: 1 });
307 const result = await db.accessLink(dbCtx, id);
308 assert.deepStrictEqual(result, expected);
309 });
310 it('stubbed missing success', async function () {
311 const returns = undefined;
312 const expected = undefined;
313 id = 'id';
314 db.statement.getLinkById.get.returns(returns);
315 db.statement.incrementLinkAccess.run.returns({ changes: 0 });
316 const result = await db.accessLink(dbCtx, id);
317 assert.deepStrictEqual(result, expected);
318 });
319 it('stubbed increment failure', async function () {
320 const expectedExeption = DBErrors.UnexpectedResult;
321 const returns = {
322 id: 'id',
323 url: 'url',
324 created: 0,
325 expires: 0,
326 'auth_token': 'abc',
327 'last_access': 0,
328 accesses: 0,
329 };
330 id = 'id';
331 db.statement.getLinkById.get.returns(returns);
332 db.statement.incrementLinkAccess.run.returns({ changes: 0 });
333 try {
334 await db.accessLink(dbCtx, id);
335 assert.fail(noExpectedException);
336 } catch (e) {
337 assert(e instanceof expectedExeption, noExpectedException);
338 }
339 });
340 it('stubbed failure', async function () {
341 const expectedExeption = new Error('blah');
342 id = 'id';
343 db.statement.getLinkById.get.throws(expectedExeption);
344 try {
345 await db.accessLink(dbCtx, id);
346 assert.fail(noExpectedException);
347 } catch (e) {
348 assert.deepStrictEqual(e, expectedExeption, noExpectedException);
349 }
350 });
351 }); // accessLink
352
353 describe('expireLink', function () {
354 let id, expires;
355
356 beforeEach(function () {
357 sinon.stub(db.statement.expireLink, 'run');
358 });
359
360 it('stubbed success', async function () {
361 const returns = {
362 changes: 1,
363 lastInsertRowid: 123,
364 };
365 const expected = {
366 changes: 1,
367 lastInsertRowid: 123,
368 };
369 id = 'id';
370 expires = null;
371 db.statement.expireLink.run.returns(returns);
372 const result = await db.expireLink(dbCtx, id, expires);
373 assert.deepStrictEqual(result, expected);
374 });
375 it('stubbed change failure', async function () {
376 const expectedExeption = DBErrors.UnexpectedResult;
377 const returns = {
378 changes: 0,
379 lastInsertRowid: undefined,
380 };
381 id = 'id';
382 db.statement.expireLink.run.returns(returns);
383 try {
384 await db.expireLink(dbCtx, id);
385 assert.fail(noExpectedException);
386 } catch (e) {
387 assert(e instanceof expectedExeption, noExpectedException);
388 }
389 });
390 it('stubbed failure', async function () {
391 const expectedExeption = new Error('blah');
392 id = 'id';
393 expires = null;
394 db.statement.expireLink.run.throws(expectedExeption);
395 try {
396 await db.expireLink(dbCtx, id, expires);
397 assert.fail(noExpectedException);
398 } catch (e) {
399 assert.deepStrictEqual(e, expectedExeption, noExpectedException);
400 }
401 });
402 }); // expireLink
403
404 describe('updateLink', function () {
405 let id, expires;
406
407 beforeEach(function () {
408 sinon.stub(db.statement.updateLink, 'run');
409 });
410
411 it('stubbed success', async function () {
412 const returns = {
413 changes: 1,
414 lastInsertRowid: 1,
415 };
416 const expected = {
417 changes: 1,
418 lastInsertRowid: 1,
419 };
420 id = 'id';
421 expires = null;
422 db.statement.updateLink.run.returns(returns);
423 const result = await db.updateLink(dbCtx, id, expires);
424 assert.deepStrictEqual(result, expected);
425 });
426 it('stubbed change failure', async function () {
427 const expectedExeption = DBErrors.UnexpectedResult;
428 const returns = {
429 changes: 0,
430 lastInsertRowid: undefined,
431 };
432 id = 'id';
433 db.statement.updateLink.run.returns(returns);
434 try {
435 await db.updateLink(dbCtx, id);
436 assert.fail(noExpectedException);
437 } catch (e) {
438 assert(e instanceof expectedExeption, noExpectedException);
439 }
440 });
441 it('stubbed failure', async function () {
442 const expectedExeption = new Error('blah');
443 id = 'id';
444 expires = null;
445 db.statement.updateLink.run.throws(expectedExeption);
446 try {
447 await db.updateLink(dbCtx, id, expires);
448 assert.fail(noExpectedException);
449 } catch (e) {
450 assert.deepStrictEqual(e, expectedExeption, noExpectedException);
451 }
452 });
453 }); // updateLink
454
455 describe('getAllLinks', function () {
456 beforeEach(function () {
457 sinon.stub(db.statement.linkGetAll, 'all');
458 });
459
460 it('stubbed success', async function () {
461 const returns = [
462 {
463 id: 'id',
464 isSpecial: false,
465 url: 'url',
466 created: 0,
467 expires: 0,
468 'auth_token': 'abc',
469 'last_access': 0,
470 accesses: 0,
471 },
472 ];
473 const expected = [
474 {
475 id: 'id',
476 isSpecial: false,
477 url: 'url',
478 created: 0,
479 expires: 0,
480 authToken: 'abc',
481 lastAccess: 0,
482 accesses: 0,
483 },
484 ];
485 db.statement.linkGetAll.all.returns(returns);
486 const result = await db.getAllLinks(dbCtx);
487 assert.deepStrictEqual(result, expected);
488 });
489 it('stubbed failure', async function () {
490 const expectedExeption = new Error('blah');
491 db.statement.linkGetAll.all.throws(expectedExeption);
492 try {
493 await db.getAllLinks(dbCtx);
494 assert.fail(noExpectedException);
495 } catch (e) {
496 assert.deepStrictEqual(e, expectedExeption, noExpectedException);
497 }
498 });
499 }); // getAllLinks
500
501 describe('_optimize', function () {
502 let cslo, oac;
503 beforeEach(function () {
504 cslo = db.changesSinceLastOptimize;
505 oac = db.optimizeAfterChanges;
506 sinon.stub(db.db, 'prepare').returns({
507 all: sinon.stub(),
508 });
509 sinon.stub(db.db, 'pragma');
510 });
511 afterEach(function () {
512 db.changesSinceLastOptimize = cslo;
513 db.optimizeAfterChanges = oac;
514 });
515 it('covers', function () {
516 db._optimize();
517 assert(db.db.pragma.called);
518 });
519 it('_maybeOptimize', function () {
520 db.changesSinceLastOptimize = BigInt(1000);
521 db.optimizeAfterChanges = BigInt(10);
522 sinon.stub(db, '_optimize');
523 db._maybeOptimize();
524 assert(db._optimize.called);
525 });
526 });
527
528 });