prettier: convert test/acceptance decaffeinated files to Prettier format

This commit is contained in:
Tim Alby 2020-05-06 12:12:47 +02:00
parent 9680e62bb1
commit d15738cb98
15 changed files with 3810 additions and 2486 deletions

View file

@ -11,360 +11,519 @@
* 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 Settings = require('settings-sharelatex');
const rclient_project_history = require("redis-sharelatex").createClient(Settings.redis.project_history);
const ProjectHistoryKeys = Settings.redis.project_history.key_schema;
const sinon = require('sinon')
const chai = require('chai')
chai.should()
const Settings = require('settings-sharelatex')
const rclient_project_history = require('redis-sharelatex').createClient(
Settings.redis.project_history
)
const ProjectHistoryKeys = Settings.redis.project_history.key_schema
const MockProjectHistoryApi = require("./helpers/MockProjectHistoryApi");
const MockWebApi = require("./helpers/MockWebApi");
const DocUpdaterClient = require("./helpers/DocUpdaterClient");
const DocUpdaterApp = require("./helpers/DocUpdaterApp");
const MockProjectHistoryApi = require('./helpers/MockProjectHistoryApi')
const MockWebApi = require('./helpers/MockWebApi')
const DocUpdaterClient = require('./helpers/DocUpdaterClient')
const DocUpdaterApp = require('./helpers/DocUpdaterApp')
describe("Applying updates to a project's structure", function() {
before(function() {
this.user_id = 'user-id-123';
return this.version = 1234;
});
describe("Applying updates to a project's structure", function () {
before(function () {
this.user_id = 'user-id-123'
return (this.version = 1234)
})
describe("renaming a file", function() {
before(function(done) {
this.project_id = DocUpdaterClient.randomId();
this.fileUpdate = {
id: DocUpdaterClient.randomId(),
pathname: '/file-path',
newPathname: '/new-file-path'
};
this.fileUpdates = [ this.fileUpdate ];
return DocUpdaterApp.ensureRunning(error => {
if (error != null) { throw error; }
return DocUpdaterClient.sendProjectUpdate(this.project_id, this.user_id, [], this.fileUpdates, this.version, (error) => {
if (error != null) { throw error; }
return setTimeout(done, 200);
});
});
});
describe('renaming a file', function () {
before(function (done) {
this.project_id = DocUpdaterClient.randomId()
this.fileUpdate = {
id: DocUpdaterClient.randomId(),
pathname: '/file-path',
newPathname: '/new-file-path'
}
this.fileUpdates = [this.fileUpdate]
return DocUpdaterApp.ensureRunning((error) => {
if (error != null) {
throw error
}
return DocUpdaterClient.sendProjectUpdate(
this.project_id,
this.user_id,
[],
this.fileUpdates,
this.version,
(error) => {
if (error != null) {
throw error
}
return setTimeout(done, 200)
}
)
})
})
return it("should push the applied file renames to the project history api", function(done) {
rclient_project_history.lrange(ProjectHistoryKeys.projectHistoryOps({project_id: this.project_id}), 0, -1, (error, updates) => {
if (error != null) { throw error; }
return it('should push the applied file renames to the project history api', function (done) {
rclient_project_history.lrange(
ProjectHistoryKeys.projectHistoryOps({ project_id: this.project_id }),
0,
-1,
(error, updates) => {
if (error != null) {
throw error
}
const update = JSON.parse(updates[0]);
update.file.should.equal(this.fileUpdate.id);
update.pathname.should.equal('/file-path');
update.new_pathname.should.equal('/new-file-path');
update.meta.user_id.should.equal(this.user_id);
update.meta.ts.should.be.a('string');
update.version.should.equal(`${this.version}.0`);
const update = JSON.parse(updates[0])
update.file.should.equal(this.fileUpdate.id)
update.pathname.should.equal('/file-path')
update.new_pathname.should.equal('/new-file-path')
update.meta.user_id.should.equal(this.user_id)
update.meta.ts.should.be.a('string')
update.version.should.equal(`${this.version}.0`)
return done();
});
return null;
});
});
return done()
}
)
return null
})
})
describe("renaming a document", function() {
before(function() {
this.docUpdate = {
id: DocUpdaterClient.randomId(),
pathname: '/doc-path',
newPathname: '/new-doc-path'
};
return this.docUpdates = [ this.docUpdate ];});
describe('renaming a document', function () {
before(function () {
this.docUpdate = {
id: DocUpdaterClient.randomId(),
pathname: '/doc-path',
newPathname: '/new-doc-path'
}
return (this.docUpdates = [this.docUpdate])
})
describe("when the document is not loaded", function() {
before(function(done) {
this.project_id = DocUpdaterClient.randomId();
DocUpdaterClient.sendProjectUpdate(this.project_id, this.user_id, this.docUpdates, [], this.version, (error) => {
if (error != null) { throw error; }
return setTimeout(done, 200);
});
return null;
});
describe('when the document is not loaded', function () {
before(function (done) {
this.project_id = DocUpdaterClient.randomId()
DocUpdaterClient.sendProjectUpdate(
this.project_id,
this.user_id,
this.docUpdates,
[],
this.version,
(error) => {
if (error != null) {
throw error
}
return setTimeout(done, 200)
}
)
return null
})
return it("should push the applied doc renames to the project history api", function(done) {
rclient_project_history.lrange(ProjectHistoryKeys.projectHistoryOps({project_id: this.project_id}), 0, -1, (error, updates) => {
if (error != null) { throw error; }
return it('should push the applied doc renames to the project history api', function (done) {
rclient_project_history.lrange(
ProjectHistoryKeys.projectHistoryOps({ project_id: this.project_id }),
0,
-1,
(error, updates) => {
if (error != null) {
throw error
}
const update = JSON.parse(updates[0]);
update.doc.should.equal(this.docUpdate.id);
update.pathname.should.equal('/doc-path');
update.new_pathname.should.equal('/new-doc-path');
update.meta.user_id.should.equal(this.user_id);
update.meta.ts.should.be.a('string');
update.version.should.equal(`${this.version}.0`);
const update = JSON.parse(updates[0])
update.doc.should.equal(this.docUpdate.id)
update.pathname.should.equal('/doc-path')
update.new_pathname.should.equal('/new-doc-path')
update.meta.user_id.should.equal(this.user_id)
update.meta.ts.should.be.a('string')
update.version.should.equal(`${this.version}.0`)
return done();
});
return null;
});
});
return done()
}
)
return null
})
})
return describe("when the document is loaded", function() {
before(function(done) {
this.project_id = DocUpdaterClient.randomId();
MockWebApi.insertDoc(this.project_id, this.docUpdate.id, {});
DocUpdaterClient.preloadDoc(this.project_id, this.docUpdate.id, error => {
if (error != null) { throw error; }
sinon.spy(MockWebApi, "getDocument");
return DocUpdaterClient.sendProjectUpdate(this.project_id, this.user_id, this.docUpdates, [], this.version, (error) => {
if (error != null) { throw error; }
return setTimeout(done, 200);
});
});
return null;
});
return describe('when the document is loaded', function () {
before(function (done) {
this.project_id = DocUpdaterClient.randomId()
MockWebApi.insertDoc(this.project_id, this.docUpdate.id, {})
DocUpdaterClient.preloadDoc(
this.project_id,
this.docUpdate.id,
(error) => {
if (error != null) {
throw error
}
sinon.spy(MockWebApi, 'getDocument')
return DocUpdaterClient.sendProjectUpdate(
this.project_id,
this.user_id,
this.docUpdates,
[],
this.version,
(error) => {
if (error != null) {
throw error
}
return setTimeout(done, 200)
}
)
}
)
return null
})
after(function() { return MockWebApi.getDocument.restore(); });
after(function () {
return MockWebApi.getDocument.restore()
})
it("should update the doc", function(done) {
DocUpdaterClient.getDoc(this.project_id, this.docUpdate.id, (error, res, doc) => {
doc.pathname.should.equal(this.docUpdate.newPathname);
return done();
});
return null;
});
it('should update the doc', function (done) {
DocUpdaterClient.getDoc(
this.project_id,
this.docUpdate.id,
(error, res, doc) => {
doc.pathname.should.equal(this.docUpdate.newPathname)
return done()
}
)
return null
})
return it("should push the applied doc renames to the project history api", function(done) {
rclient_project_history.lrange(ProjectHistoryKeys.projectHistoryOps({project_id: this.project_id}), 0, -1, (error, updates) => {
if (error != null) { throw error; }
return it('should push the applied doc renames to the project history api', function (done) {
rclient_project_history.lrange(
ProjectHistoryKeys.projectHistoryOps({ project_id: this.project_id }),
0,
-1,
(error, updates) => {
if (error != null) {
throw error
}
const update = JSON.parse(updates[0]);
update.doc.should.equal(this.docUpdate.id);
update.pathname.should.equal('/doc-path');
update.new_pathname.should.equal('/new-doc-path');
update.meta.user_id.should.equal(this.user_id);
update.meta.ts.should.be.a('string');
update.version.should.equal(`${this.version}.0`);
const update = JSON.parse(updates[0])
update.doc.should.equal(this.docUpdate.id)
update.pathname.should.equal('/doc-path')
update.new_pathname.should.equal('/new-doc-path')
update.meta.user_id.should.equal(this.user_id)
update.meta.ts.should.be.a('string')
update.version.should.equal(`${this.version}.0`)
return done();
});
return null;
});
});
});
return done()
}
)
return null
})
})
})
describe("renaming multiple documents and files", function() {
before(function() {
this.docUpdate0 = {
id: DocUpdaterClient.randomId(),
pathname: '/doc-path0',
newPathname: '/new-doc-path0'
};
this.docUpdate1 = {
id: DocUpdaterClient.randomId(),
pathname: '/doc-path1',
newPathname: '/new-doc-path1'
};
this.docUpdates = [ this.docUpdate0, this.docUpdate1 ];
this.fileUpdate0 = {
id: DocUpdaterClient.randomId(),
pathname: '/file-path0',
newPathname: '/new-file-path0'
};
this.fileUpdate1 = {
id: DocUpdaterClient.randomId(),
pathname: '/file-path1',
newPathname: '/new-file-path1'
};
return this.fileUpdates = [ this.fileUpdate0, this.fileUpdate1 ];});
describe('renaming multiple documents and files', function () {
before(function () {
this.docUpdate0 = {
id: DocUpdaterClient.randomId(),
pathname: '/doc-path0',
newPathname: '/new-doc-path0'
}
this.docUpdate1 = {
id: DocUpdaterClient.randomId(),
pathname: '/doc-path1',
newPathname: '/new-doc-path1'
}
this.docUpdates = [this.docUpdate0, this.docUpdate1]
this.fileUpdate0 = {
id: DocUpdaterClient.randomId(),
pathname: '/file-path0',
newPathname: '/new-file-path0'
}
this.fileUpdate1 = {
id: DocUpdaterClient.randomId(),
pathname: '/file-path1',
newPathname: '/new-file-path1'
}
return (this.fileUpdates = [this.fileUpdate0, this.fileUpdate1])
})
return describe("when the documents are not loaded", function() {
before(function(done) {
this.project_id = DocUpdaterClient.randomId();
DocUpdaterClient.sendProjectUpdate(this.project_id, this.user_id, this.docUpdates, this.fileUpdates, this.version, (error) => {
if (error != null) { throw error; }
return setTimeout(done, 200);
});
return null;
});
return describe('when the documents are not loaded', function () {
before(function (done) {
this.project_id = DocUpdaterClient.randomId()
DocUpdaterClient.sendProjectUpdate(
this.project_id,
this.user_id,
this.docUpdates,
this.fileUpdates,
this.version,
(error) => {
if (error != null) {
throw error
}
return setTimeout(done, 200)
}
)
return null
})
return it("should push the applied doc renames to the project history api", function(done) {
rclient_project_history.lrange(ProjectHistoryKeys.projectHistoryOps({project_id: this.project_id}), 0, -1, (error, updates) => {
if (error != null) { throw error; }
return it('should push the applied doc renames to the project history api', function (done) {
rclient_project_history.lrange(
ProjectHistoryKeys.projectHistoryOps({ project_id: this.project_id }),
0,
-1,
(error, updates) => {
if (error != null) {
throw error
}
let update = JSON.parse(updates[0]);
update.doc.should.equal(this.docUpdate0.id);
update.pathname.should.equal('/doc-path0');
update.new_pathname.should.equal('/new-doc-path0');
update.meta.user_id.should.equal(this.user_id);
update.meta.ts.should.be.a('string');
update.version.should.equal(`${this.version}.0`);
let update = JSON.parse(updates[0])
update.doc.should.equal(this.docUpdate0.id)
update.pathname.should.equal('/doc-path0')
update.new_pathname.should.equal('/new-doc-path0')
update.meta.user_id.should.equal(this.user_id)
update.meta.ts.should.be.a('string')
update.version.should.equal(`${this.version}.0`)
update = JSON.parse(updates[1]);
update.doc.should.equal(this.docUpdate1.id);
update.pathname.should.equal('/doc-path1');
update.new_pathname.should.equal('/new-doc-path1');
update.meta.user_id.should.equal(this.user_id);
update.meta.ts.should.be.a('string');
update.version.should.equal(`${this.version}.1`);
update = JSON.parse(updates[1])
update.doc.should.equal(this.docUpdate1.id)
update.pathname.should.equal('/doc-path1')
update.new_pathname.should.equal('/new-doc-path1')
update.meta.user_id.should.equal(this.user_id)
update.meta.ts.should.be.a('string')
update.version.should.equal(`${this.version}.1`)
update = JSON.parse(updates[2]);
update.file.should.equal(this.fileUpdate0.id);
update.pathname.should.equal('/file-path0');
update.new_pathname.should.equal('/new-file-path0');
update.meta.user_id.should.equal(this.user_id);
update.meta.ts.should.be.a('string');
update.version.should.equal(`${this.version}.2`);
update = JSON.parse(updates[2])
update.file.should.equal(this.fileUpdate0.id)
update.pathname.should.equal('/file-path0')
update.new_pathname.should.equal('/new-file-path0')
update.meta.user_id.should.equal(this.user_id)
update.meta.ts.should.be.a('string')
update.version.should.equal(`${this.version}.2`)
update = JSON.parse(updates[3]);
update.file.should.equal(this.fileUpdate1.id);
update.pathname.should.equal('/file-path1');
update.new_pathname.should.equal('/new-file-path1');
update.meta.user_id.should.equal(this.user_id);
update.meta.ts.should.be.a('string');
update.version.should.equal(`${this.version}.3`);
update = JSON.parse(updates[3])
update.file.should.equal(this.fileUpdate1.id)
update.pathname.should.equal('/file-path1')
update.new_pathname.should.equal('/new-file-path1')
update.meta.user_id.should.equal(this.user_id)
update.meta.ts.should.be.a('string')
update.version.should.equal(`${this.version}.3`)
return done();
});
return null;
});
});
});
return done()
}
)
return null
})
})
})
describe('adding a file', function () {
before(function (done) {
this.project_id = DocUpdaterClient.randomId()
this.fileUpdate = {
id: DocUpdaterClient.randomId(),
pathname: '/file-path',
url: 'filestore.example.com'
}
this.fileUpdates = [this.fileUpdate]
DocUpdaterClient.sendProjectUpdate(
this.project_id,
this.user_id,
[],
this.fileUpdates,
this.version,
(error) => {
if (error != null) {
throw error
}
return setTimeout(done, 200)
}
)
return null
})
describe("adding a file", function() {
before(function(done) {
this.project_id = DocUpdaterClient.randomId();
this.fileUpdate = {
id: DocUpdaterClient.randomId(),
pathname: '/file-path',
url: 'filestore.example.com'
};
this.fileUpdates = [ this.fileUpdate ];
DocUpdaterClient.sendProjectUpdate(this.project_id, this.user_id, [], this.fileUpdates, this.version, (error) => {
if (error != null) { throw error; }
return setTimeout(done, 200);
});
return null;
});
return it('should push the file addition to the project history api', function (done) {
rclient_project_history.lrange(
ProjectHistoryKeys.projectHistoryOps({ project_id: this.project_id }),
0,
-1,
(error, updates) => {
if (error != null) {
throw error
}
return it("should push the file addition to the project history api", function(done) {
rclient_project_history.lrange(ProjectHistoryKeys.projectHistoryOps({project_id: this.project_id}), 0, -1, (error, updates) => {
if (error != null) { throw error; }
const update = JSON.parse(updates[0])
update.file.should.equal(this.fileUpdate.id)
update.pathname.should.equal('/file-path')
update.url.should.equal('filestore.example.com')
update.meta.user_id.should.equal(this.user_id)
update.meta.ts.should.be.a('string')
update.version.should.equal(`${this.version}.0`)
const update = JSON.parse(updates[0]);
update.file.should.equal(this.fileUpdate.id);
update.pathname.should.equal('/file-path');
update.url.should.equal('filestore.example.com');
update.meta.user_id.should.equal(this.user_id);
update.meta.ts.should.be.a('string');
update.version.should.equal(`${this.version}.0`);
return done()
}
)
return null
})
})
return done();
});
return null;
});
});
describe('adding a doc', function () {
before(function (done) {
this.project_id = DocUpdaterClient.randomId()
this.docUpdate = {
id: DocUpdaterClient.randomId(),
pathname: '/file-path',
docLines: 'a\nb'
}
this.docUpdates = [this.docUpdate]
DocUpdaterClient.sendProjectUpdate(
this.project_id,
this.user_id,
this.docUpdates,
[],
this.version,
(error) => {
if (error != null) {
throw error
}
return setTimeout(done, 200)
}
)
return null
})
describe("adding a doc", function() {
before(function(done) {
this.project_id = DocUpdaterClient.randomId();
this.docUpdate = {
id: DocUpdaterClient.randomId(),
pathname: '/file-path',
docLines: 'a\nb'
};
this.docUpdates = [ this.docUpdate ];
DocUpdaterClient.sendProjectUpdate(this.project_id, this.user_id, this.docUpdates, [], this.version, (error) => {
if (error != null) { throw error; }
return setTimeout(done, 200);
});
return null;
});
return it('should push the doc addition to the project history api', function (done) {
rclient_project_history.lrange(
ProjectHistoryKeys.projectHistoryOps({ project_id: this.project_id }),
0,
-1,
(error, updates) => {
if (error != null) {
throw error
}
return it("should push the doc addition to the project history api", function(done) {
rclient_project_history.lrange(ProjectHistoryKeys.projectHistoryOps({project_id: this.project_id}), 0, -1, (error, updates) => {
if (error != null) { throw error; }
const update = JSON.parse(updates[0])
update.doc.should.equal(this.docUpdate.id)
update.pathname.should.equal('/file-path')
update.docLines.should.equal('a\nb')
update.meta.user_id.should.equal(this.user_id)
update.meta.ts.should.be.a('string')
update.version.should.equal(`${this.version}.0`)
const update = JSON.parse(updates[0]);
update.doc.should.equal(this.docUpdate.id);
update.pathname.should.equal('/file-path');
update.docLines.should.equal('a\nb');
update.meta.user_id.should.equal(this.user_id);
update.meta.ts.should.be.a('string');
update.version.should.equal(`${this.version}.0`);
return done()
}
)
return null
})
})
return done();
});
return null;
});
});
describe('with enough updates to flush to the history service', function () {
before(function (done) {
this.project_id = DocUpdaterClient.randomId()
this.user_id = DocUpdaterClient.randomId()
this.version0 = 12345
this.version1 = this.version0 + 1
const updates = []
for (let v = 0; v <= 599; v++) {
// Should flush after 500 ops
updates.push({
id: DocUpdaterClient.randomId(),
pathname: '/file-' + v,
docLines: 'a\nb'
})
}
describe("with enough updates to flush to the history service", function() {
before(function(done) {
this.project_id = DocUpdaterClient.randomId();
this.user_id = DocUpdaterClient.randomId();
this.version0 = 12345;
this.version1 = this.version0 + 1;
const updates = [];
for (let v = 0; v <= 599; v++) { // Should flush after 500 ops
updates.push({
id: DocUpdaterClient.randomId(),
pathname: '/file-' + v,
docLines: 'a\nb'
});
}
sinon.spy(MockProjectHistoryApi, 'flushProject')
sinon.spy(MockProjectHistoryApi, "flushProject");
// Send updates in chunks to causes multiple flushes
const projectId = this.project_id
const userId = this.project_id
DocUpdaterClient.sendProjectUpdate(
projectId,
userId,
updates.slice(0, 250),
[],
this.version0,
function (error) {
if (error != null) {
throw error
}
return DocUpdaterClient.sendProjectUpdate(
projectId,
userId,
updates.slice(250),
[],
this.version1,
(error) => {
if (error != null) {
throw error
}
return setTimeout(done, 2000)
}
)
}
)
return null
})
// Send updates in chunks to causes multiple flushes
const projectId = this.project_id;
const userId = this.project_id;
DocUpdaterClient.sendProjectUpdate(projectId, userId, updates.slice(0, 250), [], this.version0, function(error) {
if (error != null) { throw error; }
return DocUpdaterClient.sendProjectUpdate(projectId, userId, updates.slice(250), [], this.version1, (error) => {
if (error != null) { throw error; }
return setTimeout(done, 2000);
});
});
return null;
});
after(function () {
return MockProjectHistoryApi.flushProject.restore()
})
after(function() { return MockProjectHistoryApi.flushProject.restore(); });
return it('should flush project history', function () {
return MockProjectHistoryApi.flushProject
.calledWith(this.project_id)
.should.equal(true)
})
})
return it("should flush project history", function() {
return MockProjectHistoryApi.flushProject.calledWith(this.project_id).should.equal(true);
});
});
return describe('with too few updates to flush to the history service', function () {
before(function (done) {
this.project_id = DocUpdaterClient.randomId()
this.user_id = DocUpdaterClient.randomId()
this.version0 = 12345
this.version1 = this.version0 + 1
return describe("with too few updates to flush to the history service", function() {
before(function(done) {
this.project_id = DocUpdaterClient.randomId();
this.user_id = DocUpdaterClient.randomId();
this.version0 = 12345;
this.version1 = this.version0 + 1;
const updates = []
for (let v = 0; v <= 42; v++) {
// Should flush after 500 ops
updates.push({
id: DocUpdaterClient.randomId(),
pathname: '/file-' + v,
docLines: 'a\nb'
})
}
const updates = [];
for (let v = 0; v <= 42; v++) { // Should flush after 500 ops
updates.push({
id: DocUpdaterClient.randomId(),
pathname: '/file-' + v,
docLines: 'a\nb'
});
}
sinon.spy(MockProjectHistoryApi, 'flushProject')
sinon.spy(MockProjectHistoryApi, "flushProject");
// Send updates in chunks
const projectId = this.project_id
const userId = this.project_id
DocUpdaterClient.sendProjectUpdate(
projectId,
userId,
updates.slice(0, 10),
[],
this.version0,
function (error) {
if (error != null) {
throw error
}
return DocUpdaterClient.sendProjectUpdate(
projectId,
userId,
updates.slice(10),
[],
this.version1,
(error) => {
if (error != null) {
throw error
}
return setTimeout(done, 2000)
}
)
}
)
return null
})
// Send updates in chunks
const projectId = this.project_id;
const userId = this.project_id;
DocUpdaterClient.sendProjectUpdate(projectId, userId, updates.slice(0, 10), [], this.version0, function(error) {
if (error != null) { throw error; }
return DocUpdaterClient.sendProjectUpdate(projectId, userId, updates.slice(10), [], this.version1, (error) => {
if (error != null) { throw error; }
return setTimeout(done, 2000);
});
});
return null;
});
after(function () {
return MockProjectHistoryApi.flushProject.restore()
})
after(function() { return MockProjectHistoryApi.flushProject.restore(); });
return it("should not flush project history", function() {
return MockProjectHistoryApi.flushProject.calledWith(this.project_id).should.equal(false);
});
});
});
return it('should not flush project history', function () {
return MockProjectHistoryApi.flushProject
.calledWith(this.project_id)
.should.equal(false)
})
})
})

