AnalyticsUTMTrackingMiddlewareTests.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  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. setUserPropertyForSessionInBackground: sinon.stub(),
  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(
  51. this.AnalyticsManager.setUserPropertyForSessionInBackground
  52. )
  53. })
  54. })
  55. describe('with all UTM tags in query', function () {
  56. beforeEach(function () {
  57. this.req.url =
  58. '/project?utm_source=Organic&utm_medium=Facebook&utm_campaign=Some%20Campaign&utm_content=foo-bar&utm_term=overridden'
  59. this.req.query = {
  60. utm_source: 'Organic',
  61. utm_medium: 'Facebook',
  62. utm_campaign: 'Some Campaign',
  63. utm_content: 'foo-bar',
  64. utm_term: 'overridden',
  65. }
  66. this.middleware(this.req, this.res, this.next)
  67. })
  68. it('user is redirected', function () {
  69. assert.isTrue(this.res.redirected)
  70. assert.equal('/project', this.res.redirectedTo)
  71. })
  72. it('next middleware is not executed', function () {
  73. sinon.assert.notCalled(this.next)
  74. })
  75. it('page-view event is recorded for session', function () {
  76. sinon.assert.calledWith(
  77. this.AnalyticsManager.recordEventForSession,
  78. this.req.session,
  79. 'page-view',
  80. {
  81. path: '/project',
  82. utm_source: 'Organic',
  83. utm_medium: 'Facebook',
  84. utm_campaign: 'Some Campaign',
  85. utm_content: 'foo-bar',
  86. utm_term: 'overridden',
  87. }
  88. )
  89. })
  90. it('utm-tags user property is set for session', function () {
  91. sinon.assert.calledWith(
  92. this.AnalyticsManager.setUserPropertyForSessionInBackground,
  93. this.req.session,
  94. 'utm-tags',
  95. 'Organic;Facebook;Some Campaign;foo-bar'
  96. )
  97. })
  98. })
  99. describe('with some UTM tags in query', function () {
  100. beforeEach(function () {
  101. this.req.url =
  102. '/project?utm_medium=Facebook&utm_campaign=Some%20Campaign&utm_term=foo'
  103. this.req.query = {
  104. utm_medium: 'Facebook',
  105. utm_campaign: 'Some Campaign',
  106. utm_term: 'foo',
  107. }
  108. this.middleware(this.req, this.res, this.next)
  109. })
  110. it('user is redirected', function () {
  111. assert.isTrue(this.res.redirected)
  112. assert.equal('/project', this.res.redirectedTo)
  113. })
  114. it('next middleware is not executed', function () {
  115. sinon.assert.notCalled(this.next)
  116. })
  117. it('page-view event is recorded for session', function () {
  118. sinon.assert.calledWith(
  119. this.AnalyticsManager.recordEventForSession,
  120. this.req.session,
  121. 'page-view',
  122. {
  123. path: '/project',
  124. utm_medium: 'Facebook',
  125. utm_campaign: 'Some Campaign',
  126. utm_term: 'foo',
  127. }
  128. )
  129. })
  130. it('utm-tags user property is set for session', function () {
  131. sinon.assert.calledWith(
  132. this.AnalyticsManager.setUserPropertyForSessionInBackground,
  133. this.req.session,
  134. 'utm-tags',
  135. 'N/A;Facebook;Some Campaign;foo'
  136. )
  137. })
  138. })
  139. describe('with some UTM tags and additional parameters in query', function () {
  140. beforeEach(function () {
  141. this.req.url =
  142. '/project?utm_medium=Facebook&utm_campaign=Some%20Campaign&other_param=some-value'
  143. this.req.query = {
  144. utm_medium: 'Facebook',
  145. utm_campaign: 'Some Campaign',
  146. other_param: 'some-value',
  147. }
  148. this.middleware(this.req, this.res, this.next)
  149. })
  150. it('user is redirected', function () {
  151. assert.isTrue(this.res.redirected)
  152. assert.equal('/project?other_param=some-value', this.res.redirectedTo)
  153. })
  154. it('next middleware is not executed', function () {
  155. sinon.assert.notCalled(this.next)
  156. })
  157. it('page-view event is recorded for session', function () {
  158. sinon.assert.calledWith(
  159. this.AnalyticsManager.recordEventForSession,
  160. this.req.session,
  161. 'page-view',
  162. {
  163. path: '/project',
  164. utm_medium: 'Facebook',
  165. utm_campaign: 'Some Campaign',
  166. }
  167. )
  168. })
  169. it('utm-tags user property is set for session', function () {
  170. sinon.assert.calledWith(
  171. this.AnalyticsManager.setUserPropertyForSessionInBackground,
  172. this.req.session,
  173. 'utm-tags',
  174. 'N/A;Facebook;Some Campaign;N/A'
  175. )
  176. })
  177. })
  178. })