decaffeinate: Convert DocArchiveManagerTests.coffee and 4 other files to JS

This commit is contained in:
decaffeinate 2020-02-16 14:02:48 +00:00 committed by Simon Detheridge
parent 5098fa6d40
commit 06bdba5c14
5 changed files with 1512 additions and 1113 deletions

View file

@ -1,356 +1,444 @@
assert = require("chai").assert /*
sinon = require('sinon') * decaffeinate suggestions:
chai = require('chai') * DS101: Remove unnecessary use of Array.from
should = chai.should() * DS102: Remove unnecessary code created because of implicit returns
expect = chai.expect * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
modulePath = "../../../app/js/DocArchiveManager.js" */
SandboxedModule = require('sandboxed-module') const {
ObjectId = require("mongojs").ObjectId assert
Errors = require "../../../app/js/Errors" } = require("chai");
crypto = require("crypto") const sinon = require('sinon');
const chai = require('chai');
const should = chai.should();
const {
expect
} = chai;
const modulePath = "../../../app/js/DocArchiveManager.js";
const SandboxedModule = require('sandboxed-module');
const {
ObjectId
} = require("mongojs");
const Errors = require("../../../app/js/Errors");
const crypto = require("crypto");
describe "DocArchiveManager", -> describe("DocArchiveManager", function() {
beforeEach -> beforeEach(function() {
@settings = this.settings = {
docstore: docstore: {
s3: s3: {
secret: "secret" secret: "secret",
key: "this_key" key: "this_key",
bucket:"doc-archive-unit-test" bucket:"doc-archive-unit-test"
}
}
};
@request = this.request = {
put: {} put: {},
get: {} get: {},
del: {} del: {}
};
@archivedDocs = [{ this.archivedDocs = [{
_id: ObjectId() _id: ObjectId(),
inS3:true inS3:true,
rev: 2 rev: 2
}, { }, {
_id: ObjectId() _id: ObjectId(),
inS3:true inS3:true,
rev: 4 rev: 4
}, { }, {
_id: ObjectId() _id: ObjectId(),
inS3:true inS3:true,
rev: 6 rev: 6
}] }];
@mongoDocs = [{ this.mongoDocs = [{
_id: ObjectId() _id: ObjectId(),
lines: ["one", "two", "three"] lines: ["one", "two", "three"],
rev: 2 rev: 2
}, { }, {
_id: ObjectId() _id: ObjectId(),
lines: ["aaa", "bbb", "ccc"] lines: ["aaa", "bbb", "ccc"],
rev: 4 rev: 4
}, { }, {
_id: ObjectId() _id: ObjectId(),
inS3: true inS3: true,
rev: 6 rev: 6
}, { }, {
_id: ObjectId() _id: ObjectId(),
inS3: true inS3: true,
rev: 6 rev: 6
}, { }, {
_id: ObjectId() _id: ObjectId(),
lines: ["111", "222", "333"] lines: ["111", "222", "333"],
rev: 6 rev: 6
}] }];
@unarchivedDocs = [{ this.unarchivedDocs = [{
_id: ObjectId() _id: ObjectId(),
lines: ["wombat", "potato", "banana"] lines: ["wombat", "potato", "banana"],
rev: 2 rev: 2
}, { }, {
_id: ObjectId() _id: ObjectId(),
lines: ["llama", "turnip", "apple"] lines: ["llama", "turnip", "apple"],
rev: 4 rev: 4
}, { }, {
_id: ObjectId() _id: ObjectId(),
lines: ["elephant", "swede", "nectarine"] lines: ["elephant", "swede", "nectarine"],
rev: 6 rev: 6
}] }];
@mixedDocs = @archivedDocs.concat(@unarchivedDocs) this.mixedDocs = this.archivedDocs.concat(this.unarchivedDocs);
@MongoManager = this.MongoManager = {
markDocAsArchived: sinon.stub().callsArgWith(2, null) markDocAsArchived: sinon.stub().callsArgWith(2, null),
upsertIntoDocCollection: sinon.stub().callsArgWith(3, null) upsertIntoDocCollection: sinon.stub().callsArgWith(3, null),
getProjectsDocs: sinon.stub().callsArgWith(3, null, @mongoDocs) getProjectsDocs: sinon.stub().callsArgWith(3, null, this.mongoDocs),
getArchivedProjectDocs: sinon.stub().callsArgWith(2, null, @mongoDocs) getArchivedProjectDocs: sinon.stub().callsArgWith(2, null, this.mongoDocs)
};
@requires = this.requires = {
"settings-sharelatex": @settings "settings-sharelatex": this.settings,
"./MongoManager": @MongoManager "./MongoManager": this.MongoManager,
"request": @request "request": this.request,
"./RangeManager": @RangeManager = {} "./RangeManager": (this.RangeManager = {}),
"logger-sharelatex": "logger-sharelatex": {
log:-> log() {},
err:-> err() {}
@globals = }
JSON: JSON };
this.globals =
{JSON};
@error = "my errror" this.error = "my errror";
@project_id = ObjectId().toString() this.project_id = ObjectId().toString();
@stubbedError = new Errors.NotFoundError("Error in S3 request") this.stubbedError = new Errors.NotFoundError("Error in S3 request");
@DocArchiveManager = SandboxedModule.require modulePath, requires: @requires, globals: @globals return this.DocArchiveManager = SandboxedModule.require(modulePath, {requires: this.requires, globals: this.globals});
});
describe "archiveDoc", -> describe("archiveDoc", function() {
it "should use correct options", (done)-> it("should use correct options", function(done){
@request.put = sinon.stub().callsArgWith(1, null, {statusCode:200,headers:{etag:""}}) this.request.put = sinon.stub().callsArgWith(1, null, {statusCode:200,headers:{etag:""}});
@DocArchiveManager.archiveDoc @project_id, @mongoDocs[0], (err)=> return this.DocArchiveManager.archiveDoc(this.project_id, this.mongoDocs[0], err=> {
opts = @request.put.args[0][0] const opts = this.request.put.args[0][0];
assert.deepEqual(opts.aws, {key:@settings.docstore.s3.key, secret:@settings.docstore.s3.secret, bucket:@settings.docstore.s3.bucket}) assert.deepEqual(opts.aws, {key:this.settings.docstore.s3.key, secret:this.settings.docstore.s3.secret, bucket:this.settings.docstore.s3.bucket});
opts.body.should.equal JSON.stringify( opts.body.should.equal(JSON.stringify({
lines: @mongoDocs[0].lines lines: this.mongoDocs[0].lines,
ranges: @mongoDocs[0].ranges ranges: this.mongoDocs[0].ranges,
schema_v: 1 schema_v: 1
) })
opts.timeout.should.equal (30*1000) );
opts.uri.should.equal "https://#{@settings.docstore.s3.bucket}.s3.amazonaws.com/#{@project_id}/#{@mongoDocs[0]._id}" opts.timeout.should.equal((30*1000));
done() opts.uri.should.equal(`https://${this.settings.docstore.s3.bucket}.s3.amazonaws.com/${this.project_id}/${this.mongoDocs[0]._id}`);
return done();
});
});
it "should return no md5 error", (done)-> it("should return no md5 error", function(done){
data = JSON.stringify( const data = JSON.stringify({
lines: @mongoDocs[0].lines lines: this.mongoDocs[0].lines,
ranges: @mongoDocs[0].ranges ranges: this.mongoDocs[0].ranges,
schema_v: 1 schema_v: 1
) });
@md5 = crypto.createHash("md5").update(data).digest("hex") this.md5 = crypto.createHash("md5").update(data).digest("hex");
@request.put = sinon.stub().callsArgWith(1, null, {statusCode:200,headers:{etag:@md5}}) this.request.put = sinon.stub().callsArgWith(1, null, {statusCode:200,headers:{etag:this.md5}});
@DocArchiveManager.archiveDoc @project_id, @mongoDocs[0], (err)=> return this.DocArchiveManager.archiveDoc(this.project_id, this.mongoDocs[0], err=> {
should.not.exist err should.not.exist(err);
done() return done();
});
});
it "should return the error", (done)-> return it("should return the error", function(done){
@request.put = sinon.stub().callsArgWith(1, @stubbedError, {statusCode:400,headers:{etag:""}}) this.request.put = sinon.stub().callsArgWith(1, this.stubbedError, {statusCode:400,headers:{etag:""}});
@DocArchiveManager.archiveDoc @project_id, @mongoDocs[0], (err)=> return this.DocArchiveManager.archiveDoc(this.project_id, this.mongoDocs[0], err=> {
should.exist err should.exist(err);
done() return done();
});
});
});
describe "unarchiveDoc", -> describe("unarchiveDoc", function() {
it "should use correct options", (done)-> it("should use correct options", function(done){
@request.get = sinon.stub().callsArgWith(1, null, statusCode:200, @mongoDocs[0].lines) this.request.get = sinon.stub().callsArgWith(1, null, {statusCode:200}, this.mongoDocs[0].lines);
@request.del = sinon.stub().callsArgWith(1, null, statusCode:204, {}) this.request.del = sinon.stub().callsArgWith(1, null, {statusCode:204}, {});
@DocArchiveManager.unarchiveDoc @project_id, @mongoDocs[0]._id, (err)=> return this.DocArchiveManager.unarchiveDoc(this.project_id, this.mongoDocs[0]._id, err=> {
opts = @request.get.args[0][0] const opts = this.request.get.args[0][0];
assert.deepEqual(opts.aws, {key:@settings.docstore.s3.key, secret:@settings.docstore.s3.secret, bucket:@settings.docstore.s3.bucket}) assert.deepEqual(opts.aws, {key:this.settings.docstore.s3.key, secret:this.settings.docstore.s3.secret, bucket:this.settings.docstore.s3.bucket});
opts.json.should.equal true opts.json.should.equal(true);
opts.timeout.should.equal (30*1000) opts.timeout.should.equal((30*1000));
opts.uri.should.equal "https://#{@settings.docstore.s3.bucket}.s3.amazonaws.com/#{@project_id}/#{@mongoDocs[0]._id}" opts.uri.should.equal(`https://${this.settings.docstore.s3.bucket}.s3.amazonaws.com/${this.project_id}/${this.mongoDocs[0]._id}`);
done() return done();
});
});
it "should return the error", (done)-> it("should return the error", function(done){
@request.get = sinon.stub().callsArgWith(1, @stubbedError, {}, {}) this.request.get = sinon.stub().callsArgWith(1, this.stubbedError, {}, {});
@DocArchiveManager.unarchiveDoc @project_id, @mongoDocs[0], (err)=> return this.DocArchiveManager.unarchiveDoc(this.project_id, this.mongoDocs[0], err=> {
should.exist err should.exist(err);
done() return done();
});
});
it "should error if the doc lines are a string not an array", (done)-> return it("should error if the doc lines are a string not an array", function(done){
@request.get = sinon.stub().callsArgWith(1, null, statusCode:200, "this is a string") this.request.get = sinon.stub().callsArgWith(1, null, {statusCode:200}, "this is a string");
@request.del = sinon.stub() this.request.del = sinon.stub();
@DocArchiveManager.unarchiveDoc @project_id, @mongoDocs[0], (err)=> return this.DocArchiveManager.unarchiveDoc(this.project_id, this.mongoDocs[0], err=> {
should.exist err should.exist(err);
@request.del.called.should.equal false this.request.del.called.should.equal(false);
done() return done();
});
});
});
describe "archiveAllDocs", -> describe("archiveAllDocs", function() {
it "should archive all project docs which are not in s3", (done)-> it("should archive all project docs which are not in s3", function(done){
@MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, @mongoDocs) this.MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, this.mongoDocs);
@DocArchiveManager.archiveDoc = sinon.stub().callsArgWith(2, null) this.DocArchiveManager.archiveDoc = sinon.stub().callsArgWith(2, null);
@DocArchiveManager.archiveAllDocs @project_id, (err)=> return this.DocArchiveManager.archiveAllDocs(this.project_id, err=> {
@DocArchiveManager.archiveDoc.calledWith(@project_id, @mongoDocs[0]).should.equal true this.DocArchiveManager.archiveDoc.calledWith(this.project_id, this.mongoDocs[0]).should.equal(true);
@DocArchiveManager.archiveDoc.calledWith(@project_id, @mongoDocs[1]).should.equal true this.DocArchiveManager.archiveDoc.calledWith(this.project_id, this.mongoDocs[1]).should.equal(true);
@DocArchiveManager.archiveDoc.calledWith(@project_id, @mongoDocs[4]).should.equal true this.DocArchiveManager.archiveDoc.calledWith(this.project_id, this.mongoDocs[4]).should.equal(true);
@DocArchiveManager.archiveDoc.calledWith(@project_id, @mongoDocs[2]).should.equal false this.DocArchiveManager.archiveDoc.calledWith(this.project_id, this.mongoDocs[2]).should.equal(false);
@DocArchiveManager.archiveDoc.calledWith(@project_id, @mongoDocs[3]).should.equal false this.DocArchiveManager.archiveDoc.calledWith(this.project_id, this.mongoDocs[3]).should.equal(false);
should.not.exist err should.not.exist(err);
done() return done();
});
});
it "should return error if have no docs", (done)-> it("should return error if have no docs", function(done){
@MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, null) this.MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, null);
@DocArchiveManager.archiveAllDocs @project_id, (err)=> return this.DocArchiveManager.archiveAllDocs(this.project_id, err=> {
should.exist err should.exist(err);
done() return done();
});
});
it "should return the error", (done)-> it("should return the error", function(done){
@MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, @error, null) this.MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, this.error, null);
@DocArchiveManager.archiveAllDocs @project_id, (err)=> return this.DocArchiveManager.archiveAllDocs(this.project_id, err=> {
err.should.equal @error err.should.equal(this.error);
done() return done();
});
});
describe "when most have been already put in s3", -> return describe("when most have been already put in s3", function() {
beforeEach -> beforeEach(function() {
numberOfDocs = 10 * 1000 let numberOfDocs = 10 * 1000;
@mongoDocs = [] this.mongoDocs = [];
while --numberOfDocs != 0 while (--numberOfDocs !== 0) {
@mongoDocs.push({inS3:true, _id: ObjectId()}) this.mongoDocs.push({inS3:true, _id: ObjectId()});
}
@MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, @mongoDocs) this.MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, this.mongoDocs);
@DocArchiveManager.archiveDoc = sinon.stub().callsArgWith(2, null) return this.DocArchiveManager.archiveDoc = sinon.stub().callsArgWith(2, null);
});
it "should not throw and error", (done)-> return it("should not throw and error", function(done){
@DocArchiveManager.archiveAllDocs @project_id, (err)=> return this.DocArchiveManager.archiveAllDocs(this.project_id, err=> {
should.not.exist err should.not.exist(err);
done() return done();
});
});
});
});
describe "unArchiveAllDocs", -> describe("unArchiveAllDocs", function() {
it "should unarchive all inS3 docs", (done)-> it("should unarchive all inS3 docs", function(done){
@MongoManager.getArchivedProjectDocs = sinon.stub().callsArgWith(1, null, @archivedDocs) this.MongoManager.getArchivedProjectDocs = sinon.stub().callsArgWith(1, null, this.archivedDocs);
@DocArchiveManager.unarchiveDoc = sinon.stub().callsArgWith(2, null) this.DocArchiveManager.unarchiveDoc = sinon.stub().callsArgWith(2, null);
@DocArchiveManager.unArchiveAllDocs @project_id, (err)=> return this.DocArchiveManager.unArchiveAllDocs(this.project_id, err=> {
for doc in @archivedDocs for (let doc of Array.from(this.archivedDocs)) {
@DocArchiveManager.unarchiveDoc.calledWith(@project_id, doc._id).should.equal true this.DocArchiveManager.unarchiveDoc.calledWith(this.project_id, doc._id).should.equal(true);
should.not.exist err }
done() should.not.exist(err);
return done();
});
});
it "should return error if have no docs", (done)-> it("should return error if have no docs", function(done){
@MongoManager.getArchivedProjectDocs = sinon.stub().callsArgWith(1, null, null) this.MongoManager.getArchivedProjectDocs = sinon.stub().callsArgWith(1, null, null);
@DocArchiveManager.unArchiveAllDocs @project_id, (err)=> return this.DocArchiveManager.unArchiveAllDocs(this.project_id, err=> {
should.exist err should.exist(err);
done() return done();
});
});
it "should return the error", (done)-> return it("should return the error", function(done){
@MongoManager.getArchivedProjectDocs = sinon.stub().callsArgWith(1, @error, null) this.MongoManager.getArchivedProjectDocs = sinon.stub().callsArgWith(1, this.error, null);
@DocArchiveManager.unArchiveAllDocs @project_id, (err)=> return this.DocArchiveManager.unArchiveAllDocs(this.project_id, err=> {
err.should.equal @error err.should.equal(this.error);
done() return done();
});
});
});
describe "destroyAllDocs", -> describe("destroyAllDocs", function() {
beforeEach -> beforeEach(function() {
@request.del = sinon.stub().callsArgWith(1, null, statusCode:204, {}) this.request.del = sinon.stub().callsArgWith(1, null, {statusCode:204}, {});
@MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, @mixedDocs) this.MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, this.mixedDocs);
@MongoManager.findDoc = sinon.stub().callsArgWith(3, null, null) this.MongoManager.findDoc = sinon.stub().callsArgWith(3, null, null);
@MongoManager.destroyDoc = sinon.stub().yields() this.MongoManager.destroyDoc = sinon.stub().yields();
for doc in @mixedDocs return Array.from(this.mixedDocs).map((doc) =>
@MongoManager.findDoc.withArgs(@project_id, doc._id).callsArgWith(3, null, doc) this.MongoManager.findDoc.withArgs(this.project_id, doc._id).callsArgWith(3, null, doc));
});
it "should destroy all the docs", (done)-> it("should destroy all the docs", function(done){
@DocArchiveManager.destroyDoc = sinon.stub().callsArgWith(2, null) this.DocArchiveManager.destroyDoc = sinon.stub().callsArgWith(2, null);
@DocArchiveManager.destroyAllDocs @project_id, (err)=> return this.DocArchiveManager.destroyAllDocs(this.project_id, err=> {
for doc in @mixedDocs for (let doc of Array.from(this.mixedDocs)) {
@DocArchiveManager.destroyDoc.calledWith(@project_id, doc._id).should.equal true this.DocArchiveManager.destroyDoc.calledWith(this.project_id, doc._id).should.equal(true);
should.not.exist err }
done() should.not.exist(err);
return done();
});
});
it "should only the s3 docs from s3", (done)-> it("should only the s3 docs from s3", function(done){
docOpts = (doc) => const docOpts = doc => {
JSON.parse(JSON.stringify({ return JSON.parse(JSON.stringify({
aws: {key:@settings.docstore.s3.key, secret:@settings.docstore.s3.secret, bucket:@settings.docstore.s3.bucket}, aws: {key:this.settings.docstore.s3.key, secret:this.settings.docstore.s3.secret, bucket:this.settings.docstore.s3.bucket},
json: true, json: true,
timeout: 30 * 1000 timeout: 30 * 1000,
uri:"https://#{@settings.docstore.s3.bucket}.s3.amazonaws.com/#{@project_id}/#{doc._id}" uri:`https://${this.settings.docstore.s3.bucket}.s3.amazonaws.com/${this.project_id}/${doc._id}`
})) }));
};
@DocArchiveManager.destroyAllDocs @project_id, (err)=> return this.DocArchiveManager.destroyAllDocs(this.project_id, err=> {
expect(err).not.to.exist let doc;
expect(err).not.to.exist;
for doc in @archivedDocs for (doc of Array.from(this.archivedDocs)) {
sinon.assert.calledWith(@request.del, docOpts(doc)) sinon.assert.calledWith(this.request.del, docOpts(doc));
for doc in @unarchivedDocs }
expect(@request.del.calledWith(docOpts(doc))).to.equal false # no notCalledWith for (doc of Array.from(this.unarchivedDocs)) {
expect(this.request.del.calledWith(docOpts(doc))).to.equal(false);
} // no notCalledWith
done() return done();
});
});
it "should remove the docs from mongo", (done)-> return it("should remove the docs from mongo", function(done){
@DocArchiveManager.destroyAllDocs @project_id, (err)=> this.DocArchiveManager.destroyAllDocs(this.project_id, err=> {
expect(err).not.to.exist return expect(err).not.to.exist;
});
for doc in @mixedDocs for (let doc of Array.from(this.mixedDocs)) {
sinon.assert.calledWith(@MongoManager.destroyDoc, doc._id) sinon.assert.calledWith(this.MongoManager.destroyDoc, doc._id);
}
done() return done();
});
});
describe "_s3DocToMongoDoc", -> describe("_s3DocToMongoDoc", function() {
describe "with the old schema", -> describe("with the old schema", () => it("should return the docs lines", function(done) {
it "should return the docs lines", (done) -> return this.DocArchiveManager._s3DocToMongoDoc(["doc", "lines"], function(error, doc) {
@DocArchiveManager._s3DocToMongoDoc ["doc", "lines"], (error, doc) -> expect(doc).to.deep.equal({
expect(doc).to.deep.equal { lines: ["doc", "lines"]
lines: ["doc", "lines"] });
} return done();
done() });
}));
describe "with the new schema", -> describe("with the new schema", function() {
it "should return the doc lines and ranges", (done) -> it("should return the doc lines and ranges", function(done) {
@RangeManager.jsonRangesToMongo = sinon.stub().returns {"mongo": "ranges"} this.RangeManager.jsonRangesToMongo = sinon.stub().returns({"mongo": "ranges"});
@DocArchiveManager._s3DocToMongoDoc { return this.DocArchiveManager._s3DocToMongoDoc({
lines: ["doc", "lines"] lines: ["doc", "lines"],
ranges: {"json": "ranges"} ranges: {"json": "ranges"},
schema_v: 1 schema_v: 1
}, (error, doc) -> }, function(error, doc) {
expect(doc).to.deep.equal { expect(doc).to.deep.equal({
lines: ["doc", "lines"] lines: ["doc", "lines"],
ranges: {"mongo": "ranges"} ranges: {"mongo": "ranges"}
} });
done() return done();
});
});
it "should return just the doc lines when there are no ranges", (done) -> return it("should return just the doc lines when there are no ranges", function(done) {
@DocArchiveManager._s3DocToMongoDoc { return this.DocArchiveManager._s3DocToMongoDoc({
lines: ["doc", "lines"] lines: ["doc", "lines"],
schema_v: 1 schema_v: 1
}, (error, doc) -> }, function(error, doc) {
expect(doc).to.deep.equal { expect(doc).to.deep.equal({
lines: ["doc", "lines"] lines: ["doc", "lines"]
} });
done() return done();
});
});
});
describe "with an unrecognised schema", -> return describe("with an unrecognised schema", () => it("should return an error", function(done) {
it "should return an error", (done) -> return this.DocArchiveManager._s3DocToMongoDoc({
@DocArchiveManager._s3DocToMongoDoc { schema_v: 2
schema_v: 2 }, function(error, doc) {
}, (error, doc) -> expect(error).to.exist;
expect(error).to.exist return done();
done() });
}));
});
describe "_mongoDocToS3Doc", -> return describe("_mongoDocToS3Doc", function() {
describe "with a valid doc", -> describe("with a valid doc", () => it("should return the json version", function(done) {
it "should return the json version", (done) -> let doc;
@DocArchiveManager._mongoDocToS3Doc doc = { return this.DocArchiveManager._mongoDocToS3Doc((doc = {
lines: ["doc", "lines"] lines: ["doc", "lines"],
ranges: { "mock": "ranges" } ranges: { "mock": "ranges" }
}, (err, s3_doc) -> }), function(err, s3_doc) {
expect(s3_doc).to.equal JSON.stringify({ expect(s3_doc).to.equal(JSON.stringify({
lines: ["doc", "lines"] lines: ["doc", "lines"],
ranges: { "mock": "ranges" } ranges: { "mock": "ranges" },
schema_v: 1 schema_v: 1
}) })
done() );
return done();
});
}));
describe "with null bytes in the result", -> describe("with null bytes in the result", function() {
beforeEach -> beforeEach(function() {
@_stringify = JSON.stringify this._stringify = JSON.stringify;
JSON.stringify = sinon.stub().returns '{"bad": "\u0000"}' return JSON.stringify = sinon.stub().returns('{"bad": "\u0000"}');
});
afterEach -> afterEach(function() {
JSON.stringify = @_stringify return JSON.stringify = this._stringify;
});
it "should return an error", (done) -> return it("should return an error", function(done) {
@DocArchiveManager._mongoDocToS3Doc { return this.DocArchiveManager._mongoDocToS3Doc({
lines: ["doc", "lines"] lines: ["doc", "lines"],
ranges: { "mock": "ranges" } ranges: { "mock": "ranges" }
}, (err, s3_doc) -> }, function(err, s3_doc) {
expect(err).to.exist expect(err).to.exist;
done() return done();
});
});
});
describe "without doc lines", -> return describe("without doc lines", () => it("should return an error", function(done) {
it "should return an error", (done) -> return this.DocArchiveManager._mongoDocToS3Doc({}, function(err, s3_doc) {
@DocArchiveManager._mongoDocToS3Doc {}, (err, s3_doc) -> expect(err).to.exist;
expect(err).to.exist return done();
done() });
}));
});
});