View file

@ -10,137 +10,186 @@
* 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 sinon = require('sinon')
const chai = require('chai')
chai.should()
const MockTrackChangesApi = require("./helpers/MockTrackChangesApi");
const MockProjectHistoryApi = require("./helpers/MockProjectHistoryApi");
const MockWebApi = require("./helpers/MockWebApi");
const DocUpdaterClient = require("./helpers/DocUpdaterClient");
const DocUpdaterApp = require("./helpers/DocUpdaterApp");
const MockTrackChangesApi = require('./helpers/MockTrackChangesApi')
const MockProjectHistoryApi = require('./helpers/MockProjectHistoryApi')
const MockWebApi = require('./helpers/MockWebApi')
const DocUpdaterClient = require('./helpers/DocUpdaterClient')
const DocUpdaterApp = require('./helpers/DocUpdaterApp')
describe("Deleting a document", function() {
before(function(done) {
this.lines = ["one", "two", "three"];
this.version = 42;
this.update = {
doc: this.doc_id,
op: [{
i: "one and a half\n",
p: 4
}],
v: this.version
};
this.result = ["one", "one and a half", "two", "three"];
describe('Deleting a document', function () {
before(function (done) {
this.lines = ['one', 'two', 'three']
this.version = 42
this.update = {
doc: this.doc_id,
op: [
{
i: 'one and a half\n',
p: 4
}
],
v: this.version
}
this.result = ['one', 'one and a half', 'two', 'three']
sinon.spy(MockTrackChangesApi, "flushDoc");
sinon.spy(MockProjectHistoryApi, "flushProject");
return DocUpdaterApp.ensureRunning(done);
});
sinon.spy(MockTrackChangesApi, 'flushDoc')
sinon.spy(MockProjectHistoryApi, 'flushProject')
return DocUpdaterApp.ensureRunning(done)
})
after(function() {
MockTrackChangesApi.flushDoc.restore();
return MockProjectHistoryApi.flushProject.restore();
});
after(function () {
MockTrackChangesApi.flushDoc.restore()
return MockProjectHistoryApi.flushProject.restore()
})
describe("when the updated doc exists in the doc updater", function() {
before(function(done) {
[this.project_id, this.doc_id] = Array.from([DocUpdaterClient.randomId(), DocUpdaterClient.randomId()]);
sinon.spy(MockWebApi, "setDocument");
sinon.spy(MockWebApi, "getDocument");
describe('when the updated doc exists in the doc updater', function () {
before(function (done) {
;[this.project_id, this.doc_id] = Array.from([
DocUpdaterClient.randomId(),
DocUpdaterClient.randomId()
])
sinon.spy(MockWebApi, 'setDocument')
sinon.spy(MockWebApi, 'getDocument')
MockWebApi.insertDoc(this.project_id, this.doc_id, {lines: this.lines, version: this.version});
return DocUpdaterClient.preloadDoc(this.project_id, this.doc_id, error => {
if (error != null) { throw error; }
return DocUpdaterClient.sendUpdate(this.project_id, this.doc_id, this.update, error => {
if (error != null) { throw error; }
return setTimeout(() => {
return DocUpdaterClient.deleteDoc(this.project_id, this.doc_id, (error, res, body) => {
this.statusCode = res.statusCode;
return setTimeout(done, 200);
});
}
, 200);
});
});
});
MockWebApi.insertDoc(this.project_id, this.doc_id, {
lines: this.lines,
version: this.version
})
return DocUpdaterClient.preloadDoc(
this.project_id,
this.doc_id,
(error) => {
if (error != null) {
throw error
}
return DocUpdaterClient.sendUpdate(
this.project_id,
this.doc_id,
this.update,
(error) => {
if (error != null) {
throw error
}
return setTimeout(() => {
return DocUpdaterClient.deleteDoc(
this.project_id,
this.doc_id,
(error, res, body) => {
this.statusCode = res.statusCode
return setTimeout(done, 200)
}
)
}, 200)
}
)
}
)
})
after(function() {
MockWebApi.setDocument.restore();
return MockWebApi.getDocument.restore();
});
after(function () {
MockWebApi.setDocument.restore()
return MockWebApi.getDocument.restore()
})
it("should return a 204 status code", function() {
return this.statusCode.should.equal(204);
});
it('should return a 204 status code', function () {
return this.statusCode.should.equal(204)
})
it("should send the updated document and version to the web api", function() {
return MockWebApi.setDocument
.calledWith(this.project_id, this.doc_id, this.result, this.version + 1)
.should.equal(true);
});
it('should send the updated document and version to the web api', function () {
return MockWebApi.setDocument
.calledWith(this.project_id, this.doc_id, this.result, this.version + 1)
.should.equal(true)
})
it("should need to reload the doc if read again", function(done) {
MockWebApi.getDocument.called.should.equal.false;
return DocUpdaterClient.getDoc(this.project_id, this.doc_id, (error, res, doc) => {
MockWebApi.getDocument
.calledWith(this.project_id, this.doc_id)
.should.equal(true);
return done();
});
});
it('should need to reload the doc if read again', function (done) {
MockWebApi.getDocument.called.should.equal.false
return DocUpdaterClient.getDoc(
this.project_id,
this.doc_id,
(error, res, doc) => {
MockWebApi.getDocument
.calledWith(this.project_id, this.doc_id)
.should.equal(true)
return done()
}
)
})
it("should flush track changes", function() {
return MockTrackChangesApi.flushDoc.calledWith(this.doc_id).should.equal(true);
});
it('should flush track changes', function () {
return MockTrackChangesApi.flushDoc
.calledWith(this.doc_id)
.should.equal(true)
})
return it("should flush project history", function() {
return MockProjectHistoryApi.flushProject.calledWith(this.project_id).should.equal(true);
});
});
return it('should flush project history', function () {
return MockProjectHistoryApi.flushProject
.calledWith(this.project_id)
.should.equal(true)
})
})
return describe("when the doc is not in the doc updater", function() {
before(function(done) {
[this.project_id, this.doc_id] = Array.from([DocUpdaterClient.randomId(), DocUpdaterClient.randomId()]);
MockWebApi.insertDoc(this.project_id, this.doc_id, {
lines: this.lines
});
sinon.spy(MockWebApi, "setDocument");
sinon.spy(MockWebApi, "getDocument");
return DocUpdaterClient.deleteDoc(this.project_id, this.doc_id, (error, res, body) => {
this.statusCode = res.statusCode;
return setTimeout(done, 200);
});
});
return describe('when the doc is not in the doc updater', function () {
before(function (done) {
;[this.project_id, this.doc_id] = Array.from([
DocUpdaterClient.randomId(),
DocUpdaterClient.randomId()
])
MockWebApi.insertDoc(this.project_id, this.doc_id, {
lines: this.lines
})
sinon.spy(MockWebApi, 'setDocument')
sinon.spy(MockWebApi, 'getDocument')
return DocUpdaterClient.deleteDoc(
this.project_id,
this.doc_id,
(error, res, body) => {
this.statusCode = res.statusCode
return setTimeout(done, 200)
}
)
})
after(function() {
MockWebApi.setDocument.restore();
return MockWebApi.getDocument.restore();
});
after(function () {
MockWebApi.setDocument.restore()
return MockWebApi.getDocument.restore()
})
it("should return a 204 status code", function() {
return this.statusCode.should.equal(204);
});
it('should return a 204 status code', function () {
return this.statusCode.should.equal(204)
})
it("should not need to send the updated document to the web api", function() { return MockWebApi.setDocument.called.should.equal(false); });
it('should not need to send the updated document to the web api', function () {
return MockWebApi.setDocument.called.should.equal(false)
})
it("should need to reload the doc if read again", function(done) {
MockWebApi.getDocument.called.should.equal.false;
return DocUpdaterClient.getDoc(this.project_id, this.doc_id, (error, res, doc) => {
MockWebApi.getDocument
.calledWith(this.project_id, this.doc_id)
.should.equal(true);
return done();
});
});
it('should need to reload the doc if read again', function (done) {
MockWebApi.getDocument.called.should.equal.false
return DocUpdaterClient.getDoc(
this.project_id,
this.doc_id,
(error, res, doc) => {
MockWebApi.getDocument
.calledWith(this.project_id, this.doc_id)
.should.equal(true)
return done()
}
)
})
it("should flush track changes", function() {
return MockTrackChangesApi.flushDoc.calledWith(this.doc_id).should.equal(true);
});
it('should flush track changes', function () {
return MockTrackChangesApi.flushDoc
.calledWith(this.doc_id)
.should.equal(true)
})
return it("should flush project history", function() {
return MockProjectHistoryApi.flushProject.calledWith(this.project_id).should.equal(true);
});
});
});
return it('should flush project history', function () {
return MockProjectHistoryApi.flushProject
.calledWith(this.project_id)
.should.equal(true)
})
})
})

