2019-06-21 05:57:43 -04:00
|
|
|
const SandboxedModule = require('sandboxed-module')
|
|
|
|
const path = require('path')
|
2020-11-04 08:35:37 -05:00
|
|
|
const sinon = require('sinon')
|
2021-09-30 11:28:07 -04:00
|
|
|
const MockRequest = require('../helpers/MockRequest')
|
|
|
|
const MockResponse = require('../helpers/MockResponse')
|
|
|
|
const { assert } = require('chai')
|
2020-11-04 08:35:37 -05:00
|
|
|
|
|
|
|
const MODULE_PATH = path.join(
|
2019-06-21 05:57:43 -04:00
|
|
|
__dirname,
|
|
|
|
'../../../../app/src/Features/Analytics/AnalyticsManager'
|
|
|
|
)
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe('AnalyticsManager', function () {
|
|
|
|
beforeEach(function () {
|
2019-06-21 05:57:43 -04:00
|
|
|
this.fakeUserId = '123abc'
|
2021-09-30 11:28:07 -04:00
|
|
|
this.analyticsId = 'ecdb935a-52f3-4f91-aebc-7a70d2ffbb55'
|
2020-11-04 08:35:37 -05:00
|
|
|
this.Settings = {
|
2021-04-27 03:52:58 -04:00
|
|
|
analytics: { enabled: true },
|
2020-11-04 08:35:37 -05:00
|
|
|
}
|
2021-03-31 05:24:39 -04:00
|
|
|
this.analyticsEventsQueue = {
|
|
|
|
add: sinon.stub().resolves(),
|
2021-04-27 03:52:58 -04:00
|
|
|
process: sinon.stub().resolves(),
|
2021-03-31 05:24:39 -04:00
|
|
|
}
|
|
|
|
this.analyticsEditingSessionQueue = {
|
|
|
|
add: sinon.stub().resolves(),
|
2021-04-27 03:52:58 -04:00
|
|
|
process: sinon.stub().resolves(),
|
2021-03-31 05:24:39 -04:00
|
|
|
}
|
|
|
|
this.onboardingEmailsQueue = {
|
|
|
|
add: sinon.stub().resolves(),
|
2021-04-27 03:52:58 -04:00
|
|
|
process: sinon.stub().resolves(),
|
2021-03-31 05:24:39 -04:00
|
|
|
}
|
2021-05-19 04:29:39 -04:00
|
|
|
this.analyticsUserPropertiesQueue = {
|
|
|
|
add: sinon.stub().resolves(),
|
|
|
|
process: sinon.stub().resolves(),
|
|
|
|
}
|
2021-03-31 05:24:39 -04:00
|
|
|
const self = this
|
2020-11-04 08:35:37 -05:00
|
|
|
this.Queues = {
|
2021-03-31 05:24:39 -04:00
|
|
|
getAnalyticsEventsQueue: () => {
|
|
|
|
return self.analyticsEventsQueue
|
|
|
|
},
|
|
|
|
getAnalyticsEditingSessionsQueue: () => {
|
|
|
|
return self.analyticsEditingSessionQueue
|
|
|
|
},
|
|
|
|
getOnboardingEmailsQueue: () => {
|
|
|
|
return self.onboardingEmailsQueue
|
2021-04-27 03:52:58 -04:00
|
|
|
},
|
2021-05-19 04:29:39 -04:00
|
|
|
getAnalyticsUserPropertiesQueue: () => {
|
|
|
|
return self.analyticsUserPropertiesQueue
|
|
|
|
},
|
2019-06-21 05:57:43 -04:00
|
|
|
}
|
|
|
|
this.backgroundRequest = sinon.stub().yields()
|
|
|
|
this.request = sinon.stub().yields()
|
2020-11-04 08:35:37 -05:00
|
|
|
this.AnalyticsManager = SandboxedModule.require(MODULE_PATH, {
|
2019-06-21 05:57:43 -04:00
|
|
|
requires: {
|
2021-07-07 05:38:56 -04:00
|
|
|
'@overleaf/settings': this.Settings,
|
2021-04-27 03:52:58 -04:00
|
|
|
'../../infrastructure/Queues': this.Queues,
|
2021-09-10 04:30:01 -04:00
|
|
|
'./UserAnalyticsIdCache': (this.UserAnalyticsIdCache = {
|
|
|
|
get: sinon.stub().resolves(this.analyticsId),
|
|
|
|
}),
|
2021-04-27 03:52:58 -04:00
|
|
|
},
|
2019-06-21 05:57:43 -04:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe('ignores when', function () {
|
|
|
|
it('user is smoke test user', function () {
|
2020-11-04 08:35:37 -05:00
|
|
|
this.Settings.smokeTest = { userId: this.fakeUserId }
|
|
|
|
this.AnalyticsManager.identifyUser(this.fakeUserId, '')
|
2021-03-31 05:24:39 -04:00
|
|
|
sinon.assert.notCalled(this.analyticsEventsQueue.add)
|
2019-06-21 05:57:43 -04:00
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('analytics service is disabled', function () {
|
2020-11-04 08:35:37 -05:00
|
|
|
this.Settings.analytics.enabled = false
|
|
|
|
this.AnalyticsManager.identifyUser(this.fakeUserId, '')
|
2021-03-31 05:24:39 -04:00
|
|
|
sinon.assert.notCalled(this.analyticsEventsQueue.add)
|
2019-06-21 05:57:43 -04:00
|
|
|
})
|
2021-09-30 11:27:59 -04:00
|
|
|
|
|
|
|
it('userId or analyticsId is missing', function () {
|
|
|
|
this.AnalyticsManager.identifyUser(this.fakeUserId, undefined)
|
|
|
|
sinon.assert.notCalled(this.analyticsEventsQueue.add)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('userId equal analyticsId', function () {
|
|
|
|
this.AnalyticsManager.identifyUser(this.fakeUserId, this.fakeUserId)
|
|
|
|
sinon.assert.notCalled(this.analyticsEventsQueue.add)
|
|
|
|
})
|
2019-06-21 05:57:43 -04:00
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe('queues the appropriate message for', function () {
|
|
|
|
it('identifyUser', function () {
|
2021-09-10 04:30:01 -04:00
|
|
|
const analyticsId = '456def'
|
|
|
|
this.AnalyticsManager.identifyUser(this.fakeUserId, analyticsId)
|
2021-03-31 05:24:39 -04:00
|
|
|
sinon.assert.calledWithMatch(this.analyticsEventsQueue.add, 'identify', {
|
|
|
|
userId: this.fakeUserId,
|
2021-09-10 04:30:01 -04:00
|
|
|
analyticsId,
|
2021-03-31 05:24:39 -04:00
|
|
|
})
|
2019-06-21 05:57:43 -04:00
|
|
|
})
|
|
|
|
|
2021-09-10 04:30:01 -04:00
|
|
|
it('recordEventForUser', async function () {
|
2019-06-21 05:57:43 -04:00
|
|
|
const event = 'fake-event'
|
2021-09-10 04:30:01 -04:00
|
|
|
await this.AnalyticsManager.recordEventForUser(
|
|
|
|
this.fakeUserId,
|
|
|
|
event,
|
|
|
|
null
|
|
|
|
)
|
2021-03-31 05:24:39 -04:00
|
|
|
sinon.assert.calledWithMatch(this.analyticsEventsQueue.add, 'event', {
|
2021-09-10 04:30:01 -04:00
|
|
|
analyticsId: this.analyticsId,
|
2020-11-04 08:35:37 -05:00
|
|
|
event,
|
2021-04-27 03:52:58 -04:00
|
|
|
segmentation: null,
|
2021-09-10 04:30:01 -04:00
|
|
|
isLoggedIn: true,
|
2019-06-21 05:57:43 -04:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('updateEditingSession', function () {
|
2019-06-21 05:57:43 -04:00
|
|
|
const projectId = '789ghi'
|
|
|
|
const countryCode = 'fr'
|
|
|
|
this.AnalyticsManager.updateEditingSession(
|
|
|
|
this.fakeUserId,
|
|
|
|
projectId,
|
2020-11-04 08:35:37 -05:00
|
|
|
countryCode
|
2019-06-21 05:57:43 -04:00
|
|
|
)
|
2021-09-30 11:27:27 -04:00
|
|
|
sinon.assert.calledWithMatch(
|
|
|
|
this.analyticsEditingSessionQueue.add,
|
|
|
|
'editing-session',
|
|
|
|
{
|
|
|
|
userId: this.fakeUserId,
|
|
|
|
projectId,
|
|
|
|
countryCode,
|
|
|
|
}
|
|
|
|
)
|
2019-06-21 05:57:43 -04:00
|
|
|
})
|
|
|
|
})
|
2021-09-30 11:28:07 -04:00
|
|
|
|
|
|
|
describe('AnalyticsIdMiddleware', function () {
|
|
|
|
beforeEach(function () {
|
|
|
|
this.userId = '123abc'
|
|
|
|
this.analyticsId = 'bccd308c-5d72-426e-a106-662e88557795'
|
|
|
|
this.AnalyticsManager = SandboxedModule.require(MODULE_PATH, {
|
|
|
|
requires: {
|
|
|
|
'@overleaf/settings': {},
|
|
|
|
'../../infrastructure/Queues': {
|
|
|
|
getAnalyticsEventsQueue: () => {},
|
|
|
|
getAnalyticsEditingSessionsQueue: () => {},
|
|
|
|
getOnboardingEmailsQueue: () => {},
|
|
|
|
getAnalyticsUserPropertiesQueue: () => {},
|
|
|
|
},
|
|
|
|
'./UserAnalyticsIdCache': {},
|
|
|
|
uuid: {
|
|
|
|
v4: () => this.analyticsId,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
this.req = new MockRequest()
|
|
|
|
this.req.session = {}
|
|
|
|
this.res = new MockResponse()
|
|
|
|
this.next = () => {}
|
|
|
|
})
|
|
|
|
|
|
|
|
it('sets session.analyticsId with no user in session', async function () {
|
|
|
|
await this.AnalyticsManager.analyticsIdMiddleware(
|
|
|
|
this.req,
|
|
|
|
this.res,
|
|
|
|
this.next
|
|
|
|
)
|
|
|
|
assert.equal(this.analyticsId, this.req.session.analyticsId)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('does not update analyticsId when existing, with no user in session', async function () {
|
|
|
|
this.req.session.analyticsId = 'foo'
|
|
|
|
await this.AnalyticsManager.analyticsIdMiddleware(
|
|
|
|
this.req,
|
|
|
|
this.res,
|
|
|
|
this.next
|
|
|
|
)
|
|
|
|
assert.equal('foo', this.req.session.analyticsId)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('sets session.analyticsId with a logged in user in session having an analyticsId', async function () {
|
|
|
|
this.req.session.user = {
|
|
|
|
userId: this.userId,
|
|
|
|
analyticsId: this.analyticsId,
|
|
|
|
}
|
|
|
|
await this.AnalyticsManager.analyticsIdMiddleware(
|
|
|
|
this.req,
|
|
|
|
this.res,
|
|
|
|
this.next
|
|
|
|
)
|
|
|
|
assert.equal(this.analyticsId, this.req.session.analyticsId)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('sets session.analyticsId with a legacy user session without an analyticsId', async function () {
|
|
|
|
this.req.session.user = {
|
|
|
|
userId: this.userId,
|
|
|
|
analyticsId: undefined,
|
|
|
|
}
|
|
|
|
await this.AnalyticsManager.analyticsIdMiddleware(
|
|
|
|
this.req,
|
|
|
|
this.res,
|
|
|
|
this.next
|
|
|
|
)
|
|
|
|
assert.equal(this.userId, this.req.session.analyticsId)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('updates session.analyticsId with a legacy user session without an analyticsId if different', async function () {
|
|
|
|
this.req.session.user = {
|
|
|
|
userId: this.userId,
|
|
|
|
analyticsId: undefined,
|
|
|
|
}
|
|
|
|
this.req.analyticsId = 'foo'
|
|
|
|
await this.AnalyticsManager.analyticsIdMiddleware(
|
|
|
|
this.req,
|
|
|
|
this.res,
|
|
|
|
this.next
|
|
|
|
)
|
|
|
|
assert.equal(this.userId, this.req.session.analyticsId)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('does not update session.analyticsId with a legacy user session without an analyticsId if same', async function () {
|
|
|
|
this.req.session.user = {
|
|
|
|
userId: this.userId,
|
|
|
|
analyticsId: undefined,
|
|
|
|
}
|
|
|
|
this.req.analyticsId = this.userId
|
|
|
|
await this.AnalyticsManager.analyticsIdMiddleware(
|
|
|
|
this.req,
|
|
|
|
this.res,
|
|
|
|
this.next
|
|
|
|
)
|
|
|
|
assert.equal(this.userId, this.req.session.analyticsId)
|
|
|
|
|
|
|
|
await this.AnalyticsManager.analyticsIdMiddleware(
|
|
|
|
this.req,
|
|
|
|
this.res,
|
|
|
|
this.next
|
|
|
|
)
|
|
|
|
assert.equal(this.userId, this.req.session.analyticsId)
|
|
|
|
})
|
|
|
|
})
|
2019-06-21 05:57:43 -04:00
|
|
|
})
|