RejectingChangesTests.js 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  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(function (done) {
  9. DocUpdaterApp.ensureRunning(done)
  10. })
  11. describe('rejecting a single change', function () {
  12. beforeEach(function (done) {
  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. DocUpdaterClient.sendUpdate(
  35. this.project_id,
  36. this.doc.id,
  37. this.update,
  38. done
  39. )
  40. })
  41. afterEach(function () {
  42. sandbox.restore()
  43. })
  44. it('should reject the change and restore the original text', function (done) {
  45. DocUpdaterClient.getDoc(
  46. this.project_id,
  47. this.doc.id,
  48. (error, res, data) => {
  49. if (error != null) {
  50. throw error
  51. }
  52. expect(data.ranges.changes).to.have.length(1)
  53. const change = data.ranges.changes[0]
  54. expect(change.op).to.deep.equal({ i: 'quick ', p: 4 })
  55. expect(change.id).to.equal(this.id_seed + '000001')
  56. expect(data.lines).to.deep.equal([
  57. 'the quick brown fox jumps over the lazy dog',
  58. ])
  59. DocUpdaterClient.rejectChanges(
  60. this.project_id,
  61. this.doc.id,
  62. [change.id],
  63. this.user_id,
  64. (error, res, body) => {
  65. if (error != null) {
  66. throw error
  67. }
  68. expect(res.statusCode).to.equal(200)
  69. expect(body.rejectedChangeIds).to.be.an('array')
  70. expect(body.rejectedChangeIds).to.include(change.id)
  71. DocUpdaterClient.getDoc(
  72. this.project_id,
  73. this.doc.id,
  74. (error, res, data) => {
  75. if (error != null) {
  76. throw error
  77. }
  78. expect(data.ranges.changes || []).to.have.length(0)
  79. expect(data.lines).to.deep.equal([
  80. 'the brown fox jumps over the lazy dog',
  81. ])
  82. done()
  83. }
  84. )
  85. }
  86. )
  87. }
  88. )
  89. })
  90. it('should return 200 status code with rejectedChangeIds on successful rejection', function (done) {
  91. DocUpdaterClient.getDoc(
  92. this.project_id,
  93. this.doc.id,
  94. (error, res, data) => {
  95. if (error != null) {
  96. throw error
  97. }
  98. const changeId = data.ranges.changes[0].id
  99. DocUpdaterClient.rejectChanges(
  100. this.project_id,
  101. this.doc.id,
  102. [changeId],
  103. this.user_id,
  104. (error, res, body) => {
  105. if (error != null) {
  106. throw error
  107. }
  108. expect(res.statusCode).to.equal(200)
  109. expect(body.rejectedChangeIds).to.be.an('array')
  110. expect(body.rejectedChangeIds).to.include(changeId)
  111. done()
  112. }
  113. )
  114. }
  115. )
  116. })
  117. })
  118. describe('rejecting multiple changes', function () {
  119. beforeEach(function (done) {
  120. this.project_id = DocUpdaterClient.randomId()
  121. this.user_id = DocUpdaterClient.randomId()
  122. this.doc = {
  123. id: DocUpdaterClient.randomId(),
  124. lines: ['the brown fox jumps over the lazy dog'],
  125. }
  126. MockWebApi.insertDoc(this.project_id, this.doc.id, {
  127. lines: this.doc.lines,
  128. version: 0,
  129. historyRangesSupport: true,
  130. })
  131. this.id_seed_1 = 'tc_reject_1'
  132. this.id_seed_2 = 'tc_reject_2'
  133. this.updates = [
  134. {
  135. doc: this.doc.id,
  136. op: [{ i: 'quick ', p: 4 }],
  137. v: 0,
  138. meta: {
  139. user_id: this.user_id,
  140. tc: this.id_seed_1,
  141. },
  142. },
  143. {
  144. doc: this.doc.id,
  145. op: [{ d: 'lazy ', p: 35 }],
  146. v: 1,
  147. meta: {
  148. user_id: this.user_id,
  149. tc: this.id_seed_2,
  150. },
  151. },
  152. ]
  153. DocUpdaterClient.sendUpdates(
  154. this.project_id,
  155. this.doc.id,
  156. this.updates,
  157. done
  158. )
  159. })
  160. afterEach(function () {
  161. sandbox.restore()
  162. })
  163. it('should reject multiple changes in order', function (done) {
  164. DocUpdaterClient.getDoc(
  165. this.project_id,
  166. this.doc.id,
  167. (error, res, data) => {
  168. if (error != null) {
  169. throw error
  170. }
  171. expect(data.ranges.changes).to.have.length(2)
  172. expect(data.lines).to.deep.equal([
  173. 'the quick brown fox jumps over the dog',
  174. ])
  175. const changeIds = data.ranges.changes.map(change => change.id)
  176. DocUpdaterClient.rejectChanges(
  177. this.project_id,
  178. this.doc.id,
  179. changeIds,
  180. this.user_id,
  181. (error, res, body) => {
  182. if (error != null) {
  183. throw error
  184. }
  185. expect(res.statusCode).to.equal(200)
  186. expect(body.rejectedChangeIds).to.be.an('array')
  187. expect(body.rejectedChangeIds).to.have.length(2)
  188. expect(body.rejectedChangeIds).to.include.members(changeIds)
  189. DocUpdaterClient.getDoc(
  190. this.project_id,
  191. this.doc.id,
  192. (error, res, data) => {
  193. if (error != null) {
  194. throw error
  195. }
  196. expect(data.ranges.changes || []).to.have.length(0)
  197. expect(data.lines).to.deep.equal([
  198. 'the brown fox jumps over the lazy dog',
  199. ])
  200. done()
  201. }
  202. )
  203. }
  204. )
  205. }
  206. )
  207. })
  208. })
  209. describe('error cases', function () {
  210. beforeEach(function (done) {
  211. this.project_id = DocUpdaterClient.randomId()
  212. this.user_id = DocUpdaterClient.randomId()
  213. this.doc = {
  214. id: DocUpdaterClient.randomId(),
  215. lines: ['the brown fox jumps over the lazy dog'],
  216. }
  217. MockWebApi.insertDoc(this.project_id, this.doc.id, {
  218. lines: this.doc.lines,
  219. version: 0,
  220. historyRangesSupport: true,
  221. })
  222. DocUpdaterApp.ensureRunning(done)
  223. })
  224. it('should handle rejection of non-existent changes gracefully', function (done) {
  225. const nonExistentChangeId = 'nonexistent_change_id'
  226. DocUpdaterClient.rejectChanges(
  227. this.project_id,
  228. this.doc.id,
  229. [nonExistentChangeId],
  230. this.user_id,
  231. (error, res, body) => {
  232. // Should still return 200 with empty rejectedChangeIds if no changes were found to reject
  233. if (error != null) {
  234. throw error
  235. }
  236. expect(res.statusCode).to.equal(200)
  237. expect(body.rejectedChangeIds).to.be.an('array')
  238. expect(body.rejectedChangeIds).to.have.length(0)
  239. done()
  240. }
  241. )
  242. })
  243. it('should handle empty change_ids array', function (done) {
  244. DocUpdaterClient.rejectChanges(
  245. this.project_id,
  246. this.doc.id,
  247. [],
  248. this.user_id,
  249. (error, res, body) => {
  250. if (error != null) {
  251. throw error
  252. }
  253. expect(res.statusCode).to.equal(200)
  254. expect(body.rejectedChangeIds).to.be.an('array')
  255. expect(body.rejectedChangeIds).to.have.length(0)
  256. done()
  257. }
  258. )
  259. })
  260. })
  261. })