X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=test%2Fsrc%2Fmanager.js;h=cbd83243d3faecabdf8d77667151a230ac180f88;hb=737fbd003d5c4dfea81b667ef906f1c106a60612;hp=7870a55b45b62df6d4a8c3192501467c20b1e5c1;hpb=ed6dc5a66ce0eaf2dd61f9fb7a5ec048944c68ee;p=websub-hub diff --git a/test/src/manager.js b/test/src/manager.js index 7870a55..cbd8324 100644 --- a/test/src/manager.js +++ b/test/src/manager.js @@ -33,10 +33,12 @@ describe('Manager', function () { }; ctx = { params: {}, + queryParams: {}, }; manager = new Manager(stubLogger, stubDb, options); sinon.stub(manager.communication, 'verificationProcess'); sinon.stub(manager.communication, 'topicFetchProcess'); + sinon.stub(manager.communication, 'topicFetchClaimAndProcessById'); stubDb._reset(); stubLogger._reset(); }); @@ -58,18 +60,6 @@ describe('Manager', function () { await manager.getRoot(req, res, ctx); assert(res.end.called); }); - it('repeat response', async function () { - manager.startTime = (new Date()).toGMTString(); - common.isClientCached.returns(true); - await manager.getRoot(req, res, ctx); - assert(res.end.called); - }); - it('cached response', async function () { - common.isClientCached.returns(true); - await manager.getRoot(req, res, ctx); - assert(res.end.called); - assert.strictEqual(res.statusCode, 304); - }); }); // getRoot describe('getHealthcheck', function () { @@ -148,8 +138,33 @@ describe('Manager', function () { }); }); // getInfo - describe('getAdminOverview', function () { + describe('_historyBarCaption', function () { + it('covers today, none', function () { + const result = Manager._historyBarCaption(0, 0); + assert.strictEqual(result, 'today, no updates'); + }); + it('covers yesterday, singular', function () { + const result = Manager._historyBarCaption(1, 1); + assert.strictEqual(result, 'yesterday, 1 update'); + }); + it('covers older, plural', function () { + const result = Manager._historyBarCaption(7, 3); + assert.strictEqual(result, '7 days ago, 3 updates'); + }); + }); // _historyBarCaption + + describe('getHistorySVG', function () { + beforeEach(function () { + manager.db.topicPublishHistory.resolves([0, 1, 2, 1, 0, 1, 2, 0, 1]); + }); it('covers', async function () { + await manager.getHistorySVG(res, ctx); + assert(res.end.called); + }); + }); // getHistorySVG + + describe('getAdminOverview', function () { + beforeEach(function () { manager.db.topicGetAll.resolves([ { id: '56c557ce-e667-11eb-bd80-0025905f714a', @@ -171,13 +186,23 @@ describe('Manager', function () { subscribers: 12, }, ]); + }); + it('covers', async function () { await manager.getAdminOverview(res, ctx); assert(res.end.called); }); - }); + it('covers non-matching profile', async function () { + ctx.session = { + authenticatedProfile: 'https://different.example.com/profile', + }; + await manager.getAdminOverview(res, ctx); + assert.deepStrictEqual(ctx.topics, []); + assert(res.end.called); + }); + }); // getAdminOverview describe('getTopicDetails', function () { - it('covers', async function() { + beforeEach(function () { ctx.params.topicId = '56c557ce-e667-11eb-bd80-0025905f714a'; manager.db.topicGetById.resolves({ id: '56c557ce-e667-11eb-bd80-0025905f714a', @@ -213,7 +238,26 @@ describe('Manager', function () { deliveryAttemptsSinceSuccess: 0, deliveryNextAttempt: new Date(-Infinity), }]); + manager.db.topicPublishHistory.resolves([0, 1, 0, 1, 0]); + }); + it('covers', async function() { + await manager.getTopicDetails(res, ctx); + assert(res.end.called); + }); + it('covers non-matching profile', async function () { + ctx.session = { + authenticatedProfile: 'https://different.example.com/profile', + }; + await manager.getTopicDetails(res, ctx); + assert.strictEqual(ctx.topic, null); + assert(res.end.called); + }); + it('covers matching profile', async function () { + ctx.session = { + authenticatedProfile: 'https://example.com/profile', + }; await manager.getTopicDetails(res, ctx); + assert(ctx.topic); assert(res.end.called); }); }); // getTopicDetails @@ -559,13 +603,11 @@ describe('Manager', function () { }); }); // _checkMode - describe('_checkPublish', function () { - let dbCtx, data, warn, err, requestId; + describe('_publishTopics', function () { + let dbCtx, data, requestId; beforeEach(function () { dbCtx = {}; data = {}; - warn = []; - err = []; requestId = 'blah'; }); it('succeeds', async function () { @@ -573,26 +615,29 @@ describe('Manager', function () { id: 222, }); Object.assign(data, testData.validPublishRootData); - await manager._checkPublish(dbCtx, data, warn, err, requestId); - assert.strictEqual(warn.length, 0, 'unexpected warnings length'); - assert.strictEqual(err.length, 0, 'unexpected errors length'); - assert.strictEqual(data.topicId, 222, 'unexpected topic id'); + const topicResults = await manager._publishTopics(dbCtx, data, requestId); + assert.strictEqual(topicResults.length, 1); + assert.strictEqual(topicResults[0].warn.length, 0, 'unexpected warnings length'); + assert.strictEqual(topicResults[0].err.length, 0, 'unexpected errors length'); + assert.strictEqual(topicResults[0].topicId, 222, 'unexpected topic id'); }); it('fails bad url', async function () { Object.assign(data, testData.validPublishRootData, { topic: 'not_a_url' }); - await manager._checkPublish(dbCtx, data, warn, err, requestId); - assert.strictEqual(err.length, 1, 'unexpected errors length'); - assert.strictEqual(warn.length, 0); + const topicResults = await manager._publishTopics(dbCtx, data, requestId); + assert.strictEqual(topicResults.length, 1); + assert.strictEqual(topicResults[0].err.length, 1, 'unexpected errors length'); + assert.strictEqual(topicResults[0].warn.length, 0); }); it('accepts new public publish topic', async function () { manager.db.topicGetByUrl.onCall(0).resolves().onCall(1).resolves({ id: 222, }); Object.assign(data, testData.validPublishRootData); - await manager._checkPublish(dbCtx, data, warn, err, requestId); - assert.strictEqual(warn.length, 0, 'unexpected warnings length'); - assert.strictEqual(err.length, 0, 'unexpected errors length'); - assert.strictEqual(data.topicId, 222, 'unexpected topic id'); + const topicResults = await manager._publishTopics(dbCtx, data, requestId); + assert.strictEqual(topicResults.length, 1); + assert.strictEqual(topicResults[0].warn.length, 0, 'unexpected warnings length'); + assert.strictEqual(topicResults[0].err.length, 0, 'unexpected errors length'); + assert.strictEqual(topicResults[0].topicId, 222, 'unexpected topic id'); }); it('does not publish deleted topic', async function () { manager.db.topicGetByUrl.resolves({ @@ -600,12 +645,176 @@ describe('Manager', function () { isDeleted: true, }); Object.assign(data, testData.validPublishRootData); - await manager._checkPublish(dbCtx, data, warn, err, requestId); - assert.strictEqual(warn.length, 0, 'unexpected warnings length'); - assert.strictEqual(err.length, 1, 'unexpected errors length'); - assert.strictEqual(data.topicId, undefined, 'unexpected topic id'); + const topicResults = await manager._publishTopics(dbCtx, data, requestId); + assert.strictEqual(topicResults.length, 1); + assert.strictEqual(topicResults[0].warn.length, 0, 'unexpected warnings length'); + assert.strictEqual(topicResults[0].err.length, 1, 'unexpected errors length'); + assert.strictEqual(topicResults[0].topicId, undefined, 'unexpected topic id'); + }); + it('no topics', async function() { + Object.assign(data, testData.validPublishRootData); + delete data.topic; + const topicResults = await manager._publishTopics(dbCtx, data, requestId); + assert.strictEqual(topicResults.length, 0); + }); + it('multiple valid topics', async function () { + manager.db.topicGetByUrl.resolves({ + id: 222, + }); + Object.assign(data, testData.validPublishRootData); + data.url = ['https://example.com/first', 'https://example.com/second']; + data.topic = ['https://example.com/third']; + const topicResults = await manager._publishTopics(dbCtx, data, requestId); + assert.strictEqual(topicResults.length, 3); + assert.strictEqual(topicResults[0].warn.length, 0, 'unexpected warnings length'); + assert.strictEqual(topicResults[0].err.length, 0, 'unexpected errors length'); + assert.strictEqual(topicResults[0].topicId, 222, 'unexpected topic id'); + assert.strictEqual(topicResults[1].warn.length, 0, 'unexpected warnings length'); + assert.strictEqual(topicResults[1].err.length, 0, 'unexpected errors length'); + assert.strictEqual(topicResults[1].topicId, 222, 'unexpected topic id'); + assert.strictEqual(topicResults[2].warn.length, 0, 'unexpected warnings length'); + assert.strictEqual(topicResults[2].err.length, 0, 'unexpected errors length'); + assert.strictEqual(topicResults[2].topicId, 222, 'unexpected topic id'); + }); + it('mix of valid and invalid topics', async function () { + manager.db.topicGetByUrl.onCall(1).resolves().resolves({ + id: 222, + }); + Object.assign(data, testData.validPublishRootData); + data.url = ['https://example.com/first', 'not a url']; + data.topic = ['https://example.com/third']; + const topicResults = await manager._publishTopics(dbCtx, data, requestId); + assert.strictEqual(topicResults.length, 3); + assert.strictEqual(topicResults[0].warn.length, 0, 'unexpected warnings length'); + assert.strictEqual(topicResults[0].err.length, 0, 'unexpected errors length'); + assert.strictEqual(topicResults[0].topicId, 222, 'unexpected topic id'); + assert.strictEqual(topicResults[1].warn.length, 0, 'unexpected warnings length'); + assert.strictEqual(topicResults[1].err.length, 1, 'unexpected errors length'); + assert.strictEqual(topicResults[1].topicId, undefined, 'unexpected topic id'); + assert.strictEqual(topicResults[2].warn.length, 0, 'unexpected warnings length'); + assert.strictEqual(topicResults[2].err.length, 0, 'unexpected errors length'); + assert.strictEqual(topicResults[2].topicId, 222, 'unexpected topic id'); + }); + }); // _publishTopics + + describe('_publishRequest', function () { + let dbCtx, data, res, ctx; + beforeEach(function () { + dbCtx = {}; + data = {}; + res = { + end: sinon.stub(), + }; + ctx = {}; + }); + it('requires a topic', async function () { + try { + await manager._publishRequest(dbCtx, data, res, ctx); + assert.fail(noExpectedException); + } catch (e) { + assert(e instanceof Errors.ResponseError); + } + }); + it('processes one topic', async function() { + manager.db.topicGetByUrl.resolves({ + id: 222, + }); + Object.assign(data, testData.validPublishRootData); + manager.db.topicFetchRequested.resolves(); + await manager._publishRequest(dbCtx, data, res, ctx); + assert(manager.db.topicFetchRequested.called); + assert.strictEqual(res.statusCode, 202); + assert(res.end.called); + }); + it('processes mix of valid and invalid topics', async function () { + ctx.responseType = 'application/json'; + manager.db.topicGetByUrl.onCall(1).resolves().resolves({ + id: 222, + }); + Object.assign(data, testData.validPublishRootData); + data.url = ['https://example.com/first', 'not a url']; + data.topic = ['https://example.com/third']; + await manager._publishRequest(dbCtx, data, res, ctx); + assert.strictEqual(res.statusCode, 207); + assert(res.end.called); + }); + it('covers topicFetchRequest failure', async function () { + manager.db.topicGetByUrl.resolves({ + id: 222, + }); + Object.assign(data, testData.validPublishRootData); + const expected = new Error('boo'); + manager.db.topicFetchRequested.rejects(expected); + try { + await manager._publishRequest(dbCtx, data, res, ctx); + assert.fail(noExpectedException); + } catch (e) { + assert.deepStrictEqual(e, expected); + } }); - }); // _checkPublish + it('covers immediate processing error', async function() { + manager.options.manager.processImmediately = true; + manager.db.topicGetByUrl.onCall(0).resolves().onCall(1).resolves({ + id: 222, + }); + manager.communication.topicFetchClaimAndProcessById.rejects(); + Object.assign(data, testData.validPublishRootData); + await manager._publishRequest(dbCtx, data, res, ctx); + assert(manager.db.topicFetchRequested.called); + assert.strictEqual(res.statusCode, 202); + assert(res.end.called); + assert(manager.communication.topicFetchClaimAndProcessById.called) + }); + it('covers no immediate processing', async function() { + manager.options.manager.processImmediately = false; + manager.db.topicGetByUrl.onCall(0).resolves().onCall(1).resolves({ + id: 222, + }); + Object.assign(data, testData.validPublishRootData); + await manager._publishRequest(dbCtx, data, res, ctx); + assert(manager.db.topicFetchRequested.called); + assert.strictEqual(res.statusCode, 202); + assert(res.end.called); + assert(!manager.communication.topicFetchClaimAndProcessById.called) + }); + }); // _publishRequest + + describe('multiPublishContent', function () { + let publishTopics; + beforeEach(function () { + publishTopics = [{ + url: 'https://example.com/first', + warn: [], + err: [], + topicId: 222, + status: 202, + statusMessage: 'Accepted', + }, + { + url: 'not a url', + warn: [], + err: [ 'invalid topic url (failed to parse url)' ], + topicId: undefined, + status: 400, + statusMessage: 'Bad Request', + }]; + }); + it('covers json response', function () { + ctx.responseType = 'application/json'; + const expected = '[{"href":"https://example.com/first","status":202,"statusMessage":"Accepted","errors":[],"warnings":[]},{"href":"not a url","status":400,"statusMessage":"Bad Request","errors":["invalid topic url (failed to parse url)"],"warnings":[]}]'; + const result = Manager.multiPublishContent(ctx, publishTopics); + assert.deepStrictEqual(result, expected); + }); + it('covers text response', function () { + ctx.responseType = 'text/plain'; + const expected = `https://example.com/first [202 Accepted] +---- +not a url [400 Bad Request] +\terror: invalid topic url (failed to parse url)`; + const result = Manager.multiPublishContent(ctx, publishTopics); + assert.deepStrictEqual(result, expected); + }); + }); // multiPublishContent describe('processTasks', function () { it('covers', async function () {