2020-05-06 06:11:22 -04:00
|
|
|
/* eslint-disable
|
|
|
|
no-return-assign,
|
|
|
|
no-unused-vars,
|
|
|
|
*/
|
|
|
|
// TODO: This file was created by bulk-decaffeinate.
|
|
|
|
// Fix any style issues and re-enable lint.
|
2020-05-06 06:10:51 -04:00
|
|
|
/*
|
|
|
|
* decaffeinate suggestions:
|
|
|
|
* DS102: Remove unnecessary code created because of implicit returns
|
|
|
|
* DS206: Consider reworking classes to avoid initClass
|
|
|
|
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
|
|
|
*/
|
|
|
|
const sinon = require('sinon');
|
|
|
|
const chai = require('chai');
|
|
|
|
const should = chai.should();
|
|
|
|
const modulePath = "../../../../app/js/PersistenceManager.js";
|
|
|
|
const SandboxedModule = require('sandboxed-module');
|
|
|
|
const Errors = require("../../../../app/js/Errors");
|
|
|
|
|
|
|
|
describe("PersistenceManager", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
let Timer;
|
|
|
|
this.request = sinon.stub();
|
|
|
|
this.request.defaults = () => this.request;
|
|
|
|
this.PersistenceManager = SandboxedModule.require(modulePath, { requires: {
|
|
|
|
"requestretry": this.request,
|
|
|
|
"settings-sharelatex": (this.Settings = {}),
|
|
|
|
"./Metrics": (this.Metrics = {
|
|
|
|
Timer: (Timer = (function() {
|
|
|
|
Timer = class Timer {
|
|
|
|
static initClass() {
|
|
|
|
this.prototype.done = sinon.stub();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
Timer.initClass();
|
|
|
|
return Timer;
|
|
|
|
})()),
|
2020-01-14 08:53:50 -05:00
|
|
|
inc: sinon.stub()
|
2020-05-06 06:10:51 -04:00
|
|
|
}),
|
|
|
|
"logger-sharelatex": (this.logger = {log: sinon.stub(), err: sinon.stub()})
|
|
|
|
}
|
|
|
|
});
|
|
|
|
this.project_id = "project-id-123";
|
|
|
|
this.projectHistoryId = "history-id-123";
|
|
|
|
this.doc_id = "doc-id-123";
|
|
|
|
this.lines = ["one", "two", "three"];
|
|
|
|
this.version = 42;
|
|
|
|
this.callback = sinon.stub();
|
|
|
|
this.ranges = { comments: "mock", entries: "mock" };
|
|
|
|
this.pathname = '/a/b/c.tex';
|
|
|
|
this.lastUpdatedAt = Date.now();
|
|
|
|
this.lastUpdatedBy = 'last-author-id';
|
|
|
|
return this.Settings.apis = {
|
|
|
|
web: {
|
|
|
|
url: (this.url = "www.example.com"),
|
|
|
|
user: (this.user = "sharelatex"),
|
|
|
|
pass: (this.pass = "password")
|
2018-03-02 05:02:49 -05:00
|
|
|
}
|
2020-05-06 06:10:51 -04:00
|
|
|
};
|
|
|
|
});
|
|
|
|
|
|
|
|
describe("getDoc", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
return this.webResponse = {
|
|
|
|
lines: this.lines,
|
|
|
|
version: this.version,
|
|
|
|
ranges: this.ranges,
|
|
|
|
pathname: this.pathname,
|
|
|
|
projectHistoryId: this.projectHistoryId
|
|
|
|
};});
|
|
|
|
|
|
|
|
describe("with a successful response from the web api", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
this.request.callsArgWith(1, null, {statusCode: 200}, JSON.stringify(this.webResponse));
|
|
|
|
return this.PersistenceManager.getDoc(this.project_id, this.doc_id, this.callback);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should call the web api", function() {
|
|
|
|
return this.request
|
2016-12-01 11:40:15 -05:00
|
|
|
.calledWith({
|
2020-05-06 06:10:51 -04:00
|
|
|
url: `${this.url}/project/${this.project_id}/doc/${this.doc_id}`,
|
|
|
|
method: "GET",
|
|
|
|
headers: {
|
2016-12-01 11:40:15 -05:00
|
|
|
"accept": "application/json"
|
2020-05-06 06:10:51 -04:00
|
|
|
},
|
|
|
|
auth: {
|
|
|
|
user: this.user,
|
|
|
|
pass: this.pass,
|
2016-12-01 11:40:15 -05:00
|
|
|
sendImmediately: true
|
2020-05-06 06:10:51 -04:00
|
|
|
},
|
|
|
|
jar: false,
|
2016-12-01 11:40:15 -05:00
|
|
|
timeout: 5000
|
|
|
|
})
|
2020-05-06 06:10:51 -04:00
|
|
|
.should.equal(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should call the callback with the doc lines, version and ranges", function() {
|
|
|
|
return this.callback
|
|
|
|
.calledWith(null, this.lines, this.version, this.ranges, this.pathname, this.projectHistoryId)
|
|
|
|
.should.equal(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should time the execution", function() {
|
|
|
|
return this.Metrics.Timer.prototype.done.called.should.equal(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
return it("should increment the metric", function() {
|
|
|
|
return this.Metrics.inc.calledWith("getDoc", 1, {status: 200}).should.equal(true);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe("when request returns an error", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
this.error = new Error("oops");
|
|
|
|
this.error.code = "EOOPS";
|
|
|
|
this.request.callsArgWith(1, this.error, null, null);
|
|
|
|
return this.PersistenceManager.getDoc(this.project_id, this.doc_id, this.callback);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should return the error", function() {
|
|
|
|
return this.callback.calledWith(this.error).should.equal(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should time the execution", function() {
|
|
|
|
return this.Metrics.Timer.prototype.done.called.should.equal(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
return it("should increment the metric", function() {
|
|
|
|
return this.Metrics.inc.calledWith("getDoc", 1, {status: "EOOPS"}).should.equal(true);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe("when the request returns 404", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
this.request.callsArgWith(1, null, {statusCode: 404}, "");
|
|
|
|
return this.PersistenceManager.getDoc(this.project_id, this.doc_id, this.callback);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should return a NotFoundError", function() {
|
|
|
|
return this.callback.calledWith(new Errors.NotFoundError("not found")).should.equal(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should time the execution", function() {
|
|
|
|
return this.Metrics.Timer.prototype.done.called.should.equal(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
return it("should increment the metric", function() {
|
|
|
|
return this.Metrics.inc.calledWith("getDoc", 1, {status: 404}).should.equal(true);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe("when the request returns an error status code", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
this.request.callsArgWith(1, null, {statusCode: 500}, "");
|
|
|
|
return this.PersistenceManager.getDoc(this.project_id, this.doc_id, this.callback);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should return an error", function() {
|
|
|
|
return this.callback.calledWith(new Error("web api error")).should.equal(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should time the execution", function() {
|
|
|
|
return this.Metrics.Timer.prototype.done.called.should.equal(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
return it("should increment the metric", function() {
|
|
|
|
return this.Metrics.inc.calledWith("getDoc", 1, {status: 500}).should.equal(true);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe("when request returns an doc without lines", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
delete this.webResponse.lines;
|
|
|
|
this.request.callsArgWith(1, null, {statusCode: 200}, JSON.stringify(this.webResponse));
|
|
|
|
return this.PersistenceManager.getDoc(this.project_id, this.doc_id, this.callback);
|
|
|
|
});
|
|
|
|
|
|
|
|
return it("should return and error", function() {
|
|
|
|
return this.callback.calledWith(new Error("web API response had no doc lines")).should.equal(true);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe("when request returns an doc without a version", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
delete this.webResponse.version;
|
|
|
|
this.request.callsArgWith(1, null, {statusCode: 200}, JSON.stringify(this.webResponse));
|
|
|
|
return this.PersistenceManager.getDoc(this.project_id, this.doc_id, this.callback);
|
|
|
|
});
|
|
|
|
|
|
|
|
return it("should return and error", function() {
|
|
|
|
return this.callback.calledWith(new Error("web API response had no valid doc version")).should.equal(true);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
return describe("when request returns an doc without a pathname", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
delete this.webResponse.pathname;
|
|
|
|
this.request.callsArgWith(1, null, {statusCode: 200}, JSON.stringify(this.webResponse));
|
|
|
|
return this.PersistenceManager.getDoc(this.project_id, this.doc_id, this.callback);
|
|
|
|
});
|
|
|
|
|
|
|
|
return it("should return and error", function() {
|
|
|
|
return this.callback.calledWith(new Error("web API response had no valid doc pathname")).should.equal(true);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
return describe("setDoc", function() {
|
|
|
|
describe("with a successful response from the web api", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
this.request.callsArgWith(1, null, {statusCode: 200});
|
|
|
|
return this.PersistenceManager.setDoc(this.project_id, this.doc_id, this.lines, this.version, this.ranges, this.lastUpdatedAt, this.lastUpdatedBy, this.callback);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should call the web api", function() {
|
|
|
|
return this.request
|
2016-12-01 11:40:15 -05:00
|
|
|
.calledWith({
|
2020-05-06 06:10:51 -04:00
|
|
|
url: `${this.url}/project/${this.project_id}/doc/${this.doc_id}`,
|
|
|
|
json: {
|
|
|
|
lines: this.lines,
|
|
|
|
version: this.version,
|
|
|
|
ranges: this.ranges,
|
|
|
|
lastUpdatedAt: this.lastUpdatedAt,
|
|
|
|
lastUpdatedBy: this.lastUpdatedBy
|
|
|
|
},
|
|
|
|
method: "POST",
|
|
|
|
auth: {
|
|
|
|
user: this.user,
|
|
|
|
pass: this.pass,
|
2016-12-01 11:40:15 -05:00
|
|
|
sendImmediately: true
|
2020-05-06 06:10:51 -04:00
|
|
|
},
|
|
|
|
jar: false,
|
2016-12-01 11:40:15 -05:00
|
|
|
timeout: 5000
|
|
|
|
})
|
2020-05-06 06:10:51 -04:00
|
|
|
.should.equal(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should call the callback without error", function() {
|
|
|
|
return this.callback.calledWith(null).should.equal(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should time the execution", function() {
|
|
|
|
return this.Metrics.Timer.prototype.done.called.should.equal(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
return it("should increment the metric", function() {
|
|
|
|
return this.Metrics.inc.calledWith("setDoc", 1, {status: 200}).should.equal(true);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe("when request returns an error", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
this.error = new Error("oops");
|
|
|
|
this.error.code = "EOOPS";
|
|
|
|
this.request.callsArgWith(1, this.error, null, null);
|
|
|
|
return this.PersistenceManager.setDoc(this.project_id, this.doc_id, this.lines, this.version, this.ranges, this.lastUpdatedAt, this.lastUpdatedBy, this.callback);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should return the error", function() {
|
|
|
|
return this.callback.calledWith(this.error).should.equal(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should time the execution", function() {
|
|
|
|
return this.Metrics.Timer.prototype.done.called.should.equal(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
return it("should increment the metric", function() {
|
|
|
|
return this.Metrics.inc.calledWith("setDoc", 1, {status: "EOOPS"}).should.equal(true);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe("when the request returns 404", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
this.request.callsArgWith(1, null, {statusCode: 404}, "");
|
|
|
|
return this.PersistenceManager.setDoc(this.project_id, this.doc_id, this.lines, this.version, this.ranges, this.lastUpdatedAt, this.lastUpdatedBy, this.callback);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should return a NotFoundError", function() {
|
|
|
|
return this.callback.calledWith(new Errors.NotFoundError("not found")).should.equal(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should time the execution", function() {
|
|
|
|
return this.Metrics.Timer.prototype.done.called.should.equal(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
return it("should increment the metric", function() {
|
|
|
|
return this.Metrics.inc.calledWith("setDoc", 1, {status: 404}).should.equal(true);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
return describe("when the request returns an error status code", function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
this.request.callsArgWith(1, null, {statusCode: 500}, "");
|
|
|
|
return this.PersistenceManager.setDoc(this.project_id, this.doc_id, this.lines, this.version, this.ranges, this.lastUpdatedAt, this.lastUpdatedBy, this.callback);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should return an error", function() {
|
|
|
|
return this.callback.calledWith(new Error("web api error")).should.equal(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("should time the execution", function() {
|
|
|
|
return this.Metrics.Timer.prototype.done.called.should.equal(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
return it("should increment the metric", function() {
|
|
|
|
return this.Metrics.inc.calledWith("setDoc", 1, {status: 500}).should.equal(true);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|