| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438 |
- /* eslint-disable
- camelcase,
- mocha/no-identical-title,
- no-return-assign,
- */
- // TODO: This file was created by bulk-decaffeinate.
- // Fix any style issues and re-enable lint.
- /*
- * decaffeinate suggestions:
- * DS101: Remove unnecessary use of Array.from
- * DS102: Remove unnecessary code created because of implicit returns
- * DS202: Simplify dynamic range loops
- * DS205: Consider reworking code to avoid use of IIFEs
- * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
- */
- const text = require('../../../../app/js/sharejs/types/text')
- const RangesTracker = require('../../../../app/js/RangesTracker')
- describe('ShareJS text type', function () {
- beforeEach(function () {
- return (this.t = 'mock-thread-id')
- })
- describe('transform', function () {
- describe('insert / insert', function () {
- it('with an insert before', function () {
- const dest = []
- text._tc(dest, { i: 'foo', p: 9 }, { i: 'bar', p: 3 })
- return dest.should.deep.equal([{ i: 'foo', p: 12 }])
- })
- it('with an insert after', function () {
- const dest = []
- text._tc(dest, { i: 'foo', p: 3 }, { i: 'bar', p: 9 })
- return dest.should.deep.equal([{ i: 'foo', p: 3 }])
- })
- it("with an insert at the same place with side == 'right'", function () {
- const dest = []
- text._tc(dest, { i: 'foo', p: 3 }, { i: 'bar', p: 3 }, 'right')
- return dest.should.deep.equal([{ i: 'foo', p: 6 }])
- })
- return it("with an insert at the same place with side == 'left'", function () {
- const dest = []
- text._tc(dest, { i: 'foo', p: 3 }, { i: 'bar', p: 3 }, 'left')
- return dest.should.deep.equal([{ i: 'foo', p: 3 }])
- })
- })
- describe('insert / delete', function () {
- it('with a delete before', function () {
- const dest = []
- text._tc(dest, { i: 'foo', p: 9 }, { d: 'bar', p: 3 })
- return dest.should.deep.equal([{ i: 'foo', p: 6 }])
- })
- it('with a delete after', function () {
- const dest = []
- text._tc(dest, { i: 'foo', p: 3 }, { d: 'bar', p: 9 })
- return dest.should.deep.equal([{ i: 'foo', p: 3 }])
- })
- it("with a delete at the same place with side == 'right'", function () {
- const dest = []
- text._tc(dest, { i: 'foo', p: 3 }, { d: 'bar', p: 3 }, 'right')
- return dest.should.deep.equal([{ i: 'foo', p: 3 }])
- })
- return it("with a delete at the same place with side == 'left'", function () {
- const dest = []
- text._tc(dest, { i: 'foo', p: 3 }, { d: 'bar', p: 3 }, 'left')
- return dest.should.deep.equal([{ i: 'foo', p: 3 }])
- })
- })
- describe('delete / insert', function () {
- it('with an insert before', function () {
- const dest = []
- text._tc(dest, { d: 'foo', p: 9 }, { i: 'bar', p: 3 })
- return dest.should.deep.equal([{ d: 'foo', p: 12 }])
- })
- it('with an insert after', function () {
- const dest = []
- text._tc(dest, { d: 'foo', p: 3 }, { i: 'bar', p: 9 })
- return dest.should.deep.equal([{ d: 'foo', p: 3 }])
- })
- it("with an insert at the same place with side == 'right'", function () {
- const dest = []
- text._tc(dest, { d: 'foo', p: 3 }, { i: 'bar', p: 3 }, 'right')
- return dest.should.deep.equal([{ d: 'foo', p: 6 }])
- })
- it("with an insert at the same place with side == 'left'", function () {
- const dest = []
- text._tc(dest, { d: 'foo', p: 3 }, { i: 'bar', p: 3 }, 'left')
- return dest.should.deep.equal([{ d: 'foo', p: 6 }])
- })
- return it('with a delete that overlaps the insert location', function () {
- const dest = []
- text._tc(dest, { d: 'foo', p: 3 }, { i: 'bar', p: 4 })
- return dest.should.deep.equal([
- { d: 'f', p: 3 },
- { d: 'oo', p: 6 }
- ])
- })
- })
- describe('delete / delete', function () {
- it('with a delete before', function () {
- const dest = []
- text._tc(dest, { d: 'foo', p: 9 }, { d: 'bar', p: 3 })
- return dest.should.deep.equal([{ d: 'foo', p: 6 }])
- })
- it('with a delete after', function () {
- const dest = []
- text._tc(dest, { d: 'foo', p: 3 }, { d: 'bar', p: 9 })
- return dest.should.deep.equal([{ d: 'foo', p: 3 }])
- })
- it('with deleting the same content', function () {
- const dest = []
- text._tc(dest, { d: 'foo', p: 3 }, { d: 'foo', p: 3 }, 'right')
- return dest.should.deep.equal([])
- })
- it('with the delete overlapping before', function () {
- const dest = []
- text._tc(dest, { d: 'foobar', p: 3 }, { d: 'abcfoo', p: 0 }, 'right')
- return dest.should.deep.equal([{ d: 'bar', p: 0 }])
- })
- it('with the delete overlapping after', function () {
- const dest = []
- text._tc(dest, { d: 'abcfoo', p: 3 }, { d: 'foobar', p: 6 })
- return dest.should.deep.equal([{ d: 'abc', p: 3 }])
- })
- it('with the delete overlapping the whole delete', function () {
- const dest = []
- text._tc(dest, { d: 'abcfoo123', p: 3 }, { d: 'foo', p: 6 })
- return dest.should.deep.equal([{ d: 'abc123', p: 3 }])
- })
- return it('with the delete inside the whole delete', function () {
- const dest = []
- text._tc(dest, { d: 'foo', p: 6 }, { d: 'abcfoo123', p: 3 })
- return dest.should.deep.equal([])
- })
- })
- describe('comment / insert', function () {
- it('with an insert before', function () {
- const dest = []
- text._tc(dest, { c: 'foo', p: 9, t: this.t }, { i: 'bar', p: 3 })
- return dest.should.deep.equal([{ c: 'foo', p: 12, t: this.t }])
- })
- it('with an insert after', function () {
- const dest = []
- text._tc(dest, { c: 'foo', p: 3, t: this.t }, { i: 'bar', p: 9 })
- return dest.should.deep.equal([{ c: 'foo', p: 3, t: this.t }])
- })
- it('with an insert at the left edge', function () {
- const dest = []
- text._tc(dest, { c: 'foo', p: 3, t: this.t }, { i: 'bar', p: 3 })
- // RangesTracker doesn't inject inserts into comments on edges, so neither should we
- return dest.should.deep.equal([{ c: 'foo', p: 6, t: this.t }])
- })
- it('with an insert at the right edge', function () {
- const dest = []
- text._tc(dest, { c: 'foo', p: 3, t: this.t }, { i: 'bar', p: 6 })
- // RangesTracker doesn't inject inserts into comments on edges, so neither should we
- return dest.should.deep.equal([{ c: 'foo', p: 3, t: this.t }])
- })
- return it('with an insert in the middle', function () {
- const dest = []
- text._tc(dest, { c: 'foo', p: 3, t: this.t }, { i: 'bar', p: 5 })
- return dest.should.deep.equal([{ c: 'fobaro', p: 3, t: this.t }])
- })
- })
- describe('comment / delete', function () {
- it('with a delete before', function () {
- const dest = []
- text._tc(dest, { c: 'foo', p: 9, t: this.t }, { d: 'bar', p: 3 })
- return dest.should.deep.equal([{ c: 'foo', p: 6, t: this.t }])
- })
- it('with a delete after', function () {
- const dest = []
- text._tc(dest, { c: 'foo', p: 3, t: this.t }, { i: 'bar', p: 9 })
- return dest.should.deep.equal([{ c: 'foo', p: 3, t: this.t }])
- })
- it('with a delete overlapping the comment content before', function () {
- const dest = []
- text._tc(dest, { c: 'foobar', p: 6, t: this.t }, { d: '123foo', p: 3 })
- return dest.should.deep.equal([{ c: 'bar', p: 3, t: this.t }])
- })
- it('with a delete overlapping the comment content after', function () {
- const dest = []
- text._tc(dest, { c: 'foobar', p: 6, t: this.t }, { d: 'bar123', p: 9 })
- return dest.should.deep.equal([{ c: 'foo', p: 6, t: this.t }])
- })
- it('with a delete overlapping the comment content in the middle', function () {
- const dest = []
- text._tc(dest, { c: 'foo123bar', p: 6, t: this.t }, { d: '123', p: 9 })
- return dest.should.deep.equal([{ c: 'foobar', p: 6, t: this.t }])
- })
- return it('with a delete overlapping the whole comment', function () {
- const dest = []
- text._tc(dest, { c: 'foo', p: 6, t: this.t }, { d: '123foo456', p: 3 })
- return dest.should.deep.equal([{ c: '', p: 3, t: this.t }])
- })
- })
- describe('comment / insert', function () {
- return it('should not do anything', function () {
- const dest = []
- text._tc(dest, { i: 'foo', p: 6 }, { c: 'bar', p: 3 })
- return dest.should.deep.equal([{ i: 'foo', p: 6 }])
- })
- })
- describe('comment / delete', function () {
- return it('should not do anything', function () {
- const dest = []
- text._tc(dest, { d: 'foo', p: 6 }, { c: 'bar', p: 3 })
- return dest.should.deep.equal([{ d: 'foo', p: 6 }])
- })
- })
- return describe('comment / comment', function () {
- return it('should not do anything', function () {
- const dest = []
- text._tc(dest, { c: 'foo', p: 6 }, { c: 'bar', p: 3 })
- return dest.should.deep.equal([{ c: 'foo', p: 6 }])
- })
- })
- })
- describe('apply', function () {
- it('should apply an insert', function () {
- return text.apply('foo', [{ i: 'bar', p: 2 }]).should.equal('fobaro')
- })
- it('should apply a delete', function () {
- return text
- .apply('foo123bar', [{ d: '123', p: 3 }])
- .should.equal('foobar')
- })
- it('should do nothing with a comment', function () {
- return text
- .apply('foo123bar', [{ c: '123', p: 3 }])
- .should.equal('foo123bar')
- })
- it('should throw an error when deleted content does not match', function () {
- return (() => text.apply('foo123bar', [{ d: '456', p: 3 }])).should.throw(
- Error
- )
- })
- return it('should throw an error when comment content does not match', function () {
- return (() => text.apply('foo123bar', [{ c: '456', p: 3 }])).should.throw(
- Error
- )
- })
- })
- return describe('applying ops and comments in different orders', function () {
- return it('should not matter which op or comment is applied first', function () {
- let length, p
- let asc, end
- let asc1, end1
- let asc3, end3
- const transform = function (op1, op2, side) {
- const d = []
- text._tc(d, op1, op2, side)
- return d
- }
- const applySnapshot = (snapshot, op) => text.apply(snapshot, op)
- const applyRanges = function (rangesTracker, ops) {
- for (const op of Array.from(ops)) {
- rangesTracker.applyOp(op, {})
- }
- return rangesTracker
- }
- const commentsEqual = function (comments1, comments2) {
- if (comments1.length !== comments2.length) {
- return false
- }
- comments1.sort((a, b) => {
- if (a.offset - b.offset === 0) {
- return a.length - b.length
- } else {
- return a.offset - b.offset
- }
- })
- comments2.sort((a, b) => {
- if (a.offset - b.offset === 0) {
- return a.length - b.length
- } else {
- return a.offset - b.offset
- }
- })
- for (let i = 0; i < comments1.length; i++) {
- const comment1 = comments1[i]
- const comment2 = comments2[i]
- if (
- comment1.offset !== comment2.offset ||
- comment1.length !== comment2.length
- ) {
- return false
- }
- }
- return true
- }
- const SNAPSHOT = '123'
- const OPS = []
- // Insert ops
- for (
- p = 0, end = SNAPSHOT.length, asc = end >= 0;
- asc ? p <= end : p >= end;
- asc ? p++ : p--
- ) {
- OPS.push({ i: 'a', p })
- OPS.push({ i: 'bc', p })
- }
- for (
- p = 0, end1 = SNAPSHOT.length - 1, asc1 = end1 >= 0;
- asc1 ? p <= end1 : p >= end1;
- asc1 ? p++ : p--
- ) {
- var asc2, end2
- for (
- length = 1, end2 = SNAPSHOT.length - p, asc2 = end2 >= 1;
- asc2 ? length <= end2 : length >= end2;
- asc2 ? length++ : length--
- ) {
- OPS.push({ d: SNAPSHOT.slice(p, p + length), p })
- }
- }
- for (
- p = 0, end3 = SNAPSHOT.length - 1, asc3 = end3 >= 0;
- asc3 ? p <= end3 : p >= end3;
- asc3 ? p++ : p--
- ) {
- var asc4, end4
- for (
- length = 1, end4 = SNAPSHOT.length - p, asc4 = end4 >= 1;
- asc4 ? length <= end4 : length >= end4;
- asc4 ? length++ : length--
- ) {
- OPS.push({ c: SNAPSHOT.slice(p, p + length), p, t: this.t })
- }
- }
- return (() => {
- const result = []
- for (var op1 of Array.from(OPS)) {
- result.push(
- (() => {
- const result1 = []
- for (const op2 of Array.from(OPS)) {
- const op1_t = transform(op1, op2, 'left')
- const op2_t = transform(op2, op1, 'right')
- const rt12 = new RangesTracker()
- const snapshot12 = applySnapshot(
- applySnapshot(SNAPSHOT, [op1]),
- op2_t
- )
- applyRanges(rt12, [op1])
- applyRanges(rt12, op2_t)
- const rt21 = new RangesTracker()
- const snapshot21 = applySnapshot(
- applySnapshot(SNAPSHOT, [op2]),
- op1_t
- )
- applyRanges(rt21, [op2])
- applyRanges(rt21, op1_t)
- if (snapshot12 !== snapshot21) {
- console.error(
- { op1, op2, op1_t, op2_t, snapshot12, snapshot21 },
- 'Ops are not consistent'
- )
- throw new Error('OT is inconsistent')
- }
- if (!commentsEqual(rt12.comments, rt21.comments)) {
- console.log(rt12.comments)
- console.log(rt21.comments)
- console.error(
- {
- op1,
- op2,
- op1_t,
- op2_t,
- rt12_comments: rt12.comments,
- rt21_comments: rt21.comments
- },
- 'Comments are not consistent'
- )
- throw new Error('OT is inconsistent')
- } else {
- result1.push(undefined)
- }
- }
- return result1
- })()
- )
- }
- return result
- })()
- })
- })
- })
|