From 9b27804276e4eb6a6f7544fcd4d1d092c171dc04 Mon Sep 17 00:00:00 2001 From: Aileen Booker Date: Fri, 2 Jun 2023 08:18:28 -0400 Subject: [PATCH] Added tests for `DomainEventsAnalytics` no issue - Added unit tests for newly added `DomainEventsAnalytics` class to verify intended functionality --- .../segment/DomainEventsAnalytics.test.js | 199 ++++++++++++++++++ .../server/services/segment/index.test.js | 2 +- 2 files changed, 200 insertions(+), 1 deletion(-) create mode 100644 ghost/core/test/unit/server/services/segment/DomainEventsAnalytics.test.js diff --git a/ghost/core/test/unit/server/services/segment/DomainEventsAnalytics.test.js b/ghost/core/test/unit/server/services/segment/DomainEventsAnalytics.test.js new file mode 100644 index 0000000000..64e7e176e9 --- /dev/null +++ b/ghost/core/test/unit/server/services/segment/DomainEventsAnalytics.test.js @@ -0,0 +1,199 @@ +const assert = require('assert'); +const sinon = require('sinon'); +const ObjectId = require('bson-objectid').default; + +// To test +const DomainEventsAnalytics = require('../../../../../core/server/services/segment/DomainEventsAnalytics'); + +// Stubbed dependencies +const DomainEvents = require('@tryghost/domain-events'); +const {MilestoneCreatedEvent} = require('@tryghost/milestones'); +const logging = require('@tryghost/logging'); + +describe('DomainEventsAnalytics', function () { + describe('Constructor', function () { + it('doesn\'t throw', function () { + new DomainEventsAnalytics({}); + }); + }); + + describe('Domain events analytics service', function () { + let domainAnalytics; + let analyticsStub; + let sentryStub; + let loggingStub; + + beforeEach(function () { + analyticsStub = sinon.stub(); + sentryStub = sinon.stub(); + loggingStub = sinon.stub(logging, 'error'); + }); + + afterEach(function () { + sinon.restore(); + }); + + it('subscribes to events', async function () { + const domainEventsStub = sinon.stub(DomainEvents, 'subscribe').resolves(); + + domainAnalytics = new DomainEventsAnalytics({ + analytics: analyticsStub, + trackDefaults: { + userId: '1234', + properties: {email: 'john@test.com'} + }, + prefix: 'Pro: ', + sentry: { + captureException: sentryStub + } + }); + + domainAnalytics.subscribeToDomainEvents(); + assert(domainEventsStub.callCount === 1); + assert(loggingStub.callCount === 0); + }); + + it('handles milestone created event for 100 members', async function () { + domainAnalytics = new DomainEventsAnalytics({ + analytics: { + track: analyticsStub + }, + trackDefaults: { + userId: '1234', + properties: {email: 'john@test.com'} + }, + prefix: 'Pro: ', + sentry: { + captureException: sentryStub + } + }); + + domainAnalytics.subscribeToDomainEvents(); + + DomainEvents.dispatch(MilestoneCreatedEvent.create({ + milestone: { + id: new ObjectId().toHexString(), + type: 'members', + value: 100, + createdAt: new Date(), + emailSentAt: new Date() + } + })); + + await DomainEvents.allSettled(); + + assert(analyticsStub.callCount === 1); + assert(analyticsStub.calledWith({ + userId: '1234', + properties: {email: 'john@test.com'}, + event: 'Pro: 100 members reached' + })); + + DomainEvents.dispatch(MilestoneCreatedEvent.create({ + milestone: { + id: new ObjectId().toHexString(), + type: 'members', + value: 1000, + createdAt: new Date(), + emailSentAt: new Date() + } + })); + + await DomainEvents.allSettled(); + // Analytics should not be called again + assert(analyticsStub.callCount === 1); + assert(loggingStub.callCount === 0); + }); + + it('handles milestone created event for $100 ARR', async function () { + domainAnalytics = new DomainEventsAnalytics({ + analytics: { + track: analyticsStub + }, + trackDefaults: { + userId: '9876', + properties: {email: 'john+arr@test.com'} + }, + prefix: 'Pro: ', + sentry: { + captureException: sentryStub + } + }); + + domainAnalytics.subscribeToDomainEvents(); + + DomainEvents.dispatch(MilestoneCreatedEvent.create({ + milestone: { + id: new ObjectId().toHexString(), + type: 'arr', + currency: 'usd', + value: 100, + createdAt: new Date(), + emailSentAt: new Date() + } + })); + + await DomainEvents.allSettled(); + + assert(analyticsStub.callCount === 1); + assert(analyticsStub.calledWith({ + userId: '9876', + properties: {email: 'john+arr@test.com'}, + event: 'Pro: $100 MRR reached' + })); + assert(loggingStub.callCount === 0); + + DomainEvents.dispatch(MilestoneCreatedEvent.create({ + milestone: { + id: new ObjectId().toHexString(), + type: 'arr', + currency: 'usd', + value: 1000, + createdAt: new Date(), + emailSentAt: new Date() + } + })); + + await DomainEvents.allSettled(); + // Analytics should not be called again + assert(analyticsStub.callCount === 1); + assert(loggingStub.callCount === 0); + }); + + it('can handle tracking errors', async function () { + let error = new Error('Test error'); + domainAnalytics = new DomainEventsAnalytics({ + analytics: { + track: analyticsStub.throws(error) + }, + trackDefaults: {}, + prefix: '', + sentry: { + captureException: sentryStub + } + }); + + domainAnalytics.subscribeToDomainEvents(); + + try { + DomainEvents.dispatch(MilestoneCreatedEvent.create({ + milestone: { + id: new ObjectId().toHexString(), + type: 'arr', + currency: 'usd', + value: 100, + createdAt: new Date(), + emailSentAt: new Date() + } + })); + + await DomainEvents.allSettled(); + } catch (err) { + assert(analyticsStub.callCount === 1); + assert(sentryStub.callCount === 1); + assert(sentryStub.calledWith(error)); + assert(loggingStub.callCount === 1); + } + }); + }); +}); diff --git a/ghost/core/test/unit/server/services/segment/index.test.js b/ghost/core/test/unit/server/services/segment/index.test.js index dd049b28cb..c123a7db96 100644 --- a/ghost/core/test/unit/server/services/segment/index.test.js +++ b/ghost/core/test/unit/server/services/segment/index.test.js @@ -6,6 +6,6 @@ describe('Segment Analytics Service', function () { it('Provides expected public API', async function () { segmentService = require('../../../../../core/server/services/segment'); - assert.ok(segmentService.initAndRun); + assert.ok(segmentService.init); }); });