TeamInvitesControllerTests.mjs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. import esmock from 'esmock'
  2. import sinon from 'sinon'
  3. import { expect } from 'chai'
  4. const modulePath =
  5. '../../../../app/src/Features/Subscription/TeamInvitesController'
  6. describe('TeamInvitesController', function () {
  7. beforeEach(async function () {
  8. this.user = { _id: '!@312431', email: 'user@email.com' }
  9. this.adminUserId = '123jlkj'
  10. this.subscriptionId = '123434325412'
  11. this.user_email = 'bob@gmail.com'
  12. this.req = {
  13. session: {
  14. user: {
  15. _id: this.adminUserId,
  16. email: this.user_email,
  17. },
  18. },
  19. params: {},
  20. query: {},
  21. ip: '0.0.0.0',
  22. }
  23. this.subscription = {
  24. _id: this.subscriptionId,
  25. }
  26. this.TeamInvitesHandler = {
  27. promises: {
  28. acceptInvite: sinon.stub().resolves(this.subscription),
  29. getInvite: sinon.stub().resolves({
  30. invite: {
  31. email: this.user.email,
  32. token: 'token123',
  33. inviterName: this.user_email,
  34. },
  35. subscription: this.subscription,
  36. }),
  37. },
  38. }
  39. this.SubscriptionLocator = {
  40. promises: {
  41. hasSSOEnabled: sinon.stub().resolves(true),
  42. getUsersSubscription: sinon.stub().resolves(),
  43. },
  44. }
  45. this.ErrorController = { notFound: sinon.stub() }
  46. this.SessionManager = {
  47. getLoggedInUserId(session) {
  48. return session.user?._id
  49. },
  50. getSessionUser(session) {
  51. return session.user
  52. },
  53. }
  54. this.UserAuditLogHandler = {
  55. promises: {
  56. addEntry: sinon.stub().resolves(),
  57. },
  58. }
  59. this.UserGetter = {
  60. promises: {
  61. getUser: sinon.stub().resolves(this.user),
  62. getUserByMainEmail: sinon.stub().resolves(this.user),
  63. getUserByAnyEmail: sinon.stub().resolves(this.user),
  64. },
  65. }
  66. this.EmailHandler = {
  67. sendDeferredEmail: sinon.stub().resolves(),
  68. }
  69. this.RateLimiter = {
  70. RateLimiter: class {},
  71. }
  72. this.Controller = await esmock.strict(modulePath, {
  73. '../../../../app/src/Features/Subscription/TeamInvitesHandler':
  74. this.TeamInvitesHandler,
  75. '../../../../app/src/Features/Authentication/SessionManager':
  76. this.SessionManager,
  77. '../../../../app/src/Features/Subscription/SubscriptionLocator':
  78. this.SubscriptionLocator,
  79. '../../../../app/src/Features/User/UserAuditLogHandler':
  80. this.UserAuditLogHandler,
  81. '../../../../app/src/Features/Errors/ErrorController':
  82. this.ErrorController,
  83. '../../../../app/src/Features/User/UserGetter': this.UserGetter,
  84. '../../../../app/src/Features/Email/EmailHandler': this.EmailHandler,
  85. '../../../../app/src/infrastructure/RateLimiter': this.RateLimiter,
  86. '../../../../app/src/infrastructure/Modules': (this.Modules = {
  87. promises: {
  88. hooks: {
  89. fire: sinon.stub().resolves([]),
  90. },
  91. },
  92. }),
  93. '../../../../app/src/Features/SplitTests/SplitTestHandler':
  94. (this.SplitTestHandler = {
  95. promises: {
  96. getAssignment: sinon.stub().resolves({}),
  97. },
  98. }),
  99. })
  100. })
  101. describe('acceptInvite', function () {
  102. it('should add an audit log entry', function (done) {
  103. this.req.params.token = 'foo'
  104. this.req.session.user = this.user
  105. const res = {
  106. json: () => {
  107. sinon.assert.calledWith(
  108. this.UserAuditLogHandler.promises.addEntry,
  109. this.user._id,
  110. 'accept-group-invitation',
  111. this.user._id,
  112. this.req.ip,
  113. { subscriptionId: this.subscriptionId }
  114. )
  115. done()
  116. },
  117. }
  118. this.Controller.acceptInvite(this.req, res)
  119. })
  120. })
  121. describe('viewInvite', function () {
  122. const req = {
  123. params: { token: 'token123' },
  124. query: {},
  125. session: {
  126. user: { _id: 'user123' },
  127. },
  128. }
  129. describe('hasIndividualRecurlySubscription', function () {
  130. it('is true for personal subscription', function (done) {
  131. this.SubscriptionLocator.promises.getUsersSubscription.resolves({
  132. recurlySubscription_id: 'subscription123',
  133. groupPlan: false,
  134. })
  135. const res = {
  136. render: (template, data) => {
  137. expect(data.hasIndividualRecurlySubscription).to.be.true
  138. done()
  139. },
  140. }
  141. this.Controller.viewInvite(req, res)
  142. })
  143. it('is true for group subscriptions', function (done) {
  144. this.SubscriptionLocator.promises.getUsersSubscription.resolves({
  145. recurlySubscription_id: 'subscription123',
  146. groupPlan: true,
  147. })
  148. const res = {
  149. render: (template, data) => {
  150. expect(data.hasIndividualRecurlySubscription).to.be.false
  151. done()
  152. },
  153. }
  154. this.Controller.viewInvite(req, res)
  155. })
  156. it('is false for canceled subscriptions', function (done) {
  157. this.SubscriptionLocator.promises.getUsersSubscription.resolves({
  158. recurlySubscription_id: 'subscription123',
  159. groupPlan: false,
  160. recurlyStatus: {
  161. state: 'canceled',
  162. },
  163. })
  164. const res = {
  165. render: (template, data) => {
  166. expect(data.hasIndividualRecurlySubscription).to.be.false
  167. done()
  168. },
  169. }
  170. this.Controller.viewInvite(req, res)
  171. })
  172. })
  173. describe('when user is logged out', function () {
  174. it('renders logged out invite page', function (done) {
  175. const res = {
  176. render: (template, data) => {
  177. expect(template).to.equal('subscriptions/team/invite_logged_out')
  178. expect(data.groupSSOActive).to.be.undefined
  179. done()
  180. },
  181. }
  182. this.Controller.viewInvite(
  183. { params: { token: 'token123' }, session: {} },
  184. res
  185. )
  186. })
  187. it('includes groupSSOActive flag when the group has SSO enabled', function (done) {
  188. this.Modules.promises.hooks.fire = sinon.stub().resolves([true])
  189. const res = {
  190. render: (template, data) => {
  191. expect(data.groupSSOActive).to.be.true
  192. done()
  193. },
  194. }
  195. this.Controller.viewInvite(
  196. { params: { token: 'token123' }, session: {} },
  197. res
  198. )
  199. })
  200. })
  201. it('renders the view', function (done) {
  202. const res = {
  203. render: template => {
  204. expect(template).to.equal('subscriptions/team/invite')
  205. done()
  206. },
  207. }
  208. this.Controller.viewInvite(req, res)
  209. })
  210. })
  211. })