View file

@ -11,213 +11,285 @@
* 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 async = require("async");
const sinon = require('sinon')
const chai = require('chai')
chai.should()
const async = require('async')
const MockTrackChangesApi = require("./helpers/MockTrackChangesApi");
const MockProjectHistoryApi = require("./helpers/MockProjectHistoryApi");
const MockWebApi = require("./helpers/MockWebApi");
const DocUpdaterClient = require("./helpers/DocUpdaterClient");
const DocUpdaterApp = require("./helpers/DocUpdaterApp");
const MockTrackChangesApi = require('./helpers/MockTrackChangesApi')
const MockProjectHistoryApi = require('./helpers/MockProjectHistoryApi')
const MockWebApi = require('./helpers/MockWebApi')
const DocUpdaterClient = require('./helpers/DocUpdaterClient')
const DocUpdaterApp = require('./helpers/DocUpdaterApp')
describe("Deleting a project", function() {
before(function(done) {
let doc_id0, doc_id1;
this.project_id = DocUpdaterClient.randomId();
this.docs = [{
id: (doc_id0 = DocUpdaterClient.randomId()),
lines: ["one", "two", "three"],
update: {
doc: doc_id0,
op: [{
i: "one and a half\n",
p: 4
}],
v: 0
},
updatedLines: ["one", "one and a half", "two", "three"]
}, {
id: (doc_id1 = DocUpdaterClient.randomId()),
lines: ["four", "five", "six"],
update: {
doc: doc_id1,
op: [{
i: "four and a half\n",
p: 5
}],
v: 0
},
updatedLines: ["four", "four and a half", "five", "six"]
}];
for (const doc of Array.from(this.docs)) {
MockWebApi.insertDoc(this.project_id, doc.id, {
lines: doc.lines,
version: doc.update.v
});
}
describe('Deleting a project', function () {
before(function (done) {
let doc_id0, doc_id1
this.project_id = DocUpdaterClient.randomId()
this.docs = [
{
id: (doc_id0 = DocUpdaterClient.randomId()),
lines: ['one', 'two', 'three'],
update: {
doc: doc_id0,
op: [
{
i: 'one and a half\n',
p: 4
}
],
v: 0
},
updatedLines: ['one', 'one and a half', 'two', 'three']
},
{
id: (doc_id1 = DocUpdaterClient.randomId()),
lines: ['four', 'five', 'six'],
update: {
doc: doc_id1,
op: [
{
i: 'four and a half\n',
p: 5
}
],
v: 0
},
updatedLines: ['four', 'four and a half', 'five', 'six']
}
]
for (const doc of Array.from(this.docs)) {
MockWebApi.insertDoc(this.project_id, doc.id, {
lines: doc.lines,
version: doc.update.v
})
}
return DocUpdaterApp.ensureRunning(done);
});
return DocUpdaterApp.ensureRunning(done)
})
describe('with documents which have been updated', function () {
before(function (done) {
sinon.spy(MockWebApi, 'setDocument')
sinon.spy(MockTrackChangesApi, 'flushDoc')
sinon.spy(MockProjectHistoryApi, 'flushProject')
describe("with documents which have been updated", function() {
before(function(done) {
sinon.spy(MockWebApi, "setDocument");
sinon.spy(MockTrackChangesApi, "flushDoc");
sinon.spy(MockProjectHistoryApi, "flushProject");
return async.series(
this.docs.map((doc) => {
return (callback) => {
return DocUpdaterClient.preloadDoc(
this.project_id,
doc.id,
(error) => {
if (error != null) {
return callback(error)
}
return DocUpdaterClient.sendUpdate(
this.project_id,
doc.id,
doc.update,
(error) => {
return callback(error)
}
)
}
)
}
}),
(error) => {
if (error != null) {
throw error
}
return setTimeout(() => {
return DocUpdaterClient.deleteProject(
this.project_id,
(error, res, body) => {
this.statusCode = res.statusCode
return done()
}
)
}, 200)
}
)
})
return async.series(this.docs.map(doc => {
return callback => {
return DocUpdaterClient.preloadDoc(this.project_id, doc.id, error => {
if (error != null) { return callback(error); }
return DocUpdaterClient.sendUpdate(this.project_id, doc.id, doc.update, error => {
return callback(error);
});
});
};
}), error => {
if (error != null) { throw error; }
return setTimeout(() => {
return DocUpdaterClient.deleteProject(this.project_id, (error, res, body) => {
this.statusCode = res.statusCode;
return done();
});
}
, 200);
});
});
after(function () {
MockWebApi.setDocument.restore()
MockTrackChangesApi.flushDoc.restore()
return MockProjectHistoryApi.flushProject.restore()
})
after(function() {
MockWebApi.setDocument.restore();
MockTrackChangesApi.flushDoc.restore();
return MockProjectHistoryApi.flushProject.restore();
});
it('should return a 204 status code', function () {
return this.statusCode.should.equal(204)
})
it("should return a 204 status code", function() {
return this.statusCode.should.equal(204);
});
it('should send each document to the web api', function () {
return Array.from(this.docs).map((doc) =>
MockWebApi.setDocument
.calledWith(this.project_id, doc.id, doc.updatedLines)
.should.equal(true)
)
})
it("should send each document to the web api", function() {
return Array.from(this.docs).map((doc) =>
MockWebApi.setDocument
.calledWith(this.project_id, doc.id, doc.updatedLines)
.should.equal(true));
});
it('should need to reload the docs if read again', function (done) {
sinon.spy(MockWebApi, 'getDocument')
return async.series(
this.docs.map((doc) => {
return (callback) => {
MockWebApi.getDocument
.calledWith(this.project_id, doc.id)
.should.equal(false)
return DocUpdaterClient.getDoc(
this.project_id,
doc.id,
(error, res, returnedDoc) => {
MockWebApi.getDocument
.calledWith(this.project_id, doc.id)
.should.equal(true)
return callback()
}
)
}
}),
() => {
MockWebApi.getDocument.restore()
return done()
}
)
})
it("should need to reload the docs if read again", function(done) {
sinon.spy(MockWebApi, "getDocument");
return async.series(this.docs.map(doc => {
return callback => {
MockWebApi.getDocument.calledWith(this.project_id, doc.id).should.equal(false);
return DocUpdaterClient.getDoc(this.project_id, doc.id, (error, res, returnedDoc) => {
MockWebApi.getDocument.calledWith(this.project_id, doc.id).should.equal(true);
return callback();
});
};
}), () => {
MockWebApi.getDocument.restore();
return done();
});
});
it('should flush each doc in track changes', function () {
return Array.from(this.docs).map((doc) =>
MockTrackChangesApi.flushDoc.calledWith(doc.id).should.equal(true)
)
})
it("should flush each doc in track changes", function() {
return Array.from(this.docs).map((doc) =>
MockTrackChangesApi.flushDoc.calledWith(doc.id).should.equal(true));
});
return it('should flush each doc in project history', function () {
return MockProjectHistoryApi.flushProject
.calledWith(this.project_id)
.should.equal(true)
})
})
return it("should flush each doc in project history", function() {
return MockProjectHistoryApi.flushProject.calledWith(this.project_id).should.equal(true);
});
});
describe('with the background=true parameter from realtime and no request to flush the queue', function () {
before(function (done) {
sinon.spy(MockWebApi, 'setDocument')
sinon.spy(MockTrackChangesApi, 'flushDoc')
sinon.spy(MockProjectHistoryApi, 'flushProject')
describe("with the background=true parameter from realtime and no request to flush the queue", function() {
before(function(done) {
sinon.spy(MockWebApi, "setDocument");
sinon.spy(MockTrackChangesApi, "flushDoc");
sinon.spy(MockProjectHistoryApi, "flushProject");
return async.series(
this.docs.map((doc) => {
return (callback) => {
return DocUpdaterClient.preloadDoc(
this.project_id,
doc.id,
callback
)
}
}),
(error) => {
if (error != null) {
throw error
}
return setTimeout(() => {
return DocUpdaterClient.deleteProjectOnShutdown(
this.project_id,
(error, res, body) => {
this.statusCode = res.statusCode
return done()
}
)
}, 200)
}
)
})
return async.series(this.docs.map(doc => {
return callback => {
return DocUpdaterClient.preloadDoc(this.project_id, doc.id, callback);
};
}), error => {
if (error != null) { throw error; }
return setTimeout(() => {
return DocUpdaterClient.deleteProjectOnShutdown(this.project_id, (error, res, body) => {
this.statusCode = res.statusCode;
return done();
});
}
, 200);
});
});
after(function () {
MockWebApi.setDocument.restore()
MockTrackChangesApi.flushDoc.restore()
return MockProjectHistoryApi.flushProject.restore()
})
after(function() {
MockWebApi.setDocument.restore();
MockTrackChangesApi.flushDoc.restore();
return MockProjectHistoryApi.flushProject.restore();
});
it('should return a 204 status code', function () {
return this.statusCode.should.equal(204)
})
it("should return a 204 status code", function() {
return this.statusCode.should.equal(204);
});
it('should not send any documents to the web api', function () {
return MockWebApi.setDocument.called.should.equal(false)
})
it("should not send any documents to the web api", function() { return MockWebApi.setDocument.called.should.equal(false); });
it('should not flush any docs in track changes', function () {
return MockTrackChangesApi.flushDoc.called.should.equal(false)
})
it("should not flush any docs in track changes", function() { return MockTrackChangesApi.flushDoc.called.should.equal(false); });
return it('should not flush to project history', function () {
return MockProjectHistoryApi.flushProject.called.should.equal(false)
})
})
return it("should not flush to project history", function() { return MockProjectHistoryApi.flushProject.called.should.equal(false); });
});
return describe('with the background=true parameter from realtime and a request to flush the queue', function () {
before(function (done) {
sinon.spy(MockWebApi, 'setDocument')
sinon.spy(MockTrackChangesApi, 'flushDoc')
sinon.spy(MockProjectHistoryApi, 'flushProject')
return describe("with the background=true parameter from realtime and a request to flush the queue", function() {
before(function(done) {
sinon.spy(MockWebApi, "setDocument");
sinon.spy(MockTrackChangesApi, "flushDoc");
sinon.spy(MockProjectHistoryApi, "flushProject");
return async.series(
this.docs.map((doc) => {
return (callback) => {
return DocUpdaterClient.preloadDoc(
this.project_id,
doc.id,
callback
)
}
}),
(error) => {
if (error != null) {
throw error
}
return setTimeout(() => {
return DocUpdaterClient.deleteProjectOnShutdown(
this.project_id,
(error, res, body) => {
this.statusCode = res.statusCode
// after deleting the project and putting it in the queue, flush the queue
return setTimeout(
() => DocUpdaterClient.flushOldProjects(done),
2000
)
}
)
}, 200)
}
)
})
return async.series(this.docs.map(doc => {
return callback => {
return DocUpdaterClient.preloadDoc(this.project_id, doc.id, callback);
};
}), error => {
if (error != null) { throw error; }
return setTimeout(() => {
return DocUpdaterClient.deleteProjectOnShutdown(this.project_id, (error, res, body) => {
this.statusCode = res.statusCode;
// after deleting the project and putting it in the queue, flush the queue
return setTimeout(() => DocUpdaterClient.flushOldProjects(done)
, 2000);
});
}
, 200);
});
});
after(function () {
MockWebApi.setDocument.restore()
MockTrackChangesApi.flushDoc.restore()
return MockProjectHistoryApi.flushProject.restore()
})
after(function() {
MockWebApi.setDocument.restore();
MockTrackChangesApi.flushDoc.restore();
return MockProjectHistoryApi.flushProject.restore();
});
it('should return a 204 status code', function () {
return this.statusCode.should.equal(204)
})
it("should return a 204 status code", function() {
return this.statusCode.should.equal(204);
});
it('should send each document to the web api', function () {
return Array.from(this.docs).map((doc) =>
MockWebApi.setDocument
.calledWith(this.project_id, doc.id, doc.updatedLines)
.should.equal(true)
)
})
it("should send each document to the web api", function() {
return Array.from(this.docs).map((doc) =>
MockWebApi.setDocument
.calledWith(this.project_id, doc.id, doc.updatedLines)
.should.equal(true));
});
it("should flush each doc in track changes", function() {
return Array.from(this.docs).map((doc) =>
MockTrackChangesApi.flushDoc.calledWith(doc.id).should.equal(true));
});
return it("should flush to project history", function() { return MockProjectHistoryApi.flushProject.called.should.equal(true); });
});
});
it('should flush each doc in track changes', function () {
return Array.from(this.docs).map((doc) =>
MockTrackChangesApi.flushDoc.calledWith(doc.id).should.equal(true)
)
})
return it('should flush to project history', function () {
return MockProjectHistoryApi.flushProject.called.should.equal(true)
})
})
})

