HttpErrorHandlerTests.js 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. const { expect } = require('chai')
  2. const sinon = require('sinon')
  3. const MockResponse = require('../helpers/MockResponse')
  4. const MockRequest = require('../helpers/MockRequest')
  5. const SandboxedModule = require('sandboxed-module')
  6. const modulePath = '../../../../app/src/Features/Errors/HttpErrorHandler.js'
  7. describe('HttpErrorHandler', function() {
  8. beforeEach(function() {
  9. this.req = new MockRequest()
  10. this.res = new MockResponse()
  11. this.logger = {
  12. warn() {},
  13. error() {}
  14. }
  15. this.HttpErrorHandler = SandboxedModule.require(modulePath, {
  16. globals: { console },
  17. requires: {
  18. 'logger-sharelatex': this.logger
  19. }
  20. })
  21. })
  22. describe('badRequest', function() {
  23. it('returns 400', function() {
  24. this.HttpErrorHandler.badRequest(this.req, this.res)
  25. expect(this.res.statusCode).to.equal(400)
  26. })
  27. it('should print a message when no content-type is included', function() {
  28. this.HttpErrorHandler.badRequest(this.req, this.res)
  29. expect(this.res.body).to.equal('client error')
  30. })
  31. it("should render a template including the error message when content-type is 'html'", function() {
  32. this.req.accepts = () => 'html'
  33. this.HttpErrorHandler.badRequest(this.req, this.res, 'an error')
  34. expect(this.res.renderedTemplate).to.equal('general/400')
  35. expect(this.res.renderedVariables).to.deep.equal({
  36. title: 'Client Error',
  37. message: 'an error'
  38. })
  39. })
  40. it("should render a default template when content-type is 'html' and no message is provided", function() {
  41. this.req.accepts = () => 'html'
  42. this.HttpErrorHandler.badRequest(this.req, this.res)
  43. expect(this.res.renderedTemplate).to.equal('general/400')
  44. expect(this.res.renderedVariables).to.deep.equal({
  45. title: 'Client Error',
  46. message: undefined
  47. })
  48. })
  49. it("should return a json object when content-type is 'json'", function() {
  50. this.req.accepts = () => 'json'
  51. this.HttpErrorHandler.badRequest(this.req, this.res, 'an error', {
  52. foo: 'bar'
  53. })
  54. expect(JSON.parse(this.res.body)).to.deep.equal({
  55. message: 'an error',
  56. foo: 'bar'
  57. })
  58. })
  59. it("should return an empty json object when content-type is 'json' and no message and info are provided", function() {
  60. this.req.accepts = () => 'json'
  61. this.HttpErrorHandler.badRequest(this.req, this.res)
  62. expect(JSON.parse(this.res.body)).to.deep.equal({})
  63. })
  64. })
  65. describe('conflict', function() {
  66. it('returns 409', function() {
  67. this.HttpErrorHandler.conflict(this.req, this.res)
  68. expect(this.res.statusCode).to.equal(409)
  69. })
  70. it('should print a message when no content-type is included', function() {
  71. this.HttpErrorHandler.conflict(this.req, this.res)
  72. expect(this.res.body).to.equal('conflict')
  73. })
  74. it("should render a template including the error message when content-type is 'html'", function() {
  75. this.req.accepts = () => 'html'
  76. this.HttpErrorHandler.unprocessableEntity(this.req, this.res, 'an error')
  77. expect(this.res.renderedTemplate).to.equal('general/400')
  78. expect(this.res.renderedVariables).to.deep.equal({
  79. title: 'Client Error',
  80. message: 'an error'
  81. })
  82. })
  83. it("should return a json object when content-type is 'json'", function() {
  84. this.req.accepts = () => 'json'
  85. this.HttpErrorHandler.unprocessableEntity(
  86. this.req,
  87. this.res,
  88. 'an error',
  89. {
  90. foo: 'bar'
  91. }
  92. )
  93. expect(JSON.parse(this.res.body)).to.deep.equal({
  94. message: 'an error',
  95. foo: 'bar'
  96. })
  97. })
  98. })
  99. describe('forbidden', function() {
  100. it('returns 403', function() {
  101. this.HttpErrorHandler.forbidden(this.req, this.res)
  102. expect(this.res.statusCode).to.equal(403)
  103. })
  104. it('should print a message when no content-type is included', function() {
  105. this.HttpErrorHandler.forbidden(this.req, this.res)
  106. expect(this.res.body).to.equal('restricted')
  107. })
  108. it("should render a template when content-type is 'html'", function() {
  109. this.req.accepts = () => 'html'
  110. this.HttpErrorHandler.forbidden(this.req, this.res)
  111. expect(this.res.renderedTemplate).to.equal('user/restricted')
  112. expect(this.res.renderedVariables).to.deep.equal({
  113. title: 'restricted'
  114. })
  115. })
  116. it("should return a json object when content-type is 'json'", function() {
  117. this.req.accepts = () => 'json'
  118. this.HttpErrorHandler.forbidden(this.req, this.res, 'an error', {
  119. foo: 'bar'
  120. })
  121. expect(JSON.parse(this.res.body)).to.deep.equal({
  122. message: 'an error',
  123. foo: 'bar'
  124. })
  125. })
  126. })
  127. describe('notFound', function() {
  128. it('returns 404', function() {
  129. this.HttpErrorHandler.notFound(this.req, this.res)
  130. expect(this.res.statusCode).to.equal(404)
  131. })
  132. it('should print a message when no content-type is included', function() {
  133. this.HttpErrorHandler.notFound(this.req, this.res)
  134. expect(this.res.body).to.equal('not found')
  135. })
  136. it("should render a template when content-type is 'html'", function() {
  137. this.req.accepts = () => 'html'
  138. this.HttpErrorHandler.notFound(this.req, this.res)
  139. expect(this.res.renderedTemplate).to.equal('general/404')
  140. expect(this.res.renderedVariables).to.deep.equal({
  141. title: 'page_not_found'
  142. })
  143. })
  144. it("should return a json object when content-type is 'json'", function() {
  145. this.req.accepts = () => 'json'
  146. this.HttpErrorHandler.notFound(this.req, this.res, 'an error', {
  147. foo: 'bar'
  148. })
  149. expect(JSON.parse(this.res.body)).to.deep.equal({
  150. message: 'an error',
  151. foo: 'bar'
  152. })
  153. })
  154. })
  155. describe('unprocessableEntity', function() {
  156. it('returns 422', function() {
  157. this.HttpErrorHandler.unprocessableEntity(this.req, this.res)
  158. expect(this.res.statusCode).to.equal(422)
  159. })
  160. it('should print a message when no content-type is included', function() {
  161. this.HttpErrorHandler.unprocessableEntity(this.req, this.res)
  162. expect(this.res.body).to.equal('unprocessable entity')
  163. })
  164. it("should render a template including the error message when content-type is 'html'", function() {
  165. this.req.accepts = () => 'html'
  166. this.HttpErrorHandler.unprocessableEntity(this.req, this.res, 'an error')
  167. expect(this.res.renderedTemplate).to.equal('general/400')
  168. expect(this.res.renderedVariables).to.deep.equal({
  169. title: 'Client Error',
  170. message: 'an error'
  171. })
  172. })
  173. it("should return a json object when content-type is 'json'", function() {
  174. this.req.accepts = () => 'json'
  175. this.HttpErrorHandler.unprocessableEntity(
  176. this.req,
  177. this.res,
  178. 'an error',
  179. {
  180. foo: 'bar'
  181. }
  182. )
  183. expect(JSON.parse(this.res.body)).to.deep.equal({
  184. message: 'an error',
  185. foo: 'bar'
  186. })
  187. })
  188. describe('legacyInternal', function() {
  189. it('returns 500', function() {
  190. this.HttpErrorHandler.legacyInternal(this.req, this.res, new Error())
  191. expect(this.res.statusCode).to.equal(500)
  192. })
  193. it('should send the error to the logger', function() {
  194. const error = new Error('message')
  195. this.logger.error = sinon.stub()
  196. this.HttpErrorHandler.legacyInternal(
  197. this.req,
  198. this.res,
  199. 'message',
  200. error
  201. )
  202. expect(this.logger.error).to.have.been.calledWith(error)
  203. })
  204. it('should print a message when no content-type is included', function() {
  205. this.HttpErrorHandler.legacyInternal(this.req, this.res, new Error())
  206. expect(this.res.body).to.equal('internal server error')
  207. })
  208. it("should render a template when content-type is 'html'", function() {
  209. this.req.accepts = () => 'html'
  210. this.HttpErrorHandler.legacyInternal(this.req, this.res, new Error())
  211. expect(this.res.renderedTemplate).to.equal('general/500')
  212. expect(this.res.renderedVariables).to.deep.equal({
  213. title: 'Server Error'
  214. })
  215. })
  216. it("should return a json object with a static message when content-type is 'json'", function() {
  217. this.req.accepts = () => 'json'
  218. this.HttpErrorHandler.legacyInternal(
  219. this.req,
  220. this.res,
  221. 'a message',
  222. new Error()
  223. )
  224. expect(JSON.parse(this.res.body)).to.deep.equal({
  225. message: 'a message'
  226. })
  227. })
  228. })
  229. })
  230. })