X-Git-Url: https://git.squeep.com/?a=blobdiff_plain;f=test%2Fsrc%2Fdb%2Fintegration.js;h=eed37e2c55f5070c4031f4c47d1a8491ace96588;hb=3ca7fccb306d0b23626befc3791ffa360b3db1e7;hp=3cb07f94c02c1b8bae89e8fd4620e0abf7a453f0;hpb=9696c012e6b9a6c58904baa397ca0ebf78112316;p=websub-hub diff --git a/test/src/db/integration.js b/test/src/db/integration.js index 3cb07f9..eed37e2 100644 --- a/test/src/db/integration.js +++ b/test/src/db/integration.js @@ -1,5 +1,3 @@ -/* eslint-env mocha */ -/* eslint-disable sonarjs/no-identical-functions */ 'use strict'; /** @@ -16,8 +14,8 @@ * */ -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'); @@ -69,7 +67,7 @@ describe('Database Integration', function () { // eslint-disable-next-line security/detect-non-literal-require DB = require(i.module); db = new DB(stubLogger, i.config); - await db.schemaCheck(); + await db.initialize(); await db._purgeTables(true); }); after(async function () { @@ -79,34 +77,57 @@ describe('Database Integration', function () { 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); }); @@ -114,6 +135,7 @@ describe('Database Integration', function () { }); // Authentication describe('Topic', function () { + let anotherTopicId; step('requires data', async function () { try { await db.context(async (dbCtx) => { @@ -147,12 +169,15 @@ describe('Database Integration', function () { 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 () { @@ -219,10 +244,18 @@ describe('Database Integration', 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); @@ -231,7 +264,7 @@ describe('Database Integration', function () { 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); }); @@ -242,6 +275,15 @@ describe('Database Integration', function () { 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 () { @@ -259,7 +301,7 @@ describe('Database Integration', function () { const data = { ...testData.subscriptionUpsert, topicId, - } + }; await db.context(async (dbCtx) => { const result = await db.subscriptionUpsert(dbCtx, data); assert(result.lastInsertRowid); @@ -318,7 +360,8 @@ describe('Database Integration', function () { 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); }); @@ -337,7 +380,7 @@ describe('Database Integration', function () { ...testData.subscriptionUpsert, secret: 'newSecret', topicId, - } + }; await db.context(async (dbCtx) => { const result = await db.subscriptionUpsert(dbCtx, data); assert(result.lastInsertRowid); @@ -372,6 +415,28 @@ describe('Database Integration', function () { 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 () {