View file

@ -11,101 +11,135 @@
* 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 async = require("async");
const sinon = require('sinon')
const chai = require('chai')
chai.should()
const async = require('async')
const MockWebApi = require("./helpers/MockWebApi");
const DocUpdaterClient = require("./helpers/DocUpdaterClient");
const DocUpdaterApp = require("./helpers/DocUpdaterApp");
const MockWebApi = require('./helpers/MockWebApi')
const DocUpdaterClient = require('./helpers/DocUpdaterClient')
const DocUpdaterApp = require('./helpers/DocUpdaterApp')
describe("Flushing a project", function() {
before(function(done) {
let doc_id0, doc_id1;
this.project_id = DocUpdaterClient.randomId();
this.docs = [{
id: (doc_id0 = DocUpdaterClient.randomId()),
lines: ["one", "two", "three"],
update: {
doc: doc_id0,
op: [{
i: "one and a half\n",
p: 4
}],
v: 0
},
updatedLines: ["one", "one and a half", "two", "three"]
}, {
id: (doc_id1 = DocUpdaterClient.randomId()),
lines: ["four", "five", "six"],
update: {
doc: doc_id1,
op: [{
i: "four and a half\n",
p: 5
}],
v: 0
},
updatedLines: ["four", "four and a half", "five", "six"]
}];
for (const doc of Array.from(this.docs)) {
MockWebApi.insertDoc(this.project_id, doc.id, {
lines: doc.lines,
version: doc.update.v
});
}
return DocUpdaterApp.ensureRunning(done);
});
describe('Flushing a project', function () {
before(function (done) {
let doc_id0, doc_id1
this.project_id = DocUpdaterClient.randomId()
this.docs = [
{
id: (doc_id0 = DocUpdaterClient.randomId()),
lines: ['one', 'two', 'three'],
update: {
doc: doc_id0,
op: [
{
i: 'one and a half\n',
p: 4
}
],
v: 0
},
updatedLines: ['one', 'one and a half', 'two', 'three']
},
{
id: (doc_id1 = DocUpdaterClient.randomId()),
lines: ['four', 'five', 'six'],
update: {
doc: doc_id1,
op: [
{
i: 'four and a half\n',
p: 5
}
],
v: 0
},
updatedLines: ['four', 'four and a half', 'five', 'six']
}
]
for (const doc of Array.from(this.docs)) {
MockWebApi.insertDoc(this.project_id, doc.id, {
lines: doc.lines,
version: doc.update.v
})
}
return DocUpdaterApp.ensureRunning(done)
})
return describe("with documents which have been updated", function() {
before(function(done) {
sinon.spy(MockWebApi, "setDocument");
return describe('with documents which have been updated', function () {
before(function (done) {
sinon.spy(MockWebApi, 'setDocument')
return async.series(this.docs.map(doc => {
return callback => {
return DocUpdaterClient.preloadDoc(this.project_id, doc.id, error => {
if (error != null) { return callback(error); }
return DocUpdaterClient.sendUpdate(this.project_id, doc.id, doc.update, error => {
return callback(error);
});
});
};
}), error => {
if (error != null) { throw error; }
return setTimeout(() => {
return DocUpdaterClient.flushProject(this.project_id, (error, res, body) => {
this.statusCode = res.statusCode;
return done();
});
}
, 200);
});
});
return async.series(
this.docs.map((doc) => {
return (callback) => {
return DocUpdaterClient.preloadDoc(
this.project_id,
doc.id,
(error) => {
if (error != null) {
return callback(error)
}
return DocUpdaterClient.sendUpdate(
this.project_id,
doc.id,
doc.update,
(error) => {
return callback(error)
}
)
}
)
}
}),
(error) => {
if (error != null) {
throw error
}
return setTimeout(() => {
return DocUpdaterClient.flushProject(
this.project_id,
(error, res, body) => {
this.statusCode = res.statusCode
return done()
}
)
}, 200)
}
)
})
after(function() { return MockWebApi.setDocument.restore(); });
after(function () {
return MockWebApi.setDocument.restore()
})
it("should return a 204 status code", function() {
return this.statusCode.should.equal(204);
});
it('should return a 204 status code', function () {
return this.statusCode.should.equal(204)
})
it("should send each document to the web api", function() {
return Array.from(this.docs).map((doc) =>
MockWebApi.setDocument
.calledWith(this.project_id, doc.id, doc.updatedLines)
.should.equal(true));
});
return it("should update the lines in the doc updater", function(done) {
return async.series(this.docs.map(doc => {
return callback => {
return DocUpdaterClient.getDoc(this.project_id, doc.id, (error, res, returnedDoc) => {
returnedDoc.lines.should.deep.equal(doc.updatedLines);
return callback();
});
};
}), done);
});
});
});
it('should send each document to the web api', function () {
return Array.from(this.docs).map((doc) =>
MockWebApi.setDocument
.calledWith(this.project_id, doc.id, doc.updatedLines)
.should.equal(true)
)
})
return it('should update the lines in the doc updater', function (done) {
return async.series(
this.docs.map((doc) => {
return (callback) => {
return DocUpdaterClient.getDoc(
this.project_id,
doc.id,
(error, res, returnedDoc) => {
returnedDoc.lines.should.deep.equal(doc.updatedLines)
return callback()
}
)
}
}),
done
)
})
})
})

View file

@ -13,108 +13,153 @@
* 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 async = require("async");
const sinon = require('sinon')
const chai = require('chai')
chai.should()
const { expect } = chai
const async = require('async')
const MockWebApi = require("./helpers/MockWebApi");
const DocUpdaterClient = require("./helpers/DocUpdaterClient");
const DocUpdaterApp = require("./helpers/DocUpdaterApp");
const MockWebApi = require('./helpers/MockWebApi')
const DocUpdaterClient = require('./helpers/DocUpdaterClient')
const DocUpdaterApp = require('./helpers/DocUpdaterApp')
describe("Flushing a doc to Mongo", function() {
before(function(done) {
this.lines = ["one", "two", "three"];
this.version = 42;
this.update = {
doc: this.doc_id,
meta: { user_id: 'last-author-fake-id' },
op: [{
i: "one and a half\n",
p: 4
}],
v: this.version
};
this.result = ["one", "one and a half", "two", "three"];
return DocUpdaterApp.ensureRunning(done);
});
describe('Flushing a doc to Mongo', function () {
before(function (done) {
this.lines = ['one', 'two', 'three']
this.version = 42
this.update = {
doc: this.doc_id,
meta: { user_id: 'last-author-fake-id' },
op: [
{
i: 'one and a half\n',
p: 4
}
],
v: this.version
}
this.result = ['one', 'one and a half', 'two', 'three']
return DocUpdaterApp.ensureRunning(done)
})
describe("when the updated doc exists in the doc updater", function() {
before(function(done) {
[this.project_id, this.doc_id] = Array.from([DocUpdaterClient.randomId(), DocUpdaterClient.randomId()]);
sinon.spy(MockWebApi, "setDocument");
describe('when the updated doc exists in the doc updater', function () {
before(function (done) {
;[this.project_id, this.doc_id] = Array.from([
DocUpdaterClient.randomId(),
DocUpdaterClient.randomId()
])
sinon.spy(MockWebApi, 'setDocument')
MockWebApi.insertDoc(this.project_id, this.doc_id, {lines: this.lines, version: this.version});
return DocUpdaterClient.sendUpdates(this.project_id, this.doc_id, [this.update], error => {
if (error != null) { throw error; }
return setTimeout(() => {
return DocUpdaterClient.flushDoc(this.project_id, this.doc_id, done);
}
, 200);
});
});
MockWebApi.insertDoc(this.project_id, this.doc_id, {
lines: this.lines,
version: this.version
})
return DocUpdaterClient.sendUpdates(
this.project_id,
this.doc_id,
[this.update],
(error) => {
if (error != null) {
throw error
}
return setTimeout(() => {
return DocUpdaterClient.flushDoc(this.project_id, this.doc_id, done)
}, 200)
}
)
})
after(function() { return MockWebApi.setDocument.restore(); });
after(function () {
return MockWebApi.setDocument.restore()
})
it("should flush the updated doc lines and version to the web api", function() {
return MockWebApi.setDocument
.calledWith(this.project_id, this.doc_id, this.result, this.version + 1)
.should.equal(true);
});
it('should flush the updated doc lines and version to the web api', function () {
return MockWebApi.setDocument
.calledWith(this.project_id, this.doc_id, this.result, this.version + 1)
.should.equal(true)
})
return it("should flush the last update author and time to the web api", function() {
const lastUpdatedAt = MockWebApi.setDocument.lastCall.args[5];
parseInt(lastUpdatedAt).should.be.closeTo((new Date()).getTime(), 30000);
return it('should flush the last update author and time to the web api', function () {
const lastUpdatedAt = MockWebApi.setDocument.lastCall.args[5]
parseInt(lastUpdatedAt).should.be.closeTo(new Date().getTime(), 30000)
const lastUpdatedBy = MockWebApi.setDocument.lastCall.args[6];
return lastUpdatedBy.should.equal('last-author-fake-id');
});
});
const lastUpdatedBy = MockWebApi.setDocument.lastCall.args[6]
return lastUpdatedBy.should.equal('last-author-fake-id')
})
})
describe("when the doc does not exist in the doc updater", function() {
before(function(done) {
[this.project_id, this.doc_id] = Array.from([DocUpdaterClient.randomId(), DocUpdaterClient.randomId()]);
MockWebApi.insertDoc(this.project_id, this.doc_id, {
lines: this.lines
});
sinon.spy(MockWebApi, "setDocument");
return DocUpdaterClient.flushDoc(this.project_id, this.doc_id, done);
});
describe('when the doc does not exist in the doc updater', function () {
before(function (done) {
;[this.project_id, this.doc_id] = Array.from([
DocUpdaterClient.randomId(),
DocUpdaterClient.randomId()
])
MockWebApi.insertDoc(this.project_id, this.doc_id, {
lines: this.lines
})
sinon.spy(MockWebApi, 'setDocument')
return DocUpdaterClient.flushDoc(this.project_id, this.doc_id, done)
})
after(function() { return MockWebApi.setDocument.restore(); });
after(function () {
return MockWebApi.setDocument.restore()
})
return it("should not flush the doc to the web api", function() { return MockWebApi.setDocument.called.should.equal(false); });
});
return it('should not flush the doc to the web api', function () {
return MockWebApi.setDocument.called.should.equal(false)
})
})
return describe("when the web api http request takes a long time on first request", function() {
before(function(done) {
[this.project_id, this.doc_id] = Array.from([DocUpdaterClient.randomId(), DocUpdaterClient.randomId()]);
MockWebApi.insertDoc(this.project_id, this.doc_id, {
lines: this.lines,
version: this.version
});
let t = 30000;
sinon.stub(MockWebApi, "setDocument", (project_id, doc_id, lines, version, ranges, lastUpdatedAt, lastUpdatedBy, callback) => {
if (callback == null) { callback = function(error) {}; }
setTimeout(callback, t);
return t = 0;
});
return DocUpdaterClient.preloadDoc(this.project_id, this.doc_id, done);
});
return describe('when the web api http request takes a long time on first request', function () {
before(function (done) {
;[this.project_id, this.doc_id] = Array.from([
DocUpdaterClient.randomId(),
DocUpdaterClient.randomId()
])
MockWebApi.insertDoc(this.project_id, this.doc_id, {
lines: this.lines,
version: this.version
})
let t = 30000
sinon.stub(
MockWebApi,
'setDocument',
(
project_id,
doc_id,
lines,
version,
ranges,
lastUpdatedAt,
lastUpdatedBy,
callback
) => {
if (callback == null) {
callback = function (error) {}
}
setTimeout(callback, t)
return (t = 0)
}
)
return DocUpdaterClient.preloadDoc(this.project_id, this.doc_id, done)
})
after(function() { return MockWebApi.setDocument.restore(); });
return it("should still work", function(done) {
const start = Date.now();
return DocUpdaterClient.flushDoc(this.project_id, this.doc_id, (error, res, doc) => {
res.statusCode.should.equal(204);
const delta = Date.now() - start;
expect(delta).to.be.below(20000);
return done();
});
});
});
});
after(function () {
return MockWebApi.setDocument.restore()
})
return it('should still work', function (done) {
const start = Date.now()
return DocUpdaterClient.flushDoc(
this.project_id,
this.doc_id,
(error, res, doc) => {
res.statusCode.should.equal(204)
const delta = Date.now() - start
expect(delta).to.be.below(20000)
return done()
}
)
})
})
})

View file