View file

@ -1,407 +1,537 @@
SandboxedModule = require('sandboxed-module') /*
sinon = require('sinon') * decaffeinate suggestions:
chai = require('chai') * DS102: Remove unnecessary code created because of implicit returns
assert = require("chai").assert * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
chai.should() */
expect = chai.expect const SandboxedModule = require('sandboxed-module');
modulePath = require('path').join __dirname, '../../../app/js/DocManager' const sinon = require('sinon');
ObjectId = require("mongojs").ObjectId const chai = require('chai');
Errors = require "../../../app/js/Errors" const {
assert
} = require("chai");
chai.should();
const {
expect
} = chai;
const modulePath = require('path').join(__dirname, '../../../app/js/DocManager');
const {
ObjectId
} = require("mongojs");
const Errors = require("../../../app/js/Errors");
describe "DocManager", -> describe("DocManager", function() {
beforeEach -> beforeEach(function() {
@DocManager = SandboxedModule.require modulePath, requires: this.DocManager = SandboxedModule.require(modulePath, { requires: {
"./MongoManager": @MongoManager = {} "./MongoManager": (this.MongoManager = {}),
"./DocArchiveManager": @DocArchiveManager = {} "./DocArchiveManager": (this.DocArchiveManager = {}),
"./RangeManager": @RangeManager = { "./RangeManager": (this.RangeManager = {
jsonRangesToMongo: (r) -> r jsonRangesToMongo(r) { return r; },
shouldUpdateRanges: sinon.stub().returns false shouldUpdateRanges: sinon.stub().returns(false)
} }),
"logger-sharelatex": @logger = "logger-sharelatex": (this.logger = {
log: sinon.stub() log: sinon.stub(),
warn:-> warn() {},
err:-> err() {}
@doc_id = ObjectId().toString() })
@project_id = ObjectId().toString() }
@another_project_id = ObjectId().toString() }
@callback = sinon.stub() );
@stubbedError = new Error("blew up") this.doc_id = ObjectId().toString();
this.project_id = ObjectId().toString();
this.another_project_id = ObjectId().toString();
this.callback = sinon.stub();
return this.stubbedError = new Error("blew up");
});
describe "checkDocExists", -> describe("checkDocExists", function() {
beforeEach -> beforeEach(function() {
@DocManager._getDoc = sinon.stub() return this.DocManager._getDoc = sinon.stub();
});
it "should call get doc with a quick filter", (done)-> it("should call get doc with a quick filter", function(done){
@DocManager._getDoc.callsArgWith(3, null, {_id:@doc_id}) this.DocManager._getDoc.callsArgWith(3, null, {_id:this.doc_id});
@DocManager.checkDocExists @project_id, @doc_id, (err, exist)=> return this.DocManager.checkDocExists(this.project_id, this.doc_id, (err, exist)=> {
exist.should.equal true exist.should.equal(true);
@DocManager._getDoc.calledWith(@project_id, @doc_id, {_id:1, inS3:true}).should.equal true this.DocManager._getDoc.calledWith(this.project_id, this.doc_id, {_id:1, inS3:true}).should.equal(true);
done() return done();
});
});
it "should return false when doc is not there", (done)-> it("should return false when doc is not there", function(done){
@DocManager._getDoc.callsArgWith(3, null) this.DocManager._getDoc.callsArgWith(3, null);
@DocManager.checkDocExists @project_id, @doc_id, (err, exist)=> return this.DocManager.checkDocExists(this.project_id, this.doc_id, (err, exist)=> {
exist.should.equal false exist.should.equal(false);
done() return done();
});
});
it "should return error when get doc errors", (done)-> return it("should return error when get doc errors", function(done){
@DocManager._getDoc.callsArgWith(3, "error") this.DocManager._getDoc.callsArgWith(3, "error");
@DocManager.checkDocExists @project_id, @doc_id, (err, exist)=> return this.DocManager.checkDocExists(this.project_id, this.doc_id, (err, exist)=> {
err.should.equal "error" err.should.equal("error");
done() return done();
});
});
});
describe "getFullDoc", -> describe("getFullDoc", function() {
beforeEach -> beforeEach(function() {
@DocManager._getDoc = sinon.stub() this.DocManager._getDoc = sinon.stub();
@doc = return this.doc = {
_id: @doc_id _id: this.doc_id,
lines:["2134"] lines:["2134"]
};});
it "should call get doc with a quick filter", (done)-> it("should call get doc with a quick filter", function(done){
@DocManager._getDoc.callsArgWith(3, null, @doc) this.DocManager._getDoc.callsArgWith(3, null, this.doc);
@DocManager.getFullDoc @project_id, @doc_id, (err, doc)=> return this.DocManager.getFullDoc(this.project_id, this.doc_id, (err, doc)=> {
doc.should.equal @doc doc.should.equal(this.doc);
@DocManager._getDoc.calledWith(@project_id, @doc_id, {lines: true, rev: true, deleted: true, version: true, ranges: true, inS3:true}).should.equal true this.DocManager._getDoc.calledWith(this.project_id, this.doc_id, {lines: true, rev: true, deleted: true, version: true, ranges: true, inS3:true}).should.equal(true);
done() return done();
});
});
it "should return error when get doc errors", (done)-> return it("should return error when get doc errors", function(done){
@DocManager._getDoc.callsArgWith(3, "error") this.DocManager._getDoc.callsArgWith(3, "error");
@DocManager.getFullDoc @project_id, @doc_id, (err, exist)=> return this.DocManager.getFullDoc(this.project_id, this.doc_id, (err, exist)=> {
err.should.equal "error" err.should.equal("error");
done() return done();
});
});
});
describe "getRawDoc", -> describe("getRawDoc", function() {
beforeEach -> beforeEach(function() {
@DocManager._getDoc = sinon.stub() this.DocManager._getDoc = sinon.stub();
@doc = return this.doc =
lines:["2134"] {lines:["2134"]};});
it "should call get doc with a quick filter", (done)-> it("should call get doc with a quick filter", function(done){
@DocManager._getDoc.callsArgWith(3, null, @doc) this.DocManager._getDoc.callsArgWith(3, null, this.doc);
@DocManager.getDocLines @project_id, @doc_id, (err, doc)=> return this.DocManager.getDocLines(this.project_id, this.doc_id, (err, doc)=> {
doc.should.equal @doc doc.should.equal(this.doc);
@DocManager._getDoc.calledWith(@project_id, @doc_id, {lines: true, inS3:true}).should.equal true this.DocManager._getDoc.calledWith(this.project_id, this.doc_id, {lines: true, inS3:true}).should.equal(true);
done() return done();
});
});
it "should return error when get doc errors", (done)-> return it("should return error when get doc errors", function(done){
@DocManager._getDoc.callsArgWith(3, "error") this.DocManager._getDoc.callsArgWith(3, "error");
@DocManager.getDocLines @project_id, @doc_id, (err, exist)=> return this.DocManager.getDocLines(this.project_id, this.doc_id, (err, exist)=> {
err.should.equal "error" err.should.equal("error");
done() return done();
});
});
});
describe "getDoc", -> describe("getDoc", function() {
beforeEach -> beforeEach(function() {
@project = { name: "mock-project" } this.project = { name: "mock-project" };
@doc = { _id: @doc_id, project_id: @project_id, lines: ["mock-lines"] } this.doc = { _id: this.doc_id, project_id: this.project_id, lines: ["mock-lines"] };
@version = 42 this.version = 42;
@MongoManager.findDoc = sinon.stub() this.MongoManager.findDoc = sinon.stub();
@MongoManager.getDocVersion = sinon.stub().yields(null, @version) return this.MongoManager.getDocVersion = sinon.stub().yields(null, this.version);
});
describe "when using a filter", -> describe("when using a filter", function() {
beforeEach -> beforeEach(function() {
@MongoManager.findDoc.yields(null, @doc) return this.MongoManager.findDoc.yields(null, this.doc);
});
it "should error if inS3 is not set to true", (done)-> it("should error if inS3 is not set to true", function(done){
@DocManager._getDoc @project_id, @doc_id, {inS3: false}, (err)-> return this.DocManager._getDoc(this.project_id, this.doc_id, {inS3: false}, function(err){
expect(err).to.exist expect(err).to.exist;
done() return done();
});
});
it "should always get inS3 even when no filter is passed", (done)-> it("should always get inS3 even when no filter is passed", function(done){
@DocManager._getDoc @project_id, @doc_id, undefined, (err)=> return this.DocManager._getDoc(this.project_id, this.doc_id, undefined, err=> {
@MongoManager.findDoc.called.should.equal false this.MongoManager.findDoc.called.should.equal(false);
expect(err).to.exist expect(err).to.exist;
done() return done();
});
});
it "should not error if inS3 is set to true", (done)-> return it("should not error if inS3 is set to true", function(done){
@DocManager._getDoc @project_id, @doc_id, {inS3: true}, (err)-> return this.DocManager._getDoc(this.project_id, this.doc_id, {inS3: true}, function(err){
expect(err).to.not.exist expect(err).to.not.exist;
done() return done();
});
});
});
describe "when the doc is in the doc collection", -> describe("when the doc is in the doc collection", function() {
beforeEach -> beforeEach(function() {
@MongoManager.findDoc.yields(null, @doc) this.MongoManager.findDoc.yields(null, this.doc);
@DocManager._getDoc @project_id, @doc_id, {version: true, inS3:true}, @callback return this.DocManager._getDoc(this.project_id, this.doc_id, {version: true, inS3:true}, this.callback);
});
it "should get the doc from the doc collection", -> it("should get the doc from the doc collection", function() {
@MongoManager.findDoc return this.MongoManager.findDoc
.calledWith(@project_id, @doc_id) .calledWith(this.project_id, this.doc_id)
.should.equal true .should.equal(true);
});
it "should get the doc version from the docOps collection", -> it("should get the doc version from the docOps collection", function() {
@MongoManager.getDocVersion return this.MongoManager.getDocVersion
.calledWith(@doc_id) .calledWith(this.doc_id)
.should.equal true .should.equal(true);
});
it "should return the callback with the doc with the version", -> return it("should return the callback with the doc with the version", function() {
@callback.called.should.equal true this.callback.called.should.equal(true);
doc = @callback.args[0][1] const doc = this.callback.args[0][1];
doc.lines.should.equal @doc.lines doc.lines.should.equal(this.doc.lines);
doc.version.should.equal @version return doc.version.should.equal(this.version);
});
});
describe "without the version filter", -> describe("without the version filter", function() {
beforeEach -> beforeEach(function() {
@MongoManager.findDoc.yields(null, @doc) this.MongoManager.findDoc.yields(null, this.doc);
@DocManager._getDoc @project_id, @doc_id, {version: false, inS3:true}, @callback return this.DocManager._getDoc(this.project_id, this.doc_id, {version: false, inS3:true}, this.callback);
});
it "should not get the doc version from the docOps collection", -> return it("should not get the doc version from the docOps collection", function() {
@MongoManager.getDocVersion.called.should.equal false return this.MongoManager.getDocVersion.called.should.equal(false);
});
});
describe "when MongoManager.findDoc errors", -> describe("when MongoManager.findDoc errors", function() {
beforeEach -> beforeEach(function() {
@MongoManager.findDoc.yields(@stubbedError) this.MongoManager.findDoc.yields(this.stubbedError);
@DocManager._getDoc @project_id, @doc_id, {version: true, inS3:true}, @callback return this.DocManager._getDoc(this.project_id, this.doc_id, {version: true, inS3:true}, this.callback);
});
it "should return the error", -> return it("should return the error", function() {
@callback.calledWith(@stubbedError).should.equal true return this.callback.calledWith(this.stubbedError).should.equal(true);
});
});
describe "when the doc is archived", -> describe("when the doc is archived", function() {
beforeEach -> beforeEach(function() {
@doc = { _id: @doc_id, project_id: @project_id, lines: ["mock-lines"], inS3: true } this.doc = { _id: this.doc_id, project_id: this.project_id, lines: ["mock-lines"], inS3: true };
@MongoManager.findDoc.yields(null, @doc) this.MongoManager.findDoc.yields(null, this.doc);
@DocArchiveManager.unarchiveDoc = (project_id, doc_id, callback) => this.DocArchiveManager.unarchiveDoc = (project_id, doc_id, callback) => {
@doc.inS3 = false this.doc.inS3 = false;
callback() return callback();
sinon.spy @DocArchiveManager, "unarchiveDoc" };
@DocManager._getDoc @project_id, @doc_id, {version: true, inS3:true}, @callback sinon.spy(this.DocArchiveManager, "unarchiveDoc");
return this.DocManager._getDoc(this.project_id, this.doc_id, {version: true, inS3:true}, this.callback);
});
it "should call the DocArchive to unarchive the doc", -> it("should call the DocArchive to unarchive the doc", function() {
@DocArchiveManager.unarchiveDoc.calledWith(@project_id, @doc_id).should.equal true return this.DocArchiveManager.unarchiveDoc.calledWith(this.project_id, this.doc_id).should.equal(true);
});
it "should look up the doc twice", -> it("should look up the doc twice", function() {
@MongoManager.findDoc.calledTwice.should.equal true return this.MongoManager.findDoc.calledTwice.should.equal(true);
});
it "should return the doc", -> return it("should return the doc", function() {
@callback.calledWith(null, @doc).should.equal true return this.callback.calledWith(null, this.doc).should.equal(true);
});
});
describe "when the doc does not exist in the docs collection", -> return describe("when the doc does not exist in the docs collection", function() {
beforeEach -> beforeEach(function() {
@MongoManager.findDoc = sinon.stub().yields(null, null) this.MongoManager.findDoc = sinon.stub().yields(null, null);
@DocManager._getDoc @project_id, @doc_id, {version: true, inS3:true}, @callback return this.DocManager._getDoc(this.project_id, this.doc_id, {version: true, inS3:true}, this.callback);
});
it "should return a NotFoundError", -> return it("should return a NotFoundError", function() {
@callback return this.callback
.calledWith(sinon.match.has('message', "No such doc: #{@doc_id} in project #{@project_id}")) .calledWith(sinon.match.has('message', `No such doc: ${this.doc_id} in project ${this.project_id}`))
.should.equal true .should.equal(true);
});
});
});
describe "getAllNonDeletedDocs", -> describe("getAllNonDeletedDocs", function() {
describe "when the project exists", -> describe("when the project exists", function() {
beforeEach -> beforeEach(function() {
@docs = [{ _id: @doc_id, project_id: @project_id, lines: ["mock-lines"] }] this.docs = [{ _id: this.doc_id, project_id: this.project_id, lines: ["mock-lines"] }];
@MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, @docs) this.MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, this.docs);
@DocArchiveManager.unArchiveAllDocs = sinon.stub().callsArgWith(1, null, @docs) this.DocArchiveManager.unArchiveAllDocs = sinon.stub().callsArgWith(1, null, this.docs);
@filter = { lines: true } this.filter = { lines: true };
@DocManager.getAllNonDeletedDocs @project_id, @filter, @callback return this.DocManager.getAllNonDeletedDocs(this.project_id, this.filter, this.callback);
});
it "should get the project from the database", -> it("should get the project from the database", function() {
@MongoManager.getProjectsDocs return this.MongoManager.getProjectsDocs
.calledWith(@project_id, {include_deleted: false}, @filter) .calledWith(this.project_id, {include_deleted: false}, this.filter)
.should.equal true .should.equal(true);
});
it "should return the docs", -> return it("should return the docs", function() {
@callback.calledWith(null, @docs).should.equal true return this.callback.calledWith(null, this.docs).should.equal(true);
});
});
describe "when there are no docs for the project", -> return describe("when there are no docs for the project", function() {
beforeEach -> beforeEach(function() {
@MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, null) this.MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, null);
@DocArchiveManager.unArchiveAllDocs = sinon.stub().callsArgWith(1, null) this.DocArchiveManager.unArchiveAllDocs = sinon.stub().callsArgWith(1, null);
@DocManager.getAllNonDeletedDocs @project_id, @filter, @callback return this.DocManager.getAllNonDeletedDocs(this.project_id, this.filter, this.callback);
});
it "should return a NotFoundError", -> return it("should return a NotFoundError", function() {
@callback return this.callback
.calledWith(sinon.match.has('message', "No docs for project #{@project_id}")) .calledWith(sinon.match.has('message', `No docs for project ${this.project_id}`))
.should.equal true .should.equal(true);
});
});
});
describe "deleteDoc", -> describe("deleteDoc", function() {
describe "when the doc exists", -> describe("when the doc exists", function() {
beforeEach -> beforeEach(function() {
@lines = ["mock", "doc", "lines"] this.lines = ["mock", "doc", "lines"];
@rev = 77 this.rev = 77;
@DocManager.checkDocExists = sinon.stub().callsArgWith(2, null, true) this.DocManager.checkDocExists = sinon.stub().callsArgWith(2, null, true);
@MongoManager.markDocAsDeleted = sinon.stub().callsArg(2) this.MongoManager.markDocAsDeleted = sinon.stub().callsArg(2);
@DocManager.deleteDoc @project_id, @doc_id, @callback return this.DocManager.deleteDoc(this.project_id, this.doc_id, this.callback);
});
it "should get the doc", -> it("should get the doc", function() {
@DocManager.checkDocExists return this.DocManager.checkDocExists
.calledWith(@project_id, @doc_id) .calledWith(this.project_id, this.doc_id)
.should.equal true .should.equal(true);
});
it "should mark doc as deleted", -> it("should mark doc as deleted", function() {
@MongoManager.markDocAsDeleted return this.MongoManager.markDocAsDeleted
.calledWith(@project_id, @doc_id) .calledWith(this.project_id, this.doc_id)
.should.equal true .should.equal(true);
});
it "should return the callback", -> return it("should return the callback", function() {
@callback.called.should.equal true return this.callback.called.should.equal(true);
});
});
describe "when the doc does not exist", -> return describe("when the doc does not exist", function() {
beforeEach -> beforeEach(function() {
@DocManager.checkDocExists = sinon.stub().callsArgWith(2, null, false) this.DocManager.checkDocExists = sinon.stub().callsArgWith(2, null, false);
@DocManager.deleteDoc @project_id, @doc_id, @callback return this.DocManager.deleteDoc(this.project_id, this.doc_id, this.callback);
});
it "should return a NotFoundError", -> return it("should return a NotFoundError", function() {
@callback return this.callback
.calledWith(sinon.match.has('message', "No such project/doc to delete: #{@project_id}/#{@doc_id}")) .calledWith(sinon.match.has('message', `No such project/doc to delete: ${this.project_id}/${this.doc_id}`))
.should.equal true .should.equal(true);
});
});
});
describe "updateDoc", -> return describe("updateDoc", function() {
beforeEach -> beforeEach(function() {
@oldDocLines = ["old", "doc", "lines"] this.oldDocLines = ["old", "doc", "lines"];
@newDocLines = ["new", "doc", "lines"] this.newDocLines = ["new", "doc", "lines"];
@originalRanges = { this.originalRanges = {
changes: [{ changes: [{
id: ObjectId().toString() id: ObjectId().toString(),
op: { i: "foo", p: 3 } op: { i: "foo", p: 3 },
meta: meta: {
user_id: ObjectId().toString() user_id: ObjectId().toString(),
ts: new Date().toString() ts: new Date().toString()
}
}] }]
} };
@newRanges = { this.newRanges = {
changes: [{ changes: [{
id: ObjectId().toString() id: ObjectId().toString(),
op: { i: "bar", p: 6 } op: { i: "bar", p: 6 },
meta: meta: {
user_id: ObjectId().toString() user_id: ObjectId().toString(),
ts: new Date().toString() ts: new Date().toString()
}
}] }]
} };
@version = 42 this.version = 42;
@doc = { _id: @doc_id, project_id: @project_id, lines: @oldDocLines, rev: @rev = 5, version: @version, ranges: @originalRanges } this.doc = { _id: this.doc_id, project_id: this.project_id, lines: this.oldDocLines, rev: (this.rev = 5), version: this.version, ranges: this.originalRanges };
@MongoManager.upsertIntoDocCollection = sinon.stub().callsArg(3) this.MongoManager.upsertIntoDocCollection = sinon.stub().callsArg(3);
@MongoManager.setDocVersion = sinon.stub().yields() this.MongoManager.setDocVersion = sinon.stub().yields();
@DocManager._getDoc = sinon.stub() return this.DocManager._getDoc = sinon.stub();
});
describe "when only the doc lines have changed", -> describe("when only the doc lines have changed", function() {
beforeEach -> beforeEach(function() {
@DocManager._getDoc = sinon.stub().callsArgWith(3, null, @doc) this.DocManager._getDoc = sinon.stub().callsArgWith(3, null, this.doc);
@DocManager.updateDoc @project_id, @doc_id, @newDocLines, @version, @originalRanges, @callback return this.DocManager.updateDoc(this.project_id, this.doc_id, this.newDocLines, this.version, this.originalRanges, this.callback);
});
it "should get the existing doc", -> it("should get the existing doc", function() {
@DocManager._getDoc return this.DocManager._getDoc
.calledWith(@project_id, @doc_id, {version: true, rev: true, lines: true, version: true, ranges: true, inS3:true}) .calledWith(this.project_id, this.doc_id, {version: true, rev: true, lines: true, version: true, ranges: true, inS3:true})
.should.equal true .should.equal(true);
});
it "should upsert the document to the doc collection", -> it("should upsert the document to the doc collection", function() {
@MongoManager.upsertIntoDocCollection return this.MongoManager.upsertIntoDocCollection
.calledWith(@project_id, @doc_id, {lines: @newDocLines}) .calledWith(this.project_id, this.doc_id, {lines: this.newDocLines})
.should.equal true .should.equal(true);
});
it "should not update the version", -> it("should not update the version", function() {
@MongoManager.setDocVersion.called.should.equal false return this.MongoManager.setDocVersion.called.should.equal(false);
});
it "should return the callback with the new rev", -> return it("should return the callback with the new rev", function() {
@callback.calledWith(null, true, @rev + 1).should.equal true return this.callback.calledWith(null, true, this.rev + 1).should.equal(true);
});
});
describe "when the doc ranges have changed", -> describe("when the doc ranges have changed", function() {
beforeEach -> beforeEach(function() {
@DocManager._getDoc = sinon.stub().callsArgWith(3, null, @doc) this.DocManager._getDoc = sinon.stub().callsArgWith(3, null, this.doc);
@RangeManager.shouldUpdateRanges.returns true this.RangeManager.shouldUpdateRanges.returns(true);
@DocManager.updateDoc @project_id, @doc_id, @oldDocLines, @version, @newRanges, @callback return this.DocManager.updateDoc(this.project_id, this.doc_id, this.oldDocLines, this.version, this.newRanges, this.callback);
});
it "should upsert the ranges", -> it("should upsert the ranges", function() {
@MongoManager.upsertIntoDocCollection return this.MongoManager.upsertIntoDocCollection
.calledWith(@project_id, @doc_id, {ranges: @newRanges}) .calledWith(this.project_id, this.doc_id, {ranges: this.newRanges})
.should.equal true .should.equal(true);
});
it "should not update the version", -> it("should not update the version", function() {
@MongoManager.setDocVersion.called.should.equal false return this.MongoManager.setDocVersion.called.should.equal(false);
});
it "should return the callback with the new rev", -> return it("should return the callback with the new rev", function() {
@callback.calledWith(null, true, @rev + 1).should.equal true return this.callback.calledWith(null, true, this.rev + 1).should.equal(true);
});
});
describe "when only the version has changed", -> describe("when only the version has changed", function() {
beforeEach -> beforeEach(function() {
@DocManager._getDoc = sinon.stub().callsArgWith(3, null, @doc) this.DocManager._getDoc = sinon.stub().callsArgWith(3, null, this.doc);
@DocManager.updateDoc @project_id, @doc_id, @oldDocLines, @version + 1, @originalRanges, @callback return this.DocManager.updateDoc(this.project_id, this.doc_id, this.oldDocLines, this.version + 1, this.originalRanges, this.callback);
});
it "should not change the lines or ranges", -> it("should not change the lines or ranges", function() {
@MongoManager.upsertIntoDocCollection.called.should.equal false return this.MongoManager.upsertIntoDocCollection.called.should.equal(false);
});
it "should update the version", -> it("should update the version", function() {
@MongoManager.setDocVersion return this.MongoManager.setDocVersion
.calledWith(@doc_id, @version + 1) .calledWith(this.doc_id, this.version + 1)
.should.equal true .should.equal(true);
});
it "should return the callback with the old rev", -> return it("should return the callback with the old rev", function() {
@callback.calledWith(null, true, @rev).should.equal true return this.callback.calledWith(null, true, this.rev).should.equal(true);
});
});
describe "when the doc has not changed at all", -> describe("when the doc has not changed at all", function() {
beforeEach -> beforeEach(function() {
@DocManager._getDoc = sinon.stub().callsArgWith(3, null, @doc) this.DocManager._getDoc = sinon.stub().callsArgWith(3, null, this.doc);
@DocManager.updateDoc @project_id, @doc_id, @oldDocLines, @version, @originalRanges, @callback return this.DocManager.updateDoc(this.project_id, this.doc_id, this.oldDocLines, this.version, this.originalRanges, this.callback);
});
it "should not update the ranges or lines", -> it("should not update the ranges or lines", function() {
@MongoManager.upsertIntoDocCollection.called.should.equal false return this.MongoManager.upsertIntoDocCollection.called.should.equal(false);
});
it "should not update the version", -> it("should not update the version", function() {
@MongoManager.setDocVersion.called.should.equal false return this.MongoManager.setDocVersion.called.should.equal(false);
});
it "should return the callback with the old rev and modified == false", -> return it("should return the callback with the old rev and modified == false", function() {
@callback.calledWith(null, false, @rev).should.equal true return this.callback.calledWith(null, false, this.rev).should.equal(true);
});
});
describe "when the version is null", -> describe("when the version is null", function() {
beforeEach -> beforeEach(function() {
@DocManager.updateDoc @project_id, @doc_id, @newDocLines, null, @originalRanges, @callback return this.DocManager.updateDoc(this.project_id, this.doc_id, this.newDocLines, null, this.originalRanges, this.callback);
});
it "should return an error", -> return it("should return an error", function() {
@callback.calledWith(sinon.match.has('message', "no lines, version or ranges provided")).should.equal true return this.callback.calledWith(sinon.match.has('message', "no lines, version or ranges provided")).should.equal(true);
});
});
describe "when the lines are null", -> describe("when the lines are null", function() {
beforeEach -> beforeEach(function() {
@DocManager.updateDoc @project_id, @doc_id, null, @version, @originalRanges, @callback return this.DocManager.updateDoc(this.project_id, this.doc_id, null, this.version, this.originalRanges, this.callback);
});
it "should return an error", -> return it("should return an error", function() {
@callback.calledWith(sinon.match.has('message', "no lines, version or ranges provided")).should.equal true return this.callback.calledWith(sinon.match.has('message', "no lines, version or ranges provided")).should.equal(true);
});
});
describe "when the ranges are null", -> describe("when the ranges are null", function() {
beforeEach -> beforeEach(function() {
@DocManager.updateDoc @project_id, @doc_id, @newDocLines, @version, null, @callback return this.DocManager.updateDoc(this.project_id, this.doc_id, this.newDocLines, this.version, null, this.callback);
});
it "should return an error", -> return it("should return an error", function() {
@callback.calledWith(sinon.match.has('message', "no lines, version or ranges provided")).should.equal true return this.callback.calledWith(sinon.match.has('message', "no lines, version or ranges provided")).should.equal(true);
});
});
describe "when there is a generic error getting the doc", -> describe("when there is a generic error getting the doc", function() {
beforeEach -> beforeEach(function() {
@error = new Error("doc could not be found") this.error = new Error("doc could not be found");
@DocManager._getDoc = sinon.stub().callsArgWith(3, @error, null, null) this.DocManager._getDoc = sinon.stub().callsArgWith(3, this.error, null, null);
@DocManager.updateDoc @project_id, @doc_id, @newDocLines, @version, @originalRanges, @callback return this.DocManager.updateDoc(this.project_id, this.doc_id, this.newDocLines, this.version, this.originalRanges, this.callback);
});
it "should not upsert the document to the doc collection", -> it("should not upsert the document to the doc collection", function() {
@MongoManager.upsertIntoDocCollection.called.should.equal false return this.MongoManager.upsertIntoDocCollection.called.should.equal(false);
});
it "should return the callback with the error", -> return it("should return the callback with the error", function() {
@callback.calledWith(@error).should.equal true return this.callback.calledWith(this.error).should.equal(true);
});
});
describe "when the doc lines have not changed", -> describe("when the doc lines have not changed", function() {
beforeEach -> beforeEach(function() {
@DocManager._getDoc = sinon.stub().callsArgWith(3, null, @doc) this.DocManager._getDoc = sinon.stub().callsArgWith(3, null, this.doc);
@DocManager.updateDoc @project_id, @doc_id, @oldDocLines.slice(), @version, @originalRanges, @callback return this.DocManager.updateDoc(this.project_id, this.doc_id, this.oldDocLines.slice(), this.version, this.originalRanges, this.callback);
});
it "should not update the doc", -> it("should not update the doc", function() {
@MongoManager.upsertIntoDocCollection.called.should.equal false return this.MongoManager.upsertIntoDocCollection.called.should.equal(false);
});
it "should return the callback with the existing rev", -> return it("should return the callback with the existing rev", function() {
@callback.calledWith(null, false, @rev).should.equal true return this.callback.calledWith(null, false, this.rev).should.equal(true);
});
});
describe "when the doc does not exist", -> return describe("when the doc does not exist", function() {
beforeEach -> beforeEach(function() {
@DocManager._getDoc = sinon.stub().callsArgWith(3, null, null, null) this.DocManager._getDoc = sinon.stub().callsArgWith(3, null, null, null);
@DocManager.updateDoc @project_id, @doc_id, @newDocLines, @version, @originalRanges, @callback return this.DocManager.updateDoc(this.project_id, this.doc_id, this.newDocLines, this.version, this.originalRanges, this.callback);
});
it "should upsert the document to the doc collection", -> it("should upsert the document to the doc collection", function() {
@MongoManager.upsertIntoDocCollection return this.MongoManager.upsertIntoDocCollection
.calledWith(@project_id, @doc_id, {lines: @newDocLines, ranges: @originalRanges}) .calledWith(this.project_id, this.doc_id, {lines: this.newDocLines, ranges: this.originalRanges})
.should.equal true .should.equal(true);
});
it "should set the version", -> it("should set the version", function() {
@MongoManager.setDocVersion return this.MongoManager.setDocVersion
.calledWith(@doc_id, @version) .calledWith(this.doc_id, this.version)
.should.equal true .should.equal(true);
});
it "should return the callback with the new rev", -> return it("should return the callback with the new rev", function() {
@callback.calledWith(null, true, 1).should.equal true return this.callback.calledWith(null, true, 1).should.equal(true);
});
});
});
});

