9d7dbf9dbe3ae8cff770008b7afb42425c7a3362
4 const assert
= require('assert');
5 const sinon
= require('sinon'); // eslint-disable-line node/no-unpublished-require
7 const StubDatabase
= require('../../stub-db');
8 const StubLogger
= require('../../stub-logger');
9 const DB
= require('../../../src/db/abstract');
10 const DBErrors
= require('../../../src/db/errors');
12 describe('DatabaseBase', function () {
13 let db
, logger
, stubDb
;
15 logger
= new StubLogger();
17 stubDb
= new StubDatabase();
19 beforeEach(function () {
20 db
= new DB(logger
, {});
22 afterEach(function () {
26 it('covers no options', function () {
30 describe('Interface', function () {
31 it('covers abstract methods', async
function () {
32 await Promise
.all(stubDb
._implementation
.map(async (m
) => {
34 // eslint-disable-next-line security/detect-object-injection
36 assert
.fail(`${m}: did not catch NotImplemented exception`);
38 assert(e
instanceof DBErrors
.NotImplemented
, `${m}: unexpected exception ${e.name}`);
41 }); // covers abstract methods
42 it('covers private abstract methods', async
function () {
46 // eslint-disable-next-line security/detect-object-injection
49 assert(e
instanceof DBErrors
.NotImplemented
, `${m}: unexpected exception ${e.name}`);
55 describe('_isUUID', function () {
56 it('is a uuid', function () {
57 const result
= DB
._isUUID('8fde351e-2d63-11ed-8b0c-0025905f714a');
58 assert
.strictEqual(result
, true);
60 it('is not a uuid', function () {
61 const result
= DB
._isUUID('not a uuid');
62 assert
.strictEqual(result
, false);
66 describe('_isInfinites', function () {
67 it('is true for Infinity', function () {
68 const result
= DB
._isInfinites(Infinity
);
69 assert
.strictEqual(result
, true);
71 it('is true for negative Infinity', function () {
72 const result
= DB
._isInfinites(-Infinity
);
73 assert
.strictEqual(result
, true);
75 it('is false for finite value', function () {
76 const result
= DB
._isInfinites(5);
77 assert
.strictEqual(result
, false);
79 it('is false for NaN', function () {
80 const result
= DB
._isInfinites(NaN
);
81 assert
.strictEqual(result
, false);
85 describe('_ensureTypes', function () {
87 beforeEach(function () {
89 array: ['foo', 'bar'],
91 buf: Buffer
.from('foop'),
96 uuid: 'a4dd5106-2d64-11ed-a2ba-0025905f714a',
100 it('succeeds', function () {
101 db
._ensureTypes(object
, ['array'], ['array']);
102 db
._ensureTypes(object
, ['bignum', 'num'], ['number']);
103 db
._ensureTypes(object
, ['buf'], ['buffer']);
104 db
._ensureTypes(object
, ['date'], ['date']);
105 db
._ensureTypes(object
, ['str', 'veryNull'], ['string', 'null']);
107 it('data failure', function () {
109 db
._ensureTypes(object
, ['missingField'], ['string', 'null']);
110 assert
.fail('validation should have failed');
112 assert(e
instanceof DBErrors
.DataValidation
);
115 it('failure covers singular', function () {
117 db
._ensureTypes(object
, ['missingField'], ['string']);
118 assert
.fail('validation should have failed');
120 assert(e
instanceof DBErrors
.DataValidation
);
123 it('parameter failure', function () {
125 db
._ensureTypes(object
, ['missingField'], undefined);
126 assert
.fail('validation should have failed');
128 assert(e
instanceof DBErrors
.DataValidation
);
133 describe('_validateAuthentication', function () {
135 beforeEach(function () {
137 identifier: 'username',
138 credential: '$plain$secret',
140 lastAuthenticated: -Infinity
,
143 it('covers', function () {
144 db
._validateAuthentication(authentication
);
146 it('covers failure', function () {
147 assert
.throws(() => db
._validateAuthentication(undefined), DBErrors
.DataValidation
);
149 }); // _validateAuthentication
151 describe('_validateResource', function () {
153 beforeEach(function () {
155 resourceId: '42016c1e-2d66-11ed-9e10-0025905f714a',
156 secret: 'secretSecret',
157 description: 'Some other service',
161 it('covers', function () {
162 db
._validateResource(resource
);
164 it('covers failure', function () {
165 assert
.throws(() => db
._validateResource(undefined), DBErrors
.DataValidation
);
167 }); // _validateResource
169 describe('_validateToken', function () {
171 beforeEach(function () {
173 codeId: '9efc7882-2d66-11ed-b03c-0025905f714a',
174 profile: 'https://profile.example.com/',
176 clientId: 'https://app.example.com/',
179 refreshExpires: null,
185 name: 'User von Namey',
189 it('covers', function () {
190 db
._validateToken(token
);
192 it('covers failure', function () {
193 assert
.throws(() => db
._validateToken(undefined), DBErrors
.DataValidation
);
195 }); // _validateToken
197 describe('_profilesScopesBuilder', function () {
198 it('covers empty', function () {
199 const result
= DB
._profilesScopesBuilder();
200 assert
.deepStrictEqual(result
, {
206 it('builds expected structure', function () {
207 const profileScopesRows
= [
208 { profile: 'https://scopeless.example.com/', scope: null, description: null, application: null, isPermanent: null, isManuallyAdded: null },
209 { profile: 'https://profile.example.com/', scope: 'role:private', description: 'level', application: '', isPermanent: false, isManuallyAdded: true },
210 { profile: null, scope: 'profile', description: 'profile', application: 'IndieAuth', isPermanent: true, isManuallyAdded: false },
211 { profile: null, scope: 'role:private', description: 'level', application: '', isPermanent: false, isManuallyAdded: true },
212 { profile: null, scope: 'read', description: 'read', application: 'MicroPub', isPermanent: true, isManuallyAdded: false },
213 { profile: 'https://profile.example.com/', scope: 'profile', description: 'profile', application: 'IndieAuth', isPermanent: true, isManuallyAdded: false },
214 { profile: 'https://another.example.com/', scope: 'profile', description: 'profile', application: 'IndieAuth', isPermanent: true, isManuallyAdded: false },
218 'https://scopeless.example.com/': {},
219 'https://profile.example.com/': {},
220 'https://another.example.com/': {},
224 description: 'level',
227 isManuallyAdded: true,
228 profiles: ['https://profile.example.com/'],
231 description: 'profile',
232 application: 'IndieAuth',
234 isManuallyAdded: false,
235 profiles: ['https://profile.example.com/', 'https://another.example.com/'],
239 application: 'MicroPub',
241 isManuallyAdded: false,
245 profiles: ['https://scopeless.example.com/', 'https://profile.example.com/', 'https://another.example.com/'],
247 expected
.profileScopes
['https://profile.example.com/']['role:private'] = expected
.scopeIndex
['role:private'];
248 expected
.profileScopes
['https://profile.example.com/']['profile'] = expected
.scopeIndex
['profile'];
249 expected
.profileScopes
['https://another.example.com/']['profile'] = expected
.scopeIndex
['profile'];
251 const result
= DB
._profilesScopesBuilder(profileScopesRows
);
252 assert
.deepStrictEqual(result
, expected
);
254 }); // _profilesScopesBuilder
256 describe('initialize', function () {
258 beforeEach(function () {
264 db
.schemaVersionsSupported
= {
265 min: { ...currentSchema
},
266 max: { ...currentSchema
},
268 sinon
.stub(db
, '_currentSchema').resolves(currentSchema
);
270 it('covers success', async
function () {
271 await db
.initialize();
273 it('covers failure', async
function() {
274 db
.schemaVersionsSupported
= {
287 await db
.initialize();
288 assert
.fail('did not get expected exception');
290 assert(e
instanceof DBErrors
.MigrationNeeded
);