@ -11,184 +11,278 @@
* 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 sinon = require('sinon')
const chai = require('chai')
chai.should()
const { expect } = chai
const MockWebApi = require("./helpers/MockWebApi");
const DocUpdaterClient = require("./helpers/DocUpdaterClient");
const DocUpdaterApp = require("./helpers/DocUpdaterApp");
const MockWebApi = require('./helpers/MockWebApi')
const DocUpdaterClient = require('./helpers/DocUpdaterClient')
const DocUpdaterApp = require('./helpers/DocUpdaterApp')
describe("Getting a document", function() {
before(function(done) {
this.lines = ["one", "two", "three"];
this.version = 42;
return DocUpdaterApp.ensureRunning(done);
});
describe('Getting a document', function () {
before(function (done) {
this.lines = ['one', 'two', 'three']
this.version = 42
return DocUpdaterApp.ensureRunning(done)
})
describe("when the document is not loaded", function() {
before(function(done) {
[this.project_id, this.doc_id] = Array.from([DocUpdaterClient.randomId(), DocUpdaterClient.randomId()]);
sinon.spy(MockWebApi, "getDocument");
describe('when the document is not loaded', function () {
before(function (done) {
;[this.project_id, this.doc_id] = Array.from([
DocUpdaterClient.randomId(),
DocUpdaterClient.randomId()
])
sinon.spy(MockWebApi, 'getDocument')
MockWebApi.insertDoc(this.project_id, this.doc_id, {lines: this.lines, version: this.version});
MockWebApi.insertDoc(this.project_id, this.doc_id, {
lines: this.lines,
version: this.version
})
return DocUpdaterClient.getDoc(this.project_id, this.doc_id, (error, res, returnedDoc) => { this.returnedDoc = returnedDoc; return done(); });
});
return DocUpdaterClient.getDoc(
this.project_id,
this.doc_id,
(error, res, returnedDoc) => {
this.returnedDoc = returnedDoc
return done()
}
)
})
after(function() { return MockWebApi.getDocument.restore(); });
after(function () {
return MockWebApi.getDocument.restore()
})
it("should load the document from the web API", function() {
return MockWebApi.getDocument
.calledWith(this.project_id, this.doc_id)
.should.equal(true);
});
it("should return the document lines", function() {
return this.returnedDoc.lines.should.deep.equal(this.lines);
});
it('should load the document from the web API', function () {
return MockWebApi.getDocument
.calledWith(this.project_id, this.doc_id)
.should.equal(true)
})
return it("should return the document at its current version", function() {
return this.returnedDoc.version.should.equal(this.version);
});
});
it('should return the document lines', function () {
return this.returnedDoc.lines.should.deep.equal(this.lines)
})
describe("when the document is already loaded", function() {
before(function(done) {
[this.project_id, this.doc_id] = Array.from([DocUpdaterClient.randomId(), DocUpdaterClient.randomId()]);
MockWebApi.insertDoc(this.project_id, this.doc_id, {lines: this.lines, version: this.version});
return DocUpdaterClient.preloadDoc(this.project_id, this.doc_id, error => {
if (error != null) { throw error; }
sinon.spy(MockWebApi, "getDocument");
return DocUpdaterClient.getDoc(this.project_id, this.doc_id, (error, res, returnedDoc) => { this.returnedDoc = returnedDoc; return done(); });
});
});
return it('should return the document at its current version', function () {
return this.returnedDoc.version.should.equal(this.version)
})
})
after(function() { return MockWebApi.getDocument.restore(); });
describe('when the document is already loaded', function () {
before(function (done) {
;[this.project_id, this.doc_id] = Array.from([
DocUpdaterClient.randomId(),
DocUpdaterClient.randomId()
])
it("should not load the document from the web API", function() { return MockWebApi.getDocument.called.should.equal(false); });
MockWebApi.insertDoc(this.project_id, this.doc_id, {
lines: this.lines,
version: this.version
})
return DocUpdaterClient.preloadDoc(
this.project_id,
this.doc_id,
(error) => {
if (error != null) {
throw error
}
sinon.spy(MockWebApi, 'getDocument')
return DocUpdaterClient.getDoc(
this.project_id,
this.doc_id,
(error, res, returnedDoc) => {
this.returnedDoc = returnedDoc
return done()
}
)
}
)
})
return it("should return the document lines", function() {
return this.returnedDoc.lines.should.deep.equal(this.lines);
});
});
after(function () {
return MockWebApi.getDocument.restore()
})
describe("when the request asks for some recent ops", function() {
before(function(done) {
[this.project_id, this.doc_id] = Array.from([DocUpdaterClient.randomId(), DocUpdaterClient.randomId()]);
MockWebApi.insertDoc(this.project_id, this.doc_id, {
lines: (this.lines = ["one", "two", "three"])
});
it('should not load the document from the web API', function () {
return MockWebApi.getDocument.called.should.equal(false)
})
this.updates = __range__(0, 199, true).map((v) => ({
doc_id: this.doc_id,
op: [{i: v.toString(), p: 0}],
v
}));
return it('should return the document lines', function () {
return this.returnedDoc.lines.should.deep.equal(this.lines)
})
})
return DocUpdaterClient.sendUpdates(this.project_id, this.doc_id, this.updates, error => {
if (error != null) { throw error; }
sinon.spy(MockWebApi, "getDocument");
return done();
});
});
describe('when the request asks for some recent ops', function () {
before(function (done) {
;[this.project_id, this.doc_id] = Array.from([
DocUpdaterClient.randomId(),
DocUpdaterClient.randomId()
])
MockWebApi.insertDoc(this.project_id, this.doc_id, {
lines: (this.lines = ['one', 'two', 'three'])
})
after(function() { return MockWebApi.getDocument.restore(); });
describe("when the ops are loaded", function() {
before(function(done) {
return DocUpdaterClient.getDocAndRecentOps(this.project_id, this.doc_id, 190, (error, res, returnedDoc) => { this.returnedDoc = returnedDoc; return done(); });
});
this.updates = __range__(0, 199, true).map((v) => ({
doc_id: this.doc_id,
op: [{ i: v.toString(), p: 0 }],
v
}))
return it("should return the recent ops", function() {
this.returnedDoc.ops.length.should.equal(10);
return Array.from(this.updates.slice(190, -1)).map((update, i) =>
this.returnedDoc.ops[i].op.should.deep.equal(update.op));
});
});
return describe("when the ops are not all loaded", function() {
before(function(done) {
// We only track 100 ops
return DocUpdaterClient.getDocAndRecentOps(this.project_id, this.doc_id, 10, (error, res, returnedDoc) => { this.res = res; this.returnedDoc = returnedDoc; return done(); });
});
return DocUpdaterClient.sendUpdates(
this.project_id,
this.doc_id,
this.updates,
(error) => {
if (error != null) {
throw error
}
sinon.spy(MockWebApi, 'getDocument')
return done()
}
)
})
return it("should return UnprocessableEntity", function() {
return this.res.statusCode.should.equal(422);
});
});
});
after(function () {
return MockWebApi.getDocument.restore()
})
describe("when the document does not exist", function() {
before(function(done) {
[this.project_id, this.doc_id] = Array.from([DocUpdaterClient.randomId(), DocUpdaterClient.randomId()]);
return DocUpdaterClient.getDoc(this.project_id, this.doc_id, (error, res, doc) => {
this.statusCode = res.statusCode;
return done();
});
});
describe('when the ops are loaded', function () {
before(function (done) {
return DocUpdaterClient.getDocAndRecentOps(
this.project_id,
this.doc_id,
190,
(error, res, returnedDoc) => {
this.returnedDoc = returnedDoc
return done()
}
)
})
return it("should return 404", function() {
return this.statusCode.should.equal(404);
});
});
return it('should return the recent ops', function () {
this.returnedDoc.ops.length.should.equal(10)
return Array.from(this.updates.slice(190, -1)).map((update, i) =>
this.returnedDoc.ops[i].op.should.deep.equal(update.op)
)
})
})
describe("when the web api returns an error", function() {
before(function(done) {
[this.project_id, this.doc_id] = Array.from([DocUpdaterClient.randomId(), DocUpdaterClient.randomId()]);
sinon.stub(MockWebApi, "getDocument", (project_id, doc_id, callback) => {
if (callback == null) { callback = function(error, doc) {}; }
return callback(new Error("oops"));
});
return DocUpdaterClient.getDoc(this.project_id, this.doc_id, (error, res, doc) => {
this.statusCode = res.statusCode;
return done();
});
});
return describe('when the ops are not all loaded', function () {
before(function (done) {
// We only track 100 ops
return DocUpdaterClient.getDocAndRecentOps(
this.project_id,
this.doc_id,
10,
(error, res, returnedDoc) => {
this.res = res
this.returnedDoc = returnedDoc
return done()
}
)
})
after(function() { return MockWebApi.getDocument.restore(); });
return it('should return UnprocessableEntity', function () {
return this.res.statusCode.should.equal(422)
})
})
})
return it("should return 500", function() {
return this.statusCode.should.equal(500);
});
});
describe('when the document does not exist', function () {
before(function (done) {
;[this.project_id, this.doc_id] = Array.from([
DocUpdaterClient.randomId(),
DocUpdaterClient.randomId()
])
return DocUpdaterClient.getDoc(
this.project_id,
this.doc_id,
(error, res, doc) => {
this.statusCode = res.statusCode
return done()
}
)
})
return describe("when the web api http request takes a long time", function() {
before(function(done) {
this.timeout = 10000;
[this.project_id, this.doc_id] = Array.from([DocUpdaterClient.randomId(), DocUpdaterClient.randomId()]);
sinon.stub(MockWebApi, "getDocument", (project_id, doc_id, callback) => {
if (callback == null) { callback = function(error, doc) {}; }
return setTimeout(callback, 30000);
});
return done();
});
return it('should return 404', function () {
return this.statusCode.should.equal(404)
})
})
after(function() { return MockWebApi.getDocument.restore(); });
return it("should return quickly(ish)", function(done) {
const start = Date.now();
return DocUpdaterClient.getDoc(this.project_id, this.doc_id, (error, res, doc) => {
res.statusCode.should.equal(500);
const delta = Date.now() - start;
expect(delta).to.be.below(20000);
return done();
});
});
});
});
describe('when the web api returns an error', function () {
before(function (done) {
;[this.project_id, this.doc_id] = Array.from([
DocUpdaterClient.randomId(),
DocUpdaterClient.randomId()
])
sinon.stub(MockWebApi, 'getDocument', (project_id, doc_id, callback) => {
if (callback == null) {
callback = function (error, doc) {}
}
return callback(new Error('oops'))
})
return DocUpdaterClient.getDoc(
this.project_id,
this.doc_id,
(error, res, doc) => {
this.statusCode = res.statusCode
return done()
}
)
})
after(function () {
return MockWebApi.getDocument.restore()
})
return it('should return 500', function () {
return this.statusCode.should.equal(500)
})
})
return describe('when the web api http request takes a long time', function () {
before(function (done) {
this.timeout = 10000
;[this.project_id, this.doc_id] = Array.from([
DocUpdaterClient.randomId(),
DocUpdaterClient.randomId()
])
sinon.stub(MockWebApi, 'getDocument', (project_id, doc_id, callback) => {
if (callback == null) {
callback = function (error, doc) {}
}
return setTimeout(callback, 30000)
})
return done()
})
after(function () {
return MockWebApi.getDocument.restore()
})
return it('should return quickly(ish)', function (done) {
const start = Date.now()
return DocUpdaterClient.getDoc(
this.project_id,
this.doc_id,
(error, res, doc) => {
res.statusCode.should.equal(500)
const delta = Date.now() - start
expect(delta).to.be.below(20000)
return done()
}
)
})
})
})
function __range__(left, right, inclusive) {
const range = [];
const ascending = left < right;
const end = !inclusive ? right : ascending ? right + 1 : right - 1;
const range = []
const ascending = left < right
const end = !inclusive ? right : ascending ? right + 1 : right - 1
for (let i = left; ascending ? i < end : i > end; ascending ? i++ : i--) {
range.push(i);
range.push(i)
}
return range;
}
return range
}

View file

@ -11,105 +11,163 @@
* 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 sinon = require('sinon')
const chai = require('chai')
chai.should()
const { expect } = chai
const MockWebApi = require("./helpers/MockWebApi");
const DocUpdaterClient = require("./helpers/DocUpdaterClient");
const DocUpdaterApp = require("./helpers/DocUpdaterApp");
const MockWebApi = require('./helpers/MockWebApi')
const DocUpdaterClient = require('./helpers/DocUpdaterClient')
const DocUpdaterApp = require('./helpers/DocUpdaterApp')
describe("Getting documents for project", function() {
before(function(done) {
this.lines = ["one", "two", "three"];
this.version = 42;
return DocUpdaterApp.ensureRunning(done);
});
describe('Getting documents for project', function () {
before(function (done) {
this.lines = ['one', 'two', 'three']
this.version = 42
return DocUpdaterApp.ensureRunning(done)
})
describe("when project state hash does not match", function() {
before(function(done) {
this.projectStateHash = DocUpdaterClient.randomId();
[this.project_id, this.doc_id] = Array.from([DocUpdaterClient.randomId(), DocUpdaterClient.randomId()]);
describe('when project state hash does not match', function () {
before(function (done) {
this.projectStateHash = DocUpdaterClient.randomId()
;[this.project_id, this.doc_id] = Array.from([
DocUpdaterClient.randomId(),
DocUpdaterClient.randomId()
])
MockWebApi.insertDoc(this.project_id, this.doc_id, {lines: this.lines, version: this.version});
return DocUpdaterClient.preloadDoc(this.project_id, this.doc_id, error => {
if (error != null) { throw error; }
return DocUpdaterClient.getProjectDocs(this.project_id, this.projectStateHash, (error, res, returnedDocs) => {
this.res = res;
this.returnedDocs = returnedDocs;
return done();
});
});
});
MockWebApi.insertDoc(this.project_id, this.doc_id, {
lines: this.lines,
version: this.version
})
return DocUpdaterClient.preloadDoc(
this.project_id,
this.doc_id,
(error) => {
if (error != null) {
throw error
}
return DocUpdaterClient.getProjectDocs(
this.project_id,
this.projectStateHash,
(error, res, returnedDocs) => {
this.res = res
this.returnedDocs = returnedDocs
return done()
}
)
}
)
})
return it("should return a 409 Conflict response", function() {
return this.res.statusCode.should.equal(409);
});
});
return it('should return a 409 Conflict response', function () {
return this.res.statusCode.should.equal(409)
})
})
describe('when project state hash matches', function () {
before(function (done) {
this.projectStateHash = DocUpdaterClient.randomId()
;[this.project_id, this.doc_id] = Array.from([
DocUpdaterClient.randomId(),
DocUpdaterClient.randomId()
])
describe("when project state hash matches", function() {
before(function(done) {
this.projectStateHash = DocUpdaterClient.randomId();
[this.project_id, this.doc_id] = Array.from([DocUpdaterClient.randomId(), DocUpdaterClient.randomId()]);
MockWebApi.insertDoc(this.project_id, this.doc_id, {
lines: this.lines,
version: this.version
})
return DocUpdaterClient.preloadDoc(
this.project_id,
this.doc_id,
(error) => {
if (error != null) {
throw error
}
return DocUpdaterClient.getProjectDocs(
this.project_id,
this.projectStateHash,
(error, res0, returnedDocs0) => {
// set the hash
this.res0 = res0
this.returnedDocs0 = returnedDocs0
return DocUpdaterClient.getProjectDocs(
this.project_id,
this.projectStateHash,
(error, res, returnedDocs) => {
// the hash should now match
this.res = res
this.returnedDocs = returnedDocs
return done()
}
)
}
)
}
)
})
MockWebApi.insertDoc(this.project_id, this.doc_id, {lines: this.lines, version: this.version});
return DocUpdaterClient.preloadDoc(this.project_id, this.doc_id, error => {
if (error != null) { throw error; }
return DocUpdaterClient.getProjectDocs(this.project_id, this.projectStateHash, (error, res0, returnedDocs0) => {
// set the hash
this.res0 = res0;
this.returnedDocs0 = returnedDocs0;
return DocUpdaterClient.getProjectDocs(this.project_id, this.projectStateHash, (error, res, returnedDocs) => {
// the hash should now match
this.res = res;
this.returnedDocs = returnedDocs;
return done();
});
});
});
});
it('should return a 200 response', function () {
return this.res.statusCode.should.equal(200)
})
it("should return a 200 response", function() {
return this.res.statusCode.should.equal(200);
});
return it('should return the documents', function () {
return this.returnedDocs.should.deep.equal([
{ _id: this.doc_id, lines: this.lines, v: this.version }
])
})
})
return it("should return the documents", function() {
return this.returnedDocs.should.deep.equal([ {_id: this.doc_id, lines: this.lines, v: this.version} ]);
});
});
return describe('when the doc has been removed', function () {
before(function (done) {
this.projectStateHash = DocUpdaterClient.randomId()
;[this.project_id, this.doc_id] = Array.from([
DocUpdaterClient.randomId(),
DocUpdaterClient.randomId()
])
MockWebApi.insertDoc(this.project_id, this.doc_id, {
lines: this.lines,
version: this.version
})
return DocUpdaterClient.preloadDoc(
this.project_id,
this.doc_id,
(error) => {
if (error != null) {
throw error
}
return DocUpdaterClient.getProjectDocs(
this.project_id,
this.projectStateHash,
(error, res0, returnedDocs0) => {
// set the hash
this.res0 = res0
this.returnedDocs0 = returnedDocs0
return DocUpdaterClient.deleteDoc(
this.project_id,
this.doc_id,
(error, res, body) => {
// delete the doc
return DocUpdaterClient.getProjectDocs(
this.project_id,
this.projectStateHash,
(error, res1, returnedDocs) => {
// the hash would match, but the doc has been deleted
this.res = res1
this.returnedDocs = returnedDocs
return done()
}
)
}
)
}
)
}
)
})
return describe("when the doc has been removed", function() {
before(function(done) {
this.projectStateHash = DocUpdaterClient.randomId();
[this.project_id, this.doc_id] = Array.from([DocUpdaterClient.randomId(), DocUpdaterClient.randomId()]);
MockWebApi.insertDoc(this.project_id, this.doc_id, {lines: this.lines, version: this.version});
return DocUpdaterClient.preloadDoc(this.project_id, this.doc_id, error => {
if (error != null) { throw error; }
return DocUpdaterClient.getProjectDocs(this.project_id, this.projectStateHash, (error, res0, returnedDocs0) => {
// set the hash
this.res0 = res0;
this.returnedDocs0 = returnedDocs0;
return DocUpdaterClient.deleteDoc(this.project_id, this.doc_id, (error, res, body) => {
// delete the doc
return DocUpdaterClient.getProjectDocs(this.project_id, this.projectStateHash, (error, res1, returnedDocs) => {
// the hash would match, but the doc has been deleted
this.res = res1;
this.returnedDocs = returnedDocs;
return done();
});
});
});
});
});
return it("should return a 409 Conflict response", function() {
return this.res.statusCode.should.equal(409);
});
});
});
return it('should return a 409 Conflict response', function () {
return this.res.statusCode.should.equal(409)
})
})
})