View file

@ -1,357 +1,444 @@
SandboxedModule = require('sandboxed-module') /*
assert = require("chai").assert * decaffeinate suggestions:
sinon = require('sinon') * DS102: Remove unnecessary code created because of implicit returns
chai = require('chai') * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
chai.should() */
expect = chai.expect const SandboxedModule = require('sandboxed-module');
modulePath = require('path').join __dirname, '../../../app/js/HttpController' const {
ObjectId = require("mongojs").ObjectId assert
} = require("chai");
const sinon = require('sinon');
const chai = require('chai');
chai.should();
const {
expect
} = chai;
const modulePath = require('path').join(__dirname, '../../../app/js/HttpController');
const {
ObjectId
} = require("mongojs");
describe "HttpController", -> describe("HttpController", function() {
beforeEach -> beforeEach(function() {
@HttpController = SandboxedModule.require modulePath, requires: this.HttpController = SandboxedModule.require(modulePath, { requires: {
"./DocManager": @DocManager = {} "./DocManager": (this.DocManager = {}),
"./DocArchiveManager": @DocArchiveManager = {} "./DocArchiveManager": (this.DocArchiveManager = {}),
"logger-sharelatex": @logger = { log: sinon.stub(), error: sinon.stub() } "logger-sharelatex": (this.logger = { log: sinon.stub(), error: sinon.stub() }),
"./HealthChecker": {} "./HealthChecker": {}
@res = { send: sinon.stub(), json: sinon.stub(), setHeader:sinon.stub() }
@res.status = sinon.stub().returns(@res)
@req = { query:{}}
@next = sinon.stub()
@project_id = "mock-project-id"
@doc_id = "mock-doc-id"
@doc = {
_id: @doc_id
lines: ["mock", "lines", " here", "", "", " spaces "]
version: 42
rev: 5
} }
@deletedDoc = { });
deleted:true this.res = { send: sinon.stub(), json: sinon.stub(), setHeader:sinon.stub() };
_id: @doc_id this.res.status = sinon.stub().returns(this.res);
lines: ["mock", "lines", " here", "", "", " spaces "] this.req = { query:{}};
version: 42 this.next = sinon.stub();
this.project_id = "mock-project-id";
this.doc_id = "mock-doc-id";
this.doc = {
_id: this.doc_id,
lines: ["mock", "lines", " here", "", "", " spaces "],
version: 42,
rev: 5 rev: 5
} };
return this.deletedDoc = {
deleted:true,
_id: this.doc_id,
lines: ["mock", "lines", " here", "", "", " spaces "],
version: 42,
rev: 5
};});
describe "getDoc", -> describe("getDoc", function() {
describe "without deleted docs", -> describe("without deleted docs", function() {
beforeEach -> beforeEach(function() {
@req.params = this.req.params = {
project_id: @project_id project_id: this.project_id,
doc_id: @doc_id doc_id: this.doc_id
@DocManager.getFullDoc = sinon.stub().callsArgWith(2, null, @doc) };
@HttpController.getDoc @req, @res, @next this.DocManager.getFullDoc = sinon.stub().callsArgWith(2, null, this.doc);
return this.HttpController.getDoc(this.req, this.res, this.next);
});
it "should get the document with the version (including deleted)", -> it("should get the document with the version (including deleted)", function() {
@DocManager.getFullDoc return this.DocManager.getFullDoc
.calledWith(@project_id, @doc_id) .calledWith(this.project_id, this.doc_id)
.should.equal true .should.equal(true);
});
it "should return the doc as JSON", -> return it("should return the doc as JSON", function() {
@res.json return this.res.json
.calledWith({ .calledWith({
_id: @doc_id _id: this.doc_id,
lines: @doc.lines lines: this.doc.lines,
rev: @doc.rev rev: this.doc.rev,
version: @doc.version version: this.doc.version
}) })
.should.equal true .should.equal(true);
});
});
describe "which is deleted", -> return describe("which is deleted", function() {
beforeEach -> beforeEach(function() {
@req.params = this.req.params = {
project_id: @project_id project_id: this.project_id,
doc_id: @doc_id doc_id: this.doc_id
@DocManager.getFullDoc = sinon.stub().callsArgWith(2, null, @deletedDoc) };
return this.DocManager.getFullDoc = sinon.stub().callsArgWith(2, null, this.deletedDoc);
});
it "should get the doc from the doc manager", -> it("should get the doc from the doc manager", function() {
@HttpController.getDoc @req, @res, @next this.HttpController.getDoc(this.req, this.res, this.next);
@DocManager.getFullDoc.calledWith(@project_id, @doc_id).should.equal true return this.DocManager.getFullDoc.calledWith(this.project_id, this.doc_id).should.equal(true);
});
it "should return 404 if the query string delete is not set ", -> it("should return 404 if the query string delete is not set ", function() {
@HttpController.getDoc @req, @res, @next this.HttpController.getDoc(this.req, this.res, this.next);
@res.send.calledWith(404).should.equal true return this.res.send.calledWith(404).should.equal(true);
});
it "should return the doc as JSON if include_deleted is set to true", -> return it("should return the doc as JSON if include_deleted is set to true", function() {
@req.query.include_deleted = "true" this.req.query.include_deleted = "true";
@HttpController.getDoc @req, @res, @next this.HttpController.getDoc(this.req, this.res, this.next);
@res.json return this.res.json
.calledWith({ .calledWith({
_id: @doc_id _id: this.doc_id,
lines: @doc.lines lines: this.doc.lines,
rev: @doc.rev rev: this.doc.rev,
deleted: true deleted: true,
version: @doc.version version: this.doc.version
}) })
.should.equal true .should.equal(true);
});
});
});
describe "getRawDoc", -> describe("getRawDoc", function() {
beforeEach -> beforeEach(function() {
@req.params = this.req.params = {
project_id: @project_id project_id: this.project_id,
doc_id: @doc_id doc_id: this.doc_id
@DocManager.getDocLines = sinon.stub().callsArgWith(2, null, @doc) };
@HttpController.getRawDoc @req, @res, @next this.DocManager.getDocLines = sinon.stub().callsArgWith(2, null, this.doc);
return this.HttpController.getRawDoc(this.req, this.res, this.next);
});
it "should get the document without the version", -> it("should get the document without the version", function() {
@DocManager.getDocLines return this.DocManager.getDocLines
.calledWith(@project_id, @doc_id) .calledWith(this.project_id, this.doc_id)
.should.equal true .should.equal(true);
});
it "should set the content type header", -> it("should set the content type header", function() {
@res.setHeader.calledWith('content-type', 'text/plain').should.equal true return this.res.setHeader.calledWith('content-type', 'text/plain').should.equal(true);
});
it "should send the raw version of the doc", -> return it("should send the raw version of the doc", function() {
assert.deepEqual @res.send.args[0][0], "#{@doc.lines[0]}\n#{@doc.lines[1]}\n#{@doc.lines[2]}\n#{@doc.lines[3]}\n#{@doc.lines[4]}\n#{@doc.lines[5]}" return assert.deepEqual(this.res.send.args[0][0], `${this.doc.lines[0]}\n${this.doc.lines[1]}\n${this.doc.lines[2]}\n${this.doc.lines[3]}\n${this.doc.lines[4]}\n${this.doc.lines[5]}`);
});
});
describe "getAllDocs", -> describe("getAllDocs", function() {
describe "normally", -> describe("normally", function() {
beforeEach -> beforeEach(function() {
@req.params = this.req.params =
project_id: @project_id {project_id: this.project_id};
@docs = [{ this.docs = [{
_id: ObjectId() _id: ObjectId(),
lines: ["mock", "lines", "one"] lines: ["mock", "lines", "one"],
rev: 2 rev: 2
}, { }, {
_id: ObjectId() _id: ObjectId(),
lines: ["mock", "lines", "two"] lines: ["mock", "lines", "two"],
rev: 4 rev: 4
}] }];
@DocManager.getAllNonDeletedDocs = sinon.stub().callsArgWith(2, null, @docs) this.DocManager.getAllNonDeletedDocs = sinon.stub().callsArgWith(2, null, this.docs);
@HttpController.getAllDocs @req, @res, @next return this.HttpController.getAllDocs(this.req, this.res, this.next);
});
it "should get all the (non-deleted) docs", -> it("should get all the (non-deleted) docs", function() {
@DocManager.getAllNonDeletedDocs return this.DocManager.getAllNonDeletedDocs
.calledWith(@project_id, {lines: true, rev: true}) .calledWith(this.project_id, {lines: true, rev: true})
.should.equal true .should.equal(true);
});
it "should return the doc as JSON", -> return it("should return the doc as JSON", function() {
@res.json return this.res.json
.calledWith([{ .calledWith([{
_id: @docs[0]._id.toString() _id: this.docs[0]._id.toString(),
lines: @docs[0].lines lines: this.docs[0].lines,
rev: @docs[0].rev rev: this.docs[0].rev
}, { }, {
_id: @docs[1]._id.toString() _id: this.docs[1]._id.toString(),
lines: @docs[1].lines lines: this.docs[1].lines,
rev: @docs[1].rev rev: this.docs[1].rev
}]) }])
.should.equal true .should.equal(true);
});
});
describe "with a null doc", -> return describe("with a null doc", function() {
beforeEach -> beforeEach(function() {
@req.params = this.req.params =
project_id: @project_id {project_id: this.project_id};
@docs = [{ this.docs = [{
_id: ObjectId() _id: ObjectId(),
lines: ["mock", "lines", "one"] lines: ["mock", "lines", "one"],
rev: 2 rev: 2
}, },
null, null,
{ {
_id: ObjectId() _id: ObjectId(),
lines: ["mock", "lines", "two"] lines: ["mock", "lines", "two"],
rev: 4 rev: 4
}] }];
@DocManager.getAllNonDeletedDocs = sinon.stub().callsArgWith(2, null, @docs) this.DocManager.getAllNonDeletedDocs = sinon.stub().callsArgWith(2, null, this.docs);
@HttpController.getAllDocs @req, @res, @next return this.HttpController.getAllDocs(this.req, this.res, this.next);
});
it "should return the non null docs as JSON", -> it("should return the non null docs as JSON", function() {
@res.json return this.res.json
.calledWith([{ .calledWith([{
_id: @docs[0]._id.toString() _id: this.docs[0]._id.toString(),
lines: @docs[0].lines lines: this.docs[0].lines,
rev: @docs[0].rev rev: this.docs[0].rev
}, { }, {
_id: @docs[2]._id.toString() _id: this.docs[2]._id.toString(),
lines: @docs[2].lines lines: this.docs[2].lines,
rev: @docs[2].rev rev: this.docs[2].rev
}]) }])
.should.equal true .should.equal(true);
});
it "should log out an error", -> return it("should log out an error", function() {
@logger.error return this.logger.error
.calledWith( .calledWith({
err: sinon.match.has('message', "null doc") err: sinon.match.has('message', "null doc"),
project_id: @project_id project_id: this.project_id
},
"encountered null doc" "encountered null doc"
) )
.should.equal true .should.equal(true);
});
});
});
describe "getAllRanges", -> describe("getAllRanges", () => describe("normally", function() {
describe "normally", -> beforeEach(function() {
beforeEach -> this.req.params =
@req.params = {project_id: this.project_id};
project_id: @project_id this.docs = [{
@docs = [{ _id: ObjectId(),
_id: ObjectId() ranges: {"mock_ranges": "one"}
ranges: {"mock_ranges": "one"} }, {
}, { _id: ObjectId(),
_id: ObjectId() ranges: {"mock_ranges": "two"}
ranges: {"mock_ranges": "two"} }];
}] this.DocManager.getAllNonDeletedDocs = sinon.stub().callsArgWith(2, null, this.docs);
@DocManager.getAllNonDeletedDocs = sinon.stub().callsArgWith(2, null, @docs) return this.HttpController.getAllRanges(this.req, this.res, this.next);
@HttpController.getAllRanges @req, @res, @next });
it "should get all the (non-deleted) doc ranges", -> it("should get all the (non-deleted) doc ranges", function() {
@DocManager.getAllNonDeletedDocs return this.DocManager.getAllNonDeletedDocs
.calledWith(@project_id, {ranges: true}) .calledWith(this.project_id, {ranges: true})
.should.equal true .should.equal(true);
});
it "should return the doc as JSON", -> return it("should return the doc as JSON", function() {
@res.json return this.res.json
.calledWith([{ .calledWith([{
_id: @docs[0]._id.toString() _id: this.docs[0]._id.toString(),
ranges: @docs[0].ranges ranges: this.docs[0].ranges
}, { }, {
_id: @docs[1]._id.toString() _id: this.docs[1]._id.toString(),
ranges: @docs[1].ranges ranges: this.docs[1].ranges
}]) }])
.should.equal true .should.equal(true);
});
}));
describe "updateDoc", -> describe("updateDoc", function() {
beforeEach -> beforeEach(function() {
@req.params = return this.req.params = {
project_id: @project_id project_id: this.project_id,
doc_id: @doc_id doc_id: this.doc_id
};
});
describe "when the doc lines exist and were updated", -> describe("when the doc lines exist and were updated", function() {
beforeEach -> beforeEach(function() {
@req.body = this.req.body = {
lines: @lines = ["hello", "world"] lines: (this.lines = ["hello", "world"]),
version: @version = 42 version: (this.version = 42),
ranges: @ranges = { changes: "mock" } ranges: (this.ranges = { changes: "mock" })
@DocManager.updateDoc = sinon.stub().yields(null, true, @rev = 5) };
@HttpController.updateDoc @req, @res, @next this.DocManager.updateDoc = sinon.stub().yields(null, true, (this.rev = 5));
return this.HttpController.updateDoc(this.req, this.res, this.next);
});
it "should update the document", -> it("should update the document", function() {
@DocManager.updateDoc return this.DocManager.updateDoc
.calledWith(@project_id, @doc_id, @lines, @version, @ranges) .calledWith(this.project_id, this.doc_id, this.lines, this.version, this.ranges)
.should.equal true .should.equal(true);
});
it "should return a modified status", -> return it("should return a modified status", function() {
@res.json return this.res.json
.calledWith(modified: true, rev: @rev) .calledWith({modified: true, rev: this.rev})
.should.equal true .should.equal(true);
});
});
describe "when the doc lines exist and were not updated", -> describe("when the doc lines exist and were not updated", function() {
beforeEach -> beforeEach(function() {
@req.body = this.req.body = {
lines: @lines = ["hello", "world"] lines: (this.lines = ["hello", "world"]),
version: @version = 42 version: (this.version = 42),
ranges: {} ranges: {}
@DocManager.updateDoc = sinon.stub().yields(null, false, @rev = 5) };
@HttpController.updateDoc @req, @res, @next this.DocManager.updateDoc = sinon.stub().yields(null, false, (this.rev = 5));
return this.HttpController.updateDoc(this.req, this.res, this.next);
});
it "should return a modified status", -> return it("should return a modified status", function() {
@res.json return this.res.json
.calledWith(modified: false, rev: @rev) .calledWith({modified: false, rev: this.rev})
.should.equal true .should.equal(true);
});
});
describe "when the doc lines are not provided", -> describe("when the doc lines are not provided", function() {
beforeEach -> beforeEach(function() {
@req.body = { version: 42, ranges: {} } this.req.body = { version: 42, ranges: {} };
@DocManager.updateDoc = sinon.stub().yields(null, false) this.DocManager.updateDoc = sinon.stub().yields(null, false);
@HttpController.updateDoc @req, @res, @next return this.HttpController.updateDoc(this.req, this.res, this.next);
});
it "should not update the document", -> it("should not update the document", function() {
@DocManager.updateDoc.called.should.equal false return this.DocManager.updateDoc.called.should.equal(false);
});
it "should return a 400 (bad request) response", -> return it("should return a 400 (bad request) response", function() {
@res.send return this.res.send
.calledWith(400) .calledWith(400)
.should.equal true .should.equal(true);
});
});
describe "when the doc version are not provided", -> describe("when the doc version are not provided", function() {
beforeEach -> beforeEach(function() {
@req.body = { version: 42, lines: ["hello world"] } this.req.body = { version: 42, lines: ["hello world"] };
@DocManager.updateDoc = sinon.stub().yields(null, false) this.DocManager.updateDoc = sinon.stub().yields(null, false);
@HttpController.updateDoc @req, @res, @next return this.HttpController.updateDoc(this.req, this.res, this.next);
});
it "should not update the document", -> it("should not update the document", function() {
@DocManager.updateDoc.called.should.equal false return this.DocManager.updateDoc.called.should.equal(false);
});
it "should return a 400 (bad request) response", -> return it("should return a 400 (bad request) response", function() {
@res.send return this.res.send
.calledWith(400) .calledWith(400)
.should.equal true .should.equal(true);
});
});
describe "when the doc ranges is not provided", -> describe("when the doc ranges is not provided", function() {
beforeEach -> beforeEach(function() {
@req.body = { lines : [ "foo" ], version: 42 } this.req.body = { lines : [ "foo" ], version: 42 };
@DocManager.updateDoc = sinon.stub().yields(null, false) this.DocManager.updateDoc = sinon.stub().yields(null, false);
@HttpController.updateDoc @req, @res, @next return this.HttpController.updateDoc(this.req, this.res, this.next);
});
it "should not update the document", -> it("should not update the document", function() {
@DocManager.updateDoc.called.should.equal false return this.DocManager.updateDoc.called.should.equal(false);
});
it "should return a 400 (bad request) response", -> return it("should return a 400 (bad request) response", function() {
@res.send return this.res.send
.calledWith(400) .calledWith(400)
.should.equal true .should.equal(true);
});
});
describe "when the doc body is too large", -> return describe("when the doc body is too large", function() {
beforeEach -> beforeEach(function() {
@req.body = this.req.body = {
lines: @lines = Array(2049).fill('a'.repeat(1024)) lines: (this.lines = Array(2049).fill('a'.repeat(1024))),
version: @version = 42 version: (this.version = 42),
ranges: @ranges = { changes: "mock" } ranges: (this.ranges = { changes: "mock" })
@HttpController.updateDoc @req, @res, @next };
return this.HttpController.updateDoc(this.req, this.res, this.next);
});
it "should return a 413 (too large) response", -> it("should return a 413 (too large) response", function() {
sinon.assert.calledWith(@res.status, 413) return sinon.assert.calledWith(this.res.status, 413);
});
it "should report that the document body is too large", -> return it("should report that the document body is too large", function() {
sinon.assert.calledWith(@res.send, "document body too large") return sinon.assert.calledWith(this.res.send, "document body too large");
});
});
});
describe "deleteDoc", -> describe("deleteDoc", function() {
beforeEach -> beforeEach(function() {
@req.params = this.req.params = {
project_id: @project_id project_id: this.project_id,
doc_id: @doc_id doc_id: this.doc_id
@DocManager.deleteDoc = sinon.stub().callsArg(2) };
@HttpController.deleteDoc @req, @res, @next this.DocManager.deleteDoc = sinon.stub().callsArg(2);
return this.HttpController.deleteDoc(this.req, this.res, this.next);
});
it "should delete the document", -> it("should delete the document", function() {
@DocManager.deleteDoc return this.DocManager.deleteDoc
.calledWith(@project_id, @doc_id) .calledWith(this.project_id, this.doc_id)
.should.equal true .should.equal(true);
});
it "should return a 204 (No Content)", -> return it("should return a 204 (No Content)", function() {
@res.send return this.res.send
.calledWith(204) .calledWith(204)
.should.equal true .should.equal(true);
});
});
describe "archiveAllDocs", -> describe("archiveAllDocs", function() {
beforeEach -> beforeEach(function() {
@req.params = this.req.params =
project_id: @project_id {project_id: this.project_id};
@DocArchiveManager.archiveAllDocs = sinon.stub().callsArg(1) this.DocArchiveManager.archiveAllDocs = sinon.stub().callsArg(1);
@HttpController.archiveAllDocs @req, @res, @next return this.HttpController.archiveAllDocs(this.req, this.res, this.next);
});
it "should archive the project", -> it("should archive the project", function() {
@DocArchiveManager.archiveAllDocs return this.DocArchiveManager.archiveAllDocs
.calledWith(@project_id) .calledWith(this.project_id)
.should.equal true .should.equal(true);
});
it "should return a 204 (No Content)", -> return it("should return a 204 (No Content)", function() {
@res.send return this.res.send
.calledWith(204) .calledWith(204)
.should.equal true .should.equal(true);
});
});
describe "destroyAllDocs", -> return describe("destroyAllDocs", function() {
beforeEach -> beforeEach(function() {
@req.params = this.req.params =
project_id: @project_id {project_id: this.project_id};
@DocArchiveManager.destroyAllDocs = sinon.stub().callsArg(1) this.DocArchiveManager.destroyAllDocs = sinon.stub().callsArg(1);
@HttpController.destroyAllDocs @req, @res, @next return this.HttpController.destroyAllDocs(this.req, this.res, this.next);
});
it "should destroy the docs", -> it("should destroy the docs", function() {
sinon.assert.calledWith(@DocArchiveManager.destroyAllDocs, @project_id) return sinon.assert.calledWith(this.DocArchiveManager.destroyAllDocs, this.project_id);
});
it "should return 204", -> return it("should return 204", function() {
sinon.assert.calledWith(@res.send, 204) return sinon.assert.calledWith(this.res.send, 204);
});
});
});

