| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374 |
- const { expect } = require('chai')
- const MockResponse = require('../helpers/MockResponse')
- const MockRequest = require('../helpers/MockRequest')
- const SandboxedModule = require('sandboxed-module')
- const modulePath = '../../../../app/src/Features/Errors/HttpErrorHandler.js'
- describe('HttpErrorHandler', function () {
- beforeEach(function () {
- this.req = new MockRequest()
- this.res = new MockResponse()
- this.HttpErrorHandler = SandboxedModule.require(modulePath, {
- requires: {
- '@overleaf/settings': {
- appName: 'Overleaf',
- statusPageUrl: 'https://status.overlaf.com',
- },
- },
- })
- })
- describe('handleErrorByStatusCode', function () {
- it('returns the http status code of 400 errors', function () {
- const err = new Error()
- this.HttpErrorHandler.handleErrorByStatusCode(
- this.req,
- this.res,
- err,
- 400
- )
- expect(this.res.statusCode).to.equal(400)
- })
- it('returns the http status code of 500 errors', function () {
- const err = new Error()
- this.HttpErrorHandler.handleErrorByStatusCode(
- this.req,
- this.res,
- err,
- 500
- )
- expect(this.res.statusCode).to.equal(500)
- })
- it('returns the http status code of any 5xx error', function () {
- const err = new Error()
- this.HttpErrorHandler.handleErrorByStatusCode(
- this.req,
- this.res,
- err,
- 588
- )
- expect(this.res.statusCode).to.equal(588)
- })
- it('returns the http status code of any 4xx error', function () {
- const err = new Error()
- this.HttpErrorHandler.handleErrorByStatusCode(
- this.req,
- this.res,
- err,
- 488
- )
- expect(this.res.statusCode).to.equal(488)
- })
- it('returns 500 for http status codes smaller than 400', function () {
- const err = new Error()
- this.HttpErrorHandler.handleErrorByStatusCode(
- this.req,
- this.res,
- err,
- 302
- )
- expect(this.res.statusCode).to.equal(500)
- })
- it('returns 500 for http status codes larger than 600', function () {
- const err = new Error()
- this.HttpErrorHandler.handleErrorByStatusCode(
- this.req,
- this.res,
- err,
- 302
- )
- expect(this.res.statusCode).to.equal(500)
- })
- it('returns 500 when the error has no http status code', function () {
- const err = new Error()
- this.HttpErrorHandler.handleErrorByStatusCode(this.req, this.res, err)
- expect(this.res.statusCode).to.equal(500)
- })
- it('uses the conflict() error handler', function () {
- const err = new Error()
- this.HttpErrorHandler.handleErrorByStatusCode(
- this.req,
- this.res,
- err,
- 409
- )
- expect(this.res.body).to.equal('conflict')
- })
- it('uses the forbidden() error handler', function () {
- const err = new Error()
- this.HttpErrorHandler.handleErrorByStatusCode(
- this.req,
- this.res,
- err,
- 403
- )
- expect(this.res.body).to.equal('restricted')
- })
- it('uses the notFound() error handler', function () {
- const err = new Error()
- this.HttpErrorHandler.handleErrorByStatusCode(
- this.req,
- this.res,
- err,
- 404
- )
- expect(this.res.body).to.equal('not found')
- })
- it('uses the unprocessableEntity() error handler', function () {
- const err = new Error()
- err.httpStatusCode = 422
- this.HttpErrorHandler.handleErrorByStatusCode(
- this.req,
- this.res,
- err,
- 422
- )
- expect(this.res.body).to.equal('unprocessable entity')
- })
- })
- describe('badRequest', function () {
- it('returns 400', function () {
- this.HttpErrorHandler.badRequest(this.req, this.res)
- expect(this.res.statusCode).to.equal(400)
- })
- it('should print a message when no content-type is included', function () {
- this.HttpErrorHandler.badRequest(this.req, this.res)
- expect(this.res.body).to.equal('client error')
- })
- it("should render a template including the error message when content-type is 'html'", function () {
- this.req.accepts = () => 'html'
- this.HttpErrorHandler.badRequest(this.req, this.res, 'an error')
- expect(this.res.renderedTemplate).to.equal('general/400')
- expect(this.res.renderedVariables).to.deep.equal({
- title: 'Client Error',
- message: 'an error',
- })
- })
- it("should render a default template when content-type is 'html' and no message is provided", function () {
- this.req.accepts = () => 'html'
- this.HttpErrorHandler.badRequest(this.req, this.res)
- expect(this.res.renderedTemplate).to.equal('general/400')
- expect(this.res.renderedVariables).to.deep.equal({
- title: 'Client Error',
- message: undefined,
- })
- })
- it("should return a json object when content-type is 'json'", function () {
- this.req.accepts = () => 'json'
- this.HttpErrorHandler.badRequest(this.req, this.res, 'an error', {
- foo: 'bar',
- })
- expect(JSON.parse(this.res.body)).to.deep.equal({
- message: 'an error',
- foo: 'bar',
- })
- })
- it("should return an empty json object when content-type is 'json' and no message and info are provided", function () {
- this.req.accepts = () => 'json'
- this.HttpErrorHandler.badRequest(this.req, this.res)
- expect(JSON.parse(this.res.body)).to.deep.equal({})
- })
- })
- describe('conflict', function () {
- it('returns 409', function () {
- this.HttpErrorHandler.conflict(this.req, this.res)
- expect(this.res.statusCode).to.equal(409)
- })
- it('should print a message when no content-type is included', function () {
- this.HttpErrorHandler.conflict(this.req, this.res)
- expect(this.res.body).to.equal('conflict')
- })
- it("should render a template including the error message when content-type is 'html'", function () {
- this.req.accepts = () => 'html'
- this.HttpErrorHandler.unprocessableEntity(this.req, this.res, 'an error')
- expect(this.res.renderedTemplate).to.equal('general/400')
- expect(this.res.renderedVariables).to.deep.equal({
- title: 'Client Error',
- message: 'an error',
- })
- })
- it("should return a json object when content-type is 'json'", function () {
- this.req.accepts = () => 'json'
- this.HttpErrorHandler.unprocessableEntity(
- this.req,
- this.res,
- 'an error',
- {
- foo: 'bar',
- }
- )
- expect(JSON.parse(this.res.body)).to.deep.equal({
- message: 'an error',
- foo: 'bar',
- })
- })
- })
- describe('forbidden', function () {
- it('returns 403', function () {
- this.HttpErrorHandler.forbidden(this.req, this.res)
- expect(this.res.statusCode).to.equal(403)
- })
- it('should print a message when no content-type is included', function () {
- this.HttpErrorHandler.forbidden(this.req, this.res)
- expect(this.res.body).to.equal('restricted')
- })
- it("should render a template when content-type is 'html'", function () {
- this.req.accepts = () => 'html'
- this.HttpErrorHandler.forbidden(this.req, this.res)
- expect(this.res.renderedTemplate).to.equal('user/restricted')
- expect(this.res.renderedVariables).to.deep.equal({
- title: 'restricted',
- })
- })
- it("should return a json object when content-type is 'json'", function () {
- this.req.accepts = () => 'json'
- this.HttpErrorHandler.forbidden(this.req, this.res, 'an error', {
- foo: 'bar',
- })
- expect(JSON.parse(this.res.body)).to.deep.equal({
- message: 'an error',
- foo: 'bar',
- })
- })
- })
- describe('notFound', function () {
- it('returns 404', function () {
- this.HttpErrorHandler.notFound(this.req, this.res)
- expect(this.res.statusCode).to.equal(404)
- })
- it('should print a message when no content-type is included', function () {
- this.HttpErrorHandler.notFound(this.req, this.res)
- expect(this.res.body).to.equal('not found')
- })
- it("should render a template when content-type is 'html'", function () {
- this.req.accepts = () => 'html'
- this.HttpErrorHandler.notFound(this.req, this.res)
- expect(this.res.renderedTemplate).to.equal('general/404')
- expect(this.res.renderedVariables).to.deep.equal({
- title: 'page_not_found',
- })
- })
- it("should return a json object when content-type is 'json'", function () {
- this.req.accepts = () => 'json'
- this.HttpErrorHandler.notFound(this.req, this.res, 'an error', {
- foo: 'bar',
- })
- expect(JSON.parse(this.res.body)).to.deep.equal({
- message: 'an error',
- foo: 'bar',
- })
- })
- })
- describe('unprocessableEntity', function () {
- it('returns 422', function () {
- this.HttpErrorHandler.unprocessableEntity(this.req, this.res)
- expect(this.res.statusCode).to.equal(422)
- })
- it('should print a message when no content-type is included', function () {
- this.HttpErrorHandler.unprocessableEntity(this.req, this.res)
- expect(this.res.body).to.equal('unprocessable entity')
- })
- it("should render a template including the error message when content-type is 'html'", function () {
- this.req.accepts = () => 'html'
- this.HttpErrorHandler.unprocessableEntity(this.req, this.res, 'an error')
- expect(this.res.renderedTemplate).to.equal('general/400')
- expect(this.res.renderedVariables).to.deep.equal({
- title: 'Client Error',
- message: 'an error',
- })
- })
- it("should return a json object when content-type is 'json'", function () {
- this.req.accepts = () => 'json'
- this.HttpErrorHandler.unprocessableEntity(
- this.req,
- this.res,
- 'an error',
- {
- foo: 'bar',
- }
- )
- expect(JSON.parse(this.res.body)).to.deep.equal({
- message: 'an error',
- foo: 'bar',
- })
- })
- describe('legacyInternal', function () {
- it('returns 500', function () {
- this.HttpErrorHandler.legacyInternal(this.req, this.res, new Error())
- expect(this.res.statusCode).to.equal(500)
- })
- it('should send the error to the logger', function () {
- const error = new Error('message')
- this.HttpErrorHandler.legacyInternal(
- this.req,
- this.res,
- 'message',
- error
- )
- expect(this.logger.error).to.have.been.calledWith(error)
- })
- it('should print a message when no content-type is included', function () {
- this.HttpErrorHandler.legacyInternal(this.req, this.res, new Error())
- expect(this.res.body).to.equal('internal server error')
- })
- it("should render a template when content-type is 'html'", function () {
- this.req.accepts = () => 'html'
- this.HttpErrorHandler.legacyInternal(this.req, this.res, new Error())
- expect(this.res.renderedTemplate).to.equal('general/500')
- expect(this.res.renderedVariables).to.deep.equal({
- title: 'Server Error',
- })
- })
- it("should return a json object with a static message when content-type is 'json'", function () {
- this.req.accepts = () => 'json'
- this.HttpErrorHandler.legacyInternal(
- this.req,
- this.res,
- 'a message',
- new Error()
- )
- expect(JSON.parse(this.res.body)).to.deep.equal({
- message: 'a message',
- })
- })
- })
- })
- })
|