BetaProgramControllerTests.mjs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. import esmock from 'esmock'
  2. import path from 'node:path'
  3. import sinon from 'sinon'
  4. import { expect } from 'chai'
  5. import MockResponse from '../helpers/MockResponse.js'
  6. import { fileURLToPath } from 'node:url'
  7. const __dirname = fileURLToPath(new URL('.', import.meta.url))
  8. const modulePath = path.join(
  9. __dirname,
  10. '../../../../app/src/Features/BetaProgram/BetaProgramController'
  11. )
  12. describe('BetaProgramController', function () {
  13. beforeEach(async function () {
  14. this.user = {
  15. _id: (this.user_id = 'a_simple_id'),
  16. email: 'user@example.com',
  17. features: {},
  18. betaProgram: false,
  19. }
  20. this.req = {
  21. query: {},
  22. session: {
  23. user: this.user,
  24. },
  25. }
  26. this.SplitTestSessionHandler = {
  27. promises: {
  28. sessionMaintenance: sinon.stub(),
  29. },
  30. }
  31. this.BetaProgramController = await esmock.strict(modulePath, {
  32. '../../../../app/src/Features/SplitTests/SplitTestSessionHandler':
  33. this.SplitTestSessionHandler,
  34. '../../../../app/src/Features/BetaProgram/BetaProgramHandler':
  35. (this.BetaProgramHandler = {
  36. promises: {
  37. optIn: sinon.stub().resolves(),
  38. optOut: sinon.stub().resolves(),
  39. },
  40. }),
  41. '../../../../app/src/Features/User/UserGetter': (this.UserGetter = {
  42. promises: {
  43. getUser: sinon.stub().resolves(),
  44. },
  45. }),
  46. '@overleaf/settings': (this.settings = {
  47. languages: {},
  48. }),
  49. '../../../../app/src/Features/Authentication/AuthenticationController':
  50. (this.AuthenticationController = {
  51. getLoggedInUserId: sinon.stub().returns(this.user._id),
  52. }),
  53. })
  54. this.res = new MockResponse()
  55. this.next = sinon.stub()
  56. })
  57. describe('optIn', function () {
  58. it("should redirect to '/beta/participate'", function (done) {
  59. this.res.callback = () => {
  60. this.res.redirectedTo.should.equal('/beta/participate')
  61. done()
  62. }
  63. this.BetaProgramController.optIn(this.req, this.res, done)
  64. })
  65. it('should not call next with an error', function () {
  66. this.BetaProgramController.optIn(this.req, this.res, this.next)
  67. this.next.callCount.should.equal(0)
  68. })
  69. it('should call BetaProgramHandler.optIn', function () {
  70. this.BetaProgramController.optIn(this.req, this.res, this.next)
  71. this.BetaProgramHandler.promises.optIn.callCount.should.equal(1)
  72. })
  73. it('should invoke the session maintenance', function (done) {
  74. this.res.callback = () => {
  75. this.SplitTestSessionHandler.promises.sessionMaintenance.should.have.been.calledWith(
  76. this.req
  77. )
  78. done()
  79. }
  80. this.BetaProgramController.optIn(this.req, this.res, done)
  81. })
  82. describe('when BetaProgramHandler.opIn produces an error', function () {
  83. beforeEach(function () {
  84. this.BetaProgramHandler.promises.optIn.throws(new Error('woops'))
  85. })
  86. it("should not redirect to '/beta/participate'", function () {
  87. this.BetaProgramController.optIn(this.req, this.res, this.next)
  88. this.res.redirect.callCount.should.equal(0)
  89. })
  90. it('should produce an error', function (done) {
  91. this.BetaProgramController.optIn(this.req, this.res, err => {
  92. expect(err).to.be.instanceof(Error)
  93. done()
  94. })
  95. })
  96. })
  97. })
  98. describe('optOut', function () {
  99. it("should redirect to '/beta/participate'", function (done) {
  100. this.res.callback = () => {
  101. expect(this.res.redirectedTo).to.equal('/beta/participate')
  102. done()
  103. }
  104. this.BetaProgramController.optOut(this.req, this.res, done)
  105. })
  106. it('should not call next with an error', function (done) {
  107. this.res.callback = () => {
  108. this.next.callCount.should.equal(0)
  109. done()
  110. }
  111. this.BetaProgramController.optOut(this.req, this.res, done)
  112. })
  113. it('should call BetaProgramHandler.optOut', function (done) {
  114. this.res.callback = () => {
  115. this.BetaProgramHandler.promises.optOut.callCount.should.equal(1)
  116. done()
  117. }
  118. this.BetaProgramController.optOut(this.req, this.res, done)
  119. })
  120. it('should invoke the session maintenance', function (done) {
  121. this.res.callback = () => {
  122. this.SplitTestSessionHandler.promises.sessionMaintenance.should.have.been.calledWith(
  123. this.req,
  124. null
  125. )
  126. done()
  127. }
  128. this.BetaProgramController.optOut(this.req, this.res, done)
  129. })
  130. describe('when BetaProgramHandler.optOut produces an error', function () {
  131. beforeEach(function () {
  132. this.BetaProgramHandler.promises.optOut.throws(new Error('woops'))
  133. })
  134. it("should not redirect to '/beta/participate'", function (done) {
  135. this.BetaProgramController.optOut(this.req, this.res, error => {
  136. expect(error).to.exist
  137. expect(this.res.redirected).to.equal(false)
  138. done()
  139. })
  140. })
  141. it('should produce an error', function (done) {
  142. this.BetaProgramController.optOut(this.req, this.res, error => {
  143. expect(error).to.exist
  144. done()
  145. })
  146. })
  147. })
  148. })
  149. describe('optInPage', function () {
  150. beforeEach(function () {
  151. this.UserGetter.promises.getUser.resolves(this.user)
  152. })
  153. it('should render the opt-in page', function (done) {
  154. this.res.callback = () => {
  155. expect(this.res.renderedTemplate).to.equal('beta_program/opt_in')
  156. done()
  157. }
  158. this.BetaProgramController.optInPage(this.req, this.res, done)
  159. })
  160. describe('when UserGetter.getUser produces an error', function () {
  161. beforeEach(function () {
  162. this.UserGetter.promises.getUser.throws(new Error('woops'))
  163. })
  164. it('should not render the opt-in page', function () {
  165. this.BetaProgramController.optInPage(this.req, this.res, this.next)
  166. this.res.render.callCount.should.equal(0)
  167. })
  168. it('should produce an error', function (done) {
  169. this.BetaProgramController.optInPage(this.req, this.res, error => {
  170. expect(error).to.exist
  171. expect(error).to.be.instanceof(Error)
  172. done()
  173. })
  174. })
  175. })
  176. })
  177. })