View file

@ -1,168 +1,225 @@
SandboxedModule = require('sandboxed-module') /*
sinon = require('sinon') * decaffeinate suggestions:
require('chai').should() * DS102: Remove unnecessary code created because of implicit returns
modulePath = require('path').join __dirname, '../../../app/js/MongoManager' * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
ObjectId = require("mongojs").ObjectId */
assert = require("chai").assert const SandboxedModule = require('sandboxed-module');
const sinon = require('sinon');
require('chai').should();
const modulePath = require('path').join(__dirname, '../../../app/js/MongoManager');
const {
ObjectId
} = require("mongojs");
const {
assert
} = require("chai");
describe "MongoManager", -> describe("MongoManager", function() {
beforeEach -> beforeEach(function() {
@MongoManager = SandboxedModule.require modulePath, requires: this.MongoManager = SandboxedModule.require(modulePath, { requires: {
"./mongojs": "./mongojs": {
db: @db = { docs: {}, docOps: {} } db: (this.db = { docs: {}, docOps: {} }),
ObjectId: ObjectId ObjectId
'metrics-sharelatex': {timeAsyncMethod: sinon.stub()} },
'logger-sharelatex': {log: ()->} 'metrics-sharelatex': {timeAsyncMethod: sinon.stub()},
@project_id = ObjectId().toString() 'logger-sharelatex': {log(){}}
@doc_id = ObjectId().toString() }
@callback = sinon.stub() });
@stubbedErr = new Error("hello world") this.project_id = ObjectId().toString();
this.doc_id = ObjectId().toString();
this.callback = sinon.stub();
return this.stubbedErr = new Error("hello world");
});
describe "findDoc", -> describe("findDoc", function() {
beforeEach -> beforeEach(function() {
@doc = { name: "mock-doc"} this.doc = { name: "mock-doc"};
@db.docs.find = sinon.stub().callsArgWith(2, null, [@doc]) this.db.docs.find = sinon.stub().callsArgWith(2, null, [this.doc]);
@filter = { lines: true } this.filter = { lines: true };
@MongoManager.findDoc @project_id, @doc_id, @filter, @callback return this.MongoManager.findDoc(this.project_id, this.doc_id, this.filter, this.callback);
});
it "should find the doc", -> it("should find the doc", function() {
@db.docs.find return this.db.docs.find
.calledWith({ .calledWith({
_id: ObjectId(@doc_id) _id: ObjectId(this.doc_id),
project_id: ObjectId(@project_id) project_id: ObjectId(this.project_id)
}, @filter) }, this.filter)
.should.equal true .should.equal(true);
});
it "should call the callback with the doc", -> return it("should call the callback with the doc", function() {
@callback.calledWith(null, @doc).should.equal true return this.callback.calledWith(null, this.doc).should.equal(true);
});
});
describe "getProjectsDocs", -> describe("getProjectsDocs", function() {
beforeEach -> beforeEach(function() {
@filter = {lines: true} this.filter = {lines: true};
@doc1 = { name: "mock-doc1" } this.doc1 = { name: "mock-doc1" };
@doc2 = { name: "mock-doc2" } this.doc2 = { name: "mock-doc2" };
@doc3 = { name: "mock-doc3" } this.doc3 = { name: "mock-doc3" };
@doc4 = { name: "mock-doc4" } this.doc4 = { name: "mock-doc4" };
@db.docs.find = sinon.stub().callsArgWith(2, null, [@doc, @doc3, @doc4]) return this.db.docs.find = sinon.stub().callsArgWith(2, null, [this.doc, this.doc3, this.doc4]);
});
describe "with included_deleted = false", -> describe("with included_deleted = false", function() {
beforeEach -> beforeEach(function() {
@MongoManager.getProjectsDocs @project_id, include_deleted: false, @filter, @callback return this.MongoManager.getProjectsDocs(this.project_id, {include_deleted: false}, this.filter, this.callback);
});
it "should find the non-deleted docs via the project_id", -> it("should find the non-deleted docs via the project_id", function() {
@db.docs.find return this.db.docs.find
.calledWith({ .calledWith({
project_id: ObjectId(@project_id) project_id: ObjectId(this.project_id),
deleted: { $ne: true } deleted: { $ne: true }
}, @filter) }, this.filter)
.should.equal true .should.equal(true);
});
it "should call the callback with the docs", -> return it("should call the callback with the docs", function() {
@callback.calledWith(null, [@doc, @doc3, @doc4]).should.equal true return this.callback.calledWith(null, [this.doc, this.doc3, this.doc4]).should.equal(true);
});
});
describe "with included_deleted = true", -> return describe("with included_deleted = true", function() {
beforeEach -> beforeEach(function() {
@MongoManager.getProjectsDocs @project_id, include_deleted: true, @filter, @callback return this.MongoManager.getProjectsDocs(this.project_id, {include_deleted: true}, this.filter, this.callback);
});
it "should find all via the project_id", -> it("should find all via the project_id", function() {
@db.docs.find return this.db.docs.find
.calledWith({ .calledWith({
project_id: ObjectId(@project_id) project_id: ObjectId(this.project_id)
}, @filter) }, this.filter)
.should.equal true .should.equal(true);
});
it "should call the callback with the docs", -> return it("should call the callback with the docs", function() {
@callback.calledWith(null, [@doc, @doc3, @doc4]).should.equal true return this.callback.calledWith(null, [this.doc, this.doc3, this.doc4]).should.equal(true);
});
});
});
describe "upsertIntoDocCollection", -> describe("upsertIntoDocCollection", function() {
beforeEach -> beforeEach(function() {
@db.docs.update = sinon.stub().callsArgWith(3, @stubbedErr) this.db.docs.update = sinon.stub().callsArgWith(3, this.stubbedErr);
@oldRev = 77 return this.oldRev = 77;
});
it "should upsert the document", (done)-> it("should upsert the document", function(done){
@MongoManager.upsertIntoDocCollection @project_id, @doc_id, {@lines}, (err)=> return this.MongoManager.upsertIntoDocCollection(this.project_id, this.doc_id, {lines: this.lines}, err=> {
args = @db.docs.update.args[0] const args = this.db.docs.update.args[0];
assert.deepEqual args[0], {_id: ObjectId(@doc_id)} assert.deepEqual(args[0], {_id: ObjectId(this.doc_id)});
assert.equal args[1]["$set"]["lines"], @lines assert.equal(args[1]["$set"]["lines"], this.lines);
assert.equal args[1]["$inc"]["rev"], 1 assert.equal(args[1]["$inc"]["rev"], 1);
assert.deepEqual args[1]["$set"]["project_id"], ObjectId(@project_id) assert.deepEqual(args[1]["$set"]["project_id"], ObjectId(this.project_id));
done() return done();
});
});
it "should return the error", (done)-> return it("should return the error", function(done){
@MongoManager.upsertIntoDocCollection @project_id, @doc_id, {@lines}, (err)=> return this.MongoManager.upsertIntoDocCollection(this.project_id, this.doc_id, {lines: this.lines}, err=> {
err.should.equal @stubbedErr err.should.equal(this.stubbedErr);
done() return done();
});
});
});
describe "markDocAsDeleted", -> describe("markDocAsDeleted", function() {
beforeEach -> beforeEach(function() {
@db.docs.update = sinon.stub().callsArgWith(2, @stubbedErr) this.db.docs.update = sinon.stub().callsArgWith(2, this.stubbedErr);
@oldRev = 77 return this.oldRev = 77;
});
it "should process the update", (done) -> it("should process the update", function(done) {
@MongoManager.markDocAsDeleted @project_id, @doc_id, (err)=> return this.MongoManager.markDocAsDeleted(this.project_id, this.doc_id, err=> {
args = @db.docs.update.args[0] const args = this.db.docs.update.args[0];
assert.deepEqual args[0], {_id: ObjectId(@doc_id), project_id: ObjectId(@project_id)} assert.deepEqual(args[0], {_id: ObjectId(this.doc_id), project_id: ObjectId(this.project_id)});
assert.equal args[1]["$set"]["deleted"], true assert.equal(args[1]["$set"]["deleted"], true);
done() return done();
});
});
it "should return the error", (done)-> return it("should return the error", function(done){
@MongoManager.markDocAsDeleted @project_id, @doc_id, (err)=> return this.MongoManager.markDocAsDeleted(this.project_id, this.doc_id, err=> {
err.should.equal @stubbedErr err.should.equal(this.stubbedErr);
done() return done();
});
});
});
describe "destroyDoc", -> describe("destroyDoc", function() {
beforeEach (done) -> beforeEach(function(done) {
@db.docs.remove = sinon.stub().yields() this.db.docs.remove = sinon.stub().yields();
@db.docOps.remove = sinon.stub().yields() this.db.docOps.remove = sinon.stub().yields();
@MongoManager.destroyDoc '123456789012', done return this.MongoManager.destroyDoc('123456789012', done);
});
it "should destroy the doc", -> it("should destroy the doc", function() {
sinon.assert.calledWith(@db.docs.remove, {_id: ObjectId('123456789012')}) return sinon.assert.calledWith(this.db.docs.remove, {_id: ObjectId('123456789012')});
});
it "should destroy the docOps", -> return it("should destroy the docOps", function() {
sinon.assert.calledWith(@db.docOps.remove, {doc_id: ObjectId('123456789012')}) return sinon.assert.calledWith(this.db.docOps.remove, {doc_id: ObjectId('123456789012')});
});
});
describe "getDocVersion", -> describe("getDocVersion", function() {
describe "when the doc exists", -> describe("when the doc exists", function() {
beforeEach -> beforeEach(function() {
@doc = this.doc =
version: @version = 42 {version: (this.version = 42)};
@db.docOps.find = sinon.stub().callsArgWith(2, null, [@doc]) this.db.docOps.find = sinon.stub().callsArgWith(2, null, [this.doc]);
@MongoManager.getDocVersion @doc_id, @callback return this.MongoManager.getDocVersion(this.doc_id, this.callback);
});
it "should look for the doc in the database", -> it("should look for the doc in the database", function() {
@db.docOps.find return this.db.docOps.find
.calledWith({ doc_id: ObjectId(@doc_id) }, {version: 1}) .calledWith({ doc_id: ObjectId(this.doc_id) }, {version: 1})
.should.equal true .should.equal(true);
});
it "should call the callback with the version", -> return it("should call the callback with the version", function() {
@callback.calledWith(null, @version).should.equal true return this.callback.calledWith(null, this.version).should.equal(true);
});
});
describe "when the doc doesn't exist", -> return describe("when the doc doesn't exist", function() {
beforeEach -> beforeEach(function() {
@db.docOps.find = sinon.stub().callsArgWith(2, null, []) this.db.docOps.find = sinon.stub().callsArgWith(2, null, []);
@MongoManager.getDocVersion @doc_id, @callback return this.MongoManager.getDocVersion(this.doc_id, this.callback);
});
it "should call the callback with 0", -> return it("should call the callback with 0", function() {
@callback.calledWith(null, 0).should.equal true return this.callback.calledWith(null, 0).should.equal(true);
});
});
});
describe "setDocVersion", -> return describe("setDocVersion", function() {
beforeEach -> beforeEach(function() {
@version = 42 this.version = 42;
@db.docOps.update = sinon.stub().callsArg(3) this.db.docOps.update = sinon.stub().callsArg(3);
@MongoManager.setDocVersion @doc_id, @version, @callback return this.MongoManager.setDocVersion(this.doc_id, this.version, this.callback);
});
it "should update the doc version", -> it("should update the doc version", function() {
@db.docOps.update return this.db.docOps.update
.calledWith({ .calledWith({
doc_id: ObjectId(@doc_id) doc_id: ObjectId(this.doc_id)
}, { }, {
$set: $set: {
version: @version version: this.version
}
}, { }, {
upsert: true upsert: true
}) })
.should.equal true .should.equal(true);
});
it "should call the callback", -> return it("should call the callback", function() {
@callback.called.should.equal true return this.callback.called.should.equal(true);
});
});
});

