mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-29 17:13:38 -05:00
d12a0b5f07
Promisify WebApiManager GitOrigin-RevId: 95addc9442845252aa51c353676486b2dbce0662
153 lines
4.9 KiB
JavaScript
153 lines
4.9 KiB
JavaScript
import sinon from 'sinon'
|
|
import { expect } from 'chai'
|
|
import { strict as esmock } from 'esmock'
|
|
import { RequestFailedError } from '@overleaf/fetch-utils'
|
|
|
|
const MODULE_PATH = '../../../../app/js/WebApiManager.js'
|
|
|
|
describe('WebApiManager', function () {
|
|
beforeEach(async function () {
|
|
this.settings = {
|
|
apis: {
|
|
web: {
|
|
url: 'http://example.com',
|
|
user: 'overleaf',
|
|
pass: 'password',
|
|
},
|
|
},
|
|
}
|
|
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 = {
|
|
promises: {
|
|
getCachedHistoryId: sinon.stub(),
|
|
setCachedHistoryId: sinon.stub().resolves(),
|
|
},
|
|
}
|
|
this.FetchUtils = {
|
|
fetchNothing: sinon.stub().resolves(),
|
|
fetchJson: sinon.stub(),
|
|
RequestFailedError,
|
|
}
|
|
this.WebApiManager = await esmock(MODULE_PATH, {
|
|
'@overleaf/fetch-utils': this.FetchUtils,
|
|
'@overleaf/settings': this.settings,
|
|
'@overleaf/metrics': this.Metrics,
|
|
'../../../../app/js/RedisManager.js': this.RedisManager,
|
|
})
|
|
this.WebApiManager.setRetryTimeoutMs(100)
|
|
})
|
|
|
|
describe('getHistoryId', function () {
|
|
describe('when there is no cached value and the web request is successful', function () {
|
|
beforeEach(function () {
|
|
this.RedisManager.promises.getCachedHistoryId
|
|
.withArgs(this.projectId) // first call, no cached value returned
|
|
.onCall(0)
|
|
.resolves(null)
|
|
this.RedisManager.promises.getCachedHistoryId
|
|
.withArgs(this.projectId) // subsequent calls, return cached value
|
|
.resolves(this.olProjectId)
|
|
this.RedisManager.promises.getCachedHistoryId
|
|
.withArgs('mock-project-id-2') // no cached value for other project
|
|
.resolves(null)
|
|
this.FetchUtils.fetchJson.resolves({
|
|
overleaf: { history: { id: this.olProjectId } },
|
|
})
|
|
})
|
|
|
|
it('should only request project details once per project', async function () {
|
|
for (let i = 0; i < 5; i++) {
|
|
await this.WebApiManager.promises.getHistoryId(this.projectId)
|
|
}
|
|
this.FetchUtils.fetchJson.should.have.been.calledOnce
|
|
|
|
await this.WebApiManager.promises.getHistoryId('mock-project-id-2')
|
|
this.FetchUtils.fetchJson.should.have.been.calledTwice
|
|
})
|
|
|
|
it('should cache the history id', async function () {
|
|
const olProjectId = await this.WebApiManager.promises.getHistoryId(
|
|
this.projectId
|
|
)
|
|
this.RedisManager.promises.setCachedHistoryId
|
|
.calledWith(this.projectId, olProjectId)
|
|
.should.equal(true)
|
|
})
|
|
|
|
it("should return the project's history id", async function () {
|
|
const olProjectId = await this.WebApiManager.promises.getHistoryId(
|
|
this.projectId
|
|
)
|
|
|
|
expect(this.FetchUtils.fetchJson).to.have.been.calledWithMatch(
|
|
`${this.settings.apis.web.url}/project/${this.projectId}/details`,
|
|
{
|
|
basicAuth: {
|
|
user: this.settings.apis.web.user,
|
|
password: this.settings.apis.web.pass,
|
|
},
|
|
}
|
|
)
|
|
expect(olProjectId).to.equal(this.olProjectId)
|
|
})
|
|
})
|
|
|
|
describe('when the web API returns an error', function () {
|
|
beforeEach(function () {
|
|
this.error = new Error('something went wrong')
|
|
this.FetchUtils.fetchJson.rejects(this.error)
|
|
this.RedisManager.promises.getCachedHistoryId.resolves(null)
|
|
})
|
|
|
|
it('should throw an error', async function () {
|
|
await expect(
|
|
this.WebApiManager.promises.getHistoryId(this.projectId)
|
|
).to.be.rejectedWith(this.error)
|
|
})
|
|
})
|
|
|
|
describe('when web returns a 404', function () {
|
|
beforeEach(function () {
|
|
this.FetchUtils.fetchJson.rejects(
|
|
new RequestFailedError(
|
|
'http://some-url',
|
|
{},
|
|
{ status: 404 },
|
|
'Not found'
|
|
)
|
|
)
|
|
this.RedisManager.promises.getCachedHistoryId.resolves(null)
|
|
})
|
|
|
|
it('should throw an error', async function () {
|
|
await expect(
|
|
this.WebApiManager.promises.getHistoryId(this.projectId)
|
|
).to.be.rejectedWith('got a 404 from web api')
|
|
})
|
|
})
|
|
|
|
describe('when web returns a failure error code', function () {
|
|
beforeEach(function () {
|
|
this.RedisManager.promises.getCachedHistoryId.resolves(null)
|
|
this.FetchUtils.fetchJson.rejects(
|
|
new RequestFailedError(
|
|
'http://some-url',
|
|
{},
|
|
{ status: 500 },
|
|
'Error'
|
|
)
|
|
)
|
|
})
|
|
|
|
it('should throw an error', async function () {
|
|
await expect(
|
|
this.WebApiManager.promises.getHistoryId(this.projectId)
|
|
).to.be.rejectedWith(RequestFailedError)
|
|
})
|
|
})
|
|
})
|
|
})
|