@@ -68,15 +68,17 @@ describe('HTTP Error Classes', () => {
6868 statusCode : HttpStatusCodes . SERVICE_UNAVAILABLE ,
6969 customMessage : 'Maintenance mode' ,
7070 } ,
71- ] ) (
72- '$errorType uses custom message when provided' ,
73- ( { ErrorClass, errorType, statusCode, customMessage } ) => {
74- const error = new ErrorClass ( customMessage ) ;
75- expect ( error . message ) . toBe ( customMessage ) ;
76- expect ( error . statusCode ) . toBe ( statusCode ) ;
77- expect ( error . errorType ) . toBe ( errorType ) ;
78- }
79- ) ;
71+ ] ) ( '$errorType uses custom message when provided' , ( {
72+ ErrorClass,
73+ errorType,
74+ statusCode,
75+ customMessage,
76+ } ) => {
77+ const error = new ErrorClass ( customMessage ) ;
78+ expect ( error . message ) . toBe ( customMessage ) ;
79+ expect ( error . statusCode ) . toBe ( statusCode ) ;
80+ expect ( error . errorType ) . toBe ( errorType ) ;
81+ } ) ;
8082
8183 describe ( 'toJSON' , ( ) => {
8284 it . each ( [
@@ -134,19 +136,21 @@ describe('HTTP Error Classes', () => {
134136 statusCode : HttpStatusCodes . SERVICE_UNAVAILABLE ,
135137 message : 'Maintenance mode' ,
136138 } ,
137- ] ) (
138- '$errorType serializes to JSON format' ,
139- ( { ErrorClass, errorType, statusCode, message } ) => {
140- const error = new ErrorClass ( message ) ;
141- const json = error . toJSON ( ) ;
139+ ] ) ( '$errorType serializes to JSON format' , ( {
140+ ErrorClass,
141+ errorType,
142+ statusCode,
143+ message,
144+ } ) => {
145+ const error = new ErrorClass ( message ) ;
146+ const json = error . toJSON ( ) ;
142147
143- expect ( json ) . toEqual ( {
144- statusCode,
145- error : errorType ,
146- message,
147- } ) ;
148- }
149- ) ;
148+ expect ( json ) . toEqual ( {
149+ statusCode,
150+ error : errorType ,
151+ message,
152+ } ) ;
153+ } ) ;
150154
151155 it ( 'includes details in JSON when provided' , ( ) => {
152156 const details = { field : 'value' , code : 'VALIDATION_ERROR' } ;
@@ -174,6 +178,111 @@ describe('HTTP Error Classes', () => {
174178 } ) ;
175179 } ) ;
176180
181+ describe ( 'toWebResponse' , ( ) => {
182+ it . each ( [
183+ {
184+ ErrorClass : BadRequestError ,
185+ errorType : 'BadRequestError' ,
186+ statusCode : HttpStatusCodes . BAD_REQUEST ,
187+ message : 'Invalid input' ,
188+ } ,
189+ {
190+ ErrorClass : UnauthorizedError ,
191+ errorType : 'UnauthorizedError' ,
192+ statusCode : HttpStatusCodes . UNAUTHORIZED ,
193+ message : 'Token expired' ,
194+ } ,
195+ {
196+ ErrorClass : ForbiddenError ,
197+ errorType : 'ForbiddenError' ,
198+ statusCode : HttpStatusCodes . FORBIDDEN ,
199+ message : 'Access denied' ,
200+ } ,
201+ {
202+ ErrorClass : NotFoundError ,
203+ errorType : 'NotFoundError' ,
204+ statusCode : HttpStatusCodes . NOT_FOUND ,
205+ message : 'Resource not found' ,
206+ } ,
207+ {
208+ ErrorClass : MethodNotAllowedError ,
209+ errorType : 'MethodNotAllowedError' ,
210+ statusCode : HttpStatusCodes . METHOD_NOT_ALLOWED ,
211+ message : 'POST not allowed' ,
212+ } ,
213+ {
214+ ErrorClass : RequestTimeoutError ,
215+ errorType : 'RequestTimeoutError' ,
216+ statusCode : HttpStatusCodes . REQUEST_TIMEOUT ,
217+ message : 'Operation timed out' ,
218+ } ,
219+ {
220+ ErrorClass : RequestEntityTooLargeError ,
221+ errorType : 'RequestEntityTooLargeError' ,
222+ statusCode : HttpStatusCodes . REQUEST_ENTITY_TOO_LARGE ,
223+ message : 'File too large' ,
224+ } ,
225+ {
226+ ErrorClass : InternalServerError ,
227+ errorType : 'InternalServerError' ,
228+ statusCode : HttpStatusCodes . INTERNAL_SERVER_ERROR ,
229+ message : 'Database connection failed' ,
230+ } ,
231+ {
232+ ErrorClass : ServiceUnavailableError ,
233+ errorType : 'ServiceUnavailableError' ,
234+ statusCode : HttpStatusCodes . SERVICE_UNAVAILABLE ,
235+ message : 'Maintenance mode' ,
236+ } ,
237+ ] ) ( '$errorType creates Response object' , async ( {
238+ ErrorClass,
239+ errorType,
240+ statusCode,
241+ message,
242+ } ) => {
243+ const error = new ErrorClass ( message ) ;
244+ const response = error . toWebResponse ( ) ;
245+
246+ expect ( response . status ) . toEqual ( statusCode ) ;
247+ expect ( response . headers . get ( 'Content-Type' ) ) . toEqual ( 'application/json' ) ;
248+
249+ await expect ( response . json ( ) ) . resolves . toEqual ( {
250+ statusCode,
251+ error : errorType ,
252+ message,
253+ } ) ;
254+ } ) ;
255+
256+ it ( 'includes details in Response body when provided' , async ( ) => {
257+ const details = { field : 'value' , code : 'VALIDATION_ERROR' } ;
258+ const error = new BadRequestError ( 'Invalid input' , undefined , details ) ;
259+ const response = error . toWebResponse ( ) ;
260+
261+ expect ( response . status ) . toEqual ( HttpStatusCodes . BAD_REQUEST ) ;
262+
263+ await expect ( response . json ( ) ) . resolves . toEqual ( {
264+ statusCode : HttpStatusCodes . BAD_REQUEST ,
265+ error : 'BadRequestError' ,
266+ message : 'Invalid input' ,
267+ details,
268+ } ) ;
269+ } ) ;
270+
271+ it ( 'excludes details from JSON when not provided' , async ( ) => {
272+ const error = new BadRequestError ( 'Invalid input' ) ;
273+ const response = error . toWebResponse ( ) ;
274+
275+ expect ( response . status ) . toEqual ( HttpStatusCodes . BAD_REQUEST ) ;
276+
277+ await expect ( response . json ( ) ) . resolves . toEqual ( {
278+ statusCode : HttpStatusCodes . BAD_REQUEST ,
279+ error : 'BadRequestError' ,
280+ message : 'Invalid input' ,
281+ } ) ;
282+ expect ( response ) . not . toHaveProperty ( 'details' ) ;
283+ } ) ;
284+ } ) ;
285+
177286 it ( 'passes options to Error superclass' , ( ) => {
178287 const cause = new Error ( 'Root cause' ) ;
179288 const error = new BadRequestError ( 'Invalid input' , { cause } ) ;
0 commit comments