mirror of
https://github.com/overleaf/overleaf.git
synced 2025-04-14 10:54:25 +00:00
prettier: convert test/unit decaffeinated files to Prettier format
This commit is contained in:
parent
201bfbbf32
commit
7741730574
14 changed files with 5100 additions and 3792 deletions
|
@ -10,393 +10,453 @@
|
|||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
const sinon = require('sinon');
|
||||
const chai = require('chai');
|
||||
const should = chai.should();
|
||||
const { expect } = chai;
|
||||
const modulePath = "../../../../app/js/DiffGenerator.js";
|
||||
const SandboxedModule = require('sandboxed-module');
|
||||
const sinon = require('sinon')
|
||||
const chai = require('chai')
|
||||
const should = chai.should()
|
||||
const { expect } = chai
|
||||
const modulePath = '../../../../app/js/DiffGenerator.js'
|
||||
const SandboxedModule = require('sandboxed-module')
|
||||
|
||||
describe("DiffGenerator", function() {
|
||||
beforeEach(function() {
|
||||
this.DiffGenerator = SandboxedModule.require(modulePath, { requires: {
|
||||
"logger-sharelatex": { warn: sinon.stub() }
|
||||
}
|
||||
});
|
||||
this.ts = Date.now();
|
||||
this.user_id = "mock-user-id";
|
||||
this.user_id_2 = "mock-user-id-2";
|
||||
return this.meta = {
|
||||
start_ts: this.ts, end_ts: this.ts, user_id: this.user_id
|
||||
};});
|
||||
describe('DiffGenerator', function() {
|
||||
beforeEach(function() {
|
||||
this.DiffGenerator = SandboxedModule.require(modulePath, {
|
||||
requires: {
|
||||
'logger-sharelatex': { warn: sinon.stub() }
|
||||
}
|
||||
})
|
||||
this.ts = Date.now()
|
||||
this.user_id = 'mock-user-id'
|
||||
this.user_id_2 = 'mock-user-id-2'
|
||||
return (this.meta = {
|
||||
start_ts: this.ts,
|
||||
end_ts: this.ts,
|
||||
user_id: this.user_id
|
||||
})
|
||||
})
|
||||
|
||||
describe("rewindOp", function() {
|
||||
describe("rewinding an insert", function() { return it("should undo the insert", function() {
|
||||
const content = "hello world";
|
||||
const rewoundContent = this.DiffGenerator.rewindOp(content, { p: 6, i: "wo" });
|
||||
return rewoundContent.should.equal("hello rld");
|
||||
}); }
|
||||
);
|
||||
describe('rewindOp', function() {
|
||||
describe('rewinding an insert', function() {
|
||||
return it('should undo the insert', function() {
|
||||
const content = 'hello world'
|
||||
const rewoundContent = this.DiffGenerator.rewindOp(content, {
|
||||
p: 6,
|
||||
i: 'wo'
|
||||
})
|
||||
return rewoundContent.should.equal('hello rld')
|
||||
})
|
||||
})
|
||||
|
||||
describe("rewinding a delete", function() { return it("should undo the delete", function() {
|
||||
const content = "hello rld";
|
||||
const rewoundContent = this.DiffGenerator.rewindOp(content, { p: 6, d: "wo" });
|
||||
return rewoundContent.should.equal("hello world");
|
||||
}); }
|
||||
);
|
||||
describe('rewinding a delete', function() {
|
||||
return it('should undo the delete', function() {
|
||||
const content = 'hello rld'
|
||||
const rewoundContent = this.DiffGenerator.rewindOp(content, {
|
||||
p: 6,
|
||||
d: 'wo'
|
||||
})
|
||||
return rewoundContent.should.equal('hello world')
|
||||
})
|
||||
})
|
||||
|
||||
describe("with an inconsistent update", function() { return it("should throw an error", function() {
|
||||
const content = "hello world";
|
||||
return expect( () => {
|
||||
return this.DiffGenerator.rewindOp(content, { p: 6, i: "foo" });
|
||||
}).to.throw(this.DiffGenerator.ConsistencyError);
|
||||
}); }
|
||||
);
|
||||
|
||||
return describe("with an update which is beyond the length of the content", function() { return it("should undo the insert as if it were at the end of the content", function() {
|
||||
const content = "foobar";
|
||||
const rewoundContent = this.DiffGenerator.rewindOp(content, { p: 4, i: "bar" });
|
||||
return rewoundContent.should.equal("foo");
|
||||
}); }
|
||||
);
|
||||
});
|
||||
describe('with an inconsistent update', function() {
|
||||
return it('should throw an error', function() {
|
||||
const content = 'hello world'
|
||||
return expect(() => {
|
||||
return this.DiffGenerator.rewindOp(content, { p: 6, i: 'foo' })
|
||||
}).to.throw(this.DiffGenerator.ConsistencyError)
|
||||
})
|
||||
})
|
||||
|
||||
describe("rewindUpdate", function() { return it("should rewind ops in reverse", function() {
|
||||
const content = "aaabbbccc";
|
||||
const update =
|
||||
{op: [{ p: 3, i: "bbb" }, { p: 6, i: "ccc" }]};
|
||||
const rewoundContent = this.DiffGenerator.rewindUpdate(content, update);
|
||||
return rewoundContent.should.equal("aaa");
|
||||
}); }
|
||||
);
|
||||
return describe('with an update which is beyond the length of the content', function() {
|
||||
return it('should undo the insert as if it were at the end of the content', function() {
|
||||
const content = 'foobar'
|
||||
const rewoundContent = this.DiffGenerator.rewindOp(content, {
|
||||
p: 4,
|
||||
i: 'bar'
|
||||
})
|
||||
return rewoundContent.should.equal('foo')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("rewindUpdates", function() { return it("should rewind updates in reverse", function() {
|
||||
const content = "aaabbbccc";
|
||||
const updates = [
|
||||
{ op: [{ p: 3, i: "bbb" }] },
|
||||
{ op: [{ p: 6, i: "ccc" }] }
|
||||
];
|
||||
const rewoundContent = this.DiffGenerator.rewindUpdates(content, updates);
|
||||
return rewoundContent.should.equal("aaa");
|
||||
}); }
|
||||
);
|
||||
describe('rewindUpdate', function() {
|
||||
return it('should rewind ops in reverse', function() {
|
||||
const content = 'aaabbbccc'
|
||||
const update = {
|
||||
op: [
|
||||
{ p: 3, i: 'bbb' },
|
||||
{ p: 6, i: 'ccc' }
|
||||
]
|
||||
}
|
||||
const rewoundContent = this.DiffGenerator.rewindUpdate(content, update)
|
||||
return rewoundContent.should.equal('aaa')
|
||||
})
|
||||
})
|
||||
|
||||
describe("buildDiff", function() {
|
||||
beforeEach(function() {
|
||||
this.diff = [ {u: "mock-diff"} ];
|
||||
this.content = "Hello world";
|
||||
this.updates = [
|
||||
{ i: "mock-update-1" },
|
||||
{ i: "mock-update-2" },
|
||||
{ i: "mock-update-3" }
|
||||
];
|
||||
this.DiffGenerator.applyUpdateToDiff = sinon.stub().returns(this.diff);
|
||||
this.DiffGenerator.compressDiff = sinon.stub().returns(this.diff);
|
||||
return this.result = this.DiffGenerator.buildDiff(this.content, this.updates);
|
||||
});
|
||||
describe('rewindUpdates', function() {
|
||||
return it('should rewind updates in reverse', function() {
|
||||
const content = 'aaabbbccc'
|
||||
const updates = [
|
||||
{ op: [{ p: 3, i: 'bbb' }] },
|
||||
{ op: [{ p: 6, i: 'ccc' }] }
|
||||
]
|
||||
const rewoundContent = this.DiffGenerator.rewindUpdates(content, updates)
|
||||
return rewoundContent.should.equal('aaa')
|
||||
})
|
||||
})
|
||||
|
||||
it("should return the diff", function() {
|
||||
return this.result.should.deep.equal(this.diff);
|
||||
});
|
||||
describe('buildDiff', function() {
|
||||
beforeEach(function() {
|
||||
this.diff = [{ u: 'mock-diff' }]
|
||||
this.content = 'Hello world'
|
||||
this.updates = [
|
||||
{ i: 'mock-update-1' },
|
||||
{ i: 'mock-update-2' },
|
||||
{ i: 'mock-update-3' }
|
||||
]
|
||||
this.DiffGenerator.applyUpdateToDiff = sinon.stub().returns(this.diff)
|
||||
this.DiffGenerator.compressDiff = sinon.stub().returns(this.diff)
|
||||
return (this.result = this.DiffGenerator.buildDiff(
|
||||
this.content,
|
||||
this.updates
|
||||
))
|
||||
})
|
||||
|
||||
it("should build the content into an initial diff", function() {
|
||||
return this.DiffGenerator.applyUpdateToDiff
|
||||
.calledWith([{
|
||||
u: this.content
|
||||
}], this.updates[0])
|
||||
.should.equal(true);
|
||||
});
|
||||
it('should return the diff', function() {
|
||||
return this.result.should.deep.equal(this.diff)
|
||||
})
|
||||
|
||||
it("should apply each update", function() {
|
||||
return Array.from(this.updates).map((update) =>
|
||||
this.DiffGenerator.applyUpdateToDiff
|
||||
.calledWith(sinon.match.any, update)
|
||||
.should.equal(true));
|
||||
});
|
||||
it('should build the content into an initial diff', function() {
|
||||
return this.DiffGenerator.applyUpdateToDiff
|
||||
.calledWith(
|
||||
[
|
||||
{
|
||||
u: this.content
|
||||
}
|
||||
],
|
||||
this.updates[0]
|
||||
)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
return it("should compress the diff", function() {
|
||||
return this.DiffGenerator.compressDiff
|
||||
.calledWith(this.diff)
|
||||
.should.equal(true);
|
||||
});
|
||||
});
|
||||
it('should apply each update', function() {
|
||||
return Array.from(this.updates).map(update =>
|
||||
this.DiffGenerator.applyUpdateToDiff
|
||||
.calledWith(sinon.match.any, update)
|
||||
.should.equal(true)
|
||||
)
|
||||
})
|
||||
|
||||
describe("compressDiff", function() {
|
||||
describe("with adjacent inserts with the same user_id", function() { return it("should create one update with combined meta data and min/max timestamps", function() {
|
||||
const diff = this.DiffGenerator.compressDiff([
|
||||
{ i: "foo", meta: { start_ts: 10, end_ts: 20, user: { id: this.user_id } }},
|
||||
{ i: "bar", meta: { start_ts: 5, end_ts: 15, user: { id: this.user_id } }}
|
||||
]);
|
||||
return expect(diff).to.deep.equal([
|
||||
{ i: "foobar", meta: { start_ts: 5, end_ts: 20, user: { id: this.user_id } }}
|
||||
]);
|
||||
}); }
|
||||
);
|
||||
return it('should compress the diff', function() {
|
||||
return this.DiffGenerator.compressDiff
|
||||
.calledWith(this.diff)
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe("with adjacent inserts with different user_ids", function() { return it("should leave the inserts unchanged", function() {
|
||||
const input = [
|
||||
{ i: "foo", meta: { start_ts: 10, end_ts: 20, user: { id: this.user_id } }},
|
||||
{ i: "bar", meta: { start_ts: 5, end_ts: 15, user: { id: this.user_id_2 } }}
|
||||
];
|
||||
const output = this.DiffGenerator.compressDiff(input);
|
||||
return expect(output).to.deep.equal(input);
|
||||
}); }
|
||||
);
|
||||
describe('compressDiff', function() {
|
||||
describe('with adjacent inserts with the same user_id', function() {
|
||||
return it('should create one update with combined meta data and min/max timestamps', function() {
|
||||
const diff = this.DiffGenerator.compressDiff([
|
||||
{
|
||||
i: 'foo',
|
||||
meta: { start_ts: 10, end_ts: 20, user: { id: this.user_id } }
|
||||
},
|
||||
{
|
||||
i: 'bar',
|
||||
meta: { start_ts: 5, end_ts: 15, user: { id: this.user_id } }
|
||||
}
|
||||
])
|
||||
return expect(diff).to.deep.equal([
|
||||
{
|
||||
i: 'foobar',
|
||||
meta: { start_ts: 5, end_ts: 20, user: { id: this.user_id } }
|
||||
}
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe("with adjacent deletes with the same user_id", function() { return it("should create one update with combined meta data and min/max timestamps", function() {
|
||||
const diff = this.DiffGenerator.compressDiff([
|
||||
{ d: "foo", meta: { start_ts: 10, end_ts: 20, user: { id: this.user_id } }},
|
||||
{ d: "bar", meta: { start_ts: 5, end_ts: 15, user: { id: this.user_id } }}
|
||||
]);
|
||||
return expect(diff).to.deep.equal([
|
||||
{ d: "foobar", meta: { start_ts: 5, end_ts: 20, user: { id: this.user_id } }}
|
||||
]);
|
||||
}); }
|
||||
);
|
||||
describe('with adjacent inserts with different user_ids', function() {
|
||||
return it('should leave the inserts unchanged', function() {
|
||||
const input = [
|
||||
{
|
||||
i: 'foo',
|
||||
meta: { start_ts: 10, end_ts: 20, user: { id: this.user_id } }
|
||||
},
|
||||
{
|
||||
i: 'bar',
|
||||
meta: { start_ts: 5, end_ts: 15, user: { id: this.user_id_2 } }
|
||||
}
|
||||
]
|
||||
const output = this.DiffGenerator.compressDiff(input)
|
||||
return expect(output).to.deep.equal(input)
|
||||
})
|
||||
})
|
||||
|
||||
return describe("with adjacent deletes with different user_ids", function() { return it("should leave the deletes unchanged", function() {
|
||||
const input = [
|
||||
{ d: "foo", meta: { start_ts: 10, end_ts: 20, user: { id: this.user_id } }},
|
||||
{ d: "bar", meta: { start_ts: 5, end_ts: 15, user: { id: this.user_id_2 } }}
|
||||
];
|
||||
const output = this.DiffGenerator.compressDiff(input);
|
||||
return expect(output).to.deep.equal(input);
|
||||
}); }
|
||||
);
|
||||
});
|
||||
describe('with adjacent deletes with the same user_id', function() {
|
||||
return it('should create one update with combined meta data and min/max timestamps', function() {
|
||||
const diff = this.DiffGenerator.compressDiff([
|
||||
{
|
||||
d: 'foo',
|
||||
meta: { start_ts: 10, end_ts: 20, user: { id: this.user_id } }
|
||||
},
|
||||
{
|
||||
d: 'bar',
|
||||
meta: { start_ts: 5, end_ts: 15, user: { id: this.user_id } }
|
||||
}
|
||||
])
|
||||
return expect(diff).to.deep.equal([
|
||||
{
|
||||
d: 'foobar',
|
||||
meta: { start_ts: 5, end_ts: 20, user: { id: this.user_id } }
|
||||
}
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
return describe("applyUpdateToDiff", function() {
|
||||
describe("an insert", function() {
|
||||
it("should insert into the middle of (u)nchanged text", function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff(
|
||||
[ { u: "foobar" } ],
|
||||
{ op: [{ p: 3, i: "baz" }], meta: this.meta }
|
||||
);
|
||||
return expect(diff).to.deep.equal([
|
||||
{ u: "foo" },
|
||||
{ i: "baz", meta: this.meta },
|
||||
{ u: "bar" }
|
||||
]);
|
||||
});
|
||||
return describe('with adjacent deletes with different user_ids', function() {
|
||||
return it('should leave the deletes unchanged', function() {
|
||||
const input = [
|
||||
{
|
||||
d: 'foo',
|
||||
meta: { start_ts: 10, end_ts: 20, user: { id: this.user_id } }
|
||||
},
|
||||
{
|
||||
d: 'bar',
|
||||
meta: { start_ts: 5, end_ts: 15, user: { id: this.user_id_2 } }
|
||||
}
|
||||
]
|
||||
const output = this.DiffGenerator.compressDiff(input)
|
||||
return expect(output).to.deep.equal(input)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it("should insert into the start of (u)changed text", function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff(
|
||||
[ { u: "foobar" } ],
|
||||
{ op: [{ p: 0, i: "baz" }], meta: this.meta }
|
||||
);
|
||||
return expect(diff).to.deep.equal([
|
||||
{ i: "baz", meta: this.meta },
|
||||
{ u: "foobar" }
|
||||
]);
|
||||
});
|
||||
return describe('applyUpdateToDiff', function() {
|
||||
describe('an insert', function() {
|
||||
it('should insert into the middle of (u)nchanged text', function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff([{ u: 'foobar' }], {
|
||||
op: [{ p: 3, i: 'baz' }],
|
||||
meta: this.meta
|
||||
})
|
||||
return expect(diff).to.deep.equal([
|
||||
{ u: 'foo' },
|
||||
{ i: 'baz', meta: this.meta },
|
||||
{ u: 'bar' }
|
||||
])
|
||||
})
|
||||
|
||||
it("should insert into the end of (u)changed text", function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff(
|
||||
[ { u: "foobar" } ],
|
||||
{ op: [{ p: 6, i: "baz" }], meta: this.meta }
|
||||
);
|
||||
return expect(diff).to.deep.equal([
|
||||
{ u: "foobar" },
|
||||
{ i: "baz", meta: this.meta }
|
||||
]);
|
||||
});
|
||||
it('should insert into the start of (u)changed text', function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff([{ u: 'foobar' }], {
|
||||
op: [{ p: 0, i: 'baz' }],
|
||||
meta: this.meta
|
||||
})
|
||||
return expect(diff).to.deep.equal([
|
||||
{ i: 'baz', meta: this.meta },
|
||||
{ u: 'foobar' }
|
||||
])
|
||||
})
|
||||
|
||||
it("should insert into the middle of (i)inserted text", function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff(
|
||||
[ { i: "foobar", meta: this.meta } ],
|
||||
{ op: [{ p: 3, i: "baz" }], meta: this.meta }
|
||||
);
|
||||
return expect(diff).to.deep.equal([
|
||||
{ i: "foo", meta: this.meta },
|
||||
{ i: "baz", meta: this.meta },
|
||||
{ i: "bar", meta: this.meta }
|
||||
]);
|
||||
});
|
||||
it('should insert into the end of (u)changed text', function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff([{ u: 'foobar' }], {
|
||||
op: [{ p: 6, i: 'baz' }],
|
||||
meta: this.meta
|
||||
})
|
||||
return expect(diff).to.deep.equal([
|
||||
{ u: 'foobar' },
|
||||
{ i: 'baz', meta: this.meta }
|
||||
])
|
||||
})
|
||||
|
||||
return it("should not count deletes in the running length total", function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff(
|
||||
[
|
||||
{ d: "deleted", meta: this.meta },
|
||||
{ u: "foobar" }
|
||||
],
|
||||
{ op: [{ p: 3, i: "baz" }], meta: this.meta }
|
||||
);
|
||||
return expect(diff).to.deep.equal([
|
||||
{ d: "deleted", meta: this.meta },
|
||||
{ u: "foo" },
|
||||
{ i: "baz", meta: this.meta },
|
||||
{ u: "bar" }
|
||||
]);
|
||||
});
|
||||
});
|
||||
it('should insert into the middle of (i)inserted text', function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff(
|
||||
[{ i: 'foobar', meta: this.meta }],
|
||||
{ op: [{ p: 3, i: 'baz' }], meta: this.meta }
|
||||
)
|
||||
return expect(diff).to.deep.equal([
|
||||
{ i: 'foo', meta: this.meta },
|
||||
{ i: 'baz', meta: this.meta },
|
||||
{ i: 'bar', meta: this.meta }
|
||||
])
|
||||
})
|
||||
|
||||
return describe("a delete", function() {
|
||||
describe("deleting unchanged text", function() {
|
||||
it("should delete from the middle of (u)nchanged text", function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff(
|
||||
[ { u: "foobazbar" } ],
|
||||
{ op: [{ p: 3, d: "baz" }], meta: this.meta }
|
||||
);
|
||||
return expect(diff).to.deep.equal([
|
||||
{ u: "foo" },
|
||||
{ d: "baz", meta: this.meta },
|
||||
{ u: "bar" }
|
||||
]);
|
||||
});
|
||||
return it('should not count deletes in the running length total', function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff(
|
||||
[{ d: 'deleted', meta: this.meta }, { u: 'foobar' }],
|
||||
{ op: [{ p: 3, i: 'baz' }], meta: this.meta }
|
||||
)
|
||||
return expect(diff).to.deep.equal([
|
||||
{ d: 'deleted', meta: this.meta },
|
||||
{ u: 'foo' },
|
||||
{ i: 'baz', meta: this.meta },
|
||||
{ u: 'bar' }
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
it("should delete from the start of (u)nchanged text", function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff(
|
||||
[ { u: "foobazbar" } ],
|
||||
{ op: [{ p: 0, d: "foo" }], meta: this.meta }
|
||||
);
|
||||
return expect(diff).to.deep.equal([
|
||||
{ d: "foo", meta: this.meta },
|
||||
{ u: "bazbar" }
|
||||
]);
|
||||
});
|
||||
return describe('a delete', function() {
|
||||
describe('deleting unchanged text', function() {
|
||||
it('should delete from the middle of (u)nchanged text', function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff(
|
||||
[{ u: 'foobazbar' }],
|
||||
{ op: [{ p: 3, d: 'baz' }], meta: this.meta }
|
||||
)
|
||||
return expect(diff).to.deep.equal([
|
||||
{ u: 'foo' },
|
||||
{ d: 'baz', meta: this.meta },
|
||||
{ u: 'bar' }
|
||||
])
|
||||
})
|
||||
|
||||
it("should delete from the end of (u)nchanged text", function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff(
|
||||
[ { u: "foobazbar" } ],
|
||||
{ op: [{ p: 6, d: "bar" }], meta: this.meta }
|
||||
);
|
||||
return expect(diff).to.deep.equal([
|
||||
{ u: "foobaz" },
|
||||
{ d: "bar", meta: this.meta }
|
||||
]);
|
||||
});
|
||||
it('should delete from the start of (u)nchanged text', function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff(
|
||||
[{ u: 'foobazbar' }],
|
||||
{ op: [{ p: 0, d: 'foo' }], meta: this.meta }
|
||||
)
|
||||
return expect(diff).to.deep.equal([
|
||||
{ d: 'foo', meta: this.meta },
|
||||
{ u: 'bazbar' }
|
||||
])
|
||||
})
|
||||
|
||||
return it("should delete across multiple (u)changed text parts", function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff(
|
||||
[ { u: "foo" }, { u: "baz" }, { u: "bar" } ],
|
||||
{ op: [{ p: 2, d: "obazb" }], meta: this.meta }
|
||||
);
|
||||
return expect(diff).to.deep.equal([
|
||||
{ u: "fo" },
|
||||
{ d: "o", meta: this.meta },
|
||||
{ d: "baz", meta: this.meta },
|
||||
{ d: "b", meta: this.meta },
|
||||
{ u: "ar" }
|
||||
]);
|
||||
});
|
||||
});
|
||||
it('should delete from the end of (u)nchanged text', function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff(
|
||||
[{ u: 'foobazbar' }],
|
||||
{ op: [{ p: 6, d: 'bar' }], meta: this.meta }
|
||||
)
|
||||
return expect(diff).to.deep.equal([
|
||||
{ u: 'foobaz' },
|
||||
{ d: 'bar', meta: this.meta }
|
||||
])
|
||||
})
|
||||
|
||||
describe("deleting inserts", function() {
|
||||
it("should delete from the middle of (i)nserted text", function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff(
|
||||
[ { i: "foobazbar", meta: this.meta } ],
|
||||
{ op: [{ p: 3, d: "baz" }], meta: this.meta }
|
||||
);
|
||||
return expect(diff).to.deep.equal([
|
||||
{ i: "foo", meta: this.meta },
|
||||
{ i: "bar", meta: this.meta }
|
||||
]);
|
||||
});
|
||||
return it('should delete across multiple (u)changed text parts', function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff(
|
||||
[{ u: 'foo' }, { u: 'baz' }, { u: 'bar' }],
|
||||
{ op: [{ p: 2, d: 'obazb' }], meta: this.meta }
|
||||
)
|
||||
return expect(diff).to.deep.equal([
|
||||
{ u: 'fo' },
|
||||
{ d: 'o', meta: this.meta },
|
||||
{ d: 'baz', meta: this.meta },
|
||||
{ d: 'b', meta: this.meta },
|
||||
{ u: 'ar' }
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
it("should delete from the start of (u)nchanged text", function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff(
|
||||
[ { i: "foobazbar", meta: this.meta } ],
|
||||
{ op: [{ p: 0, d: "foo" }], meta: this.meta }
|
||||
);
|
||||
return expect(diff).to.deep.equal([
|
||||
{ i: "bazbar", meta: this.meta }
|
||||
]);
|
||||
});
|
||||
describe('deleting inserts', function() {
|
||||
it('should delete from the middle of (i)nserted text', function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff(
|
||||
[{ i: 'foobazbar', meta: this.meta }],
|
||||
{ op: [{ p: 3, d: 'baz' }], meta: this.meta }
|
||||
)
|
||||
return expect(diff).to.deep.equal([
|
||||
{ i: 'foo', meta: this.meta },
|
||||
{ i: 'bar', meta: this.meta }
|
||||
])
|
||||
})
|
||||
|
||||
it("should delete from the end of (u)nchanged text", function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff(
|
||||
[ { i: "foobazbar", meta: this.meta } ],
|
||||
{ op: [{ p: 6, d: "bar" }], meta: this.meta }
|
||||
);
|
||||
return expect(diff).to.deep.equal([
|
||||
{ i: "foobaz", meta: this.meta }
|
||||
]);
|
||||
});
|
||||
it('should delete from the start of (u)nchanged text', function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff(
|
||||
[{ i: 'foobazbar', meta: this.meta }],
|
||||
{ op: [{ p: 0, d: 'foo' }], meta: this.meta }
|
||||
)
|
||||
return expect(diff).to.deep.equal([{ i: 'bazbar', meta: this.meta }])
|
||||
})
|
||||
|
||||
return it("should delete across multiple (u)changed and (i)nserted text parts", function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff(
|
||||
[ { u: "foo" }, { i: "baz", meta: this.meta }, { u: "bar" } ],
|
||||
{ op: [{ p: 2, d: "obazb" }], meta: this.meta }
|
||||
);
|
||||
return expect(diff).to.deep.equal([
|
||||
{ u: "fo" },
|
||||
{ d: "o", meta: this.meta },
|
||||
{ d: "b", meta: this.meta },
|
||||
{ u: "ar" }
|
||||
]);
|
||||
});
|
||||
});
|
||||
it('should delete from the end of (u)nchanged text', function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff(
|
||||
[{ i: 'foobazbar', meta: this.meta }],
|
||||
{ op: [{ p: 6, d: 'bar' }], meta: this.meta }
|
||||
)
|
||||
return expect(diff).to.deep.equal([{ i: 'foobaz', meta: this.meta }])
|
||||
})
|
||||
|
||||
describe("deleting over existing deletes", function() { return it("should delete across multiple (u)changed and (d)deleted text parts", function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff(
|
||||
[ { u: "foo" }, { d: "baz", meta: this.meta }, { u: "bar" } ],
|
||||
{ op: [{ p: 2, d: "ob" }], meta: this.meta }
|
||||
);
|
||||
return expect(diff).to.deep.equal([
|
||||
{ u: "fo" },
|
||||
{ d: "o", meta: this.meta },
|
||||
{ d: "baz", meta: this.meta },
|
||||
{ d: "b", meta: this.meta },
|
||||
{ u: "ar" }
|
||||
]);
|
||||
}); }
|
||||
);
|
||||
return it('should delete across multiple (u)changed and (i)nserted text parts', function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff(
|
||||
[{ u: 'foo' }, { i: 'baz', meta: this.meta }, { u: 'bar' }],
|
||||
{ op: [{ p: 2, d: 'obazb' }], meta: this.meta }
|
||||
)
|
||||
return expect(diff).to.deep.equal([
|
||||
{ u: 'fo' },
|
||||
{ d: 'o', meta: this.meta },
|
||||
{ d: 'b', meta: this.meta },
|
||||
{ u: 'ar' }
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe("deleting when the text doesn't match", function() {
|
||||
it("should throw an error when deleting from the middle of (u)nchanged text", function() {
|
||||
return expect(
|
||||
() => this.DiffGenerator.applyUpdateToDiff(
|
||||
[ { u: "foobazbar" } ],
|
||||
{ op: [{ p: 3, d: "xxx" }], meta: this.meta }
|
||||
)
|
||||
).to.throw(this.DiffGenerator.ConsistencyError);
|
||||
});
|
||||
describe('deleting over existing deletes', function() {
|
||||
return it('should delete across multiple (u)changed and (d)deleted text parts', function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff(
|
||||
[{ u: 'foo' }, { d: 'baz', meta: this.meta }, { u: 'bar' }],
|
||||
{ op: [{ p: 2, d: 'ob' }], meta: this.meta }
|
||||
)
|
||||
return expect(diff).to.deep.equal([
|
||||
{ u: 'fo' },
|
||||
{ d: 'o', meta: this.meta },
|
||||
{ d: 'baz', meta: this.meta },
|
||||
{ d: 'b', meta: this.meta },
|
||||
{ u: 'ar' }
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
it("should throw an error when deleting from the start of (u)nchanged text", function() {
|
||||
return expect(
|
||||
() => this.DiffGenerator.applyUpdateToDiff(
|
||||
[ { u: "foobazbar" } ],
|
||||
{ op: [{ p: 0, d: "xxx" }], meta: this.meta }
|
||||
)
|
||||
).to.throw(this.DiffGenerator.ConsistencyError);
|
||||
});
|
||||
describe("deleting when the text doesn't match", function() {
|
||||
it('should throw an error when deleting from the middle of (u)nchanged text', function() {
|
||||
return expect(() =>
|
||||
this.DiffGenerator.applyUpdateToDiff([{ u: 'foobazbar' }], {
|
||||
op: [{ p: 3, d: 'xxx' }],
|
||||
meta: this.meta
|
||||
})
|
||||
).to.throw(this.DiffGenerator.ConsistencyError)
|
||||
})
|
||||
|
||||
return it("should throw an error when deleting from the end of (u)nchanged text", function() {
|
||||
return expect(
|
||||
() => this.DiffGenerator.applyUpdateToDiff(
|
||||
[ { u: "foobazbar" } ],
|
||||
{ op: [{ p: 6, d: "xxx" }] , meta: this.meta }
|
||||
)
|
||||
).to.throw(this.DiffGenerator.ConsistencyError);
|
||||
});
|
||||
});
|
||||
it('should throw an error when deleting from the start of (u)nchanged text', function() {
|
||||
return expect(() =>
|
||||
this.DiffGenerator.applyUpdateToDiff([{ u: 'foobazbar' }], {
|
||||
op: [{ p: 0, d: 'xxx' }],
|
||||
meta: this.meta
|
||||
})
|
||||
).to.throw(this.DiffGenerator.ConsistencyError)
|
||||
})
|
||||
|
||||
describe("when the last update in the existing diff is a delete", function() { return it("should insert the new update before the delete", function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff(
|
||||
[ { u: "foo" }, { d: "bar", meta: this.meta } ],
|
||||
{ op: [{ p: 3, i: "baz" }], meta: this.meta }
|
||||
);
|
||||
return expect(diff).to.deep.equal([
|
||||
{ u: "foo" },
|
||||
{ i: "baz", meta: this.meta },
|
||||
{ d: "bar", meta: this.meta }
|
||||
]);
|
||||
}); }
|
||||
);
|
||||
|
||||
return describe("when the only update in the existing diff is a delete", function() { return it("should insert the new update after the delete", function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff(
|
||||
[ { d: "bar", meta: this.meta } ],
|
||||
{ op: [{ p: 0, i: "baz" }], meta: this.meta }
|
||||
);
|
||||
return expect(diff).to.deep.equal([
|
||||
{ d: "bar", meta: this.meta },
|
||||
{ i: "baz", meta: this.meta }
|
||||
]);
|
||||
}); }
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
return it('should throw an error when deleting from the end of (u)nchanged text', function() {
|
||||
return expect(() =>
|
||||
this.DiffGenerator.applyUpdateToDiff([{ u: 'foobazbar' }], {
|
||||
op: [{ p: 6, d: 'xxx' }],
|
||||
meta: this.meta
|
||||
})
|
||||
).to.throw(this.DiffGenerator.ConsistencyError)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when the last update in the existing diff is a delete', function() {
|
||||
return it('should insert the new update before the delete', function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff(
|
||||
[{ u: 'foo' }, { d: 'bar', meta: this.meta }],
|
||||
{ op: [{ p: 3, i: 'baz' }], meta: this.meta }
|
||||
)
|
||||
return expect(diff).to.deep.equal([
|
||||
{ u: 'foo' },
|
||||
{ i: 'baz', meta: this.meta },
|
||||
{ d: 'bar', meta: this.meta }
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
return describe('when the only update in the existing diff is a delete', function() {
|
||||
return it('should insert the new update after the delete', function() {
|
||||
const diff = this.DiffGenerator.applyUpdateToDiff(
|
||||
[{ d: 'bar', meta: this.meta }],
|
||||
{ op: [{ p: 0, i: 'baz' }], meta: this.meta }
|
||||
)
|
||||
return expect(diff).to.deep.equal([
|
||||
{ d: 'bar', meta: this.meta },
|
||||
{ i: 'baz', meta: this.meta }
|
||||
])
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -10,301 +10,439 @@
|
|||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
const sinon = require('sinon');
|
||||
const chai = require('chai');
|
||||
const should = chai.should();
|
||||
const { expect } = chai;
|
||||
const modulePath = "../../../../app/js/DiffManager.js";
|
||||
const SandboxedModule = require('sandboxed-module');
|
||||
const sinon = require('sinon')
|
||||
const chai = require('chai')
|
||||
const should = chai.should()
|
||||
const { expect } = chai
|
||||
const modulePath = '../../../../app/js/DiffManager.js'
|
||||
const SandboxedModule = require('sandboxed-module')
|
||||
|
||||
describe("DiffManager", function() {
|
||||
beforeEach(function() {
|
||||
this.DiffManager = SandboxedModule.require(modulePath, { requires: {
|
||||
"logger-sharelatex": (this.logger = { log: sinon.stub(), error: sinon.stub(), warn: sinon.stub() }),
|
||||
"./UpdatesManager": (this.UpdatesManager = {}),
|
||||
"./DocumentUpdaterManager": (this.DocumentUpdaterManager = {}),
|
||||
"./DiffGenerator": (this.DiffGenerator = {})
|
||||
}
|
||||
});
|
||||
this.callback = sinon.stub();
|
||||
this.from = new Date();
|
||||
this.to = new Date(Date.now() + 10000);
|
||||
this.project_id = "mock-project-id";
|
||||
return this.doc_id = "mock-doc-id";
|
||||
});
|
||||
describe('DiffManager', function() {
|
||||
beforeEach(function() {
|
||||
this.DiffManager = SandboxedModule.require(modulePath, {
|
||||
requires: {
|
||||
'logger-sharelatex': (this.logger = {
|
||||
log: sinon.stub(),
|
||||
error: sinon.stub(),
|
||||
warn: sinon.stub()
|
||||
}),
|
||||
'./UpdatesManager': (this.UpdatesManager = {}),
|
||||
'./DocumentUpdaterManager': (this.DocumentUpdaterManager = {}),
|
||||
'./DiffGenerator': (this.DiffGenerator = {})
|
||||
}
|
||||
})
|
||||
this.callback = sinon.stub()
|
||||
this.from = new Date()
|
||||
this.to = new Date(Date.now() + 10000)
|
||||
this.project_id = 'mock-project-id'
|
||||
return (this.doc_id = 'mock-doc-id')
|
||||
})
|
||||
|
||||
describe("getLatestDocAndUpdates", function() {
|
||||
beforeEach(function() {
|
||||
this.content = "hello world";
|
||||
this.version = 42;
|
||||
this.updates = [ "mock-update-1", "mock-update-2" ];
|
||||
describe('getLatestDocAndUpdates', function() {
|
||||
beforeEach(function() {
|
||||
this.content = 'hello world'
|
||||
this.version = 42
|
||||
this.updates = ['mock-update-1', 'mock-update-2']
|
||||
|
||||
this.DocumentUpdaterManager.getDocument = sinon.stub().callsArgWith(2, null, this.content, this.version);
|
||||
return this.UpdatesManager.getDocUpdatesWithUserInfo = sinon.stub().callsArgWith(3, null, this.updates);
|
||||
});
|
||||
this.DocumentUpdaterManager.getDocument = sinon
|
||||
.stub()
|
||||
.callsArgWith(2, null, this.content, this.version)
|
||||
return (this.UpdatesManager.getDocUpdatesWithUserInfo = sinon
|
||||
.stub()
|
||||
.callsArgWith(3, null, this.updates))
|
||||
})
|
||||
|
||||
describe("with a fromVersion", function() {
|
||||
beforeEach(function() {
|
||||
return this.DiffManager.getLatestDocAndUpdates(this.project_id, this.doc_id, this.from, this.callback);
|
||||
});
|
||||
describe('with a fromVersion', function() {
|
||||
beforeEach(function() {
|
||||
return this.DiffManager.getLatestDocAndUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.from,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
it("should get the latest version of the doc", function() {
|
||||
return this.DocumentUpdaterManager.getDocument
|
||||
.calledWith(this.project_id, this.doc_id)
|
||||
.should.equal(true);
|
||||
});
|
||||
it('should get the latest version of the doc', function() {
|
||||
return this.DocumentUpdaterManager.getDocument
|
||||
.calledWith(this.project_id, this.doc_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it("should get the latest updates", function() {
|
||||
return this.UpdatesManager.getDocUpdatesWithUserInfo
|
||||
.calledWith(this.project_id, this.doc_id, {from: this.from})
|
||||
.should.equal(true);
|
||||
});
|
||||
it('should get the latest updates', function() {
|
||||
return this.UpdatesManager.getDocUpdatesWithUserInfo
|
||||
.calledWith(this.project_id, this.doc_id, { from: this.from })
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
return it("should call the callback with the content, version and updates", function() {
|
||||
return this.callback.calledWith(null, this.content, this.version, this.updates).should.equal(true);
|
||||
});
|
||||
});
|
||||
return it('should call the callback with the content, version and updates', function() {
|
||||
return this.callback
|
||||
.calledWith(null, this.content, this.version, this.updates)
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
return describe("with no fromVersion", function() {
|
||||
beforeEach(function() {
|
||||
return this.DiffManager.getLatestDocAndUpdates(this.project_id, this.doc_id, null, this.callback);
|
||||
});
|
||||
return describe('with no fromVersion', function() {
|
||||
beforeEach(function() {
|
||||
return this.DiffManager.getLatestDocAndUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
null,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
it("should get the latest version of the doc", function() {
|
||||
return this.DocumentUpdaterManager.getDocument
|
||||
.calledWith(this.project_id, this.doc_id)
|
||||
.should.equal(true);
|
||||
});
|
||||
it('should get the latest version of the doc', function() {
|
||||
return this.DocumentUpdaterManager.getDocument
|
||||
.calledWith(this.project_id, this.doc_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it("should not get the latest updates", function() {
|
||||
return this.UpdatesManager.getDocUpdatesWithUserInfo
|
||||
.called.should.equal(false);
|
||||
});
|
||||
it('should not get the latest updates', function() {
|
||||
return this.UpdatesManager.getDocUpdatesWithUserInfo.called.should.equal(
|
||||
false
|
||||
)
|
||||
})
|
||||
|
||||
return it("should call the callback with the content, version and blank updates", function() {
|
||||
return this.callback.calledWith(null, this.content, this.version, []).should.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return it('should call the callback with the content, version and blank updates', function() {
|
||||
return this.callback
|
||||
.calledWith(null, this.content, this.version, [])
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("getDiff", function() {
|
||||
beforeEach(function() {
|
||||
this.content = "hello world";
|
||||
// Op versions are the version they were applied to, so doc is always one version
|
||||
// ahead.s
|
||||
this.version = 43;
|
||||
this.updates = [
|
||||
{ op: "mock-4", v: 42, meta: { start_ts: new Date(this.to.getTime() + 20)} },
|
||||
{ op: "mock-3", v: 41, meta: { start_ts: new Date(this.to.getTime() + 10)} },
|
||||
{ op: "mock-2", v: 40, meta: { start_ts: new Date(this.to.getTime() - 10)} },
|
||||
{ op: "mock-1", v: 39, meta: { start_ts: new Date(this.to.getTime() - 20)} }
|
||||
];
|
||||
this.fromVersion = 39;
|
||||
this.toVersion = 40;
|
||||
this.diffed_updates = this.updates.slice(2);
|
||||
this.rewound_content = "rewound-content";
|
||||
return this.diff = [ {u: "mock-diff"} ];});
|
||||
|
||||
describe("with matching versions", function() {
|
||||
beforeEach(function() {
|
||||
this.DiffManager.getDocumentBeforeVersion = sinon.stub().callsArgWith(3, null, this.rewound_content, this.updates);
|
||||
this.DiffGenerator.buildDiff = sinon.stub().returns(this.diff);
|
||||
return this.DiffManager.getDiff(this.project_id, this.doc_id, this.fromVersion, this.toVersion, this.callback);
|
||||
});
|
||||
describe('getDiff', function() {
|
||||
beforeEach(function() {
|
||||
this.content = 'hello world'
|
||||
// Op versions are the version they were applied to, so doc is always one version
|
||||
// ahead.s
|
||||
this.version = 43
|
||||
this.updates = [
|
||||
{
|
||||
op: 'mock-4',
|
||||
v: 42,
|
||||
meta: { start_ts: new Date(this.to.getTime() + 20) }
|
||||
},
|
||||
{
|
||||
op: 'mock-3',
|
||||
v: 41,
|
||||
meta: { start_ts: new Date(this.to.getTime() + 10) }
|
||||
},
|
||||
{
|
||||
op: 'mock-2',
|
||||
v: 40,
|
||||
meta: { start_ts: new Date(this.to.getTime() - 10) }
|
||||
},
|
||||
{
|
||||
op: 'mock-1',
|
||||
v: 39,
|
||||
meta: { start_ts: new Date(this.to.getTime() - 20) }
|
||||
}
|
||||
]
|
||||
this.fromVersion = 39
|
||||
this.toVersion = 40
|
||||
this.diffed_updates = this.updates.slice(2)
|
||||
this.rewound_content = 'rewound-content'
|
||||
return (this.diff = [{ u: 'mock-diff' }])
|
||||
})
|
||||
|
||||
it("should get the latest doc and version with all recent updates", function() {
|
||||
return this.DiffManager.getDocumentBeforeVersion
|
||||
.calledWith(this.project_id, this.doc_id, this.fromVersion)
|
||||
.should.equal(true);
|
||||
});
|
||||
describe('with matching versions', function() {
|
||||
beforeEach(function() {
|
||||
this.DiffManager.getDocumentBeforeVersion = sinon
|
||||
.stub()
|
||||
.callsArgWith(3, null, this.rewound_content, this.updates)
|
||||
this.DiffGenerator.buildDiff = sinon.stub().returns(this.diff)
|
||||
return this.DiffManager.getDiff(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.fromVersion,
|
||||
this.toVersion,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
it("should generate the diff", function() {
|
||||
return this.DiffGenerator.buildDiff
|
||||
.calledWith(this.rewound_content, this.diffed_updates.slice().reverse())
|
||||
.should.equal(true);
|
||||
});
|
||||
it('should get the latest doc and version with all recent updates', function() {
|
||||
return this.DiffManager.getDocumentBeforeVersion
|
||||
.calledWith(this.project_id, this.doc_id, this.fromVersion)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
return it("should call the callback with the diff", function() {
|
||||
return this.callback.calledWith(null, this.diff).should.equal(true);
|
||||
});
|
||||
});
|
||||
it('should generate the diff', function() {
|
||||
return this.DiffGenerator.buildDiff
|
||||
.calledWith(
|
||||
this.rewound_content,
|
||||
this.diffed_updates.slice().reverse()
|
||||
)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
return describe("when the updates are inconsistent", function() {
|
||||
beforeEach(function() {
|
||||
this.DiffManager.getLatestDocAndUpdates = sinon.stub().callsArgWith(3, null, this.content, this.version, this.updates);
|
||||
this.DiffGenerator.buildDiff = sinon.stub().throws(this.error = new Error("inconsistent!"));
|
||||
return this.DiffManager.getDiff(this.project_id, this.doc_id, this.fromVersion, this.toVersion, this.callback);
|
||||
});
|
||||
return it('should call the callback with the diff', function() {
|
||||
return this.callback.calledWith(null, this.diff).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
return it("should call the callback with an error", function() {
|
||||
return this.callback
|
||||
.calledWith(this.error)
|
||||
.should.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
return describe('when the updates are inconsistent', function() {
|
||||
beforeEach(function() {
|
||||
this.DiffManager.getLatestDocAndUpdates = sinon
|
||||
.stub()
|
||||
.callsArgWith(3, null, this.content, this.version, this.updates)
|
||||
this.DiffGenerator.buildDiff = sinon
|
||||
.stub()
|
||||
.throws((this.error = new Error('inconsistent!')))
|
||||
return this.DiffManager.getDiff(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.fromVersion,
|
||||
this.toVersion,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
describe("getDocumentBeforeVersion", function() {
|
||||
beforeEach(function() {
|
||||
this.DiffManager._tryGetDocumentBeforeVersion = sinon.stub();
|
||||
this.document = "mock-documents";
|
||||
return this.rewound_updates = "mock-rewound-updates";
|
||||
});
|
||||
return it('should call the callback with an error', function() {
|
||||
return this.callback.calledWith(this.error).should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("succesfully", function() {
|
||||
beforeEach(function() {
|
||||
this.DiffManager._tryGetDocumentBeforeVersion.yields(null, this.document, this.rewound_updates);
|
||||
return this.DiffManager.getDocumentBeforeVersion(this.project_id, this.doc_id, this.version, this.callback);
|
||||
});
|
||||
|
||||
it("should call _tryGetDocumentBeforeVersion", function() {
|
||||
return this.DiffManager._tryGetDocumentBeforeVersion
|
||||
.calledWith(this.project_id, this.doc_id, this.version)
|
||||
.should.equal(true);
|
||||
});
|
||||
|
||||
return it("should call the callback with the response", function() {
|
||||
return this.callback.calledWith(null, this.document, this.rewound_updates).should.equal(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("with a retry needed", function() {
|
||||
beforeEach(function() {
|
||||
let retried = false;
|
||||
this.DiffManager._tryGetDocumentBeforeVersion = (project_id, doc_id, version, callback) => {
|
||||
if (!retried) {
|
||||
retried = true;
|
||||
const error = new Error();
|
||||
error.retry = true;
|
||||
return callback(error);
|
||||
} else {
|
||||
return callback(null, this.document, this.rewound_updates);
|
||||
}
|
||||
};
|
||||
sinon.spy(this.DiffManager, "_tryGetDocumentBeforeVersion");
|
||||
return this.DiffManager.getDocumentBeforeVersion(this.project_id, this.doc_id, this.version, this.callback);
|
||||
});
|
||||
|
||||
it("should call _tryGetDocumentBeforeVersion twice", function() {
|
||||
return this.DiffManager._tryGetDocumentBeforeVersion
|
||||
.calledTwice
|
||||
.should.equal(true);
|
||||
});
|
||||
|
||||
return it("should call the callback with the response", function() {
|
||||
return this.callback.calledWith(null, this.document, this.rewound_updates).should.equal(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("with a non-retriable error", function() {
|
||||
beforeEach(function() {
|
||||
this.error = new Error("oops");
|
||||
this.DiffManager._tryGetDocumentBeforeVersion.yields(this.error);
|
||||
return this.DiffManager.getDocumentBeforeVersion(this.project_id, this.doc_id, this.version, this.callback);
|
||||
});
|
||||
|
||||
it("should call _tryGetDocumentBeforeVersion once", function() {
|
||||
return this.DiffManager._tryGetDocumentBeforeVersion
|
||||
.calledOnce
|
||||
.should.equal(true);
|
||||
});
|
||||
|
||||
return it("should call the callback with the error", function() {
|
||||
return this.callback.calledWith(this.error).should.equal(true);
|
||||
});
|
||||
});
|
||||
|
||||
return describe("when retry limit is matched", function() {
|
||||
beforeEach(function() {
|
||||
this.error = new Error("oops");
|
||||
this.error.retry = true;
|
||||
this.DiffManager._tryGetDocumentBeforeVersion.yields(this.error);
|
||||
return this.DiffManager.getDocumentBeforeVersion(this.project_id, this.doc_id, this.version, this.callback);
|
||||
});
|
||||
|
||||
it("should call _tryGetDocumentBeforeVersion three times (max retries)", function() {
|
||||
return this.DiffManager._tryGetDocumentBeforeVersion
|
||||
.calledThrice
|
||||
.should.equal(true);
|
||||
});
|
||||
|
||||
return it("should call the callback with the error", function() {
|
||||
return this.callback.calledWith(this.error).should.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('getDocumentBeforeVersion', function() {
|
||||
beforeEach(function() {
|
||||
this.DiffManager._tryGetDocumentBeforeVersion = sinon.stub()
|
||||
this.document = 'mock-documents'
|
||||
return (this.rewound_updates = 'mock-rewound-updates')
|
||||
})
|
||||
|
||||
return describe("_tryGetDocumentBeforeVersion", function() {
|
||||
beforeEach(function() {
|
||||
this.content = "hello world";
|
||||
// Op versions are the version they were applied to, so doc is always one version
|
||||
// ahead.s
|
||||
this.version = 43;
|
||||
this.updates = [
|
||||
{ op: "mock-4", v: 42, meta: { start_ts: new Date(this.to.getTime() + 20)} },
|
||||
{ op: "mock-3", v: 41, meta: { start_ts: new Date(this.to.getTime() + 10)} },
|
||||
{ op: "mock-2", v: 40, meta: { start_ts: new Date(this.to.getTime() - 10)} },
|
||||
{ op: "mock-1", v: 39, meta: { start_ts: new Date(this.to.getTime() - 20)} }
|
||||
];
|
||||
this.fromVersion = 39;
|
||||
this.rewound_content = "rewound-content";
|
||||
return this.diff = [ {u: "mock-diff"} ];});
|
||||
|
||||
describe("with matching versions", function() {
|
||||
beforeEach(function() {
|
||||
this.DiffManager.getLatestDocAndUpdates = sinon.stub().callsArgWith(3, null, this.content, this.version, this.updates);
|
||||
this.DiffGenerator.rewindUpdates = sinon.spy((content, updates) => {
|
||||
// the rewindUpdates method reverses the 'updates' array
|
||||
updates.reverse();
|
||||
return this.rewound_content;
|
||||
});
|
||||
this.rewindUpdatesWithArgs = this.DiffGenerator.rewindUpdates.withArgs(this.content, this.updates.slice().reverse());
|
||||
return this.DiffManager._tryGetDocumentBeforeVersion(this.project_id, this.doc_id, this.fromVersion, this.callback);
|
||||
});
|
||||
describe('succesfully', function() {
|
||||
beforeEach(function() {
|
||||
this.DiffManager._tryGetDocumentBeforeVersion.yields(
|
||||
null,
|
||||
this.document,
|
||||
this.rewound_updates
|
||||
)
|
||||
return this.DiffManager.getDocumentBeforeVersion(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.version,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
it("should get the latest doc and version with all recent updates", function() {
|
||||
return this.DiffManager.getLatestDocAndUpdates
|
||||
.calledWith(this.project_id, this.doc_id, this.fromVersion)
|
||||
.should.equal(true);
|
||||
});
|
||||
it('should call _tryGetDocumentBeforeVersion', function() {
|
||||
return this.DiffManager._tryGetDocumentBeforeVersion
|
||||
.calledWith(this.project_id, this.doc_id, this.version)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it("should rewind the diff", function() {
|
||||
return sinon.assert.calledOnce(this.rewindUpdatesWithArgs);
|
||||
});
|
||||
return it('should call the callback with the response', function() {
|
||||
return this.callback
|
||||
.calledWith(null, this.document, this.rewound_updates)
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
return it("should call the callback with the rewound document and updates", function() {
|
||||
return this.callback.calledWith(null, this.rewound_content, this.updates).should.equal(true);
|
||||
});
|
||||
});
|
||||
describe('with a retry needed', function() {
|
||||
beforeEach(function() {
|
||||
let retried = false
|
||||
this.DiffManager._tryGetDocumentBeforeVersion = (
|
||||
project_id,
|
||||
doc_id,
|
||||
version,
|
||||
callback
|
||||
) => {
|
||||
if (!retried) {
|
||||
retried = true
|
||||
const error = new Error()
|
||||
error.retry = true
|
||||
return callback(error)
|
||||
} else {
|
||||
return callback(null, this.document, this.rewound_updates)
|
||||
}
|
||||
}
|
||||
sinon.spy(this.DiffManager, '_tryGetDocumentBeforeVersion')
|
||||
return this.DiffManager.getDocumentBeforeVersion(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.version,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
describe("with mismatching versions", function() {
|
||||
beforeEach(function() {
|
||||
this.version = 50;
|
||||
this.updates = [ { op: "mock-1", v: 40 }, { op: "mock-1", v: 39 } ];
|
||||
this.DiffManager.getLatestDocAndUpdates = sinon.stub().callsArgWith(3, null, this.content, this.version, this.updates);
|
||||
return this.DiffManager._tryGetDocumentBeforeVersion(this.project_id, this.doc_id, this.fromVersion, this.callback);
|
||||
});
|
||||
it('should call _tryGetDocumentBeforeVersion twice', function() {
|
||||
return this.DiffManager._tryGetDocumentBeforeVersion.calledTwice.should.equal(
|
||||
true
|
||||
)
|
||||
})
|
||||
|
||||
return it("should call the callback with an error with retry = true set", function() {
|
||||
this.callback.calledOnce.should.equal(true);
|
||||
const error = this.callback.args[0][0];
|
||||
return expect(error.retry).to.equal(true);
|
||||
});
|
||||
});
|
||||
return it('should call the callback with the response', function() {
|
||||
return this.callback
|
||||
.calledWith(null, this.document, this.rewound_updates)
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
return describe("when the updates are inconsistent", function() {
|
||||
beforeEach(function() {
|
||||
this.DiffManager.getLatestDocAndUpdates = sinon.stub().callsArgWith(3, null, this.content, this.version, this.updates);
|
||||
this.DiffGenerator.rewindUpdates = sinon.stub().throws(this.error = new Error("inconsistent!"));
|
||||
return this.DiffManager.getDocumentBeforeVersion(this.project_id, this.doc_id, this.fromVersion, this.callback);
|
||||
});
|
||||
describe('with a non-retriable error', function() {
|
||||
beforeEach(function() {
|
||||
this.error = new Error('oops')
|
||||
this.DiffManager._tryGetDocumentBeforeVersion.yields(this.error)
|
||||
return this.DiffManager.getDocumentBeforeVersion(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.version,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
return it("should call the callback with an error", function() {
|
||||
return this.callback
|
||||
.calledWith(this.error)
|
||||
.should.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
it('should call _tryGetDocumentBeforeVersion once', function() {
|
||||
return this.DiffManager._tryGetDocumentBeforeVersion.calledOnce.should.equal(
|
||||
true
|
||||
)
|
||||
})
|
||||
|
||||
return it('should call the callback with the error', function() {
|
||||
return this.callback.calledWith(this.error).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
return describe('when retry limit is matched', function() {
|
||||
beforeEach(function() {
|
||||
this.error = new Error('oops')
|
||||
this.error.retry = true
|
||||
this.DiffManager._tryGetDocumentBeforeVersion.yields(this.error)
|
||||
return this.DiffManager.getDocumentBeforeVersion(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.version,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
it('should call _tryGetDocumentBeforeVersion three times (max retries)', function() {
|
||||
return this.DiffManager._tryGetDocumentBeforeVersion.calledThrice.should.equal(
|
||||
true
|
||||
)
|
||||
})
|
||||
|
||||
return it('should call the callback with the error', function() {
|
||||
return this.callback.calledWith(this.error).should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
return describe('_tryGetDocumentBeforeVersion', function() {
|
||||
beforeEach(function() {
|
||||
this.content = 'hello world'
|
||||
// Op versions are the version they were applied to, so doc is always one version
|
||||
// ahead.s
|
||||
this.version = 43
|
||||
this.updates = [
|
||||
{
|
||||
op: 'mock-4',
|
||||
v: 42,
|
||||
meta: { start_ts: new Date(this.to.getTime() + 20) }
|
||||
},
|
||||
{
|
||||
op: 'mock-3',
|
||||
v: 41,
|
||||
meta: { start_ts: new Date(this.to.getTime() + 10) }
|
||||
},
|
||||
{
|
||||
op: 'mock-2',
|
||||
v: 40,
|
||||
meta: { start_ts: new Date(this.to.getTime() - 10) }
|
||||
},
|
||||
{
|
||||
op: 'mock-1',
|
||||
v: 39,
|
||||
meta: { start_ts: new Date(this.to.getTime() - 20) }
|
||||
}
|
||||
]
|
||||
this.fromVersion = 39
|
||||
this.rewound_content = 'rewound-content'
|
||||
return (this.diff = [{ u: 'mock-diff' }])
|
||||
})
|
||||
|
||||
describe('with matching versions', function() {
|
||||
beforeEach(function() {
|
||||
this.DiffManager.getLatestDocAndUpdates = sinon
|
||||
.stub()
|
||||
.callsArgWith(3, null, this.content, this.version, this.updates)
|
||||
this.DiffGenerator.rewindUpdates = sinon.spy((content, updates) => {
|
||||
// the rewindUpdates method reverses the 'updates' array
|
||||
updates.reverse()
|
||||
return this.rewound_content
|
||||
})
|
||||
this.rewindUpdatesWithArgs = this.DiffGenerator.rewindUpdates.withArgs(
|
||||
this.content,
|
||||
this.updates.slice().reverse()
|
||||
)
|
||||
return this.DiffManager._tryGetDocumentBeforeVersion(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.fromVersion,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
it('should get the latest doc and version with all recent updates', function() {
|
||||
return this.DiffManager.getLatestDocAndUpdates
|
||||
.calledWith(this.project_id, this.doc_id, this.fromVersion)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should rewind the diff', function() {
|
||||
return sinon.assert.calledOnce(this.rewindUpdatesWithArgs)
|
||||
})
|
||||
|
||||
return it('should call the callback with the rewound document and updates', function() {
|
||||
return this.callback
|
||||
.calledWith(null, this.rewound_content, this.updates)
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with mismatching versions', function() {
|
||||
beforeEach(function() {
|
||||
this.version = 50
|
||||
this.updates = [
|
||||
{ op: 'mock-1', v: 40 },
|
||||
{ op: 'mock-1', v: 39 }
|
||||
]
|
||||
this.DiffManager.getLatestDocAndUpdates = sinon
|
||||
.stub()
|
||||
.callsArgWith(3, null, this.content, this.version, this.updates)
|
||||
return this.DiffManager._tryGetDocumentBeforeVersion(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.fromVersion,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
return it('should call the callback with an error with retry = true set', function() {
|
||||
this.callback.calledOnce.should.equal(true)
|
||||
const error = this.callback.args[0][0]
|
||||
return expect(error.retry).to.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
return describe('when the updates are inconsistent', function() {
|
||||
beforeEach(function() {
|
||||
this.DiffManager.getLatestDocAndUpdates = sinon
|
||||
.stub()
|
||||
.callsArgWith(3, null, this.content, this.version, this.updates)
|
||||
this.DiffGenerator.rewindUpdates = sinon
|
||||
.stub()
|
||||
.throws((this.error = new Error('inconsistent!')))
|
||||
return this.DiffManager.getDocumentBeforeVersion(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.fromVersion,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
return it('should call the callback with an error', function() {
|
||||
return this.callback.calledWith(this.error).should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -9,88 +9,104 @@
|
|||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
const chai = require('chai');
|
||||
chai.should();
|
||||
const sinon = require("sinon");
|
||||
const modulePath = "../../../../app/js/MongoAWS.js";
|
||||
const SandboxedModule = require('sandboxed-module');
|
||||
const {ObjectId} = require("mongojs");
|
||||
const MemoryStream = require('memorystream');
|
||||
const zlib = require("zlib");
|
||||
const chai = require('chai')
|
||||
chai.should()
|
||||
const sinon = require('sinon')
|
||||
const modulePath = '../../../../app/js/MongoAWS.js'
|
||||
const SandboxedModule = require('sandboxed-module')
|
||||
const { ObjectId } = require('mongojs')
|
||||
const MemoryStream = require('memorystream')
|
||||
const zlib = require('zlib')
|
||||
|
||||
describe("MongoAWS", function() {
|
||||
beforeEach(function() {
|
||||
this.MongoAWS = SandboxedModule.require(modulePath, { requires: {
|
||||
"settings-sharelatex": (this.settings = {
|
||||
trackchanges: {
|
||||
s3: {
|
||||
secret: "s3-secret",
|
||||
key: "s3-key"
|
||||
},
|
||||
stores: {
|
||||
doc_history: "s3-bucket"
|
||||
}
|
||||
}
|
||||
}),
|
||||
"child_process": (this.child_process = {}),
|
||||
"mongo-uri": (this.mongouri = {}),
|
||||
"logger-sharelatex": (this.logger = {log: sinon.stub(), error: sinon.stub(), err() {}}),
|
||||
"aws-sdk": (this.awssdk = {}),
|
||||
"fs": (this.fs = {}),
|
||||
"s3-streams": (this.S3S = {}),
|
||||
"./mongojs" : { db: (this.db = {}), ObjectId },
|
||||
"JSONStream": (this.JSONStream = {}),
|
||||
"readline-stream": (this.readline = sinon.stub()),
|
||||
'metrics-sharelatex': {inc(){}}
|
||||
}
|
||||
});
|
||||
describe('MongoAWS', function() {
|
||||
beforeEach(function() {
|
||||
this.MongoAWS = SandboxedModule.require(modulePath, {
|
||||
requires: {
|
||||
'settings-sharelatex': (this.settings = {
|
||||
trackchanges: {
|
||||
s3: {
|
||||
secret: 's3-secret',
|
||||
key: 's3-key'
|
||||
},
|
||||
stores: {
|
||||
doc_history: 's3-bucket'
|
||||
}
|
||||
}
|
||||
}),
|
||||
child_process: (this.child_process = {}),
|
||||
'mongo-uri': (this.mongouri = {}),
|
||||
'logger-sharelatex': (this.logger = {
|
||||
log: sinon.stub(),
|
||||
error: sinon.stub(),
|
||||
err() {}
|
||||
}),
|
||||
'aws-sdk': (this.awssdk = {}),
|
||||
fs: (this.fs = {}),
|
||||
's3-streams': (this.S3S = {}),
|
||||
'./mongojs': { db: (this.db = {}), ObjectId },
|
||||
JSONStream: (this.JSONStream = {}),
|
||||
'readline-stream': (this.readline = sinon.stub()),
|
||||
'metrics-sharelatex': { inc() {} }
|
||||
}
|
||||
})
|
||||
|
||||
this.project_id = ObjectId().toString();
|
||||
this.doc_id = ObjectId().toString();
|
||||
this.pack_id = ObjectId();
|
||||
this.update = { v:123 };
|
||||
return this.callback = sinon.stub();
|
||||
});
|
||||
this.project_id = ObjectId().toString()
|
||||
this.doc_id = ObjectId().toString()
|
||||
this.pack_id = ObjectId()
|
||||
this.update = { v: 123 }
|
||||
return (this.callback = sinon.stub())
|
||||
})
|
||||
|
||||
describe("archivePack", function() {
|
||||
describe('archivePack', function() {
|
||||
beforeEach(function(done) {
|
||||
this.awssdk.config = { update: sinon.stub() }
|
||||
this.awssdk.S3 = sinon.stub()
|
||||
this.S3S.WriteStream = () => MemoryStream.createWriteStream()
|
||||
this.db.docHistory = {}
|
||||
this.db.docHistory.findOne = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { pack: 'hello' })
|
||||
|
||||
beforeEach(function(done) {
|
||||
this.awssdk.config = { update: sinon.stub() };
|
||||
this.awssdk.S3 = sinon.stub();
|
||||
this.S3S.WriteStream = () => MemoryStream.createWriteStream();
|
||||
this.db.docHistory = {};
|
||||
this.db.docHistory.findOne = sinon.stub().callsArgWith(1, null, {"pack":"hello"});
|
||||
return this.MongoAWS.archivePack(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.pack_id,
|
||||
(err, result) => {
|
||||
this.callback()
|
||||
return done()
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
return this.MongoAWS.archivePack(this.project_id, this.doc_id, this.pack_id, (err, result) => {
|
||||
this.callback();
|
||||
return done();
|
||||
});
|
||||
});
|
||||
return it('should call the callback', function() {
|
||||
return this.callback.called.should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
return it("should call the callback", function() {
|
||||
return this.callback.called.should.equal(true);
|
||||
});
|
||||
});
|
||||
return describe('unArchivePack', function() {
|
||||
beforeEach(function(done) {
|
||||
return zlib.gzip('{"pack":"123"}', (err, zbuf) => {
|
||||
this.awssdk.config = { update: sinon.stub() }
|
||||
this.awssdk.S3 = sinon.stub()
|
||||
this.S3S.ReadStream = () =>
|
||||
MemoryStream.createReadStream(zbuf, { readable: true })
|
||||
this.db.docHistory = {}
|
||||
this.db.docHistory.insert = sinon.stub().callsArgWith(1, null, 'pack')
|
||||
|
||||
return describe("unArchivePack", function() {
|
||||
return this.MongoAWS.unArchivePack(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.pack_id,
|
||||
(err, result) => {
|
||||
this.callback()
|
||||
return done()
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
beforeEach(function(done) {
|
||||
return zlib.gzip('{"pack":"123"}', (err, zbuf) => {
|
||||
this.awssdk.config = { update: sinon.stub() };
|
||||
this.awssdk.S3 = sinon.stub();
|
||||
this.S3S.ReadStream = () => MemoryStream.createReadStream(zbuf, {readable:true});
|
||||
this.db.docHistory = {};
|
||||
this.db.docHistory.insert = sinon.stub().callsArgWith(1, null, "pack");
|
||||
|
||||
return this.MongoAWS.unArchivePack(this.project_id, this.doc_id, this.pack_id, (err, result) => {
|
||||
this.callback();
|
||||
return done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return it("should call db.docHistory.insert", function() {
|
||||
return this.db.docHistory.insert.called.should.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
return it('should call db.docHistory.insert', function() {
|
||||
return this.db.docHistory.insert.called.should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -9,127 +9,197 @@
|
|||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
const sinon = require('sinon');
|
||||
const chai = require('chai');
|
||||
const should = chai.should();
|
||||
const { expect } = chai;
|
||||
const modulePath = "../../../../app/js/DocumentUpdaterManager.js";
|
||||
const SandboxedModule = require('sandboxed-module');
|
||||
const sinon = require('sinon')
|
||||
const chai = require('chai')
|
||||
const should = chai.should()
|
||||
const { expect } = chai
|
||||
const modulePath = '../../../../app/js/DocumentUpdaterManager.js'
|
||||
const SandboxedModule = require('sandboxed-module')
|
||||
|
||||
describe("DocumentUpdaterManager", function() {
|
||||
beforeEach(function() {
|
||||
this.DocumentUpdaterManager = SandboxedModule.require(modulePath, { requires: {
|
||||
"request": (this.request = {}),
|
||||
"logger-sharelatex": (this.logger = { log: sinon.stub(), error: sinon.stub() }),
|
||||
'settings-sharelatex': (this.settings =
|
||||
{apis : {documentupdater: {url : "http://example.com"}}})
|
||||
}
|
||||
}
|
||||
);
|
||||
this.callback = sinon.stub();
|
||||
this.lines = ["one", "two", "three"];
|
||||
return this.version = 42;
|
||||
});
|
||||
describe('DocumentUpdaterManager', function() {
|
||||
beforeEach(function() {
|
||||
this.DocumentUpdaterManager = SandboxedModule.require(modulePath, {
|
||||
requires: {
|
||||
request: (this.request = {}),
|
||||
'logger-sharelatex': (this.logger = {
|
||||
log: sinon.stub(),
|
||||
error: sinon.stub()
|
||||
}),
|
||||
'settings-sharelatex': (this.settings = {
|
||||
apis: { documentupdater: { url: 'http://example.com' } }
|
||||
})
|
||||
}
|
||||
})
|
||||
this.callback = sinon.stub()
|
||||
this.lines = ['one', 'two', 'three']
|
||||
return (this.version = 42)
|
||||
})
|
||||
|
||||
describe("getDocument", function() {
|
||||
describe("successfully", function() {
|
||||
beforeEach(function() {
|
||||
this.body = JSON.stringify({
|
||||
lines: this.lines,
|
||||
version: this.version,
|
||||
ops: []});
|
||||
this.request.get = sinon.stub().callsArgWith(1, null, {statusCode: 200}, this.body);
|
||||
return this.DocumentUpdaterManager.getDocument(this.project_id, this.doc_id, this.callback);
|
||||
});
|
||||
describe('getDocument', function() {
|
||||
describe('successfully', function() {
|
||||
beforeEach(function() {
|
||||
this.body = JSON.stringify({
|
||||
lines: this.lines,
|
||||
version: this.version,
|
||||
ops: []
|
||||
})
|
||||
this.request.get = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 200 }, this.body)
|
||||
return this.DocumentUpdaterManager.getDocument(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
it('should get the document from the document updater', function() {
|
||||
const url = `${this.settings.apis.documentupdater.url}/project/${this.project_id}/doc/${this.doc_id}`;
|
||||
return this.request.get.calledWith(url).should.equal(true);
|
||||
});
|
||||
it('should get the document from the document updater', function() {
|
||||
const url = `${this.settings.apis.documentupdater.url}/project/${this.project_id}/doc/${this.doc_id}`
|
||||
return this.request.get.calledWith(url).should.equal(true)
|
||||
})
|
||||
|
||||
return it("should call the callback with the content and version", function() {
|
||||
return this.callback.calledWith(null, this.lines.join("\n"), this.version).should.equal(true);
|
||||
});
|
||||
});
|
||||
return it('should call the callback with the content and version', function() {
|
||||
return this.callback
|
||||
.calledWith(null, this.lines.join('\n'), this.version)
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe("when the document updater API returns an error", function() {
|
||||
beforeEach(function() {
|
||||
this.request.get = sinon.stub().callsArgWith(1, (this.error = new Error("something went wrong")), null, null);
|
||||
return this.DocumentUpdaterManager.getDocument(this.project_id, this.doc_id, this.callback);
|
||||
});
|
||||
describe('when the document updater API returns an error', function() {
|
||||
beforeEach(function() {
|
||||
this.request.get = sinon
|
||||
.stub()
|
||||
.callsArgWith(
|
||||
1,
|
||||
(this.error = new Error('something went wrong')),
|
||||
null,
|
||||
null
|
||||
)
|
||||
return this.DocumentUpdaterManager.getDocument(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
return it("should return an error to the callback", function() {
|
||||
return this.callback.calledWith(this.error).should.equal(true);
|
||||
});
|
||||
});
|
||||
return it('should return an error to the callback', function() {
|
||||
return this.callback.calledWith(this.error).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
return describe("when the document updater returns a failure error code", function() {
|
||||
beforeEach(function() {
|
||||
this.request.get = sinon.stub().callsArgWith(1, null, { statusCode: 500 }, "");
|
||||
return this.DocumentUpdaterManager.getDocument(this.project_id, this.doc_id, this.callback);
|
||||
});
|
||||
return describe('when the document updater returns a failure error code', function() {
|
||||
beforeEach(function() {
|
||||
this.request.get = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 500 }, '')
|
||||
return this.DocumentUpdaterManager.getDocument(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
return it("should return the callback with an error", function() {
|
||||
return this.callback
|
||||
.calledWith(sinon.match.has('message', "doc updater returned a non-success status code: 500"))
|
||||
.should.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
return it('should return the callback with an error', function() {
|
||||
return this.callback
|
||||
.calledWith(
|
||||
sinon.match.has(
|
||||
'message',
|
||||
'doc updater returned a non-success status code: 500'
|
||||
)
|
||||
)
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
return describe("setDocument", function() {
|
||||
beforeEach(function() {
|
||||
this.content = "mock content";
|
||||
return this.user_id = "user-id-123";
|
||||
});
|
||||
return describe('setDocument', function() {
|
||||
beforeEach(function() {
|
||||
this.content = 'mock content'
|
||||
return (this.user_id = 'user-id-123')
|
||||
})
|
||||
|
||||
describe("successfully", function() {
|
||||
beforeEach(function() {
|
||||
this.request.post = sinon.stub().callsArgWith(1, null, {statusCode: 200});
|
||||
return this.DocumentUpdaterManager.setDocument(this.project_id, this.doc_id, this.content, this.user_id, this.callback);
|
||||
});
|
||||
describe('successfully', function() {
|
||||
beforeEach(function() {
|
||||
this.request.post = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 200 })
|
||||
return this.DocumentUpdaterManager.setDocument(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.content,
|
||||
this.user_id,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
it('should set the document in the document updater', function() {
|
||||
const url = `${this.settings.apis.documentupdater.url}/project/${this.project_id}/doc/${this.doc_id}`;
|
||||
return this.request.post
|
||||
.calledWith({
|
||||
url,
|
||||
json: {
|
||||
lines: this.content.split("\n"),
|
||||
source: "restore",
|
||||
user_id: this.user_id,
|
||||
undoing: true
|
||||
}
|
||||
}).should.equal(true);
|
||||
});
|
||||
it('should set the document in the document updater', function() {
|
||||
const url = `${this.settings.apis.documentupdater.url}/project/${this.project_id}/doc/${this.doc_id}`
|
||||
return this.request.post
|
||||
.calledWith({
|
||||
url,
|
||||
json: {
|
||||
lines: this.content.split('\n'),
|
||||
source: 'restore',
|
||||
user_id: this.user_id,
|
||||
undoing: true
|
||||
}
|
||||
})
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
return it("should call the callback", function() {
|
||||
return this.callback.calledWith(null).should.equal(true);
|
||||
});
|
||||
});
|
||||
return it('should call the callback', function() {
|
||||
return this.callback.calledWith(null).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe("when the document updater API returns an error", function() {
|
||||
beforeEach(function() {
|
||||
this.request.post = sinon.stub().callsArgWith(1, (this.error = new Error("something went wrong")), null, null);
|
||||
return this.DocumentUpdaterManager.setDocument(this.project_id, this.doc_id, this.content, this.user_id, this.callback);
|
||||
});
|
||||
describe('when the document updater API returns an error', function() {
|
||||
beforeEach(function() {
|
||||
this.request.post = sinon
|
||||
.stub()
|
||||
.callsArgWith(
|
||||
1,
|
||||
(this.error = new Error('something went wrong')),
|
||||
null,
|
||||
null
|
||||
)
|
||||
return this.DocumentUpdaterManager.setDocument(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.content,
|
||||
this.user_id,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
return it("should return an error to the callback", function() {
|
||||
return this.callback.calledWith(this.error).should.equal(true);
|
||||
});
|
||||
});
|
||||
return it('should return an error to the callback', function() {
|
||||
return this.callback.calledWith(this.error).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
return describe("when the document updater returns a failure error code", function() {
|
||||
beforeEach(function() {
|
||||
this.request.post = sinon.stub().callsArgWith(1, null, { statusCode: 500 }, "");
|
||||
return this.DocumentUpdaterManager.setDocument(this.project_id, this.doc_id, this.content, this.user_id, this.callback);
|
||||
});
|
||||
return describe('when the document updater returns a failure error code', function() {
|
||||
beforeEach(function() {
|
||||
this.request.post = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 500 }, '')
|
||||
return this.DocumentUpdaterManager.setDocument(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.content,
|
||||
this.user_id,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
return it("should return the callback with an error", function() {
|
||||
return this.callback
|
||||
.calledWith(sinon.match.has('message', "doc updater returned a non-success status code: 500"))
|
||||
.should.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
return it('should return the callback with an error', function() {
|
||||
return this.callback
|
||||
.calledWith(
|
||||
sinon.match.has(
|
||||
'message',
|
||||
'doc updater returned a non-success status code: 500'
|
||||
)
|
||||
)
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -9,175 +9,193 @@
|
|||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
const sinon = require('sinon');
|
||||
const chai = require('chai');
|
||||
const should = chai.should();
|
||||
const { expect } = chai;
|
||||
const modulePath = "../../../../app/js/HttpController.js";
|
||||
const SandboxedModule = require('sandboxed-module');
|
||||
const sinon = require('sinon')
|
||||
const chai = require('chai')
|
||||
const should = chai.should()
|
||||
const { expect } = chai
|
||||
const modulePath = '../../../../app/js/HttpController.js'
|
||||
const SandboxedModule = require('sandboxed-module')
|
||||
|
||||
describe("HttpController", function() {
|
||||
beforeEach(function() {
|
||||
this.HttpController = SandboxedModule.require(modulePath, { requires: {
|
||||
"logger-sharelatex": { log: sinon.stub() },
|
||||
"./UpdatesManager": (this.UpdatesManager = {}),
|
||||
"./DiffManager": (this.DiffManager = {}),
|
||||
"./RestoreManager": (this.RestoreManager = {}),
|
||||
"./PackManager": (this.PackManager = {}),
|
||||
"./DocArchiveManager": (this.DocArchiveManager = {}),
|
||||
"./HealthChecker": (this.HealthChecker = {})
|
||||
}
|
||||
});
|
||||
this.doc_id = "doc-id-123";
|
||||
this.project_id = "project-id-123";
|
||||
this.next = sinon.stub();
|
||||
this.user_id = "mock-user-123";
|
||||
return this.now = Date.now();
|
||||
});
|
||||
describe('HttpController', function() {
|
||||
beforeEach(function() {
|
||||
this.HttpController = SandboxedModule.require(modulePath, {
|
||||
requires: {
|
||||
'logger-sharelatex': { log: sinon.stub() },
|
||||
'./UpdatesManager': (this.UpdatesManager = {}),
|
||||
'./DiffManager': (this.DiffManager = {}),
|
||||
'./RestoreManager': (this.RestoreManager = {}),
|
||||
'./PackManager': (this.PackManager = {}),
|
||||
'./DocArchiveManager': (this.DocArchiveManager = {}),
|
||||
'./HealthChecker': (this.HealthChecker = {})
|
||||
}
|
||||
})
|
||||
this.doc_id = 'doc-id-123'
|
||||
this.project_id = 'project-id-123'
|
||||
this.next = sinon.stub()
|
||||
this.user_id = 'mock-user-123'
|
||||
return (this.now = Date.now())
|
||||
})
|
||||
|
||||
describe("flushDoc", function() {
|
||||
beforeEach(function() {
|
||||
this.req = {
|
||||
params: {
|
||||
doc_id: this.doc_id,
|
||||
project_id: this.project_id
|
||||
}
|
||||
};
|
||||
this.res =
|
||||
{send: sinon.stub()};
|
||||
this.UpdatesManager.processUncompressedUpdatesWithLock = sinon.stub().callsArg(2);
|
||||
return this.HttpController.flushDoc(this.req, this.res, this.next);
|
||||
});
|
||||
describe('flushDoc', function() {
|
||||
beforeEach(function() {
|
||||
this.req = {
|
||||
params: {
|
||||
doc_id: this.doc_id,
|
||||
project_id: this.project_id
|
||||
}
|
||||
}
|
||||
this.res = { send: sinon.stub() }
|
||||
this.UpdatesManager.processUncompressedUpdatesWithLock = sinon
|
||||
.stub()
|
||||
.callsArg(2)
|
||||
return this.HttpController.flushDoc(this.req, this.res, this.next)
|
||||
})
|
||||
|
||||
it("should process the updates", function() {
|
||||
return this.UpdatesManager.processUncompressedUpdatesWithLock
|
||||
.calledWith(this.project_id, this.doc_id)
|
||||
.should.equal(true);
|
||||
});
|
||||
it('should process the updates', function() {
|
||||
return this.UpdatesManager.processUncompressedUpdatesWithLock
|
||||
.calledWith(this.project_id, this.doc_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
return it("should return a success code", function() {
|
||||
return this.res.send.calledWith(204).should.equal(true);
|
||||
});
|
||||
});
|
||||
return it('should return a success code', function() {
|
||||
return this.res.send.calledWith(204).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe("flushProject", function() {
|
||||
beforeEach(function() {
|
||||
this.req = {
|
||||
params: {
|
||||
project_id: this.project_id
|
||||
}
|
||||
};
|
||||
this.res =
|
||||
{send: sinon.stub()};
|
||||
this.UpdatesManager.processUncompressedUpdatesForProject = sinon.stub().callsArg(1);
|
||||
return this.HttpController.flushProject(this.req, this.res, this.next);
|
||||
});
|
||||
describe('flushProject', function() {
|
||||
beforeEach(function() {
|
||||
this.req = {
|
||||
params: {
|
||||
project_id: this.project_id
|
||||
}
|
||||
}
|
||||
this.res = { send: sinon.stub() }
|
||||
this.UpdatesManager.processUncompressedUpdatesForProject = sinon
|
||||
.stub()
|
||||
.callsArg(1)
|
||||
return this.HttpController.flushProject(this.req, this.res, this.next)
|
||||
})
|
||||
|
||||
it("should process the updates", function() {
|
||||
return this.UpdatesManager.processUncompressedUpdatesForProject
|
||||
.calledWith(this.project_id)
|
||||
.should.equal(true);
|
||||
});
|
||||
it('should process the updates', function() {
|
||||
return this.UpdatesManager.processUncompressedUpdatesForProject
|
||||
.calledWith(this.project_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
return it("should return a success code", function() {
|
||||
return this.res.send.calledWith(204).should.equal(true);
|
||||
});
|
||||
});
|
||||
return it('should return a success code', function() {
|
||||
return this.res.send.calledWith(204).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('getDiff', function() {
|
||||
beforeEach(function() {
|
||||
this.from = 42
|
||||
this.to = 45
|
||||
this.req = {
|
||||
params: {
|
||||
doc_id: this.doc_id,
|
||||
project_id: this.project_id
|
||||
},
|
||||
query: {
|
||||
from: this.from.toString(),
|
||||
to: this.to.toString()
|
||||
}
|
||||
}
|
||||
this.res = { json: sinon.stub() }
|
||||
this.diff = [{ u: 'mock-diff' }]
|
||||
this.DiffManager.getDiff = sinon.stub().callsArgWith(4, null, this.diff)
|
||||
return this.HttpController.getDiff(this.req, this.res, this.next)
|
||||
})
|
||||
|
||||
describe("getDiff", function() {
|
||||
beforeEach(function() {
|
||||
this.from = 42;
|
||||
this.to = 45;
|
||||
this.req = {
|
||||
params: {
|
||||
doc_id: this.doc_id,
|
||||
project_id: this.project_id
|
||||
},
|
||||
query: {
|
||||
from: this.from.toString(),
|
||||
to: this.to.toString()
|
||||
}
|
||||
};
|
||||
this.res =
|
||||
{json: sinon.stub()};
|
||||
this.diff = [ {u: "mock-diff"} ];
|
||||
this.DiffManager.getDiff = sinon.stub().callsArgWith(4, null, this.diff);
|
||||
return this.HttpController.getDiff(this.req, this.res, this.next);
|
||||
});
|
||||
it('should get the diff', function() {
|
||||
return this.DiffManager.getDiff
|
||||
.calledWith(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
parseInt(this.from, 10),
|
||||
parseInt(this.to, 10)
|
||||
)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it("should get the diff", function() {
|
||||
return this.DiffManager.getDiff
|
||||
.calledWith(this.project_id, this.doc_id, parseInt(this.from, 10), parseInt(this.to, 10))
|
||||
.should.equal(true);
|
||||
});
|
||||
return it('should return the diff', function() {
|
||||
return this.res.json.calledWith({ diff: this.diff }).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
return it("should return the diff", function() {
|
||||
return this.res.json.calledWith({diff: this.diff}).should.equal(true);
|
||||
});
|
||||
});
|
||||
describe('getUpdates', function() {
|
||||
beforeEach(function() {
|
||||
this.before = Date.now()
|
||||
this.nextBeforeTimestamp = this.before - 100
|
||||
this.min_count = 10
|
||||
this.req = {
|
||||
params: {
|
||||
project_id: this.project_id
|
||||
},
|
||||
query: {
|
||||
before: this.before.toString(),
|
||||
min_count: this.min_count.toString()
|
||||
}
|
||||
}
|
||||
this.res = { json: sinon.stub() }
|
||||
this.updates = ['mock-summarized-updates']
|
||||
this.UpdatesManager.getSummarizedProjectUpdates = sinon
|
||||
.stub()
|
||||
.callsArgWith(2, null, this.updates, this.nextBeforeTimestamp)
|
||||
return this.HttpController.getUpdates(this.req, this.res, this.next)
|
||||
})
|
||||
|
||||
describe("getUpdates", function() {
|
||||
beforeEach(function() {
|
||||
this.before = Date.now();
|
||||
this.nextBeforeTimestamp = this.before - 100;
|
||||
this.min_count = 10;
|
||||
this.req = {
|
||||
params: {
|
||||
project_id: this.project_id
|
||||
},
|
||||
query: {
|
||||
before: this.before.toString(),
|
||||
min_count: this.min_count.toString()
|
||||
}
|
||||
};
|
||||
this.res =
|
||||
{json: sinon.stub()};
|
||||
this.updates = ["mock-summarized-updates"];
|
||||
this.UpdatesManager.getSummarizedProjectUpdates = sinon.stub().callsArgWith(2, null, this.updates, this.nextBeforeTimestamp);
|
||||
return this.HttpController.getUpdates(this.req, this.res, this.next);
|
||||
});
|
||||
it('should get the updates', function() {
|
||||
return this.UpdatesManager.getSummarizedProjectUpdates
|
||||
.calledWith(this.project_id, {
|
||||
before: this.before,
|
||||
min_count: this.min_count
|
||||
})
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it("should get the updates", function() {
|
||||
return this.UpdatesManager.getSummarizedProjectUpdates
|
||||
.calledWith(this.project_id, {before: this.before, min_count: this.min_count})
|
||||
.should.equal(true);
|
||||
});
|
||||
return it('should return the formatted updates', function() {
|
||||
return this.res.json
|
||||
.calledWith({
|
||||
updates: this.updates,
|
||||
nextBeforeTimestamp: this.nextBeforeTimestamp
|
||||
})
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
return it("should return the formatted updates", function() {
|
||||
return this.res.json.calledWith({updates: this.updates, nextBeforeTimestamp: this.nextBeforeTimestamp}).should.equal(true);
|
||||
});
|
||||
});
|
||||
return describe('RestoreManager', function() {
|
||||
beforeEach(function() {
|
||||
this.version = '42'
|
||||
this.req = {
|
||||
params: {
|
||||
doc_id: this.doc_id,
|
||||
project_id: this.project_id,
|
||||
version: this.version
|
||||
},
|
||||
headers: {
|
||||
'x-user-id': this.user_id
|
||||
}
|
||||
}
|
||||
this.res = { send: sinon.stub() }
|
||||
|
||||
return describe("RestoreManager", function() {
|
||||
beforeEach(function() {
|
||||
this.version = "42";
|
||||
this.req = {
|
||||
params: {
|
||||
doc_id: this.doc_id,
|
||||
project_id: this.project_id,
|
||||
version: this.version
|
||||
},
|
||||
headers: {
|
||||
"x-user-id": this.user_id
|
||||
}
|
||||
};
|
||||
this.res =
|
||||
{send: sinon.stub()};
|
||||
this.RestoreManager.restoreToBeforeVersion = sinon.stub().callsArg(4)
|
||||
return this.HttpController.restore(this.req, this.res, this.next)
|
||||
})
|
||||
|
||||
this.RestoreManager.restoreToBeforeVersion = sinon.stub().callsArg(4);
|
||||
return this.HttpController.restore(this.req, this.res, this.next);
|
||||
});
|
||||
|
||||
it("should restore the document", function() {
|
||||
return this.RestoreManager.restoreToBeforeVersion
|
||||
.calledWith(this.project_id, this.doc_id, parseInt(this.version, 10), this.user_id)
|
||||
.should.equal(true);
|
||||
});
|
||||
|
||||
return it("should return a success code", function() {
|
||||
return this.res.send.calledWith(204).should.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
it('should restore the document', function() {
|
||||
return this.RestoreManager.restoreToBeforeVersion
|
||||
.calledWith(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
parseInt(this.version, 10),
|
||||
this.user_id
|
||||
)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
return it('should return a success code', function() {
|
||||
return this.res.send.calledWith(204).should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -15,270 +15,306 @@
|
|||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
const sinon = require('sinon');
|
||||
const chai = require('chai');
|
||||
const should = chai.should();
|
||||
const { expect } = chai;
|
||||
const modulePath = "../../../../app/js/LockManager.js";
|
||||
const SandboxedModule = require('sandboxed-module');
|
||||
const sinon = require('sinon')
|
||||
const chai = require('chai')
|
||||
const should = chai.should()
|
||||
const { expect } = chai
|
||||
const modulePath = '../../../../app/js/LockManager.js'
|
||||
const SandboxedModule = require('sandboxed-module')
|
||||
|
||||
describe("LockManager", function() {
|
||||
beforeEach(function() {
|
||||
this.Settings = {
|
||||
redis: {
|
||||
lock:{}
|
||||
}
|
||||
};
|
||||
this.LockManager = SandboxedModule.require(modulePath, { requires: {
|
||||
"redis-sharelatex": {
|
||||
createClient: () => { return this.rclient =
|
||||
{auth: sinon.stub()}; }
|
||||
},
|
||||
"settings-sharelatex": this.Settings,
|
||||
"logger-sharelatex": {error() {}}
|
||||
}
|
||||
});
|
||||
describe('LockManager', function() {
|
||||
beforeEach(function() {
|
||||
this.Settings = {
|
||||
redis: {
|
||||
lock: {}
|
||||
}
|
||||
}
|
||||
this.LockManager = SandboxedModule.require(modulePath, {
|
||||
requires: {
|
||||
'redis-sharelatex': {
|
||||
createClient: () => {
|
||||
return (this.rclient = { auth: sinon.stub() })
|
||||
}
|
||||
},
|
||||
'settings-sharelatex': this.Settings,
|
||||
'logger-sharelatex': { error() {} }
|
||||
}
|
||||
})
|
||||
|
||||
this.key = "lock-key";
|
||||
return this.callback = sinon.stub();
|
||||
});
|
||||
this.key = 'lock-key'
|
||||
return (this.callback = sinon.stub())
|
||||
})
|
||||
|
||||
describe("checkLock", function() {
|
||||
describe("when the lock is taken", function() {
|
||||
beforeEach(function() {
|
||||
this.rclient.exists = sinon.stub().callsArgWith(1, null, "1");
|
||||
return this.LockManager.checkLock(this.key, this.callback);
|
||||
});
|
||||
describe('checkLock', function() {
|
||||
describe('when the lock is taken', function() {
|
||||
beforeEach(function() {
|
||||
this.rclient.exists = sinon.stub().callsArgWith(1, null, '1')
|
||||
return this.LockManager.checkLock(this.key, this.callback)
|
||||
})
|
||||
|
||||
it("should check the lock in redis", function() {
|
||||
return this.rclient.exists
|
||||
.calledWith(this.key)
|
||||
.should.equal(true);
|
||||
});
|
||||
it('should check the lock in redis', function() {
|
||||
return this.rclient.exists.calledWith(this.key).should.equal(true)
|
||||
})
|
||||
|
||||
return it("should return the callback with false", function() {
|
||||
return this.callback.calledWith(null, false).should.equal(true);
|
||||
});
|
||||
});
|
||||
return it('should return the callback with false', function() {
|
||||
return this.callback.calledWith(null, false).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
return describe("when the lock is free", function() {
|
||||
beforeEach(function() {
|
||||
this.rclient.exists = sinon.stub().callsArgWith(1, null, "0");
|
||||
return this.LockManager.checkLock(this.key, this.callback);
|
||||
});
|
||||
return describe('when the lock is free', function() {
|
||||
beforeEach(function() {
|
||||
this.rclient.exists = sinon.stub().callsArgWith(1, null, '0')
|
||||
return this.LockManager.checkLock(this.key, this.callback)
|
||||
})
|
||||
|
||||
return it("should return the callback with true", function() {
|
||||
return this.callback.calledWith(null, true).should.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
return it('should return the callback with true', function() {
|
||||
return this.callback.calledWith(null, true).should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('tryLock', function() {
|
||||
describe('when the lock is taken', function() {
|
||||
beforeEach(function() {
|
||||
this.rclient.set = sinon.stub().callsArgWith(5, null, null)
|
||||
this.LockManager.randomLock = sinon
|
||||
.stub()
|
||||
.returns('locked-random-value')
|
||||
return this.LockManager.tryLock(this.key, this.callback)
|
||||
})
|
||||
|
||||
describe("tryLock", function() {
|
||||
describe("when the lock is taken", function() {
|
||||
beforeEach(function() {
|
||||
this.rclient.set = sinon.stub().callsArgWith(5, null, null);
|
||||
this.LockManager.randomLock = sinon.stub().returns("locked-random-value");
|
||||
return this.LockManager.tryLock(this.key, this.callback);
|
||||
});
|
||||
it('should check the lock in redis', function() {
|
||||
return this.rclient.set
|
||||
.calledWith(
|
||||
this.key,
|
||||
'locked-random-value',
|
||||
'EX',
|
||||
this.LockManager.LOCK_TTL,
|
||||
'NX'
|
||||
)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it("should check the lock in redis", function() {
|
||||
return this.rclient.set
|
||||
.calledWith(this.key, "locked-random-value", "EX", this.LockManager.LOCK_TTL, "NX")
|
||||
.should.equal(true);
|
||||
});
|
||||
return it('should return the callback with false', function() {
|
||||
return this.callback.calledWith(null, false).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
return it("should return the callback with false", function() {
|
||||
return this.callback.calledWith(null, false).should.equal(true);
|
||||
});
|
||||
});
|
||||
return describe('when the lock is free', function() {
|
||||
beforeEach(function() {
|
||||
this.rclient.set = sinon.stub().callsArgWith(5, null, 'OK')
|
||||
return this.LockManager.tryLock(this.key, this.callback)
|
||||
})
|
||||
|
||||
return describe("when the lock is free", function() {
|
||||
beforeEach(function() {
|
||||
this.rclient.set = sinon.stub().callsArgWith(5, null, "OK");
|
||||
return this.LockManager.tryLock(this.key, this.callback);
|
||||
});
|
||||
return it('should return the callback with true', function() {
|
||||
return this.callback.calledWith(null, true).should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
return it("should return the callback with true", function() {
|
||||
return this.callback.calledWith(null, true).should.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('deleteLock', function() {
|
||||
return beforeEach(function() {
|
||||
beforeEach(function() {
|
||||
this.rclient.del = sinon.stub().callsArg(1)
|
||||
return this.LockManager.deleteLock(this.key, this.callback)
|
||||
})
|
||||
|
||||
describe("deleteLock", function() { return beforeEach(function() {
|
||||
beforeEach(function() {
|
||||
this.rclient.del = sinon.stub().callsArg(1);
|
||||
return this.LockManager.deleteLock(this.key, this.callback);
|
||||
});
|
||||
it('should delete the lock in redis', function() {
|
||||
return this.rclient.del.calledWith(key).should.equal(true)
|
||||
})
|
||||
|
||||
it("should delete the lock in redis", function() {
|
||||
return this.rclient.del
|
||||
.calledWith(key)
|
||||
.should.equal(true);
|
||||
});
|
||||
return it('should call the callback', function() {
|
||||
return this.callback.called.should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
return it("should call the callback", function() {
|
||||
return this.callback.called.should.equal(true);
|
||||
});
|
||||
}); }
|
||||
);
|
||||
describe('getLock', function() {
|
||||
describe('when the lock is not taken', function() {
|
||||
beforeEach(function(done) {
|
||||
this.LockManager.tryLock = sinon.stub().callsArgWith(1, null, true)
|
||||
return this.LockManager.getLock(this.key, (...args) => {
|
||||
this.callback(...Array.from(args || []))
|
||||
return done()
|
||||
})
|
||||
})
|
||||
|
||||
describe("getLock", function() {
|
||||
describe("when the lock is not taken", function() {
|
||||
beforeEach(function(done) {
|
||||
this.LockManager.tryLock = sinon.stub().callsArgWith(1, null, true);
|
||||
return this.LockManager.getLock(this.key, (...args) => {
|
||||
this.callback(...Array.from(args || []));
|
||||
return done();
|
||||
});
|
||||
});
|
||||
it('should try to get the lock', function() {
|
||||
return this.LockManager.tryLock.calledWith(this.key).should.equal(true)
|
||||
})
|
||||
|
||||
it("should try to get the lock", function() {
|
||||
return this.LockManager.tryLock
|
||||
.calledWith(this.key)
|
||||
.should.equal(true);
|
||||
});
|
||||
it('should only need to try once', function() {
|
||||
return this.LockManager.tryLock.callCount.should.equal(1)
|
||||
})
|
||||
|
||||
it("should only need to try once", function() {
|
||||
return this.LockManager.tryLock.callCount.should.equal(1);
|
||||
});
|
||||
return it('should return the callback', function() {
|
||||
return this.callback.calledWith(null).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
return it("should return the callback", function() {
|
||||
return this.callback.calledWith(null).should.equal(true);
|
||||
});
|
||||
});
|
||||
describe('when the lock is initially set', function() {
|
||||
beforeEach(function(done) {
|
||||
const startTime = Date.now()
|
||||
this.LockManager.LOCK_TEST_INTERVAL = 5
|
||||
this.LockManager.tryLock = function(doc_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, isFree) {}
|
||||
}
|
||||
if (Date.now() - startTime < 100) {
|
||||
return callback(null, false)
|
||||
} else {
|
||||
return callback(null, true)
|
||||
}
|
||||
}
|
||||
sinon.spy(this.LockManager, 'tryLock')
|
||||
|
||||
describe("when the lock is initially set", function() {
|
||||
beforeEach(function(done) {
|
||||
const startTime = Date.now();
|
||||
this.LockManager.LOCK_TEST_INTERVAL = 5;
|
||||
this.LockManager.tryLock = function(doc_id, callback) {
|
||||
if (callback == null) { callback = function(error, isFree) {}; }
|
||||
if ((Date.now() - startTime) < 100) {
|
||||
return callback(null, false);
|
||||
} else {
|
||||
return callback(null, true);
|
||||
}
|
||||
};
|
||||
sinon.spy(this.LockManager, "tryLock");
|
||||
return this.LockManager.getLock(this.key, (...args) => {
|
||||
this.callback(...Array.from(args || []))
|
||||
return done()
|
||||
})
|
||||
})
|
||||
|
||||
return this.LockManager.getLock(this.key, (...args) => {
|
||||
this.callback(...Array.from(args || []));
|
||||
return done();
|
||||
});
|
||||
});
|
||||
it('should call tryLock multiple times until free', function() {
|
||||
return (this.LockManager.tryLock.callCount > 1).should.equal(true)
|
||||
})
|
||||
|
||||
it("should call tryLock multiple times until free", function() {
|
||||
return (this.LockManager.tryLock.callCount > 1).should.equal(true);
|
||||
});
|
||||
return it('should return the callback', function() {
|
||||
return this.callback.calledWith(null).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
return it("should return the callback", function() {
|
||||
return this.callback.calledWith(null).should.equal(true);
|
||||
});
|
||||
});
|
||||
return describe('when the lock times out', function() {
|
||||
beforeEach(function(done) {
|
||||
const time = Date.now()
|
||||
this.LockManager.MAX_LOCK_WAIT_TIME = 5
|
||||
this.LockManager.tryLock = sinon.stub().callsArgWith(1, null, false)
|
||||
return this.LockManager.getLock(this.key, (...args) => {
|
||||
this.callback(...Array.from(args || []))
|
||||
return done()
|
||||
})
|
||||
})
|
||||
|
||||
return describe("when the lock times out", function() {
|
||||
beforeEach(function(done) {
|
||||
const time = Date.now();
|
||||
this.LockManager.MAX_LOCK_WAIT_TIME = 5;
|
||||
this.LockManager.tryLock = sinon.stub().callsArgWith(1, null, false);
|
||||
return this.LockManager.getLock(this.key, (...args) => {
|
||||
this.callback(...Array.from(args || []));
|
||||
return done();
|
||||
});
|
||||
});
|
||||
return it('should return the callback with an error', function() {
|
||||
return this.callback
|
||||
.calledWith(sinon.match.instanceOf(Error))
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
return it("should return the callback with an error", function() {
|
||||
return this.callback.calledWith(sinon.match.instanceOf(Error)).should.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
return describe('runWithLock', function() {
|
||||
describe('with successful run', function() {
|
||||
beforeEach(function() {
|
||||
this.runner = function(releaseLock) {
|
||||
if (releaseLock == null) {
|
||||
releaseLock = function(error) {}
|
||||
}
|
||||
return releaseLock()
|
||||
}
|
||||
sinon.spy(this, 'runner')
|
||||
this.LockManager.getLock = sinon.stub().callsArg(1)
|
||||
this.LockManager.releaseLock = sinon.stub().callsArg(2)
|
||||
return this.LockManager.runWithLock(
|
||||
this.key,
|
||||
this.runner,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
return describe("runWithLock", function() {
|
||||
describe("with successful run", function() {
|
||||
beforeEach(function() {
|
||||
this.runner = function(releaseLock) {
|
||||
if (releaseLock == null) { releaseLock = function(error) {}; }
|
||||
return releaseLock();
|
||||
};
|
||||
sinon.spy(this, "runner");
|
||||
this.LockManager.getLock = sinon.stub().callsArg(1);
|
||||
this.LockManager.releaseLock = sinon.stub().callsArg(2);
|
||||
return this.LockManager.runWithLock(this.key, this.runner, this.callback);
|
||||
});
|
||||
it('should get the lock', function() {
|
||||
return this.LockManager.getLock.calledWith(this.key).should.equal(true)
|
||||
})
|
||||
|
||||
it("should get the lock", function() {
|
||||
return this.LockManager.getLock
|
||||
.calledWith(this.key)
|
||||
.should.equal(true);
|
||||
});
|
||||
it('should run the passed function', function() {
|
||||
return this.runner.called.should.equal(true)
|
||||
})
|
||||
|
||||
it("should run the passed function", function() {
|
||||
return this.runner.called.should.equal(true);
|
||||
});
|
||||
it('should release the lock', function() {
|
||||
return this.LockManager.releaseLock
|
||||
.calledWith(this.key)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it("should release the lock", function() {
|
||||
return this.LockManager.releaseLock
|
||||
.calledWith(this.key)
|
||||
.should.equal(true);
|
||||
});
|
||||
return it('should call the callback', function() {
|
||||
return this.callback.called.should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
return it("should call the callback", function() {
|
||||
return this.callback.called.should.equal(true);
|
||||
});
|
||||
});
|
||||
describe('when the runner function returns an error', function() {
|
||||
beforeEach(function() {
|
||||
this.error = new Error('oops')
|
||||
this.runner = releaseLock => {
|
||||
if (releaseLock == null) {
|
||||
releaseLock = function(error) {}
|
||||
}
|
||||
return releaseLock(this.error)
|
||||
}
|
||||
sinon.spy(this, 'runner')
|
||||
this.LockManager.getLock = sinon.stub().callsArg(1)
|
||||
this.LockManager.releaseLock = sinon.stub().callsArg(2)
|
||||
return this.LockManager.runWithLock(
|
||||
this.key,
|
||||
this.runner,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
describe("when the runner function returns an error", function() {
|
||||
beforeEach(function() {
|
||||
this.error = new Error("oops");
|
||||
this.runner = releaseLock => {
|
||||
if (releaseLock == null) { releaseLock = function(error) {}; }
|
||||
return releaseLock(this.error);
|
||||
};
|
||||
sinon.spy(this, "runner");
|
||||
this.LockManager.getLock = sinon.stub().callsArg(1);
|
||||
this.LockManager.releaseLock = sinon.stub().callsArg(2);
|
||||
return this.LockManager.runWithLock(this.key, this.runner, this.callback);
|
||||
});
|
||||
it('should release the lock', function() {
|
||||
return this.LockManager.releaseLock
|
||||
.calledWith(this.key)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it("should release the lock", function() {
|
||||
return this.LockManager.releaseLock
|
||||
.calledWith(this.key)
|
||||
.should.equal(true);
|
||||
});
|
||||
return it('should call the callback with the error', function() {
|
||||
return this.callback.calledWith(this.error).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
return it("should call the callback with the error", function() {
|
||||
return this.callback.calledWith(this.error).should.equal(true);
|
||||
});
|
||||
});
|
||||
return describe('releaseLock', function() {
|
||||
describe('when the lock is current', function() {
|
||||
beforeEach(function() {
|
||||
this.rclient.eval = sinon.stub().yields(null, 1)
|
||||
return this.LockManager.releaseLock(
|
||||
this.key,
|
||||
this.lockValue,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
return describe("releaseLock", function() {
|
||||
describe("when the lock is current", function() {
|
||||
beforeEach(function() {
|
||||
this.rclient.eval = sinon.stub().yields(null, 1);
|
||||
return this.LockManager.releaseLock(this.key, this.lockValue, this.callback);
|
||||
});
|
||||
it('should clear the data from redis', function() {
|
||||
return this.rclient.eval
|
||||
.calledWith(
|
||||
this.LockManager.unlockScript,
|
||||
1,
|
||||
this.key,
|
||||
this.lockValue
|
||||
)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should clear the data from redis', function() {
|
||||
return this.rclient.eval.calledWith(this.LockManager.unlockScript, 1, this.key, this.lockValue).should.equal(true);
|
||||
});
|
||||
return it('should call the callback', function() {
|
||||
return this.callback.called.should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
return it('should call the callback', function() {
|
||||
return this.callback.called.should.equal(true);
|
||||
});
|
||||
});
|
||||
|
||||
return describe("when the lock has expired", function() {
|
||||
beforeEach(function() {
|
||||
this.rclient.eval = sinon.stub().yields(null, 0);
|
||||
return this.LockManager.releaseLock(this.key, this.lockValue, this.callback);
|
||||
});
|
||||
|
||||
return it('should return an error if the lock has expired', function() {
|
||||
return this.callback.calledWith(sinon.match.has('message', "tried to release timed out lock")).should.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
return describe('when the lock has expired', function() {
|
||||
beforeEach(function() {
|
||||
this.rclient.eval = sinon.stub().yields(null, 0)
|
||||
return this.LockManager.releaseLock(
|
||||
this.key,
|
||||
this.lockValue,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
return it('should return an error if the lock has expired', function() {
|
||||
return this.callback
|
||||
.calledWith(
|
||||
sinon.match.has('message', 'tried to release timed out lock')
|
||||
)
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -9,195 +9,237 @@
|
|||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
const sinon = require('sinon');
|
||||
const chai = require('chai');
|
||||
const should = chai.should();
|
||||
const { expect } = chai;
|
||||
const modulePath = "../../../../app/js/MongoManager.js";
|
||||
const packModulePath = "../../../../app/js/PackManager.js";
|
||||
const SandboxedModule = require('sandboxed-module');
|
||||
const {ObjectId} = require("mongojs");
|
||||
const tk = require("timekeeper");
|
||||
const sinon = require('sinon')
|
||||
const chai = require('chai')
|
||||
const should = chai.should()
|
||||
const { expect } = chai
|
||||
const modulePath = '../../../../app/js/MongoManager.js'
|
||||
const packModulePath = '../../../../app/js/PackManager.js'
|
||||
const SandboxedModule = require('sandboxed-module')
|
||||
const { ObjectId } = require('mongojs')
|
||||
const tk = require('timekeeper')
|
||||
|
||||
describe("MongoManager", function() {
|
||||
beforeEach(function() {
|
||||
tk.freeze(new Date());
|
||||
this.MongoManager = SandboxedModule.require(modulePath, { requires: {
|
||||
"./mongojs" : { db: (this.db = {}), ObjectId },
|
||||
"./PackManager" : (this.PackManager = {}),
|
||||
'metrics-sharelatex': {timeAsyncMethod(){}},
|
||||
'logger-sharelatex': {log(){}}
|
||||
}
|
||||
});
|
||||
this.callback = sinon.stub();
|
||||
this.doc_id = ObjectId().toString();
|
||||
return this.project_id = ObjectId().toString();
|
||||
});
|
||||
describe('MongoManager', function() {
|
||||
beforeEach(function() {
|
||||
tk.freeze(new Date())
|
||||
this.MongoManager = SandboxedModule.require(modulePath, {
|
||||
requires: {
|
||||
'./mongojs': { db: (this.db = {}), ObjectId },
|
||||
'./PackManager': (this.PackManager = {}),
|
||||
'metrics-sharelatex': { timeAsyncMethod() {} },
|
||||
'logger-sharelatex': { log() {} }
|
||||
}
|
||||
})
|
||||
this.callback = sinon.stub()
|
||||
this.doc_id = ObjectId().toString()
|
||||
return (this.project_id = ObjectId().toString())
|
||||
})
|
||||
|
||||
afterEach(function() { return tk.reset(); });
|
||||
afterEach(function() {
|
||||
return tk.reset()
|
||||
})
|
||||
|
||||
describe("getLastCompressedUpdate", function() {
|
||||
beforeEach(function() {
|
||||
this.update = "mock-update";
|
||||
this.db.docHistory = {};
|
||||
this.db.docHistory.find = sinon.stub().returns(this.db.docHistory);
|
||||
this.db.docHistory.findOne = sinon.stub().returns(this.db.docHistory);
|
||||
this.db.docHistory.sort = sinon.stub().returns(this.db.docHistory);
|
||||
this.db.docHistory.limit = sinon.stub().returns(this.db.docHistory);
|
||||
this.db.docHistory.toArray = sinon.stub().callsArgWith(0, null, [this.update]);
|
||||
describe('getLastCompressedUpdate', function() {
|
||||
beforeEach(function() {
|
||||
this.update = 'mock-update'
|
||||
this.db.docHistory = {}
|
||||
this.db.docHistory.find = sinon.stub().returns(this.db.docHistory)
|
||||
this.db.docHistory.findOne = sinon.stub().returns(this.db.docHistory)
|
||||
this.db.docHistory.sort = sinon.stub().returns(this.db.docHistory)
|
||||
this.db.docHistory.limit = sinon.stub().returns(this.db.docHistory)
|
||||
this.db.docHistory.toArray = sinon
|
||||
.stub()
|
||||
.callsArgWith(0, null, [this.update])
|
||||
|
||||
return this.MongoManager.getLastCompressedUpdate(this.doc_id, this.callback);
|
||||
});
|
||||
return this.MongoManager.getLastCompressedUpdate(
|
||||
this.doc_id,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
it("should find the updates for the doc", function() {
|
||||
return this.db.docHistory.find
|
||||
.calledWith({doc_id: ObjectId(this.doc_id)})
|
||||
.should.equal(true);
|
||||
});
|
||||
it('should find the updates for the doc', function() {
|
||||
return this.db.docHistory.find
|
||||
.calledWith({ doc_id: ObjectId(this.doc_id) })
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it("should limit to one result", function() {
|
||||
return this.db.docHistory.limit
|
||||
.calledWith(1)
|
||||
.should.equal(true);
|
||||
});
|
||||
it('should limit to one result', function() {
|
||||
return this.db.docHistory.limit.calledWith(1).should.equal(true)
|
||||
})
|
||||
|
||||
it("should sort in descending version order", function() {
|
||||
return this.db.docHistory.sort
|
||||
.calledWith({v: -1})
|
||||
.should.equal(true);
|
||||
});
|
||||
it('should sort in descending version order', function() {
|
||||
return this.db.docHistory.sort.calledWith({ v: -1 }).should.equal(true)
|
||||
})
|
||||
|
||||
return it("should call the call back with the update", function() {
|
||||
return this.callback.calledWith(null, this.update).should.equal(true);
|
||||
});
|
||||
});
|
||||
return it('should call the call back with the update', function() {
|
||||
return this.callback.calledWith(null, this.update).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('peekLastCompressedUpdate', function() {
|
||||
describe('when there is no last update', function() {
|
||||
beforeEach(function() {
|
||||
this.PackManager.getLastPackFromIndex = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, null)
|
||||
this.MongoManager.getLastCompressedUpdate = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, null)
|
||||
return this.MongoManager.peekLastCompressedUpdate(
|
||||
this.doc_id,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
describe("peekLastCompressedUpdate", function() {
|
||||
describe("when there is no last update", function() {
|
||||
beforeEach(function() {
|
||||
this.PackManager.getLastPackFromIndex = sinon.stub().callsArgWith(1, null, null);
|
||||
this.MongoManager.getLastCompressedUpdate = sinon.stub().callsArgWith(1, null, null);
|
||||
return this.MongoManager.peekLastCompressedUpdate(this.doc_id, this.callback);
|
||||
});
|
||||
it('should get the last update', function() {
|
||||
return this.MongoManager.getLastCompressedUpdate
|
||||
.calledWith(this.doc_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it("should get the last update", function() {
|
||||
return this.MongoManager.getLastCompressedUpdate
|
||||
.calledWith(this.doc_id)
|
||||
.should.equal(true);
|
||||
});
|
||||
return it('should call the callback with no update', function() {
|
||||
return this.callback.calledWith(null, null).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
return it("should call the callback with no update", function() {
|
||||
return this.callback.calledWith(null, null).should.equal(true);
|
||||
});
|
||||
});
|
||||
describe('when there is an update', function() {
|
||||
beforeEach(function() {
|
||||
this.update = { _id: Object() }
|
||||
this.MongoManager.getLastCompressedUpdate = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, this.update)
|
||||
return this.MongoManager.peekLastCompressedUpdate(
|
||||
this.doc_id,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
describe("when there is an update", function() {
|
||||
beforeEach(function() {
|
||||
this.update = { _id: Object() };
|
||||
this.MongoManager.getLastCompressedUpdate = sinon.stub().callsArgWith(1, null, this.update);
|
||||
return this.MongoManager.peekLastCompressedUpdate(this.doc_id, this.callback);
|
||||
});
|
||||
it('should get the last update', function() {
|
||||
return this.MongoManager.getLastCompressedUpdate
|
||||
.calledWith(this.doc_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it("should get the last update", function() {
|
||||
return this.MongoManager.getLastCompressedUpdate
|
||||
.calledWith(this.doc_id)
|
||||
.should.equal(true);
|
||||
});
|
||||
return it('should call the callback with the update', function() {
|
||||
return this.callback.calledWith(null, this.update).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
return it("should call the callback with the update", function() {
|
||||
return this.callback.calledWith(null, this.update).should.equal(true);
|
||||
});
|
||||
});
|
||||
return describe('when there is a last update in S3', function() {
|
||||
beforeEach(function() {
|
||||
this.update = { _id: Object(), v: 12345, v_end: 12345, inS3: true }
|
||||
this.PackManager.getLastPackFromIndex = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, this.update)
|
||||
this.MongoManager.getLastCompressedUpdate = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null)
|
||||
return this.MongoManager.peekLastCompressedUpdate(
|
||||
this.doc_id,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
return describe("when there is a last update in S3", function() {
|
||||
beforeEach(function() {
|
||||
this.update = { _id: Object(), v: 12345, v_end: 12345, inS3:true};
|
||||
this.PackManager.getLastPackFromIndex = sinon.stub().callsArgWith(1, null, this.update);
|
||||
this.MongoManager.getLastCompressedUpdate = sinon.stub().callsArgWith(1, null);
|
||||
return this.MongoManager.peekLastCompressedUpdate(this.doc_id, this.callback);
|
||||
});
|
||||
it('should get the last update', function() {
|
||||
return this.MongoManager.getLastCompressedUpdate
|
||||
.calledWith(this.doc_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it("should get the last update", function() {
|
||||
return this.MongoManager.getLastCompressedUpdate
|
||||
.calledWith(this.doc_id)
|
||||
.should.equal(true);
|
||||
});
|
||||
return it('should call the callback with a null update and the correct version', function() {
|
||||
return this.callback
|
||||
.calledWith(null, null, this.update.v_end)
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
return it("should call the callback with a null update and the correct version", function() {
|
||||
return this.callback.calledWith(null, null, this.update.v_end).should.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('backportProjectId', function() {
|
||||
beforeEach(function() {
|
||||
this.db.docHistory = { update: sinon.stub().callsArg(3) }
|
||||
return this.MongoManager.backportProjectId(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
it("should insert the project_id into all entries for the doc_id which don't have it set", function() {
|
||||
return this.db.docHistory.update
|
||||
.calledWith(
|
||||
{
|
||||
doc_id: ObjectId(this.doc_id),
|
||||
project_id: { $exists: false }
|
||||
},
|
||||
{
|
||||
$set: { project_id: ObjectId(this.project_id) }
|
||||
},
|
||||
{
|
||||
multi: true
|
||||
}
|
||||
)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
describe("backportProjectId", function() {
|
||||
beforeEach(function() {
|
||||
this.db.docHistory =
|
||||
{update: sinon.stub().callsArg(3)};
|
||||
return this.MongoManager.backportProjectId(this.project_id, this.doc_id, this.callback);
|
||||
});
|
||||
return it('should call the callback', function() {
|
||||
return this.callback.called.should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
it("should insert the project_id into all entries for the doc_id which don't have it set", function() {
|
||||
return this.db.docHistory.update
|
||||
.calledWith({
|
||||
doc_id: ObjectId(this.doc_id),
|
||||
project_id: { $exists: false }
|
||||
}, {
|
||||
$set: { project_id: ObjectId(this.project_id) }
|
||||
}, {
|
||||
multi: true
|
||||
})
|
||||
.should.equal(true);
|
||||
});
|
||||
describe('getProjectMetaData', function() {
|
||||
beforeEach(function() {
|
||||
this.metadata = { mock: 'metadata' }
|
||||
this.db.projectHistoryMetaData = {
|
||||
find: sinon.stub().callsArgWith(1, null, [this.metadata])
|
||||
}
|
||||
return this.MongoManager.getProjectMetaData(
|
||||
this.project_id,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
return it("should call the callback", function() {
|
||||
return this.callback.called.should.equal(true);
|
||||
});
|
||||
});
|
||||
it('should look up the meta data in the db', function() {
|
||||
return this.db.projectHistoryMetaData.find
|
||||
.calledWith({ project_id: ObjectId(this.project_id) })
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
describe("getProjectMetaData", function() {
|
||||
beforeEach(function() {
|
||||
this.metadata = { "mock": "metadata" };
|
||||
this.db.projectHistoryMetaData =
|
||||
{find: sinon.stub().callsArgWith(1, null, [this.metadata])};
|
||||
return this.MongoManager.getProjectMetaData(this.project_id, this.callback);
|
||||
});
|
||||
return it('should return the metadata', function() {
|
||||
return this.callback.calledWith(null, this.metadata).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
it("should look up the meta data in the db", function() {
|
||||
return this.db.projectHistoryMetaData.find
|
||||
.calledWith({ project_id: ObjectId(this.project_id) })
|
||||
.should.equal(true);
|
||||
});
|
||||
return describe('setProjectMetaData', function() {
|
||||
beforeEach(function() {
|
||||
this.metadata = { mock: 'metadata' }
|
||||
this.db.projectHistoryMetaData = {
|
||||
update: sinon.stub().callsArgWith(3, null, [this.metadata])
|
||||
}
|
||||
return this.MongoManager.setProjectMetaData(
|
||||
this.project_id,
|
||||
this.metadata,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
return it("should return the metadata", function() {
|
||||
return this.callback.calledWith(null, this.metadata).should.equal(true);
|
||||
});
|
||||
});
|
||||
|
||||
return describe("setProjectMetaData", function() {
|
||||
beforeEach(function() {
|
||||
this.metadata = { "mock": "metadata" };
|
||||
this.db.projectHistoryMetaData =
|
||||
{update: sinon.stub().callsArgWith(3, null, [this.metadata])};
|
||||
return this.MongoManager.setProjectMetaData(this.project_id, this.metadata, this.callback);
|
||||
});
|
||||
|
||||
it("should upsert the metadata into the DB", function() {
|
||||
return this.db.projectHistoryMetaData.update
|
||||
.calledWith({
|
||||
project_id: ObjectId(this.project_id)
|
||||
}, {
|
||||
$set: this.metadata
|
||||
}, {
|
||||
upsert: true
|
||||
})
|
||||
.should.equal(true);
|
||||
});
|
||||
|
||||
return it("should call the callback", function() {
|
||||
return this.callback.called.should.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
it('should upsert the metadata into the DB', function() {
|
||||
return this.db.projectHistoryMetaData.update
|
||||
.calledWith(
|
||||
{
|
||||
project_id: ObjectId(this.project_id)
|
||||
},
|
||||
{
|
||||
$set: this.metadata
|
||||
},
|
||||
{
|
||||
upsert: true
|
||||
}
|
||||
)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
return it('should call the callback', function() {
|
||||
return this.callback.called.should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -11,118 +11,156 @@
|
|||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
const sinon = require('sinon');
|
||||
const chai = require('chai');
|
||||
const should = chai.should();
|
||||
const { expect } = chai;
|
||||
const modulePath = "../../../../app/js/RedisManager.js";
|
||||
const SandboxedModule = require('sandboxed-module');
|
||||
const sinon = require('sinon')
|
||||
const chai = require('chai')
|
||||
const should = chai.should()
|
||||
const { expect } = chai
|
||||
const modulePath = '../../../../app/js/RedisManager.js'
|
||||
const SandboxedModule = require('sandboxed-module')
|
||||
|
||||
describe("RedisManager", function() {
|
||||
beforeEach(function() {
|
||||
this.RedisManager = SandboxedModule.require(modulePath, { requires: {
|
||||
"redis-sharelatex" : {
|
||||
createClient: () => { return this.rclient = {
|
||||
auth: sinon.stub(),
|
||||
multi: () => this.rclient
|
||||
}; }
|
||||
},
|
||||
"settings-sharelatex": {
|
||||
redis: {
|
||||
history: {
|
||||
key_schema: {
|
||||
uncompressedHistoryOps({doc_id}) { return `UncompressedHistoryOps:${doc_id}`; },
|
||||
docsWithHistoryOps({project_id}) { return `DocsWithHistoryOps:${project_id}`; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
this.doc_id = "doc-id-123";
|
||||
this.project_id = "project-id-123";
|
||||
this.batchSize = 100;
|
||||
return this.callback = sinon.stub();
|
||||
});
|
||||
describe('RedisManager', function() {
|
||||
beforeEach(function() {
|
||||
this.RedisManager = SandboxedModule.require(modulePath, {
|
||||
requires: {
|
||||
'redis-sharelatex': {
|
||||
createClient: () => {
|
||||
return (this.rclient = {
|
||||
auth: sinon.stub(),
|
||||
multi: () => this.rclient
|
||||
})
|
||||
}
|
||||
},
|
||||
'settings-sharelatex': {
|
||||
redis: {
|
||||
history: {
|
||||
key_schema: {
|
||||
uncompressedHistoryOps({ doc_id }) {
|
||||
return `UncompressedHistoryOps:${doc_id}`
|
||||
},
|
||||
docsWithHistoryOps({ project_id }) {
|
||||
return `DocsWithHistoryOps:${project_id}`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
this.doc_id = 'doc-id-123'
|
||||
this.project_id = 'project-id-123'
|
||||
this.batchSize = 100
|
||||
return (this.callback = sinon.stub())
|
||||
})
|
||||
|
||||
describe("getOldestDocUpdates", function() {
|
||||
beforeEach(function() {
|
||||
this.rawUpdates = [ {v: 42, op: "mock-op-42"}, { v: 45, op: "mock-op-45" }];
|
||||
this.jsonUpdates = (Array.from(this.rawUpdates).map((update) => JSON.stringify(update)));
|
||||
this.rclient.lrange = sinon.stub().callsArgWith(3, null, this.jsonUpdates);
|
||||
return this.RedisManager.getOldestDocUpdates(this.doc_id, this.batchSize, this.callback);
|
||||
});
|
||||
describe('getOldestDocUpdates', function() {
|
||||
beforeEach(function() {
|
||||
this.rawUpdates = [
|
||||
{ v: 42, op: 'mock-op-42' },
|
||||
{ v: 45, op: 'mock-op-45' }
|
||||
]
|
||||
this.jsonUpdates = Array.from(this.rawUpdates).map(update =>
|
||||
JSON.stringify(update)
|
||||
)
|
||||
this.rclient.lrange = sinon.stub().callsArgWith(3, null, this.jsonUpdates)
|
||||
return this.RedisManager.getOldestDocUpdates(
|
||||
this.doc_id,
|
||||
this.batchSize,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
it("should read the updates from redis", function() {
|
||||
return this.rclient.lrange
|
||||
.calledWith(`UncompressedHistoryOps:${this.doc_id}`, 0, this.batchSize - 1)
|
||||
.should.equal(true);
|
||||
});
|
||||
it('should read the updates from redis', function() {
|
||||
return this.rclient.lrange
|
||||
.calledWith(
|
||||
`UncompressedHistoryOps:${this.doc_id}`,
|
||||
0,
|
||||
this.batchSize - 1
|
||||
)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it("should call the callback with the unparsed ops", function() {
|
||||
return this.callback.calledWith(null, this.jsonUpdates).should.equal(true);
|
||||
});
|
||||
it('should call the callback with the unparsed ops', function() {
|
||||
return this.callback.calledWith(null, this.jsonUpdates).should.equal(true)
|
||||
})
|
||||
|
||||
describe('expandDocUpdates', function() {
|
||||
beforeEach(function() {
|
||||
return this.RedisManager.expandDocUpdates(
|
||||
this.jsonUpdates,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
describe("expandDocUpdates", function() {
|
||||
beforeEach(function() {
|
||||
return this.RedisManager.expandDocUpdates(this.jsonUpdates, this.callback);
|
||||
});
|
||||
return it('should call the callback with the parsed ops', function() {
|
||||
return this.callback
|
||||
.calledWith(null, this.rawUpdates)
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
return it("should call the callback with the parsed ops", function() {
|
||||
return this.callback.calledWith(null, this.rawUpdates).should.equal(true);
|
||||
});
|
||||
});
|
||||
return describe('deleteAppliedDocUpdates', function() {
|
||||
beforeEach(function() {
|
||||
this.rclient.lrem = sinon.stub()
|
||||
this.rclient.srem = sinon.stub()
|
||||
this.rclient.exec = sinon.stub().callsArgWith(0)
|
||||
return this.RedisManager.deleteAppliedDocUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.jsonUpdates,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
it('should delete the first update from redis', function() {
|
||||
return this.rclient.lrem
|
||||
.calledWith(
|
||||
`UncompressedHistoryOps:${this.doc_id}`,
|
||||
1,
|
||||
this.jsonUpdates[0]
|
||||
)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
return describe("deleteAppliedDocUpdates", function() {
|
||||
beforeEach(function() {
|
||||
this.rclient.lrem = sinon.stub();
|
||||
this.rclient.srem = sinon.stub();
|
||||
this.rclient.exec = sinon.stub().callsArgWith(0);
|
||||
return this.RedisManager.deleteAppliedDocUpdates(this.project_id, this.doc_id, this.jsonUpdates, this.callback);
|
||||
});
|
||||
it('should delete the second update from redis', function() {
|
||||
return this.rclient.lrem
|
||||
.calledWith(
|
||||
`UncompressedHistoryOps:${this.doc_id}`,
|
||||
1,
|
||||
this.jsonUpdates[1]
|
||||
)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it("should delete the first update from redis", function() {
|
||||
return this.rclient.lrem
|
||||
.calledWith(`UncompressedHistoryOps:${this.doc_id}`, 1, this.jsonUpdates[0])
|
||||
.should.equal(true);
|
||||
});
|
||||
it('should delete the doc from the set of docs with history ops', function() {
|
||||
return this.rclient.srem
|
||||
.calledWith(`DocsWithHistoryOps:${this.project_id}`, this.doc_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it("should delete the second update from redis", function() {
|
||||
return this.rclient.lrem
|
||||
.calledWith(`UncompressedHistoryOps:${this.doc_id}`, 1, this.jsonUpdates[1])
|
||||
.should.equal(true);
|
||||
});
|
||||
return it('should call the callback ', function() {
|
||||
return this.callback.called.should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it("should delete the doc from the set of docs with history ops", function() {
|
||||
return this.rclient.srem
|
||||
.calledWith(`DocsWithHistoryOps:${this.project_id}`, this.doc_id)
|
||||
.should.equal(true);
|
||||
});
|
||||
return describe('getDocIdsWithHistoryOps', function() {
|
||||
beforeEach(function() {
|
||||
this.doc_ids = ['mock-id-1', 'mock-id-2']
|
||||
this.rclient.smembers = sinon.stub().callsArgWith(1, null, this.doc_ids)
|
||||
return this.RedisManager.getDocIdsWithHistoryOps(
|
||||
this.project_id,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
return it("should call the callback ", function() {
|
||||
return this.callback.called.should.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
it('should read the doc_ids from redis', function() {
|
||||
return this.rclient.smembers
|
||||
.calledWith(`DocsWithHistoryOps:${this.project_id}`)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
return describe("getDocIdsWithHistoryOps", function() {
|
||||
beforeEach(function() {
|
||||
this.doc_ids = ["mock-id-1", "mock-id-2"];
|
||||
this.rclient.smembers = sinon.stub().callsArgWith(1, null, this.doc_ids);
|
||||
return this.RedisManager.getDocIdsWithHistoryOps(this.project_id, this.callback);
|
||||
});
|
||||
|
||||
it("should read the doc_ids from redis", function() {
|
||||
return this.rclient.smembers
|
||||
.calledWith(`DocsWithHistoryOps:${this.project_id}`)
|
||||
.should.equal(true);
|
||||
});
|
||||
|
||||
return it("should call the callback with the doc_ids", function() {
|
||||
return this.callback.calledWith(null, this.doc_ids).should.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
return it('should call the callback with the doc_ids', function() {
|
||||
return this.callback.calledWith(null, this.doc_ids).should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -9,51 +9,62 @@
|
|||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
const sinon = require('sinon');
|
||||
const chai = require('chai');
|
||||
const should = chai.should();
|
||||
const { expect } = chai;
|
||||
const modulePath = "../../../../app/js/RestoreManager.js";
|
||||
const SandboxedModule = require('sandboxed-module');
|
||||
const sinon = require('sinon')
|
||||
const chai = require('chai')
|
||||
const should = chai.should()
|
||||
const { expect } = chai
|
||||
const modulePath = '../../../../app/js/RestoreManager.js'
|
||||
const SandboxedModule = require('sandboxed-module')
|
||||
|
||||
describe("RestoreManager", function() {
|
||||
beforeEach(function() {
|
||||
this.RestoreManager = SandboxedModule.require(modulePath, { requires: {
|
||||
"logger-sharelatex": (this.logger = { log: sinon.stub(), error: sinon.stub() }),
|
||||
"./DocumentUpdaterManager": (this.DocumentUpdaterManager = {}),
|
||||
"./DiffManager": (this.DiffManager = {})
|
||||
}
|
||||
});
|
||||
this.callback = sinon.stub();
|
||||
this.project_id = "mock-project-id";
|
||||
this.doc_id = "mock-doc-id";
|
||||
this.user_id = "mock-user-id";
|
||||
return this.version = 42;
|
||||
});
|
||||
describe('RestoreManager', function() {
|
||||
beforeEach(function() {
|
||||
this.RestoreManager = SandboxedModule.require(modulePath, {
|
||||
requires: {
|
||||
'logger-sharelatex': (this.logger = {
|
||||
log: sinon.stub(),
|
||||
error: sinon.stub()
|
||||
}),
|
||||
'./DocumentUpdaterManager': (this.DocumentUpdaterManager = {}),
|
||||
'./DiffManager': (this.DiffManager = {})
|
||||
}
|
||||
})
|
||||
this.callback = sinon.stub()
|
||||
this.project_id = 'mock-project-id'
|
||||
this.doc_id = 'mock-doc-id'
|
||||
this.user_id = 'mock-user-id'
|
||||
return (this.version = 42)
|
||||
})
|
||||
|
||||
return describe("restoreToBeforeVersion", function() {
|
||||
beforeEach(function() {
|
||||
this.content = "mock content";
|
||||
this.DocumentUpdaterManager.setDocument = sinon.stub().callsArg(4);
|
||||
this.DiffManager.getDocumentBeforeVersion = sinon.stub().callsArgWith(3, null, this.content);
|
||||
return this.RestoreManager.restoreToBeforeVersion(this.project_id, this.doc_id, this.version, this.user_id, this.callback);
|
||||
});
|
||||
return describe('restoreToBeforeVersion', function() {
|
||||
beforeEach(function() {
|
||||
this.content = 'mock content'
|
||||
this.DocumentUpdaterManager.setDocument = sinon.stub().callsArg(4)
|
||||
this.DiffManager.getDocumentBeforeVersion = sinon
|
||||
.stub()
|
||||
.callsArgWith(3, null, this.content)
|
||||
return this.RestoreManager.restoreToBeforeVersion(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.version,
|
||||
this.user_id,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
it("should get the content before the requested version", function() {
|
||||
return this.DiffManager.getDocumentBeforeVersion
|
||||
.calledWith(this.project_id, this.doc_id, this.version)
|
||||
.should.equal(true);
|
||||
});
|
||||
it('should get the content before the requested version', function() {
|
||||
return this.DiffManager.getDocumentBeforeVersion
|
||||
.calledWith(this.project_id, this.doc_id, this.version)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it("should set the document in the document updater", function() {
|
||||
return this.DocumentUpdaterManager.setDocument
|
||||
.calledWith(this.project_id, this.doc_id, this.content, this.user_id)
|
||||
.should.equal(true);
|
||||
});
|
||||
it('should set the document in the document updater', function() {
|
||||
return this.DocumentUpdaterManager.setDocument
|
||||
.calledWith(this.project_id, this.doc_id, this.content, this.user_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
return it("should call the callback", function() {
|
||||
return this.callback.called.should.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return it('should call the callback', function() {
|
||||
return this.callback.called.should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -9,157 +9,180 @@
|
|||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
const sinon = require('sinon');
|
||||
const chai = require('chai');
|
||||
const should = chai.should();
|
||||
const { expect } = chai;
|
||||
const modulePath = "../../../../app/js/UpdateTrimmer.js";
|
||||
const SandboxedModule = require('sandboxed-module');
|
||||
const tk = require("timekeeper");
|
||||
const sinon = require('sinon')
|
||||
const chai = require('chai')
|
||||
const should = chai.should()
|
||||
const { expect } = chai
|
||||
const modulePath = '../../../../app/js/UpdateTrimmer.js'
|
||||
const SandboxedModule = require('sandboxed-module')
|
||||
const tk = require('timekeeper')
|
||||
|
||||
describe("UpdateTrimmer", function() {
|
||||
beforeEach(function() {
|
||||
this.now = new Date();
|
||||
tk.freeze(this.now);
|
||||
describe('UpdateTrimmer', function() {
|
||||
beforeEach(function() {
|
||||
this.now = new Date()
|
||||
tk.freeze(this.now)
|
||||
|
||||
this.UpdateTrimmer = SandboxedModule.require(modulePath, { requires: {
|
||||
"logger-sharelatex": (this.logger = { log: sinon.stub(), error: sinon.stub() }),
|
||||
"./WebApiManager": (this.WebApiManager = {}),
|
||||
"./MongoManager": (this.MongoManager = {})
|
||||
}
|
||||
});
|
||||
this.UpdateTrimmer = SandboxedModule.require(modulePath, {
|
||||
requires: {
|
||||
'logger-sharelatex': (this.logger = {
|
||||
log: sinon.stub(),
|
||||
error: sinon.stub()
|
||||
}),
|
||||
'./WebApiManager': (this.WebApiManager = {}),
|
||||
'./MongoManager': (this.MongoManager = {})
|
||||
}
|
||||
})
|
||||
|
||||
this.callback = sinon.stub();
|
||||
return this.project_id = "mock-project-id";
|
||||
});
|
||||
this.callback = sinon.stub()
|
||||
return (this.project_id = 'mock-project-id')
|
||||
})
|
||||
|
||||
afterEach(function() { return tk.reset(); });
|
||||
afterEach(function() {
|
||||
return tk.reset()
|
||||
})
|
||||
|
||||
return describe("shouldTrimUpdates", function() {
|
||||
beforeEach(function() {
|
||||
this.metadata = {};
|
||||
this.details =
|
||||
{features: {}};
|
||||
this.MongoManager.getProjectMetaData = sinon.stub().callsArgWith(1, null, this.metadata);
|
||||
this.MongoManager.setProjectMetaData = sinon.stub().callsArgWith(2);
|
||||
this.MongoManager.upgradeHistory = sinon.stub().callsArgWith(1);
|
||||
return this.WebApiManager.getProjectDetails = sinon.stub().callsArgWith(1, null, this.details);
|
||||
});
|
||||
return describe('shouldTrimUpdates', function() {
|
||||
beforeEach(function() {
|
||||
this.metadata = {}
|
||||
this.details = { features: {} }
|
||||
this.MongoManager.getProjectMetaData = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, this.metadata)
|
||||
this.MongoManager.setProjectMetaData = sinon.stub().callsArgWith(2)
|
||||
this.MongoManager.upgradeHistory = sinon.stub().callsArgWith(1)
|
||||
return (this.WebApiManager.getProjectDetails = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, this.details))
|
||||
})
|
||||
|
||||
describe("with preserveHistory set in the project meta data", function() {
|
||||
beforeEach(function() {
|
||||
this.metadata.preserveHistory = true;
|
||||
return this.UpdateTrimmer.shouldTrimUpdates(this.project_id, this.callback);
|
||||
});
|
||||
describe('with preserveHistory set in the project meta data', function() {
|
||||
beforeEach(function() {
|
||||
this.metadata.preserveHistory = true
|
||||
return this.UpdateTrimmer.shouldTrimUpdates(
|
||||
this.project_id,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
it("should look up the meta data", function() {
|
||||
return this.MongoManager.getProjectMetaData
|
||||
.calledWith(this.project_id)
|
||||
.should.equal(true);
|
||||
});
|
||||
it('should look up the meta data', function() {
|
||||
return this.MongoManager.getProjectMetaData
|
||||
.calledWith(this.project_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it("should not look up the project details", function() {
|
||||
return this.WebApiManager.getProjectDetails
|
||||
.called
|
||||
.should.equal(false);
|
||||
});
|
||||
it('should not look up the project details', function() {
|
||||
return this.WebApiManager.getProjectDetails.called.should.equal(false)
|
||||
})
|
||||
|
||||
return it("should return false", function() {
|
||||
return this.callback.calledWith(null, false).should.equal(true);
|
||||
});
|
||||
});
|
||||
return it('should return false', function() {
|
||||
return this.callback.calledWith(null, false).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe("without preserveHistory set in the project meta data", function() {
|
||||
beforeEach(function() {
|
||||
return this.metadata.preserveHistory = false;
|
||||
});
|
||||
describe('without preserveHistory set in the project meta data', function() {
|
||||
beforeEach(function() {
|
||||
return (this.metadata.preserveHistory = false)
|
||||
})
|
||||
|
||||
describe("when the project has the versioning feature", function() {
|
||||
beforeEach(function() {
|
||||
this.details.features.versioning = true;
|
||||
return this.UpdateTrimmer.shouldTrimUpdates(this.project_id, this.callback);
|
||||
});
|
||||
describe('when the project has the versioning feature', function() {
|
||||
beforeEach(function() {
|
||||
this.details.features.versioning = true
|
||||
return this.UpdateTrimmer.shouldTrimUpdates(
|
||||
this.project_id,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
it("should look up the meta data", function() {
|
||||
return this.MongoManager.getProjectMetaData
|
||||
.calledWith(this.project_id)
|
||||
.should.equal(true);
|
||||
});
|
||||
it('should look up the meta data', function() {
|
||||
return this.MongoManager.getProjectMetaData
|
||||
.calledWith(this.project_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it("should look up the project details", function() {
|
||||
return this.WebApiManager.getProjectDetails
|
||||
.calledWith(this.project_id)
|
||||
.should.equal(true);
|
||||
});
|
||||
it('should look up the project details', function() {
|
||||
return this.WebApiManager.getProjectDetails
|
||||
.calledWith(this.project_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it("should insert preserveHistory into the metadata", function() {
|
||||
return this.MongoManager.setProjectMetaData
|
||||
.calledWith(this.project_id, {preserveHistory: true})
|
||||
.should.equal(true);
|
||||
});
|
||||
it('should insert preserveHistory into the metadata', function() {
|
||||
return this.MongoManager.setProjectMetaData
|
||||
.calledWith(this.project_id, { preserveHistory: true })
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it("should upgrade any existing history", function() {
|
||||
return this.MongoManager.upgradeHistory
|
||||
.calledWith(this.project_id)
|
||||
.should.equal(true);
|
||||
});
|
||||
it('should upgrade any existing history', function() {
|
||||
return this.MongoManager.upgradeHistory
|
||||
.calledWith(this.project_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
return it("should return false", function() {
|
||||
return this.callback.calledWith(null, false).should.equal(true);
|
||||
});
|
||||
});
|
||||
return it('should return false', function() {
|
||||
return this.callback.calledWith(null, false).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
return describe("when the project does not have the versioning feature", function() {
|
||||
beforeEach(function() {
|
||||
this.details.features.versioning = false;
|
||||
return this.UpdateTrimmer.shouldTrimUpdates(this.project_id, this.callback);
|
||||
});
|
||||
return describe('when the project does not have the versioning feature', function() {
|
||||
beforeEach(function() {
|
||||
this.details.features.versioning = false
|
||||
return this.UpdateTrimmer.shouldTrimUpdates(
|
||||
this.project_id,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
return it("should return true", function() {
|
||||
return this.callback.calledWith(null, true).should.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
return it('should return true', function() {
|
||||
return this.callback.calledWith(null, true).should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
return describe("without any meta data", function() {
|
||||
beforeEach(function() {
|
||||
return this.MongoManager.getProjectMetaData = sinon.stub().callsArgWith(1, null, null);
|
||||
});
|
||||
return describe('without any meta data', function() {
|
||||
beforeEach(function() {
|
||||
return (this.MongoManager.getProjectMetaData = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, null))
|
||||
})
|
||||
|
||||
describe("when the project has the versioning feature", function() {
|
||||
beforeEach(function() {
|
||||
this.details.features.versioning = true;
|
||||
return this.UpdateTrimmer.shouldTrimUpdates(this.project_id, this.callback);
|
||||
});
|
||||
describe('when the project has the versioning feature', function() {
|
||||
beforeEach(function() {
|
||||
this.details.features.versioning = true
|
||||
return this.UpdateTrimmer.shouldTrimUpdates(
|
||||
this.project_id,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
it("should insert preserveHistory into the metadata", function() {
|
||||
return this.MongoManager.setProjectMetaData
|
||||
.calledWith(this.project_id, {preserveHistory: true})
|
||||
.should.equal(true);
|
||||
});
|
||||
it('should insert preserveHistory into the metadata', function() {
|
||||
return this.MongoManager.setProjectMetaData
|
||||
.calledWith(this.project_id, { preserveHistory: true })
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it("should upgrade any existing history", function() {
|
||||
return this.MongoManager.upgradeHistory
|
||||
.calledWith(this.project_id)
|
||||
.should.equal(true);
|
||||
});
|
||||
it('should upgrade any existing history', function() {
|
||||
return this.MongoManager.upgradeHistory
|
||||
.calledWith(this.project_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
return it("should return false", function() {
|
||||
return this.callback.calledWith(null, false).should.equal(true);
|
||||
});
|
||||
});
|
||||
return it('should return false', function() {
|
||||
return this.callback.calledWith(null, false).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
return describe("when the project does not have the versioning feature", function() {
|
||||
beforeEach(function() {
|
||||
this.details.features.versioning = false;
|
||||
return this.UpdateTrimmer.shouldTrimUpdates(this.project_id, this.callback);
|
||||
});
|
||||
|
||||
return it("should return true", function() {
|
||||
return this.callback.calledWith(null, true).should.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
return describe('when the project does not have the versioning feature', function() {
|
||||
beforeEach(function() {
|
||||
this.details.features.versioning = false
|
||||
return this.UpdateTrimmer.shouldTrimUpdates(
|
||||
this.project_id,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
return it('should return true', function() {
|
||||
return this.callback.calledWith(null, true).should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -9,162 +9,206 @@
|
|||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
const sinon = require('sinon');
|
||||
const chai = require('chai');
|
||||
const should = chai.should();
|
||||
const { expect } = chai;
|
||||
const modulePath = "../../../../app/js/WebApiManager.js";
|
||||
const SandboxedModule = require('sandboxed-module');
|
||||
const sinon = require('sinon')
|
||||
const chai = require('chai')
|
||||
const should = chai.should()
|
||||
const { expect } = chai
|
||||
const modulePath = '../../../../app/js/WebApiManager.js'
|
||||
const SandboxedModule = require('sandboxed-module')
|
||||
|
||||
describe("WebApiManager", function() {
|
||||
beforeEach(function() {
|
||||
this.WebApiManager = SandboxedModule.require(modulePath, { requires: {
|
||||
"requestretry": (this.request = {}),
|
||||
"logger-sharelatex": (this.logger = { log: sinon.stub(), error: sinon.stub() }),
|
||||
'settings-sharelatex': (this.settings = {
|
||||
apis: {
|
||||
web: {
|
||||
url: "http://example.com",
|
||||
user: "sharelatex",
|
||||
pass: "password"
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
);
|
||||
this.callback = sinon.stub();
|
||||
this.user_id = "mock-user-id";
|
||||
this.project_id = "mock-project-id";
|
||||
this.user_info = {
|
||||
email: "leo@sharelatex.com",
|
||||
id: this.user_id,
|
||||
first_name: "Leo",
|
||||
last_nane: "Lion",
|
||||
extra_param: "blah"
|
||||
};
|
||||
return this.project =
|
||||
{features: "mock-features"};
|
||||
});
|
||||
describe('WebApiManager', function() {
|
||||
beforeEach(function() {
|
||||
this.WebApiManager = SandboxedModule.require(modulePath, {
|
||||
requires: {
|
||||
requestretry: (this.request = {}),
|
||||
'logger-sharelatex': (this.logger = {
|
||||
log: sinon.stub(),
|
||||
error: sinon.stub()
|
||||
}),
|
||||
'settings-sharelatex': (this.settings = {
|
||||
apis: {
|
||||
web: {
|
||||
url: 'http://example.com',
|
||||
user: 'sharelatex',
|
||||
pass: 'password'
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
this.callback = sinon.stub()
|
||||
this.user_id = 'mock-user-id'
|
||||
this.project_id = 'mock-project-id'
|
||||
this.user_info = {
|
||||
email: 'leo@sharelatex.com',
|
||||
id: this.user_id,
|
||||
first_name: 'Leo',
|
||||
last_nane: 'Lion',
|
||||
extra_param: 'blah'
|
||||
}
|
||||
return (this.project = { features: 'mock-features' })
|
||||
})
|
||||
|
||||
describe("getUserInfo", function() {
|
||||
describe("successfully", function() {
|
||||
beforeEach(function() {
|
||||
this.body = JSON.stringify(this.user_info);
|
||||
this.request.get = sinon.stub().callsArgWith(1, null, {statusCode: 200}, this.body);
|
||||
return this.WebApiManager.getUserInfo(this.user_id, this.callback);
|
||||
});
|
||||
describe('getUserInfo', function() {
|
||||
describe('successfully', function() {
|
||||
beforeEach(function() {
|
||||
this.body = JSON.stringify(this.user_info)
|
||||
this.request.get = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 200 }, this.body)
|
||||
return this.WebApiManager.getUserInfo(this.user_id, this.callback)
|
||||
})
|
||||
|
||||
it('should get the user from the web api', function() {
|
||||
return this.request.get
|
||||
.calledWithMatch({
|
||||
url: `${this.settings.apis.web.url}/user/${this.user_id}/personal_info`,
|
||||
auth: {
|
||||
user: this.settings.apis.web.user,
|
||||
pass: this.settings.apis.web.pass,
|
||||
sendImmediately: true
|
||||
}
|
||||
})
|
||||
.should.equal(true);
|
||||
});
|
||||
it('should get the user from the web api', function() {
|
||||
return this.request.get
|
||||
.calledWithMatch({
|
||||
url: `${this.settings.apis.web.url}/user/${this.user_id}/personal_info`,
|
||||
auth: {
|
||||
user: this.settings.apis.web.user,
|
||||
pass: this.settings.apis.web.pass,
|
||||
sendImmediately: true
|
||||
}
|
||||
})
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
return it("should call the callback with only the email, id and names", function() {
|
||||
return this.callback.calledWith(null, {
|
||||
id: this.user_id,
|
||||
email: this.user_info.email,
|
||||
first_name: this.user_info.first_name,
|
||||
last_name: this.user_info.last_name
|
||||
}).should.equal(true);
|
||||
});
|
||||
});
|
||||
return it('should call the callback with only the email, id and names', function() {
|
||||
return this.callback
|
||||
.calledWith(null, {
|
||||
id: this.user_id,
|
||||
email: this.user_info.email,
|
||||
first_name: this.user_info.first_name,
|
||||
last_name: this.user_info.last_name
|
||||
})
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe("when the web API returns an error", function() {
|
||||
beforeEach(function() {
|
||||
this.request.get = sinon.stub().callsArgWith(1, (this.error = new Error("something went wrong")), null, null);
|
||||
return this.WebApiManager.getUserInfo(this.user_id, this.callback);
|
||||
});
|
||||
describe('when the web API returns an error', function() {
|
||||
beforeEach(function() {
|
||||
this.request.get = sinon
|
||||
.stub()
|
||||
.callsArgWith(
|
||||
1,
|
||||
(this.error = new Error('something went wrong')),
|
||||
null,
|
||||
null
|
||||
)
|
||||
return this.WebApiManager.getUserInfo(this.user_id, this.callback)
|
||||
})
|
||||
|
||||
return it("should return an error to the callback", function() {
|
||||
return this.callback.calledWith(this.error).should.equal(true);
|
||||
});
|
||||
});
|
||||
return it('should return an error to the callback', function() {
|
||||
return this.callback.calledWith(this.error).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe("when the web returns a failure error code", function() {
|
||||
beforeEach(function() {
|
||||
this.request.get = sinon.stub().callsArgWith(1, null, { statusCode: 500, attempts: 42}, "");
|
||||
return this.WebApiManager.getUserInfo(this.user_id, this.callback);
|
||||
});
|
||||
describe('when the web returns a failure error code', function() {
|
||||
beforeEach(function() {
|
||||
this.request.get = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 500, attempts: 42 }, '')
|
||||
return this.WebApiManager.getUserInfo(this.user_id, this.callback)
|
||||
})
|
||||
|
||||
return it("should return the callback with an error", function() {
|
||||
return this.callback
|
||||
.calledWith(sinon.match.has('message', "web returned a non-success status code: 500 (attempts: 42)"))
|
||||
.should.equal(true);
|
||||
});
|
||||
});
|
||||
return it('should return the callback with an error', function() {
|
||||
return this.callback
|
||||
.calledWith(
|
||||
sinon.match.has(
|
||||
'message',
|
||||
'web returned a non-success status code: 500 (attempts: 42)'
|
||||
)
|
||||
)
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
return describe("when the user cannot be found", function() {
|
||||
beforeEach(function() {
|
||||
this.request.get = sinon.stub().callsArgWith(1, null, {statusCode: 404}, "nothing");
|
||||
return this.WebApiManager.getUserInfo(this.user_id, this.callback);
|
||||
});
|
||||
return describe('when the user cannot be found', function() {
|
||||
beforeEach(function() {
|
||||
this.request.get = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 404 }, 'nothing')
|
||||
return this.WebApiManager.getUserInfo(this.user_id, this.callback)
|
||||
})
|
||||
|
||||
return it("should return a null value", function() {
|
||||
return this.callback
|
||||
.calledWith(null, null)
|
||||
.should.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
return it('should return a null value', function() {
|
||||
return this.callback.calledWith(null, null).should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
return describe('getProjectDetails', function() {
|
||||
describe('successfully', function() {
|
||||
beforeEach(function() {
|
||||
this.body = JSON.stringify(this.project)
|
||||
this.request.get = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 200 }, this.body)
|
||||
return this.WebApiManager.getProjectDetails(
|
||||
this.project_id,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
return describe("getProjectDetails", function() {
|
||||
describe("successfully", function() {
|
||||
beforeEach(function() {
|
||||
this.body = JSON.stringify(this.project);
|
||||
this.request.get = sinon.stub().callsArgWith(1, null, {statusCode: 200}, this.body);
|
||||
return this.WebApiManager.getProjectDetails(this.project_id, this.callback);
|
||||
});
|
||||
it('should get the project from the web api', function() {
|
||||
return this.request.get
|
||||
.calledWithMatch({
|
||||
url: `${this.settings.apis.web.url}/project/${this.project_id}/details`,
|
||||
auth: {
|
||||
user: this.settings.apis.web.user,
|
||||
pass: this.settings.apis.web.pass,
|
||||
sendImmediately: true
|
||||
}
|
||||
})
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should get the project from the web api', function() {
|
||||
return this.request.get
|
||||
.calledWithMatch({
|
||||
url: `${this.settings.apis.web.url}/project/${this.project_id}/details`,
|
||||
auth: {
|
||||
user: this.settings.apis.web.user,
|
||||
pass: this.settings.apis.web.pass,
|
||||
sendImmediately: true
|
||||
}
|
||||
})
|
||||
.should.equal(true);
|
||||
});
|
||||
return it('should call the callback with the project', function() {
|
||||
return this.callback.calledWith(null, this.project).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
return it("should call the callback with the project", function() {
|
||||
return this.callback.calledWith(null, this.project).should.equal(true);
|
||||
});
|
||||
});
|
||||
describe('when the web API returns an error', function() {
|
||||
beforeEach(function() {
|
||||
this.request.get = sinon
|
||||
.stub()
|
||||
.callsArgWith(
|
||||
1,
|
||||
(this.error = new Error('something went wrong')),
|
||||
null,
|
||||
null
|
||||
)
|
||||
return this.WebApiManager.getProjectDetails(
|
||||
this.project_id,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
describe("when the web API returns an error", function() {
|
||||
beforeEach(function() {
|
||||
this.request.get = sinon.stub().callsArgWith(1, (this.error = new Error("something went wrong")), null, null);
|
||||
return this.WebApiManager.getProjectDetails(this.project_id, this.callback);
|
||||
});
|
||||
return it('should return an error to the callback', function() {
|
||||
return this.callback.calledWith(this.error).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
return it("should return an error to the callback", function() {
|
||||
return this.callback.calledWith(this.error).should.equal(true);
|
||||
});
|
||||
});
|
||||
return describe('when the web returns a failure error code', function() {
|
||||
beforeEach(function() {
|
||||
this.request.get = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 500, attempts: 42 }, '')
|
||||
return this.WebApiManager.getProjectDetails(
|
||||
this.project_id,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
return describe("when the web returns a failure error code", function() {
|
||||
beforeEach(function() {
|
||||
this.request.get = sinon.stub().callsArgWith(1, null, { statusCode: 500, attempts: 42 }, "");
|
||||
return this.WebApiManager.getProjectDetails(this.project_id, this.callback);
|
||||
});
|
||||
|
||||
return it("should return the callback with an error", function() {
|
||||
return this.callback
|
||||
.calledWith(sinon.match.has('message', "web returned a non-success status code: 500 (attempts: 42)"))
|
||||
.should.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
return it('should return the callback with an error', function() {
|
||||
return this.callback
|
||||
.calledWith(
|
||||
sinon.match.has(
|
||||
'message',
|
||||
'web returned a non-success status code: 500 (attempts: 42)'
|
||||
)
|
||||
)
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Add table
Reference in a new issue