From c345e40f6ff124692b1403e04ce2b62c073cceb7 Mon Sep 17 00:00:00 2001 From: Yaacov Rydzinski Date: Sun, 27 Oct 2024 10:14:03 +0200 Subject: [PATCH] fix: handle default and different types passed to abort method --- src/execution/__tests__/abort-signal-test.ts | 116 +++++++++++++++++-- src/execution/execute.ts | 6 +- 2 files changed, 107 insertions(+), 15 deletions(-) diff --git a/src/execution/__tests__/abort-signal-test.ts b/src/execution/__tests__/abort-signal-test.ts index 7e34c3dc91..36e9d57595 100644 --- a/src/execution/__tests__/abort-signal-test.ts +++ b/src/execution/__tests__/abort-signal-test.ts @@ -89,7 +89,7 @@ describe('Execute: Cancellation', () => { }, }); - abortController.abort('Aborted'); + abortController.abort(); const result = await resultPromise; @@ -99,7 +99,99 @@ describe('Execute: Cancellation', () => { }, errors: [ { - message: 'Aborted', + message: 'This operation was aborted', + path: ['todo', 'id'], + locations: [{ line: 4, column: 11 }], + }, + ], + }); + }); + + it('should stop the execution when aborted during object field completion with a custom error', async () => { + const abortController = new AbortController(); + const document = parse(` + query { + todo { + id + author { + id + } + } + } + `); + + const resultPromise = execute({ + document, + schema, + abortSignal: abortController.signal, + rootValue: { + todo: async () => + Promise.resolve({ + id: '1', + text: 'Hello, World!', + /* c8 ignore next */ + author: () => expect.fail('Should not be called'), + }), + }, + }); + + abortController.abort(new Error('Custom abort error')); + + const result = await resultPromise; + + expectJSON(result).toDeepEqual({ + data: { + todo: null, + }, + errors: [ + { + message: 'Custom abort error', + path: ['todo', 'id'], + locations: [{ line: 4, column: 11 }], + }, + ], + }); + }); + + it('should stop the execution when aborted during object field completion with a custom string', async () => { + const abortController = new AbortController(); + const document = parse(` + query { + todo { + id + author { + id + } + } + } + `); + + const resultPromise = execute({ + document, + schema, + abortSignal: abortController.signal, + rootValue: { + todo: async () => + Promise.resolve({ + id: '1', + text: 'Hello, World!', + /* c8 ignore next */ + author: () => expect.fail('Should not be called'), + }), + }, + }); + + abortController.abort('Custom abort error message'); + + const result = await resultPromise; + + expectJSON(result).toDeepEqual({ + data: { + todo: null, + }, + errors: [ + { + message: 'Unexpected error value: "Custom abort error message"', path: ['todo', 'id'], locations: [{ line: 4, column: 11 }], }, @@ -135,7 +227,7 @@ describe('Execute: Cancellation', () => { }, }); - abortController.abort('Aborted'); + abortController.abort(); const result = await resultPromise; @@ -148,7 +240,7 @@ describe('Execute: Cancellation', () => { }, errors: [ { - message: 'Aborted', + message: 'This operation was aborted', path: ['todo', 'author', 'id'], locations: [{ line: 6, column: 13 }], }, @@ -187,7 +279,7 @@ describe('Execute: Cancellation', () => { abortSignal: abortController.signal, }); - abortController.abort('Aborted'); + abortController.abort(); const result = await resultPromise; @@ -197,7 +289,7 @@ describe('Execute: Cancellation', () => { }, errors: [ { - message: 'Aborted', + message: 'This operation was aborted', path: ['todo', 'id'], locations: [{ line: 4, column: 11 }], }, @@ -242,7 +334,7 @@ describe('Execute: Cancellation', () => { await resolveOnNextTick(); await resolveOnNextTick(); - abortController.abort('Aborted'); + abortController.abort(); const result = await resultPromise; @@ -267,7 +359,7 @@ describe('Execute: Cancellation', () => { line: 6, }, ], - message: 'Aborted', + message: 'This operation was aborted', path: ['todo', 'text'], }, ], @@ -299,7 +391,7 @@ describe('Execute: Cancellation', () => { }, }); - abortController.abort('Aborted'); + abortController.abort(); const result = await resultPromise; @@ -310,7 +402,7 @@ describe('Execute: Cancellation', () => { }, errors: [ { - message: 'Aborted', + message: 'This operation was aborted', path: ['bar'], locations: [{ line: 4, column: 9 }], }, @@ -330,7 +422,7 @@ describe('Execute: Cancellation', () => { } } `); - abortController.abort('Aborted'); + abortController.abort(); const result = await execute({ document, schema, @@ -344,7 +436,7 @@ describe('Execute: Cancellation', () => { expectJSON(result).toDeepEqual({ errors: [ { - message: 'Aborted', + message: 'This operation was aborted', }, ], }); diff --git a/src/execution/execute.ts b/src/execution/execute.ts index 5cfb8c1924..4765933bb4 100644 --- a/src/execution/execute.ts +++ b/src/execution/execute.ts @@ -518,7 +518,7 @@ export function validateExecutionArgs( } = args; if (abortSignal?.aborted) { - return [locatedError(new Error(abortSignal.reason), undefined)]; + return [locatedError(abortSignal.reason, undefined)]; } // If the schema used for execution is invalid, throw an error. @@ -668,7 +668,7 @@ function executeFieldsSerially( const abortSignal = exeContext.validatedExecutionArgs.abortSignal; if (abortSignal?.aborted) { handleFieldError( - new Error(abortSignal.reason), + abortSignal.reason, exeContext, parentType, fieldDetailsList, @@ -732,7 +732,7 @@ function executeFields( const abortSignal = exeContext.validatedExecutionArgs.abortSignal; if (abortSignal?.aborted) { throw locatedError( - new Error(abortSignal.reason), + abortSignal.reason, toNodes(fieldDetailsList), pathToArray(fieldPath), );