ProjectHistoryHandler.test.mjs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  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.js', () => ({
  30. Project: ctx.ProjectModel,
  31. }))
  32. vi.doMock(
  33. '../../../../app/src/Features/Project/ProjectDetailsHandler.js',
  34. () => ({
  35. default: (ctx.ProjectDetailsHandler = {
  36. promises: {},
  37. }),
  38. })
  39. )
  40. vi.doMock('../../../../app/src/Features/History/HistoryManager.js', () => ({
  41. default: (ctx.HistoryManager = {
  42. promises: {},
  43. }),
  44. }))
  45. vi.doMock(
  46. '../../../../app/src/Features/Project/ProjectEntityUpdateHandler',
  47. () => ({
  48. default: (ctx.ProjectEntityUpdateHandler = {
  49. promises: {},
  50. }),
  51. })
  52. )
  53. return (ctx.ProjectHistoryHandler = (await import(modulePath)).default)
  54. })
  55. describe('starting history for an existing project', function () {
  56. beforeEach(async function (ctx) {
  57. ctx.HistoryManager.promises.initializeProject = sinon
  58. .stub()
  59. .resolves(ctx.historyId)
  60. ctx.HistoryManager.promises.flushProject = sinon.stub()
  61. return (ctx.ProjectEntityUpdateHandler.promises.resyncProjectHistory =
  62. sinon.stub())
  63. })
  64. describe('when the history does not already exist', function () {
  65. beforeEach(async function (ctx) {
  66. ctx.ProjectDetailsHandler.promises.getDetails = sinon
  67. .stub()
  68. .withArgs(projectId)
  69. .resolves(ctx.project)
  70. ctx.ProjectModel.updateOne = sinon.stub().resolves({ matchedCount: 1 })
  71. return ctx.ProjectHistoryHandler.promises.ensureHistoryExistsForProject(
  72. projectId
  73. )
  74. })
  75. it('should get any existing history id for the project', async function (ctx) {
  76. return ctx.ProjectDetailsHandler.promises.getDetails
  77. .calledWith(projectId)
  78. .should.equal(true)
  79. })
  80. it('should initialize a new history in the v1 history service', async function (ctx) {
  81. return ctx.HistoryManager.promises.initializeProject.called.should.equal(
  82. true
  83. )
  84. })
  85. it('should set the new history id on the project', async function (ctx) {
  86. return ctx.ProjectModel.updateOne
  87. .calledWith(
  88. { _id: projectId, 'overleaf.history.id': { $exists: false } },
  89. { 'overleaf.history.id': ctx.historyId }
  90. )
  91. .should.equal(true)
  92. })
  93. it('should resync the project history', async function (ctx) {
  94. return ctx.ProjectEntityUpdateHandler.promises.resyncProjectHistory
  95. .calledWith(projectId)
  96. .should.equal(true)
  97. })
  98. it('should flush the project history', async function (ctx) {
  99. return ctx.HistoryManager.promises.flushProject
  100. .calledWith(projectId)
  101. .should.equal(true)
  102. })
  103. })
  104. describe('when the history already exists', function () {
  105. beforeEach(function (ctx) {
  106. ctx.project.overleaf = { history: { id: 1234 } }
  107. ctx.ProjectDetailsHandler.promises.getDetails = sinon
  108. .stub()
  109. .withArgs(projectId)
  110. .resolves(ctx.project)
  111. ctx.ProjectModel.updateOne = sinon.stub().resolves({ matchedCount: 1 })
  112. return ctx.ProjectHistoryHandler.promises.ensureHistoryExistsForProject(
  113. projectId
  114. )
  115. })
  116. it('should get any existing history id for the project', async function (ctx) {
  117. return ctx.ProjectDetailsHandler.promises.getDetails
  118. .calledWith(projectId)
  119. .should.equal(true)
  120. })
  121. it('should not initialize a new history in the v1 history service', async function (ctx) {
  122. return ctx.HistoryManager.promises.initializeProject.called.should.equal(
  123. false
  124. )
  125. })
  126. it('should not set the new history id on the project', async function (ctx) {
  127. return ctx.ProjectModel.updateOne.called.should.equal(false)
  128. })
  129. it('should not resync the project history', async function (ctx) {
  130. return ctx.ProjectEntityUpdateHandler.promises.resyncProjectHistory.called.should.equal(
  131. false
  132. )
  133. })
  134. it('should not flush the project history', async function (ctx) {
  135. return ctx.HistoryManager.promises.flushProject.called.should.equal(
  136. false
  137. )
  138. })
  139. })
  140. })
  141. })