| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- import async from 'async'
- import sinon from 'sinon'
- import { expect } from 'chai'
- import { strict as esmock } from 'esmock'
- const MODULE_PATH = '../../../../app/js/WebApiManager.js'
- describe('WebApiManager', function () {
- beforeEach(async function () {
- this.request = sinon.stub()
- this.settings = {
- apis: {
- web: {
- url: 'http://example.com',
- user: 'overleaf',
- pass: 'password',
- },
- },
- }
- this.callback = sinon.stub()
- this.userId = 'mock-user-id'
- this.projectId = 'mock-project-id'
- this.project = { features: 'mock-features' }
- this.olProjectId = 12345
- this.Metrics = { inc: sinon.stub() }
- this.RedisManager = {
- getCachedHistoryId: sinon.stub(),
- setCachedHistoryId: sinon.stub().yields(),
- }
- this.WebApiManager = await esmock(MODULE_PATH, {
- requestretry: this.request,
- '@overleaf/settings': this.settings,
- '@overleaf/metrics': this.Metrics,
- '../../../../app/js/RedisManager.js': this.RedisManager,
- })
- })
- describe('getHistoryId', function () {
- describe('when there is no cached value and the web request is successful', function () {
- beforeEach(function () {
- this.RedisManager.getCachedHistoryId
- .withArgs(this.projectId) // first call, no cached value returned
- .onCall(0)
- .yields()
- this.RedisManager.getCachedHistoryId
- .withArgs(this.projectId) // subsequent calls, return cached value
- .yields(null, this.olProjectId)
- this.RedisManager.getCachedHistoryId
- .withArgs('mock-project-id-2') // no cached value for other project
- .yields()
- this.request.yields(
- null,
- { statusCode: 200 },
- { overleaf: { history: { id: this.olProjectId } } }
- )
- })
- it('should only request project details once per project', function (done) {
- async.times(
- 5,
- (n, cb) => {
- this.WebApiManager.getHistoryId(this.projectId, cb)
- },
- () => {
- this.request.callCount.should.equal(1)
- this.WebApiManager.getHistoryId('mock-project-id-2', () => {
- this.request.callCount.should.equal(2)
- done()
- })
- }
- )
- })
- it('should cache the history id', function (done) {
- this.WebApiManager.getHistoryId(
- this.projectId,
- (error, olProjectId) => {
- if (error) return done(error)
- this.RedisManager.setCachedHistoryId
- .calledWith(this.projectId, olProjectId)
- .should.equal(true)
- done()
- }
- )
- })
- it('should call the callback with the project', function (done) {
- this.WebApiManager.getHistoryId(
- this.projectId,
- (error, olProjectId) => {
- expect(error).to.be.null
- expect(
- this.request.calledWithMatch({
- method: 'GET',
- url: `${this.settings.apis.web.url}/project/${this.projectId}/details`,
- json: true,
- auth: {
- user: this.settings.apis.web.user,
- pass: this.settings.apis.web.pass,
- sendImmediately: true,
- },
- })
- ).to.be.true
- expect(olProjectId).to.equal(this.olProjectId)
- done()
- }
- )
- })
- })
- describe('when the web API returns an error', function () {
- beforeEach(function () {
- this.error = new Error('something went wrong')
- this.request.yields(this.error)
- this.RedisManager.getCachedHistoryId.yields()
- this.WebApiManager.getHistoryId(this.projectId, this.callback)
- })
- it('should return an error to the callback', function () {
- this.callback.calledWith(this.error).should.equal(true)
- })
- })
- describe('when web returns a 404', function () {
- beforeEach(function () {
- this.request.callsArgWith(1, null, { statusCode: 404 }, '')
- this.RedisManager.getCachedHistoryId.yields()
- this.WebApiManager.getHistoryId(this.projectId, this.callback)
- })
- it('should return the callback with an error', function () {
- this.callback
- .calledWith(sinon.match.has('message', 'got a 404 from web api'))
- .should.equal(true)
- })
- })
- describe('when web returns a failure error code', function () {
- beforeEach(function () {
- this.RedisManager.getCachedHistoryId.yields()
- this.request.callsArgWith(
- 1,
- null,
- { statusCode: 500, attempts: 42 },
- ''
- )
- this.WebApiManager.getHistoryId(this.projectId, this.callback)
- })
- it('should return the callback with an error', function () {
- this.callback
- .calledWith(
- sinon.match.has(
- 'message',
- 'web returned a non-success status code: 500 (attempts: 42)'
- )
- )
- .should.equal(true)
- })
- })
- })
- })
|