Files
overleaf-cep/services/real-time/test/unit/js/WebApiManager.test.js
Andrew Rumble 3073c94522 Merge pull request #30215 from overleaf/ar/convert-real-time-to-esm
[real-time] convert real time to esm

GitOrigin-RevId: 7cc530cc977549d3274be42585735e1fd72cad5f
2026-01-13 09:06:30 +00:00

256 lines
7.4 KiB
JavaScript

import { vi, describe, beforeEach, it } from 'vitest'
/* 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
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
import sinon from 'sinon'
const modulePath = '../../../app/js/WebApiManager.js'
describe('WebApiManager', function () {
beforeEach(async function (ctx) {
ctx.project_id = 'project-id-123'
ctx.user_id = 'user-id-123'
ctx.user = { _id: ctx.user_id }
ctx.callback = sinon.stub()
vi.doMock('request', () => ({
default: (ctx.request = {}),
}))
vi.doMock('@overleaf/settings', () => ({
default: (ctx.settings = {
apis: {
web: {
url: 'http://web.example.com',
user: 'username',
pass: 'password',
},
},
}),
}))
return (ctx.WebApiManager = (await import(modulePath)).default)
})
return describe('joinProject', function () {
describe('successfully', function () {
beforeEach(function (ctx) {
ctx.response = {
project: { name: 'Test project' },
privilegeLevel: 'owner',
isRestrictedUser: true,
isTokenMember: true,
isInvitedMember: true,
}
ctx.request.post = sinon
.stub()
.callsArgWith(1, null, { statusCode: 200 }, ctx.response)
return ctx.WebApiManager.joinProject(
ctx.project_id,
ctx.user,
ctx.callback
)
})
it('should send a request to web to join the project', function (ctx) {
return ctx.request.post
.calledWith({
url: `${ctx.settings.apis.web.url}/project/${ctx.project_id}/join`,
auth: {
user: ctx.settings.apis.web.user,
pass: ctx.settings.apis.web.pass,
sendImmediately: true,
},
json: {
userId: ctx.user_id,
anonymousAccessToken: undefined,
},
jar: false,
})
.should.equal(true)
})
return it('should return the project, privilegeLevel, and restricted flag', function (ctx) {
return ctx.callback
.calledWith(null, ctx.response.project, ctx.response.privilegeLevel, {
isRestrictedUser: ctx.response.isRestrictedUser,
isTokenMember: ctx.response.isTokenMember,
isInvitedMember: ctx.response.isInvitedMember,
})
.should.equal(true)
})
})
describe('with anon user', function () {
beforeEach(function (ctx) {
ctx.user_id = 'anonymous-user'
ctx.token = 'a-ro-token'
ctx.user = {
_id: ctx.user_id,
anonymousAccessToken: ctx.token,
}
ctx.response = {
project: { name: 'Test project' },
privilegeLevel: 'readOnly',
isRestrictedUser: true,
isTokenMember: false,
isInvitedMember: false,
}
ctx.request.post = sinon
.stub()
.yields(null, { statusCode: 200 }, ctx.response)
ctx.WebApiManager.joinProject(ctx.project_id, ctx.user, ctx.callback)
})
it('should send a request to web to join the project', function (ctx) {
ctx.request.post.should.have.been.calledWith({
url: `${ctx.settings.apis.web.url}/project/${ctx.project_id}/join`,
auth: {
user: ctx.settings.apis.web.user,
pass: ctx.settings.apis.web.pass,
sendImmediately: true,
},
json: {
userId: ctx.user_id,
anonymousAccessToken: ctx.token,
},
jar: false,
})
})
it('should return the project, privilegeLevel, and restricted flag', function (ctx) {
ctx.callback.should.have.been.calledWith(
null,
ctx.response.project,
ctx.response.privilegeLevel,
{
isRestrictedUser: ctx.response.isRestrictedUser,
isTokenMember: ctx.response.isTokenMember,
isInvitedMember: ctx.response.isInvitedMember,
}
)
})
})
describe('when web replies with a 403', function () {
beforeEach(function (ctx) {
ctx.request.post = sinon
.stub()
.callsArgWith(1, null, { statusCode: 403 }, null)
ctx.WebApiManager.joinProject(ctx.project_id, ctx.user_id, ctx.callback)
})
it('should call the callback with an error', function (ctx) {
ctx.callback
.calledWith(
sinon.match({
message: 'not authorized',
})
)
.should.equal(true)
})
})
describe('when web replies with a 404', function () {
beforeEach(function (ctx) {
ctx.request.post = sinon
.stub()
.callsArgWith(1, null, { statusCode: 404 }, null)
ctx.WebApiManager.joinProject(ctx.project_id, ctx.user_id, ctx.callback)
})
it('should call the callback with an error', function (ctx) {
ctx.callback
.calledWith(
sinon.match({
message: 'project not found',
info: { code: 'ProjectNotFound' },
})
)
.should.equal(true)
})
})
describe('with an error from web', function () {
beforeEach(function (ctx) {
ctx.request.post = sinon
.stub()
.callsArgWith(1, null, { statusCode: 500 }, null)
return ctx.WebApiManager.joinProject(
ctx.project_id,
ctx.user_id,
ctx.callback
)
})
return it('should call the callback with an error', function (ctx) {
return ctx.callback
.calledWith(
sinon.match({
message: 'non-success status code from web',
info: { statusCode: 500 },
})
)
.should.equal(true)
})
})
describe('with no data from web', function () {
beforeEach(function (ctx) {
ctx.request.post = sinon
.stub()
.callsArgWith(1, null, { statusCode: 200 }, null)
return ctx.WebApiManager.joinProject(
ctx.project_id,
ctx.user_id,
ctx.callback
)
})
return it('should call the callback with an error', function (ctx) {
return ctx.callback
.calledWith(
sinon.match({
message: 'no data returned from joinProject request',
})
)
.should.equal(true)
})
})
return describe('when the project is over its rate limit', function () {
beforeEach(function (ctx) {
ctx.request.post = sinon
.stub()
.callsArgWith(1, null, { statusCode: 429 }, null)
return ctx.WebApiManager.joinProject(
ctx.project_id,
ctx.user_id,
ctx.callback
)
})
return it('should call the callback with a TooManyRequests error code', function (ctx) {
return ctx.callback
.calledWith(
sinon.match({
message: 'rate-limit hit when joining project',
info: {
code: 'TooManyRequests',
},
})
)
.should.equal(true)
})
})
})
})