LimitationsManagerTests.js 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931
  1. const SandboxedModule = require('sandboxed-module')
  2. const assert = require('assert')
  3. const sinon = require('sinon')
  4. const { expect } = require('chai')
  5. const modulePath = require('path').join(
  6. __dirname,
  7. '../../../../app/src/Features/Subscription/LimitationsManager'
  8. )
  9. describe('LimitationsManager', function () {
  10. beforeEach(function () {
  11. this.user = {
  12. _id: (this.userId = 'user-id'),
  13. features: { collaborators: 1 },
  14. }
  15. this.project = {
  16. _id: (this.projectId = 'project-id'),
  17. owner_ref: this.userId,
  18. }
  19. this.ProjectGetter = {
  20. promises: {
  21. getProject: sinon.stub().callsFake(async (projectId, fields) => {
  22. if (projectId === this.projectId) {
  23. return this.project
  24. } else {
  25. return null
  26. }
  27. }),
  28. },
  29. }
  30. this.UserGetter = {
  31. promises: {
  32. getUser: sinon.stub().callsFake(async (userId, filter) => {
  33. if (userId === this.userId) {
  34. return this.user
  35. } else {
  36. return null
  37. }
  38. }),
  39. },
  40. }
  41. this.SubscriptionLocator = {
  42. promises: {
  43. getUsersSubscription: sinon.stub().resolves(),
  44. getSubscription: sinon.stub().resolves(),
  45. getMemberSubscriptions: sinon.stub().resolves(),
  46. },
  47. }
  48. this.V1SubscriptionManager = {
  49. promises: {
  50. getSubscriptionsFromV1: sinon.stub().resolves(),
  51. },
  52. }
  53. this.CollaboratorsGetter = {
  54. promises: {
  55. getInvitedCollaboratorCount: sinon.stub().resolves(),
  56. getInvitedEditCollaboratorCount: sinon.stub().resolves(),
  57. },
  58. }
  59. this.CollaboratorsInviteGetter = {
  60. promises: {
  61. getInviteCount: sinon.stub().resolves(),
  62. getEditInviteCount: sinon.stub().resolves(),
  63. },
  64. }
  65. this.LimitationsManager = SandboxedModule.require(modulePath, {
  66. requires: {
  67. '../Project/ProjectGetter': this.ProjectGetter,
  68. '../User/UserGetter': this.UserGetter,
  69. './SubscriptionLocator': this.SubscriptionLocator,
  70. '@overleaf/settings': (this.Settings = {}),
  71. '../Collaborators/CollaboratorsGetter': this.CollaboratorsGetter,
  72. '../Collaborators/CollaboratorsInviteGetter':
  73. this.CollaboratorsInviteGetter,
  74. './V1SubscriptionManager': this.V1SubscriptionManager,
  75. },
  76. })
  77. })
  78. describe('allowedNumberOfCollaboratorsInProject', function () {
  79. describe('when the project is owned by a user without a subscription', function () {
  80. beforeEach(function (done) {
  81. this.Settings.defaultFeatures = { collaborators: 23 }
  82. this.project.owner_ref = this.userId
  83. delete this.user.features
  84. this.callback = sinon.stub().callsFake(() => done())
  85. this.LimitationsManager.allowedNumberOfCollaboratorsInProject(
  86. this.projectId,
  87. this.callback
  88. )
  89. })
  90. it('should return the default number', function () {
  91. this.callback
  92. .calledWith(null, this.Settings.defaultFeatures.collaborators)
  93. .should.equal(true)
  94. })
  95. })
  96. describe('when the project is owned by a user with a subscription', function () {
  97. beforeEach(function (done) {
  98. this.project.owner_ref = this.userId
  99. this.user.features = { collaborators: 21 }
  100. this.callback = sinon.stub().callsFake(() => done())
  101. this.LimitationsManager.allowedNumberOfCollaboratorsInProject(
  102. this.projectId,
  103. this.callback
  104. )
  105. })
  106. it('should return the number of collaborators the user is allowed', function () {
  107. this.callback
  108. .calledWith(null, this.user.features.collaborators)
  109. .should.equal(true)
  110. })
  111. })
  112. })
  113. describe('allowedNumberOfCollaboratorsForUser', function () {
  114. describe('when the user has no features', function () {
  115. beforeEach(function (done) {
  116. this.Settings.defaultFeatures = { collaborators: 23 }
  117. delete this.user.features
  118. this.callback = sinon.stub().callsFake(() => done())
  119. this.LimitationsManager.allowedNumberOfCollaboratorsForUser(
  120. this.userId,
  121. this.callback
  122. )
  123. })
  124. it('should return the default number', function () {
  125. this.callback
  126. .calledWith(null, this.Settings.defaultFeatures.collaborators)
  127. .should.equal(true)
  128. })
  129. })
  130. describe('when the user has features', function () {
  131. beforeEach(function (done) {
  132. this.user.features = { collaborators: 21 }
  133. this.callback = sinon.stub().callsFake(() => done())
  134. this.LimitationsManager.allowedNumberOfCollaboratorsForUser(
  135. this.userId,
  136. this.callback
  137. )
  138. })
  139. it('should return the number of collaborators the user is allowed', function () {
  140. this.callback
  141. .calledWith(null, this.user.features.collaborators)
  142. .should.equal(true)
  143. })
  144. })
  145. })
  146. describe('canAcceptEditCollaboratorInvite', function () {
  147. describe('when the project has fewer collaborators than allowed', function () {
  148. beforeEach(function () {
  149. this.current_number = 1
  150. this.user.features.collaborators = 2
  151. this.CollaboratorsGetter.promises.getInvitedEditCollaboratorCount =
  152. sinon.stub().resolves(this.current_number)
  153. })
  154. it('should return true', async function () {
  155. const result =
  156. await this.LimitationsManager.promises.canAcceptEditCollaboratorInvite(
  157. this.projectId
  158. )
  159. expect(result).to.be.true
  160. })
  161. })
  162. describe('when accepting the invite would exceed the collaborator limit', function () {
  163. beforeEach(function () {
  164. this.current_number = 2
  165. this.user.features.collaborators = 2
  166. this.CollaboratorsGetter.promises.getInvitedEditCollaboratorCount =
  167. sinon.stub().resolves(this.current_number)
  168. })
  169. it('should return false', async function () {
  170. const result =
  171. await this.LimitationsManager.promises.canAcceptEditCollaboratorInvite(
  172. this.projectId
  173. )
  174. expect(result).to.be.false
  175. })
  176. })
  177. describe('when the project has more collaborators than allowed', function () {
  178. beforeEach(function () {
  179. this.current_number = 3
  180. this.user.features.collaborators = 2
  181. this.CollaboratorsGetter.promises.getInvitedEditCollaboratorCount =
  182. sinon.stub().resolves(this.current_number)
  183. })
  184. it('should return false', async function () {
  185. const result =
  186. await this.LimitationsManager.promises.canAcceptEditCollaboratorInvite(
  187. this.projectId
  188. )
  189. expect(result).to.be.false
  190. })
  191. })
  192. describe('when the project has infinite collaborators', function () {
  193. beforeEach(function () {
  194. this.current_number = 100
  195. this.user.features.collaborators = -1
  196. this.CollaboratorsGetter.promises.getInvitedEditCollaboratorCount =
  197. sinon.stub().resolves(this.current_number)
  198. })
  199. it('should return true', async function () {
  200. const result =
  201. await this.LimitationsManager.promises.canAcceptEditCollaboratorInvite(
  202. this.projectId
  203. )
  204. expect(result).to.be.true
  205. })
  206. })
  207. })
  208. describe('canAddXCollaborators', function () {
  209. describe('when the project has fewer collaborators than allowed', function () {
  210. beforeEach(function (done) {
  211. this.current_number = 1
  212. this.user.features.collaborators = 2
  213. this.invite_count = 0
  214. this.CollaboratorsGetter.promises.getInvitedCollaboratorCount = sinon
  215. .stub()
  216. .resolves(this.current_number)
  217. this.CollaboratorsInviteGetter.promises.getInviteCount = sinon
  218. .stub()
  219. .resolves(this.invite_count)
  220. this.callback = sinon.stub().callsFake(() => done())
  221. this.LimitationsManager.canAddXCollaborators(
  222. this.projectId,
  223. 1,
  224. this.callback
  225. )
  226. })
  227. it('should return true', function () {
  228. this.callback.calledWith(null, true).should.equal(true)
  229. })
  230. })
  231. describe('when the project has fewer collaborators and invites than allowed', function () {
  232. beforeEach(function (done) {
  233. this.current_number = 1
  234. this.user.features.collaborators = 4
  235. this.invite_count = 1
  236. this.CollaboratorsGetter.promises.getInvitedCollaboratorCount = sinon
  237. .stub()
  238. .resolves(this.current_number)
  239. this.CollaboratorsInviteGetter.promises.getInviteCount = sinon
  240. .stub()
  241. .resolves(this.invite_count)
  242. this.callback = sinon.stub().callsFake(() => done())
  243. this.LimitationsManager.canAddXCollaborators(
  244. this.projectId,
  245. 1,
  246. this.callback
  247. )
  248. })
  249. it('should return true', function () {
  250. this.callback.calledWith(null, true).should.equal(true)
  251. })
  252. })
  253. describe('when the project has fewer collaborators than allowed but I want to add more than allowed', function () {
  254. beforeEach(function (done) {
  255. this.current_number = 1
  256. this.user.features.collaborators = 2
  257. this.invite_count = 0
  258. this.CollaboratorsGetter.promises.getInvitedCollaboratorCount = sinon
  259. .stub()
  260. .resolves(this.current_number)
  261. this.CollaboratorsInviteGetter.promises.getInviteCount = sinon
  262. .stub()
  263. .resolves(this.invite_count)
  264. this.callback = sinon.stub().callsFake(() => done())
  265. this.LimitationsManager.canAddXCollaborators(
  266. this.projectId,
  267. 2,
  268. this.callback
  269. )
  270. })
  271. it('should return false', function () {
  272. this.callback.calledWith(null, false).should.equal(true)
  273. })
  274. })
  275. describe('when the project has more collaborators than allowed', function () {
  276. beforeEach(function (done) {
  277. this.current_number = 3
  278. this.user.features.collaborators = 2
  279. this.invite_count = 0
  280. this.CollaboratorsGetter.promises.getInvitedCollaboratorCount = sinon
  281. .stub()
  282. .resolves(this.current_number)
  283. this.CollaboratorsInviteGetter.promises.getInviteCount = sinon
  284. .stub()
  285. .resolves(this.invite_count)
  286. this.callback = sinon.stub().callsFake(() => done())
  287. this.LimitationsManager.canAddXCollaborators(
  288. this.projectId,
  289. 1,
  290. this.callback
  291. )
  292. })
  293. it('should return false', function () {
  294. this.callback.calledWith(null, false).should.equal(true)
  295. })
  296. })
  297. describe('when the project has infinite collaborators', function () {
  298. beforeEach(function (done) {
  299. this.current_number = 100
  300. this.user.features.collaborators = -1
  301. this.invite_count = 0
  302. this.CollaboratorsGetter.promises.getInvitedCollaboratorCount = sinon
  303. .stub()
  304. .resolves(this.current_number)
  305. this.CollaboratorsInviteGetter.promises.getInviteCount = sinon
  306. .stub()
  307. .resolves(this.invite_count)
  308. this.callback = sinon.stub().callsFake(() => done())
  309. this.LimitationsManager.canAddXCollaborators(
  310. this.projectId,
  311. 1,
  312. this.callback
  313. )
  314. })
  315. it('should return true', function () {
  316. this.callback.calledWith(null, true).should.equal(true)
  317. })
  318. })
  319. describe('when the project has more invites than allowed', function () {
  320. beforeEach(function (done) {
  321. this.current_number = 0
  322. this.user.features.collaborators = 2
  323. this.invite_count = 2
  324. this.CollaboratorsGetter.promises.getInvitedCollaboratorCount = sinon
  325. .stub()
  326. .resolves(this.current_number)
  327. this.CollaboratorsInviteGetter.promises.getInviteCount = sinon
  328. .stub()
  329. .resolves(this.invite_count)
  330. this.callback = sinon.stub().callsFake(() => done())
  331. this.LimitationsManager.canAddXCollaborators(
  332. this.projectId,
  333. 1,
  334. this.callback
  335. )
  336. })
  337. it('should return false', function () {
  338. this.callback.calledWith(null, false).should.equal(true)
  339. })
  340. })
  341. describe('when the project has more invites and collaborators than allowed', function () {
  342. beforeEach(function (done) {
  343. this.current_number = 1
  344. this.user.features.collaborators = 2
  345. this.invite_count = 1
  346. this.CollaboratorsGetter.promises.getInvitedCollaboratorCount = sinon
  347. .stub()
  348. .resolves(this.current_number)
  349. this.CollaboratorsInviteGetter.promises.getInviteCount = sinon
  350. .stub()
  351. .resolves(this.invite_count)
  352. this.callback = sinon.stub().callsFake(() => done())
  353. this.LimitationsManager.canAddXCollaborators(
  354. this.projectId,
  355. 1,
  356. this.callback
  357. )
  358. })
  359. it('should return false', function () {
  360. this.callback.calledWith(null, false).should.equal(true)
  361. })
  362. })
  363. })
  364. describe('canAddXEditCollaborators', function () {
  365. describe('when the project has fewer collaborators than allowed', function () {
  366. beforeEach(function (done) {
  367. this.current_number = 1
  368. this.user.features.collaborators = 2
  369. this.invite_count = 0
  370. this.CollaboratorsGetter.promises.getInvitedEditCollaboratorCount =
  371. sinon.stub().resolves(this.current_number)
  372. this.CollaboratorsInviteGetter.promises.getEditInviteCount = sinon
  373. .stub()
  374. .resolves(this.invite_count)
  375. this.callback = sinon.stub().callsFake(() => done())
  376. this.LimitationsManager.canAddXEditCollaborators(
  377. this.projectId,
  378. 1,
  379. this.callback
  380. )
  381. })
  382. it('should return true', function () {
  383. this.callback.calledWith(null, true).should.equal(true)
  384. })
  385. })
  386. describe('when the project has fewer collaborators and invites than allowed', function () {
  387. beforeEach(function (done) {
  388. this.current_number = 1
  389. this.user.features.collaborators = 4
  390. this.invite_count = 1
  391. this.CollaboratorsGetter.promises.getInvitedEditCollaboratorCount =
  392. sinon.stub().resolves(this.current_number)
  393. this.CollaboratorsInviteGetter.promises.getEditInviteCount = sinon
  394. .stub()
  395. .resolves(this.invite_count)
  396. this.callback = sinon.stub().callsFake(() => done())
  397. this.LimitationsManager.canAddXEditCollaborators(
  398. this.projectId,
  399. 1,
  400. this.callback
  401. )
  402. })
  403. it('should return true', function () {
  404. this.callback.calledWith(null, true).should.equal(true)
  405. })
  406. })
  407. describe('when the project has fewer collaborators than allowed but I want to add more than allowed', function () {
  408. beforeEach(function (done) {
  409. this.current_number = 1
  410. this.user.features.collaborators = 2
  411. this.invite_count = 0
  412. this.CollaboratorsGetter.promises.getInvitedEditCollaboratorCount =
  413. sinon.stub().resolves(this.current_number)
  414. this.CollaboratorsInviteGetter.promises.getEditInviteCount = sinon
  415. .stub()
  416. .resolves(this.invite_count)
  417. this.callback = sinon.stub().callsFake(() => done())
  418. this.LimitationsManager.canAddXEditCollaborators(
  419. this.projectId,
  420. 2,
  421. this.callback
  422. )
  423. })
  424. it('should return false', function () {
  425. this.callback.calledWith(null, false).should.equal(true)
  426. })
  427. })
  428. describe('when the project has more collaborators than allowed', function () {
  429. beforeEach(function (done) {
  430. this.current_number = 3
  431. this.user.features.collaborators = 2
  432. this.invite_count = 0
  433. this.CollaboratorsGetter.promises.getInvitedEditCollaboratorCount =
  434. sinon.stub().resolves(this.current_number)
  435. this.CollaboratorsInviteGetter.promises.getEditInviteCount = sinon
  436. .stub()
  437. .resolves(this.invite_count)
  438. this.callback = sinon.stub().callsFake(() => done())
  439. this.LimitationsManager.canAddXEditCollaborators(
  440. this.projectId,
  441. 1,
  442. this.callback
  443. )
  444. })
  445. it('should return false', function () {
  446. this.callback.calledWith(null, false).should.equal(true)
  447. })
  448. })
  449. describe('when the project has infinite collaborators', function () {
  450. beforeEach(function (done) {
  451. this.current_number = 100
  452. this.user.features.collaborators = -1
  453. this.invite_count = 0
  454. this.CollaboratorsGetter.promises.getInvitedEditCollaboratorCount =
  455. sinon.stub().resolves(this.current_number)
  456. this.CollaboratorsInviteGetter.promises.getEditInviteCount = sinon
  457. .stub()
  458. .resolves(this.invite_count)
  459. this.callback = sinon.stub().callsFake(() => done())
  460. this.LimitationsManager.canAddXEditCollaborators(
  461. this.projectId,
  462. 1,
  463. this.callback
  464. )
  465. })
  466. it('should return true', function () {
  467. this.callback.calledWith(null, true).should.equal(true)
  468. })
  469. })
  470. describe('when the project has more invites than allowed', function () {
  471. beforeEach(function (done) {
  472. this.current_number = 0
  473. this.user.features.collaborators = 2
  474. this.invite_count = 2
  475. this.CollaboratorsGetter.promises.getInvitedEditCollaboratorCount =
  476. sinon.stub().resolves(this.current_number)
  477. this.CollaboratorsInviteGetter.promises.getEditInviteCount = sinon
  478. .stub()
  479. .resolves(this.invite_count)
  480. this.callback = sinon.stub().callsFake(() => done())
  481. this.LimitationsManager.canAddXEditCollaborators(
  482. this.projectId,
  483. 1,
  484. this.callback
  485. )
  486. })
  487. it('should return false', function () {
  488. this.callback.calledWith(null, false).should.equal(true)
  489. })
  490. })
  491. describe('when the project has more invites and collaborators than allowed', function () {
  492. beforeEach(function (done) {
  493. this.current_number = 1
  494. this.user.features.collaborators = 2
  495. this.invite_count = 1
  496. this.CollaboratorsGetter.promises.getInvitedEditCollaboratorCount =
  497. sinon.stub().resolves(this.current_number)
  498. this.CollaboratorsInviteGetter.promises.getEditInviteCount = sinon
  499. .stub()
  500. .resolves(this.invite_count)
  501. this.callback = sinon.stub().callsFake(() => done())
  502. this.LimitationsManager.canAddXEditCollaborators(
  503. this.projectId,
  504. 1,
  505. this.callback
  506. )
  507. })
  508. it('should return false', function () {
  509. this.callback.calledWith(null, false).should.equal(true)
  510. })
  511. })
  512. })
  513. describe('userHasV2Subscription', function () {
  514. beforeEach(function () {
  515. this.SubscriptionLocator.promises.getUsersSubscription = sinon
  516. .stub()
  517. .resolves()
  518. })
  519. it('should return true if the recurly token is set', function (done) {
  520. this.SubscriptionLocator.promises.getUsersSubscription = sinon
  521. .stub()
  522. .resolves({
  523. recurlySubscription_id: '1234',
  524. })
  525. this.LimitationsManager.userHasV2Subscription(
  526. this.user,
  527. (err, hasSubscription) => {
  528. assert.equal(err, null)
  529. hasSubscription.should.equal(true)
  530. done()
  531. }
  532. )
  533. })
  534. it('should return false if the recurly token is not set', function (done) {
  535. this.SubscriptionLocator.promises.getUsersSubscription.resolves({})
  536. this.subscription = {}
  537. this.LimitationsManager.userHasV2Subscription(
  538. this.user,
  539. (err, hasSubscription) => {
  540. assert.equal(err, null)
  541. hasSubscription.should.equal(false)
  542. done()
  543. }
  544. )
  545. })
  546. it('should return false if the subscription is undefined', function (done) {
  547. this.SubscriptionLocator.promises.getUsersSubscription.resolves()
  548. this.LimitationsManager.userHasV2Subscription(
  549. this.user,
  550. (err, hasSubscription) => {
  551. assert.equal(err, null)
  552. hasSubscription.should.equal(false)
  553. done()
  554. }
  555. )
  556. })
  557. it('should return the subscription', function (done) {
  558. const stubbedSubscription = { freeTrial: {}, token: '' }
  559. this.SubscriptionLocator.promises.getUsersSubscription.resolves(
  560. stubbedSubscription
  561. )
  562. this.LimitationsManager.userHasV2Subscription(
  563. this.user,
  564. (err, hasSubOrIsGroupMember, subscription) => {
  565. assert.equal(err, null)
  566. subscription.should.deep.equal(stubbedSubscription)
  567. done()
  568. }
  569. )
  570. })
  571. describe('when user has a custom account', function () {
  572. beforeEach(function () {
  573. this.fakeSubscription = { customAccount: true }
  574. this.SubscriptionLocator.promises.getUsersSubscription.resolves(
  575. this.fakeSubscription
  576. )
  577. })
  578. it('should return true', function (done) {
  579. this.LimitationsManager.userHasV2Subscription(
  580. this.user,
  581. (err, hasSubscription, subscription) => {
  582. assert.equal(err, null)
  583. hasSubscription.should.equal(true)
  584. done()
  585. }
  586. )
  587. })
  588. it('should return the subscription', function (done) {
  589. this.LimitationsManager.userHasV2Subscription(
  590. this.user,
  591. (err, hasSubscription, subscription) => {
  592. assert.equal(err, null)
  593. subscription.should.deep.equal(this.fakeSubscription)
  594. done()
  595. }
  596. )
  597. })
  598. })
  599. })
  600. describe('userIsMemberOfGroupSubscription', function () {
  601. beforeEach(function () {
  602. this.SubscriptionLocator.promises.getMemberSubscriptions = sinon
  603. .stub()
  604. .resolves()
  605. })
  606. it('should return false if there are no groups subcriptions', function (done) {
  607. this.SubscriptionLocator.promises.getMemberSubscriptions.resolves([])
  608. this.LimitationsManager.userIsMemberOfGroupSubscription(
  609. this.user,
  610. (err, isMember) => {
  611. assert.equal(err, null)
  612. isMember.should.equal(false)
  613. done()
  614. }
  615. )
  616. })
  617. it('should return true if there are no groups subcriptions', function (done) {
  618. let subscriptions
  619. this.SubscriptionLocator.promises.getMemberSubscriptions.resolves(
  620. (subscriptions = ['mock-subscription'])
  621. )
  622. this.LimitationsManager.userIsMemberOfGroupSubscription(
  623. this.user,
  624. (err, isMember, retSubscriptions) => {
  625. assert.equal(err, null)
  626. isMember.should.equal(true)
  627. retSubscriptions.should.equal(subscriptions)
  628. done()
  629. }
  630. )
  631. })
  632. })
  633. describe('hasPaidSubscription', function () {
  634. beforeEach(function () {
  635. this.SubscriptionLocator.promises.getMemberSubscriptions = sinon
  636. .stub()
  637. .resolves([])
  638. this.SubscriptionLocator.promises.getUsersSubscription = sinon
  639. .stub()
  640. .resolves(null)
  641. this.V1SubscriptionManager.promises.userHasV1Subscription = sinon
  642. .stub()
  643. .yields(null, null)
  644. })
  645. it('should return true if userIsMemberOfGroupSubscription', function (done) {
  646. this.SubscriptionLocator.promises.getMemberSubscriptions = sinon
  647. .stub()
  648. .resolves([{ _id: '123' }])
  649. this.LimitationsManager.hasPaidSubscription(
  650. this.user,
  651. (err, hasSubOrIsGroupMember) => {
  652. assert.equal(err, null)
  653. hasSubOrIsGroupMember.should.equal(true)
  654. done()
  655. }
  656. )
  657. })
  658. it('should return true if userHasV2Subscription', function (done) {
  659. this.SubscriptionLocator.promises.getUsersSubscription = sinon
  660. .stub()
  661. .resolves({ recurlySubscription_id: '123' })
  662. this.LimitationsManager.hasPaidSubscription(
  663. this.user,
  664. (err, hasSubOrIsGroupMember) => {
  665. assert.equal(err, null)
  666. hasSubOrIsGroupMember.should.equal(true)
  667. done()
  668. }
  669. )
  670. })
  671. it('should return true if userHasV1Subscription', function (done) {
  672. this.V1SubscriptionManager.promises.getSubscriptionsFromV1 = sinon
  673. .stub()
  674. .resolves({ has_subscription: true })
  675. this.LimitationsManager.hasPaidSubscription(
  676. this.user,
  677. (err, hasSubOrIsGroupMember) => {
  678. assert.equal(err, null)
  679. hasSubOrIsGroupMember.should.equal(true)
  680. done()
  681. }
  682. )
  683. })
  684. it('should return false if none are true', function (done) {
  685. this.LimitationsManager.hasPaidSubscription(
  686. this.user,
  687. (err, hasSubOrIsGroupMember) => {
  688. assert.equal(err, null)
  689. hasSubOrIsGroupMember.should.equal(false)
  690. done()
  691. }
  692. )
  693. })
  694. it('should have userHasSubscriptionOrIsGroupMember alias', function (done) {
  695. this.LimitationsManager.userHasSubscriptionOrIsGroupMember(
  696. this.user,
  697. (err, hasSubOrIsGroupMember) => {
  698. assert.equal(err, null)
  699. hasSubOrIsGroupMember.should.equal(false)
  700. done()
  701. }
  702. )
  703. })
  704. })
  705. describe('userHasV1OrV2Subscription', function () {
  706. beforeEach(function () {
  707. this.SubscriptionLocator.promises.getUsersSubscription = sinon
  708. .stub()
  709. .resolves()
  710. this.V1SubscriptionManager.promises.userHasV1Subscription = sinon
  711. .stub()
  712. .resolves()
  713. })
  714. it('should return true if userHasV2Subscription', function (done) {
  715. this.SubscriptionLocator.promises.getUsersSubscription = sinon
  716. .stub()
  717. .resolves({ recurlySubscription_id: '123' })
  718. this.LimitationsManager.userHasV1OrV2Subscription(
  719. this.user,
  720. (err, hasSub) => {
  721. assert.equal(err, null)
  722. hasSub.should.equal(true)
  723. done()
  724. }
  725. )
  726. })
  727. it('should return true if userHasV1Subscription', function (done) {
  728. this.V1SubscriptionManager.promises.getSubscriptionsFromV1 = sinon
  729. .stub()
  730. .resolves({ has_subscription: true })
  731. this.LimitationsManager.userHasV1OrV2Subscription(
  732. this.user,
  733. (err, hasSub) => {
  734. assert.equal(err, null)
  735. hasSub.should.equal(true)
  736. done()
  737. }
  738. )
  739. })
  740. it('should return false if none are true', function (done) {
  741. this.LimitationsManager.userHasV1OrV2Subscription(
  742. this.user,
  743. (err, hasSub) => {
  744. assert.equal(err, null)
  745. hasSub.should.equal(false)
  746. done()
  747. }
  748. )
  749. })
  750. })
  751. describe('hasGroupMembersLimitReached', function () {
  752. beforeEach(function () {
  753. this.subscriptionId = '12312'
  754. this.subscription = {
  755. membersLimit: 3,
  756. member_ids: ['', ''],
  757. teamInvites: [
  758. { email: 'bob@example.com', sentAt: new Date(), token: 'hey' },
  759. ],
  760. }
  761. })
  762. it('should return true if the limit is hit (including members and invites)', function (done) {
  763. this.SubscriptionLocator.promises.getSubscription.resolves(
  764. this.subscription
  765. )
  766. this.LimitationsManager.hasGroupMembersLimitReached(
  767. this.subscriptionId,
  768. (err, limitReached) => {
  769. assert.equal(err, null)
  770. limitReached.should.equal(true)
  771. done()
  772. }
  773. )
  774. })
  775. it('should return false if the limit is not hit (including members and invites)', function (done) {
  776. this.subscription.membersLimit = 4
  777. this.SubscriptionLocator.promises.getSubscription.resolves(
  778. this.subscription
  779. )
  780. this.LimitationsManager.hasGroupMembersLimitReached(
  781. this.subscriptionId,
  782. (err, limitReached) => {
  783. assert.equal(err, null)
  784. limitReached.should.equal(false)
  785. done()
  786. }
  787. )
  788. })
  789. it('should return true if the limit has been exceded (including members and invites)', function (done) {
  790. this.subscription.membersLimit = 2
  791. this.SubscriptionLocator.promises.getSubscription.resolves(
  792. this.subscription
  793. )
  794. this.LimitationsManager.hasGroupMembersLimitReached(
  795. this.subscriptionId,
  796. (err, limitReached) => {
  797. assert.equal(err, null)
  798. limitReached.should.equal(true)
  799. done()
  800. }
  801. )
  802. })
  803. })
  804. describe('userHasV1Subscription', function () {
  805. it('should return true if v1 returns has_subscription = true', function (done) {
  806. this.V1SubscriptionManager.promises.getSubscriptionsFromV1 = sinon
  807. .stub()
  808. .resolves({ has_subscription: true })
  809. this.LimitationsManager.userHasV1Subscription(
  810. this.user,
  811. (error, result) => {
  812. assert.equal(error, null)
  813. this.V1SubscriptionManager.promises.getSubscriptionsFromV1
  814. .calledWith(this.userId)
  815. .should.equal(true)
  816. result.should.equal(true)
  817. done()
  818. }
  819. )
  820. })
  821. it('should return false if v1 returns has_subscription = false', function (done) {
  822. this.V1SubscriptionManager.promises.getSubscriptionsFromV1 = sinon
  823. .stub()
  824. .resolves({ has_subscription: false })
  825. this.LimitationsManager.userHasV1Subscription(
  826. this.user,
  827. (error, result) => {
  828. assert.equal(error, null)
  829. this.V1SubscriptionManager.promises.getSubscriptionsFromV1
  830. .calledWith(this.userId)
  831. .should.equal(true)
  832. result.should.equal(false)
  833. done()
  834. }
  835. )
  836. })
  837. it('should return false if v1 returns nothing', function (done) {
  838. this.V1SubscriptionManager.promises.getSubscriptionsFromV1 = sinon
  839. .stub()
  840. .resolves({ has_subscription: false })
  841. this.LimitationsManager.userHasV1Subscription(
  842. this.user,
  843. (error, result) => {
  844. assert.equal(error, null)
  845. this.V1SubscriptionManager.promises.getSubscriptionsFromV1
  846. .calledWith(this.userId)
  847. .should.equal(true)
  848. result.should.equal(false)
  849. done()
  850. }
  851. )
  852. })
  853. })
  854. })