File diff suppressed because it is too large Load diff

View file

@ -12,316 +12,462 @@
* 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
} = require("chai");
const Settings = require('settings-sharelatex');
const rclient_du = require("redis-sharelatex").createClient(Settings.redis.documentupdater);
const Keys = Settings.redis.documentupdater.key_schema;
const sinon = require('sinon')
const chai = require('chai')
chai.should()
const { expect } = require('chai')
const Settings = require('settings-sharelatex')
const rclient_du = require('redis-sharelatex').createClient(
Settings.redis.documentupdater
)
const Keys = Settings.redis.documentupdater.key_schema
const MockTrackChangesApi = require("./helpers/MockTrackChangesApi");
const MockProjectHistoryApi = require("./helpers/MockProjectHistoryApi");
const MockWebApi = require("./helpers/MockWebApi");
const DocUpdaterClient = require("./helpers/DocUpdaterClient");
const DocUpdaterApp = require("./helpers/DocUpdaterApp");
const MockTrackChangesApi = require('./helpers/MockTrackChangesApi')
const MockProjectHistoryApi = require('./helpers/MockProjectHistoryApi')
const MockWebApi = require('./helpers/MockWebApi')
const DocUpdaterClient = require('./helpers/DocUpdaterClient')
const DocUpdaterApp = require('./helpers/DocUpdaterApp')
describe("Setting a document", function() {
before(function(done) {
this.lines = ["one", "two", "three"];
this.version = 42;
this.update = {
doc: this.doc_id,
op: [{
i: "one and a half\n",
p: 4
}],
v: this.version
};
this.result = ["one", "one and a half", "two", "three"];
this.newLines = ["these", "are", "the", "new", "lines"];
this.source = "dropbox";
this.user_id = "user-id-123";
describe('Setting a document', function () {
before(function (done) {
this.lines = ['one', 'two', 'three']
this.version = 42
this.update = {
doc: this.doc_id,
op: [
{
i: 'one and a half\n',
p: 4
}
],
v: this.version
}
this.result = ['one', 'one and a half', 'two', 'three']
this.newLines = ['these', 'are', 'the', 'new', 'lines']
this.source = 'dropbox'
this.user_id = 'user-id-123'
sinon.spy(MockTrackChangesApi, "flushDoc");
sinon.spy(MockProjectHistoryApi, "flushProject");
sinon.spy(MockWebApi, "setDocument");
return DocUpdaterApp.ensureRunning(done);
});
sinon.spy(MockTrackChangesApi, 'flushDoc')
sinon.spy(MockProjectHistoryApi, 'flushProject')
sinon.spy(MockWebApi, 'setDocument')
return DocUpdaterApp.ensureRunning(done)
})
after(function() {
MockTrackChangesApi.flushDoc.restore();
MockProjectHistoryApi.flushProject.restore();
return MockWebApi.setDocument.restore();
});
after(function () {
MockTrackChangesApi.flushDoc.restore()
MockProjectHistoryApi.flushProject.restore()
return MockWebApi.setDocument.restore()
})
describe("when the updated doc exists in the doc updater", function() {
before(function(done) {
[this.project_id, this.doc_id] = Array.from([DocUpdaterClient.randomId(), DocUpdaterClient.randomId()]);
MockWebApi.insertDoc(this.project_id, this.doc_id, {lines: this.lines, version: this.version});
DocUpdaterClient.preloadDoc(this.project_id, this.doc_id, error => {
if (error != null) { throw error; }
return DocUpdaterClient.sendUpdate(this.project_id, this.doc_id, this.update, error => {
if (error != null) { throw error; }
return setTimeout(() => {
return DocUpdaterClient.setDocLines(this.project_id, this.doc_id, this.newLines, this.source, this.user_id, false, (error, res, body) => {
this.statusCode = res.statusCode;
return done();
});
}
, 200);
});
});
return null;
});
describe('when the updated doc exists in the doc updater', function () {
before(function (done) {
;[this.project_id, this.doc_id] = Array.from([
DocUpdaterClient.randomId(),
DocUpdaterClient.randomId()
])
MockWebApi.insertDoc(this.project_id, this.doc_id, {
lines: this.lines,
version: this.version
})
DocUpdaterClient.preloadDoc(this.project_id, this.doc_id, (error) => {
if (error != null) {
throw error
}
return DocUpdaterClient.sendUpdate(
this.project_id,
this.doc_id,
this.update,
(error) => {
if (error != null) {
throw error
}
return setTimeout(() => {
return DocUpdaterClient.setDocLines(
this.project_id,
this.doc_id,
this.newLines,
this.source,
this.user_id,
false,
(error, res, body) => {
this.statusCode = res.statusCode
return done()
}
)
}, 200)
}
)
})
return null
})
after(function() {
MockTrackChangesApi.flushDoc.reset();
MockProjectHistoryApi.flushProject.reset();
return MockWebApi.setDocument.reset();
});
after(function () {
MockTrackChangesApi.flushDoc.reset()
MockProjectHistoryApi.flushProject.reset()
return MockWebApi.setDocument.reset()
})
it("should return a 204 status code", function() {
return this.statusCode.should.equal(204);
});
it('should return a 204 status code', function () {
return this.statusCode.should.equal(204)
})
it("should send the updated doc lines and version to the web api", function() {
return MockWebApi.setDocument
.calledWith(this.project_id, this.doc_id, this.newLines)
.should.equal(true);
});
it('should send the updated doc lines and version to the web api', function () {
return MockWebApi.setDocument
.calledWith(this.project_id, this.doc_id, this.newLines)
.should.equal(true)
})
it("should update the lines in the doc updater", function(done) {
DocUpdaterClient.getDoc(this.project_id, this.doc_id, (error, res, doc) => {
doc.lines.should.deep.equal(this.newLines);
return done();
});
return null;
});
it('should update the lines in the doc updater', function (done) {
DocUpdaterClient.getDoc(
this.project_id,
this.doc_id,
(error, res, doc) => {
doc.lines.should.deep.equal(this.newLines)
return done()
}
)
return null
})
it("should bump the version in the doc updater", function(done) {
DocUpdaterClient.getDoc(this.project_id, this.doc_id, (error, res, doc) => {
doc.version.should.equal(this.version + 2);
return done();
});
return null;
});
it('should bump the version in the doc updater', function (done) {
DocUpdaterClient.getDoc(
this.project_id,
this.doc_id,
(error, res, doc) => {
doc.version.should.equal(this.version + 2)
return done()
}
)
return null
})
return it("should leave the document in redis", function(done) {
rclient_du.get(Keys.docLines({doc_id: this.doc_id}), (error, lines) => {
if (error != null) { throw error; }
expect(JSON.parse(lines)).to.deep.equal(this.newLines);
return done();
});
return null;
});
});
return it('should leave the document in redis', function (done) {
rclient_du.get(Keys.docLines({ doc_id: this.doc_id }), (error, lines) => {
if (error != null) {
throw error
}
expect(JSON.parse(lines)).to.deep.equal(this.newLines)
return done()
})
return null
})
})
describe("when the updated doc does not exist in the doc updater", function() {
before(function(done) {
[this.project_id, this.doc_id] = Array.from([DocUpdaterClient.randomId(), DocUpdaterClient.randomId()]);
MockWebApi.insertDoc(this.project_id, this.doc_id, {lines: this.lines, version: this.version});
DocUpdaterClient.setDocLines(this.project_id, this.doc_id, this.newLines, this.source, this.user_id, false, (error, res, body) => {
this.statusCode = res.statusCode;
return setTimeout(done, 200);
});
return null;
});
describe('when the updated doc does not exist in the doc updater', function () {
before(function (done) {
;[this.project_id, this.doc_id] = Array.from([
DocUpdaterClient.randomId(),
DocUpdaterClient.randomId()
])
MockWebApi.insertDoc(this.project_id, this.doc_id, {
lines: this.lines,
version: this.version
})
DocUpdaterClient.setDocLines(
this.project_id,
this.doc_id,
this.newLines,
this.source,
this.user_id,
false,
(error, res, body) => {
this.statusCode = res.statusCode
return setTimeout(done, 200)
}
)
return null
})
after(function() {
MockTrackChangesApi.flushDoc.reset();
MockProjectHistoryApi.flushProject.reset();
return MockWebApi.setDocument.reset();
});
after(function () {
MockTrackChangesApi.flushDoc.reset()
MockProjectHistoryApi.flushProject.reset()
return MockWebApi.setDocument.reset()
})
it("should return a 204 status code", function() {
return this.statusCode.should.equal(204);
});
it('should return a 204 status code', function () {
return this.statusCode.should.equal(204)
})
it("should send the updated doc lines to the web api", function() {
return MockWebApi.setDocument
.calledWith(this.project_id, this.doc_id, this.newLines)
.should.equal(true);
});
it('should send the updated doc lines to the web api', function () {
return MockWebApi.setDocument
.calledWith(this.project_id, this.doc_id, this.newLines)
.should.equal(true)
})
it("should flush track changes", function() {
return MockTrackChangesApi.flushDoc.calledWith(this.doc_id).should.equal(true);
});
it('should flush track changes', function () {
return MockTrackChangesApi.flushDoc
.calledWith(this.doc_id)
.should.equal(true)
})
it("should flush project history", function() {
return MockProjectHistoryApi.flushProject.calledWith(this.project_id).should.equal(true);
});
it('should flush project history', function () {
return MockProjectHistoryApi.flushProject
.calledWith(this.project_id)
.should.equal(true)
})
return it("should remove the document from redis", function(done) {
rclient_du.get(Keys.docLines({doc_id: this.doc_id}), (error, lines) => {
if (error != null) { throw error; }
expect(lines).to.not.exist;
return done();
});
return null;
});
});
return it('should remove the document from redis', function (done) {
rclient_du.get(Keys.docLines({ doc_id: this.doc_id }), (error, lines) => {
if (error != null) {
throw error
}
expect(lines).to.not.exist
return done()
})
return null
})
})
describe("when the updated doc is too large for the body parser", function() {
before(function(done) {
[this.project_id, this.doc_id] = Array.from([DocUpdaterClient.randomId(), DocUpdaterClient.randomId()]);
MockWebApi.insertDoc(this.project_id, this.doc_id, {lines: this.lines, version: this.version});
this.newLines = [];
while (JSON.stringify(this.newLines).length < (Settings.max_doc_length + (64 * 1024))) {
this.newLines.push("(a long line of text)".repeat(10000));
}
DocUpdaterClient.setDocLines(this.project_id, this.doc_id, this.newLines, this.source, this.user_id, false, (error, res, body) => {
this.statusCode = res.statusCode;
return setTimeout(done, 200);
});
return null;
});
describe('when the updated doc is too large for the body parser', function () {
before(function (done) {
;[this.project_id, this.doc_id] = Array.from([
DocUpdaterClient.randomId(),
DocUpdaterClient.randomId()
])
MockWebApi.insertDoc(this.project_id, this.doc_id, {
lines: this.lines,
version: this.version
})
this.newLines = []
while (
JSON.stringify(this.newLines).length <
Settings.max_doc_length + 64 * 1024
) {
this.newLines.push('(a long line of text)'.repeat(10000))
}
DocUpdaterClient.setDocLines(
this.project_id,
this.doc_id,
this.newLines,
this.source,
this.user_id,
false,
(error, res, body) => {
this.statusCode = res.statusCode
return setTimeout(done, 200)
}
)
return null
})
after(function() {
MockTrackChangesApi.flushDoc.reset();
MockProjectHistoryApi.flushProject.reset();
return MockWebApi.setDocument.reset();
});
after(function () {
MockTrackChangesApi.flushDoc.reset()
MockProjectHistoryApi.flushProject.reset()
return MockWebApi.setDocument.reset()
})
it("should return a 413 status code", function() {
return this.statusCode.should.equal(413);
});
it('should return a 413 status code', function () {
return this.statusCode.should.equal(413)
})
it("should not send the updated doc lines to the web api", function() { return MockWebApi.setDocument.called.should.equal(false); });
it('should not send the updated doc lines to the web api', function () {
return MockWebApi.setDocument.called.should.equal(false)
})
it("should not flush track changes", function() { return MockTrackChangesApi.flushDoc.called.should.equal(false); });
it('should not flush track changes', function () {
return MockTrackChangesApi.flushDoc.called.should.equal(false)
})
return it("should not flush project history", function() { return MockProjectHistoryApi.flushProject.called.should.equal(false); });
});
return it('should not flush project history', function () {
return MockProjectHistoryApi.flushProject.called.should.equal(false)
})
})
describe("when the updated doc is large but under the bodyParser and HTTPController size limit", function() {
before(function(done) {
[this.project_id, this.doc_id] = Array.from([DocUpdaterClient.randomId(), DocUpdaterClient.randomId()]);
MockWebApi.insertDoc(this.project_id, this.doc_id, {lines: this.lines, version: this.version});
describe('when the updated doc is large but under the bodyParser and HTTPController size limit', function () {
before(function (done) {
;[this.project_id, this.doc_id] = Array.from([
DocUpdaterClient.randomId(),
DocUpdaterClient.randomId()
])
MockWebApi.insertDoc(this.project_id, this.doc_id, {
lines: this.lines,
version: this.version
})
this.newLines = [];
while (JSON.stringify(this.newLines).length < (2 * 1024 * 1024)) { // limit in HTTPController
this.newLines.push("(a long line of text)".repeat(10000));
}
this.newLines.pop(); // remove the line which took it over the limit
DocUpdaterClient.setDocLines(this.project_id, this.doc_id, this.newLines, this.source, this.user_id, false, (error, res, body) => {
this.statusCode = res.statusCode;
return setTimeout(done, 200);
});
return null;
});
this.newLines = []
while (JSON.stringify(this.newLines).length < 2 * 1024 * 1024) {
// limit in HTTPController
this.newLines.push('(a long line of text)'.repeat(10000))
}
this.newLines.pop() // remove the line which took it over the limit
DocUpdaterClient.setDocLines(
this.project_id,
this.doc_id,
this.newLines,
this.source,
this.user_id,
false,
(error, res, body) => {
this.statusCode = res.statusCode
return setTimeout(done, 200)
}
)
return null
})
after(function() {
MockTrackChangesApi.flushDoc.reset();
MockProjectHistoryApi.flushProject.reset();
return MockWebApi.setDocument.reset();
});
after(function () {
MockTrackChangesApi.flushDoc.reset()
MockProjectHistoryApi.flushProject.reset()
return MockWebApi.setDocument.reset()
})
it("should return a 204 status code", function() {
return this.statusCode.should.equal(204);
});
it('should return a 204 status code', function () {
return this.statusCode.should.equal(204)
})
return it("should send the updated doc lines to the web api", function() {
return MockWebApi.setDocument
.calledWith(this.project_id, this.doc_id, this.newLines)
.should.equal(true);
});
});
return it('should send the updated doc lines to the web api', function () {
return MockWebApi.setDocument
.calledWith(this.project_id, this.doc_id, this.newLines)
.should.equal(true)
})
})
return describe("with track changes", function() {
before(function() {
this.lines = ["one", "one and a half", "two", "three"];
this.id_seed = "587357bd35e64f6157";
return this.update = {
doc: this.doc_id,
op: [{
d: "one and a half\n",
p: 4
}],
meta: {
tc: this.id_seed,
user_id: this.user_id
},
v: this.version
};
});
return describe('with track changes', function () {
before(function () {
this.lines = ['one', 'one and a half', 'two', 'three']
this.id_seed = '587357bd35e64f6157'
return (this.update = {
doc: this.doc_id,
op: [
{
d: 'one and a half\n',
p: 4
}
],
meta: {
tc: this.id_seed,
user_id: this.user_id
},
v: this.version
})
})
describe("with the undo flag", function() {
before(function(done) {
[this.project_id, this.doc_id] = Array.from([DocUpdaterClient.randomId(), DocUpdaterClient.randomId()]);
MockWebApi.insertDoc(this.project_id, this.doc_id, {lines: this.lines, version: this.version});
DocUpdaterClient.preloadDoc(this.project_id, this.doc_id, error => {
if (error != null) { throw error; }
return DocUpdaterClient.sendUpdate(this.project_id, this.doc_id, this.update, error => {
if (error != null) { throw error; }
// Go back to old lines, with undo flag
return DocUpdaterClient.setDocLines(this.project_id, this.doc_id, this.lines, this.source, this.user_id, true, (error, res, body) => {
this.statusCode = res.statusCode;
return setTimeout(done, 200);
});
});
});
return null;
});
describe('with the undo flag', function () {
before(function (done) {
;[this.project_id, this.doc_id] = Array.from([
DocUpdaterClient.randomId(),
DocUpdaterClient.randomId()
])
MockWebApi.insertDoc(this.project_id, this.doc_id, {
lines: this.lines,
version: this.version
})
DocUpdaterClient.preloadDoc(this.project_id, this.doc_id, (error) => {
if (error != null) {
throw error
}
return DocUpdaterClient.sendUpdate(
this.project_id,
this.doc_id,
this.update,
(error) => {
if (error != null) {
throw error
}
// Go back to old lines, with undo flag
return DocUpdaterClient.setDocLines(
this.project_id,
this.doc_id,
this.lines,
this.source,
this.user_id,
true,
(error, res, body) => {
this.statusCode = res.statusCode
return setTimeout(done, 200)
}
)
}
)
})
return null
})
after(function() {
MockTrackChangesApi.flushDoc.reset();
MockProjectHistoryApi.flushProject.reset();
return MockWebApi.setDocument.reset();
});
after(function () {
MockTrackChangesApi.flushDoc.reset()
MockProjectHistoryApi.flushProject.reset()
return MockWebApi.setDocument.reset()
})
return it("should undo the tracked changes", function(done) {
DocUpdaterClient.getDoc(this.project_id, this.doc_id, (error, res, data) => {
if (error != null) { throw error; }
const {
ranges
} = data;
expect(ranges.changes).to.be.undefined;
return done();
});
return null;
});
});
return it('should undo the tracked changes', function (done) {
DocUpdaterClient.getDoc(
this.project_id,
this.doc_id,
(error, res, data) => {
if (error != null) {
throw error
}
const { ranges } = data
expect(ranges.changes).to.be.undefined
return done()
}
)
return null
})
})
return describe("without the undo flag", function() {
before(function(done) {
[this.project_id, this.doc_id] = Array.from([DocUpdaterClient.randomId(), DocUpdaterClient.randomId()]);
MockWebApi.insertDoc(this.project_id, this.doc_id, {lines: this.lines, version: this.version});
DocUpdaterClient.preloadDoc(this.project_id, this.doc_id, error => {
if (error != null) { throw error; }
return DocUpdaterClient.sendUpdate(this.project_id, this.doc_id, this.update, error => {
if (error != null) { throw error; }
// Go back to old lines, without undo flag
return DocUpdaterClient.setDocLines(this.project_id, this.doc_id, this.lines, this.source, this.user_id, false, (error, res, body) => {
this.statusCode = res.statusCode;
return setTimeout(done, 200);
});
});
});
return null;
});
after(function() {
MockTrackChangesApi.flushDoc.reset();
MockProjectHistoryApi.flushProject.reset();
return MockWebApi.setDocument.reset();
});
return it("should not undo the tracked changes", function(done) {
DocUpdaterClient.getDoc(this.project_id, this.doc_id, (error, res, data) => {
if (error != null) { throw error; }
const {
ranges
} = data;
expect(ranges.changes.length).to.equal(1);
return done();
});
return null;
});
});
});
});
return describe('without the undo flag', function () {
before(function (done) {
;[this.project_id, this.doc_id] = Array.from([
DocUpdaterClient.randomId(),
DocUpdaterClient.randomId()
])
MockWebApi.insertDoc(this.project_id, this.doc_id, {
lines: this.lines,
version: this.version
})
DocUpdaterClient.preloadDoc(this.project_id, this.doc_id, (error) => {
if (error != null) {
throw error
}
return DocUpdaterClient.sendUpdate(
this.project_id,
this.doc_id,
this.update,
(error) => {
if (error != null) {
throw error
}
// Go back to old lines, without undo flag
return DocUpdaterClient.setDocLines(
this.project_id,
this.doc_id,
this.lines,
this.source,
this.user_id,
false,
(error, res, body) => {
this.statusCode = res.statusCode
return setTimeout(done, 200)
}
)
}
)
})
return null
})
after(function () {
MockTrackChangesApi.flushDoc.reset()
MockProjectHistoryApi.flushProject.reset()
return MockWebApi.setDocument.reset()
})
return it('should not undo the tracked changes', function (done) {
DocUpdaterClient.getDoc(
this.project_id,
this.doc_id,
(error, res, data) => {
if (error != null) {
throw error
}
const { ranges } = data
expect(ranges.changes.length).to.equal(1)
return done()
}
)
return null
})
})
})
})

