overleaf/services/document-updater/test/unit/js/PersistenceManager/PersistenceManagerTests.js
Eric Mc Sween 4d70bd664f Reintroduce Node 12 and metrics upgrades
These changes were previously merged, not deployed, and reverted. This
reverts the revert.

This reverts commit a6b8c6c658b33b6eee78b8b99e43308f32211ae2, reversing
changes made to 93c98921372eed4244d22fce800716cb27eca299.
2021-04-01 15:51:00 -04:00

443 lines
13 KiB
JavaScript

/* eslint-disable
no-return-assign,
no-unused-vars,
*/
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
/*
* 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 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
})()),
inc: sinon.stub()
}),
'./Errors': Errors
}
})
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')
}
})
})
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
.calledWith({
url: `${this.url}/project/${this.project_id}/doc/${this.doc_id}`,
method: 'GET',
headers: {
accept: 'application/json'
},
auth: {
user: this.user,
pass: this.pass,
sendImmediately: true
},
jar: false,
timeout: 5000
})
.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 a generic connection error', function () {
return this.callback
.calledWith(
sinon.match
.instanceOf(Error)
.and(sinon.match.has('message', 'error connecting to web API'))
)
.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(sinon.match.instanceOf(Errors.NotFoundError))
.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(sinon.match.instanceOf(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(sinon.match.instanceOf(Error))
.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(sinon.match.instanceOf(Error))
.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(sinon.match.instanceOf(Error))
.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
.calledWith({
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,
sendImmediately: true
},
jar: false,
timeout: 5000
})
.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 a generic connection error', function () {
return this.callback
.calledWith(
sinon.match
.instanceOf(Error)
.and(sinon.match.has('message', 'error connecting to web API'))
)
.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(sinon.match.instanceOf(Errors.NotFoundError))
.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(sinon.match.instanceOf(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)
})
})
})
})