ranges-tracker-test.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  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' })
  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. })
  61. expect(this.rangesTracker.changes.map(c => c.op)).to.deep.equal([
  62. { p: 10, d: 'one' },
  63. { p: 15, d: '56789two0123456789three012345' },
  64. ])
  65. })
  66. it('a tracked delete between two tracked deletes joins them into a single tracked delete', function () {
  67. this.rangesTracker.track_changes = true
  68. this.rangesTracker.applyOp({
  69. p: 20,
  70. d: '0123456789',
  71. })
  72. expect(this.rangesTracker.changes.map(c => c.op)).to.deep.equal([
  73. { p: 10, d: 'one' },
  74. { p: 20, d: 'two0123456789three' },
  75. ])
  76. })
  77. it("rejecting one tracked delete doesn't reject the others", function () {
  78. this.rangesTracker.track_changes = true
  79. this.rangesTracker.applyOp({
  80. p: 20,
  81. i: 'two',
  82. u: true,
  83. })
  84. expect(this.rangesTracker.changes.map(c => c.op)).to.deep.equal([
  85. { p: 10, d: 'one' },
  86. { p: 33, d: 'three' },
  87. ])
  88. })
  89. it("rejecting all tracked deletes doesn't introduce tracked inserts", function () {
  90. this.rangesTracker.track_changes = true
  91. this.rangesTracker.applyOp({
  92. p: 10,
  93. i: 'one',
  94. u: true,
  95. })
  96. this.rangesTracker.applyOp({
  97. p: 23,
  98. i: 'two',
  99. u: true,
  100. })
  101. this.rangesTracker.applyOp({
  102. p: 36,
  103. i: 'three',
  104. u: true,
  105. })
  106. expect(this.rangesTracker.changes.map(c => c.op)).to.deep.equal([])
  107. })
  108. })
  109. describe('with multiple tracked deletes at the same position', function () {
  110. beforeEach(function () {
  111. this.comments = []
  112. this.changes = [
  113. { id: 'id1', op: { p: 33, d: 'before' } },
  114. { id: 'id2', op: { p: 50, d: 'right before' } },
  115. { id: 'id3', op: { p: 50, d: 'this one' } },
  116. { id: 'id4', op: { p: 50, d: 'right after' } },
  117. { id: 'id5', op: { p: 75, d: 'long after' } },
  118. ]
  119. this.rangesTracker = new RangesTracker(this.changes, this.comments)
  120. })
  121. it('preserves the text order when rejecting changes', function () {
  122. this.rangesTracker.applyOp(
  123. { p: 50, i: 'this one', u: true },
  124. { user_id: 'user-id' }
  125. )
  126. expect(this.rangesTracker.changes).to.deep.equal([
  127. { id: 'id1', op: { p: 33, d: 'before' } },
  128. { id: 'id2', op: { p: 50, d: 'right before' } },
  129. { id: 'id4', op: { p: 58, d: 'right after' } },
  130. { id: 'id5', op: { p: 83, d: 'long after' } },
  131. ])
  132. })
  133. it('moves all tracked deletes after the insert if not rejecting changes', function () {
  134. this.rangesTracker.applyOp(
  135. { p: 50, i: 'some other text', u: true, orderedRejections: true },
  136. { user_id: 'user-id' }
  137. )
  138. expect(this.rangesTracker.changes).to.deep.equal([
  139. { id: 'id1', op: { p: 33, d: 'before' } },
  140. { id: 'id2', op: { p: 65, d: 'right before' } },
  141. { id: 'id3', op: { p: 65, d: 'this one' } },
  142. { id: 'id4', op: { p: 65, d: 'right after' } },
  143. { id: 'id5', op: { p: 90, d: 'long after' } },
  144. ])
  145. })
  146. })
  147. describe('with multiple tracked deletes at the same position with the same content', function () {
  148. beforeEach(function () {
  149. this.comments = []
  150. this.changes = [
  151. { id: 'id1', op: { p: 10, d: 'cat' } },
  152. { id: 'id2', op: { p: 10, d: 'giraffe' } },
  153. { id: 'id3', op: { p: 10, d: 'cat' } },
  154. { id: 'id4', op: { p: 10, d: 'giraffe' } },
  155. ]
  156. this.rangesTracker = new RangesTracker(this.changes, this.comments)
  157. })
  158. it('removes only the first matching tracked delete', function () {
  159. this.rangesTracker.applyOp(
  160. { p: 10, i: 'giraffe', u: true },
  161. { user_id: 'user-id' }
  162. )
  163. expect(this.rangesTracker.changes).to.deep.equal([
  164. { id: 'id1', op: { p: 10, d: 'cat' } },
  165. { id: 'id3', op: { p: 17, d: 'cat' } },
  166. { id: 'id4', op: { p: 17, d: 'giraffe' } },
  167. ])
  168. })
  169. })
  170. describe('with a tracked insert at the same position as a tracked delete', function () {
  171. beforeEach(function () {
  172. this.comments = []
  173. this.changes = [
  174. {
  175. id: 'id1',
  176. op: { p: 5, d: 'before' },
  177. metadata: { user_id: 'user-id' },
  178. },
  179. {
  180. id: 'id2',
  181. op: { p: 10, d: 'delete' },
  182. metadata: { user_id: 'user-id' },
  183. },
  184. {
  185. id: 'id3',
  186. op: { p: 10, i: 'insert' },
  187. metadata: { user_id: 'user-id' },
  188. },
  189. ]
  190. this.rangesTracker = new RangesTracker(this.changes, this.comments)
  191. })
  192. it('places a tracked insert at the same position before both the delete and the insert', function () {
  193. this.rangesTracker.track_changes = true
  194. this.rangesTracker.applyOp(
  195. { p: 10, i: 'incoming' },
  196. { user_id: 'user-id' }
  197. )
  198. expect(this.rangesTracker.changes.map(change => change.op)).to.deep.equal(
  199. [
  200. { p: 5, d: 'before' },
  201. { p: 10, i: 'incoming' },
  202. { p: 18, d: 'delete' },
  203. { p: 18, i: 'insert' },
  204. ]
  205. )
  206. })
  207. })
  208. })