LabelsManagerTests.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. import sinon from 'sinon'
  2. import { expect } from 'chai'
  3. import mongodb from 'mongodb-legacy'
  4. import tk from 'timekeeper'
  5. import { strict as esmock } from 'esmock'
  6. const { ObjectId } = mongodb
  7. const MODULE_PATH = '../../../../app/js/LabelsManager.js'
  8. describe('LabelsManager', function () {
  9. beforeEach(async function () {
  10. this.now = new Date()
  11. tk.freeze(this.now)
  12. this.db = {
  13. projectHistoryLabels: {
  14. deleteOne: sinon.stub(),
  15. find: sinon.stub(),
  16. insertOne: sinon.stub(),
  17. },
  18. }
  19. this.mongodb = {
  20. ObjectId,
  21. db: this.db,
  22. }
  23. this.HistoryStoreManager = {
  24. getChunkAtVersion: sinon.stub().yields(),
  25. }
  26. this.UpdatesProcessor = {
  27. processUpdatesForProject: sinon.stub().yields(),
  28. }
  29. this.WebApiManager = {
  30. getHistoryId: sinon.stub(),
  31. }
  32. this.LabelsManager = await esmock(MODULE_PATH, {
  33. '../../../../app/js/mongodb.js': this.mongodb,
  34. '../../../../app/js/HistoryStoreManager.js': this.HistoryStoreManager,
  35. '../../../../app/js/UpdatesProcessor.js': this.UpdatesProcessor,
  36. '../../../../app/js/WebApiManager.js': this.WebApiManager,
  37. })
  38. this.project_id = new ObjectId().toString()
  39. this.historyId = 123
  40. this.user_id = new ObjectId().toString()
  41. this.label_id = new ObjectId().toString()
  42. this.callback = sinon.stub()
  43. })
  44. afterEach(function () {
  45. tk.reset()
  46. })
  47. describe('getLabels', function () {
  48. beforeEach(function () {
  49. this.label = {
  50. _id: new ObjectId(),
  51. comment: 'some comment',
  52. version: 123,
  53. user_id: new ObjectId(),
  54. created_at: new Date(),
  55. }
  56. this.db.projectHistoryLabels.find.returns({
  57. toArray: sinon.stub().yields(null, [this.label]),
  58. })
  59. })
  60. describe('with valid project id', function () {
  61. beforeEach(function () {
  62. this.LabelsManager.getLabels(this.project_id, this.callback)
  63. })
  64. it('gets the labels state from mongo', function () {
  65. expect(this.db.projectHistoryLabels.find).to.have.been.calledWith({
  66. project_id: new ObjectId(this.project_id),
  67. })
  68. })
  69. it('returns formatted labels', function () {
  70. expect(this.callback).to.have.been.calledWith(null, [
  71. sinon.match({
  72. id: this.label._id,
  73. comment: this.label.comment,
  74. version: this.label.version,
  75. user_id: this.label.user_id,
  76. created_at: this.label.created_at,
  77. }),
  78. ])
  79. })
  80. })
  81. describe('with invalid project id', function () {
  82. it('returns an error', function (done) {
  83. this.LabelsManager.getLabels('invalid id', error => {
  84. expect(error).to.exist
  85. done()
  86. })
  87. })
  88. })
  89. })
  90. describe('createLabel', function () {
  91. beforeEach(function () {
  92. this.version = 123
  93. this.comment = 'a comment'
  94. this.WebApiManager.getHistoryId.yields(null, this.historyId)
  95. })
  96. describe('with createdAt', function () {
  97. beforeEach(function () {
  98. this.createdAt = new Date(1)
  99. this.db.projectHistoryLabels.insertOne.yields(null, {
  100. insertedId: new ObjectId(this.label_id),
  101. })
  102. this.LabelsManager.createLabel(
  103. this.project_id,
  104. this.user_id,
  105. this.version,
  106. this.comment,
  107. this.createdAt,
  108. true,
  109. this.callback
  110. )
  111. })
  112. it('flushes unprocessed updates', function () {
  113. expect(
  114. this.UpdatesProcessor.processUpdatesForProject
  115. ).to.have.been.calledWith(this.project_id)
  116. })
  117. it('finds the V1 project id', function () {
  118. expect(this.WebApiManager.getHistoryId).to.have.been.calledWith(
  119. this.project_id
  120. )
  121. })
  122. it('checks there is a chunk for the project + version', function () {
  123. expect(
  124. this.HistoryStoreManager.getChunkAtVersion
  125. ).to.have.been.calledWith(this.project_id, this.historyId, this.version)
  126. })
  127. it('create the label in mongo', function () {
  128. expect(this.db.projectHistoryLabels.insertOne).to.have.been.calledWith(
  129. sinon.match({
  130. project_id: new ObjectId(this.project_id),
  131. comment: this.comment,
  132. version: this.version,
  133. user_id: new ObjectId(this.user_id),
  134. created_at: this.createdAt,
  135. }),
  136. sinon.match.any
  137. )
  138. })
  139. it('returns the label', function () {
  140. expect(this.callback).to.have.been.calledWith(null, {
  141. id: new ObjectId(this.label_id),
  142. comment: this.comment,
  143. version: this.version,
  144. user_id: new ObjectId(this.user_id),
  145. created_at: this.createdAt,
  146. })
  147. })
  148. })
  149. describe('without createdAt', function () {
  150. beforeEach(function () {
  151. this.db.projectHistoryLabels.insertOne.yields(null, {
  152. insertedId: new ObjectId(this.label_id),
  153. })
  154. this.LabelsManager.createLabel(
  155. this.project_id,
  156. this.user_id,
  157. this.version,
  158. this.comment,
  159. undefined,
  160. true,
  161. this.callback
  162. )
  163. })
  164. it('create the label with the current date', function () {
  165. expect(this.db.projectHistoryLabels.insertOne).to.have.been.calledWith(
  166. sinon.match({
  167. project_id: new ObjectId(this.project_id),
  168. comment: this.comment,
  169. version: this.version,
  170. user_id: new ObjectId(this.user_id),
  171. created_at: this.now,
  172. })
  173. )
  174. })
  175. })
  176. describe('with shouldValidateExists = false', function () {
  177. beforeEach(function () {
  178. this.createdAt = new Date(1)
  179. this.db.projectHistoryLabels.insertOne.yields(null, {
  180. insertedId: new ObjectId(this.label_id),
  181. })
  182. this.LabelsManager.createLabel(
  183. this.project_id,
  184. this.user_id,
  185. this.version,
  186. this.comment,
  187. this.createdAt,
  188. false,
  189. this.callback
  190. )
  191. })
  192. it('checks there is a chunk for the project + version', function () {
  193. expect(this.HistoryStoreManager.getChunkAtVersion).to.not.have.been
  194. .called
  195. })
  196. })
  197. describe('with no userId', function () {
  198. beforeEach(function () {
  199. this.db.projectHistoryLabels.insertOne.yields(null, {
  200. insertedId: new ObjectId(this.label_id),
  201. })
  202. const userId = undefined
  203. this.LabelsManager.createLabel(
  204. this.project_id,
  205. userId,
  206. this.version,
  207. this.comment,
  208. this.createdAt,
  209. false,
  210. this.callback
  211. )
  212. })
  213. it('creates the label without user_id', function () {
  214. expect(this.db.projectHistoryLabels.insertOne).to.have.been.calledWith(
  215. sinon.match({
  216. project_id: new ObjectId(this.project_id),
  217. comment: this.comment,
  218. version: this.version,
  219. user_id: undefined,
  220. created_at: this.now,
  221. })
  222. )
  223. })
  224. })
  225. })
  226. describe('deleteLabelForUser', function () {
  227. beforeEach(function () {
  228. this.db.projectHistoryLabels.deleteOne.yields()
  229. this.LabelsManager.deleteLabelForUser(
  230. this.project_id,
  231. this.user_id,
  232. this.label_id,
  233. this.callback
  234. )
  235. })
  236. it('removes the label from the database', function () {
  237. expect(this.db.projectHistoryLabels.deleteOne).to.have.been.calledWith(
  238. {
  239. _id: new ObjectId(this.label_id),
  240. project_id: new ObjectId(this.project_id),
  241. user_id: new ObjectId(this.user_id),
  242. },
  243. this.callback
  244. )
  245. })
  246. })
  247. describe('deleteLabel', function () {
  248. beforeEach(function () {
  249. this.db.projectHistoryLabels.deleteOne.yields()
  250. this.LabelsManager.deleteLabel(
  251. this.project_id,
  252. this.label_id,
  253. this.callback
  254. )
  255. })
  256. it('removes the label from the database', function () {
  257. expect(this.db.projectHistoryLabels.deleteOne).to.have.been.calledWith(
  258. {
  259. _id: new ObjectId(this.label_id),
  260. project_id: new ObjectId(this.project_id),
  261. },
  262. this.callback
  263. )
  264. })
  265. })
  266. })