mirror of
https://github.com/overleaf/overleaf.git
synced 2024-09-16 02:52:31 -04:00
prettier: convert test/acceptance decaffeinated files to Prettier format
This commit is contained in:
parent
011262986d
commit
3183aca524
12 changed files with 1913 additions and 1339 deletions
|
@ -10,384 +10,581 @@
|
|||
* 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");
|
||||
chai.should();
|
||||
const { expect } = chai;
|
||||
const mongojs = require("../../../app/js/mongojs");
|
||||
const { ObjectId } = mongojs;
|
||||
const Settings = require("settings-sharelatex");
|
||||
const request = require("request");
|
||||
const rclient = require("redis").createClient(Settings.redis.history); // Only works locally for now
|
||||
const sinon = require('sinon')
|
||||
const chai = require('chai')
|
||||
chai.should()
|
||||
const { expect } = chai
|
||||
const mongojs = require('../../../app/js/mongojs')
|
||||
const { ObjectId } = mongojs
|
||||
const Settings = require('settings-sharelatex')
|
||||
const request = require('request')
|
||||
const rclient = require('redis').createClient(Settings.redis.history) // Only works locally for now
|
||||
|
||||
const TrackChangesApp = require("./helpers/TrackChangesApp");
|
||||
const TrackChangesClient = require("./helpers/TrackChangesClient");
|
||||
const MockWebApi = require("./helpers/MockWebApi");
|
||||
const TrackChangesApp = require('./helpers/TrackChangesApp')
|
||||
const TrackChangesClient = require('./helpers/TrackChangesClient')
|
||||
const MockWebApi = require('./helpers/MockWebApi')
|
||||
|
||||
describe("Appending doc ops to the history", function() {
|
||||
before(function(done) { return TrackChangesApp.ensureRunning(done); });
|
||||
describe('Appending doc ops to the history', function() {
|
||||
before(function(done) {
|
||||
return TrackChangesApp.ensureRunning(done)
|
||||
})
|
||||
|
||||
describe("when the history does not exist yet", function() {
|
||||
before(function(done) {
|
||||
this.project_id = ObjectId().toString();
|
||||
this.doc_id = ObjectId().toString();
|
||||
this.user_id = ObjectId().toString();
|
||||
MockWebApi.projects[this.project_id] = {features: {versioning: false}};
|
||||
TrackChangesClient.pushRawUpdates(this.project_id, this.doc_id, [{
|
||||
op: [{ i: "f", p: 3 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 3
|
||||
}, {
|
||||
op: [{ i: "o", p: 4 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 4
|
||||
}, {
|
||||
op: [{ i: "o", p: 5 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 5
|
||||
}], error => {
|
||||
if (error != null) { throw error; }
|
||||
return TrackChangesClient.flushAndGetCompressedUpdates(this.project_id, this.doc_id, (error, updates) => {
|
||||
this.updates = updates;
|
||||
if (error != null) { throw error; }
|
||||
return done();
|
||||
});
|
||||
});
|
||||
return null;
|
||||
});
|
||||
describe('when the history does not exist yet', function() {
|
||||
before(function(done) {
|
||||
this.project_id = ObjectId().toString()
|
||||
this.doc_id = ObjectId().toString()
|
||||
this.user_id = ObjectId().toString()
|
||||
MockWebApi.projects[this.project_id] = { features: { versioning: false } }
|
||||
TrackChangesClient.pushRawUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
[
|
||||
{
|
||||
op: [{ i: 'f', p: 3 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 3
|
||||
},
|
||||
{
|
||||
op: [{ i: 'o', p: 4 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 4
|
||||
},
|
||||
{
|
||||
op: [{ i: 'o', p: 5 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 5
|
||||
}
|
||||
],
|
||||
error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return TrackChangesClient.flushAndGetCompressedUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
(error, updates) => {
|
||||
this.updates = updates
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return done()
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
return null
|
||||
})
|
||||
|
||||
it("should insert the compressed op into mongo", function() {
|
||||
return expect(this.updates[0].pack[0].op).to.deep.equal([{
|
||||
p: 3, i: "foo"
|
||||
}]);
|
||||
});
|
||||
it('should insert the compressed op into mongo', function() {
|
||||
return expect(this.updates[0].pack[0].op).to.deep.equal([
|
||||
{
|
||||
p: 3,
|
||||
i: 'foo'
|
||||
}
|
||||
])
|
||||
})
|
||||
|
||||
it("should insert the correct version number into mongo", function() {
|
||||
return expect(this.updates[0].v).to.equal(5);
|
||||
});
|
||||
it('should insert the correct version number into mongo', function() {
|
||||
return expect(this.updates[0].v).to.equal(5)
|
||||
})
|
||||
|
||||
it("should store the doc id", function() {
|
||||
return expect(this.updates[0].doc_id.toString()).to.equal(this.doc_id);
|
||||
});
|
||||
it('should store the doc id', function() {
|
||||
return expect(this.updates[0].doc_id.toString()).to.equal(this.doc_id)
|
||||
})
|
||||
|
||||
it("should store the project id", function() {
|
||||
return expect(this.updates[0].project_id.toString()).to.equal(this.project_id);
|
||||
});
|
||||
it('should store the project id', function() {
|
||||
return expect(this.updates[0].project_id.toString()).to.equal(
|
||||
this.project_id
|
||||
)
|
||||
})
|
||||
|
||||
return it("should clear the doc from the DocsWithHistoryOps set", function(done) {
|
||||
rclient.sismember(`DocsWithHistoryOps:${this.project_id}`, this.doc_id, (error, member) => {
|
||||
member.should.equal(0);
|
||||
return done();
|
||||
});
|
||||
return null;
|
||||
});
|
||||
});
|
||||
return it('should clear the doc from the DocsWithHistoryOps set', function(done) {
|
||||
rclient.sismember(
|
||||
`DocsWithHistoryOps:${this.project_id}`,
|
||||
this.doc_id,
|
||||
(error, member) => {
|
||||
member.should.equal(0)
|
||||
return done()
|
||||
}
|
||||
)
|
||||
return null
|
||||
})
|
||||
})
|
||||
|
||||
describe("when the history has already been started", function() {
|
||||
beforeEach(function(done) {
|
||||
this.project_id = ObjectId().toString();
|
||||
this.doc_id = ObjectId().toString();
|
||||
this.user_id = ObjectId().toString();
|
||||
MockWebApi.projects[this.project_id] = {features: {versioning: false}};
|
||||
TrackChangesClient.pushRawUpdates(this.project_id, this.doc_id, [{
|
||||
op: [{ i: "f", p: 3 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 3
|
||||
}, {
|
||||
op: [{ i: "o", p: 4 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 4
|
||||
}, {
|
||||
op: [{ i: "o", p: 5 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 5
|
||||
}], error => {
|
||||
if (error != null) { throw error; }
|
||||
return TrackChangesClient.flushAndGetCompressedUpdates(this.project_id, this.doc_id, (error, updates) => {
|
||||
if (error != null) { throw error; }
|
||||
return done();
|
||||
});
|
||||
});
|
||||
return null;
|
||||
});
|
||||
describe('when the history has already been started', function() {
|
||||
beforeEach(function(done) {
|
||||
this.project_id = ObjectId().toString()
|
||||
this.doc_id = ObjectId().toString()
|
||||
this.user_id = ObjectId().toString()
|
||||
MockWebApi.projects[this.project_id] = { features: { versioning: false } }
|
||||
TrackChangesClient.pushRawUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
[
|
||||
{
|
||||
op: [{ i: 'f', p: 3 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 3
|
||||
},
|
||||
{
|
||||
op: [{ i: 'o', p: 4 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 4
|
||||
},
|
||||
{
|
||||
op: [{ i: 'o', p: 5 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 5
|
||||
}
|
||||
],
|
||||
error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return TrackChangesClient.flushAndGetCompressedUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
(error, updates) => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return done()
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
return null
|
||||
})
|
||||
|
||||
describe("when the updates are recent and from the same user", function() {
|
||||
beforeEach(function(done) {
|
||||
TrackChangesClient.pushRawUpdates(this.project_id, this.doc_id, [{
|
||||
op: [{ i: "b", p: 6 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 6
|
||||
}, {
|
||||
op: [{ i: "a", p: 7 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 7
|
||||
}, {
|
||||
op: [{ i: "r", p: 8 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 8
|
||||
}], error => {
|
||||
if (error != null) { throw error; }
|
||||
return TrackChangesClient.flushAndGetCompressedUpdates(this.project_id, this.doc_id, (error, updates) => {
|
||||
this.updates = updates;
|
||||
if (error != null) { throw error; }
|
||||
return done();
|
||||
});
|
||||
});
|
||||
return null;
|
||||
});
|
||||
describe('when the updates are recent and from the same user', function() {
|
||||
beforeEach(function(done) {
|
||||
TrackChangesClient.pushRawUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
[
|
||||
{
|
||||
op: [{ i: 'b', p: 6 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 6
|
||||
},
|
||||
{
|
||||
op: [{ i: 'a', p: 7 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 7
|
||||
},
|
||||
{
|
||||
op: [{ i: 'r', p: 8 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 8
|
||||
}
|
||||
],
|
||||
error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return TrackChangesClient.flushAndGetCompressedUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
(error, updates) => {
|
||||
this.updates = updates
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return done()
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
return null
|
||||
})
|
||||
|
||||
it("should combine all the updates into one pack", function() {
|
||||
return expect(this.updates[0].pack[1].op).to.deep.equal([{
|
||||
p: 6, i: "bar"
|
||||
}]);
|
||||
});
|
||||
it('should combine all the updates into one pack', function() {
|
||||
return expect(this.updates[0].pack[1].op).to.deep.equal([
|
||||
{
|
||||
p: 6,
|
||||
i: 'bar'
|
||||
}
|
||||
])
|
||||
})
|
||||
|
||||
return it("should insert the correct version number into mongo", function() {
|
||||
return expect(this.updates[0].v_end).to.equal(8);
|
||||
});
|
||||
});
|
||||
return it('should insert the correct version number into mongo', function() {
|
||||
return expect(this.updates[0].v_end).to.equal(8)
|
||||
})
|
||||
})
|
||||
|
||||
return describe('when the updates are far apart', function() {
|
||||
beforeEach(function(done) {
|
||||
const oneDay = 24 * 60 * 60 * 1000
|
||||
TrackChangesClient.pushRawUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
[
|
||||
{
|
||||
op: [{ i: 'b', p: 6 }],
|
||||
meta: { ts: Date.now() + oneDay, user_id: this.user_id },
|
||||
v: 6
|
||||
},
|
||||
{
|
||||
op: [{ i: 'a', p: 7 }],
|
||||
meta: { ts: Date.now() + oneDay, user_id: this.user_id },
|
||||
v: 7
|
||||
},
|
||||
{
|
||||
op: [{ i: 'r', p: 8 }],
|
||||
meta: { ts: Date.now() + oneDay, user_id: this.user_id },
|
||||
v: 8
|
||||
}
|
||||
],
|
||||
error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return TrackChangesClient.flushAndGetCompressedUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
(error, updates) => {
|
||||
this.updates = updates
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return done()
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
return null
|
||||
})
|
||||
|
||||
return describe("when the updates are far apart", function() {
|
||||
beforeEach(function(done) {
|
||||
const oneDay = 24 * 60 * 60 * 1000;
|
||||
TrackChangesClient.pushRawUpdates(this.project_id, this.doc_id, [{
|
||||
op: [{ i: "b", p: 6 }],
|
||||
meta: { ts: Date.now() + oneDay, user_id: this.user_id },
|
||||
v: 6
|
||||
}, {
|
||||
op: [{ i: "a", p: 7 }],
|
||||
meta: { ts: Date.now() + oneDay, user_id: this.user_id },
|
||||
v: 7
|
||||
}, {
|
||||
op: [{ i: "r", p: 8 }],
|
||||
meta: { ts: Date.now() + oneDay, user_id: this.user_id },
|
||||
v: 8
|
||||
}], error => {
|
||||
if (error != null) { throw error; }
|
||||
return TrackChangesClient.flushAndGetCompressedUpdates(this.project_id, this.doc_id, (error, updates) => {
|
||||
this.updates = updates;
|
||||
if (error != null) { throw error; }
|
||||
return done();
|
||||
});
|
||||
});
|
||||
return null;
|
||||
});
|
||||
return it('should combine the updates into one pack', function() {
|
||||
expect(this.updates[0].pack[0].op).to.deep.equal([
|
||||
{
|
||||
p: 3,
|
||||
i: 'foo'
|
||||
}
|
||||
])
|
||||
return expect(this.updates[0].pack[1].op).to.deep.equal([
|
||||
{
|
||||
p: 6,
|
||||
i: 'bar'
|
||||
}
|
||||
])
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
return it("should combine the updates into one pack", function() {
|
||||
expect(this.updates[0].pack[0].op).to.deep.equal([{
|
||||
p: 3, i: "foo"
|
||||
}]);
|
||||
return expect(this.updates[0].pack[1].op).to.deep.equal([{
|
||||
p: 6, i: "bar"
|
||||
}]);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('when the updates need processing in batches', function() {
|
||||
before(function(done) {
|
||||
this.project_id = ObjectId().toString()
|
||||
this.doc_id = ObjectId().toString()
|
||||
this.user_id = ObjectId().toString()
|
||||
MockWebApi.projects[this.project_id] = { features: { versioning: false } }
|
||||
const updates = []
|
||||
this.expectedOp = [{ p: 0, i: '' }]
|
||||
for (let i = 0; i <= 250; i++) {
|
||||
updates.push({
|
||||
op: [{ i: 'a', p: 0 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: i
|
||||
})
|
||||
this.expectedOp[0].i = `a${this.expectedOp[0].i}`
|
||||
}
|
||||
|
||||
describe("when the updates need processing in batches", function() {
|
||||
before(function(done) {
|
||||
this.project_id = ObjectId().toString();
|
||||
this.doc_id = ObjectId().toString();
|
||||
this.user_id = ObjectId().toString();
|
||||
MockWebApi.projects[this.project_id] = {features: {versioning: false}};
|
||||
const updates = [];
|
||||
this.expectedOp = [{ p:0, i: "" }];
|
||||
for (let i = 0; i <= 250; i++) {
|
||||
updates.push({
|
||||
op: [{i: "a", p: 0}],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: i
|
||||
});
|
||||
this.expectedOp[0].i = `a${this.expectedOp[0].i}`;
|
||||
}
|
||||
TrackChangesClient.pushRawUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
updates,
|
||||
error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return TrackChangesClient.flushAndGetCompressedUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
(error, updates1) => {
|
||||
this.updates = updates1
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return done()
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
return null
|
||||
})
|
||||
|
||||
TrackChangesClient.pushRawUpdates(this.project_id, this.doc_id, updates, error => {
|
||||
if (error != null) { throw error; }
|
||||
return TrackChangesClient.flushAndGetCompressedUpdates(this.project_id, this.doc_id, (error, updates1) => {
|
||||
this.updates = updates1;
|
||||
if (error != null) { throw error; }
|
||||
return done();
|
||||
});
|
||||
});
|
||||
return null;
|
||||
});
|
||||
it('should concat the compressed op into mongo', function() {
|
||||
return expect(this.updates[0].pack.length).to.deep.equal(3)
|
||||
}) // batch size is 100
|
||||
|
||||
it("should concat the compressed op into mongo", function() {
|
||||
return expect(this.updates[0].pack.length).to.deep.equal(3);
|
||||
}); // batch size is 100
|
||||
return it('should insert the correct version number into mongo', function() {
|
||||
return expect(this.updates[0].v_end).to.equal(250)
|
||||
})
|
||||
})
|
||||
|
||||
return it("should insert the correct version number into mongo", function() {
|
||||
return expect(this.updates[0].v_end).to.equal(250);
|
||||
});
|
||||
});
|
||||
describe('when there are multiple ops in each update', function() {
|
||||
before(function(done) {
|
||||
this.project_id = ObjectId().toString()
|
||||
this.doc_id = ObjectId().toString()
|
||||
this.user_id = ObjectId().toString()
|
||||
MockWebApi.projects[this.project_id] = { features: { versioning: false } }
|
||||
const oneDay = 24 * 60 * 60 * 1000
|
||||
TrackChangesClient.pushRawUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
[
|
||||
{
|
||||
op: [
|
||||
{ i: 'f', p: 3 },
|
||||
{ i: 'o', p: 4 },
|
||||
{ i: 'o', p: 5 }
|
||||
],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 3
|
||||
},
|
||||
{
|
||||
op: [
|
||||
{ i: 'b', p: 6 },
|
||||
{ i: 'a', p: 7 },
|
||||
{ i: 'r', p: 8 }
|
||||
],
|
||||
meta: { ts: Date.now() + oneDay, user_id: this.user_id },
|
||||
v: 4
|
||||
}
|
||||
],
|
||||
error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return TrackChangesClient.flushAndGetCompressedUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
(error, updates) => {
|
||||
this.updates = updates
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return done()
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
return null
|
||||
})
|
||||
|
||||
it('should insert the compressed ops into mongo', function() {
|
||||
expect(this.updates[0].pack[0].op).to.deep.equal([
|
||||
{
|
||||
p: 3,
|
||||
i: 'foo'
|
||||
}
|
||||
])
|
||||
return expect(this.updates[0].pack[1].op).to.deep.equal([
|
||||
{
|
||||
p: 6,
|
||||
i: 'bar'
|
||||
}
|
||||
])
|
||||
})
|
||||
|
||||
describe("when there are multiple ops in each update", function() {
|
||||
before(function(done) {
|
||||
this.project_id = ObjectId().toString();
|
||||
this.doc_id = ObjectId().toString();
|
||||
this.user_id = ObjectId().toString();
|
||||
MockWebApi.projects[this.project_id] = {features: {versioning: false}};
|
||||
const oneDay = 24 * 60 * 60 * 1000;
|
||||
TrackChangesClient.pushRawUpdates(this.project_id, this.doc_id, [{
|
||||
op: [{ i: "f", p: 3 }, { i: "o", p: 4 }, { i: "o", p: 5 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 3
|
||||
}, {
|
||||
op: [{ i: "b", p: 6 }, { i: "a", p: 7 }, { i: "r", p: 8 }],
|
||||
meta: { ts: Date.now() + oneDay, user_id: this.user_id },
|
||||
v: 4
|
||||
}], error => {
|
||||
if (error != null) { throw error; }
|
||||
return TrackChangesClient.flushAndGetCompressedUpdates(this.project_id, this.doc_id, (error, updates) => {
|
||||
this.updates = updates;
|
||||
if (error != null) { throw error; }
|
||||
return done();
|
||||
});
|
||||
});
|
||||
return null;
|
||||
});
|
||||
return it('should insert the correct version numbers into mongo', function() {
|
||||
expect(this.updates[0].pack[0].v).to.equal(3)
|
||||
return expect(this.updates[0].pack[1].v).to.equal(4)
|
||||
})
|
||||
})
|
||||
|
||||
it("should insert the compressed ops into mongo", function() {
|
||||
expect(this.updates[0].pack[0].op).to.deep.equal([{
|
||||
p: 3, i: "foo"
|
||||
}]);
|
||||
return expect(this.updates[0].pack[1].op).to.deep.equal([{
|
||||
p: 6, i: "bar"
|
||||
}]);
|
||||
});
|
||||
describe('when there is a no-op update', function() {
|
||||
before(function(done) {
|
||||
this.project_id = ObjectId().toString()
|
||||
this.doc_id = ObjectId().toString()
|
||||
this.user_id = ObjectId().toString()
|
||||
MockWebApi.projects[this.project_id] = { features: { versioning: false } }
|
||||
const oneDay = 24 * 60 * 60 * 1000
|
||||
TrackChangesClient.pushRawUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
[
|
||||
{
|
||||
op: [],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 3
|
||||
},
|
||||
{
|
||||
op: [{ i: 'foo', p: 3 }],
|
||||
meta: { ts: Date.now() + oneDay, user_id: this.user_id },
|
||||
v: 4
|
||||
}
|
||||
],
|
||||
error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return TrackChangesClient.flushAndGetCompressedUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
(error, updates) => {
|
||||
this.updates = updates
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return done()
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
return null
|
||||
})
|
||||
|
||||
return it("should insert the correct version numbers into mongo", function() {
|
||||
expect(this.updates[0].pack[0].v).to.equal(3);
|
||||
return expect(this.updates[0].pack[1].v).to.equal(4);
|
||||
});
|
||||
});
|
||||
it('should insert the compressed no-op into mongo', function() {
|
||||
return expect(this.updates[0].pack[0].op).to.deep.equal([])
|
||||
})
|
||||
|
||||
describe("when there is a no-op update", function() {
|
||||
before(function(done) {
|
||||
this.project_id = ObjectId().toString();
|
||||
this.doc_id = ObjectId().toString();
|
||||
this.user_id = ObjectId().toString();
|
||||
MockWebApi.projects[this.project_id] = {features: {versioning: false}};
|
||||
const oneDay = 24 * 60 * 60 * 1000;
|
||||
TrackChangesClient.pushRawUpdates(this.project_id, this.doc_id, [{
|
||||
op: [],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 3
|
||||
}, {
|
||||
op: [{ i: "foo", p: 3 }],
|
||||
meta: { ts: Date.now() + oneDay, user_id: this.user_id },
|
||||
v: 4
|
||||
}], error => {
|
||||
if (error != null) { throw error; }
|
||||
return TrackChangesClient.flushAndGetCompressedUpdates(this.project_id, this.doc_id, (error, updates) => {
|
||||
this.updates = updates;
|
||||
if (error != null) { throw error; }
|
||||
return done();
|
||||
});
|
||||
});
|
||||
return null;
|
||||
});
|
||||
it('should insert the compressed next update into mongo', function() {
|
||||
return expect(this.updates[0].pack[1].op).to.deep.equal([
|
||||
{
|
||||
p: 3,
|
||||
i: 'foo'
|
||||
}
|
||||
])
|
||||
})
|
||||
|
||||
it("should insert the compressed no-op into mongo", function() {
|
||||
return expect(this.updates[0].pack[0].op).to.deep.equal([]);
|
||||
});
|
||||
return it('should insert the correct version numbers into mongo', function() {
|
||||
expect(this.updates[0].pack[0].v).to.equal(3)
|
||||
return expect(this.updates[0].pack[1].v).to.equal(4)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when there is a comment update', function() {
|
||||
before(function(done) {
|
||||
this.project_id = ObjectId().toString()
|
||||
this.doc_id = ObjectId().toString()
|
||||
this.user_id = ObjectId().toString()
|
||||
MockWebApi.projects[this.project_id] = { features: { versioning: false } }
|
||||
TrackChangesClient.pushRawUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
[
|
||||
{
|
||||
op: [
|
||||
{ c: 'foo', p: 3 },
|
||||
{ d: 'bar', p: 6 }
|
||||
],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 3
|
||||
}
|
||||
],
|
||||
error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return TrackChangesClient.flushAndGetCompressedUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
(error, updates) => {
|
||||
this.updates = updates
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return done()
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
return null
|
||||
})
|
||||
|
||||
it("should insert the compressed next update into mongo", function() {
|
||||
return expect(this.updates[0].pack[1].op).to.deep.equal([{
|
||||
p: 3, i: "foo"
|
||||
}]);
|
||||
});
|
||||
it('should ignore the comment op', function() {
|
||||
return expect(this.updates[0].pack[0].op).to.deep.equal([
|
||||
{ d: 'bar', p: 6 }
|
||||
])
|
||||
})
|
||||
|
||||
return it("should insert the correct version numbers into mongo", function() {
|
||||
expect(this.updates[0].pack[0].v).to.equal(3);
|
||||
return expect(this.updates[0].pack[1].v).to.equal(4);
|
||||
});
|
||||
});
|
||||
return it('should insert the correct version numbers into mongo', function() {
|
||||
return expect(this.updates[0].pack[0].v).to.equal(3)
|
||||
})
|
||||
})
|
||||
|
||||
describe("when there is a comment update", function() {
|
||||
before(function(done) {
|
||||
this.project_id = ObjectId().toString();
|
||||
this.doc_id = ObjectId().toString();
|
||||
this.user_id = ObjectId().toString();
|
||||
MockWebApi.projects[this.project_id] = {features: {versioning: false}};
|
||||
TrackChangesClient.pushRawUpdates(this.project_id, this.doc_id, [{
|
||||
op: [{ c: "foo", p: 3 }, {d: "bar", p: 6}],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 3
|
||||
}], error => {
|
||||
if (error != null) { throw error; }
|
||||
return TrackChangesClient.flushAndGetCompressedUpdates(this.project_id, this.doc_id, (error, updates) => {
|
||||
this.updates = updates;
|
||||
if (error != null) { throw error; }
|
||||
return done();
|
||||
});
|
||||
});
|
||||
return null;
|
||||
});
|
||||
describe('when the project has versioning enabled', function() {
|
||||
before(function(done) {
|
||||
this.project_id = ObjectId().toString()
|
||||
this.doc_id = ObjectId().toString()
|
||||
this.user_id = ObjectId().toString()
|
||||
MockWebApi.projects[this.project_id] = { features: { versioning: true } }
|
||||
|
||||
it("should ignore the comment op", function() {
|
||||
return expect(this.updates[0].pack[0].op).to.deep.equal([{d: "bar", p: 6}]);
|
||||
});
|
||||
TrackChangesClient.pushRawUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
[
|
||||
{
|
||||
op: [{ i: 'f', p: 3 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 3
|
||||
}
|
||||
],
|
||||
error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return TrackChangesClient.flushAndGetCompressedUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
(error, updates) => {
|
||||
this.updates = updates
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return done()
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
return null
|
||||
})
|
||||
|
||||
return it("should insert the correct version numbers into mongo", function() {
|
||||
return expect(this.updates[0].pack[0].v).to.equal(3);
|
||||
});
|
||||
});
|
||||
return it('should not add a expiresAt entry in the update in mongo', function() {
|
||||
return expect(this.updates[0].expiresAt).to.be.undefined
|
||||
})
|
||||
})
|
||||
|
||||
describe("when the project has versioning enabled", function() {
|
||||
before(function(done) {
|
||||
this.project_id = ObjectId().toString();
|
||||
this.doc_id = ObjectId().toString();
|
||||
this.user_id = ObjectId().toString();
|
||||
MockWebApi.projects[this.project_id] = {features: {versioning: true}};
|
||||
return describe('when the project does not have versioning enabled', function() {
|
||||
before(function(done) {
|
||||
this.project_id = ObjectId().toString()
|
||||
this.doc_id = ObjectId().toString()
|
||||
this.user_id = ObjectId().toString()
|
||||
MockWebApi.projects[this.project_id] = { features: { versioning: false } }
|
||||
|
||||
TrackChangesClient.pushRawUpdates(this.project_id, this.doc_id, [{
|
||||
op: [{ i: "f", p: 3 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 3
|
||||
}], error => {
|
||||
if (error != null) { throw error; }
|
||||
return TrackChangesClient.flushAndGetCompressedUpdates(this.project_id, this.doc_id, (error, updates) => {
|
||||
this.updates = updates;
|
||||
if (error != null) { throw error; }
|
||||
return done();
|
||||
});
|
||||
});
|
||||
return null;
|
||||
});
|
||||
TrackChangesClient.pushRawUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
[
|
||||
{
|
||||
op: [{ i: 'f', p: 3 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 3
|
||||
}
|
||||
],
|
||||
error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return TrackChangesClient.flushAndGetCompressedUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
(error, updates) => {
|
||||
this.updates = updates
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return done()
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
return null
|
||||
})
|
||||
|
||||
return it("should not add a expiresAt entry in the update in mongo", function() {
|
||||
return expect(this.updates[0].expiresAt).to.be.undefined;
|
||||
});
|
||||
});
|
||||
|
||||
return describe("when the project does not have versioning enabled", function() {
|
||||
before(function(done) {
|
||||
this.project_id = ObjectId().toString();
|
||||
this.doc_id = ObjectId().toString();
|
||||
this.user_id = ObjectId().toString();
|
||||
MockWebApi.projects[this.project_id] = {features: {versioning: false}};
|
||||
|
||||
TrackChangesClient.pushRawUpdates(this.project_id, this.doc_id, [{
|
||||
op: [{ i: "f", p: 3 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 3
|
||||
}], error => {
|
||||
if (error != null) { throw error; }
|
||||
return TrackChangesClient.flushAndGetCompressedUpdates(this.project_id, this.doc_id, (error, updates) => {
|
||||
this.updates = updates;
|
||||
if (error != null) { throw error; }
|
||||
return done();
|
||||
});
|
||||
});
|
||||
return null;
|
||||
});
|
||||
|
||||
return it("should add a expiresAt entry in the update in mongo", function() {
|
||||
return expect(this.updates[0].expiresAt).to.exist;
|
||||
});
|
||||
});
|
||||
});
|
||||
return it('should add a expiresAt entry in the update in mongo', function() {
|
||||
return expect(this.updates[0].expiresAt).to.exist
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -14,176 +14,260 @@
|
|||
* 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");
|
||||
chai.should();
|
||||
const { expect } = chai;
|
||||
const mongojs = require("../../../app/js/mongojs");
|
||||
const { db } = mongojs;
|
||||
const { ObjectId } = mongojs;
|
||||
const Settings = require("settings-sharelatex");
|
||||
const request = require("request");
|
||||
const rclient = require("redis").createClient(Settings.redis.history); // Only works locally for now
|
||||
const sinon = require('sinon')
|
||||
const chai = require('chai')
|
||||
chai.should()
|
||||
const { expect } = chai
|
||||
const mongojs = require('../../../app/js/mongojs')
|
||||
const { db } = mongojs
|
||||
const { ObjectId } = mongojs
|
||||
const Settings = require('settings-sharelatex')
|
||||
const request = require('request')
|
||||
const rclient = require('redis').createClient(Settings.redis.history) // Only works locally for now
|
||||
|
||||
const TrackChangesApp = require("./helpers/TrackChangesApp");
|
||||
const TrackChangesClient = require("./helpers/TrackChangesClient");
|
||||
const MockDocStoreApi = require("./helpers/MockDocStoreApi");
|
||||
const MockWebApi = require("./helpers/MockWebApi");
|
||||
const TrackChangesApp = require('./helpers/TrackChangesApp')
|
||||
const TrackChangesClient = require('./helpers/TrackChangesClient')
|
||||
const MockDocStoreApi = require('./helpers/MockDocStoreApi')
|
||||
const MockWebApi = require('./helpers/MockWebApi')
|
||||
|
||||
describe("Archiving updates", function() {
|
||||
before(function(done) {
|
||||
if (__guard__(__guard__(Settings != null ? Settings.trackchanges : undefined, x1 => x1.s3), x => x.key.length) < 1) {
|
||||
const message = new Error("s3 keys not setup, this test setup will fail");
|
||||
return done(message);
|
||||
}
|
||||
describe('Archiving updates', function() {
|
||||
before(function(done) {
|
||||
if (
|
||||
__guard__(
|
||||
__guard__(
|
||||
Settings != null ? Settings.trackchanges : undefined,
|
||||
x1 => x1.s3
|
||||
),
|
||||
x => x.key.length
|
||||
) < 1
|
||||
) {
|
||||
const message = new Error('s3 keys not setup, this test setup will fail')
|
||||
return done(message)
|
||||
}
|
||||
|
||||
return TrackChangesClient.waitForS3(done);
|
||||
});
|
||||
return TrackChangesClient.waitForS3(done)
|
||||
})
|
||||
|
||||
before(function(done) {
|
||||
this.now = Date.now();
|
||||
this.to = this.now;
|
||||
this.user_id = ObjectId().toString();
|
||||
this.doc_id = ObjectId().toString();
|
||||
this.project_id = ObjectId().toString();
|
||||
before(function(done) {
|
||||
this.now = Date.now()
|
||||
this.to = this.now
|
||||
this.user_id = ObjectId().toString()
|
||||
this.doc_id = ObjectId().toString()
|
||||
this.project_id = ObjectId().toString()
|
||||
|
||||
this.minutes = 60 * 1000;
|
||||
this.hours = 60 * this.minutes;
|
||||
this.minutes = 60 * 1000
|
||||
this.hours = 60 * this.minutes
|
||||
|
||||
MockWebApi.projects[this.project_id] = {
|
||||
features: {
|
||||
versioning: true
|
||||
}
|
||||
};
|
||||
sinon.spy(MockWebApi, "getProjectDetails");
|
||||
MockWebApi.projects[this.project_id] = {
|
||||
features: {
|
||||
versioning: true
|
||||
}
|
||||
}
|
||||
sinon.spy(MockWebApi, 'getProjectDetails')
|
||||
|
||||
MockWebApi.users[this.user_id] = (this.user = {
|
||||
email: "user@sharelatex.com",
|
||||
first_name: "Leo",
|
||||
last_name: "Lion",
|
||||
id: this.user_id
|
||||
});
|
||||
sinon.spy(MockWebApi, "getUserInfo");
|
||||
MockWebApi.users[this.user_id] = this.user = {
|
||||
email: 'user@sharelatex.com',
|
||||
first_name: 'Leo',
|
||||
last_name: 'Lion',
|
||||
id: this.user_id
|
||||
}
|
||||
sinon.spy(MockWebApi, 'getUserInfo')
|
||||
|
||||
MockDocStoreApi.docs[this.doc_id] = (this.doc = {
|
||||
_id: this.doc_id,
|
||||
project_id: this.project_id
|
||||
});
|
||||
sinon.spy(MockDocStoreApi, "getAllDoc");
|
||||
MockDocStoreApi.docs[this.doc_id] = this.doc = {
|
||||
_id: this.doc_id,
|
||||
project_id: this.project_id
|
||||
}
|
||||
sinon.spy(MockDocStoreApi, 'getAllDoc')
|
||||
|
||||
this.updates = [];
|
||||
for (let i = 0, end = 512+10, asc = end >= 0; asc ? i <= end : i >= end; asc ? i++ : i--) {
|
||||
this.updates.push({
|
||||
op: [{ i: "a", p: 0 }],
|
||||
meta: { ts: this.now + ((i-2048) * this.hours), user_id: this.user_id },
|
||||
v: (2 * i) + 1
|
||||
});
|
||||
this.updates.push({
|
||||
op: [{ i: "b", p: 0 }],
|
||||
meta: { ts: this.now + ((i-2048) * this.hours) + (10*this.minutes), user_id: this.user_id },
|
||||
v: (2 * i) + 2
|
||||
});
|
||||
}
|
||||
TrackChangesApp.ensureRunning(() => {
|
||||
return TrackChangesClient.pushRawUpdates(this.project_id, this.doc_id, this.updates, error => {
|
||||
if (error != null) { throw error; }
|
||||
return TrackChangesClient.flushDoc(this.project_id, this.doc_id, (error) => {
|
||||
if (error != null) { throw error; }
|
||||
return done();
|
||||
});
|
||||
});
|
||||
});
|
||||
return null;
|
||||
});
|
||||
this.updates = []
|
||||
for (
|
||||
let i = 0, end = 512 + 10, asc = end >= 0;
|
||||
asc ? i <= end : i >= end;
|
||||
asc ? i++ : i--
|
||||
) {
|
||||
this.updates.push({
|
||||
op: [{ i: 'a', p: 0 }],
|
||||
meta: { ts: this.now + (i - 2048) * this.hours, user_id: this.user_id },
|
||||
v: 2 * i + 1
|
||||
})
|
||||
this.updates.push({
|
||||
op: [{ i: 'b', p: 0 }],
|
||||
meta: {
|
||||
ts: this.now + (i - 2048) * this.hours + 10 * this.minutes,
|
||||
user_id: this.user_id
|
||||
},
|
||||
v: 2 * i + 2
|
||||
})
|
||||
}
|
||||
TrackChangesApp.ensureRunning(() => {
|
||||
return TrackChangesClient.pushRawUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.updates,
|
||||
error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return TrackChangesClient.flushDoc(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return done()
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
})
|
||||
return null
|
||||
})
|
||||
|
||||
after(function(done) {
|
||||
MockWebApi.getUserInfo.restore();
|
||||
return db.docHistory.remove({project_id: ObjectId(this.project_id)}, () => {
|
||||
return db.docHistoryIndex.remove({project_id: ObjectId(this.project_id)}, () => {
|
||||
return TrackChangesClient.removeS3Doc(this.project_id, this.doc_id, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
after(function(done) {
|
||||
MockWebApi.getUserInfo.restore()
|
||||
return db.docHistory.remove(
|
||||
{ project_id: ObjectId(this.project_id) },
|
||||
() => {
|
||||
return db.docHistoryIndex.remove(
|
||||
{ project_id: ObjectId(this.project_id) },
|
||||
() => {
|
||||
return TrackChangesClient.removeS3Doc(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
done
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
describe("archiving a doc's updates", function() {
|
||||
before(function(done) {
|
||||
TrackChangesClient.pushDocHistory(this.project_id, this.doc_id, (error) => {
|
||||
if (error != null) { throw error; }
|
||||
return done();
|
||||
});
|
||||
return null;
|
||||
});
|
||||
describe("archiving a doc's updates", function() {
|
||||
before(function(done) {
|
||||
TrackChangesClient.pushDocHistory(this.project_id, this.doc_id, error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return done()
|
||||
})
|
||||
return null
|
||||
})
|
||||
|
||||
it("should have one cached pack", function(done) {
|
||||
return db.docHistory.count({ doc_id: ObjectId(this.doc_id), expiresAt:{$exists:true}}, (error, count) => {
|
||||
if (error != null) { throw error; }
|
||||
count.should.equal(1);
|
||||
return done();
|
||||
});
|
||||
});
|
||||
it('should have one cached pack', function(done) {
|
||||
return db.docHistory.count(
|
||||
{ doc_id: ObjectId(this.doc_id), expiresAt: { $exists: true } },
|
||||
(error, count) => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
count.should.equal(1)
|
||||
return done()
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("should have one remaining pack after cache is expired", function(done) {
|
||||
return db.docHistory.remove({
|
||||
doc_id: ObjectId(this.doc_id),
|
||||
expiresAt:{$exists:true}
|
||||
}, (err, result) => {
|
||||
if (typeof error !== 'undefined' && error !== null) { throw error; }
|
||||
return db.docHistory.count({ doc_id: ObjectId(this.doc_id)}, (error, count) => {
|
||||
if (error != null) { throw error; }
|
||||
count.should.equal(1);
|
||||
return done();
|
||||
});
|
||||
});
|
||||
});
|
||||
it('should have one remaining pack after cache is expired', function(done) {
|
||||
return db.docHistory.remove(
|
||||
{
|
||||
doc_id: ObjectId(this.doc_id),
|
||||
expiresAt: { $exists: true }
|
||||
},
|
||||
(err, result) => {
|
||||
if (typeof error !== 'undefined' && error !== null) {
|
||||
throw error
|
||||
}
|
||||
return db.docHistory.count(
|
||||
{ doc_id: ObjectId(this.doc_id) },
|
||||
(error, count) => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
count.should.equal(1)
|
||||
return done()
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("should have a docHistoryIndex entry marked as inS3", function(done) {
|
||||
return db.docHistoryIndex.findOne({ _id: ObjectId(this.doc_id) }, (error, index) => {
|
||||
if (error != null) { throw error; }
|
||||
index.packs[0].inS3.should.equal(true);
|
||||
return done();
|
||||
});
|
||||
});
|
||||
it('should have a docHistoryIndex entry marked as inS3', function(done) {
|
||||
return db.docHistoryIndex.findOne(
|
||||
{ _id: ObjectId(this.doc_id) },
|
||||
(error, index) => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
index.packs[0].inS3.should.equal(true)
|
||||
return done()
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("should have a docHistoryIndex entry with the last version", function(done) {
|
||||
return db.docHistoryIndex.findOne({ _id: ObjectId(this.doc_id) }, (error, index) => {
|
||||
if (error != null) { throw error; }
|
||||
index.packs[0].v_end.should.equal(1024);
|
||||
return done();
|
||||
});
|
||||
});
|
||||
it('should have a docHistoryIndex entry with the last version', function(done) {
|
||||
return db.docHistoryIndex.findOne(
|
||||
{ _id: ObjectId(this.doc_id) },
|
||||
(error, index) => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
index.packs[0].v_end.should.equal(1024)
|
||||
return done()
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
return it("should store 1024 doc changes in S3 in one pack", function(done) {
|
||||
return db.docHistoryIndex.findOne({ _id: ObjectId(this.doc_id) }, (error, index) => {
|
||||
if (error != null) { throw error; }
|
||||
const pack_id = index.packs[0]._id;
|
||||
return TrackChangesClient.getS3Doc(this.project_id, this.doc_id, pack_id, (error, doc) => {
|
||||
doc.n.should.equal(1024);
|
||||
doc.pack.length.should.equal(1024);
|
||||
return done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
return it('should store 1024 doc changes in S3 in one pack', function(done) {
|
||||
return db.docHistoryIndex.findOne(
|
||||
{ _id: ObjectId(this.doc_id) },
|
||||
(error, index) => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
const pack_id = index.packs[0]._id
|
||||
return TrackChangesClient.getS3Doc(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
pack_id,
|
||||
(error, doc) => {
|
||||
doc.n.should.equal(1024)
|
||||
doc.pack.length.should.equal(1024)
|
||||
return done()
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
return describe("unarchiving a doc's updates", function() {
|
||||
before(function(done) {
|
||||
TrackChangesClient.pullDocHistory(this.project_id, this.doc_id, (error) => {
|
||||
if (error != null) { throw error; }
|
||||
return done();
|
||||
});
|
||||
return null;
|
||||
});
|
||||
return describe("unarchiving a doc's updates", function() {
|
||||
before(function(done) {
|
||||
TrackChangesClient.pullDocHistory(this.project_id, this.doc_id, error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return done()
|
||||
})
|
||||
return null
|
||||
})
|
||||
|
||||
return it("should restore both packs", function(done) {
|
||||
return db.docHistory.count({ doc_id: ObjectId(this.doc_id) }, (error, count) => {
|
||||
if (error != null) { throw error; }
|
||||
count.should.equal(2);
|
||||
return done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
return it('should restore both packs', function(done) {
|
||||
return db.docHistory.count(
|
||||
{ doc_id: ObjectId(this.doc_id) },
|
||||
(error, count) => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
count.should.equal(2)
|
||||
return done()
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
function __guard__(value, transform) {
|
||||
return (typeof value !== 'undefined' && value !== null) ? transform(value) : undefined;
|
||||
}
|
||||
return typeof value !== 'undefined' && value !== null
|
||||
? transform(value)
|
||||
: undefined
|
||||
}
|
||||
|
|
|
@ -10,188 +10,267 @@
|
|||
* 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");
|
||||
chai.should();
|
||||
const { expect } = chai;
|
||||
const mongojs = require("../../../app/js/mongojs");
|
||||
const { ObjectId } = mongojs;
|
||||
const Settings = require("settings-sharelatex");
|
||||
const request = require("request");
|
||||
const rclient = require("redis").createClient(Settings.redis.history); // Only works locally for now
|
||||
const sinon = require('sinon')
|
||||
const chai = require('chai')
|
||||
chai.should()
|
||||
const { expect } = chai
|
||||
const mongojs = require('../../../app/js/mongojs')
|
||||
const { ObjectId } = mongojs
|
||||
const Settings = require('settings-sharelatex')
|
||||
const request = require('request')
|
||||
const rclient = require('redis').createClient(Settings.redis.history) // Only works locally for now
|
||||
|
||||
const TrackChangesApp = require("./helpers/TrackChangesApp");
|
||||
const TrackChangesClient = require("./helpers/TrackChangesClient");
|
||||
const MockWebApi = require("./helpers/MockWebApi");
|
||||
const TrackChangesApp = require('./helpers/TrackChangesApp')
|
||||
const TrackChangesClient = require('./helpers/TrackChangesClient')
|
||||
const MockWebApi = require('./helpers/MockWebApi')
|
||||
|
||||
describe("Flushing updates", function() {
|
||||
before(function(done) { return TrackChangesApp.ensureRunning(done); });
|
||||
describe('Flushing updates', function() {
|
||||
before(function(done) {
|
||||
return TrackChangesApp.ensureRunning(done)
|
||||
})
|
||||
|
||||
describe("flushing a doc's updates", function() {
|
||||
before(function(done) {
|
||||
this.project_id = ObjectId().toString();
|
||||
this.doc_id = ObjectId().toString();
|
||||
this.user_id = ObjectId().toString();
|
||||
MockWebApi.projects[this.project_id] = {features: {versioning: true}};
|
||||
describe("flushing a doc's updates", function() {
|
||||
before(function(done) {
|
||||
this.project_id = ObjectId().toString()
|
||||
this.doc_id = ObjectId().toString()
|
||||
this.user_id = ObjectId().toString()
|
||||
MockWebApi.projects[this.project_id] = { features: { versioning: true } }
|
||||
|
||||
TrackChangesClient.pushRawUpdates(this.project_id, this.doc_id, [{
|
||||
op: [{ i: "f", p: 3 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 3
|
||||
}], error => {
|
||||
if (error != null) { throw error; }
|
||||
return TrackChangesClient.flushDoc(this.project_id, this.doc_id, (error) => {
|
||||
if (error != null) { throw error; }
|
||||
return done();
|
||||
});
|
||||
});
|
||||
return null;
|
||||
});
|
||||
TrackChangesClient.pushRawUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
[
|
||||
{
|
||||
op: [{ i: 'f', p: 3 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 3
|
||||
}
|
||||
],
|
||||
error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return TrackChangesClient.flushDoc(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return done()
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
return null
|
||||
})
|
||||
|
||||
return it("should flush the op into mongo", function(done) {
|
||||
TrackChangesClient.getCompressedUpdates(this.doc_id, (error, updates) => {
|
||||
expect(updates[0].pack[0].op).to.deep.equal([{
|
||||
p: 3, i: "f"
|
||||
}]);
|
||||
return done();
|
||||
});
|
||||
return null;
|
||||
});
|
||||
});
|
||||
return it('should flush the op into mongo', function(done) {
|
||||
TrackChangesClient.getCompressedUpdates(this.doc_id, (error, updates) => {
|
||||
expect(updates[0].pack[0].op).to.deep.equal([
|
||||
{
|
||||
p: 3,
|
||||
i: 'f'
|
||||
}
|
||||
])
|
||||
return done()
|
||||
})
|
||||
return null
|
||||
})
|
||||
})
|
||||
|
||||
return describe("flushing a project's updates", function() {
|
||||
describe("with versioning enabled", function() {
|
||||
before(function(done) {
|
||||
this.project_id = ObjectId().toString();
|
||||
this.doc_id = ObjectId().toString();
|
||||
this.user_id = ObjectId().toString();
|
||||
return describe("flushing a project's updates", function() {
|
||||
describe('with versioning enabled', function() {
|
||||
before(function(done) {
|
||||
this.project_id = ObjectId().toString()
|
||||
this.doc_id = ObjectId().toString()
|
||||
this.user_id = ObjectId().toString()
|
||||
|
||||
this.weeks = 7 * 24 * 60 * 60 * 1000;
|
||||
this.weeks = 7 * 24 * 60 * 60 * 1000
|
||||
|
||||
MockWebApi.projects[this.project_id] = {
|
||||
features: {
|
||||
versioning: true
|
||||
}
|
||||
};
|
||||
MockWebApi.projects[this.project_id] = {
|
||||
features: {
|
||||
versioning: true
|
||||
}
|
||||
}
|
||||
|
||||
TrackChangesClient.pushRawUpdates(this.project_id, this.doc_id, [{
|
||||
op: [{ i: "g", p: 2 }],
|
||||
meta: { ts: Date.now() - (2 * this.weeks), user_id: this.user_id },
|
||||
v: 2
|
||||
}, {
|
||||
op: [{ i: "f", p: 3 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 3
|
||||
}], error => {
|
||||
if (error != null) { throw error; }
|
||||
return TrackChangesClient.flushProject(this.project_id, (error) => {
|
||||
if (error != null) { throw error; }
|
||||
return done();
|
||||
});
|
||||
});
|
||||
return null;
|
||||
});
|
||||
TrackChangesClient.pushRawUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
[
|
||||
{
|
||||
op: [{ i: 'g', p: 2 }],
|
||||
meta: { ts: Date.now() - 2 * this.weeks, user_id: this.user_id },
|
||||
v: 2
|
||||
},
|
||||
{
|
||||
op: [{ i: 'f', p: 3 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 3
|
||||
}
|
||||
],
|
||||
error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return TrackChangesClient.flushProject(this.project_id, error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return done()
|
||||
})
|
||||
}
|
||||
)
|
||||
return null
|
||||
})
|
||||
|
||||
it("should not mark the updates for deletion", function(done) {
|
||||
TrackChangesClient.getCompressedUpdates(this.doc_id, (error, updates) => {
|
||||
expect(updates[0].expiresAt).to.not.exist;
|
||||
return done();
|
||||
});
|
||||
return null;
|
||||
});
|
||||
it('should not mark the updates for deletion', function(done) {
|
||||
TrackChangesClient.getCompressedUpdates(
|
||||
this.doc_id,
|
||||
(error, updates) => {
|
||||
expect(updates[0].expiresAt).to.not.exist
|
||||
return done()
|
||||
}
|
||||
)
|
||||
return null
|
||||
})
|
||||
|
||||
return it("should preserve history forever", function(done) {
|
||||
TrackChangesClient.getProjectMetaData(this.project_id, (error, project) => {
|
||||
expect(project.preserveHistory).to.equal(true);
|
||||
return done();
|
||||
});
|
||||
return null;
|
||||
});
|
||||
});
|
||||
return it('should preserve history forever', function(done) {
|
||||
TrackChangesClient.getProjectMetaData(
|
||||
this.project_id,
|
||||
(error, project) => {
|
||||
expect(project.preserveHistory).to.equal(true)
|
||||
return done()
|
||||
}
|
||||
)
|
||||
return null
|
||||
})
|
||||
})
|
||||
|
||||
describe("without versioning enabled", function() {
|
||||
before(function(done) {
|
||||
this.project_id = ObjectId().toString();
|
||||
this.doc_id = ObjectId().toString();
|
||||
this.user_id = ObjectId().toString();
|
||||
describe('without versioning enabled', function() {
|
||||
before(function(done) {
|
||||
this.project_id = ObjectId().toString()
|
||||
this.doc_id = ObjectId().toString()
|
||||
this.user_id = ObjectId().toString()
|
||||
|
||||
this.weeks = 7 * 24 * 60 * 60 * 1000;
|
||||
this.weeks = 7 * 24 * 60 * 60 * 1000
|
||||
|
||||
MockWebApi.projects[this.project_id] = {
|
||||
features: {
|
||||
versioning: false
|
||||
}
|
||||
};
|
||||
MockWebApi.projects[this.project_id] = {
|
||||
features: {
|
||||
versioning: false
|
||||
}
|
||||
}
|
||||
|
||||
TrackChangesClient.pushRawUpdates(this.project_id, this.doc_id, [{
|
||||
op: [{ i: "g", p: 2 }],
|
||||
meta: { ts: Date.now() - (2 * this.weeks), user_id: this.user_id },
|
||||
v: 2
|
||||
}, {
|
||||
op: [{ i: "f", p: 3 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 3
|
||||
}], error => {
|
||||
if (error != null) { throw error; }
|
||||
return TrackChangesClient.flushProject(this.project_id, (error) => {
|
||||
if (error != null) { throw error; }
|
||||
return done();
|
||||
});
|
||||
});
|
||||
return null;
|
||||
});
|
||||
TrackChangesClient.pushRawUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
[
|
||||
{
|
||||
op: [{ i: 'g', p: 2 }],
|
||||
meta: { ts: Date.now() - 2 * this.weeks, user_id: this.user_id },
|
||||
v: 2
|
||||
},
|
||||
{
|
||||
op: [{ i: 'f', p: 3 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 3
|
||||
}
|
||||
],
|
||||
error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return TrackChangesClient.flushProject(this.project_id, error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return done()
|
||||
})
|
||||
}
|
||||
)
|
||||
return null
|
||||
})
|
||||
|
||||
return it("should mark the updates for deletion", function(done) {
|
||||
TrackChangesClient.getCompressedUpdates(this.doc_id, (error, updates) => {
|
||||
expect(updates[0].expiresAt).to.exist;
|
||||
return done();
|
||||
});
|
||||
return null;
|
||||
});
|
||||
});
|
||||
return it('should mark the updates for deletion', function(done) {
|
||||
TrackChangesClient.getCompressedUpdates(
|
||||
this.doc_id,
|
||||
(error, updates) => {
|
||||
expect(updates[0].expiresAt).to.exist
|
||||
return done()
|
||||
}
|
||||
)
|
||||
return null
|
||||
})
|
||||
})
|
||||
|
||||
return describe("without versioning enabled but with preserveHistory set to true", function() {
|
||||
before(function(done) {
|
||||
this.project_id = ObjectId().toString();
|
||||
this.doc_id = ObjectId().toString();
|
||||
this.user_id = ObjectId().toString();
|
||||
return describe('without versioning enabled but with preserveHistory set to true', function() {
|
||||
before(function(done) {
|
||||
this.project_id = ObjectId().toString()
|
||||
this.doc_id = ObjectId().toString()
|
||||
this.user_id = ObjectId().toString()
|
||||
|
||||
this.weeks = 7 * 24 * 60 * 60 * 1000;
|
||||
this.weeks = 7 * 24 * 60 * 60 * 1000
|
||||
|
||||
MockWebApi.projects[this.project_id] = {
|
||||
features: {
|
||||
versioning: false
|
||||
}
|
||||
};
|
||||
MockWebApi.projects[this.project_id] = {
|
||||
features: {
|
||||
versioning: false
|
||||
}
|
||||
}
|
||||
|
||||
TrackChangesClient.setPreserveHistoryForProject(this.project_id, error => {
|
||||
if (error != null) { throw error; }
|
||||
return TrackChangesClient.pushRawUpdates(this.project_id, this.doc_id, [{
|
||||
op: [{ i: "g", p: 2 }],
|
||||
meta: { ts: Date.now() - (2 * this.weeks), user_id: this.user_id },
|
||||
v: 2
|
||||
}, {
|
||||
op: [{ i: "f", p: 3 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 3
|
||||
}], error => {
|
||||
if (error != null) { throw error; }
|
||||
return TrackChangesClient.flushProject(this.project_id, (error) => {
|
||||
if (error != null) { throw error; }
|
||||
return done();
|
||||
});
|
||||
});
|
||||
});
|
||||
return null;
|
||||
});
|
||||
TrackChangesClient.setPreserveHistoryForProject(
|
||||
this.project_id,
|
||||
error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return TrackChangesClient.pushRawUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
[
|
||||
{
|
||||
op: [{ i: 'g', p: 2 }],
|
||||
meta: {
|
||||
ts: Date.now() - 2 * this.weeks,
|
||||
user_id: this.user_id
|
||||
},
|
||||
v: 2
|
||||
},
|
||||
{
|
||||
op: [{ i: 'f', p: 3 }],
|
||||
meta: { ts: Date.now(), user_id: this.user_id },
|
||||
v: 3
|
||||
}
|
||||
],
|
||||
error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return TrackChangesClient.flushProject(
|
||||
this.project_id,
|
||||
error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return done()
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
return null
|
||||
})
|
||||
|
||||
return it("should not mark the updates for deletion", function(done) {
|
||||
TrackChangesClient.getCompressedUpdates(this.doc_id, (error, updates) => {
|
||||
expect(updates[0].expiresAt).to.not.exist;
|
||||
return done();
|
||||
});
|
||||
return null;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
return it('should not mark the updates for deletion', function(done) {
|
||||
TrackChangesClient.getCompressedUpdates(
|
||||
this.doc_id,
|
||||
(error, updates) => {
|
||||
expect(updates[0].expiresAt).to.not.exist
|
||||
return done()
|
||||
}
|
||||
)
|
||||
return null
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -9,97 +9,123 @@
|
|||
* 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");
|
||||
chai.should();
|
||||
const { expect } = chai;
|
||||
const mongojs = require("../../../app/js/mongojs");
|
||||
const { db } = mongojs;
|
||||
const { ObjectId } = mongojs;
|
||||
const Settings = require("settings-sharelatex");
|
||||
const sinon = require('sinon')
|
||||
const chai = require('chai')
|
||||
chai.should()
|
||||
const { expect } = chai
|
||||
const mongojs = require('../../../app/js/mongojs')
|
||||
const { db } = mongojs
|
||||
const { ObjectId } = mongojs
|
||||
const Settings = require('settings-sharelatex')
|
||||
|
||||
const TrackChangesApp = require("./helpers/TrackChangesApp");
|
||||
const TrackChangesClient = require("./helpers/TrackChangesClient");
|
||||
const MockDocUpdaterApi = require("./helpers/MockDocUpdaterApi");
|
||||
const MockWebApi = require("./helpers/MockWebApi");
|
||||
const TrackChangesApp = require('./helpers/TrackChangesApp')
|
||||
const TrackChangesClient = require('./helpers/TrackChangesClient')
|
||||
const MockDocUpdaterApi = require('./helpers/MockDocUpdaterApi')
|
||||
const MockWebApi = require('./helpers/MockWebApi')
|
||||
|
||||
describe("Getting a diff", function() {
|
||||
describe('Getting a diff', function() {
|
||||
beforeEach(function(done) {
|
||||
sinon.spy(MockDocUpdaterApi, 'getDoc')
|
||||
|
||||
beforeEach(function(done) {
|
||||
sinon.spy(MockDocUpdaterApi, "getDoc");
|
||||
this.now = Date.now()
|
||||
this.from = this.now - 100000000
|
||||
this.to = this.now
|
||||
this.user_id = ObjectId().toString()
|
||||
this.doc_id = ObjectId().toString()
|
||||
this.project_id = ObjectId().toString()
|
||||
MockWebApi.projects[this.project_id] = { features: { versioning: true } }
|
||||
|
||||
this.now = Date.now();
|
||||
this.from = this.now - 100000000;
|
||||
this.to = this.now;
|
||||
this.user_id = ObjectId().toString();
|
||||
this.doc_id = ObjectId().toString();
|
||||
this.project_id = ObjectId().toString();
|
||||
MockWebApi.projects[this.project_id] = {features: {versioning: true}};
|
||||
MockWebApi.users[this.user_id] = this.user = {
|
||||
email: 'user@sharelatex.com',
|
||||
first_name: 'Leo',
|
||||
last_name: 'Lion',
|
||||
id: this.user_id
|
||||
}
|
||||
sinon.spy(MockWebApi, 'getUserInfo')
|
||||
|
||||
MockWebApi.users[this.user_id] = (this.user = {
|
||||
email: "user@sharelatex.com",
|
||||
first_name: "Leo",
|
||||
last_name: "Lion",
|
||||
id: this.user_id
|
||||
});
|
||||
sinon.spy(MockWebApi, "getUserInfo");
|
||||
const twoMinutes = 2 * 60 * 1000
|
||||
|
||||
const twoMinutes = 2 * 60 * 1000;
|
||||
this.updates = [
|
||||
{
|
||||
op: [{ i: 'one ', p: 0 }],
|
||||
meta: { ts: this.from - twoMinutes, user_id: this.user_id },
|
||||
v: 3
|
||||
},
|
||||
{
|
||||
op: [{ i: 'two ', p: 4 }],
|
||||
meta: { ts: this.from + twoMinutes, user_id: this.user_id },
|
||||
v: (this.fromVersion = 4)
|
||||
},
|
||||
{
|
||||
op: [{ i: 'three ', p: 8 }],
|
||||
meta: { ts: this.to - twoMinutes, user_id: this.user_id },
|
||||
v: (this.toVersion = 5)
|
||||
},
|
||||
{
|
||||
op: [{ i: 'four', p: 14 }],
|
||||
meta: { ts: this.to + twoMinutes, user_id: this.user_id },
|
||||
v: 6
|
||||
}
|
||||
]
|
||||
this.lines = ['one two three four']
|
||||
this.expected_diff = [
|
||||
{ u: 'one ' },
|
||||
{
|
||||
i: 'two three ',
|
||||
meta: {
|
||||
start_ts: this.from + twoMinutes,
|
||||
end_ts: this.to - twoMinutes,
|
||||
user: this.user
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
this.updates = [{
|
||||
op: [{ i: "one ", p: 0 }],
|
||||
meta: { ts: this.from - twoMinutes, user_id: this.user_id },
|
||||
v: 3
|
||||
}, {
|
||||
op: [{ i: "two ", p: 4 }],
|
||||
meta: { ts: this.from + twoMinutes, user_id: this.user_id },
|
||||
v: (this.fromVersion = 4)
|
||||
}, {
|
||||
op: [{ i: "three ", p: 8 }],
|
||||
meta: { ts: this.to - twoMinutes, user_id: this.user_id },
|
||||
v: (this.toVersion = 5)
|
||||
}, {
|
||||
op: [{ i: "four", p: 14 }],
|
||||
meta: { ts: this.to + twoMinutes, user_id: this.user_id },
|
||||
v: 6
|
||||
}];
|
||||
this.lines = ["one two three four"];
|
||||
this.expected_diff = [
|
||||
{ u: "one " },
|
||||
{ i: "two three ", meta: { start_ts: this.from + twoMinutes, end_ts: this.to - twoMinutes, user: this.user } }
|
||||
];
|
||||
MockDocUpdaterApi.docs[this.doc_id] = {
|
||||
lines: this.lines,
|
||||
version: 7
|
||||
}
|
||||
TrackChangesApp.ensureRunning(() => {
|
||||
return TrackChangesClient.pushRawUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.updates,
|
||||
error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return TrackChangesClient.getDiff(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.fromVersion,
|
||||
this.toVersion,
|
||||
(error, diff) => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
this.diff = diff.diff
|
||||
return done()
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
})
|
||||
return null
|
||||
})
|
||||
|
||||
MockDocUpdaterApi.docs[this.doc_id] = {
|
||||
lines: this.lines,
|
||||
version: 7
|
||||
};
|
||||
TrackChangesApp.ensureRunning(() => {
|
||||
return TrackChangesClient.pushRawUpdates(this.project_id, this.doc_id, this.updates, error => {
|
||||
if (error != null) { throw error; }
|
||||
return TrackChangesClient.getDiff(this.project_id, this.doc_id, this.fromVersion, this.toVersion, (error, diff) => {
|
||||
if (error != null) { throw error; }
|
||||
this.diff = diff.diff;
|
||||
return done();
|
||||
});
|
||||
});
|
||||
});
|
||||
return null;
|
||||
});
|
||||
afterEach(function() {
|
||||
MockDocUpdaterApi.getDoc.restore()
|
||||
MockWebApi.getUserInfo.restore()
|
||||
return null
|
||||
})
|
||||
|
||||
afterEach(function() {
|
||||
MockDocUpdaterApi.getDoc.restore();
|
||||
MockWebApi.getUserInfo.restore();
|
||||
return null;
|
||||
});
|
||||
it('should return the diff', function() {
|
||||
return expect(this.diff).to.deep.equal(this.expected_diff)
|
||||
})
|
||||
|
||||
it("should return the diff", function() {
|
||||
return expect(this.diff).to.deep.equal(this.expected_diff);
|
||||
});
|
||||
|
||||
return it("should get the doc from the doc updater", function() {
|
||||
MockDocUpdaterApi.getDoc
|
||||
.calledWith(this.project_id, this.doc_id)
|
||||
.should.equal(true);
|
||||
return null;
|
||||
});
|
||||
});
|
||||
return it('should get the doc from the doc updater', function() {
|
||||
MockDocUpdaterApi.getDoc
|
||||
.calledWith(this.project_id, this.doc_id)
|
||||
.should.equal(true)
|
||||
return null
|
||||
})
|
||||
})
|
||||
|
|
|
@ -10,154 +10,181 @@
|
|||
* 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");
|
||||
chai.should();
|
||||
const { expect } = chai;
|
||||
const mongojs = require("../../../app/js/mongojs");
|
||||
const { db } = mongojs;
|
||||
const { ObjectId } = mongojs;
|
||||
const Settings = require("settings-sharelatex");
|
||||
const sinon = require('sinon')
|
||||
const chai = require('chai')
|
||||
chai.should()
|
||||
const { expect } = chai
|
||||
const mongojs = require('../../../app/js/mongojs')
|
||||
const { db } = mongojs
|
||||
const { ObjectId } = mongojs
|
||||
const Settings = require('settings-sharelatex')
|
||||
|
||||
const TrackChangesApp = require("./helpers/TrackChangesApp");
|
||||
const TrackChangesClient = require("./helpers/TrackChangesClient");
|
||||
const MockWebApi = require("./helpers/MockWebApi");
|
||||
const TrackChangesApp = require('./helpers/TrackChangesApp')
|
||||
const TrackChangesClient = require('./helpers/TrackChangesClient')
|
||||
const MockWebApi = require('./helpers/MockWebApi')
|
||||
|
||||
describe("Getting updates", function() {
|
||||
before(function(done) {
|
||||
this.now = Date.now();
|
||||
this.to = this.now;
|
||||
this.user_id = ObjectId().toString();
|
||||
this.deleted_user_id = 'deleted_user';
|
||||
this.doc_id = ObjectId().toString();
|
||||
this.project_id = ObjectId().toString();
|
||||
describe('Getting updates', function() {
|
||||
before(function(done) {
|
||||
this.now = Date.now()
|
||||
this.to = this.now
|
||||
this.user_id = ObjectId().toString()
|
||||
this.deleted_user_id = 'deleted_user'
|
||||
this.doc_id = ObjectId().toString()
|
||||
this.project_id = ObjectId().toString()
|
||||
|
||||
this.minutes = 60 * 1000;
|
||||
this.hours = 60 * this.minutes;
|
||||
this.minutes = 60 * 1000
|
||||
this.hours = 60 * this.minutes
|
||||
|
||||
MockWebApi.projects[this.project_id] = {
|
||||
features: {
|
||||
versioning: true
|
||||
}
|
||||
};
|
||||
MockWebApi.projects[this.project_id] = {
|
||||
features: {
|
||||
versioning: true
|
||||
}
|
||||
}
|
||||
|
||||
MockWebApi.users[this.user_id] = (this.user = {
|
||||
email: "user@sharelatex.com",
|
||||
first_name: "Leo",
|
||||
last_name: "Lion",
|
||||
id: this.user_id
|
||||
});
|
||||
sinon.spy(MockWebApi, "getUserInfo");
|
||||
MockWebApi.users[this.user_id] = this.user = {
|
||||
email: 'user@sharelatex.com',
|
||||
first_name: 'Leo',
|
||||
last_name: 'Lion',
|
||||
id: this.user_id
|
||||
}
|
||||
sinon.spy(MockWebApi, 'getUserInfo')
|
||||
|
||||
this.updates = [];
|
||||
for (let i = 0; i <= 9; i++) {
|
||||
this.updates.push({
|
||||
op: [{ i: "a", p: 0 }],
|
||||
meta: { ts: this.now - ((9 - i) * this.hours) - (2 * this.minutes), user_id: this.user_id },
|
||||
v: (2 * i) + 1
|
||||
});
|
||||
this.updates.push({
|
||||
op: [{ i: "b", p: 0 }],
|
||||
meta: { ts: this.now - ((9 - i) * this.hours), user_id: this.user_id },
|
||||
v: (2 * i) + 2
|
||||
});
|
||||
}
|
||||
this.updates[0].meta.user_id = this.deleted_user_id;
|
||||
this.updates = []
|
||||
for (let i = 0; i <= 9; i++) {
|
||||
this.updates.push({
|
||||
op: [{ i: 'a', p: 0 }],
|
||||
meta: {
|
||||
ts: this.now - (9 - i) * this.hours - 2 * this.minutes,
|
||||
user_id: this.user_id
|
||||
},
|
||||
v: 2 * i + 1
|
||||
})
|
||||
this.updates.push({
|
||||
op: [{ i: 'b', p: 0 }],
|
||||
meta: { ts: this.now - (9 - i) * this.hours, user_id: this.user_id },
|
||||
v: 2 * i + 2
|
||||
})
|
||||
}
|
||||
this.updates[0].meta.user_id = this.deleted_user_id
|
||||
|
||||
TrackChangesApp.ensureRunning(() => {
|
||||
return TrackChangesClient.pushRawUpdates(this.project_id, this.doc_id, this.updates, error => {
|
||||
if (error != null) { throw error; }
|
||||
return done();
|
||||
});
|
||||
});
|
||||
return null;
|
||||
});
|
||||
TrackChangesApp.ensureRunning(() => {
|
||||
return TrackChangesClient.pushRawUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.updates,
|
||||
error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return done()
|
||||
}
|
||||
)
|
||||
})
|
||||
return null
|
||||
})
|
||||
|
||||
({
|
||||
after() {
|
||||
MockWebApi.getUserInfo.restore();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
;({
|
||||
after() {
|
||||
MockWebApi.getUserInfo.restore()
|
||||
return null
|
||||
}
|
||||
})
|
||||
|
||||
describe("getting updates up to the limit", function() {
|
||||
before(function(done) {
|
||||
TrackChangesClient.getUpdates(this.project_id, { before: this.to + 1, min_count: 3 }, (error, body) => {
|
||||
if (error != null) { throw error; }
|
||||
this.updates = body.updates;
|
||||
return done();
|
||||
});
|
||||
return null;
|
||||
});
|
||||
describe('getting updates up to the limit', function() {
|
||||
before(function(done) {
|
||||
TrackChangesClient.getUpdates(
|
||||
this.project_id,
|
||||
{ before: this.to + 1, min_count: 3 },
|
||||
(error, body) => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
this.updates = body.updates
|
||||
return done()
|
||||
}
|
||||
)
|
||||
return null
|
||||
})
|
||||
|
||||
it("should fetch the user details from the web api", function() {
|
||||
return MockWebApi.getUserInfo
|
||||
.calledWith(this.user_id)
|
||||
.should.equal(true);
|
||||
});
|
||||
it('should fetch the user details from the web api', function() {
|
||||
return MockWebApi.getUserInfo.calledWith(this.user_id).should.equal(true)
|
||||
})
|
||||
|
||||
return it("should return at least the min_count number of summarized updates", function() {
|
||||
const docs1 = {};
|
||||
docs1[this.doc_id] = {toV: 20, fromV: 19};
|
||||
const docs2 = {};
|
||||
docs2[this.doc_id] = {toV: 18, fromV: 17};
|
||||
const docs3 = {};
|
||||
docs3[this.doc_id] = {toV: 16, fromV: 15};
|
||||
return expect(this.updates.slice(0,3)).to.deep.equal([{
|
||||
docs: docs1,
|
||||
meta: {
|
||||
start_ts: this.to - (2 * this.minutes),
|
||||
end_ts: this.to,
|
||||
users: [this.user]
|
||||
}
|
||||
}, {
|
||||
docs: docs2,
|
||||
meta: {
|
||||
start_ts: this.to - (1 * this.hours) - (2 * this.minutes),
|
||||
end_ts: this.to - (1 * this.hours),
|
||||
users: [this.user]
|
||||
}
|
||||
}, {
|
||||
docs: docs3,
|
||||
meta: {
|
||||
start_ts: this.to - (2 * this.hours) - (2 * this.minutes),
|
||||
end_ts: this.to - (2 * this.hours),
|
||||
users: [this.user]
|
||||
}
|
||||
}]);
|
||||
});
|
||||
});
|
||||
return it('should return at least the min_count number of summarized updates', function() {
|
||||
const docs1 = {}
|
||||
docs1[this.doc_id] = { toV: 20, fromV: 19 }
|
||||
const docs2 = {}
|
||||
docs2[this.doc_id] = { toV: 18, fromV: 17 }
|
||||
const docs3 = {}
|
||||
docs3[this.doc_id] = { toV: 16, fromV: 15 }
|
||||
return expect(this.updates.slice(0, 3)).to.deep.equal([
|
||||
{
|
||||
docs: docs1,
|
||||
meta: {
|
||||
start_ts: this.to - 2 * this.minutes,
|
||||
end_ts: this.to,
|
||||
users: [this.user]
|
||||
}
|
||||
},
|
||||
{
|
||||
docs: docs2,
|
||||
meta: {
|
||||
start_ts: this.to - 1 * this.hours - 2 * this.minutes,
|
||||
end_ts: this.to - 1 * this.hours,
|
||||
users: [this.user]
|
||||
}
|
||||
},
|
||||
{
|
||||
docs: docs3,
|
||||
meta: {
|
||||
start_ts: this.to - 2 * this.hours - 2 * this.minutes,
|
||||
end_ts: this.to - 2 * this.hours,
|
||||
users: [this.user]
|
||||
}
|
||||
}
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
return describe("getting updates beyond the end of the database", function() {
|
||||
before(function(done) {
|
||||
TrackChangesClient.getUpdates(this.project_id, { before: (this.to - (8 * this.hours)) + 1, min_count: 30 }, (error, body) => {
|
||||
if (error != null) { throw error; }
|
||||
this.updates = body.updates;
|
||||
return done();
|
||||
});
|
||||
return null;
|
||||
});
|
||||
return describe('getting updates beyond the end of the database', function() {
|
||||
before(function(done) {
|
||||
TrackChangesClient.getUpdates(
|
||||
this.project_id,
|
||||
{ before: this.to - 8 * this.hours + 1, min_count: 30 },
|
||||
(error, body) => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
this.updates = body.updates
|
||||
return done()
|
||||
}
|
||||
)
|
||||
return null
|
||||
})
|
||||
|
||||
return it("should return as many updates as it can", function() {
|
||||
const docs1 = {};
|
||||
docs1[this.doc_id] = {toV: 4, fromV: 3};
|
||||
const docs2 = {};
|
||||
docs2[this.doc_id] = {toV: 2, fromV: 1};
|
||||
return expect(this.updates).to.deep.equal([{
|
||||
docs: docs1,
|
||||
meta: {
|
||||
start_ts: this.to - (8 * this.hours) - (2 * this.minutes),
|
||||
end_ts: this.to - (8 * this.hours),
|
||||
users: [this.user]
|
||||
}
|
||||
}, {
|
||||
docs: docs2,
|
||||
meta: {
|
||||
start_ts: this.to - (9 * this.hours) - (2 * this.minutes),
|
||||
end_ts: this.to - (9 * this.hours),
|
||||
users: [this.user, null]
|
||||
}
|
||||
}]);
|
||||
});
|
||||
});
|
||||
});
|
||||
return it('should return as many updates as it can', function() {
|
||||
const docs1 = {}
|
||||
docs1[this.doc_id] = { toV: 4, fromV: 3 }
|
||||
const docs2 = {}
|
||||
docs2[this.doc_id] = { toV: 2, fromV: 1 }
|
||||
return expect(this.updates).to.deep.equal([
|
||||
{
|
||||
docs: docs1,
|
||||
meta: {
|
||||
start_ts: this.to - 8 * this.hours - 2 * this.minutes,
|
||||
end_ts: this.to - 8 * this.hours,
|
||||
users: [this.user]
|
||||
}
|
||||
},
|
||||
{
|
||||
docs: docs2,
|
||||
meta: {
|
||||
start_ts: this.to - 9 * this.hours - 2 * this.minutes,
|
||||
end_ts: this.to - 9 * this.hours,
|
||||
users: [this.user, null]
|
||||
}
|
||||
}
|
||||
])
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -9,52 +9,58 @@
|
|||
* 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");
|
||||
chai.should();
|
||||
const { expect } = chai;
|
||||
const mongojs = require("../../../app/js/mongojs");
|
||||
const { ObjectId } = mongojs;
|
||||
const Settings = require("settings-sharelatex");
|
||||
const LockManager = require("../../../app/js/LockManager");
|
||||
const rclient = require("redis").createClient(Settings.redis.history); // Only works locally for now
|
||||
const TrackChangesApp = require("./helpers/TrackChangesApp");
|
||||
const sinon = require('sinon')
|
||||
const chai = require('chai')
|
||||
chai.should()
|
||||
const { expect } = chai
|
||||
const mongojs = require('../../../app/js/mongojs')
|
||||
const { ObjectId } = mongojs
|
||||
const Settings = require('settings-sharelatex')
|
||||
const LockManager = require('../../../app/js/LockManager')
|
||||
const rclient = require('redis').createClient(Settings.redis.history) // Only works locally for now
|
||||
const TrackChangesApp = require('./helpers/TrackChangesApp')
|
||||
|
||||
describe("Locking document", function() {
|
||||
describe('Locking document', function() {
|
||||
before(function(done) {
|
||||
TrackChangesApp.ensureRunning(done)
|
||||
return null
|
||||
})
|
||||
|
||||
before(function(done){
|
||||
TrackChangesApp.ensureRunning(done);
|
||||
return null;
|
||||
});
|
||||
|
||||
return describe("when the lock has expired in redis", function() {
|
||||
before(function(done) {
|
||||
LockManager.LOCK_TTL = 1; // second
|
||||
LockManager.runWithLock("doc123", releaseA => {
|
||||
// we create a lock A and allow it to expire in redis
|
||||
return setTimeout(() =>
|
||||
// now we create a new lock B and try to release A
|
||||
LockManager.runWithLock("doc123", releaseB => {
|
||||
return releaseA();
|
||||
} // try to release lock A to see if it wipes out lock B
|
||||
, (error) => {})
|
||||
|
||||
// we never release lock B so nothing should happen here
|
||||
, 1500);
|
||||
} // enough time to wait until the lock has expired
|
||||
, error =>
|
||||
// we get here after trying to release lock A
|
||||
done()
|
||||
);
|
||||
return null;
|
||||
});
|
||||
return describe('when the lock has expired in redis', function() {
|
||||
before(function(done) {
|
||||
LockManager.LOCK_TTL = 1 // second
|
||||
LockManager.runWithLock(
|
||||
'doc123',
|
||||
releaseA => {
|
||||
// we create a lock A and allow it to expire in redis
|
||||
return setTimeout(
|
||||
() =>
|
||||
// now we create a new lock B and try to release A
|
||||
LockManager.runWithLock(
|
||||
'doc123',
|
||||
releaseB => {
|
||||
return releaseA()
|
||||
}, // try to release lock A to see if it wipes out lock B
|
||||
error => {}
|
||||
),
|
||||
|
||||
return it("the new lock should not be removed by the expired locker", function(done) {
|
||||
LockManager.checkLock("doc123", (err, isFree) => {
|
||||
expect(isFree).to.equal(false);
|
||||
return done();
|
||||
});
|
||||
return null;
|
||||
});
|
||||
});
|
||||
});
|
||||
// we never release lock B so nothing should happen here
|
||||
1500
|
||||
)
|
||||
}, // enough time to wait until the lock has expired
|
||||
error =>
|
||||
// we get here after trying to release lock A
|
||||
done()
|
||||
)
|
||||
return null
|
||||
})
|
||||
|
||||
return it('the new lock should not be removed by the expired locker', function(done) {
|
||||
LockManager.checkLock('doc123', (err, isFree) => {
|
||||
expect(isFree).to.equal(false)
|
||||
return done()
|
||||
})
|
||||
return null
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -9,86 +9,112 @@
|
|||
* 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");
|
||||
chai.should();
|
||||
const { expect } = chai;
|
||||
const mongojs = require("../../../app/js/mongojs");
|
||||
const { db } = mongojs;
|
||||
const { ObjectId } = mongojs;
|
||||
const Settings = require("settings-sharelatex");
|
||||
const sinon = require('sinon')
|
||||
const chai = require('chai')
|
||||
chai.should()
|
||||
const { expect } = chai
|
||||
const mongojs = require('../../../app/js/mongojs')
|
||||
const { db } = mongojs
|
||||
const { ObjectId } = mongojs
|
||||
const Settings = require('settings-sharelatex')
|
||||
|
||||
const TrackChangesApp = require("./helpers/TrackChangesApp");
|
||||
const TrackChangesClient = require("./helpers/TrackChangesClient");
|
||||
const MockDocUpdaterApi = require("./helpers/MockDocUpdaterApi");
|
||||
const MockWebApi = require("./helpers/MockWebApi");
|
||||
const TrackChangesApp = require('./helpers/TrackChangesApp')
|
||||
const TrackChangesClient = require('./helpers/TrackChangesClient')
|
||||
const MockDocUpdaterApi = require('./helpers/MockDocUpdaterApi')
|
||||
const MockWebApi = require('./helpers/MockWebApi')
|
||||
|
||||
describe("Restoring a version", function() {
|
||||
before(function(done) {
|
||||
sinon.spy(MockDocUpdaterApi, "setDoc");
|
||||
describe('Restoring a version', function() {
|
||||
before(function(done) {
|
||||
sinon.spy(MockDocUpdaterApi, 'setDoc')
|
||||
|
||||
this.now = Date.now();
|
||||
this.user_id = ObjectId().toString();
|
||||
this.doc_id = ObjectId().toString();
|
||||
this.project_id = ObjectId().toString();
|
||||
MockWebApi.projects[this.project_id] = {features: {versioning: true}};
|
||||
|
||||
const minutes = 60 * 1000;
|
||||
this.now = Date.now()
|
||||
this.user_id = ObjectId().toString()
|
||||
this.doc_id = ObjectId().toString()
|
||||
this.project_id = ObjectId().toString()
|
||||
MockWebApi.projects[this.project_id] = { features: { versioning: true } }
|
||||
|
||||
this.updates = [{
|
||||
op: [{ i: "one ", p: 0 }],
|
||||
meta: { ts: this.now - (6 * minutes), user_id: this.user_id },
|
||||
v: 3
|
||||
}, {
|
||||
op: [{ i: "two ", p: 4 }],
|
||||
meta: { ts: this.now - (4 * minutes), user_id: this.user_id },
|
||||
v: 4
|
||||
}, {
|
||||
op: [{ i: "three ", p: 8 }],
|
||||
meta: { ts: this.now - (2 * minutes), user_id: this.user_id },
|
||||
v: 5
|
||||
}, {
|
||||
op: [{ i: "four", p: 14 }],
|
||||
meta: { ts: this.now, user_id: this.user_id },
|
||||
v: 6
|
||||
}];
|
||||
this.lines = ["one two three four"];
|
||||
this.restored_lines = ["one two "];
|
||||
this.beforeVersion = 5;
|
||||
const minutes = 60 * 1000
|
||||
|
||||
MockWebApi.users[this.user_id] = (this.user = {
|
||||
email: "user@sharelatex.com",
|
||||
first_name: "Leo",
|
||||
last_name: "Lion",
|
||||
id: this.user_id
|
||||
});
|
||||
this.updates = [
|
||||
{
|
||||
op: [{ i: 'one ', p: 0 }],
|
||||
meta: { ts: this.now - 6 * minutes, user_id: this.user_id },
|
||||
v: 3
|
||||
},
|
||||
{
|
||||
op: [{ i: 'two ', p: 4 }],
|
||||
meta: { ts: this.now - 4 * minutes, user_id: this.user_id },
|
||||
v: 4
|
||||
},
|
||||
{
|
||||
op: [{ i: 'three ', p: 8 }],
|
||||
meta: { ts: this.now - 2 * minutes, user_id: this.user_id },
|
||||
v: 5
|
||||
},
|
||||
{
|
||||
op: [{ i: 'four', p: 14 }],
|
||||
meta: { ts: this.now, user_id: this.user_id },
|
||||
v: 6
|
||||
}
|
||||
]
|
||||
this.lines = ['one two three four']
|
||||
this.restored_lines = ['one two ']
|
||||
this.beforeVersion = 5
|
||||
|
||||
MockDocUpdaterApi.docs[this.doc_id] = {
|
||||
lines: this.lines,
|
||||
version: 7
|
||||
};
|
||||
MockWebApi.users[this.user_id] = this.user = {
|
||||
email: 'user@sharelatex.com',
|
||||
first_name: 'Leo',
|
||||
last_name: 'Lion',
|
||||
id: this.user_id
|
||||
}
|
||||
|
||||
TrackChangesApp.ensureRunning(() => {
|
||||
return TrackChangesClient.pushRawUpdates(this.project_id, this.doc_id, this.updates, error => {
|
||||
if (error != null) { throw error; }
|
||||
return TrackChangesClient.restoreDoc(this.project_id, this.doc_id, this.beforeVersion, this.user_id, error => {
|
||||
if (error != null) { throw error; }
|
||||
return done();
|
||||
});
|
||||
});
|
||||
});
|
||||
return null;
|
||||
});
|
||||
MockDocUpdaterApi.docs[this.doc_id] = {
|
||||
lines: this.lines,
|
||||
version: 7
|
||||
}
|
||||
|
||||
after(function() {
|
||||
MockDocUpdaterApi.setDoc.restore();
|
||||
return null;
|
||||
});
|
||||
TrackChangesApp.ensureRunning(() => {
|
||||
return TrackChangesClient.pushRawUpdates(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.updates,
|
||||
error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return TrackChangesClient.restoreDoc(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.beforeVersion,
|
||||
this.user_id,
|
||||
error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return done()
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
})
|
||||
return null
|
||||
})
|
||||
|
||||
return it("should set the doc in the doc updater", function() {
|
||||
MockDocUpdaterApi.setDoc
|
||||
.calledWith(this.project_id, this.doc_id, this.restored_lines, this.user_id, true)
|
||||
.should.equal(true);
|
||||
return null;
|
||||
});
|
||||
});
|
||||
after(function() {
|
||||
MockDocUpdaterApi.setDoc.restore()
|
||||
return null
|
||||
})
|
||||
|
||||
return it('should set the doc in the doc updater', function() {
|
||||
MockDocUpdaterApi.setDoc
|
||||
.calledWith(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.restored_lines,
|
||||
this.user_id,
|
||||
true
|
||||
)
|
||||
.should.equal(true)
|
||||
return null
|
||||
})
|
||||
})
|
||||
|
|
|
@ -10,40 +10,45 @@
|
|||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
let MockDocUpdaterApi;
|
||||
const express = require("express");
|
||||
const app = express();
|
||||
let MockDocUpdaterApi
|
||||
const express = require('express')
|
||||
const app = express()
|
||||
|
||||
module.exports = (MockDocUpdaterApi = {
|
||||
docs: {},
|
||||
module.exports = MockDocUpdaterApi = {
|
||||
docs: {},
|
||||
|
||||
getAllDoc(project_id, callback) {
|
||||
if (callback == null) { callback = function(error) {}; }
|
||||
return callback(null, this.docs);
|
||||
},
|
||||
getAllDoc(project_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
}
|
||||
return callback(null, this.docs)
|
||||
},
|
||||
|
||||
run() {
|
||||
app.get("/project/:project_id/doc", (req, res, next) => {
|
||||
return this.getAllDoc(req.params.project_id, (error, docs) => {
|
||||
if (error != null) {
|
||||
res.send(500);
|
||||
}
|
||||
if ((docs == null)) {
|
||||
return res.send(404);
|
||||
} else {
|
||||
return res.send(JSON.stringify(docs));
|
||||
}
|
||||
});
|
||||
});
|
||||
run() {
|
||||
app.get('/project/:project_id/doc', (req, res, next) => {
|
||||
return this.getAllDoc(req.params.project_id, (error, docs) => {
|
||||
if (error != null) {
|
||||
res.send(500)
|
||||
}
|
||||
if (docs == null) {
|
||||
return res.send(404)
|
||||
} else {
|
||||
return res.send(JSON.stringify(docs))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
return app.listen(3016, (error) => {
|
||||
if (error != null) { throw error; }
|
||||
}).on("error", (error) => {
|
||||
console.error("error starting MockDocStoreApi:", error.message);
|
||||
return process.exit(1);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
MockDocUpdaterApi.run();
|
||||
return app
|
||||
.listen(3016, error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
})
|
||||
.on('error', error => {
|
||||
console.error('error starting MockDocStoreApi:', error.message)
|
||||
return process.exit(1)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
MockDocUpdaterApi.run()
|
||||
|
|
|
@ -11,58 +11,81 @@
|
|||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
let MockDocUpdaterApi;
|
||||
const express = require("express");
|
||||
const app = express();
|
||||
let MockDocUpdaterApi
|
||||
const express = require('express')
|
||||
const app = express()
|
||||
|
||||
module.exports = (MockDocUpdaterApi = {
|
||||
docs: {},
|
||||
module.exports = MockDocUpdaterApi = {
|
||||
docs: {},
|
||||
|
||||
getDoc(project_id, doc_id, callback) {
|
||||
if (callback == null) { callback = function(error) {}; }
|
||||
return callback(null, this.docs[doc_id]);
|
||||
},
|
||||
getDoc(project_id, doc_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
}
|
||||
return callback(null, this.docs[doc_id])
|
||||
},
|
||||
|
||||
setDoc(project_id, doc_id, lines, user_id, undoing, callback) {
|
||||
if (callback == null) { callback = function(error) {}; }
|
||||
if (!this.docs[doc_id]) { this.docs[doc_id] = {}; }
|
||||
this.docs[doc_id].lines = lines;
|
||||
return callback();
|
||||
},
|
||||
setDoc(project_id, doc_id, lines, user_id, undoing, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
}
|
||||
if (!this.docs[doc_id]) {
|
||||
this.docs[doc_id] = {}
|
||||
}
|
||||
this.docs[doc_id].lines = lines
|
||||
return callback()
|
||||
},
|
||||
|
||||
run() {
|
||||
app.get("/project/:project_id/doc/:doc_id", (req, res, next) => {
|
||||
return this.getDoc(req.params.project_id, req.params.doc_id, (error, doc) => {
|
||||
if (error != null) {
|
||||
res.send(500);
|
||||
}
|
||||
if ((doc == null)) {
|
||||
return res.send(404);
|
||||
} else {
|
||||
return res.send(JSON.stringify(doc));
|
||||
}
|
||||
});
|
||||
});
|
||||
run() {
|
||||
app.get('/project/:project_id/doc/:doc_id', (req, res, next) => {
|
||||
return this.getDoc(
|
||||
req.params.project_id,
|
||||
req.params.doc_id,
|
||||
(error, doc) => {
|
||||
if (error != null) {
|
||||
res.send(500)
|
||||
}
|
||||
if (doc == null) {
|
||||
return res.send(404)
|
||||
} else {
|
||||
return res.send(JSON.stringify(doc))
|
||||
}
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
app.post("/project/:project_id/doc/:doc_id", express.bodyParser(), (req, res, next) => {
|
||||
return this.setDoc(req.params.project_id, req.params.doc_id, req.body.lines, req.body.user_id, req.body.undoing, (errr, doc) => {
|
||||
if (typeof error !== 'undefined' && error !== null) {
|
||||
return res.send(500);
|
||||
} else {
|
||||
return res.send(204);
|
||||
}
|
||||
});
|
||||
});
|
||||
app.post(
|
||||
'/project/:project_id/doc/:doc_id',
|
||||
express.bodyParser(),
|
||||
(req, res, next) => {
|
||||
return this.setDoc(
|
||||
req.params.project_id,
|
||||
req.params.doc_id,
|
||||
req.body.lines,
|
||||
req.body.user_id,
|
||||
req.body.undoing,
|
||||
(errr, doc) => {
|
||||
if (typeof error !== 'undefined' && error !== null) {
|
||||
return res.send(500)
|
||||
} else {
|
||||
return res.send(204)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
return app.listen(3003, (error) => {
|
||||
if (error != null) { throw error; }
|
||||
}).on("error", (error) => {
|
||||
console.error("error starting MockDocUpdaterApi:", error.message);
|
||||
return process.exit(1);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
MockDocUpdaterApi.run();
|
||||
return app
|
||||
.listen(3003, error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
})
|
||||
.on('error', error => {
|
||||
console.error('error starting MockDocUpdaterApi:', error.message)
|
||||
return process.exit(1)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
MockDocUpdaterApi.run()
|
||||
|
|
|
@ -10,60 +10,67 @@
|
|||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
let MockWebApi;
|
||||
const express = require("express");
|
||||
const app = express();
|
||||
let MockWebApi
|
||||
const express = require('express')
|
||||
const app = express()
|
||||
|
||||
module.exports = (MockWebApi = {
|
||||
users: {},
|
||||
module.exports = MockWebApi = {
|
||||
users: {},
|
||||
|
||||
projects: {},
|
||||
projects: {},
|
||||
|
||||
getUserInfo(user_id, callback) {
|
||||
if (callback == null) { callback = function(error) {}; }
|
||||
return callback(null, this.users[user_id] || null);
|
||||
},
|
||||
getUserInfo(user_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
}
|
||||
return callback(null, this.users[user_id] || null)
|
||||
},
|
||||
|
||||
getProjectDetails(project_id, callback) {
|
||||
if (callback == null) { callback = function(error, project) {}; }
|
||||
return callback(null, this.projects[project_id]);
|
||||
},
|
||||
getProjectDetails(project_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, project) {}
|
||||
}
|
||||
return callback(null, this.projects[project_id])
|
||||
},
|
||||
|
||||
run() {
|
||||
app.get("/user/:user_id/personal_info", (req, res, next) => {
|
||||
return this.getUserInfo(req.params.user_id, (error, user) => {
|
||||
if (error != null) {
|
||||
res.send(500);
|
||||
}
|
||||
if ((user == null)) {
|
||||
return res.send(404);
|
||||
} else {
|
||||
return res.send(JSON.stringify(user));
|
||||
}
|
||||
});
|
||||
});
|
||||
run() {
|
||||
app.get('/user/:user_id/personal_info', (req, res, next) => {
|
||||
return this.getUserInfo(req.params.user_id, (error, user) => {
|
||||
if (error != null) {
|
||||
res.send(500)
|
||||
}
|
||||
if (user == null) {
|
||||
return res.send(404)
|
||||
} else {
|
||||
return res.send(JSON.stringify(user))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
app.get("/project/:project_id/details", (req, res, next) => {
|
||||
return this.getProjectDetails(req.params.project_id, (error, project) => {
|
||||
if (error != null) {
|
||||
res.send(500);
|
||||
}
|
||||
if ((project == null)) {
|
||||
return res.send(404);
|
||||
} else {
|
||||
return res.send(JSON.stringify(project));
|
||||
}
|
||||
});
|
||||
});
|
||||
app.get('/project/:project_id/details', (req, res, next) => {
|
||||
return this.getProjectDetails(req.params.project_id, (error, project) => {
|
||||
if (error != null) {
|
||||
res.send(500)
|
||||
}
|
||||
if (project == null) {
|
||||
return res.send(404)
|
||||
} else {
|
||||
return res.send(JSON.stringify(project))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
return app.listen(3000, (error) => {
|
||||
if (error != null) { throw error; }
|
||||
}).on("error", (error) => {
|
||||
console.error("error starting MockWebApiServer:", error.message);
|
||||
return process.exit(1);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
MockWebApi.run();
|
||||
return app
|
||||
.listen(3000, error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
})
|
||||
.on('error', error => {
|
||||
console.error('error starting MockWebApiServer:', error.message)
|
||||
return process.exit(1)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
MockWebApi.run()
|
||||
|
|
|
@ -12,40 +12,55 @@
|
|||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
const app = require('../../../../app');
|
||||
require("logger-sharelatex");
|
||||
const logger = require("logger-sharelatex");
|
||||
const Settings = require("settings-sharelatex");
|
||||
const app = require('../../../../app')
|
||||
require('logger-sharelatex')
|
||||
const logger = require('logger-sharelatex')
|
||||
const Settings = require('settings-sharelatex')
|
||||
|
||||
module.exports = {
|
||||
running: false,
|
||||
initing: false,
|
||||
callbacks: [],
|
||||
ensureRunning(callback) {
|
||||
if (callback == null) { callback = function(error) {}; }
|
||||
if (this.running) {
|
||||
return callback();
|
||||
} else if (this.initing) {
|
||||
return this.callbacks.push(callback);
|
||||
} else {
|
||||
this.initing = true;
|
||||
this.callbacks.push(callback);
|
||||
return app.listen(__guard__(Settings.internal != null ? Settings.internal.trackchanges : undefined, x => x.port), "localhost", error => {
|
||||
if (error != null) { throw error; }
|
||||
this.running = true;
|
||||
logger.log("track changes running in dev mode");
|
||||
running: false,
|
||||
initing: false,
|
||||
callbacks: [],
|
||||
ensureRunning(callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
}
|
||||
if (this.running) {
|
||||
return callback()
|
||||
} else if (this.initing) {
|
||||
return this.callbacks.push(callback)
|
||||
} else {
|
||||
this.initing = true
|
||||
this.callbacks.push(callback)
|
||||
return app.listen(
|
||||
__guard__(
|
||||
Settings.internal != null
|
||||
? Settings.internal.trackchanges
|
||||
: undefined,
|
||||
x => x.port
|
||||
),
|
||||
'localhost',
|
||||
error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
this.running = true
|
||||
logger.log('track changes running in dev mode')
|
||||
|
||||
return (() => {
|
||||
const result = [];
|
||||
for (callback of Array.from(this.callbacks)) {
|
||||
result.push(callback());
|
||||
}
|
||||
return result;
|
||||
})();
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
return (() => {
|
||||
const result = []
|
||||
for (callback of Array.from(this.callbacks)) {
|
||||
result.push(callback())
|
||||
}
|
||||
return result
|
||||
})()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
function __guard__(value, transform) {
|
||||
return (typeof value !== 'undefined' && value !== null) ? transform(value) : undefined;
|
||||
}
|
||||
return typeof value !== 'undefined' && value !== null
|
||||
? transform(value)
|
||||
: undefined
|
||||
}
|
||||
|
|
|
@ -12,198 +12,277 @@
|
|||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
let TrackChangesClient;
|
||||
const async = require('async');
|
||||
const zlib = require('zlib');
|
||||
const request = require("request");
|
||||
const Settings = require("settings-sharelatex");
|
||||
const rclient = require("redis-sharelatex").createClient(Settings.redis.history); // Only works locally for now
|
||||
const Keys = Settings.redis.history.key_schema;
|
||||
const {db, ObjectId} = require("../../../../app/js/mongojs");
|
||||
let TrackChangesClient
|
||||
const async = require('async')
|
||||
const zlib = require('zlib')
|
||||
const request = require('request')
|
||||
const Settings = require('settings-sharelatex')
|
||||
const rclient = require('redis-sharelatex').createClient(Settings.redis.history) // Only works locally for now
|
||||
const Keys = Settings.redis.history.key_schema
|
||||
const { db, ObjectId } = require('../../../../app/js/mongojs')
|
||||
|
||||
const aws = require("aws-sdk");
|
||||
const aws = require('aws-sdk')
|
||||
const s3 = new aws.S3({
|
||||
accessKeyId: Settings.trackchanges.s3.key,
|
||||
secretAccessKey: Settings.trackchanges.s3.secret,
|
||||
endpoint: Settings.trackchanges.s3.endpoint,
|
||||
s3ForcePathStyle: Settings.trackchanges.s3.pathStyle
|
||||
});
|
||||
const S3_BUCKET = Settings.trackchanges.stores.doc_history;
|
||||
accessKeyId: Settings.trackchanges.s3.key,
|
||||
secretAccessKey: Settings.trackchanges.s3.secret,
|
||||
endpoint: Settings.trackchanges.s3.endpoint,
|
||||
s3ForcePathStyle: Settings.trackchanges.s3.pathStyle
|
||||
})
|
||||
const S3_BUCKET = Settings.trackchanges.stores.doc_history
|
||||
|
||||
module.exports = (TrackChangesClient = {
|
||||
flushAndGetCompressedUpdates(project_id, doc_id, callback) {
|
||||
if (callback == null) { callback = function(error, updates) {}; }
|
||||
return TrackChangesClient.flushDoc(project_id, doc_id, (error) => {
|
||||
if (error != null) { return callback(error); }
|
||||
return TrackChangesClient.getCompressedUpdates(doc_id, callback);
|
||||
});
|
||||
},
|
||||
module.exports = TrackChangesClient = {
|
||||
flushAndGetCompressedUpdates(project_id, doc_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, updates) {}
|
||||
}
|
||||
return TrackChangesClient.flushDoc(project_id, doc_id, error => {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
return TrackChangesClient.getCompressedUpdates(doc_id, callback)
|
||||
})
|
||||
},
|
||||
|
||||
flushDoc(project_id, doc_id, callback) {
|
||||
if (callback == null) { callback = function(error) {}; }
|
||||
return request.post({
|
||||
url: `http://localhost:3015/project/${project_id}/doc/${doc_id}/flush`
|
||||
}, (error, response, body) => {
|
||||
response.statusCode.should.equal(204);
|
||||
return callback(error);
|
||||
});
|
||||
},
|
||||
flushDoc(project_id, doc_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
}
|
||||
return request.post(
|
||||
{
|
||||
url: `http://localhost:3015/project/${project_id}/doc/${doc_id}/flush`
|
||||
},
|
||||
(error, response, body) => {
|
||||
response.statusCode.should.equal(204)
|
||||
return callback(error)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
flushProject(project_id, callback) {
|
||||
if (callback == null) { callback = function(error) {}; }
|
||||
return request.post({
|
||||
url: `http://localhost:3015/project/${project_id}/flush`
|
||||
}, (error, response, body) => {
|
||||
response.statusCode.should.equal(204);
|
||||
return callback(error);
|
||||
});
|
||||
},
|
||||
flushProject(project_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
}
|
||||
return request.post(
|
||||
{
|
||||
url: `http://localhost:3015/project/${project_id}/flush`
|
||||
},
|
||||
(error, response, body) => {
|
||||
response.statusCode.should.equal(204)
|
||||
return callback(error)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
getCompressedUpdates(doc_id, callback) {
|
||||
if (callback == null) { callback = function(error, updates) {}; }
|
||||
return db.docHistory
|
||||
.find({doc_id: ObjectId(doc_id)})
|
||||
.sort({"meta.end_ts": 1})
|
||||
.toArray(callback);
|
||||
},
|
||||
getCompressedUpdates(doc_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, updates) {}
|
||||
}
|
||||
return db.docHistory
|
||||
.find({ doc_id: ObjectId(doc_id) })
|
||||
.sort({ 'meta.end_ts': 1 })
|
||||
.toArray(callback)
|
||||
},
|
||||
|
||||
getProjectMetaData(project_id, callback) {
|
||||
if (callback == null) { callback = function(error, updates) {}; }
|
||||
return db.projectHistoryMetaData
|
||||
.find({
|
||||
project_id: ObjectId(project_id)
|
||||
},
|
||||
(error, projects) => callback(error, projects[0]));
|
||||
},
|
||||
getProjectMetaData(project_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, updates) {}
|
||||
}
|
||||
return db.projectHistoryMetaData.find(
|
||||
{
|
||||
project_id: ObjectId(project_id)
|
||||
},
|
||||
(error, projects) => callback(error, projects[0])
|
||||
)
|
||||
},
|
||||
|
||||
setPreserveHistoryForProject(project_id, callback) {
|
||||
if (callback == null) { callback = function(error) {}; }
|
||||
return db.projectHistoryMetaData.update({
|
||||
project_id: ObjectId(project_id)
|
||||
}, {
|
||||
$set: { preserveHistory: true }
|
||||
}, {
|
||||
upsert: true
|
||||
}, callback);
|
||||
},
|
||||
setPreserveHistoryForProject(project_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
}
|
||||
return db.projectHistoryMetaData.update(
|
||||
{
|
||||
project_id: ObjectId(project_id)
|
||||
},
|
||||
{
|
||||
$set: { preserveHistory: true }
|
||||
},
|
||||
{
|
||||
upsert: true
|
||||
},
|
||||
callback
|
||||
)
|
||||
},
|
||||
|
||||
pushRawUpdates(project_id, doc_id, updates, callback) {
|
||||
if (callback == null) { callback = function(error) {}; }
|
||||
return rclient.sadd(Keys.docsWithHistoryOps({project_id}), doc_id, (error) => {
|
||||
if (error != null) { return callback(error); }
|
||||
return rclient.rpush(Keys.uncompressedHistoryOps({doc_id}), ...Array.from(((Array.from(updates).map((u) => JSON.stringify(u))))), callback);
|
||||
});
|
||||
},
|
||||
pushRawUpdates(project_id, doc_id, updates, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
}
|
||||
return rclient.sadd(
|
||||
Keys.docsWithHistoryOps({ project_id }),
|
||||
doc_id,
|
||||
error => {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
return rclient.rpush(
|
||||
Keys.uncompressedHistoryOps({ doc_id }),
|
||||
...Array.from(Array.from(updates).map(u => JSON.stringify(u))),
|
||||
callback
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
getDiff(project_id, doc_id, from, to, callback) {
|
||||
if (callback == null) { callback = function(error, diff) {}; }
|
||||
return request.get({
|
||||
url: `http://localhost:3015/project/${project_id}/doc/${doc_id}/diff?from=${from}&to=${to}`
|
||||
}, (error, response, body) => {
|
||||
response.statusCode.should.equal(200);
|
||||
return callback(null, JSON.parse(body));
|
||||
});
|
||||
},
|
||||
getDiff(project_id, doc_id, from, to, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, diff) {}
|
||||
}
|
||||
return request.get(
|
||||
{
|
||||
url: `http://localhost:3015/project/${project_id}/doc/${doc_id}/diff?from=${from}&to=${to}`
|
||||
},
|
||||
(error, response, body) => {
|
||||
response.statusCode.should.equal(200)
|
||||
return callback(null, JSON.parse(body))
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
getUpdates(project_id, options, callback) {
|
||||
if (callback == null) { callback = function(error, body) {}; }
|
||||
return request.get({
|
||||
url: `http://localhost:3015/project/${project_id}/updates?before=${options.before}&min_count=${options.min_count}`
|
||||
}, (error, response, body) => {
|
||||
response.statusCode.should.equal(200);
|
||||
return callback(null, JSON.parse(body));
|
||||
});
|
||||
},
|
||||
getUpdates(project_id, options, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, body) {}
|
||||
}
|
||||
return request.get(
|
||||
{
|
||||
url: `http://localhost:3015/project/${project_id}/updates?before=${options.before}&min_count=${options.min_count}`
|
||||
},
|
||||
(error, response, body) => {
|
||||
response.statusCode.should.equal(200)
|
||||
return callback(null, JSON.parse(body))
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
restoreDoc(project_id, doc_id, version, user_id, callback) {
|
||||
if (callback == null) { callback = function(error) {}; }
|
||||
return request.post({
|
||||
url: `http://localhost:3015/project/${project_id}/doc/${doc_id}/version/${version}/restore`,
|
||||
headers: {
|
||||
"X-User-Id": user_id
|
||||
}
|
||||
}, (error, response, body) => {
|
||||
response.statusCode.should.equal(204);
|
||||
return callback(null);
|
||||
});
|
||||
},
|
||||
restoreDoc(project_id, doc_id, version, user_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
}
|
||||
return request.post(
|
||||
{
|
||||
url: `http://localhost:3015/project/${project_id}/doc/${doc_id}/version/${version}/restore`,
|
||||
headers: {
|
||||
'X-User-Id': user_id
|
||||
}
|
||||
},
|
||||
(error, response, body) => {
|
||||
response.statusCode.should.equal(204)
|
||||
return callback(null)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
pushDocHistory(project_id, doc_id, callback) {
|
||||
if (callback == null) { callback = function(error) {}; }
|
||||
return request.post({
|
||||
url: `http://localhost:3015/project/${project_id}/doc/${doc_id}/push`
|
||||
}, (error, response, body) => {
|
||||
response.statusCode.should.equal(204);
|
||||
return callback(error);
|
||||
});
|
||||
},
|
||||
pushDocHistory(project_id, doc_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
}
|
||||
return request.post(
|
||||
{
|
||||
url: `http://localhost:3015/project/${project_id}/doc/${doc_id}/push`
|
||||
},
|
||||
(error, response, body) => {
|
||||
response.statusCode.should.equal(204)
|
||||
return callback(error)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
pullDocHistory(project_id, doc_id, callback) {
|
||||
if (callback == null) { callback = function(error) {}; }
|
||||
return request.post({
|
||||
url: `http://localhost:3015/project/${project_id}/doc/${doc_id}/pull`
|
||||
}, (error, response, body) => {
|
||||
response.statusCode.should.equal(204);
|
||||
return callback(error);
|
||||
});
|
||||
},
|
||||
pullDocHistory(project_id, doc_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
}
|
||||
return request.post(
|
||||
{
|
||||
url: `http://localhost:3015/project/${project_id}/doc/${doc_id}/pull`
|
||||
},
|
||||
(error, response, body) => {
|
||||
response.statusCode.should.equal(204)
|
||||
return callback(error)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
waitForS3(done, retries) {
|
||||
if (retries == null) { retries = 42; }
|
||||
if (!Settings.trackchanges.s3.endpoint) {
|
||||
return done();
|
||||
}
|
||||
waitForS3(done, retries) {
|
||||
if (retries == null) {
|
||||
retries = 42
|
||||
}
|
||||
if (!Settings.trackchanges.s3.endpoint) {
|
||||
return done()
|
||||
}
|
||||
|
||||
return request.get(`${Settings.trackchanges.s3.endpoint}/`, (err, res) => {
|
||||
if (res && (res.statusCode < 500)) {
|
||||
return done();
|
||||
}
|
||||
return request.get(`${Settings.trackchanges.s3.endpoint}/`, (err, res) => {
|
||||
if (res && res.statusCode < 500) {
|
||||
return done()
|
||||
}
|
||||
|
||||
if (retries === 0) {
|
||||
return done(err || new Error(`s3 returned ${res.statusCode}`));
|
||||
}
|
||||
if (retries === 0) {
|
||||
return done(err || new Error(`s3 returned ${res.statusCode}`))
|
||||
}
|
||||
|
||||
return setTimeout(() => TrackChangesClient.waitForS3(done, --retries)
|
||||
, 1000);
|
||||
});
|
||||
},
|
||||
return setTimeout(
|
||||
() => TrackChangesClient.waitForS3(done, --retries),
|
||||
1000
|
||||
)
|
||||
})
|
||||
},
|
||||
|
||||
getS3Doc(project_id, doc_id, pack_id, callback) {
|
||||
if (callback == null) { callback = function(error, body) {}; }
|
||||
const params = {
|
||||
Bucket: S3_BUCKET,
|
||||
Key: `${project_id}/changes-${doc_id}/pack-${pack_id}`
|
||||
};
|
||||
getS3Doc(project_id, doc_id, pack_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, body) {}
|
||||
}
|
||||
const params = {
|
||||
Bucket: S3_BUCKET,
|
||||
Key: `${project_id}/changes-${doc_id}/pack-${pack_id}`
|
||||
}
|
||||
|
||||
return s3.getObject(params, (error, data) => {
|
||||
if (error != null) { return callback(error); }
|
||||
const body = data.Body;
|
||||
if ((body == null)) { return callback(new Error("empty response from s3")); }
|
||||
return zlib.gunzip(body, (err, result) => {
|
||||
if (err != null) { return callback(err); }
|
||||
return callback(null, JSON.parse(result.toString()));
|
||||
});
|
||||
});
|
||||
},
|
||||
return s3.getObject(params, (error, data) => {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
const body = data.Body
|
||||
if (body == null) {
|
||||
return callback(new Error('empty response from s3'))
|
||||
}
|
||||
return zlib.gunzip(body, (err, result) => {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
return callback(null, JSON.parse(result.toString()))
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
removeS3Doc(project_id, doc_id, callback) {
|
||||
if (callback == null) { callback = function(error, res, body) {}; }
|
||||
let params = {
|
||||
Bucket: S3_BUCKET,
|
||||
Prefix: `${project_id}/changes-${doc_id}`
|
||||
};
|
||||
removeS3Doc(project_id, doc_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, res, body) {}
|
||||
}
|
||||
let params = {
|
||||
Bucket: S3_BUCKET,
|
||||
Prefix: `${project_id}/changes-${doc_id}`
|
||||
}
|
||||
|
||||
return s3.listObjects(params, (error, data) => {
|
||||
if (error != null) { return callback(error); }
|
||||
return s3.listObjects(params, (error, data) => {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
|
||||
params = {
|
||||
Bucket: S3_BUCKET,
|
||||
Delete: {
|
||||
Objects: data.Contents.map(s3object => ({Key: s3object.Key}))
|
||||
}
|
||||
};
|
||||
params = {
|
||||
Bucket: S3_BUCKET,
|
||||
Delete: {
|
||||
Objects: data.Contents.map(s3object => ({ Key: s3object.Key }))
|
||||
}
|
||||
}
|
||||
|
||||
return s3.deleteObjects(params, callback);
|
||||
});
|
||||
}
|
||||
});
|
||||
return s3.deleteObjects(params, callback)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue