AnalyticsUTMTrackingMiddleware.test.mjs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. import esmock from 'esmock'
  2. import sinon from 'sinon'
  3. import MockRequest from '../helpers/MockRequest.js'
  4. import MockResponse from '../helpers/MockResponse.js'
  5. import { assert } from 'chai'
  6. const MODULE_PATH = new URL(
  7. '../../../../app/src/Features/Analytics/AnalyticsUTMTrackingMiddleware',
  8. import.meta.url
  9. ).pathname
  10. describe('AnalyticsUTMTrackingMiddleware', function () {
  11. beforeEach(async function () {
  12. this.analyticsId = 'ecdb935a-52f3-4f91-aebc-7a70d2ffbb55'
  13. this.userId = '61795fcb013504bb7b663092'
  14. this.req = new MockRequest()
  15. this.res = new MockResponse()
  16. this.next = sinon.stub().returns()
  17. this.req.session = {
  18. user: {
  19. _id: this.userId,
  20. analyticsId: this.analyticsId,
  21. },
  22. }
  23. this.AnalyticsUTMTrackingMiddleware = await esmock.strict(MODULE_PATH, {
  24. '../../../../app/src/Features/Analytics/AnalyticsManager.js':
  25. (this.AnalyticsManager = {
  26. recordEventForSession: sinon.stub().resolves(),
  27. setUserPropertyForSessionInBackground: sinon.stub(),
  28. }),
  29. '@overleaf/settings': {
  30. siteUrl: 'https://www.overleaf.com',
  31. },
  32. })
  33. this.middleware = this.AnalyticsUTMTrackingMiddleware.recordUTMTags()
  34. })
  35. describe('without UTM tags in query', function () {
  36. beforeEach(function () {
  37. this.req.url = '/project'
  38. this.middleware(this.req, this.res, this.next)
  39. })
  40. it('user is not redirected', function () {
  41. assert.isFalse(this.res.redirected)
  42. })
  43. it('next middleware is executed', function () {
  44. sinon.assert.calledOnce(this.next)
  45. })
  46. it('no event or user property is recorded', function () {
  47. sinon.assert.notCalled(this.AnalyticsManager.recordEventForSession)
  48. sinon.assert.notCalled(
  49. this.AnalyticsManager.setUserPropertyForSessionInBackground
  50. )
  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.setUserPropertyForSessionInBackground,
  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.setUserPropertyForSessionInBackground,
  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.setUserPropertyForSessionInBackground,
  170. this.req.session,
  171. 'utm-tags',
  172. 'N/A;Facebook;Some Campaign;N/A'
  173. )
  174. })
  175. })
  176. })