View file

@ -11,33 +11,37 @@
* 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").logger.level("fatal");
const app = require('../../../../app')
require('logger-sharelatex').logger.level('fatal')
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(3003, "localhost", error => {
if (error != null) { throw error; }
this.running = true;
return (() => {
const result = [];
for (callback of Array.from(this.callbacks)) {
result.push(callback());
}
return result;
})();
});
}
}
};
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(3003, 'localhost', (error) => {
if (error != null) {
throw error
}
this.running = true
return (() => {
const result = []
for (callback of Array.from(this.callbacks)) {
result.push(callback())
}
return result
})()
})
}
}
}

View file

@ -11,167 +11,268 @@
* DS207: Consider shorter variations of null checks
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
let DocUpdaterClient;
const Settings = require('settings-sharelatex');
const rclient = require("redis-sharelatex").createClient(Settings.redis.documentupdater);
const keys = Settings.redis.documentupdater.key_schema;
const request = require("request").defaults({jar: false});
const async = require("async");
let DocUpdaterClient
const Settings = require('settings-sharelatex')
const rclient = require('redis-sharelatex').createClient(
Settings.redis.documentupdater
)
const keys = Settings.redis.documentupdater.key_schema
const request = require('request').defaults({ jar: false })
const async = require('async')
const rclient_sub = require("redis-sharelatex").createClient(Settings.redis.pubsub);
rclient_sub.subscribe("applied-ops");
rclient_sub.setMaxListeners(0);
module.exports = (DocUpdaterClient = {
randomId() {
const chars = __range__(1, 24, true).map((i) =>
Math.random().toString(16)[2]);
return chars.join("");
},
subscribeToAppliedOps(callback) {
if (callback == null) { callback = function(message) {}; }
return rclient_sub.on("message", callback);
},
const rclient_sub = require('redis-sharelatex').createClient(
Settings.redis.pubsub
)
rclient_sub.subscribe('applied-ops')
rclient_sub.setMaxListeners(0)
sendUpdate(project_id, doc_id, update, callback) {
if (callback == null) { callback = function(error) {}; }
return rclient.rpush(keys.pendingUpdates({doc_id}), JSON.stringify(update), (error) => {
if (error != null) { return callback(error); }
const doc_key = `${project_id}:${doc_id}`;
return rclient.sadd("DocsWithPendingUpdates", doc_key, (error) => {
if (error != null) { return callback(error); }
return rclient.rpush("pending-updates-list", doc_key, callback);
});
});
},
module.exports = DocUpdaterClient = {
randomId() {
const chars = __range__(1, 24, true).map(
(i) => Math.random().toString(16)[2]
)
return chars.join('')
},
sendUpdates(project_id, doc_id, updates, callback) {
if (callback == null) { callback = function(error) {}; }
return DocUpdaterClient.preloadDoc(project_id, doc_id, (error) => {
if (error != null) { return callback(error); }
const jobs = [];
for (const update of Array.from(updates)) {
((update => jobs.push(callback => DocUpdaterClient.sendUpdate(project_id, doc_id, update, callback))))(update);
}
return async.series(jobs, err => DocUpdaterClient.waitForPendingUpdates(project_id, doc_id, callback));
});
},
subscribeToAppliedOps(callback) {
if (callback == null) {
callback = function (message) {}
}
return rclient_sub.on('message', callback)
},
waitForPendingUpdates(project_id, doc_id, callback) {
return async.retry({times: 30, interval: 100}, cb => rclient.llen(keys.pendingUpdates({doc_id}), (err, length) => {
if (length > 0) {
return cb(new Error("updates still pending"));
} else {
return cb();
}
sendUpdate(project_id, doc_id, update, callback) {
if (callback == null) {
callback = function (error) {}
}
return rclient.rpush(
keys.pendingUpdates({ doc_id }),
JSON.stringify(update),
(error) => {
if (error != null) {
return callback(error)
}
const doc_key = `${project_id}:${doc_id}`
return rclient.sadd('DocsWithPendingUpdates', doc_key, (error) => {
if (error != null) {
return callback(error)
}
return rclient.rpush('pending-updates-list', doc_key, callback)
})
, callback);
},
}
)
},
getDoc(project_id, doc_id, callback) {
if (callback == null) { callback = function(error, res, body) {}; }
return request.get(`http://localhost:3003/project/${project_id}/doc/${doc_id}`, (error, res, body) => {
if ((body != null) && (res.statusCode >= 200) && (res.statusCode < 300)) {
body = JSON.parse(body);
}
return callback(error, res, body);
});
},
sendUpdates(project_id, doc_id, updates, callback) {
if (callback == null) {
callback = function (error) {}
}
return DocUpdaterClient.preloadDoc(project_id, doc_id, (error) => {
if (error != null) {
return callback(error)
}
const jobs = []
for (const update of Array.from(updates)) {
;((update) =>
jobs.push((callback) =>
DocUpdaterClient.sendUpdate(project_id, doc_id, update, callback)
))(update)
}
return async.series(jobs, (err) =>
DocUpdaterClient.waitForPendingUpdates(project_id, doc_id, callback)
)
})
},
getDocAndRecentOps(project_id, doc_id, fromVersion, callback) {
if (callback == null) { callback = function(error, res, body) {}; }
return request.get(`http://localhost:3003/project/${project_id}/doc/${doc_id}?fromVersion=${fromVersion}`, (error, res, body) => {
if ((body != null) && (res.statusCode >= 200) && (res.statusCode < 300)) {
body = JSON.parse(body);
}
return callback(error, res, body);
});
},
waitForPendingUpdates(project_id, doc_id, callback) {
return async.retry(
{ times: 30, interval: 100 },
(cb) =>
rclient.llen(keys.pendingUpdates({ doc_id }), (err, length) => {
if (length > 0) {
return cb(new Error('updates still pending'))
} else {
return cb()
}
}),
callback
)
},
preloadDoc(project_id, doc_id, callback) {
if (callback == null) { callback = function(error) {}; }
return DocUpdaterClient.getDoc(project_id, doc_id, callback);
},
getDoc(project_id, doc_id, callback) {
if (callback == null) {
callback = function (error, res, body) {}
}
return request.get(
`http://localhost:3003/project/${project_id}/doc/${doc_id}`,
(error, res, body) => {
if (body != null && res.statusCode >= 200 && res.statusCode < 300) {
body = JSON.parse(body)
}
return callback(error, res, body)
}
)
},
flushDoc(project_id, doc_id, callback) {
if (callback == null) { callback = function(error) {}; }
return request.post(`http://localhost:3003/project/${project_id}/doc/${doc_id}/flush`, (error, res, body) => callback(error, res, body));
},
getDocAndRecentOps(project_id, doc_id, fromVersion, callback) {
if (callback == null) {
callback = function (error, res, body) {}
}
return request.get(
`http://localhost:3003/project/${project_id}/doc/${doc_id}?fromVersion=${fromVersion}`,
(error, res, body) => {
if (body != null && res.statusCode >= 200 && res.statusCode < 300) {
body = JSON.parse(body)
}
return callback(error, res, body)
}
)
},
setDocLines(project_id, doc_id, lines, source, user_id, undoing, callback) {
if (callback == null) { callback = function(error) {}; }
return request.post({
url: `http://localhost:3003/project/${project_id}/doc/${doc_id}`,
json: {
lines,
source,
user_id,
undoing
}
}, (error, res, body) => callback(error, res, body));
},
preloadDoc(project_id, doc_id, callback) {
if (callback == null) {
callback = function (error) {}
}
return DocUpdaterClient.getDoc(project_id, doc_id, callback)
},
deleteDoc(project_id, doc_id, callback) {
if (callback == null) { callback = function(error) {}; }
return request.del(`http://localhost:3003/project/${project_id}/doc/${doc_id}`, (error, res, body) => callback(error, res, body));
},
flushDoc(project_id, doc_id, callback) {
if (callback == null) {
callback = function (error) {}
}
return request.post(
`http://localhost:3003/project/${project_id}/doc/${doc_id}/flush`,
(error, res, body) => callback(error, res, body)
)
},
flushProject(project_id, callback) {
if (callback == null) { callback = function() {}; }
return request.post(`http://localhost:3003/project/${project_id}/flush`, callback);
},
setDocLines(project_id, doc_id, lines, source, user_id, undoing, callback) {
if (callback == null) {
callback = function (error) {}
}
return request.post(
{
url: `http://localhost:3003/project/${project_id}/doc/${doc_id}`,
json: {
lines,
source,
user_id,
undoing
}
},
(error, res, body) => callback(error, res, body)
)
},
deleteProject(project_id, callback) {
if (callback == null) { callback = function() {}; }
return request.del(`http://localhost:3003/project/${project_id}`, callback);
},
deleteDoc(project_id, doc_id, callback) {
if (callback == null) {
callback = function (error) {}
}
return request.del(
`http://localhost:3003/project/${project_id}/doc/${doc_id}`,
(error, res, body) => callback(error, res, body)
)
},
deleteProjectOnShutdown(project_id, callback) {
if (callback == null) { callback = function() {}; }
return request.del(`http://localhost:3003/project/${project_id}?background=true&shutdown=true`, callback);
},
flushProject(project_id, callback) {
if (callback == null) {
callback = function () {}
}
return request.post(
`http://localhost:3003/project/${project_id}/flush`,
callback
)
},
flushOldProjects(callback) {
if (callback == null) { callback = function() {}; }
return request.get("http://localhost:3003/flush_queued_projects?min_delete_age=1", callback);
},
deleteProject(project_id, callback) {
if (callback == null) {
callback = function () {}
}
return request.del(`http://localhost:3003/project/${project_id}`, callback)
},
acceptChange(project_id, doc_id, change_id, callback) {
if (callback == null) { callback = function() {}; }
return request.post(`http://localhost:3003/project/${project_id}/doc/${doc_id}/change/${change_id}/accept`, callback);
},
deleteProjectOnShutdown(project_id, callback) {
if (callback == null) {
callback = function () {}
}
return request.del(
`http://localhost:3003/project/${project_id}?background=true&shutdown=true`,
callback
)
},
removeComment(project_id, doc_id, comment, callback) {
if (callback == null) { callback = function() {}; }
return request.del(`http://localhost:3003/project/${project_id}/doc/${doc_id}/comment/${comment}`, callback);
},
flushOldProjects(callback) {
if (callback == null) {
callback = function () {}
}
return request.get(
'http://localhost:3003/flush_queued_projects?min_delete_age=1',
callback
)
},
getProjectDocs(project_id, projectStateHash, callback) {
if (callback == null) { callback = function() {}; }
return request.get(`http://localhost:3003/project/${project_id}/doc?state=${projectStateHash}`, (error, res, body) => {
if ((body != null) && (res.statusCode >= 200) && (res.statusCode < 300)) {
body = JSON.parse(body);
}
return callback(error, res, body);
});
},
acceptChange(project_id, doc_id, change_id, callback) {
if (callback == null) {
callback = function () {}
}
return request.post(
`http://localhost:3003/project/${project_id}/doc/${doc_id}/change/${change_id}/accept`,
callback
)
},
sendProjectUpdate(project_id, userId, docUpdates, fileUpdates, version, callback) {
if (callback == null) { callback = function(error) {}; }
return request.post({
url: `http://localhost:3003/project/${project_id}`,
json: { userId, docUpdates, fileUpdates, version }
}, (error, res, body) => callback(error, res, body));
}
});
removeComment(project_id, doc_id, comment, callback) {
if (callback == null) {
callback = function () {}
}
return request.del(
`http://localhost:3003/project/${project_id}/doc/${doc_id}/comment/${comment}`,
callback
)
},
getProjectDocs(project_id, projectStateHash, callback) {
if (callback == null) {
callback = function () {}
}
return request.get(
`http://localhost:3003/project/${project_id}/doc?state=${projectStateHash}`,
(error, res, body) => {
if (body != null && res.statusCode >= 200 && res.statusCode < 300) {
body = JSON.parse(body)
}
return callback(error, res, body)
}
)
},
sendProjectUpdate(
project_id,
userId,
docUpdates,
fileUpdates,
version,
callback
) {
if (callback == null) {
callback = function (error) {}
}
return request.post(
{
url: `http://localhost:3003/project/${project_id}`,
json: { userId, docUpdates, fileUpdates, version }
},
(error, res, body) => callback(error, res, body)
)
}
}
function __range__(left, right, inclusive) {
const range = [];
const ascending = left < right;
const end = !inclusive ? right : ascending ? right + 1 : right - 1;
const range = []
const ascending = left < right
const end = !inclusive ? right : ascending ? right + 1 : right - 1
for (let i = left; ascending ? i < end : i > end; ascending ? i++ : i--) {
range.push(i);
range.push(i)
}
return range;
}
return range
}

View file

@ -10,31 +10,35 @@
* DS207: Consider shorter variations of null checks
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
let MockProjectHistoryApi;
const express = require("express");
const app = express();
let MockProjectHistoryApi
const express = require('express')
const app = express()
module.exports = (MockProjectHistoryApi = {
flushProject(doc_id, callback) {
if (callback == null) { callback = function(error) {}; }
return callback();
},
module.exports = MockProjectHistoryApi = {
flushProject(doc_id, callback) {
if (callback == null) {
callback = function (error) {}
}
return callback()
},
run() {
app.post("/project/:project_id/flush", (req, res, next) => {
return this.flushProject(req.params.project_id, (error) => {
if (error != null) {
return res.sendStatus(500);
} else {
return res.sendStatus(204);
}
});
});
run() {
app.post('/project/:project_id/flush', (req, res, next) => {
return this.flushProject(req.params.project_id, (error) => {
if (error != null) {
return res.sendStatus(500)
} else {
return res.sendStatus(204)
}
})
})
return app.listen(3054, (error) => {
if (error != null) { throw error; }
});
}
});
return app.listen(3054, (error) => {
if (error != null) {
throw error
}
})
}
}
MockProjectHistoryApi.run();
MockProjectHistoryApi.run()

View file

@ -10,35 +10,40 @@
* DS207: Consider shorter variations of null checks
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
let MockTrackChangesApi;
const express = require("express");
const app = express();
let MockTrackChangesApi
const express = require('express')
const app = express()
module.exports = (MockTrackChangesApi = {
flushDoc(doc_id, callback) {
if (callback == null) { callback = function(error) {}; }
return callback();
},
module.exports = MockTrackChangesApi = {
flushDoc(doc_id, callback) {
if (callback == null) {
callback = function (error) {}
}
return callback()
},
run() {
app.post("/project/:project_id/doc/:doc_id/flush", (req, res, next) => {
return this.flushDoc(req.params.doc_id, (error) => {
if (error != null) {
return res.sendStatus(500);
} else {
return res.sendStatus(204);
}
});
});
run() {
app.post('/project/:project_id/doc/:doc_id/flush', (req, res, next) => {
return this.flushDoc(req.params.doc_id, (error) => {
if (error != null) {
return res.sendStatus(500)
} else {
return res.sendStatus(204)
}
})
})
return app.listen(3015, (error) => {
if (error != null) { throw error; }
}).on("error", (error) => {
console.error("error starting MockTrackChangesApi:", error.message);
return process.exit(1);
});
}
});
MockTrackChangesApi.run();
return app
.listen(3015, (error) => {
if (error != null) {
throw error
}
})
.on('error', (error) => {
console.error('error starting MockTrackChangesApi:', error.message)
return process.exit(1)
})
}
}
MockTrackChangesApi.run()

View file

@ -11,72 +11,113 @@
* 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 bodyParser = require("body-parser");
const app = express();
const MAX_REQUEST_SIZE = 2*((2*1024*1024) + (64*1024));
let MockWebApi
const express = require('express')
const bodyParser = require('body-parser')
const app = express()
const MAX_REQUEST_SIZE = 2 * (2 * 1024 * 1024 + 64 * 1024)
module.exports = (MockWebApi = {
docs: {},
module.exports = MockWebApi = {
docs: {},
clearDocs() { return this.docs = {}; },
clearDocs() {
return (this.docs = {})
},
insertDoc(project_id, doc_id, doc) {
if (doc.version == null) { doc.version = 0; }
if (doc.lines == null) { doc.lines = []; }
doc.pathname = '/a/b/c.tex';
return this.docs[`${project_id}:${doc_id}`] = doc;
},
insertDoc(project_id, doc_id, doc) {
if (doc.version == null) {
doc.version = 0
}
if (doc.lines == null) {
doc.lines = []
}
doc.pathname = '/a/b/c.tex'
return (this.docs[`${project_id}:${doc_id}`] = doc)
},
setDocument(project_id, doc_id, lines, version, ranges, lastUpdatedAt, lastUpdatedBy, callback) {
if (callback == null) { callback = function(error) {}; }
const doc = this.docs[`${project_id}:${doc_id}`] || (this.docs[`${project_id}:${doc_id}`] = {});
doc.lines = lines;
doc.version = version;
doc.ranges = ranges;
doc.pathname = '/a/b/c.tex';
doc.lastUpdatedAt = lastUpdatedAt;
doc.lastUpdatedBy = lastUpdatedBy;
return callback(null);
},
setDocument(
project_id,
doc_id,
lines,
version,
ranges,
lastUpdatedAt,
lastUpdatedBy,
callback
) {
if (callback == null) {
callback = function (error) {}
}
const doc =
this.docs[`${project_id}:${doc_id}`] ||
(this.docs[`${project_id}:${doc_id}`] = {})
doc.lines = lines
doc.version = version
doc.ranges = ranges
doc.pathname = '/a/b/c.tex'
doc.lastUpdatedAt = lastUpdatedAt
doc.lastUpdatedBy = lastUpdatedBy
return callback(null)
},
getDocument(project_id, doc_id, callback) {
if (callback == null) { callback = function(error, doc) {}; }
return callback(null, this.docs[`${project_id}:${doc_id}`]);
},
getDocument(project_id, doc_id, callback) {
if (callback == null) {
callback = function (error, doc) {}
}
return callback(null, this.docs[`${project_id}:${doc_id}`])
},
run() {
app.get("/project/:project_id/doc/:doc_id", (req, res, next) => {
return this.getDocument(req.params.project_id, req.params.doc_id, (error, doc) => {
if (error != null) {
return res.sendStatus(500);
} else if (doc != null) {
return res.send(JSON.stringify(doc));
} else {
return res.sendStatus(404);
}
});
});
run() {
app.get('/project/:project_id/doc/:doc_id', (req, res, next) => {
return this.getDocument(
req.params.project_id,
req.params.doc_id,
(error, doc) => {
if (error != null) {
return res.sendStatus(500)
} else if (doc != null) {
return res.send(JSON.stringify(doc))
} else {
return res.sendStatus(404)
}
}
)
})
app.post("/project/:project_id/doc/:doc_id", bodyParser.json({limit: MAX_REQUEST_SIZE}), (req, res, next) => {
return MockWebApi.setDocument(req.params.project_id, req.params.doc_id, req.body.lines, req.body.version, req.body.ranges, req.body.lastUpdatedAt, req.body.lastUpdatedBy, (error) => {
if (error != null) {
return res.sendStatus(500);
} else {
return res.sendStatus(204);
}
});
});
app.post(
'/project/:project_id/doc/:doc_id',
bodyParser.json({ limit: MAX_REQUEST_SIZE }),
(req, res, next) => {
return MockWebApi.setDocument(
req.params.project_id,
req.params.doc_id,
req.body.lines,
req.body.version,
req.body.ranges,
req.body.lastUpdatedAt,
req.body.lastUpdatedBy,
(error) => {
if (error != null) {
return res.sendStatus(500)
} else {
return res.sendStatus(204)
}
}
)
}
)
return app.listen(3000, (error) => {
if (error != null) { throw error; }
}).on("error", (error) => {
console.error("error starting MockWebApi:", 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 MockWebApi:', error.message)
return process.exit(1)
})
}
}
MockWebApi.run()