ProjectCRUDTests.mjs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. import { expect } from 'chai'
  2. import UserHelper from './helpers/User.mjs'
  3. import { Project } from '../../../app/src/models/Project.js'
  4. import mongodb from 'mongodb-legacy'
  5. import cheerio from 'cheerio'
  6. import { Subscription } from '../../../app/src/models/Subscription.js'
  7. import Features from '../../../app/src/infrastructure/Features.js'
  8. const ObjectId = mongodb.ObjectId
  9. const User = UserHelper.promises
  10. describe('Project CRUD', function () {
  11. beforeEach(async function () {
  12. this.user = new User()
  13. await this.user.login()
  14. this.projectId = await this.user.createProject('example-project')
  15. })
  16. describe('project page', function () {
  17. const loadProject = async function (user, projectId) {
  18. const { response, body } = await user.doRequest(
  19. 'GET',
  20. `/project/${projectId}`
  21. )
  22. expect(response.statusCode).to.equal(200)
  23. return body
  24. }
  25. it('should cast refProviders to booleans', async function () {
  26. await this.user.mongoUpdate({
  27. $set: {
  28. refProviders: {
  29. mendeley: { encrypted: 'aaa' },
  30. zotero: { encrypted: 'bbb' },
  31. },
  32. },
  33. })
  34. const body = await loadProject(this.user, this.projectId)
  35. const dom = cheerio.load(body)
  36. const metaOlUser = dom('meta[name="ol-user"]')[0]
  37. const userData = JSON.parse(metaOlUser.attribs.content)
  38. expect(userData.refProviders.mendeley).to.equal(true)
  39. expect(userData.refProviders.zotero).to.equal(true)
  40. })
  41. it('should show UpgradePrompt for user without a subscription', async function () {
  42. const body = await loadProject(this.user, this.projectId)
  43. expect(body).to.include(
  44. Features.hasFeature('saas')
  45. ? // `content` means true in this context
  46. '<meta name="ol-showUpgradePrompt" data-type="boolean" content>'
  47. : '<meta name="ol-showUpgradePrompt" data-type="boolean">'
  48. )
  49. })
  50. it('should not show UpgradePrompt for user with a subscription', async function () {
  51. await Subscription.create({
  52. admin_id: this.user._id,
  53. manager_ids: [this.user._id],
  54. })
  55. const body = await loadProject(this.user, this.projectId)
  56. // having no `content` means false in this context
  57. expect(body).to.include(
  58. '<meta name="ol-showUpgradePrompt" data-type="boolean">'
  59. )
  60. })
  61. })
  62. describe("when project doesn't exist", function () {
  63. it('should return 404', async function () {
  64. const { response } = await this.user.doRequest(
  65. 'GET',
  66. '/project/aaaaaaaaaaaaaaaaaaaaaaaa'
  67. )
  68. expect(response.statusCode).to.equal(404)
  69. })
  70. })
  71. describe('when project has malformed id', function () {
  72. it('should return 404', async function () {
  73. const { response } = await this.user.doRequest('GET', '/project/blah')
  74. expect(response.statusCode).to.equal(404)
  75. })
  76. })
  77. describe('when trashing a project', function () {
  78. it('should mark the project as trashed for the user', async function () {
  79. const { response } = await this.user.doRequest(
  80. 'POST',
  81. `/project/${this.projectId}/trash`
  82. )
  83. expect(response.statusCode).to.equal(200)
  84. const trashedProject = await Project.findById(this.projectId).exec()
  85. expectObjectIdArrayEqual(trashedProject.trashed, [this.user._id])
  86. })
  87. it('does nothing if the user has already trashed the project', async function () {
  88. // Mark as trashed the first time
  89. await this.user.doRequest('POST', `/project/${this.projectId}/trash`)
  90. // And then a second time
  91. await this.user.doRequest('POST', `/project/${this.projectId}/trash`)
  92. const trashedProject = await Project.findById(this.projectId).exec()
  93. expectObjectIdArrayEqual(trashedProject.trashed, [this.user._id])
  94. })
  95. describe('with an array archived state', function () {
  96. it('should mark the project as not archived for the user', async function () {
  97. await Project.updateOne(
  98. { _id: this.projectId },
  99. { $set: { archived: [new ObjectId(this.user._id)] } }
  100. ).exec()
  101. const { response } = await this.user.doRequest(
  102. 'POST',
  103. `/project/${this.projectId}/trash`
  104. )
  105. expect(response.statusCode).to.equal(200)
  106. const trashedProject = await Project.findById(this.projectId).exec()
  107. expectObjectIdArrayEqual(trashedProject.archived, [])
  108. })
  109. })
  110. describe('with a legacy boolean state', function () {
  111. it('should mark the project as not archived for the user', async function () {
  112. await Project.updateOne(
  113. { _id: this.projectId },
  114. { $set: { archived: true } }
  115. ).exec()
  116. const { response } = await this.user.doRequest(
  117. 'POST',
  118. `/project/${this.projectId}/trash`
  119. )
  120. expect(response.statusCode).to.equal(200)
  121. const trashedProject = await Project.findById(this.projectId).exec()
  122. expectObjectIdArrayEqual(trashedProject.archived, [])
  123. })
  124. })
  125. })
  126. describe('when untrashing a project', function () {
  127. it('should mark the project as untrashed for the user', async function () {
  128. await Project.updateOne(
  129. { _id: this.projectId },
  130. { trashed: [new ObjectId(this.user._id)] }
  131. ).exec()
  132. const { response } = await this.user.doRequest(
  133. 'DELETE',
  134. `/project/${this.projectId}/trash`
  135. )
  136. expect(response.statusCode).to.equal(200)
  137. const trashedProject = await Project.findById(this.projectId).exec()
  138. expectObjectIdArrayEqual(trashedProject.trashed, [])
  139. })
  140. it('does nothing if the user has already untrashed the project', async function () {
  141. await Project.updateOne(
  142. { _id: this.projectId },
  143. { trashed: [new ObjectId(this.user._id)] }
  144. ).exec()
  145. // Mark as untrashed the first time
  146. await this.user.doRequest('DELETE', `/project/${this.projectId}/trash`)
  147. // And then a second time
  148. await this.user.doRequest('DELETE', `/project/${this.projectId}/trash`)
  149. const trashedProject = await Project.findById(this.projectId).exec()
  150. expectObjectIdArrayEqual(trashedProject.trashed, [])
  151. })
  152. it('sets trashed to an empty array if not set', async function () {
  153. await this.user.doRequest('DELETE', `/project/${this.projectId}/trash`)
  154. const trashedProject = await Project.findById(this.projectId).exec()
  155. expectObjectIdArrayEqual(trashedProject.trashed, [])
  156. })
  157. })
  158. })
  159. function expectObjectIdArrayEqual(objectIdArray, stringArray) {
  160. const stringifiedArray = objectIdArray.map(id => id.toString())
  161. expect(stringifiedArray).to.deep.equal(stringArray)
  162. }