-/* eslint-env mocha */
-/* eslint-disable sonarjs/no-identical-functions */
'use strict';
/**
*
*/
-const assert = require('assert');
-const { step } = require('mocha-steps'); // eslint-disable-line node/no-unpublished-require
+const assert = require('node:assert');
+const { step } = require('mocha-steps');
const stubLogger = require('../../stub-logger');
const DBErrors = require('../../../src/db/errors');
const testData = require('../../test-data/db-integration');
assert(db);
});
+ it('is healthy', async function () {
+ const result = await db.healthCheck();
+ assert(result);
+ });
+
describe('Authentication', function () {
- let identifier, credential;
+ let identifier, credential, otpKey;
beforeEach(function () {
identifier = 'username';
credential = 'myEncryptedPassword';
+ otpKey = '1234567890123456789012';
});
- step('create auth entry', async function() {
+ step('create auth entry', async function () {
await db.context(async (dbCtx) => {
await db.authenticationUpsert(dbCtx, identifier, credential);
});
});
- step('get auth entry', async function() {
+ step('get auth entry', async function () {
await db.context(async (dbCtx) => {
const authInfo = await db.authenticationGet(dbCtx, identifier);
assert.strictEqual(authInfo.credential, credential);
});
});
- step('valid auth event', async function() {
+ step('valid auth event', async function () {
await db.context(async (dbCtx) => {
await db.authenticationSuccess(dbCtx, identifier);
const authInfo = await db.authenticationGet(dbCtx, identifier);
assert.notStrictEqual(authInfo.lastAuthentication, undefined);
});
});
- step('update auth entry', async function() {
+ step('update auth entry', async function () {
await db.context(async (dbCtx) => {
credential = 'myNewPassword';
- await db.authenticationUpsert(dbCtx, identifier, credential);
+ await db.authenticationUpsert(dbCtx, identifier, credential, otpKey);
+ const authInfo = await db.authenticationGet(dbCtx, identifier);
+ assert.strictEqual(authInfo.credential, credential);
+ assert.strictEqual(authInfo.otpKey, otpKey);
+ });
+ });
+ step('update auth otp key', async function () {
+ await db.context(async (dbCtx) => {
+ const removedOTPKey = null;
+ await db.authenticationUpdateOTPKey(dbCtx, identifier, removedOTPKey);
+ const authInfo = await db.authenticationGet(dbCtx, identifier);
+ assert.strictEqual(authInfo.otpKey, removedOTPKey);
+ });
+ });
+ step('update credential', async function () {
+ await db.context(async (dbCtx) => {
+ credential = '$plain$anotherCredential';
+ await db.authenticationUpdateCredential(dbCtx, identifier, credential);
const authInfo = await db.authenticationGet(dbCtx, identifier);
assert.strictEqual(authInfo.credential, credential);
});
}); // Authentication
describe('Topic', function () {
+ let anotherTopicId;
step('requires data', async function () {
try {
await db.context(async (dbCtx) => {
const data = {
topicId,
leaseSecondsMin: 60,
- }
+ };
await db.context(async(dbCtx) => {
- let topic = await db.topicGetByUrl(dbCtx, testData.topicSet.url);
+ const expected = await db.topicGetByUrl(dbCtx, testData.topicSet.url, true);
+ expected.leaseSecondsMin = data.leaseSecondsMin;
+ let topic = await db.topicGetByUrl(dbCtx, testData.topicSet.url, false);
await db.topicUpdate(dbCtx, { ...topic, ...data });
topic = await db.topicGetByUrl(dbCtx, testData.topicSet.url);
assert.strictEqual(Number(topic.leaseSecondsMin), data.leaseSecondsMin);
+ assert.deepEqual(topic, expected);
});
});
step('gets topic by id', async function () {
assert.strictEqual(Number(topic.contentFetchAttemptsSinceSuccess), 0);
});
});
+ step('gets publish history', async function () {
+ await db.context(async (dbCtx) => {
+ const result = (await db.topicPublishHistory(dbCtx, topicId, 7))
+ .map((x) => Number(x));
+ const expected = [1, 0, 0, 0, 0, 0, 0];
+ assert.deepStrictEqual(result, expected);
+ });
+ });
step('deletes a topic', async function () {
await db.context(async (dbCtx) => {
const result = await db.topicSet(dbCtx, testData.anotherTopicSet);
- const anotherTopicId = result.lastInsertRowid;
+ anotherTopicId = result.lastInsertRowid;
await db.topicDeleted(dbCtx, anotherTopicId);
const topic = await db.topicGetById(dbCtx, anotherTopicId);
assert.strictEqual(topic.isDeleted, true);
step('update un-deletes a topic', async function () {
await db.context(async (dbCtx) => {
const result = await db.topicSet(dbCtx, testData.anotherTopicSet);
- const anotherTopicId = result.lastInsertRowid;
+ assert.strictEqual(result.lastInsertRowid, anotherTopicId);
const topic = await db.topicGetById(dbCtx, anotherTopicId);
assert.strictEqual(topic.isDeleted, false);
});
assert(topics.length);
});
});
+ // pending delete of deleted topic with no subscriptions
+ step('really deletes unsubscribed deleted topic', async function() {
+ await db.context(async (dbCtx) => {
+ await db.topicDeleted(dbCtx, anotherTopicId);
+ await db.topicPendingDelete(dbCtx, anotherTopicId);
+ const topic = await db.topicGetById(dbCtx, anotherTopicId);
+ assert(!topic);
+ });
+ });
}); // Topic
describe('Subscription', function () {
const data = {
...testData.subscriptionUpsert,
topicId,
- }
+ };
await db.context(async (dbCtx) => {
const result = await db.subscriptionUpsert(dbCtx, data);
assert(result.lastInsertRowid);
step('complete subscription', async function () {
const { callback } = testData.subscriptionUpsert;
await db.context(async (dbCtx) => {
- await db.subscriptionDeliveryComplete(dbCtx, callback, topicId);
+ const topic = await db.topicGetById(dbCtx, topicId);
+ await db.subscriptionDeliveryComplete(dbCtx, callback, topicId, topic.contentUpdated);
const subscription = await db.subscriptionGetById(dbCtx, subscriptionId);
assert.strictEqual(Number(subscription.deliveryAttemptsSinceSuccess), 0);
});
...testData.subscriptionUpsert,
secret: 'newSecret',
topicId,
- }
+ };
await db.context(async (dbCtx) => {
const result = await db.subscriptionUpsert(dbCtx, data);
assert(result.lastInsertRowid);
assert(!subscription);
});
});
+ step('create expired subscription', async function () {
+ const data = {
+ ...testData.subscriptionUpsert,
+ secret: 'newSecret',
+ topicId,
+ leaseSeconds: -1,
+ };
+ await db.context(async (dbCtx) => {
+ const result = await db.subscriptionUpsert(dbCtx, data);
+ assert(result.lastInsertRowid);
+ assert.notStrictEqual(result.lastInsertRowid, subscriptionId);
+ subscriptionId = result.lastInsertRowid;
+ assert.strictEqual(result.changes, 1);
+ });
+ });
+ step('delete expired subscriptions', async function() {
+ await db.context(async (dbCtx) => {
+ await db.subscriptionDeleteExpired(dbCtx, topicId);
+ const subscription = await db.subscriptionGet(dbCtx, testData.subscriptionUpsert.callback, topicId);
+ assert(!subscription);
+ });
+ });
}); // Subscription
describe('Verification', function () {