View file

@ -1,155 +1,192 @@
SandboxedModule = require('sandboxed-module') /*
sinon = require('sinon') * decaffeinate suggestions:
require('chai').should() * DS102: Remove unnecessary code created because of implicit returns
expect = require('chai').expect * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
modulePath = require('path').join __dirname, '../../../app/js/RangeManager' */
ObjectId = require("mongojs").ObjectId const SandboxedModule = require('sandboxed-module');
assert = require("chai").assert const sinon = require('sinon');
_ = require "underscore" require('chai').should();
const {
expect
} = require('chai');
const modulePath = require('path').join(__dirname, '../../../app/js/RangeManager');
const {
ObjectId
} = require("mongojs");
const {
assert
} = require("chai");
const _ = require("underscore");
describe "RangeManager", -> describe("RangeManager", function() {
beforeEach -> beforeEach(function() {
@RangeManager = SandboxedModule.require modulePath, requires: return this.RangeManager = SandboxedModule.require(modulePath, { requires: {
"./mongojs": "./mongojs": {
ObjectId: ObjectId ObjectId
}
}
}
);
});
describe "jsonRangesToMongo", -> describe("jsonRangesToMongo", function() {
it "should convert ObjectIds and dates to proper objects", -> it("should convert ObjectIds and dates to proper objects", function() {
change_id = ObjectId().toString() const change_id = ObjectId().toString();
comment_id = ObjectId().toString() const comment_id = ObjectId().toString();
user_id = ObjectId().toString() const user_id = ObjectId().toString();
thread_id = ObjectId().toString() const thread_id = ObjectId().toString();
ts = new Date().toJSON() const ts = new Date().toJSON();
@RangeManager.jsonRangesToMongo({ return this.RangeManager.jsonRangesToMongo({
changes: [{ changes: [{
id: change_id id: change_id,
op: { i: "foo", p: 3 } op: { i: "foo", p: 3 },
metadata: metadata: {
user_id: user_id user_id,
ts: ts ts
}] }
}],
comments: [{ comments: [{
id: comment_id id: comment_id,
op: { c: "foo", p: 3, t: thread_id } op: { c: "foo", p: 3, t: thread_id }
}] }]
}).should.deep.equal { }).should.deep.equal({
changes: [{ changes: [{
id: ObjectId(change_id) id: ObjectId(change_id),
op: { i: "foo", p: 3 } op: { i: "foo", p: 3 },
metadata: metadata: {
user_id: ObjectId(user_id) user_id: ObjectId(user_id),
ts: new Date(ts) ts: new Date(ts)
}] }
}],
comments: [{ comments: [{
id: ObjectId(comment_id) id: ObjectId(comment_id),
op: { c: "foo", p: 3, t: ObjectId(thread_id) } op: { c: "foo", p: 3, t: ObjectId(thread_id) }
}] }]
} });
});
it "should leave malformed ObjectIds as they are", -> it("should leave malformed ObjectIds as they are", function() {
change_id = "foo" const change_id = "foo";
comment_id = "bar" const comment_id = "bar";
user_id = "baz" const user_id = "baz";
@RangeManager.jsonRangesToMongo({ return this.RangeManager.jsonRangesToMongo({
changes: [{ changes: [{
id: change_id id: change_id,
metadata: metadata: {
user_id: user_id user_id
}] }
}],
comments: [{ comments: [{
id: comment_id id: comment_id
}] }]
}).should.deep.equal { }).should.deep.equal({
changes: [{ changes: [{
id: change_id id: change_id,
metadata: metadata: {
user_id: user_id user_id
}] }
}],
comments: [{ comments: [{
id: comment_id id: comment_id
}] }]
} });
});
it "should be consistent when transformed through json -> mongo -> json", -> return it("should be consistent when transformed through json -> mongo -> json", function() {
change_id = ObjectId().toString() const change_id = ObjectId().toString();
comment_id = ObjectId().toString() const comment_id = ObjectId().toString();
user_id = ObjectId().toString() const user_id = ObjectId().toString();
thread_id = ObjectId().toString() const thread_id = ObjectId().toString();
ts = new Date().toJSON() const ts = new Date().toJSON();
ranges1 = { const ranges1 = {
changes: [{ changes: [{
id: change_id id: change_id,
op: { i: "foo", p: 3 } op: { i: "foo", p: 3 },
metadata: metadata: {
user_id: user_id user_id,
ts: ts ts
}] }
}],
comments: [{ comments: [{
id: comment_id id: comment_id,
op: { c: "foo", p: 3, t: thread_id } op: { c: "foo", p: 3, t: thread_id }
}] }]
} };
ranges1_copy = JSON.parse(JSON.stringify(ranges1)) # jsonRangesToMongo modifies in place const ranges1_copy = JSON.parse(JSON.stringify(ranges1)); // jsonRangesToMongo modifies in place
ranges2 = JSON.parse(JSON.stringify(@RangeManager.jsonRangesToMongo(ranges1_copy))) const ranges2 = JSON.parse(JSON.stringify(this.RangeManager.jsonRangesToMongo(ranges1_copy)));
ranges1.should.deep.equal ranges2 return ranges1.should.deep.equal(ranges2);
});
});
describe "shouldUpdateRanges", -> return describe("shouldUpdateRanges", function() {
beforeEach () -> beforeEach(function() {
@ranges = { this.ranges = {
changes: [{ changes: [{
id: ObjectId() id: ObjectId(),
op: { i: "foo", p: 3 } op: { i: "foo", p: 3 },
metadata: metadata: {
user_id: ObjectId() user_id: ObjectId(),
ts: new Date() ts: new Date()
}] }
}],
comments: [{ comments: [{
id: ObjectId() id: ObjectId(),
op: { c: "foo", p: 3, t: ObjectId() } op: { c: "foo", p: 3, t: ObjectId() }
}] }]
} };
@ranges_copy = @RangeManager.jsonRangesToMongo(JSON.parse(JSON.stringify(@ranges))) return this.ranges_copy = this.RangeManager.jsonRangesToMongo(JSON.parse(JSON.stringify(this.ranges)));
});
describe "with a blank new range", -> describe("with a blank new range", () => it("should throw an error", function() {
it "should throw an error", -> return expect(() => {
expect(() => return this.RangeManager.shouldUpdateRanges(this.ranges, null);
@RangeManager.shouldUpdateRanges(@ranges, null) }).to.throw(Error);
).to.throw(Error) }));
describe "with a blank old range", -> describe("with a blank old range", () => it("should treat it like {}", function() {
it "should treat it like {}", -> this.RangeManager.shouldUpdateRanges(null, {}).should.equal(false);
@RangeManager.shouldUpdateRanges(null, {}).should.equal false return this.RangeManager.shouldUpdateRanges(null, this.ranges).should.equal(true);
@RangeManager.shouldUpdateRanges(null, @ranges).should.equal true }));
describe "with no changes", -> describe("with no changes", () => it("should return false", function() {
it "should return false", -> return this.RangeManager.shouldUpdateRanges(this.ranges, this.ranges_copy).should.equal(false);
@RangeManager.shouldUpdateRanges(@ranges, @ranges_copy).should.equal false }));
describe "with changes", -> return describe("with changes", function() {
it "should return true when the change id changes", -> it("should return true when the change id changes", function() {
@ranges_copy.changes[0].id = ObjectId() this.ranges_copy.changes[0].id = ObjectId();
@RangeManager.shouldUpdateRanges(@ranges, @ranges_copy).should.equal true return this.RangeManager.shouldUpdateRanges(this.ranges, this.ranges_copy).should.equal(true);
});
it "should return true when the change user id changes", -> it("should return true when the change user id changes", function() {
@ranges_copy.changes[0].metadata.user_id = ObjectId() this.ranges_copy.changes[0].metadata.user_id = ObjectId();
@RangeManager.shouldUpdateRanges(@ranges, @ranges_copy).should.equal true return this.RangeManager.shouldUpdateRanges(this.ranges, this.ranges_copy).should.equal(true);
});
it "should return true when the change ts changes", -> it("should return true when the change ts changes", function() {
@ranges_copy.changes[0].metadata.ts = new Date(Date.now() + 1000) this.ranges_copy.changes[0].metadata.ts = new Date(Date.now() + 1000);
@RangeManager.shouldUpdateRanges(@ranges, @ranges_copy).should.equal true return this.RangeManager.shouldUpdateRanges(this.ranges, this.ranges_copy).should.equal(true);
});
it "should return true when the change op changes", -> it("should return true when the change op changes", function() {
@ranges_copy.changes[0].op.i = "bar" this.ranges_copy.changes[0].op.i = "bar";
@RangeManager.shouldUpdateRanges(@ranges, @ranges_copy).should.equal true return this.RangeManager.shouldUpdateRanges(this.ranges, this.ranges_copy).should.equal(true);
});
it "should return true when the comment id changes", -> it("should return true when the comment id changes", function() {
@ranges_copy.comments[0].id = ObjectId() this.ranges_copy.comments[0].id = ObjectId();
@RangeManager.shouldUpdateRanges(@ranges, @ranges_copy).should.equal true return this.RangeManager.shouldUpdateRanges(this.ranges, this.ranges_copy).should.equal(true);
});
it "should return true when the comment offset changes", -> it("should return true when the comment offset changes", function() {
@ranges_copy.comments[0].op.p = 17 this.ranges_copy.comments[0].op.p = 17;
@RangeManager.shouldUpdateRanges(@ranges, @ranges_copy).should.equal true return this.RangeManager.shouldUpdateRanges(this.ranges, this.ranges_copy).should.equal(true);
});
it "should return true when the comment content changes", -> return it("should return true when the comment content changes", function() {
@ranges_copy.comments[0].op.c = "bar" this.ranges_copy.comments[0].op.c = "bar";
@RangeManager.shouldUpdateRanges(@ranges, @ranges_copy).should.equal true return this.RangeManager.shouldUpdateRanges(this.ranges, this.ranges_copy).should.equal(true);
});
});
});
});