ProjectStructureMongoLockTest.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /* eslint-disable
  2. handle-callback-err,
  3. max-len,
  4. */
  5. // TODO: This file was created by bulk-decaffeinate.
  6. // Fix any style issues and re-enable lint.
  7. /*
  8. * decaffeinate suggestions:
  9. * DS101: Remove unnecessary use of Array.from
  10. * DS102: Remove unnecessary code created because of implicit returns
  11. * DS207: Consider shorter variations of null checks
  12. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  13. */
  14. const APP_PATH = '../../../app/src'
  15. const LockManager = require(`${APP_PATH}/infrastructure/LockManager`)
  16. const ProjectCreationHandler = require(`${APP_PATH}/Features/Project/ProjectCreationHandler.js`)
  17. const ProjectGetter = require(`${APP_PATH}/Features/Project/ProjectGetter.js`)
  18. const ProjectEntityMongoUpdateHandler = require(`${APP_PATH}/Features/Project/ProjectEntityMongoUpdateHandler.js`)
  19. const UserCreator = require(`${APP_PATH}/Features/User/UserCreator.js`)
  20. const { expect } = require('chai')
  21. const _ = require('lodash')
  22. // These tests are neither acceptance tests nor unit tests. It's difficult to
  23. // test/verify that our locking is doing what we hope.
  24. // These tests call methods in ProjectGetter and ProjectEntityMongoUpdateHandler
  25. // to see that they DO NOT work when a lock has been taken.
  26. //
  27. // It is tested that these methods DO work when the lock has not been taken in
  28. // other acceptance tests.
  29. describe('ProjectStructureMongoLock', function() {
  30. describe('whilst a project lock is taken', function() {
  31. beforeEach(function(done) {
  32. // We want to instantly fail if the lock is taken
  33. LockManager.MAX_LOCK_WAIT_TIME = 1
  34. this.lockValue = 'lock-value'
  35. const userDetails = {
  36. holdingAccount: false,
  37. email: 'test@example.com'
  38. }
  39. UserCreator.createNewUser(userDetails, (err, user) => {
  40. this.user = user
  41. if (err != null) {
  42. throw err
  43. }
  44. return ProjectCreationHandler.createBlankProject(
  45. user._id,
  46. 'locked-project',
  47. (err, project) => {
  48. if (err != null) {
  49. throw err
  50. }
  51. this.locked_project = project
  52. const namespace = ProjectEntityMongoUpdateHandler.LOCK_NAMESPACE
  53. this.lock_key = `lock:web:${namespace}:${project._id}`
  54. return LockManager._getLock(
  55. this.lock_key,
  56. namespace,
  57. (err, lockValue) => {
  58. this.lockValue = lockValue
  59. return done()
  60. }
  61. )
  62. }
  63. )
  64. })
  65. })
  66. after(function(done) {
  67. return LockManager._releaseLock(this.lock_key, this.lockValue, done)
  68. })
  69. describe('interacting with the locked project', function() {
  70. const LOCKING_UPDATE_METHODS = [
  71. 'addDoc',
  72. 'addFile',
  73. 'mkdirp',
  74. 'moveEntity',
  75. 'renameEntity',
  76. 'addFolder'
  77. ]
  78. for (var methodName of Array.from(LOCKING_UPDATE_METHODS)) {
  79. it(`cannot call ProjectEntityMongoUpdateHandler.${methodName}`, function(done) {
  80. const method = ProjectEntityMongoUpdateHandler[methodName]
  81. const args = _.times(method.length - 2, _.constant(null))
  82. return method(this.locked_project._id, args, err => {
  83. expect(err).to.be.instanceOf(Error)
  84. expect(err).to.have.property('message', 'Timeout')
  85. return done()
  86. })
  87. })
  88. }
  89. it('cannot get the project without a projection', function(done) {
  90. return ProjectGetter.getProject(this.locked_project._id, err => {
  91. expect(err).to.be.instanceOf(Error)
  92. expect(err).to.have.property('message', 'Timeout')
  93. return done()
  94. })
  95. })
  96. it('cannot get the project if rootFolder is in the projection', function(done) {
  97. return ProjectGetter.getProject(
  98. this.locked_project._id,
  99. { rootFolder: true },
  100. err => {
  101. expect(err).to.be.instanceOf(Error)
  102. expect(err).to.have.property('message', 'Timeout')
  103. return done()
  104. }
  105. )
  106. })
  107. it('can get the project if rootFolder is not in the projection', function(done) {
  108. return ProjectGetter.getProject(
  109. this.locked_project._id,
  110. { _id: true },
  111. (err, project) => {
  112. expect(err).to.equal(null)
  113. expect(project._id).to.deep.equal(this.locked_project._id)
  114. return done()
  115. }
  116. )
  117. })
  118. })
  119. describe('interacting with other projects', function() {
  120. beforeEach(function(done) {
  121. return ProjectCreationHandler.createBlankProject(
  122. this.user._id,
  123. 'unlocked-project',
  124. (err, project) => {
  125. if (err != null) {
  126. throw err
  127. }
  128. this.unlocked_project = project
  129. return done()
  130. }
  131. )
  132. })
  133. it('can add folders to other projects', function(done) {
  134. return ProjectEntityMongoUpdateHandler.addFolder(
  135. this.unlocked_project._id,
  136. this.unlocked_project.rootFolder[0]._id,
  137. 'new folder',
  138. (err, folder) => {
  139. expect(err).to.equal(null)
  140. expect(folder).to.exist
  141. return done()
  142. }
  143. )
  144. })
  145. it('can get other projects without a projection', function(done) {
  146. return ProjectGetter.getProject(
  147. this.unlocked_project._id,
  148. (err, project) => {
  149. expect(err).to.equal(null)
  150. expect(project._id).to.deep.equal(this.unlocked_project._id)
  151. return done()
  152. }
  153. )
  154. })
  155. })
  156. })
  157. })