overleaf/services/track-changes/test/unit/coffee/DiffGenerator/DiffGeneratorTests.coffee

269 lines
7.8 KiB
CoffeeScript
Raw Normal View History

2014-03-01 08:31:34 -05:00
sinon = require('sinon')
chai = require('chai')
should = chai.should()
expect = chai.expect
modulePath = "../../../../app/js/DiffGenerator.js"
SandboxedModule = require('sandboxed-module')
describe "DiffGenerator", ->
beforeEach ->
@DiffGenerator = SandboxedModule.require modulePath
@ts = Date.now()
@user_id = "mock-user-id"
@meta = {
start_ts: @ts, end_ts: @ts, user_id: @user_id
}
2014-03-11 11:24:38 -04:00
describe "rewindOp", ->
2014-03-01 08:31:34 -05:00
describe "rewinding an insert", ->
it "should undo the insert", ->
content = "hello world"
2014-03-11 11:24:38 -04:00
rewoundContent = @DiffGenerator.rewindOp content, { p: 6, i: "wo" }
2014-03-01 08:31:34 -05:00
rewoundContent.should.equal "hello rld"
describe "rewinding a delete", ->
it "should undo the delete", ->
content = "hello rld"
2014-03-11 11:24:38 -04:00
rewoundContent = @DiffGenerator.rewindOp content, { p: 6, d: "wo" }
2014-03-01 08:31:34 -05:00
rewoundContent.should.equal "hello world"
describe "with an inconsistent update", ->
it "should throw an error", ->
content = "hello world"
expect( () =>
2014-03-11 11:24:38 -04:00
@DiffGenerator.rewindOp content, { p: 6, i: "foo" }
2014-03-01 08:31:34 -05:00
).to.throw(@DiffGenerator.ConsistencyError)
2014-03-11 11:24:38 -04:00
describe "rewindUpdate", ->
it "should rewind ops in reverse", ->
content = "aaabbbccc"
update =
op: [{ p: 3, i: "bbb" }, { p: 6, i: "ccc" }]
rewoundContent = @DiffGenerator.rewindUpdate content, update
rewoundContent.should.equal "aaa"
2014-03-01 08:31:34 -05:00
describe "rewindUpdates", ->
it "should rewind updates in reverse", ->
content = "aaabbbccc"
updates = [
2014-03-11 11:24:38 -04:00
{ op: [{ p: 3, i: "bbb" }] },
{ op: [{ p: 6, i: "ccc" }] }
2014-03-01 08:31:34 -05:00
]
rewoundContent = @DiffGenerator.rewindUpdates content, updates
rewoundContent.should.equal "aaa"
2014-03-03 12:39:59 -05:00
describe "buildDiff", ->
beforeEach ->
@diff = [ u: "mock-diff" ]
@content = "Hello world"
@updates = [
{ i: "mock-update-1" }
{ i: "mock-update-2" }
{ i: "mock-update-3" }
]
@DiffGenerator.applyUpdateToDiff = sinon.stub().returns(@diff)
@result = @DiffGenerator.buildDiff(@content, @updates)
it "should return the diff", ->
@result.should.deep.equal @diff
it "should build the content into an initial diff", ->
@DiffGenerator.applyUpdateToDiff
.calledWith([{
u: @content
}], @updates[0])
.should.equal true
it "should apply each update", ->
for update in @updates
@DiffGenerator.applyUpdateToDiff
.calledWith(sinon.match.any, update)
.should.equal true
2014-03-01 08:31:34 -05:00
describe "applyUpdateToDiff", ->
describe "an insert", ->
it "should insert into the middle of (u)nchanged text", ->
diff = @DiffGenerator.applyUpdateToDiff(
[ { u: "foobar" } ],
2014-03-11 11:24:38 -04:00
{ op: [{ p: 3, i: "baz" }], meta: @meta }
2014-03-01 08:31:34 -05:00
)
expect(diff).to.deep.equal([
{ u: "foo" }
{ i: "baz", meta: @meta }
{ u: "bar" }
])
it "should insert into the start of (u)changed text", ->
diff = @DiffGenerator.applyUpdateToDiff(
[ { u: "foobar" } ],
2014-03-11 11:24:38 -04:00
{ op: [{ p: 0, i: "baz" }], meta: @meta }
2014-03-01 08:31:34 -05:00
)
expect(diff).to.deep.equal([
{ i: "baz", meta: @meta }
{ u: "foobar" }
])
it "should insert into the end of (u)changed text", ->
diff = @DiffGenerator.applyUpdateToDiff(
[ { u: "foobar" } ],
2014-03-11 11:24:38 -04:00
{ op: [{ p: 6, i: "baz" }], meta: @meta }
2014-03-01 08:31:34 -05:00
)
expect(diff).to.deep.equal([
{ u: "foobar" }
{ i: "baz", meta: @meta }
])
it "should insert into the middle of (i)inserted text", ->
diff = @DiffGenerator.applyUpdateToDiff(
[ { i: "foobar", meta: @meta } ],
2014-03-11 11:24:38 -04:00
{ op: [{ p: 3, i: "baz" }], meta: @meta }
2014-03-01 08:31:34 -05:00
)
expect(diff).to.deep.equal([
{ i: "foo", meta: @meta }
{ i: "baz", meta: @meta }
{ i: "bar", meta: @meta }
])
it "should not count deletes in the running length total", ->
diff = @DiffGenerator.applyUpdateToDiff(
[
{ d: "deleted", meta: @meta }
{ u: "foobar" }
],
2014-03-11 11:24:38 -04:00
{ op: [{ p: 3, i: "baz" }], meta: @meta }
2014-03-01 08:31:34 -05:00
)
expect(diff).to.deep.equal([
{ d: "deleted", meta: @meta }
{ u: "foo" }
{ i: "baz", meta: @meta }
{ u: "bar" }
])
describe "a delete", ->
describe "deleting unchanged text", ->
it "should delete from the middle of (u)nchanged text", ->
diff = @DiffGenerator.applyUpdateToDiff(
[ { u: "foobazbar" } ],
2014-03-11 11:24:38 -04:00
{ op: [{ p: 3, d: "baz" }], meta: @meta }
2014-03-01 08:31:34 -05:00
)
expect(diff).to.deep.equal([
{ u: "foo" }
{ d: "baz", meta: @meta }
{ u: "bar" }
])
it "should delete from the start of (u)nchanged text", ->
diff = @DiffGenerator.applyUpdateToDiff(
[ { u: "foobazbar" } ],
2014-03-11 11:24:38 -04:00
{ op: [{ p: 0, d: "foo" }], meta: @meta }
2014-03-01 08:31:34 -05:00
)
expect(diff).to.deep.equal([
{ d: "foo", meta: @meta }
{ u: "bazbar" }
])
it "should delete from the end of (u)nchanged text", ->
diff = @DiffGenerator.applyUpdateToDiff(
[ { u: "foobazbar" } ],
2014-03-11 11:24:38 -04:00
{ op: [{ p: 6, d: "bar" }], meta: @meta }
2014-03-01 08:31:34 -05:00
)
expect(diff).to.deep.equal([
{ u: "foobaz" }
{ d: "bar", meta: @meta }
])
it "should delete across multiple (u)changed text parts", ->
diff = @DiffGenerator.applyUpdateToDiff(
[ { u: "foo" }, { u: "baz" }, { u: "bar" } ],
2014-03-11 11:24:38 -04:00
{ op: [{ p: 2, d: "obazb" }], meta: @meta }
2014-03-01 08:31:34 -05:00
)
expect(diff).to.deep.equal([
{ u: "fo" }
{ d: "o", meta: @meta }
{ d: "baz", meta: @meta }
{ d: "b", meta: @meta }
{ u: "ar" }
])
describe "deleting inserts", ->
it "should delete from the middle of (i)nserted text", ->
diff = @DiffGenerator.applyUpdateToDiff(
[ { i: "foobazbar", meta: @meta } ],
2014-03-11 11:24:38 -04:00
{ op: [{ p: 3, d: "baz" }], meta: @meta }
2014-03-01 08:31:34 -05:00
)
expect(diff).to.deep.equal([
{ i: "foo", meta: @meta }
{ i: "bar", meta: @meta }
])
it "should delete from the start of (u)nchanged text", ->
diff = @DiffGenerator.applyUpdateToDiff(
[ { i: "foobazbar", meta: @meta } ],
2014-03-11 11:24:38 -04:00
{ op: [{ p: 0, d: "foo" }], meta: @meta }
2014-03-01 08:31:34 -05:00
)
expect(diff).to.deep.equal([
{ i: "bazbar", meta: @meta }
])
it "should delete from the end of (u)nchanged text", ->
diff = @DiffGenerator.applyUpdateToDiff(
[ { i: "foobazbar", meta: @meta } ],
2014-03-11 11:24:38 -04:00
{ op: [{ p: 6, d: "bar" }], meta: @meta }
2014-03-01 08:31:34 -05:00
)
expect(diff).to.deep.equal([
{ i: "foobaz", meta: @meta }
])
it "should delete across multiple (u)changed and (i)nserted text parts", ->
diff = @DiffGenerator.applyUpdateToDiff(
[ { u: "foo" }, { i: "baz", meta: @meta }, { u: "bar" } ],
2014-03-11 11:24:38 -04:00
{ op: [{ p: 2, d: "obazb" }], meta: @meta }
2014-03-01 08:31:34 -05:00
)
expect(diff).to.deep.equal([
{ u: "fo" }
{ d: "o", meta: @meta }
{ d: "b", meta: @meta }
{ u: "ar" }
])
describe "deleting over existing deletes", ->
it "should delete across multiple (u)changed and (d)deleted text parts", ->
diff = @DiffGenerator.applyUpdateToDiff(
[ { u: "foo" }, { d: "baz", meta: @meta }, { u: "bar" } ],
2014-03-11 11:24:38 -04:00
{ op: [{ p: 2, d: "ob" }], meta: @meta }
2014-03-01 08:31:34 -05:00
)
expect(diff).to.deep.equal([
{ u: "fo" }
{ d: "o", meta: @meta }
{ d: "baz", meta: @meta }
{ d: "b", meta: @meta }
{ u: "ar" }
])
describe "deleting when the text doesn't match", ->
it "should throw an error when deleting from the middle of (u)nchanged text", ->
expect(
() => @DiffGenerator.applyUpdateToDiff(
[ { u: "foobazbar" } ],
2014-03-11 11:24:38 -04:00
{ op: [{ p: 3, d: "xxx" }], meta: @meta }
2014-03-01 08:31:34 -05:00
)
).to.throw(@DiffGenerator.ConsistencyError)
it "should throw an error when deleting from the start of (u)nchanged text", ->
expect(
() => @DiffGenerator.applyUpdateToDiff(
[ { u: "foobazbar" } ],
2014-03-11 11:24:38 -04:00
{ op: [{ p: 0, d: "xxx" }], meta: @meta }
2014-03-01 08:31:34 -05:00
)
).to.throw(@DiffGenerator.ConsistencyError)
it "should throw an error when deleting from the end of (u)nchanged text", ->
expect(
() => @DiffGenerator.applyUpdateToDiff(
[ { u: "foobazbar" } ],
2014-03-11 11:24:38 -04:00
{ op: [{ p: 6, d: "xxx" }] , meta: @meta }
2014-03-01 08:31:34 -05:00
)
).to.throw(@DiffGenerator.ConsistencyError)