ProjectHistoryHandler.test.mjs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. import { vi } from 'vitest'
  2. import sinon from 'sinon'
  3. const modulePath =
  4. '../../../../app/src/Features/Project/ProjectHistoryHandler.mjs'
  5. describe('ProjectHistoryHandler', function () {
  6. const projectId = '4eecb1c1bffa66588e0000a1'
  7. beforeEach(async function (ctx) {
  8. let Project
  9. ctx.ProjectModel = Project = (function () {
  10. Project = class Project {
  11. static initClass() {
  12. this.prototype.rootFolder = [this.rootFolder]
  13. }
  14. constructor(options) {
  15. this._id = projectId
  16. this.name = 'project_name_here'
  17. this.rev = 0
  18. }
  19. }
  20. Project.initClass()
  21. return Project
  22. })()
  23. ctx.project = new ctx.ProjectModel()
  24. ctx.historyId = ctx.project._id.toString()
  25. ctx.callback = sinon.stub()
  26. vi.doMock('@overleaf/settings', () => ({
  27. default: (ctx.Settings = {}),
  28. }))
  29. vi.doMock('../../../../app/src/models/Project.mjs', () => ({
  30. Project: ctx.ProjectModel,
  31. }))
  32. vi.doMock(
  33. '../../../../app/src/Features/Project/ProjectDetailsHandler.mjs',
  34. () => ({
  35. default: (ctx.ProjectDetailsHandler = {
  36. promises: {},
  37. }),
  38. })
  39. )
  40. vi.doMock(
  41. '../../../../app/src/Features/History/HistoryManager.mjs',
  42. () => ({
  43. default: (ctx.HistoryManager = {
  44. promises: {},
  45. }),
  46. })
  47. )
  48. vi.doMock(
  49. '../../../../app/src/Features/Project/ProjectEntityUpdateHandler',
  50. () => ({
  51. default: (ctx.ProjectEntityUpdateHandler = {
  52. promises: {},
  53. }),
  54. })
  55. )
  56. return (ctx.ProjectHistoryHandler = (await import(modulePath)).default)
  57. })
  58. describe('starting history for an existing project', function () {
  59. beforeEach(async function (ctx) {
  60. ctx.HistoryManager.promises.initializeProject = sinon
  61. .stub()
  62. .resolves(ctx.historyId)
  63. ctx.HistoryManager.promises.flushProject = sinon.stub()
  64. return (ctx.ProjectEntityUpdateHandler.promises.resyncProjectHistory =
  65. sinon.stub())
  66. })
  67. describe('when the history does not already exist', function () {
  68. beforeEach(async function (ctx) {
  69. ctx.ProjectDetailsHandler.promises.getDetails = sinon
  70. .stub()
  71. .withArgs(projectId)
  72. .resolves(ctx.project)
  73. ctx.ProjectModel.updateOne = sinon.stub().resolves({ matchedCount: 1 })
  74. return ctx.ProjectHistoryHandler.promises.ensureHistoryExistsForProject(
  75. projectId
  76. )
  77. })
  78. it('should get any existing history id for the project', async function (ctx) {
  79. return ctx.ProjectDetailsHandler.promises.getDetails
  80. .calledWith(projectId)
  81. .should.equal(true)
  82. })
  83. it('should initialize a new history in the v1 history service', async function (ctx) {
  84. return ctx.HistoryManager.promises.initializeProject.called.should.equal(
  85. true
  86. )
  87. })
  88. it('should set the new history id on the project', async function (ctx) {
  89. return ctx.ProjectModel.updateOne
  90. .calledWith(
  91. { _id: projectId, 'overleaf.history.id': { $exists: false } },
  92. { 'overleaf.history.id': ctx.historyId }
  93. )
  94. .should.equal(true)
  95. })
  96. it('should resync the project history', async function (ctx) {
  97. return ctx.ProjectEntityUpdateHandler.promises.resyncProjectHistory
  98. .calledWith(projectId)
  99. .should.equal(true)
  100. })
  101. it('should flush the project history', async function (ctx) {
  102. return ctx.HistoryManager.promises.flushProject
  103. .calledWith(projectId)
  104. .should.equal(true)
  105. })
  106. })
  107. describe('when the history already exists', function () {
  108. beforeEach(function (ctx) {
  109. ctx.project.overleaf = { history: { id: 1234 } }
  110. ctx.ProjectDetailsHandler.promises.getDetails = sinon
  111. .stub()
  112. .withArgs(projectId)
  113. .resolves(ctx.project)
  114. ctx.ProjectModel.updateOne = sinon.stub().resolves({ matchedCount: 1 })
  115. return ctx.ProjectHistoryHandler.promises.ensureHistoryExistsForProject(
  116. projectId
  117. )
  118. })
  119. it('should get any existing history id for the project', async function (ctx) {
  120. return ctx.ProjectDetailsHandler.promises.getDetails
  121. .calledWith(projectId)
  122. .should.equal(true)
  123. })
  124. it('should not initialize a new history in the v1 history service', async function (ctx) {
  125. return ctx.HistoryManager.promises.initializeProject.called.should.equal(
  126. false
  127. )
  128. })
  129. it('should not set the new history id on the project', async function (ctx) {
  130. return ctx.ProjectModel.updateOne.called.should.equal(false)
  131. })
  132. it('should not resync the project history', async function (ctx) {
  133. return ctx.ProjectEntityUpdateHandler.promises.resyncProjectHistory.called.should.equal(
  134. false
  135. )
  136. })
  137. it('should not flush the project history', async function (ctx) {
  138. return ctx.HistoryManager.promises.flushProject.called.should.equal(
  139. false
  140. )
  141. })
  142. })
  143. })
  144. })