redeem proffered tickets, db schema 1.1.0
[squeep-indie-auther] / test / src / chores.js
1 /* eslint-env mocha */
2 /* eslint-disable node/no-unpublished-require */
3 'use strict';
4
5 const assert = require('assert');
6 const sinon = require('sinon');
7 const StubDB = require('../stub-db');
8 const StubLogger = require('../stub-logger');
9 const Chores = require('../../src/chores');
10
11 const snooze = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
12
13 const expectedException = new Error('oh no');
14
15 describe('Chores', function () {
16 let chores, stubLogger, stubDb, stubQueuePublisher, options;
17 beforeEach(function () {
18 stubLogger = new StubLogger();
19 stubLogger._reset();
20 stubDb = new StubDB();
21 stubDb._reset();
22 stubQueuePublisher = {
23 publish: sinon.stub(),
24 };
25 });
26 afterEach(function () {
27 chores?.stopAllChores();
28 sinon.restore();
29 });
30
31 describe('constructor', function () {
32 this.slow(200);
33 it('empty options, no cleaning', async function () {
34 options = undefined;
35 chores = new Chores(stubLogger, stubDb, stubQueuePublisher, options);
36 assert.strictEqual(chores.chores.cleanTokens.timeoutObj, undefined);
37 assert.strictEqual(chores.chores.cleanScopes.timeoutObj, undefined);
38 assert.strictEqual(chores.chores.publishTickets.timeoutObj, undefined);
39 });
40
41 it('cleans scopes', async function () {
42 options = {
43 chores: {
44 scopeCleanupMs: 1,
45 },
46 };
47 chores = new Chores(stubLogger, stubDb, stubQueuePublisher, options);
48 await snooze(50);
49 assert(chores.chores.cleanScopes.timeoutObj);
50 assert(chores.db.scopeCleanup.called);
51 });
52
53 it('cleans tokens', async function () {
54 options = {
55 chores: {
56 tokenCleanupMs: 1,
57 },
58 manager: {
59 codeValidityTimeoutMs: 10,
60 },
61 };
62 chores = new Chores(stubLogger, stubDb, stubQueuePublisher, options);
63 await snooze(50);
64 assert(chores.chores.cleanTokens.timeoutObj);
65 assert(chores.db.tokenCleanup.called);
66 });
67
68 it('publishes tickets', async function () {
69 options = {
70 chores: {
71 publishTicketsMs: 1,
72 },
73 queues: {
74 ticketRedeemedName: 'queue',
75 },
76 };
77 chores = new Chores(stubLogger, stubDb, stubQueuePublisher, options);
78 await snooze(50);
79 assert(chores.chores.publishTickets.timeoutObj);
80 assert(chores.db.ticketTokenGetUnpublished.called);
81 });
82
83 }); // constructor
84
85 describe('cleanTokens', function () {
86 it('logs cleaning', async function () {
87 const cleaned = 10;
88 options = {
89 chores: {
90 tokenCleanupMs: 100,
91 },
92 manager: {
93 codeValidityTimeoutMs: 10,
94 },
95 };
96 stubDb.tokenCleanup.resolves(cleaned);
97 chores = new Chores(stubLogger, stubDb, stubQueuePublisher, options);
98 clearTimeout(chores.cleanTokensTimeout);
99 await chores.cleanTokens();
100 assert(stubLogger.info.called);
101 });
102 it('covers failure', async function () {
103 options = {
104 chores: {
105 tokenCleanupMs: 1,
106 },
107 manager: {
108 codeValidityTimeoutMs: 10,
109 },
110 };
111 stubDb.tokenCleanup.rejects(expectedException);
112 chores = new Chores(stubLogger, stubDb, stubQueuePublisher, options);
113 await assert.rejects(() => chores.cleanTokens(), expectedException);
114 });
115 it('covers default', async function () {
116 stubDb.tokenCleanup.resolves(0);
117 chores = new Chores(stubLogger, stubDb, stubQueuePublisher, {
118 manager: {
119 codeValidityTimeoutMs: 10,
120 },
121 });
122 await chores.cleanTokens();
123 assert(stubDb.tokenCleanup.called);
124 });
125 }); // cleanTokens
126
127 describe('cleanScopes', function () {
128 it('logs cleaning', async function () {
129 const cleaned = 10;
130 options = {
131 chores: {
132 scopeCleanupMs: 100,
133 },
134 };
135 stubDb.scopeCleanup.resolves(cleaned);
136 chores = new Chores(stubLogger, stubDb, stubQueuePublisher, options);
137 clearTimeout(chores.cleanScopesTimeout);
138 await chores.cleanScopes();
139 assert(stubLogger.info.called);
140 });
141 it('covers failure', async function () {
142 options = {
143 chores: {
144 scopeCleanupMs: 1,
145 },
146 };
147 stubDb.scopeCleanup.rejects(expectedException);
148 chores = new Chores(stubLogger, stubDb, stubQueuePublisher, options);
149 await assert.rejects(() => chores.cleanScopes(), expectedException);
150 });
151 it('covers default', async function () {
152 stubDb.scopeCleanup.resolves(0);
153 chores = new Chores(stubLogger, stubDb, stubQueuePublisher, {});
154 await chores.cleanScopes();
155 assert(stubDb.scopeCleanup.called);
156 });
157 }); // cleanScopes
158
159 describe('publishTickets', function () {
160 beforeEach(function () {
161 options = {
162 queues: {
163 ticketRedeemedName: 'queue',
164 },
165 };
166 stubDb.ticketTokenGetUnpublished.resolves([{
167 ticket: 'xxxTICKETxxx',
168 resource: 'https://resource.example.com/',
169 subject: 'https://subject.example.com/',
170 iss: null,
171 }]);
172 chores = new Chores(stubLogger, stubDb, stubQueuePublisher, options);
173 });
174 it('publishes a ticket', async function () {
175 await chores.publishTickets();
176 assert(stubQueuePublisher.publish.called);
177 assert(stubDb.ticketTokenPublished.called);
178 });
179 it('covers error', async function () {
180 stubQueuePublisher.publish.rejects(expectedException);
181 await chores.publishTickets();
182 assert(stubQueuePublisher.publish.called);
183 assert(stubDb.ticketTokenPublished.notCalled);
184 });
185 }); // publishTickets
186
187 }); // Chores