mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-12 13:13:45 +01:00
Merge pull request #36223 from overleaf/jpa-zod-web-core-2
[web] core-2: adopt strict zod schema and extend test coverage GitOrigin-RevId: f26d349fefb6bf9e042cb39117395120c3f7c877
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
import { expect } from 'chai'
|
||||
import UserHelper from './helpers/User.mjs'
|
||||
import { expectValidationErrorRaw } from '@overleaf/validation-tools/testUtils.js'
|
||||
|
||||
const User = UserHelper.promises
|
||||
|
||||
describe('References', function () {
|
||||
let owner, projectId
|
||||
|
||||
beforeEach(async function () {
|
||||
owner = new User()
|
||||
await owner.login()
|
||||
projectId = await owner.createProject('references-test', {
|
||||
template: 'blank',
|
||||
})
|
||||
})
|
||||
|
||||
describe('POST /project/:Project_id/references/indexAll', function () {
|
||||
it('should return the projectId and empty keys', async function () {
|
||||
const { response, body } = await owner.doRequest('post', {
|
||||
url: `/project/${projectId}/references/indexAll`,
|
||||
json: { shouldBroadcast: false },
|
||||
})
|
||||
expect(response.statusCode).to.equal(200)
|
||||
expect(body).to.deep.equal({ projectId, keys: [] })
|
||||
})
|
||||
|
||||
it('should reject a malformed project id with 404', async function () {
|
||||
const { response, body } = await owner.doRequest('post', {
|
||||
url: `/project/not-an-object-id/references/indexAll`,
|
||||
json: { shouldBroadcast: false },
|
||||
})
|
||||
expectValidationErrorRaw(
|
||||
{ statusCode: response.statusCode, body },
|
||||
404,
|
||||
'Project_id'
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,5 +1,6 @@
|
||||
import { beforeEach, describe, it, vi } from 'vitest'
|
||||
import { afterEach, beforeEach, describe, it, vi } from 'vitest'
|
||||
import sinon from 'sinon'
|
||||
import { setReqValidationModeForTests } from '@overleaf/validation-tools'
|
||||
import MockRequest from '../helpers/MockRequest.mjs'
|
||||
import MockResponse from '../helpers/MockResponse.mjs'
|
||||
const modulePath =
|
||||
@@ -7,7 +8,8 @@ const modulePath =
|
||||
|
||||
describe('ReferencesController', function () {
|
||||
beforeEach(async function (ctx) {
|
||||
ctx.projectId = '2222'
|
||||
// Project_id is validated as a Mongo ObjectId
|
||||
ctx.projectId = '507f191e810c19729de860ea'
|
||||
|
||||
vi.doMock('@overleaf/settings', () => ({
|
||||
default: (ctx.settings = {
|
||||
@@ -142,5 +144,27 @@ describe('ReferencesController', function () {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('request validation', function () {
|
||||
beforeEach(function () {
|
||||
setReqValidationModeForTests('enforce')
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
setReqValidationModeForTests(null)
|
||||
})
|
||||
|
||||
it('should reject a malformed project id', function (ctx) {
|
||||
ctx.req.params.Project_id = 'not-an-object-id'
|
||||
;(() =>
|
||||
ctx.controller.indexAll(ctx.req, ctx.res, ctx.next)).should.throw()
|
||||
})
|
||||
|
||||
it('should reject an unrecognized body field', function (ctx) {
|
||||
ctx.req.body.unexpectedField = 'nope'
|
||||
;(() =>
|
||||
ctx.controller.indexAll(ctx.req, ctx.res, ctx.next)).should.throw()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import mongodb from 'mongodb-legacy'
|
||||
import sinon from 'sinon'
|
||||
import Errors from '../../../../app/src/Features/Errors/Errors.js'
|
||||
import MockResponse from '../helpers/MockResponse.mjs'
|
||||
import MockRequest from '../helpers/MockRequest.mjs'
|
||||
import { asZodError } from '@overleaf/validation-tools/testUtils.js'
|
||||
import {
|
||||
getRawReqInput,
|
||||
setReqValidationModeForTests,
|
||||
} from '@overleaf/validation-tools'
|
||||
|
||||
const ObjectId = mongodb.ObjectId
|
||||
|
||||
@@ -132,7 +136,7 @@ describe('TpdsController', function () {
|
||||
await new Promise(resolve => {
|
||||
const res = new MockResponse(vi)
|
||||
const req = new MockRequest(vi)
|
||||
req.params.user_id = ctx.user_id
|
||||
req.params = { ...getRawReqInput(req).params, user_id: ctx.user_id }
|
||||
req.body = { projectName: 'foo' }
|
||||
res.callback = err => {
|
||||
if (err) resolve(err)
|
||||
@@ -165,6 +169,10 @@ describe('TpdsController', function () {
|
||||
}
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
setReqValidationModeForTests(null)
|
||||
})
|
||||
|
||||
it('should throw without any input', async function (ctx) {
|
||||
const next = sinon.stub()
|
||||
await ctx.TpdsController.resolveProject(ctx.req, {}, next)
|
||||
@@ -278,6 +286,41 @@ describe('TpdsController', function () {
|
||||
ctx.TpdsController.resolveProject(ctx.req, res)
|
||||
})
|
||||
})
|
||||
|
||||
it('should still resolve a body with an unrecognized field in log mode', async function (ctx) {
|
||||
setReqValidationModeForTests('log')
|
||||
await new Promise(resolve => {
|
||||
ctx.req.body = { projectName: 'projectName', extra: 'nope' }
|
||||
const res = {
|
||||
json: payload => {
|
||||
expect(payload).to.deep.equal({
|
||||
status: 'success',
|
||||
projectId: ctx.resolvedProject._id.toString(),
|
||||
historyId: 42,
|
||||
otMigrationStage: 1,
|
||||
})
|
||||
resolve()
|
||||
},
|
||||
}
|
||||
ctx.TpdsController.resolveProject(ctx.req, res)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when enforced', function () {
|
||||
afterEach(function () {
|
||||
setReqValidationModeForTests(null)
|
||||
})
|
||||
|
||||
it('should reject a body with an unrecognized field', async function (ctx) {
|
||||
setReqValidationModeForTests('enforce')
|
||||
ctx.req.body = { projectName: 'projectName', extra: 'nope' }
|
||||
const next = sinon.stub()
|
||||
await ctx.TpdsController.resolveProject(ctx.req, {}, next)
|
||||
expect(next).to.have.been.calledWithMatch({
|
||||
name: 'InvalidRequestError',
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('getting an update', function () {
|
||||
@@ -286,7 +329,7 @@ describe('TpdsController', function () {
|
||||
ctx.path = '/here.txt'
|
||||
ctx.req = {
|
||||
params: {
|
||||
0: `${ctx.projectName}${ctx.path}`,
|
||||
path: `${ctx.projectName}${ctx.path}`,
|
||||
user_id: ctx.user_id,
|
||||
project_id: '',
|
||||
},
|
||||
@@ -341,9 +384,11 @@ describe('TpdsController', function () {
|
||||
it('should process the update with the update receiver by id', async function (ctx) {
|
||||
await new Promise(resolve => {
|
||||
const path = '/here.txt'
|
||||
// project_id is validated as a Mongo ObjectId
|
||||
const projectId = new ObjectId().toString()
|
||||
const req = {
|
||||
pause() {},
|
||||
params: { 0: path, user_id: ctx.user_id, project_id: '123' },
|
||||
params: { path, user_id: ctx.user_id, project_id: projectId },
|
||||
session: {
|
||||
destroy() {},
|
||||
},
|
||||
@@ -355,7 +400,7 @@ describe('TpdsController', function () {
|
||||
json: () => {
|
||||
ctx.TpdsUpdateHandler.promises.newUpdate.should.have.been.calledWith(
|
||||
ctx.user_id,
|
||||
'123',
|
||||
projectId,
|
||||
'', // projectName
|
||||
'/here.txt',
|
||||
req,
|
||||
@@ -400,7 +445,7 @@ describe('TpdsController', function () {
|
||||
await new Promise(resolve => {
|
||||
const path = '/projectName/here.txt'
|
||||
const req = {
|
||||
params: { 0: path, user_id: ctx.user_id, project_id: '' },
|
||||
params: { path, user_id: ctx.user_id, project_id: '' },
|
||||
session: {
|
||||
destroy() {},
|
||||
},
|
||||
@@ -429,8 +474,10 @@ describe('TpdsController', function () {
|
||||
it('should process the delete with the update receiver by id', async function (ctx) {
|
||||
await new Promise(resolve => {
|
||||
const path = '/here.txt'
|
||||
// project_id is validated as a Mongo ObjectId
|
||||
const projectId = new ObjectId().toString()
|
||||
const req = {
|
||||
params: { 0: path, user_id: ctx.user_id, project_id: '123' },
|
||||
params: { path, user_id: ctx.user_id, project_id: projectId },
|
||||
session: {
|
||||
destroy() {},
|
||||
},
|
||||
@@ -442,7 +489,7 @@ describe('TpdsController', function () {
|
||||
sendStatus: () => {
|
||||
ctx.TpdsUpdateHandler.promises.deleteUpdate.should.have.been.calledWith(
|
||||
ctx.user_id,
|
||||
'123',
|
||||
projectId,
|
||||
'', // projectName
|
||||
'/here.txt',
|
||||
ctx.source
|
||||
@@ -525,7 +572,7 @@ describe('TpdsController', function () {
|
||||
describe('parseParams', function () {
|
||||
it('should take the project name off the start and replace with slash', function (ctx) {
|
||||
const path = 'noSlashHere'
|
||||
const req = { params: { 0: path, user_id: ctx.user_id } }
|
||||
const req = { params: { path, user_id: ctx.user_id } }
|
||||
const result = ctx.TpdsController.parseParams(req)
|
||||
result.userId.should.equal(ctx.user_id)
|
||||
result.filePath.should.equal('/')
|
||||
@@ -534,7 +581,7 @@ describe('TpdsController', function () {
|
||||
|
||||
it('should take the project name off the start and it with no slashes in', function (ctx) {
|
||||
const path = '/project/file.tex'
|
||||
const req = { params: { 0: path, user_id: ctx.user_id } }
|
||||
const req = { params: { path, user_id: ctx.user_id } }
|
||||
const result = ctx.TpdsController.parseParams(req)
|
||||
result.userId.should.equal(ctx.user_id)
|
||||
result.filePath.should.equal('/file.tex')
|
||||
@@ -543,7 +590,7 @@ describe('TpdsController', function () {
|
||||
|
||||
it('should take the project name of and return a slash for the file path', function (ctx) {
|
||||
const path = '/project_name'
|
||||
const req = { params: { 0: path, user_id: ctx.user_id } }
|
||||
const req = { params: { path, user_id: ctx.user_id } }
|
||||
const result = ctx.TpdsController.parseParams(req)
|
||||
result.projectName.should.equal('project_name')
|
||||
result.filePath.should.equal('/')
|
||||
@@ -554,8 +601,9 @@ describe('TpdsController', function () {
|
||||
beforeEach(async function (ctx) {
|
||||
ctx.req = {
|
||||
params: {
|
||||
0: (ctx.path = 'chapters/main.tex'),
|
||||
project_id: (ctx.project_id = 'project-id-123'),
|
||||
path: (ctx.path = 'chapters/main.tex'),
|
||||
// project_id is validated as a Mongo ObjectId
|
||||
project_id: (ctx.project_id = new ObjectId().toString()),
|
||||
},
|
||||
session: {
|
||||
destroy: sinon.stub(),
|
||||
@@ -595,8 +643,9 @@ describe('TpdsController', function () {
|
||||
beforeEach(async function (ctx) {
|
||||
ctx.req = {
|
||||
params: {
|
||||
0: (ctx.path = 'chapters/main.tex'),
|
||||
project_id: (ctx.project_id = 'project-id-123'),
|
||||
path: (ctx.path = 'chapters/main.tex'),
|
||||
// project_id is validated as a Mongo ObjectId
|
||||
project_id: (ctx.project_id = new ObjectId().toString()),
|
||||
},
|
||||
session: {
|
||||
destroy: sinon.stub(),
|
||||
|
||||
Reference in New Issue
Block a user