RejectingChangesTests.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. const sinon = require('sinon')
  2. const { expect } = require('chai')
  3. const MockWebApi = require('./helpers/MockWebApi')
  4. const DocUpdaterClient = require('./helpers/DocUpdaterClient')
  5. const DocUpdaterApp = require('./helpers/DocUpdaterApp')
  6. const sandbox = sinon.createSandbox()
  7. describe('Rejecting Changes', function () {
  8. before(async function () {
  9. await DocUpdaterApp.ensureRunning()
  10. })
  11. describe('rejecting a single change', function () {
  12. beforeEach(async function () {
  13. this.project_id = DocUpdaterClient.randomId()
  14. this.user_id = DocUpdaterClient.randomId()
  15. this.doc = {
  16. id: DocUpdaterClient.randomId(),
  17. lines: ['the brown fox jumps over the lazy dog'],
  18. }
  19. MockWebApi.insertDoc(this.project_id, this.doc.id, {
  20. lines: this.doc.lines,
  21. version: 0,
  22. historyRangesSupport: true,
  23. })
  24. this.id_seed = 'tc_reject_test'
  25. this.update = {
  26. doc: this.doc.id,
  27. op: [{ i: 'quick ', p: 4 }],
  28. v: 0,
  29. meta: {
  30. user_id: this.user_id,
  31. tc: this.id_seed,
  32. },
  33. }
  34. await DocUpdaterClient.sendUpdate(
  35. this.project_id,
  36. this.doc.id,
  37. this.update
  38. )
  39. })
  40. afterEach(function () {
  41. sandbox.restore()
  42. })
  43. it('should reject the change and restore the original text', async function () {
  44. const doc1 = await DocUpdaterClient.getDoc(this.project_id, this.doc.id)
  45. expect(doc1.ranges.changes).to.have.length(1)
  46. const change = doc1.ranges.changes[0]
  47. expect(change.op).to.deep.equal({ i: 'quick ', p: 4 })
  48. expect(change.id).to.equal(this.id_seed + '000001')
  49. expect(doc1.lines).to.deep.equal([
  50. 'the quick brown fox jumps over the lazy dog',
  51. ])
  52. const { rejectedChangeIds } = await DocUpdaterClient.rejectChanges(
  53. this.project_id,
  54. this.doc.id,
  55. [change.id],
  56. this.user_id
  57. )
  58. expect(rejectedChangeIds).to.be.an('array')
  59. expect(rejectedChangeIds).to.include(change.id)
  60. const doc2 = await DocUpdaterClient.getDoc(this.project_id, this.doc.id)
  61. expect(doc2.ranges.changes || []).to.have.length(0)
  62. expect(doc2.lines).to.deep.equal([
  63. 'the brown fox jumps over the lazy dog',
  64. ])
  65. })
  66. it('should return 200 status code with rejectedChangeIds on successful rejection', async function () {
  67. const data = await DocUpdaterClient.getDoc(this.project_id, this.doc.id)
  68. const changeId = data.ranges.changes[0].id
  69. const { rejectedChangeIds } = await DocUpdaterClient.rejectChanges(
  70. this.project_id,
  71. this.doc.id,
  72. [changeId],
  73. this.user_id
  74. )
  75. expect(rejectedChangeIds).to.be.an('array')
  76. expect(rejectedChangeIds).to.include(changeId)
  77. })
  78. })
  79. describe('rejecting multiple changes', function () {
  80. beforeEach(async function () {
  81. this.project_id = DocUpdaterClient.randomId()
  82. this.user_id = DocUpdaterClient.randomId()
  83. this.doc = {
  84. id: DocUpdaterClient.randomId(),
  85. lines: ['the brown fox jumps over the lazy dog'],
  86. }
  87. MockWebApi.insertDoc(this.project_id, this.doc.id, {
  88. lines: this.doc.lines,
  89. version: 0,
  90. historyRangesSupport: true,
  91. })
  92. this.id_seed_1 = 'tc_reject_1'
  93. this.id_seed_2 = 'tc_reject_2'
  94. this.updates = [
  95. {
  96. doc: this.doc.id,
  97. op: [{ i: 'quick ', p: 4 }],
  98. v: 0,
  99. meta: {
  100. user_id: this.user_id,
  101. tc: this.id_seed_1,
  102. },
  103. },
  104. {
  105. doc: this.doc.id,
  106. op: [{ d: 'lazy ', p: 35 }],
  107. v: 1,
  108. meta: {
  109. user_id: this.user_id,
  110. tc: this.id_seed_2,
  111. },
  112. },
  113. ]
  114. await DocUpdaterClient.sendUpdates(
  115. this.project_id,
  116. this.doc.id,
  117. this.updates
  118. )
  119. })
  120. afterEach(function () {
  121. sandbox.restore()
  122. })
  123. it('should reject multiple changes in order', async function () {
  124. const data = await DocUpdaterClient.getDoc(this.project_id, this.doc.id)
  125. expect(data.ranges.changes).to.have.length(2)
  126. expect(data.lines).to.deep.equal([
  127. 'the quick brown fox jumps over the dog',
  128. ])
  129. const changeIds = data.ranges.changes.map(change => change.id)
  130. const { rejectedChangeIds } = await DocUpdaterClient.rejectChanges(
  131. this.project_id,
  132. this.doc.id,
  133. changeIds,
  134. this.user_id
  135. )
  136. expect(rejectedChangeIds).to.be.an('array')
  137. expect(rejectedChangeIds).to.have.length(2)
  138. expect(rejectedChangeIds).to.include.members(changeIds)
  139. const data2 = await DocUpdaterClient.getDoc(this.project_id, this.doc.id)
  140. expect(data2.ranges.changes || []).to.have.length(0)
  141. expect(data2.lines).to.deep.equal([
  142. 'the brown fox jumps over the lazy dog',
  143. ])
  144. })
  145. })
  146. describe('error cases', function () {
  147. beforeEach(async function () {
  148. this.project_id = DocUpdaterClient.randomId()
  149. this.user_id = DocUpdaterClient.randomId()
  150. this.doc = {
  151. id: DocUpdaterClient.randomId(),
  152. lines: ['the brown fox jumps over the lazy dog'],
  153. }
  154. MockWebApi.insertDoc(this.project_id, this.doc.id, {
  155. lines: this.doc.lines,
  156. version: 0,
  157. historyRangesSupport: true,
  158. })
  159. await DocUpdaterApp.ensureRunning()
  160. })
  161. it('should handle rejection of non-existent changes gracefully', async function () {
  162. const nonExistentChangeId = 'nonexistent_change_id'
  163. const { rejectedChangeIds } = await DocUpdaterClient.rejectChanges(
  164. this.project_id,
  165. this.doc.id,
  166. [nonExistentChangeId],
  167. this.user_id
  168. )
  169. // Should still return 200 with empty rejectedChangeIds if no changes were found to reject
  170. expect(rejectedChangeIds).to.be.an('array')
  171. expect(rejectedChangeIds).to.have.length(0)
  172. })
  173. it('should handle empty change_ids array', async function () {
  174. const { rejectedChangeIds } = await DocUpdaterClient.rejectChanges(
  175. this.project_id,
  176. this.doc.id,
  177. [],
  178. this.user_id
  179. )
  180. expect(rejectedChangeIds).to.be.an('array')
  181. expect(rejectedChangeIds).to.have.length(0)
  182. })
  183. })
  184. })