sinon.restore();
});
+ it('covers listener', function () {
+ const listenerOptions = new Config('test');
+ listenerOptions.db.cacheEnabled = true;
+ const listenerDb = new DB(stubLogger, listenerOptions, pgpStub);
+ assert(listenerDb);
+ });
+
// Ensure all interface methods are implemented
describe('Implementation', function () {
it('implements interface', async function () {
db.pgpInitOptions.query(event);
assert(db.logger.debug.called);
});
+ it('covers NOTIFY', function () {
+ const event = { query: 'NOTIFY thing' };
+ db.pgpInitOptions.query(event);
+ assert(!db.logger.debug.called);
+ });
}); // query
describe('receive', function () {
it('covers', function () {
assert(db.logger.debug.called);
assert.deepStrictEqual(data, expectedData);
});
+ it('covers NOTIFY', function () {
+ const data = [
+ {
+ column_one: 'one', // eslint-disable-line camelcase
+ column_two: 2, // eslint-disable-line camelcase
+ },
+ {
+ column_one: 'foo', // eslint-disable-line camelcase
+ column_two: 4, // eslint-disable-line camelcase
+ },
+ ];
+ const result = {
+ command: 'NOTIFY',
+ };
+ const event = {};
+ const expectedData = [
+ {
+ columnOne: 'one',
+ columnTwo: 2,
+ },
+ {
+ columnOne: 'foo',
+ columnTwo: 4,
+ },
+ ];
+ db.pgpInitOptions.receive(data, result, event)
+ assert(!db.logger.debug.called);
+ assert.deepStrictEqual(data, expectedData);
+ });
}); // receive
}); // pgpInitOptions
});
}); // _initTables
- describe('schemaCheck', function () {
+ describe('initialize', function () {
+ after(function () {
+ delete db.listener;
+ });
it('passes supported version', async function () {
const version = { major: 1, minor: 0, patch: 0 };
sinon.stub(db.db, 'one').resolves(version);
- await db.schemaCheck(false);
+ await db.initialize(false);
});
it('fails low version', async function () {
const version = { major: 0, minor: 0, patch: 0 };
sinon.stub(db.db, 'one').resolves(version);
try {
- await db.schemaCheck(false);
+ await db.initialize(false);
assert.fail(noExpectedException);
} catch (e) {
assert(e instanceof DBErrors.MigrationNeeded);
const version = { major: 100, minor: 100, patch: 100 };
sinon.stub(db.db, 'one').resolves(version);
try {
- await db.schemaCheck(false);
+ await db.initialize(false);
assert.fail(noExpectedException);
} catch (e) {
assert(e instanceof DBErrors.MigrationNeeded);
});
it('covers migration', async function() {
sinon.stub(db.db, 'oneOrNone').resolves({});
- sinon.stub(db.db, 'multiResult');
- sinon.stub(db, '_currentSchema').resolves(db.schemaVersionsSupported.max);
+ sinon.stub(db.db, 'multiResult').resolves({});
+ sinon.stub(db, '_currentSchema').resolves(db.schemaVersionsSupported.min);
+ sinon.stub(db.db, 'one').resolves(db.schemaVersionsSupported.max);
+ await db.initialize();
+ });
+ it('covers migration failure', async function() {
+ const expected = new Error('oh no');
+ sinon.stub(db.db, 'oneOrNone').resolves({});
+ sinon.stub(db.db, 'multiResult').rejects(expected);
+ sinon.stub(db, '_currentSchema').resolves(db.schemaVersionsSupported.min);
sinon.stub(db.db, 'one').resolves(db.schemaVersionsSupported.max);
- await db.schemaCheck();
+ try {
+ await db.initialize();
+ assert.fail(noExpectedException);
+ } catch (e) {
+ assert.deepStrictEqual(e, expected);
+ }
});
- }); // schemaCheck
+ it('covers listener', async function() {
+ db.listener = {
+ start: sinon.stub(),
+ };
+ const version = { major: 1, minor: 0, patch: 0 };
+ sinon.stub(db.db, 'one').resolves(version);
+ await db.initialize(false);
+ assert(db.listener.start.called);
+ });
+ }); // initialize
describe('healthCheck', function () {
beforeEach(function () {
}); // _queryFileHelper
describe('_closeConnection', function () {
+ after(function () {
+ delete db.listener;
+ });
it('success', async function () {
sinon.stub(db._pgp, 'end');
await db._closeConnection();
assert.deepStrictEqual(e, expected);
}
});
+ it('covers listener', async function () {
+ db.listener = {
+ stop: sinon.stub(),
+ };
+ sinon.stub(db._pgp, 'end');
+ await db._closeConnection();
+ assert(db._pgp.end.called);
+ });
}); // _closeConnection
describe('_purgeTables', function () {
});
}); // _purgeTables
+ describe('_topicChanged', function () {
+ beforeEach(function () {
+ db.cache = new Map();
+ sinon.stub(db.cache, 'delete');
+ });
+ after(function () {
+ delete db.cache;
+ });
+ it('covers', function () {
+ db._topicChanged('topic-id');
+ assert(db.cache.delete.called);
+ });
+ it('ignores ping', function () {
+ db._topicChanged('ping');
+ assert(!db.cache.delete.called);
+ });
+ }); // _topicChanged
+
+ describe('_listenerEstablished', function () {
+ it('creates cache', function () {
+ delete db.cache;
+ db._listenerEstablished();
+ assert(db.cache instanceof Map);
+ });
+ }); // _listenerEstablished
+
+ describe('_listenerLost', function () {
+ it('removes cache', function () {
+ db.cache = new Map();
+ db._listenerLost();
+ assert(!db.cache);
+ });
+ }); // _listenerLost
+
+ describe('_cacheGet', function () {
+ let key;
+ beforeEach(function () {
+ key = 'key';
+ });
+ it('nothing if no cache', function () {
+ delete db.cache;
+ const result = db._cacheGet(key);
+ assert.strictEqual(result, undefined);
+ });
+ it('nothing if no entry', function () {
+ db.cache = new Map();
+ const result = db._cacheGet(key);
+ assert.strictEqual(result, undefined);
+ });
+ it('returns cached entry', function () {
+ db.cache = new Map();
+ const expected = {
+ foo: 'bar',
+ };
+ db._cacheSet(key, expected);
+ const result = db._cacheGet(key);
+ assert.deepStrictEqual(result, expected);
+ });
+ }); // _cacheGet
+
+ describe('_cacheSet', function () {
+ let key;
+ beforeEach(function () {
+ key = 'key';
+ });
+ it('covers no cache', function () {
+ delete db.cache;
+ db._cacheSet(key, 'data');
+ });
+ it('covers cache', function () {
+ db.cache = new Map();
+ const expected = 'blah';
+ db._cacheSet(key, expected);
+ const result = db._cacheGet(key);
+ assert.deepStrictEqual(result, expected);
+ });
+ }); // _cacheSet
+
describe('context', function () {
it('covers', async function () {
await db.context(common.nop);
changes: 1,
lastInsertRowid: undefined,
duration: 10,
- }
+ };
sinon.stub(db.db, 'result').resolves(dbResult);
const result = await db.subscriptionDelete(dbCtx, callback, topicId);
assert.deepStrictEqual(result, expected);
});
}); // subscriptionDelete
+ describe('subscriptionDeleteExpired', function () {
+ it('success', async function () {
+ const dbResult = {
+ rowCount: 1,
+ rows: [],
+ duration: 10,
+ };
+ const expected = {
+ changes: 1,
+ lastInsertRowid: undefined,
+ duration: 10,
+ };
+ sinon.stub(db.db, 'result').resolves(dbResult);
+ const result = await db.subscriptionDeleteExpired(dbCtx, topicId);
+ assert.deepStrictEqual(result, expected);
+ });
+ it('failure', async function() {
+ const expected = new Error();
+ sinon.stub(db.db, 'result').rejects(expected);
+ try {
+ await db.subscriptionDeleteExpired(dbCtx, topicId);
+ assert.fail(noExpectedException);
+ } catch (e) {
+ assert.deepStrictEqual(e, expected);
+ }
+ });
+ });
+
describe('subscriptionDeliveryClaim', function () {
it('success', async function() {
const dbResult = [
}); // subscriptionDeliveryClaimById
describe('subscriptionDeliveryComplete', function () {
+ let topicContentUpdated;
+ before(function () {
+ topicContentUpdated = new Date();
+ });
it('success', async function() {
const dbResult = {
rowCount: 1,
};
sinon.stub(db.db, 'result').resolves(dbResult);
- await db.subscriptionDeliveryComplete(dbCtx, callback, topicId);
+ await db.subscriptionDeliveryComplete(dbCtx, callback, topicId, topicContentUpdated);
});
it('failure', async function () {
const dbResult = {
};
sinon.stub(db.db, 'result').onCall(0).resolves(dbResult);
try {
- await db.subscriptionDeliveryComplete(dbCtx, callback, topicId);
+ await db.subscriptionDeliveryComplete(dbCtx, callback, topicId, topicContentUpdated);
assert.fail(noExpectedException);
} catch (e) {
assert(e instanceof DBErrors.UnexpectedResult);
};
sinon.stub(db.db, 'result').onCall(0).resolves(dbResult0).onCall(1).resolves(dbResult1);
try {
- await db.subscriptionDeliveryComplete(dbCtx, callback, topicId);
+ await db.subscriptionDeliveryComplete(dbCtx, callback, topicId, topicContentUpdated);
assert.fail(noExpectedException);
} catch (e) {
assert(e instanceof DBErrors.UnexpectedResult);
}); // topicGetByUrl
describe('topicGetContentById', function () {
+ let topic;
+ beforeEach(function () {
+ delete db.cache;
+ topic = {
+ id: topicId,
+ };
+ });
it('success', async function() {
- const expected = { id: topicId };
+ const expected = topic;
sinon.stub(db.db, 'oneOrNone').resolves(expected);
const result = await db.topicGetContentById(dbCtx, topicId);
assert.deepStrictEqual(result, expected);
assert.deepStrictEqual(e, expected);
}
});
+ it('caches success', async function () {
+ db.cache = new Map();
+ const expected = topic;
+ sinon.stub(db.db, 'oneOrNone').resolves(expected);
+ const result = await db.topicGetContentById(dbCtx, topicId);
+ assert.deepStrictEqual(result, expected);
+ });
+ it('covers cached entry', async function() {
+ let result;
+ db.cache = new Map();
+ const expected = topic;
+ sinon.stub(db.db, 'oneOrNone').resolves(expected);
+ result = await db.topicGetContentById(dbCtx, topicId);
+ assert.deepStrictEqual(result, expected);
+ result = await db.topicGetContentById(dbCtx, topicId);
+ assert.deepStrictEqual(result, expected);
+ });
}); // topicGetContentById
+ describe('topicPendingDelete', function () {
+ beforeEach(function () {
+ sinon.stub(db.db, 'one');
+ sinon.stub(db.db, 'result');
+ });
+ it('success', async function () {
+ db.db.one.onCall(0).resolves({
+ id: topicId,
+ isDeleted: true,
+ }).onCall(1).resolves({
+ count: 0,
+ });
+ const dbResult = {
+ rowCount: 1,
+ rows: [],
+ duration: 10,
+ };
+ db.db.result.resolves(dbResult);
+ await db.topicPendingDelete(dbCtx, topicId);
+ assert(db.db.result.called);
+ });
+ it('does not delete non-deleted topic', async function () {
+ db.db.one.onCall(0).resolves({
+ id: topicId,
+ isDeleted: false,
+ }).onCall(1).resolves({
+ count: 0,
+ });
+ await db.topicPendingDelete(dbCtx, topicId);
+ assert(!db.db.result.called);
+ });
+ it('does not delete topic with active subscriptions', async function () {
+ db.db.one.onCall(0).resolves({
+ id: topicId,
+ isDeleted: true,
+ }).onCall(1).resolves({
+ count: 10,
+ });
+ await db.topicPendingDelete(dbCtx, topicId);
+ assert(!db.db.result.called);
+ });
+ it('covers no deletion', async function () {
+ db.db.one.onCall(0).resolves({
+ id: topicId,
+ isDeleted: true,
+ }).onCall(1).resolves({
+ count: 0,
+ });
+ const dbResult = {
+ rowCount: 0,
+ rows: [],
+ duration: 10,
+ };
+ db.db.result.resolves(dbResult);
+ try {
+ await db.topicPendingDelete(dbCtx, topicId);
+ assert.fail(noExpectedException);
+ } catch (e) {
+ assert(e instanceof DBErrors.UnexpectedResult);
+ }
+ });
+ });
+
describe('topicSet', function () {
let data;
beforeEach(function () {
contentType: 'text/plain',
contentHash: 'abc123',
};
+ sinon.stub(db.db, 'result');
});
it('success', async function() {
const dbResult = {
lastInsertRowid: undefined,
duration: 10,
};
- sinon.stub(db.db, 'result').resolves(dbResult);
+ db.db.result.resolves(dbResult);
const result = await db.topicSetContent(dbCtx, data);
assert.deepStrictEqual(result, expected);
});
rows: [],
duration: 10,
};
- sinon.stub(db.db, 'result').resolves(dbResult);
+ db.db.result.resolves(dbResult);
+ try {
+ await db.topicSetContent(dbCtx, data);
+ assert.fail(noExpectedException);
+ } catch (e) {
+ assert(e instanceof DBErrors.UnexpectedResult);
+ }
+ });
+ it('failure 2', async function () {
+ const dbResultSuccess = {
+ rowCount: 1,
+ rows: [],
+ duration: 10,
+ };
+ const dbResultFail = {
+ rowCount: 0,
+ rows: [],
+ duration: 10,
+ };
+ db.db.result
+ .onCall(0).resolves(dbResultSuccess)
+ .onCall(1).resolves(dbResultFail);
try {
await db.topicSetContent(dbCtx, data);
assert.fail(noExpectedException);
}
});
- });
+ }); // topicUpdate
describe('verificationClaim', function () {
it('success', async function() {