bf74e973033ae70d3f734c8284a5861bdb9c9c55
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 () {
47 // eslint-disable-next-line security/detect-object-injection
50 assert(e
instanceof DBErrors
.NotImplemented
, `${m}: unexpected exception ${e.name}`);
56 describe('_ensureTypes', function () {
58 beforeEach(function () {
60 array: ['foo', 'bar'],
62 buf: Buffer
.from('foop'),
69 uuid: 'a4dd5106-2d64-11ed-a2ba-0025905f714a',
73 it('succeeds', function () {
74 db
._ensureTypes(object
, ['array'], ['array']);
75 db
._ensureTypes(object
, ['bignum'], ['bigint']);
76 db
._ensureTypes(object
, ['bignum', 'num'], ['number']);
77 db
._ensureTypes(object
, ['buf'], ['buffer']);
78 db
._ensureTypes(object
, ['date'], ['date']);
79 db
._ensureTypes(object
, ['infP', 'infN'], ['infinites']);
80 db
._ensureTypes(object
, ['str', 'veryNull'], ['string', 'null']);
82 it('data failure', function () {
83 assert
.throws(() => db
._ensureTypes(object
, ['missingField'], ['string', 'null']), DBErrors
.DataValidation
);
85 it('failure covers singular', function () {
87 db
._ensureTypes(object
, ['missingField'], ['string']);
88 assert
.fail('validation should have failed');
90 assert(e
instanceof DBErrors
.DataValidation
);
93 it('parameter failure', function () {
95 db
._ensureTypes(object
, ['missingField'], undefined);
96 assert
.fail('validation should have failed');
98 assert(e
instanceof DBErrors
.DataValidation
);
101 it('covers unknown type', function () {
102 assert
.throws(() => db
._ensureTypes(object
, ['field'], ['not a type']));
106 describe('_validateAuthentication', function () {
108 beforeEach(function () {
110 identifier: 'username',
111 credential: '$plain$secret',
113 lastAuthentication: -Infinity
,
116 it('covers', function () {
117 db
._validateAuthentication(authentication
);
119 it('covers failure', function () {
120 assert
.throws(() => db
._validateAuthentication(undefined), DBErrors
.DataValidation
);
122 }); // _validateAuthentication
124 describe('_validateResource', function () {
126 beforeEach(function () {
128 resourceId: '42016c1e-2d66-11ed-9e10-0025905f714a',
129 secret: 'secretSecret',
130 description: 'Some other service',
134 it('covers', function () {
135 db
._validateResource(resource
);
137 it('covers failure', function () {
138 assert
.throws(() => db
._validateResource(undefined), DBErrors
.DataValidation
);
140 }); // _validateResource
142 describe('_validateToken', function () {
144 beforeEach(function () {
146 codeId: '9efc7882-2d66-11ed-b03c-0025905f714a',
147 profile: 'https://profile.example.com/',
149 clientId: 'https://app.example.com/',
152 refreshExpires: null,
158 name: 'User von Namey',
162 it('covers', function () {
163 db
._validateToken(token
);
165 it('covers failure', function () {
166 assert
.throws(() => db
._validateToken(undefined), DBErrors
.DataValidation
);
168 }); // _validateToken
170 describe('_profilesScopesBuilder', function () {
171 it('covers empty', function () {
172 const result
= DB
._profilesScopesBuilder();
173 assert
.deepStrictEqual(result
, {
179 it('builds expected structure', function () {
180 const profileScopesRows
= [
181 { profile: 'https://scopeless.example.com/', scope: null, description: null, application: null, isPermanent: null, isManuallyAdded: null },
182 { profile: 'https://profile.example.com/', scope: 'role:private', description: 'level', application: '', isPermanent: false, isManuallyAdded: true },
183 { profile: null, scope: 'profile', description: 'profile', application: 'IndieAuth', isPermanent: true, isManuallyAdded: false },
184 { profile: null, scope: 'role:private', description: 'level', application: '', isPermanent: false, isManuallyAdded: true },
185 { profile: null, scope: 'read', description: 'read', application: 'MicroPub', isPermanent: true, isManuallyAdded: false },
186 { profile: 'https://profile.example.com/', scope: 'profile', description: 'profile', application: 'IndieAuth', isPermanent: true, isManuallyAdded: false },
187 { profile: 'https://another.example.com/', scope: 'profile', description: 'profile', application: 'IndieAuth', isPermanent: true, isManuallyAdded: false },
191 'https://scopeless.example.com/': {},
192 'https://profile.example.com/': {},
193 'https://another.example.com/': {},
197 description: 'level',
200 isManuallyAdded: true,
201 profiles: ['https://profile.example.com/'],
204 description: 'profile',
205 application: 'IndieAuth',
207 isManuallyAdded: false,
208 profiles: ['https://profile.example.com/', 'https://another.example.com/'],
212 application: 'MicroPub',
214 isManuallyAdded: false,
218 profiles: ['https://scopeless.example.com/', 'https://profile.example.com/', 'https://another.example.com/'],
220 expected
.profileScopes
['https://profile.example.com/']['role:private'] = expected
.scopeIndex
['role:private'];
221 expected
.profileScopes
['https://profile.example.com/']['profile'] = expected
.scopeIndex
['profile'];
222 expected
.profileScopes
['https://another.example.com/']['profile'] = expected
.scopeIndex
['profile'];
224 const result
= DB
._profilesScopesBuilder(profileScopesRows
);
225 assert
.deepStrictEqual(result
, expected
);
227 }); // _profilesScopesBuilder
229 describe('initialize', function () {
231 beforeEach(function () {
237 db
.schemaVersionsSupported
= {
238 min: { ...currentSchema
},
239 max: { ...currentSchema
},
241 sinon
.stub(db
, '_currentSchema').resolves(currentSchema
);
243 it('covers success', async
function () {
244 await db
.initialize();
246 it('covers failure', async
function() {
247 db
.schemaVersionsSupported
= {
260 await db
.initialize();
261 assert
.fail('did not get expected exception');
263 assert(e
instanceof DBErrors
.MigrationNeeded
);