From 9f3d24202b50c0f2dc15b2c19994c8bdd29bac6a Mon Sep 17 00:00:00 2001 From: D050513 Date: Wed, 22 Nov 2023 23:15:18 +0100 Subject: [PATCH 1/2] adjust tests for revised log formatting in production --- test/tests/error-handling-prod.test.js | 36 ++++++++++++-------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/test/tests/error-handling-prod.test.js b/test/tests/error-handling-prod.test.js index e7089e31..a409b751 100644 --- a/test/tests/error-handling-prod.test.js +++ b/test/tests/error-handling-prod.test.js @@ -42,16 +42,15 @@ describe('graphql - error handling in production', () => { const response = await POST('/graphql', { query }) expect(response.data).toMatchObject({ errors }) expect(response.data.errors[0].extensions).not.toHaveProperty('stacktrace') // No stacktrace in production - expect(console.warn.mock.calls[0][1]).toMatchObject({ + const log = console.warn.mock.calls[0][1] || JSON.parse(console.warn.mock.calls[0][0]) + expect(log).toMatchObject({ code: '400', element: 'notEmptyI', entity: 'ValidationErrorsService.A', message: 'Value is required', numericSeverity: 4, target: 'notEmptyI', - type: 'cds.Integer', - value: undefined, - stack: expect.any(String) + type: 'cds.Integer' }) }) @@ -157,9 +156,11 @@ describe('graphql - error handling in production', () => { expect(response.data.errors[0].extensions).not.toHaveProperty('stacktrace') // No stacktrace outside of error details expect(response.data.errors[0].extensions.details[0]).not.toHaveProperty('stacktrace') // No stacktrace in production expect(response.data.errors[0].extensions.details[1]).not.toHaveProperty('stacktrace') // No stacktrace in production - expect(console.warn.mock.calls[0][1]).toMatchObject({ + const log = console.warn.mock.calls[0][1] || JSON.parse(console.warn.mock.calls[0][0]) + const msgProperty = log.msg ? 'msg' : 'message' + expect(log).toMatchObject({ code: '400', - message: 'Multiple errors occurred. Please see the details for more information.', + [msgProperty]: 'Multiple errors occurred. Please see the details for more information.', details: [ { args: ['inRange'], @@ -169,9 +170,7 @@ describe('graphql - error handling in production', () => { message: 'Value is required', numericSeverity: 4, target: 'inRange', - type: 'cds.Integer', - value: undefined, - stack: expect.any(String) + type: 'cds.Integer' }, { args: ['"foo"', '"high", "medium", "low"'], @@ -183,12 +182,11 @@ describe('graphql - error handling in production', () => { numericSeverity: 4, target: 'oneOfEnumValues', type: 'cds.String', - value: 'foo', - stack: expect.any(String) + value: 'foo' } ] }) - expect(console.warn.mock.calls[0][1]).not.toHaveProperty('stacktrace') // No stacktrace outside of error details + expect(log).not.toHaveProperty('stacktrace') // No stacktrace outside of error details }) }) @@ -362,29 +360,29 @@ describe('graphql - error handling in production', () => { expect(response.data.errors[0].extensions).not.toHaveProperty('stacktrace') // No stacktrace outside of error details expect(response.data.errors[0].extensions.details[0]).not.toHaveProperty('stacktrace') // No stacktrace in production expect(response.data.errors[0].extensions.details[1]).not.toHaveProperty('stacktrace') // No stacktrace in production - expect(console.error.mock.calls[0][1]).toMatchObject({ + const log = console.error.mock.calls[0][1] || JSON.parse(console.error.mock.calls[0][0]) + const msgProperty = log.msg ? 'msg' : 'message' + expect(log).toMatchObject({ code: '500', - message: 'Multiple errors occurred. Please see the details for more information.', + [msgProperty]: 'Multiple errors occurred. Please see the details for more information.', details: [ { code: 'Some-Custom-Code1', message: 'Some Custom Error Message 1', numericSeverity: 4, status: 418, - target: 'some_field', - stack: expect.any(String) + target: 'some_field' }, { code: 'Some-Custom-Code2', message: 'Some Custom Error Message 2', numericSeverity: 4, status: 500, - target: 'some_field', - stack: expect.any(String) + target: 'some_field' } ] }) - expect(console.error.mock.calls[0][1]).not.toHaveProperty('stacktrace') // No stacktrace outside of error details + expect(log).not.toHaveProperty('stacktrace') // No stacktrace outside of error details }) test('Thrown error is modified in srv.on(error) handler', async () => { From faf936316084dd97009d1469ae5b5be6adfcdcf8 Mon Sep 17 00:00:00 2001 From: Marcel Schwarz Date: Mon, 27 Nov 2023 17:52:15 +0100 Subject: [PATCH 2/2] Add error logging tests for dev --- test/tests/error-handling-dev.test.js | 64 +++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/test/tests/error-handling-dev.test.js b/test/tests/error-handling-dev.test.js index 0f3dec7c..c415cd3d 100644 --- a/test/tests/error-handling-dev.test.js +++ b/test/tests/error-handling-dev.test.js @@ -7,6 +7,15 @@ describe('graphql - error handling in development', () => { // Prevent axios from throwing errors for non 2xx status codes axios.defaults.validateStatus = false + beforeEach(() => { + jest.spyOn(console, 'warn') + jest.spyOn(console, 'error') + }) + + afterEach(() => { + jest.clearAllMocks() + }) + describe('Errors thrown by CDS', () => { test('Single @mandatory validation error', async () => { const query = gql` @@ -175,6 +184,38 @@ describe('graphql - error handling in development', () => { expect(response.data.errors[0].extensions).not.toHaveProperty('stacktrace') // No stacktrace outside of error details expect(response.data.errors[0].extensions.details[0].stacktrace[0]).not.toHaveLength(0) // Stacktrace exists and is not empty expect(response.data.errors[0].extensions.details[1].stacktrace[0]).not.toHaveLength(0) // Stacktrace exists and is not empty + expect(console.warn.mock.calls[0][1]).toMatchObject({ + code: '400', + message: 'Multiple errors occurred. Please see the details for more information.', + details: [ + { + args: ['inRange'], + code: '400', + element: 'inRange', + entity: 'ValidationErrorsService.C', + message: 'Value is required', + numericSeverity: 4, + target: 'inRange', + type: 'cds.Integer', + value: undefined, + stack: expect.any(String) + }, + { + args: ['"foo"', '"high", "medium", "low"'], + code: '400', + element: 'oneOfEnumValues', + entity: 'ValidationErrorsService.C', + enum: ['@assert.range', 'type', 'enum'], + message: 'Value "foo" is invalid according to enum declaration {"high", "medium", "low"}', + numericSeverity: 4, + target: 'oneOfEnumValues', + type: 'cds.String', + value: 'foo', + stack: expect.any(String) + } + ] + }) + expect(console.warn.mock.calls[0][1]).not.toHaveProperty('stacktrace') // No stacktrace outside of error details }) }) @@ -361,6 +402,29 @@ describe('graphql - error handling in development', () => { expect(response.data.errors[0].extensions).not.toHaveProperty('stacktrace') // No stacktrace outside of error details expect(response.data.errors[0].extensions.details[0].stacktrace[0]).not.toHaveLength(0) // Stacktrace exists and is not empty expect(response.data.errors[0].extensions.details[1].stacktrace[0]).not.toHaveLength(0) // Stacktrace exists and is not empty + expect(console.error.mock.calls[0][1]).toMatchObject({ + code: '500', + message: 'Multiple errors occurred. Please see the details for more information.', + details: [ + { + code: 'Some-Custom-Code1', + message: 'Some Custom Error Message 1', + numericSeverity: 4, + status: 418, + target: 'some_field', + stack: expect.any(String) + }, + { + code: 'Some-Custom-Code2', + message: 'Some Custom Error Message 2', + numericSeverity: 4, + status: 500, + target: 'some_field', + stack: expect.any(String) + } + ] + }) + expect(console.error.mock.calls[0][1]).not.toHaveProperty('stacktrace') // No stacktrace outside of error details }) test('Thrown error is modified in srv.on(error) handler', async () => {