From d15738cb984b30f049e4ca434348a0644308d1f2 Mon Sep 17 00:00:00 2001 From: Tim Alby Date: Wed, 6 May 2020 12:12:47 +0200 Subject: [PATCH] prettier: convert test/acceptance decaffeinated files to Prettier format --- .../js/ApplyingUpdatesToADocTests.js | 1170 ++++++++++------- .../ApplyingUpdatesToProjectStructureTests.js | 785 ++++++----- .../acceptance/js/DeletingADocumentTests.js | 279 ++-- .../acceptance/js/DeletingAProjectTests.js | 442 ++++--- .../acceptance/js/FlushingAProjectTests.js | 214 +-- .../test/acceptance/js/FlushingDocsTests.js | 229 ++-- .../acceptance/js/GettingADocumentTests.js | 396 +++--- .../acceptance/js/GettingProjectDocsTests.js | 238 ++-- .../test/acceptance/js/RangesTests.js | 1126 +++++++++------- .../acceptance/js/SettingADocumentTests.js | 700 ++++++---- .../acceptance/js/helpers/DocUpdaterApp.js | 60 +- .../acceptance/js/helpers/DocUpdaterClient.js | 383 ++++-- .../js/helpers/MockProjectHistoryApi.js | 52 +- .../js/helpers/MockTrackChangesApi.js | 61 +- .../test/acceptance/js/helpers/MockWebApi.js | 161 ++- 15 files changed, 3810 insertions(+), 2486 deletions(-) diff --git a/services/document-updater/test/acceptance/js/ApplyingUpdatesToADocTests.js b/services/document-updater/test/acceptance/js/ApplyingUpdatesToADocTests.js index 928e656d03..aab254ff96 100644 --- a/services/document-updater/test/acceptance/js/ApplyingUpdatesToADocTests.js +++ b/services/document-updater/test/acceptance/js/ApplyingUpdatesToADocTests.js @@ -11,495 +11,785 @@ * 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 Settings = require('settings-sharelatex'); -const rclient_history = require("redis-sharelatex").createClient(Settings.redis.history); // note: this is track changes, not project-history -const rclient_project_history = require("redis-sharelatex").createClient(Settings.redis.project_history); -const rclient_du = require("redis-sharelatex").createClient(Settings.redis.documentupdater); -const Keys = Settings.redis.documentupdater.key_schema; -const HistoryKeys = Settings.redis.history.key_schema; -const ProjectHistoryKeys = Settings.redis.project_history.key_schema; +const sinon = require('sinon') +const chai = require('chai') +chai.should() +const { expect } = chai +const async = require('async') +const Settings = require('settings-sharelatex') +const rclient_history = require('redis-sharelatex').createClient( + Settings.redis.history +) // note: this is track changes, not project-history +const rclient_project_history = require('redis-sharelatex').createClient( + Settings.redis.project_history +) +const rclient_du = require('redis-sharelatex').createClient( + Settings.redis.documentupdater +) +const Keys = Settings.redis.documentupdater.key_schema +const HistoryKeys = Settings.redis.history.key_schema +const ProjectHistoryKeys = Settings.redis.project_history.key_schema -const MockTrackChangesApi = require("./helpers/MockTrackChangesApi"); -const MockWebApi = require("./helpers/MockWebApi"); -const DocUpdaterClient = require("./helpers/DocUpdaterClient"); -const DocUpdaterApp = require("./helpers/DocUpdaterApp"); +const MockTrackChangesApi = require('./helpers/MockTrackChangesApi') +const MockWebApi = require('./helpers/MockWebApi') +const DocUpdaterClient = require('./helpers/DocUpdaterClient') +const DocUpdaterApp = require('./helpers/DocUpdaterApp') -describe("Applying updates to a doc", 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"]; - return DocUpdaterApp.ensureRunning(done); - }); +describe('Applying updates to a doc', 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'] + 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"); - this.startTime = Date.now(); - MockWebApi.insertDoc(this.project_id, this.doc_id, {lines: this.lines, version: this.version}); - DocUpdaterClient.sendUpdate(this.project_id, this.doc_id, this.update, (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, this.doc_id] = Array.from([ + DocUpdaterClient.randomId(), + DocUpdaterClient.randomId() + ]) + sinon.spy(MockWebApi, 'getDocument') + this.startTime = Date.now() + MockWebApi.insertDoc(this.project_id, this.doc_id, { + lines: this.lines, + version: this.version + }) + DocUpdaterClient.sendUpdate( + this.project_id, + this.doc_id, + this.update, + (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 load the document from the web API", function() { - return MockWebApi.getDocument - .calledWith(this.project_id, this.doc_id) - .should.equal(true); - }); + 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 update the doc", function(done) { - DocUpdaterClient.getDoc(this.project_id, this.doc_id, (error, res, doc) => { - doc.lines.should.deep.equal(this.result); - return done(); - }); - return null; - }); + it('should update the doc', function (done) { + DocUpdaterClient.getDoc( + this.project_id, + this.doc_id, + (error, res, doc) => { + doc.lines.should.deep.equal(this.result) + return done() + } + ) + return null + }) - it("should push the applied updates to the track changes api", function(done) { - rclient_history.lrange(HistoryKeys.uncompressedHistoryOps({doc_id: this.doc_id}), 0, -1, (error, updates) => { - if (error != null) { throw error; } - JSON.parse(updates[0]).op.should.deep.equal(this.update.op); - return rclient_history.sismember(HistoryKeys.docsWithHistoryOps({project_id: this.project_id}), this.doc_id, (error, result) => { - if (error != null) { throw error; } - result.should.equal(1); - return done(); - }); - }); - return null; - }); + it('should push the applied updates to the track changes api', function (done) { + rclient_history.lrange( + HistoryKeys.uncompressedHistoryOps({ doc_id: this.doc_id }), + 0, + -1, + (error, updates) => { + if (error != null) { + throw error + } + JSON.parse(updates[0]).op.should.deep.equal(this.update.op) + return rclient_history.sismember( + HistoryKeys.docsWithHistoryOps({ project_id: this.project_id }), + this.doc_id, + (error, result) => { + if (error != null) { + throw error + } + result.should.equal(1) + return done() + } + ) + } + ) + return null + }) - it("should push the applied updates to the project history changes api", function(done) { - rclient_project_history.lrange(ProjectHistoryKeys.projectHistoryOps({project_id: this.project_id}), 0, -1, (error, updates) => { - if (error != null) { throw error; } - JSON.parse(updates[0]).op.should.deep.equal(this.update.op); - return done(); - }); - return null; - }); + it('should push the applied updates to the project history changes api', function (done) { + rclient_project_history.lrange( + ProjectHistoryKeys.projectHistoryOps({ project_id: this.project_id }), + 0, + -1, + (error, updates) => { + if (error != null) { + throw error + } + JSON.parse(updates[0]).op.should.deep.equal(this.update.op) + return done() + } + ) + return null + }) - it("should set the first op timestamp", function(done) { - rclient_project_history.get(ProjectHistoryKeys.projectHistoryFirstOpTimestamp({project_id: this.project_id}), (error, result) => { - if (error != null) { throw error; } - result.should.be.within(this.startTime, Date.now()); - this.firstOpTimestamp = result; - return done(); - }); - return null; - }); + it('should set the first op timestamp', function (done) { + rclient_project_history.get( + ProjectHistoryKeys.projectHistoryFirstOpTimestamp({ + project_id: this.project_id + }), + (error, result) => { + if (error != null) { + throw error + } + result.should.be.within(this.startTime, Date.now()) + this.firstOpTimestamp = result + return done() + } + ) + return null + }) - return describe("when sending another update", function() { - before(function(done) { - this.timeout = 10000; - this.second_update = Object.create(this.update); - this.second_update.v = this.version + 1; - DocUpdaterClient.sendUpdate(this.project_id, this.doc_id, this.second_update, (error) => { - if (error != null) { throw error; } - return setTimeout(done, 200); - }); - return null; - }); + return describe('when sending another update', function () { + before(function (done) { + this.timeout = 10000 + this.second_update = Object.create(this.update) + this.second_update.v = this.version + 1 + DocUpdaterClient.sendUpdate( + this.project_id, + this.doc_id, + this.second_update, + (error) => { + if (error != null) { + throw error + } + return setTimeout(done, 200) + } + ) + return null + }) - return it("should not change the first op timestamp", function(done) { - rclient_project_history.get(ProjectHistoryKeys.projectHistoryFirstOpTimestamp({project_id: this.project_id}), (error, result) => { - if (error != null) { throw error; } - result.should.equal(this.firstOpTimestamp); - return done(); - }); - return null; - }); - }); - }); + return it('should not change the first op timestamp', function (done) { + rclient_project_history.get( + ProjectHistoryKeys.projectHistoryFirstOpTimestamp({ + project_id: this.project_id + }), + (error, result) => { + if (error != null) { + throw error + } + result.should.equal(this.firstOpTimestamp) + return done() + } + ) + return null + }) + }) + }) - describe("when the document is loaded", function() { - before(function(done) { - [this.project_id, this.doc_id] = Array.from([DocUpdaterClient.randomId(), DocUpdaterClient.randomId()]); + describe('when the document is 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}); - DocUpdaterClient.preloadDoc(this.project_id, this.doc_id, error => { - if (error != null) { throw error; } - sinon.spy(MockWebApi, "getDocument"); - return DocUpdaterClient.sendUpdate(this.project_id, this.doc_id, this.update, (error) => { - if (error != null) { throw error; } - return setTimeout(done, 200); - }); - }); - return null; - }); + 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 + } + sinon.spy(MockWebApi, 'getDocument') + return DocUpdaterClient.sendUpdate( + this.project_id, + this.doc_id, + this.update, + (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 not need to call the web api", function() { return MockWebApi.getDocument.called.should.equal(false); }); + it('should not need to call the web api', function () { + return MockWebApi.getDocument.called.should.equal(false) + }) - it("should update the doc", function(done) { - DocUpdaterClient.getDoc(this.project_id, this.doc_id, (error, res, doc) => { - doc.lines.should.deep.equal(this.result); - return done(); - }); - return null; - }); + it('should update the doc', function (done) { + DocUpdaterClient.getDoc( + this.project_id, + this.doc_id, + (error, res, doc) => { + doc.lines.should.deep.equal(this.result) + return done() + } + ) + return null + }) - it("should push the applied updates to the track changes api", function(done) { - rclient_history.lrange(HistoryKeys.uncompressedHistoryOps({doc_id: this.doc_id}), 0, -1, (error, updates) => { - JSON.parse(updates[0]).op.should.deep.equal(this.update.op); - return rclient_history.sismember(HistoryKeys.docsWithHistoryOps({project_id: this.project_id}), this.doc_id, (error, result) => { - result.should.equal(1); - return done(); - }); - }); - return null; - }); + it('should push the applied updates to the track changes api', function (done) { + rclient_history.lrange( + HistoryKeys.uncompressedHistoryOps({ doc_id: this.doc_id }), + 0, + -1, + (error, updates) => { + JSON.parse(updates[0]).op.should.deep.equal(this.update.op) + return rclient_history.sismember( + HistoryKeys.docsWithHistoryOps({ project_id: this.project_id }), + this.doc_id, + (error, result) => { + result.should.equal(1) + return done() + } + ) + } + ) + return null + }) - return it("should push the applied updates to the project history changes api", function(done) { - rclient_project_history.lrange(ProjectHistoryKeys.projectHistoryOps({project_id: this.project_id}), 0, -1, (error, updates) => { - JSON.parse(updates[0]).op.should.deep.equal(this.update.op); - return done(); - }); - return null; - }); - }); + return it('should push the applied updates to the project history changes api', function (done) { + rclient_project_history.lrange( + ProjectHistoryKeys.projectHistoryOps({ project_id: this.project_id }), + 0, + -1, + (error, updates) => { + JSON.parse(updates[0]).op.should.deep.equal(this.update.op) + return done() + } + ) + return null + }) + }) - describe("when the document is loaded and is using project-history only", function() { - before(function(done) { - [this.project_id, this.doc_id] = Array.from([DocUpdaterClient.randomId(), DocUpdaterClient.randomId()]); + describe('when the document is loaded and is using project-history only', 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, projectHistoryType: 'project-history'}); - DocUpdaterClient.preloadDoc(this.project_id, this.doc_id, error => { - if (error != null) { throw error; } - sinon.spy(MockWebApi, "getDocument"); - return DocUpdaterClient.sendUpdate(this.project_id, this.doc_id, this.update, (error) => { - if (error != null) { throw error; } - return setTimeout(done, 200); - }); - }); - return null; - }); + MockWebApi.insertDoc(this.project_id, this.doc_id, { + lines: this.lines, + version: this.version, + projectHistoryType: 'project-history' + }) + DocUpdaterClient.preloadDoc(this.project_id, this.doc_id, (error) => { + if (error != null) { + throw error + } + sinon.spy(MockWebApi, 'getDocument') + return DocUpdaterClient.sendUpdate( + this.project_id, + this.doc_id, + this.update, + (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.doc_id, (error, res, doc) => { - doc.lines.should.deep.equal(this.result); - return done(); - }); - return null; - }); + it('should update the doc', function (done) { + DocUpdaterClient.getDoc( + this.project_id, + this.doc_id, + (error, res, doc) => { + doc.lines.should.deep.equal(this.result) + return done() + } + ) + return null + }) - it("should not push any applied updates to the track changes api", function(done) { - rclient_history.lrange(HistoryKeys.uncompressedHistoryOps({doc_id: this.doc_id}), 0, -1, (error, updates) => { - updates.length.should.equal(0); - return done(); - }); - return null; - }); + it('should not push any applied updates to the track changes api', function (done) { + rclient_history.lrange( + HistoryKeys.uncompressedHistoryOps({ doc_id: this.doc_id }), + 0, + -1, + (error, updates) => { + updates.length.should.equal(0) + return done() + } + ) + return null + }) - return it("should push the applied updates to the project history changes api", function(done) { - rclient_project_history.lrange(ProjectHistoryKeys.projectHistoryOps({project_id: this.project_id}), 0, -1, (error, updates) => { - JSON.parse(updates[0]).op.should.deep.equal(this.update.op); - return done(); - }); - return null; - }); - }); + return it('should push the applied updates to the project history changes api', function (done) { + rclient_project_history.lrange( + ProjectHistoryKeys.projectHistoryOps({ project_id: this.project_id }), + 0, + -1, + (error, updates) => { + JSON.parse(updates[0]).op.should.deep.equal(this.update.op) + return done() + } + ) + return null + }) + }) - describe("when the document has been deleted", function() { - describe("when the ops come in a single linear order", function() { - before(function(done) { - [this.project_id, this.doc_id] = Array.from([DocUpdaterClient.randomId(), DocUpdaterClient.randomId()]); - const lines = ["", "", ""]; - MockWebApi.insertDoc(this.project_id, this.doc_id, {lines, version: 0}); - this.updates = [ - { doc_id: this.doc_id, v: 0, op: [{i: "h", p: 0} ] }, - { doc_id: this.doc_id, v: 1, op: [{i: "e", p: 1} ] }, - { doc_id: this.doc_id, v: 2, op: [{i: "l", p: 2} ] }, - { doc_id: this.doc_id, v: 3, op: [{i: "l", p: 3} ] }, - { doc_id: this.doc_id, v: 4, op: [{i: "o", p: 4} ] }, - { doc_id: this.doc_id, v: 5, op: [{i: " ", p: 5} ] }, - { doc_id: this.doc_id, v: 6, op: [{i: "w", p: 6} ] }, - { doc_id: this.doc_id, v: 7, op: [{i: "o", p: 7} ] }, - { doc_id: this.doc_id, v: 8, op: [{i: "r", p: 8} ] }, - { doc_id: this.doc_id, v: 9, op: [{i: "l", p: 9} ] }, - { doc_id: this.doc_id, v: 10, op: [{i: "d", p: 10}] } - ]; - this.my_result = ["hello world", "", ""]; - return done(); - }); + describe('when the document has been deleted', function () { + describe('when the ops come in a single linear order', function () { + before(function (done) { + ;[this.project_id, this.doc_id] = Array.from([ + DocUpdaterClient.randomId(), + DocUpdaterClient.randomId() + ]) + const lines = ['', '', ''] + MockWebApi.insertDoc(this.project_id, this.doc_id, { + lines, + version: 0 + }) + this.updates = [ + { doc_id: this.doc_id, v: 0, op: [{ i: 'h', p: 0 }] }, + { doc_id: this.doc_id, v: 1, op: [{ i: 'e', p: 1 }] }, + { doc_id: this.doc_id, v: 2, op: [{ i: 'l', p: 2 }] }, + { doc_id: this.doc_id, v: 3, op: [{ i: 'l', p: 3 }] }, + { doc_id: this.doc_id, v: 4, op: [{ i: 'o', p: 4 }] }, + { doc_id: this.doc_id, v: 5, op: [{ i: ' ', p: 5 }] }, + { doc_id: this.doc_id, v: 6, op: [{ i: 'w', p: 6 }] }, + { doc_id: this.doc_id, v: 7, op: [{ i: 'o', p: 7 }] }, + { doc_id: this.doc_id, v: 8, op: [{ i: 'r', p: 8 }] }, + { doc_id: this.doc_id, v: 9, op: [{ i: 'l', p: 9 }] }, + { doc_id: this.doc_id, v: 10, op: [{ i: 'd', p: 10 }] } + ] + this.my_result = ['hello world', '', ''] + return done() + }) - it("should be able to continue applying updates when the project has been deleted", function(done) { - let update; - const actions = []; - for (update of Array.from(this.updates.slice(0,6))) { - (update => { - return actions.push(callback => DocUpdaterClient.sendUpdate(this.project_id, this.doc_id, update, callback)); - })(update); - } - actions.push(callback => DocUpdaterClient.deleteDoc(this.project_id, this.doc_id, callback)); - for (update of Array.from(this.updates.slice(6))) { - (update => { - return actions.push(callback => DocUpdaterClient.sendUpdate(this.project_id, this.doc_id, update, callback)); - })(update); - } + it('should be able to continue applying updates when the project has been deleted', function (done) { + let update + const actions = [] + for (update of Array.from(this.updates.slice(0, 6))) { + ;((update) => { + return actions.push((callback) => + DocUpdaterClient.sendUpdate( + this.project_id, + this.doc_id, + update, + callback + ) + ) + })(update) + } + actions.push((callback) => + DocUpdaterClient.deleteDoc(this.project_id, this.doc_id, callback) + ) + for (update of Array.from(this.updates.slice(6))) { + ;((update) => { + return actions.push((callback) => + DocUpdaterClient.sendUpdate( + this.project_id, + this.doc_id, + update, + callback + ) + ) + })(update) + } - async.series(actions, error => { - if (error != null) { throw error; } - return DocUpdaterClient.getDoc(this.project_id, this.doc_id, (error, res, doc) => { - doc.lines.should.deep.equal(this.my_result); - return done(); - }); - }); - return null; - }); + async.series(actions, (error) => { + if (error != null) { + throw error + } + return DocUpdaterClient.getDoc( + this.project_id, + this.doc_id, + (error, res, doc) => { + doc.lines.should.deep.equal(this.my_result) + return done() + } + ) + }) + return null + }) - it("should push the applied updates to the track changes api", function(done) { - rclient_history.lrange(HistoryKeys.uncompressedHistoryOps({doc_id: this.doc_id}), 0, -1, (error, updates) => { - updates = (Array.from(updates).map((u) => JSON.parse(u))); - for (let i = 0; i < this.updates.length; i++) { - const appliedUpdate = this.updates[i]; - appliedUpdate.op.should.deep.equal(updates[i].op); - } + it('should push the applied updates to the track changes api', function (done) { + rclient_history.lrange( + HistoryKeys.uncompressedHistoryOps({ doc_id: this.doc_id }), + 0, + -1, + (error, updates) => { + updates = Array.from(updates).map((u) => JSON.parse(u)) + for (let i = 0; i < this.updates.length; i++) { + const appliedUpdate = this.updates[i] + appliedUpdate.op.should.deep.equal(updates[i].op) + } - return rclient_history.sismember(HistoryKeys.docsWithHistoryOps({project_id: this.project_id}), this.doc_id, (error, result) => { - result.should.equal(1); - return done(); - }); - }); - return null; - }); + return rclient_history.sismember( + HistoryKeys.docsWithHistoryOps({ project_id: this.project_id }), + this.doc_id, + (error, result) => { + result.should.equal(1) + return done() + } + ) + } + ) + return null + }) - return it("should store the doc ops in the correct order", function(done) { - rclient_du.lrange(Keys.docOps({doc_id: this.doc_id}), 0, -1, (error, updates) => { - updates = (Array.from(updates).map((u) => JSON.parse(u))); - for (let i = 0; i < this.updates.length; i++) { - const appliedUpdate = this.updates[i]; - appliedUpdate.op.should.deep.equal(updates[i].op); - } - return done(); - }); - return null; - }); - }); + return it('should store the doc ops in the correct order', function (done) { + rclient_du.lrange( + Keys.docOps({ doc_id: this.doc_id }), + 0, + -1, + (error, updates) => { + updates = Array.from(updates).map((u) => JSON.parse(u)) + for (let i = 0; i < this.updates.length; i++) { + const appliedUpdate = this.updates[i] + appliedUpdate.op.should.deep.equal(updates[i].op) + } + return done() + } + ) + return null + }) + }) - return describe("when older ops come in after the delete", function() { - before(function(done) { - [this.project_id, this.doc_id] = Array.from([DocUpdaterClient.randomId(), DocUpdaterClient.randomId()]); - const lines = ["", "", ""]; - MockWebApi.insertDoc(this.project_id, this.doc_id, {lines, version: 0}); - this.updates = [ - { doc_id: this.doc_id, v: 0, op: [{i: "h", p: 0} ] }, - { doc_id: this.doc_id, v: 1, op: [{i: "e", p: 1} ] }, - { doc_id: this.doc_id, v: 2, op: [{i: "l", p: 2} ] }, - { doc_id: this.doc_id, v: 3, op: [{i: "l", p: 3} ] }, - { doc_id: this.doc_id, v: 4, op: [{i: "o", p: 4} ] }, - { doc_id: this.doc_id, v: 0, op: [{i: "world", p: 1} ] } - ]; - this.my_result = ["hello", "world", ""]; - return done(); - }); + return describe('when older ops come in after the delete', function () { + before(function (done) { + ;[this.project_id, this.doc_id] = Array.from([ + DocUpdaterClient.randomId(), + DocUpdaterClient.randomId() + ]) + const lines = ['', '', ''] + MockWebApi.insertDoc(this.project_id, this.doc_id, { + lines, + version: 0 + }) + this.updates = [ + { doc_id: this.doc_id, v: 0, op: [{ i: 'h', p: 0 }] }, + { doc_id: this.doc_id, v: 1, op: [{ i: 'e', p: 1 }] }, + { doc_id: this.doc_id, v: 2, op: [{ i: 'l', p: 2 }] }, + { doc_id: this.doc_id, v: 3, op: [{ i: 'l', p: 3 }] }, + { doc_id: this.doc_id, v: 4, op: [{ i: 'o', p: 4 }] }, + { doc_id: this.doc_id, v: 0, op: [{ i: 'world', p: 1 }] } + ] + this.my_result = ['hello', 'world', ''] + return done() + }) - return it("should be able to continue applying updates when the project has been deleted", function(done) { - let update; - const actions = []; - for (update of Array.from(this.updates.slice(0,5))) { - (update => { - return actions.push(callback => DocUpdaterClient.sendUpdate(this.project_id, this.doc_id, update, callback)); - })(update); - } - actions.push(callback => DocUpdaterClient.deleteDoc(this.project_id, this.doc_id, callback)); - for (update of Array.from(this.updates.slice(5))) { - (update => { - return actions.push(callback => DocUpdaterClient.sendUpdate(this.project_id, this.doc_id, update, callback)); - })(update); - } + return it('should be able to continue applying updates when the project has been deleted', function (done) { + let update + const actions = [] + for (update of Array.from(this.updates.slice(0, 5))) { + ;((update) => { + return actions.push((callback) => + DocUpdaterClient.sendUpdate( + this.project_id, + this.doc_id, + update, + callback + ) + ) + })(update) + } + actions.push((callback) => + DocUpdaterClient.deleteDoc(this.project_id, this.doc_id, callback) + ) + for (update of Array.from(this.updates.slice(5))) { + ;((update) => { + return actions.push((callback) => + DocUpdaterClient.sendUpdate( + this.project_id, + this.doc_id, + update, + callback + ) + ) + })(update) + } - async.series(actions, error => { - if (error != null) { throw error; } - return DocUpdaterClient.getDoc(this.project_id, this.doc_id, (error, res, doc) => { - doc.lines.should.deep.equal(this.my_result); - return done(); - }); - }); - return null; - }); - }); - }); + async.series(actions, (error) => { + if (error != null) { + throw error + } + return DocUpdaterClient.getDoc( + this.project_id, + this.doc_id, + (error, res, doc) => { + doc.lines.should.deep.equal(this.my_result) + return done() + } + ) + }) + return null + }) + }) + }) - describe("with a broken update", function() { - before(function(done) { - [this.project_id, this.doc_id] = Array.from([DocUpdaterClient.randomId(), DocUpdaterClient.randomId()]); - this.broken_update = { doc_id: this.doc_id, v: this.version, op: [{d: "not the correct content", p: 0} ] }; - MockWebApi.insertDoc(this.project_id, this.doc_id, {lines: this.lines, version: this.version}); + describe('with a broken update', function () { + before(function (done) { + ;[this.project_id, this.doc_id] = Array.from([ + DocUpdaterClient.randomId(), + DocUpdaterClient.randomId() + ]) + this.broken_update = { + doc_id: this.doc_id, + v: this.version, + op: [{ d: 'not the correct content', p: 0 }] + } + MockWebApi.insertDoc(this.project_id, this.doc_id, { + lines: this.lines, + version: this.version + }) - DocUpdaterClient.subscribeToAppliedOps(this.messageCallback = sinon.stub()); + DocUpdaterClient.subscribeToAppliedOps( + (this.messageCallback = sinon.stub()) + ) - DocUpdaterClient.sendUpdate(this.project_id, this.doc_id, this.broken_update, (error) => { - if (error != null) { throw error; } - return setTimeout(done, 200); - }); - return null; - }); + DocUpdaterClient.sendUpdate( + this.project_id, + this.doc_id, + this.broken_update, + (error) => { + if (error != null) { + throw error + } + return setTimeout(done, 200) + } + ) + return null + }) - it("should not update the doc", function(done) { - DocUpdaterClient.getDoc(this.project_id, this.doc_id, (error, res, doc) => { - doc.lines.should.deep.equal(this.lines); - return done(); - }); - return null; - }); + it('should not update the doc', function (done) { + DocUpdaterClient.getDoc( + this.project_id, + this.doc_id, + (error, res, doc) => { + doc.lines.should.deep.equal(this.lines) + return done() + } + ) + return null + }) - return it("should send a message with an error", function() { - this.messageCallback.called.should.equal(true); - const [channel, message] = Array.from(this.messageCallback.args[0]); - channel.should.equal("applied-ops"); - return JSON.parse(message).should.deep.include({ - project_id: this.project_id, - doc_id: this.doc_id, - error:'Delete component does not match' - }); - }); -}); + return it('should send a message with an error', function () { + this.messageCallback.called.should.equal(true) + const [channel, message] = Array.from(this.messageCallback.args[0]) + channel.should.equal('applied-ops') + return JSON.parse(message).should.deep.include({ + project_id: this.project_id, + doc_id: this.doc_id, + error: 'Delete component does not match' + }) + }) + }) - describe("with enough updates to flush to the track changes api", function() { - before(function(done) { - [this.project_id, this.doc_id] = Array.from([DocUpdaterClient.randomId(), DocUpdaterClient.randomId()]); - const updates = []; - for (let v = 0; v <= 199; v++) { // Should flush after 100 ops - updates.push({ - doc_id: this.doc_id, - op: [{i: v.toString(), p: 0}], - v - }); - } + describe('with enough updates to flush to the track changes api', function () { + before(function (done) { + ;[this.project_id, this.doc_id] = Array.from([ + DocUpdaterClient.randomId(), + DocUpdaterClient.randomId() + ]) + const updates = [] + for (let v = 0; v <= 199; v++) { + // Should flush after 100 ops + updates.push({ + doc_id: this.doc_id, + op: [{ i: v.toString(), p: 0 }], + v + }) + } - sinon.spy(MockTrackChangesApi, "flushDoc"); + sinon.spy(MockTrackChangesApi, 'flushDoc') - MockWebApi.insertDoc(this.project_id, this.doc_id, {lines: this.lines, version: 0}); + MockWebApi.insertDoc(this.project_id, this.doc_id, { + lines: this.lines, + version: 0 + }) - // Send updates in chunks to causes multiple flushes - const actions = []; - for (let i = 0; i <= 19; i++) { - (i => { - return actions.push(cb => { - return DocUpdaterClient.sendUpdates(this.project_id, this.doc_id, updates.slice(i*10, (i+1)*10), cb); - }); - })(i); - } - async.series(actions, error => { - if (error != null) { throw error; } - return setTimeout(done, 2000); - }); - return null; - }); + // Send updates in chunks to causes multiple flushes + const actions = [] + for (let i = 0; i <= 19; i++) { + ;((i) => { + return actions.push((cb) => { + return DocUpdaterClient.sendUpdates( + this.project_id, + this.doc_id, + updates.slice(i * 10, (i + 1) * 10), + cb + ) + }) + })(i) + } + async.series(actions, (error) => { + if (error != null) { + throw error + } + return setTimeout(done, 2000) + }) + return null + }) - after(function() { return MockTrackChangesApi.flushDoc.restore(); }); + after(function () { + return MockTrackChangesApi.flushDoc.restore() + }) - return it("should flush the doc twice", function() { return MockTrackChangesApi.flushDoc.calledTwice.should.equal(true); }); - }); + return it('should flush the doc twice', function () { + return MockTrackChangesApi.flushDoc.calledTwice.should.equal(true) + }) + }) - describe("when there is no version in Mongo", 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 - }); + describe('when there is no version in Mongo', 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 + }) - const update = { - doc: this.doc_id, - op: this.update.op, - v: 0 - }; - DocUpdaterClient.sendUpdate(this.project_id, this.doc_id, update, (error) => { - if (error != null) { throw error; } - return setTimeout(done, 200); - }); - return null; - }); + const update = { + doc: this.doc_id, + op: this.update.op, + v: 0 + } + DocUpdaterClient.sendUpdate( + this.project_id, + this.doc_id, + update, + (error) => { + if (error != null) { + throw error + } + return setTimeout(done, 200) + } + ) + return null + }) - return it("should update the doc (using version = 0)", function(done) { - DocUpdaterClient.getDoc(this.project_id, this.doc_id, (error, res, doc) => { - doc.lines.should.deep.equal(this.result); - return done(); - }); - return null; - }); - }); + return it('should update the doc (using version = 0)', function (done) { + DocUpdaterClient.getDoc( + this.project_id, + this.doc_id, + (error, res, doc) => { + doc.lines.should.deep.equal(this.result) + return done() + } + ) + return null + }) + }) - return describe("when the sending duplicate 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, version: this.version}); + return describe('when the sending duplicate 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, + version: this.version + }) - DocUpdaterClient.subscribeToAppliedOps(this.messageCallback = sinon.stub()); + DocUpdaterClient.subscribeToAppliedOps( + (this.messageCallback = sinon.stub()) + ) - // One user delete 'one', the next turns it into 'once'. The second becomes a NOP. - DocUpdaterClient.sendUpdate(this.project_id, this.doc_id, { - doc: this.doc_id, - op: [{ - i: "one and a half\n", - p: 4 - }], - v: this.version, - meta: { - source: "ikHceq3yfAdQYzBo4-xZ" - } - }, error => { - if (error != null) { throw error; } - return setTimeout(() => { - return DocUpdaterClient.sendUpdate(this.project_id, this.doc_id, { - doc: this.doc_id, - op: [{ - i: "one and a half\n", - p: 4 - }], - v: this.version, - dupIfSource: ["ikHceq3yfAdQYzBo4-xZ"], - meta: { - source: "ikHceq3yfAdQYzBo4-xZ" - } - }, error => { - if (error != null) { throw error; } - return setTimeout(done, 200); - }); - } - , 200); - }); - return null; - }); + // One user delete 'one', the next turns it into 'once'. The second becomes a NOP. + DocUpdaterClient.sendUpdate( + this.project_id, + this.doc_id, + { + doc: this.doc_id, + op: [ + { + i: 'one and a half\n', + p: 4 + } + ], + v: this.version, + meta: { + source: 'ikHceq3yfAdQYzBo4-xZ' + } + }, + (error) => { + if (error != null) { + throw error + } + return setTimeout(() => { + return DocUpdaterClient.sendUpdate( + this.project_id, + this.doc_id, + { + doc: this.doc_id, + op: [ + { + i: 'one and a half\n', + p: 4 + } + ], + v: this.version, + dupIfSource: ['ikHceq3yfAdQYzBo4-xZ'], + meta: { + source: 'ikHceq3yfAdQYzBo4-xZ' + } + }, + (error) => { + if (error != null) { + throw error + } + return setTimeout(done, 200) + } + ) + }, 200) + } + ) + return null + }) - it("should update the doc", function(done) { - DocUpdaterClient.getDoc(this.project_id, this.doc_id, (error, res, doc) => { - doc.lines.should.deep.equal(this.result); - return done(); - }); - return null; - }); - - return it("should return a message about duplicate ops", function() { - this.messageCallback.calledTwice.should.equal(true); - this.messageCallback.args[0][0].should.equal("applied-ops"); - expect(JSON.parse(this.messageCallback.args[0][1]).op.dup).to.be.undefined; - this.messageCallback.args[1][0].should.equal("applied-ops"); - return expect(JSON.parse(this.messageCallback.args[1][1]).op.dup).to.equal(true); - }); - }); -}); + it('should update the doc', function (done) { + DocUpdaterClient.getDoc( + this.project_id, + this.doc_id, + (error, res, doc) => { + doc.lines.should.deep.equal(this.result) + return done() + } + ) + return null + }) + return it('should return a message about duplicate ops', function () { + this.messageCallback.calledTwice.should.equal(true) + this.messageCallback.args[0][0].should.equal('applied-ops') + expect(JSON.parse(this.messageCallback.args[0][1]).op.dup).to.be.undefined + this.messageCallback.args[1][0].should.equal('applied-ops') + return expect( + JSON.parse(this.messageCallback.args[1][1]).op.dup + ).to.equal(true) + }) + }) +}) diff --git a/services/document-updater/test/acceptance/js/ApplyingUpdatesToProjectStructureTests.js b/services/document-updater/test/acceptance/js/ApplyingUpdatesToProjectStructureTests.js index d20c3f8aef..793a9fa5a8 100644 --- a/services/document-updater/test/acceptance/js/ApplyingUpdatesToProjectStructureTests.js +++ b/services/document-updater/test/acceptance/js/ApplyingUpdatesToProjectStructureTests.js @@ -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) + }) + }) +}) diff --git a/services/document-updater/test/acceptance/js/DeletingADocumentTests.js b/services/document-updater/test/acceptance/js/DeletingADocumentTests.js index 73f61646cf..fbb8055aae 100644 --- a/services/document-updater/test/acceptance/js/DeletingADocumentTests.js +++ b/services/document-updater/test/acceptance/js/DeletingADocumentTests.js @@ -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) + }) + }) +}) diff --git a/services/document-updater/test/acceptance/js/DeletingAProjectTests.js b/services/document-updater/test/acceptance/js/DeletingAProjectTests.js index 74e1afd0b1..f050ea22e1 100644 --- a/services/document-updater/test/acceptance/js/DeletingAProjectTests.js +++ b/services/document-updater/test/acceptance/js/DeletingAProjectTests.js @@ -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) + }) + }) +}) diff --git a/services/document-updater/test/acceptance/js/FlushingAProjectTests.js b/services/document-updater/test/acceptance/js/FlushingAProjectTests.js index ea45d4af26..c860fce849 100644 --- a/services/document-updater/test/acceptance/js/FlushingAProjectTests.js +++ b/services/document-updater/test/acceptance/js/FlushingAProjectTests.js @@ -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 + ) + }) + }) +}) diff --git a/services/document-updater/test/acceptance/js/FlushingDocsTests.js b/services/document-updater/test/acceptance/js/FlushingDocsTests.js index 5d8c066f20..5556870f8e 100644 --- a/services/document-updater/test/acceptance/js/FlushingDocsTests.js +++ b/services/document-updater/test/acceptance/js/FlushingDocsTests.js @@ -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() + } + ) + }) + }) +}) diff --git a/services/document-updater/test/acceptance/js/GettingADocumentTests.js b/services/document-updater/test/acceptance/js/GettingADocumentTests.js index ad51413387..fc97c8d825 100644 --- a/services/document-updater/test/acceptance/js/GettingADocumentTests.js +++ b/services/document-updater/test/acceptance/js/GettingADocumentTests.js @@ -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; -} \ No newline at end of file + return range +} diff --git a/services/document-updater/test/acceptance/js/GettingProjectDocsTests.js b/services/document-updater/test/acceptance/js/GettingProjectDocsTests.js index cd5d359dd5..72a6824562 100644 --- a/services/document-updater/test/acceptance/js/GettingProjectDocsTests.js +++ b/services/document-updater/test/acceptance/js/GettingProjectDocsTests.js @@ -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) + }) + }) +}) diff --git a/services/document-updater/test/acceptance/js/RangesTests.js b/services/document-updater/test/acceptance/js/RangesTests.js index e5daa62018..df0afe01e5 100644 --- a/services/document-updater/test/acceptance/js/RangesTests.js +++ b/services/document-updater/test/acceptance/js/RangesTests.js @@ -11,463 +11,685 @@ * 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 {db, ObjectId} = require("../../../app/js/mongojs"); -const MockWebApi = require("./helpers/MockWebApi"); -const DocUpdaterClient = require("./helpers/DocUpdaterClient"); -const DocUpdaterApp = require("./helpers/DocUpdaterApp"); +const { db, ObjectId } = require('../../../app/js/mongojs') +const MockWebApi = require('./helpers/MockWebApi') +const DocUpdaterClient = require('./helpers/DocUpdaterClient') +const DocUpdaterApp = require('./helpers/DocUpdaterApp') -describe("Ranges", function() { - before(function(done) { return DocUpdaterApp.ensureRunning(done); }); +describe('Ranges', function () { + before(function (done) { + return DocUpdaterApp.ensureRunning(done) + }) - describe("tracking changes from ops", function() { - before(function(done) { - this.project_id = DocUpdaterClient.randomId(); - this.user_id = DocUpdaterClient.randomId(); - this.id_seed = "587357bd35e64f6157"; - this.doc = { - id: DocUpdaterClient.randomId(), - lines: ["aaa"] - }; - this.updates = [{ - doc: this.doc.id, - op: [{ i: "123", p: 1 }], - v: 0, - meta: { user_id: this.user_id } - }, { - doc: this.doc.id, - op: [{ i: "456", p: 5 }], - v: 1, - meta: { user_id: this.user_id, tc: this.id_seed } - }, { - doc: this.doc.id, - op: [{ d: "12", p: 1 }], - v: 2, - meta: { user_id: this.user_id } - }]; - MockWebApi.insertDoc(this.project_id, this.doc.id, { - lines: this.doc.lines, - version: 0 - }); - const jobs = []; - for (const update of Array.from(this.updates)) { - (update => { - return jobs.push(callback => DocUpdaterClient.sendUpdate(this.project_id, this.doc.id, update, callback)); - })(update); - } - - return DocUpdaterApp.ensureRunning(error => { - if (error != null) { throw error; } - return DocUpdaterClient.preloadDoc(this.project_id, this.doc.id, error => { - if (error != null) { throw error; } - return async.series(jobs, (error) => { - if (error != null) { throw error; } - return done(); - }); - }); - }); - }); - - it("should update the ranges", function(done) { - return DocUpdaterClient.getDoc(this.project_id, this.doc.id, (error, res, data) => { - if (error != null) { throw error; } - const { - ranges - } = data; - const change = ranges.changes[0]; - change.op.should.deep.equal({ i: "456", p: 3 }); - change.id.should.equal(this.id_seed + "000001"); - change.metadata.user_id.should.equal(this.user_id); - return done(); - }); - }); - - return describe("Adding comments", function() { - describe("standalone", function() { - before(function(done) { - this.project_id = DocUpdaterClient.randomId(); - this.user_id = DocUpdaterClient.randomId(); - this.doc = { - id: DocUpdaterClient.randomId(), - lines: ["foo bar baz"] - }; - this.updates = [{ - doc: this.doc.id, - op: [{ c: "bar", p: 4, t: (this.tid = DocUpdaterClient.randomId()) }], - v: 0 - }]; - MockWebApi.insertDoc(this.project_id, this.doc.id, { - lines: this.doc.lines, - version: 0 - }); - const jobs = []; - for (const update of Array.from(this.updates)) { - (update => { - return jobs.push(callback => DocUpdaterClient.sendUpdate(this.project_id, this.doc.id, update, callback)); - })(update); - } - return DocUpdaterClient.preloadDoc(this.project_id, this.doc.id, error => { - if (error != null) { throw error; } - return async.series(jobs, (error) => { - if (error != null) { throw error; } - return setTimeout(done, 200); - }); - }); - }); - - return it("should update the ranges", function(done) { - return DocUpdaterClient.getDoc(this.project_id, this.doc.id, (error, res, data) => { - if (error != null) { throw error; } - const { - ranges - } = data; - const comment = ranges.comments[0]; - comment.op.should.deep.equal({ c: "bar", p: 4, t: this.tid }); - comment.id.should.equal(this.tid); - return done(); - }); - }); - }); + describe('tracking changes from ops', function () { + before(function (done) { + this.project_id = DocUpdaterClient.randomId() + this.user_id = DocUpdaterClient.randomId() + this.id_seed = '587357bd35e64f6157' + this.doc = { + id: DocUpdaterClient.randomId(), + lines: ['aaa'] + } + this.updates = [ + { + doc: this.doc.id, + op: [{ i: '123', p: 1 }], + v: 0, + meta: { user_id: this.user_id } + }, + { + doc: this.doc.id, + op: [{ i: '456', p: 5 }], + v: 1, + meta: { user_id: this.user_id, tc: this.id_seed } + }, + { + doc: this.doc.id, + op: [{ d: '12', p: 1 }], + v: 2, + meta: { user_id: this.user_id } + } + ] + MockWebApi.insertDoc(this.project_id, this.doc.id, { + lines: this.doc.lines, + version: 0 + }) + const jobs = [] + for (const update of Array.from(this.updates)) { + ;((update) => { + return jobs.push((callback) => + DocUpdaterClient.sendUpdate( + this.project_id, + this.doc.id, + update, + callback + ) + ) + })(update) + } - return describe("with conflicting ops needing OT", function() { - before(function(done) { - this.project_id = DocUpdaterClient.randomId(); - this.user_id = DocUpdaterClient.randomId(); - this.doc = { - id: DocUpdaterClient.randomId(), - lines: ["foo bar baz"] - }; - this.updates = [{ - doc: this.doc.id, - op: [{ i: "ABC", p: 3 }], - v: 0, - meta: { user_id: this.user_id } - }, { - doc: this.doc.id, - op: [{ c: "bar", p: 4, t: (this.tid = DocUpdaterClient.randomId()) }], - v: 0 - }]; - MockWebApi.insertDoc(this.project_id, this.doc.id, { - lines: this.doc.lines, - version: 0 - }); - const jobs = []; - for (const update of Array.from(this.updates)) { - (update => { - return jobs.push(callback => DocUpdaterClient.sendUpdate(this.project_id, this.doc.id, update, callback)); - })(update); - } - return DocUpdaterClient.preloadDoc(this.project_id, this.doc.id, error => { - if (error != null) { throw error; } - return async.series(jobs, (error) => { - if (error != null) { throw error; } - return setTimeout(done, 200); - }); - }); - }); - - return it("should update the comments with the OT shifted comment", function(done) { - return DocUpdaterClient.getDoc(this.project_id, this.doc.id, (error, res, data) => { - if (error != null) { throw error; } - const { - ranges - } = data; - const comment = ranges.comments[0]; - comment.op.should.deep.equal({ c: "bar", p: 7, t: this.tid }); - return done(); - }); - }); - }); - }); - }); + return DocUpdaterApp.ensureRunning((error) => { + if (error != null) { + throw error + } + return DocUpdaterClient.preloadDoc( + this.project_id, + this.doc.id, + (error) => { + if (error != null) { + throw error + } + return async.series(jobs, (error) => { + if (error != null) { + throw error + } + return done() + }) + } + ) + }) + }) - describe("Loading ranges from persistence layer", function() { - before(function(done) { - this.project_id = DocUpdaterClient.randomId(); - this.user_id = DocUpdaterClient.randomId(); - this.id_seed = "587357bd35e64f6157"; - this.doc = { - id: DocUpdaterClient.randomId(), - lines: ["a123aa"] - }; - this.update = { - doc: this.doc.id, - op: [{ i: "456", p: 5 }], - v: 0, - meta: { user_id: this.user_id, tc: this.id_seed } - }; - MockWebApi.insertDoc(this.project_id, this.doc.id, { - lines: this.doc.lines, - version: 0, - ranges: { - changes: [{ - op: { i: "123", p: 1 }, - metadata: { - user_id: this.user_id, - ts: new Date() - } - }] - } - }); - 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(done, 200); - }); - }); - }); - - it("should have preloaded the existing ranges", function(done) { - return DocUpdaterClient.getDoc(this.project_id, this.doc.id, (error, res, data) => { - if (error != null) { throw error; } - const {changes} = data.ranges; - changes[0].op.should.deep.equal({ i: "123", p: 1 }); - changes[1].op.should.deep.equal({ i: "456", p: 5 }); - return done(); - }); - }); - - return it("should flush the ranges to the persistence layer again", function(done) { - return DocUpdaterClient.flushDoc(this.project_id, this.doc.id, error => { - if (error != null) { throw error; } - return MockWebApi.getDocument(this.project_id, this.doc.id, (error, doc) => { - const {changes} = doc.ranges; - changes[0].op.should.deep.equal({ i: "123", p: 1 }); - changes[1].op.should.deep.equal({ i: "456", p: 5 }); - return done(); - }); - }); - }); - }); + it('should update the ranges', function (done) { + return DocUpdaterClient.getDoc( + this.project_id, + this.doc.id, + (error, res, data) => { + if (error != null) { + throw error + } + const { ranges } = data + const change = ranges.changes[0] + change.op.should.deep.equal({ i: '456', p: 3 }) + change.id.should.equal(this.id_seed + '000001') + change.metadata.user_id.should.equal(this.user_id) + return done() + } + ) + }) - describe("accepting a change", function() { - before(function(done) { - this.project_id = DocUpdaterClient.randomId(); - this.user_id = DocUpdaterClient.randomId(); - this.id_seed = "587357bd35e64f6157"; - this.doc = { - id: DocUpdaterClient.randomId(), - lines: ["aaa"] - }; - this.update = { - doc: this.doc.id, - op: [{ i: "456", p: 1 }], - v: 0, - meta: { user_id: this.user_id, tc: this.id_seed } - }; - MockWebApi.insertDoc(this.project_id, this.doc.id, { - lines: this.doc.lines, - version: 0 - }); - 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.getDoc(this.project_id, this.doc.id, (error, res, data) => { - if (error != null) { throw error; } - const { - ranges - } = data; - const change = ranges.changes[0]; - change.op.should.deep.equal({ i: "456", p: 1 }); - change.id.should.equal(this.id_seed + "000001"); - change.metadata.user_id.should.equal(this.user_id); - return done(); - }); - } - , 200); - }); - }); - }); - - return it("should remove the change after accepting", function(done) { - return DocUpdaterClient.acceptChange(this.project_id, this.doc.id, this.id_seed + "000001", error => { - if (error != null) { throw error; } - return DocUpdaterClient.getDoc(this.project_id, this.doc.id, (error, res, data) => { - if (error != null) { throw error; } - expect(data.ranges.changes).to.be.undefined; - return done(); - }); - }); - }); - }); + return describe('Adding comments', function () { + describe('standalone', function () { + before(function (done) { + this.project_id = DocUpdaterClient.randomId() + this.user_id = DocUpdaterClient.randomId() + this.doc = { + id: DocUpdaterClient.randomId(), + lines: ['foo bar baz'] + } + this.updates = [ + { + doc: this.doc.id, + op: [ + { c: 'bar', p: 4, t: (this.tid = DocUpdaterClient.randomId()) } + ], + v: 0 + } + ] + MockWebApi.insertDoc(this.project_id, this.doc.id, { + lines: this.doc.lines, + version: 0 + }) + const jobs = [] + for (const update of Array.from(this.updates)) { + ;((update) => { + return jobs.push((callback) => + DocUpdaterClient.sendUpdate( + this.project_id, + this.doc.id, + update, + callback + ) + ) + })(update) + } + return DocUpdaterClient.preloadDoc( + this.project_id, + this.doc.id, + (error) => { + if (error != null) { + throw error + } + return async.series(jobs, (error) => { + if (error != null) { + throw error + } + return setTimeout(done, 200) + }) + } + ) + }) - describe("deleting a comment range", function() { - before(function(done) { - this.project_id = DocUpdaterClient.randomId(); - this.user_id = DocUpdaterClient.randomId(); - this.doc = { - id: DocUpdaterClient.randomId(), - lines: ["foo bar"] - }; - this.update = { - doc: this.doc.id, - op: [{ c: "bar", p: 4, t: (this.tid = DocUpdaterClient.randomId()) }], - v: 0 - }; - MockWebApi.insertDoc(this.project_id, this.doc.id, { - lines: this.doc.lines, - version: 0 - }); - 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.getDoc(this.project_id, this.doc.id, (error, res, data) => { - if (error != null) { throw error; } - const { - ranges - } = data; - const change = ranges.comments[0]; - change.op.should.deep.equal({ c: "bar", p: 4, t: this.tid }); - change.id.should.equal(this.tid); - return done(); - }); - } - , 200); - }); - }); - }); - - return it("should remove the comment range", function(done) { - return DocUpdaterClient.removeComment(this.project_id, this.doc.id, this.tid, (error, res) => { - if (error != null) { throw error; } - expect(res.statusCode).to.equal(204); - return DocUpdaterClient.getDoc(this.project_id, this.doc.id, (error, res, data) => { - if (error != null) { throw error; } - expect(data.ranges.comments).to.be.undefined; - return done(); - }); - }); - }); - }); - - describe("tripping range size limit", function() { - before(function(done) { - this.project_id = DocUpdaterClient.randomId(); - this.user_id = DocUpdaterClient.randomId(); - this.id_seed = DocUpdaterClient.randomId(); - this.doc = { - id: DocUpdaterClient.randomId(), - lines: ["aaa"] - }; - this.i = new Array(3 * 1024 * 1024).join("a"); - this.updates = [{ - doc: this.doc.id, - op: [{ i: this.i, p: 1 }], - v: 0, - meta: { user_id: this.user_id, tc: this.id_seed } - }]; - MockWebApi.insertDoc(this.project_id, this.doc.id, { - lines: this.doc.lines, - version: 0 - }); - const jobs = []; - for (const update of Array.from(this.updates)) { - (update => { - return jobs.push(callback => DocUpdaterClient.sendUpdate(this.project_id, this.doc.id, update, callback)); - })(update); - } - return DocUpdaterClient.preloadDoc(this.project_id, this.doc.id, error => { - if (error != null) { throw error; } - return async.series(jobs, (error) => { - if (error != null) { throw error; } - return setTimeout(done, 200); - }); - }); - }); - - return it("should not update the ranges", function(done) { - return 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 it('should update the ranges', function (done) { + return DocUpdaterClient.getDoc( + this.project_id, + this.doc.id, + (error, res, data) => { + if (error != null) { + throw error + } + const { ranges } = data + const comment = ranges.comments[0] + comment.op.should.deep.equal({ c: 'bar', p: 4, t: this.tid }) + comment.id.should.equal(this.tid) + return done() + } + ) + }) + }) - return describe("deleting text surrounding a comment", function() { - before(function(done) { - this.project_id = DocUpdaterClient.randomId(); - this.user_id = DocUpdaterClient.randomId(); - this.doc_id = DocUpdaterClient.randomId(); - MockWebApi.insertDoc(this.project_id, this.doc_id, { - lines: ["foo bar baz"], - version: 0, - ranges: { - comments: [{ - op: { c: "a", p: 5, tid: (this.tid = DocUpdaterClient.randomId()) }, - metadata: { - user_id: this.user_id, - ts: new Date() - } - }] - } - }); - this.updates = [{ - doc: this.doc_id, - op: [{ d: "foo ", p: 0 }], - v: 0, - meta: { user_id: this.user_id } - }, { - doc: this.doc_id, - op: [{ d: "bar ", p: 0 }], - v: 1, - meta: { user_id: this.user_id } - }]; - const jobs = []; - for (const update of Array.from(this.updates)) { - (update => { - return jobs.push(callback => DocUpdaterClient.sendUpdate(this.project_id, this.doc_id, update, callback)); - })(update); - } - return DocUpdaterClient.preloadDoc(this.project_id, this.doc_id, error => { - if (error != null) { throw error; } - return async.series(jobs, function(error) { - if (error != null) { throw error; } - return setTimeout(() => { - return DocUpdaterClient.getDoc(this.project_id, this.doc_id, (error, res, data) => { - if (error != null) { throw error; } - return done(); - }); - } - , 200); - }); - }); - }); - - return it("should write a snapshot from before the destructive change", function(done) { - return DocUpdaterClient.getDoc(this.project_id, this.doc_id, (error, res, data) => { - if (error != null) { return done(error); } - return db.docSnapshots.find({ - project_id: ObjectId(this.project_id), - doc_id: ObjectId(this.doc_id) - }, (error, docSnapshots) => { - if (error != null) { return done(error); } - expect(docSnapshots.length).to.equal(1); - expect(docSnapshots[0].version).to.equal(1); - expect(docSnapshots[0].lines).to.deep.equal(["bar baz"]); - expect(docSnapshots[0].ranges.comments[0].op).to.deep.equal({ - c: "a", - p: 1, - tid: this.tid - }); - return done(); - }); - }); - }); - }); -}); + return describe('with conflicting ops needing OT', function () { + before(function (done) { + this.project_id = DocUpdaterClient.randomId() + this.user_id = DocUpdaterClient.randomId() + this.doc = { + id: DocUpdaterClient.randomId(), + lines: ['foo bar baz'] + } + this.updates = [ + { + doc: this.doc.id, + op: [{ i: 'ABC', p: 3 }], + v: 0, + meta: { user_id: this.user_id } + }, + { + doc: this.doc.id, + op: [ + { c: 'bar', p: 4, t: (this.tid = DocUpdaterClient.randomId()) } + ], + v: 0 + } + ] + MockWebApi.insertDoc(this.project_id, this.doc.id, { + lines: this.doc.lines, + version: 0 + }) + const jobs = [] + for (const update of Array.from(this.updates)) { + ;((update) => { + return jobs.push((callback) => + DocUpdaterClient.sendUpdate( + this.project_id, + this.doc.id, + update, + callback + ) + ) + })(update) + } + return DocUpdaterClient.preloadDoc( + this.project_id, + this.doc.id, + (error) => { + if (error != null) { + throw error + } + return async.series(jobs, (error) => { + if (error != null) { + throw error + } + return setTimeout(done, 200) + }) + } + ) + }) + + return it('should update the comments with the OT shifted comment', function (done) { + return DocUpdaterClient.getDoc( + this.project_id, + this.doc.id, + (error, res, data) => { + if (error != null) { + throw error + } + const { ranges } = data + const comment = ranges.comments[0] + comment.op.should.deep.equal({ c: 'bar', p: 7, t: this.tid }) + return done() + } + ) + }) + }) + }) + }) + + describe('Loading ranges from persistence layer', function () { + before(function (done) { + this.project_id = DocUpdaterClient.randomId() + this.user_id = DocUpdaterClient.randomId() + this.id_seed = '587357bd35e64f6157' + this.doc = { + id: DocUpdaterClient.randomId(), + lines: ['a123aa'] + } + this.update = { + doc: this.doc.id, + op: [{ i: '456', p: 5 }], + v: 0, + meta: { user_id: this.user_id, tc: this.id_seed } + } + MockWebApi.insertDoc(this.project_id, this.doc.id, { + lines: this.doc.lines, + version: 0, + ranges: { + changes: [ + { + op: { i: '123', p: 1 }, + metadata: { + user_id: this.user_id, + ts: new Date() + } + } + ] + } + }) + 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(done, 200) + } + ) + } + ) + }) + + it('should have preloaded the existing ranges', function (done) { + return DocUpdaterClient.getDoc( + this.project_id, + this.doc.id, + (error, res, data) => { + if (error != null) { + throw error + } + const { changes } = data.ranges + changes[0].op.should.deep.equal({ i: '123', p: 1 }) + changes[1].op.should.deep.equal({ i: '456', p: 5 }) + return done() + } + ) + }) + + return it('should flush the ranges to the persistence layer again', function (done) { + return DocUpdaterClient.flushDoc( + this.project_id, + this.doc.id, + (error) => { + if (error != null) { + throw error + } + return MockWebApi.getDocument( + this.project_id, + this.doc.id, + (error, doc) => { + const { changes } = doc.ranges + changes[0].op.should.deep.equal({ i: '123', p: 1 }) + changes[1].op.should.deep.equal({ i: '456', p: 5 }) + return done() + } + ) + } + ) + }) + }) + + describe('accepting a change', function () { + before(function (done) { + this.project_id = DocUpdaterClient.randomId() + this.user_id = DocUpdaterClient.randomId() + this.id_seed = '587357bd35e64f6157' + this.doc = { + id: DocUpdaterClient.randomId(), + lines: ['aaa'] + } + this.update = { + doc: this.doc.id, + op: [{ i: '456', p: 1 }], + v: 0, + meta: { user_id: this.user_id, tc: this.id_seed } + } + MockWebApi.insertDoc(this.project_id, this.doc.id, { + lines: this.doc.lines, + version: 0 + }) + 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.getDoc( + this.project_id, + this.doc.id, + (error, res, data) => { + if (error != null) { + throw error + } + const { ranges } = data + const change = ranges.changes[0] + change.op.should.deep.equal({ i: '456', p: 1 }) + change.id.should.equal(this.id_seed + '000001') + change.metadata.user_id.should.equal(this.user_id) + return done() + } + ) + }, 200) + } + ) + } + ) + }) + + return it('should remove the change after accepting', function (done) { + return DocUpdaterClient.acceptChange( + this.project_id, + this.doc.id, + this.id_seed + '000001', + (error) => { + if (error != null) { + throw error + } + return DocUpdaterClient.getDoc( + this.project_id, + this.doc.id, + (error, res, data) => { + if (error != null) { + throw error + } + expect(data.ranges.changes).to.be.undefined + return done() + } + ) + } + ) + }) + }) + + describe('deleting a comment range', function () { + before(function (done) { + this.project_id = DocUpdaterClient.randomId() + this.user_id = DocUpdaterClient.randomId() + this.doc = { + id: DocUpdaterClient.randomId(), + lines: ['foo bar'] + } + this.update = { + doc: this.doc.id, + op: [{ c: 'bar', p: 4, t: (this.tid = DocUpdaterClient.randomId()) }], + v: 0 + } + MockWebApi.insertDoc(this.project_id, this.doc.id, { + lines: this.doc.lines, + version: 0 + }) + 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.getDoc( + this.project_id, + this.doc.id, + (error, res, data) => { + if (error != null) { + throw error + } + const { ranges } = data + const change = ranges.comments[0] + change.op.should.deep.equal({ c: 'bar', p: 4, t: this.tid }) + change.id.should.equal(this.tid) + return done() + } + ) + }, 200) + } + ) + } + ) + }) + + return it('should remove the comment range', function (done) { + return DocUpdaterClient.removeComment( + this.project_id, + this.doc.id, + this.tid, + (error, res) => { + if (error != null) { + throw error + } + expect(res.statusCode).to.equal(204) + return DocUpdaterClient.getDoc( + this.project_id, + this.doc.id, + (error, res, data) => { + if (error != null) { + throw error + } + expect(data.ranges.comments).to.be.undefined + return done() + } + ) + } + ) + }) + }) + + describe('tripping range size limit', function () { + before(function (done) { + this.project_id = DocUpdaterClient.randomId() + this.user_id = DocUpdaterClient.randomId() + this.id_seed = DocUpdaterClient.randomId() + this.doc = { + id: DocUpdaterClient.randomId(), + lines: ['aaa'] + } + this.i = new Array(3 * 1024 * 1024).join('a') + this.updates = [ + { + doc: this.doc.id, + op: [{ i: this.i, p: 1 }], + v: 0, + meta: { user_id: this.user_id, tc: this.id_seed } + } + ] + MockWebApi.insertDoc(this.project_id, this.doc.id, { + lines: this.doc.lines, + version: 0 + }) + const jobs = [] + for (const update of Array.from(this.updates)) { + ;((update) => { + return jobs.push((callback) => + DocUpdaterClient.sendUpdate( + this.project_id, + this.doc.id, + update, + callback + ) + ) + })(update) + } + return DocUpdaterClient.preloadDoc( + this.project_id, + this.doc.id, + (error) => { + if (error != null) { + throw error + } + return async.series(jobs, (error) => { + if (error != null) { + throw error + } + return setTimeout(done, 200) + }) + } + ) + }) + + return it('should not update the ranges', function (done) { + return 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 describe('deleting text surrounding a comment', function () { + before(function (done) { + this.project_id = DocUpdaterClient.randomId() + this.user_id = DocUpdaterClient.randomId() + this.doc_id = DocUpdaterClient.randomId() + MockWebApi.insertDoc(this.project_id, this.doc_id, { + lines: ['foo bar baz'], + version: 0, + ranges: { + comments: [ + { + op: { + c: 'a', + p: 5, + tid: (this.tid = DocUpdaterClient.randomId()) + }, + metadata: { + user_id: this.user_id, + ts: new Date() + } + } + ] + } + }) + this.updates = [ + { + doc: this.doc_id, + op: [{ d: 'foo ', p: 0 }], + v: 0, + meta: { user_id: this.user_id } + }, + { + doc: this.doc_id, + op: [{ d: 'bar ', p: 0 }], + v: 1, + meta: { user_id: this.user_id } + } + ] + const jobs = [] + for (const update of Array.from(this.updates)) { + ;((update) => { + return jobs.push((callback) => + DocUpdaterClient.sendUpdate( + this.project_id, + this.doc_id, + update, + callback + ) + ) + })(update) + } + return DocUpdaterClient.preloadDoc( + this.project_id, + this.doc_id, + (error) => { + if (error != null) { + throw error + } + return async.series(jobs, function (error) { + if (error != null) { + throw error + } + return setTimeout(() => { + return DocUpdaterClient.getDoc( + this.project_id, + this.doc_id, + (error, res, data) => { + if (error != null) { + throw error + } + return done() + } + ) + }, 200) + }) + } + ) + }) + + return it('should write a snapshot from before the destructive change', function (done) { + return DocUpdaterClient.getDoc( + this.project_id, + this.doc_id, + (error, res, data) => { + if (error != null) { + return done(error) + } + return db.docSnapshots.find( + { + project_id: ObjectId(this.project_id), + doc_id: ObjectId(this.doc_id) + }, + (error, docSnapshots) => { + if (error != null) { + return done(error) + } + expect(docSnapshots.length).to.equal(1) + expect(docSnapshots[0].version).to.equal(1) + expect(docSnapshots[0].lines).to.deep.equal(['bar baz']) + expect(docSnapshots[0].ranges.comments[0].op).to.deep.equal({ + c: 'a', + p: 1, + tid: this.tid + }) + return done() + } + ) + } + ) + }) + }) +}) diff --git a/services/document-updater/test/acceptance/js/SettingADocumentTests.js b/services/document-updater/test/acceptance/js/SettingADocumentTests.js index 61fba26f17..6c13282ba5 100644 --- a/services/document-updater/test/acceptance/js/SettingADocumentTests.js +++ b/services/document-updater/test/acceptance/js/SettingADocumentTests.js @@ -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 + }) + }) + }) +}) diff --git a/services/document-updater/test/acceptance/js/helpers/DocUpdaterApp.js b/services/document-updater/test/acceptance/js/helpers/DocUpdaterApp.js index a08fd82fac..b922032cd8 100644 --- a/services/document-updater/test/acceptance/js/helpers/DocUpdaterApp.js +++ b/services/document-updater/test/acceptance/js/helpers/DocUpdaterApp.js @@ -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 + })() + }) + } + } +} diff --git a/services/document-updater/test/acceptance/js/helpers/DocUpdaterClient.js b/services/document-updater/test/acceptance/js/helpers/DocUpdaterClient.js index 9f55291cd0..53793135eb 100644 --- a/services/document-updater/test/acceptance/js/helpers/DocUpdaterClient.js +++ b/services/document-updater/test/acceptance/js/helpers/DocUpdaterClient.js @@ -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; -} \ No newline at end of file + return range +} diff --git a/services/document-updater/test/acceptance/js/helpers/MockProjectHistoryApi.js b/services/document-updater/test/acceptance/js/helpers/MockProjectHistoryApi.js index 84e2d7075c..6d72c77baf 100644 --- a/services/document-updater/test/acceptance/js/helpers/MockProjectHistoryApi.js +++ b/services/document-updater/test/acceptance/js/helpers/MockProjectHistoryApi.js @@ -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() diff --git a/services/document-updater/test/acceptance/js/helpers/MockTrackChangesApi.js b/services/document-updater/test/acceptance/js/helpers/MockTrackChangesApi.js index ef14b85beb..319a02b7ca 100644 --- a/services/document-updater/test/acceptance/js/helpers/MockTrackChangesApi.js +++ b/services/document-updater/test/acceptance/js/helpers/MockTrackChangesApi.js @@ -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() diff --git a/services/document-updater/test/acceptance/js/helpers/MockWebApi.js b/services/document-updater/test/acceptance/js/helpers/MockWebApi.js index 653dc3bf2a..fc6bd49e27 100644 --- a/services/document-updater/test/acceptance/js/helpers/MockWebApi.js +++ b/services/document-updater/test/acceptance/js/helpers/MockWebApi.js @@ -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()