ranges-tracker-test.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. const { expect } = require('chai')
  2. const RangesTracker = require('../..')
  3. describe('RangesTracker', function () {
  4. describe('with duplicate change ids', function () {
  5. beforeEach(function () {
  6. this.comments = []
  7. this.changes = [
  8. { id: 'id1', op: { p: 1, i: 'hello' } },
  9. { id: 'id2', op: { p: 10, i: 'world' } },
  10. { id: 'id3', op: { p: 20, i: '!!!' } },
  11. { id: 'id1', op: { p: 30, d: 'duplicate' } },
  12. ]
  13. this.rangesTracker = new RangesTracker(this.changes, this.comments)
  14. })
  15. it('getChanges() returns all changes with the given ids', function () {
  16. expect(this.rangesTracker.getChanges(['id1', 'id2'])).to.deep.equal([
  17. this.changes[0],
  18. this.changes[1],
  19. this.changes[3],
  20. ])
  21. })
  22. it('removeChangeIds() removes all changes with the given ids', function () {
  23. this.rangesTracker.removeChangeIds(['id1', 'id2'])
  24. expect(this.rangesTracker.changes).to.deep.equal([this.changes[2]])
  25. })
  26. })
  27. describe('with duplicate tracked insert ids', function () {
  28. beforeEach(function () {
  29. this.comments = []
  30. this.changes = [
  31. { id: 'id1', op: { p: 10, i: 'one' } },
  32. { id: 'id1', op: { p: 20, i: 'two' } },
  33. { id: 'id1', op: { p: 30, d: 'three' } },
  34. ]
  35. this.rangesTracker = new RangesTracker(this.changes, this.comments)
  36. })
  37. it("deleting one tracked insert doesn't delete the others", function () {
  38. this.rangesTracker.applyOp({ p: 20, d: 'two', fixedRemoveChange: true })
  39. expect(this.rangesTracker.changes).to.deep.equal([
  40. this.changes[0],
  41. this.changes[2],
  42. ])
  43. })
  44. })
  45. describe('with duplicate tracked delete ids', function () {
  46. beforeEach(function () {
  47. this.comments = []
  48. this.changes = [
  49. { id: 'id1', op: { p: 10, d: 'one' } },
  50. { id: 'id1', op: { p: 20, d: 'two' } },
  51. { id: 'id1', op: { p: 30, d: 'three' } },
  52. ]
  53. this.rangesTracker = new RangesTracker(this.changes, this.comments)
  54. })
  55. it('deleting over tracked deletes in tracked changes mode removes the tracked deletes covered', function () {
  56. this.rangesTracker.track_changes = true
  57. this.rangesTracker.applyOp({
  58. p: 15,
  59. d: '567890123456789012345',
  60. fixedRemoveChange: true,
  61. })
  62. expect(this.rangesTracker.changes.map(c => c.op)).to.deep.equal([
  63. { p: 10, d: 'one' },
  64. { p: 15, d: '56789two0123456789three012345' },
  65. ])
  66. })
  67. it('a tracked delete between two tracked deletes joins them into a single tracked delete', function () {
  68. this.rangesTracker.track_changes = true
  69. this.rangesTracker.applyOp({
  70. p: 20,
  71. d: '0123456789',
  72. fixedRemoveChange: true,
  73. })
  74. expect(this.rangesTracker.changes.map(c => c.op)).to.deep.equal([
  75. { p: 10, d: 'one' },
  76. { p: 20, d: 'two0123456789three' },
  77. ])
  78. })
  79. it("rejecting one tracked delete doesn't reject the others", function () {
  80. this.rangesTracker.track_changes = true
  81. this.rangesTracker.applyOp({
  82. p: 20,
  83. i: 'two',
  84. u: true,
  85. fixedRemoveChange: true,
  86. })
  87. expect(this.rangesTracker.changes.map(c => c.op)).to.deep.equal([
  88. { p: 10, d: 'one' },
  89. { p: 33, d: 'three' },
  90. ])
  91. })
  92. it("rejecting all tracked deletes doesn't introduce tracked inserts", function () {
  93. this.rangesTracker.track_changes = true
  94. this.rangesTracker.applyOp({
  95. p: 10,
  96. i: 'one',
  97. u: true,
  98. fixedRemoveChange: true,
  99. })
  100. this.rangesTracker.applyOp({
  101. p: 23,
  102. i: 'two',
  103. u: true,
  104. fixedRemoveChange: true,
  105. })
  106. this.rangesTracker.applyOp({
  107. p: 36,
  108. i: 'three',
  109. u: true,
  110. fixedRemoveChange: true,
  111. })
  112. expect(this.rangesTracker.changes.map(c => c.op)).to.deep.equal([])
  113. })
  114. })
  115. describe('with multiple tracked deletes at the same position', function () {
  116. beforeEach(function () {
  117. this.comments = []
  118. this.changes = [
  119. { id: 'id1', op: { p: 33, d: 'before' } },
  120. { id: 'id2', op: { p: 50, d: 'right before' } },
  121. { id: 'id3', op: { p: 50, d: 'this one' } },
  122. { id: 'id4', op: { p: 50, d: 'right after' } },
  123. { id: 'id5', op: { p: 75, d: 'long after' } },
  124. ]
  125. this.rangesTracker = new RangesTracker(this.changes, this.comments)
  126. })
  127. it('preserves the text order when rejecting changes', function () {
  128. this.rangesTracker.applyOp(
  129. { p: 50, i: 'this one', u: true },
  130. { user_id: 'user-id' }
  131. )
  132. expect(this.rangesTracker.changes).to.deep.equal([
  133. { id: 'id1', op: { p: 33, d: 'before' } },
  134. { id: 'id2', op: { p: 50, d: 'right before' } },
  135. { id: 'id4', op: { p: 58, d: 'right after' } },
  136. { id: 'id5', op: { p: 83, d: 'long after' } },
  137. ])
  138. })
  139. it('moves all tracked deletes after the insert if not rejecting changes', function () {
  140. this.rangesTracker.applyOp(
  141. { p: 50, i: 'some other text', u: true, orderedRejections: true },
  142. { user_id: 'user-id' }
  143. )
  144. expect(this.rangesTracker.changes).to.deep.equal([
  145. { id: 'id1', op: { p: 33, d: 'before' } },
  146. { id: 'id2', op: { p: 65, d: 'right before' } },
  147. { id: 'id3', op: { p: 65, d: 'this one' } },
  148. { id: 'id4', op: { p: 65, d: 'right after' } },
  149. { id: 'id5', op: { p: 90, d: 'long after' } },
  150. ])
  151. })
  152. })
  153. describe('with multiple tracked deletes at the same position with the same content', function () {
  154. beforeEach(function () {
  155. this.comments = []
  156. this.changes = [
  157. { id: 'id1', op: { p: 10, d: 'cat' } },
  158. { id: 'id2', op: { p: 10, d: 'giraffe' } },
  159. { id: 'id3', op: { p: 10, d: 'cat' } },
  160. { id: 'id4', op: { p: 10, d: 'giraffe' } },
  161. ]
  162. this.rangesTracker = new RangesTracker(this.changes, this.comments)
  163. })
  164. it('removes only the first matching tracked delete', function () {
  165. this.rangesTracker.applyOp(
  166. { p: 10, i: 'giraffe', u: true },
  167. { user_id: 'user-id' }
  168. )
  169. expect(this.rangesTracker.changes).to.deep.equal([
  170. { id: 'id1', op: { p: 10, d: 'cat' } },
  171. { id: 'id3', op: { p: 17, d: 'cat' } },
  172. { id: 'id4', op: { p: 17, d: 'giraffe' } },
  173. ])
  174. })
  175. })
  176. describe('with a tracked insert at the same position as a tracked delete', function () {
  177. beforeEach(function () {
  178. this.comments = []
  179. this.changes = [
  180. {
  181. id: 'id1',
  182. op: { p: 5, d: 'before' },
  183. metadata: { user_id: 'user-id' },
  184. },
  185. {
  186. id: 'id2',
  187. op: { p: 10, d: 'delete' },
  188. metadata: { user_id: 'user-id' },
  189. },
  190. {
  191. id: 'id3',
  192. op: { p: 10, i: 'insert' },
  193. metadata: { user_id: 'user-id' },
  194. },
  195. ]
  196. this.rangesTracker = new RangesTracker(this.changes, this.comments)
  197. })
  198. it('places a tracked insert at the same position before both the delete and the insert', function () {
  199. this.rangesTracker.track_changes = true
  200. this.rangesTracker.applyOp(
  201. { p: 10, i: 'incoming' },
  202. { user_id: 'user-id' }
  203. )
  204. expect(this.rangesTracker.changes.map(change => change.op)).to.deep.equal(
  205. [
  206. { p: 5, d: 'before' },
  207. { p: 10, i: 'incoming' },
  208. { p: 18, d: 'delete' },
  209. { p: 18, i: 'insert' },
  210. ]
  211. )
  212. })
  213. })
  214. })