AnalyticsUTMTrackingMiddlewareTests.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. const SandboxedModule = require('sandboxed-module')
  2. const path = require('path')
  3. const sinon = require('sinon')
  4. const MockRequest = require('../helpers/MockRequest')
  5. const MockResponse = require('../helpers/MockResponse')
  6. const { assert } = require('chai')
  7. const MODULE_PATH = path.join(
  8. __dirname,
  9. '../../../../app/src/Features/Analytics/AnalyticsUTMTrackingMiddleware'
  10. )
  11. describe('AnalyticsUTMTrackingMiddleware', function () {
  12. beforeEach(function () {
  13. this.analyticsId = 'ecdb935a-52f3-4f91-aebc-7a70d2ffbb55'
  14. this.userId = '61795fcb013504bb7b663092'
  15. this.req = new MockRequest()
  16. this.res = new MockResponse()
  17. this.next = sinon.stub().returns()
  18. this.req.session = {
  19. user: {
  20. _id: this.userId,
  21. analyticsId: this.analyticsId,
  22. },
  23. }
  24. this.AnalyticsUTMTrackingMiddleware = SandboxedModule.require(MODULE_PATH, {
  25. requires: {
  26. './AnalyticsManager': (this.AnalyticsManager = {
  27. recordEventForSession: sinon.stub().resolves(),
  28. setUserPropertyForSession: sinon.stub().resolves(),
  29. }),
  30. '@overleaf/settings': {
  31. siteUrl: 'https://www.overleaf.com',
  32. },
  33. },
  34. })
  35. this.middleware = this.AnalyticsUTMTrackingMiddleware.recordUTMTags()
  36. })
  37. describe('without UTM tags in query', function () {
  38. beforeEach(function () {
  39. this.req.url = '/project'
  40. this.middleware(this.req, this.res, this.next)
  41. })
  42. it('user is not redirected', function () {
  43. assert.isFalse(this.res.redirected)
  44. })
  45. it('next middleware is executed', function () {
  46. sinon.assert.calledOnce(this.next)
  47. })
  48. it('no event or user property is recorded', function () {
  49. sinon.assert.notCalled(this.AnalyticsManager.recordEventForSession)
  50. sinon.assert.notCalled(this.AnalyticsManager.setUserPropertyForSession)
  51. })
  52. })
  53. describe('with all UTM tags in query', function () {
  54. beforeEach(function () {
  55. this.req.url =
  56. '/project?utm_source=Organic&utm_medium=Facebook&utm_campaign=Some%20Campaign&utm_content=foo-bar&utm_term=overridden'
  57. this.req.query = {
  58. utm_source: 'Organic',
  59. utm_medium: 'Facebook',
  60. utm_campaign: 'Some Campaign',
  61. utm_content: 'foo-bar',
  62. utm_term: 'overridden',
  63. }
  64. this.middleware(this.req, this.res, this.next)
  65. })
  66. it('user is redirected', function () {
  67. assert.isTrue(this.res.redirected)
  68. assert.equal('/project', this.res.redirectedTo)
  69. })
  70. it('next middleware is not executed', function () {
  71. sinon.assert.notCalled(this.next)
  72. })
  73. it('page-view event is recorded for session', function () {
  74. sinon.assert.calledWith(
  75. this.AnalyticsManager.recordEventForSession,
  76. this.req.session,
  77. 'page-view',
  78. {
  79. path: '/project',
  80. utm_source: 'Organic',
  81. utm_medium: 'Facebook',
  82. utm_campaign: 'Some Campaign',
  83. utm_content: 'foo-bar',
  84. utm_term: 'overridden',
  85. }
  86. )
  87. })
  88. it('utm-tags user property is set for session', function () {
  89. sinon.assert.calledWith(
  90. this.AnalyticsManager.setUserPropertyForSession,
  91. this.req.session,
  92. 'utm-tags',
  93. 'Organic;Facebook;Some Campaign;foo-bar'
  94. )
  95. })
  96. })
  97. describe('with some UTM tags in query', function () {
  98. beforeEach(function () {
  99. this.req.url =
  100. '/project?utm_medium=Facebook&utm_campaign=Some%20Campaign&utm_term=foo'
  101. this.req.query = {
  102. utm_medium: 'Facebook',
  103. utm_campaign: 'Some Campaign',
  104. utm_term: 'foo',
  105. }
  106. this.middleware(this.req, this.res, this.next)
  107. })
  108. it('user is redirected', function () {
  109. assert.isTrue(this.res.redirected)
  110. assert.equal('/project', this.res.redirectedTo)
  111. })
  112. it('next middleware is not executed', function () {
  113. sinon.assert.notCalled(this.next)
  114. })
  115. it('page-view event is recorded for session', function () {
  116. sinon.assert.calledWith(
  117. this.AnalyticsManager.recordEventForSession,
  118. this.req.session,
  119. 'page-view',
  120. {
  121. path: '/project',
  122. utm_medium: 'Facebook',
  123. utm_campaign: 'Some Campaign',
  124. utm_term: 'foo',
  125. }
  126. )
  127. })
  128. it('utm-tags user property is set for session', function () {
  129. sinon.assert.calledWith(
  130. this.AnalyticsManager.setUserPropertyForSession,
  131. this.req.session,
  132. 'utm-tags',
  133. 'N/A;Facebook;Some Campaign;foo'
  134. )
  135. })
  136. })
  137. describe('with some UTM tags and additional parameters in query', function () {
  138. beforeEach(function () {
  139. this.req.url =
  140. '/project?utm_medium=Facebook&utm_campaign=Some%20Campaign&other_param=some-value'
  141. this.req.query = {
  142. utm_medium: 'Facebook',
  143. utm_campaign: 'Some Campaign',
  144. other_param: 'some-value',
  145. }
  146. this.middleware(this.req, this.res, this.next)
  147. })
  148. it('user is redirected', function () {
  149. assert.isTrue(this.res.redirected)
  150. assert.equal('/project?other_param=some-value', this.res.redirectedTo)
  151. })
  152. it('next middleware is not executed', function () {
  153. sinon.assert.notCalled(this.next)
  154. })
  155. it('page-view event is recorded for session', function () {
  156. sinon.assert.calledWith(
  157. this.AnalyticsManager.recordEventForSession,
  158. this.req.session,
  159. 'page-view',
  160. {
  161. path: '/project',
  162. utm_medium: 'Facebook',
  163. utm_campaign: 'Some Campaign',
  164. }
  165. )
  166. })
  167. it('utm-tags user property is set for session', function () {
  168. sinon.assert.calledWith(
  169. this.AnalyticsManager.setUserPropertyForSession,
  170. this.req.session,
  171. 'utm-tags',
  172. 'N/A;Facebook;Some Campaign;N/A'
  173. )
  174. })
  175. })
  176. })