Skip to content

Commit 8f84774

Browse files
author
igor.luckenkov
committed
ignore coverage and skip abortion test if node doesn't support AbortController
1 parent e4b51d3 commit 8f84774

File tree

3 files changed

+85
-69
lines changed

3 files changed

+85
-69
lines changed

src/execution/__tests__/executor-test.ts

Lines changed: 72 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ import { describe, it } from 'mocha';
44
import { expectJSON } from '../../__testUtils__/expectJSON.js';
55
import { resolveOnNextTick } from '../../__testUtils__/resolveOnNextTick.js';
66

7-
import { AbortController } from '../../jsutils/AbortController.js';
7+
import {
8+
AbortController,
9+
hasAbortControllerSupport,
10+
} from '../../jsutils/AbortController.js';
811
import { inspect } from '../../jsutils/inspect.js';
912

1013
import { Kind } from '../../language/kinds.js';
@@ -1315,59 +1318,60 @@ describe('Execute: Handles basic execution tasks', () => {
13151318
expect(possibleTypes).to.deep.equal([fooObject]);
13161319
});
13171320

1318-
it('stops execution and throws an error when signal is aborted', async () => {
1319-
/**
1320-
* This test has 3 resolvers nested in each other.
1321-
* Every resolve function waits 200ms before returning data.
1322-
*
1323-
* The test waits for the first resolver and half of the 2nd resolver execution time (200ms + 100ms)
1324-
* and then aborts the execution.
1325-
*
1326-
* 2nd resolver execution finishes, and we then expect to not execute the 3rd resolver
1327-
* and to get an error about aborted operation.
1328-
*/
1329-
1330-
const WAIT_MS_BEFORE_RESOLVING = 200;
1331-
const ABORT_IN_MS_AFTER_STARTING_EXECUTION =
1332-
WAIT_MS_BEFORE_RESOLVING + WAIT_MS_BEFORE_RESOLVING / 2;
1333-
1334-
const schema = new GraphQLSchema({
1335-
query: new GraphQLObjectType({
1336-
name: 'Query',
1337-
fields: {
1338-
resolvesIn500ms: {
1339-
type: new GraphQLObjectType({
1340-
name: 'ResolvesIn500ms',
1341-
fields: {
1342-
resolvesIn400ms: {
1343-
type: new GraphQLObjectType({
1344-
name: 'ResolvesIn400ms',
1345-
fields: {
1346-
shouldNotBeResolved: {
1347-
type: GraphQLString,
1348-
/* c8 ignore next 3 */
1349-
resolve: () => {
1350-
throw new Error('This should not be executed!');
1321+
/* c8 ignore start */
1322+
if (hasAbortControllerSupport) {
1323+
it('stops execution and throws an error when signal is aborted', async () => {
1324+
/**
1325+
* This test has 3 resolvers nested in each other.
1326+
* Every resolve function waits 200ms before returning data.
1327+
*
1328+
* The test waits for the first resolver and half of the 2nd resolver execution time (200ms + 100ms)
1329+
* and then aborts the execution.
1330+
*
1331+
* 2nd resolver execution finishes, and we then expect to not execute the 3rd resolver
1332+
* and to get an error about aborted operation.
1333+
*/
1334+
1335+
const WAIT_MS_BEFORE_RESOLVING = 200;
1336+
const ABORT_IN_MS_AFTER_STARTING_EXECUTION =
1337+
WAIT_MS_BEFORE_RESOLVING + WAIT_MS_BEFORE_RESOLVING / 2;
1338+
1339+
const schema = new GraphQLSchema({
1340+
query: new GraphQLObjectType({
1341+
name: 'Query',
1342+
fields: {
1343+
resolvesIn500ms: {
1344+
type: new GraphQLObjectType({
1345+
name: 'ResolvesIn500ms',
1346+
fields: {
1347+
resolvesIn400ms: {
1348+
type: new GraphQLObjectType({
1349+
name: 'ResolvesIn400ms',
1350+
fields: {
1351+
shouldNotBeResolved: {
1352+
type: GraphQLString,
1353+
resolve: () => {
1354+
throw new Error('This should not be executed!');
1355+
},
13511356
},
13521357
},
1353-
},
1354-
}),
1355-
resolve: () =>
1356-
new Promise((resolve) => {
1357-
setTimeout(() => resolve({}), WAIT_MS_BEFORE_RESOLVING);
13581358
}),
1359+
resolve: () =>
1360+
new Promise((resolve) => {
1361+
setTimeout(() => resolve({}), WAIT_MS_BEFORE_RESOLVING);
1362+
}),
1363+
},
13591364
},
1360-
},
1361-
}),
1362-
resolve: () =>
1363-
new Promise((resolve) => {
1364-
setTimeout(() => resolve({}), WAIT_MS_BEFORE_RESOLVING);
13651365
}),
1366+
resolve: () =>
1367+
new Promise((resolve) => {
1368+
setTimeout(() => resolve({}), WAIT_MS_BEFORE_RESOLVING);
1369+
}),
1370+
},
13661371
},
1367-
},
1368-
}),
1369-
});
1370-
const document = parse(`
1372+
}),
1373+
});
1374+
const document = parse(`
13711375
query {
13721376
resolvesIn500ms {
13731377
resolvesIn400ms {
@@ -1377,22 +1381,24 @@ describe('Execute: Handles basic execution tasks', () => {
13771381
}
13781382
`);
13791383

1380-
const abortController = new AbortController();
1381-
const executionPromise = execute({
1382-
schema,
1383-
document,
1384-
signal: abortController.signal,
1385-
});
1386-
1387-
setTimeout(
1388-
() => abortController.abort(),
1389-
ABORT_IN_MS_AFTER_STARTING_EXECUTION,
1390-
);
1391-
1392-
const result = await executionPromise;
1393-
expect(result.errors?.[0].message).to.eq('Execution aborted.');
1394-
expect(result.data).to.eql({
1395-
resolvesIn500ms: { resolvesIn400ms: null },
1396-
});
1397-
});
1384+
const abortController = new AbortController();
1385+
const executionPromise = execute({
1386+
schema,
1387+
document,
1388+
signal: abortController.signal,
1389+
});
1390+
1391+
setTimeout(
1392+
() => abortController.abort(),
1393+
ABORT_IN_MS_AFTER_STARTING_EXECUTION,
1394+
);
1395+
1396+
const result = await executionPromise;
1397+
expect(result.errors?.[0].message).to.eq('Execution aborted.');
1398+
expect(result.data).to.eql({
1399+
resolvesIn500ms: { resolvesIn400ms: null },
1400+
});
1401+
});
1402+
}
1403+
/* c8 ignore stop */
13981404
});

src/execution/execute.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,7 @@ export function experimentalExecuteIncrementally(
348348
return executeImpl(exeContext);
349349
}
350350

351+
/* c8 ignore start */
351352
function subscribeToAbortSignal(exeContext: ExecutionContext): () => void {
352353
const { abortion } = exeContext;
353354
if (!abortion) {
@@ -362,6 +363,7 @@ function subscribeToAbortSignal(exeContext: ExecutionContext): () => void {
362363
abortion.executionAbortController.abort();
363364
};
364365
}
366+
/* c8 ignore stop */
365367

366368
function executeImpl(
367369
exeContext: ExecutionContext,
@@ -546,6 +548,7 @@ export function buildExecutionContext(
546548
};
547549
}
548550

551+
/* c8 ignore start */
549552
function getContextAbortionEntities(
550553
passedInAbortSignal: Maybe<IAbortSignal>,
551554
): ExecutionContext['abortion'] {
@@ -561,6 +564,7 @@ function getContextAbortionEntities(
561564
executionAbortSignal: executionAbortController.signal,
562565
};
563566
}
567+
/* c8 ignore stop */
564568

565569
function buildPerEventExecutionContext(
566570
exeContext: ExecutionContext,
@@ -892,12 +896,11 @@ function completeValue(
892896
result: unknown,
893897
asyncPayloadRecord?: AsyncPayloadRecord,
894898
): PromiseOrValue<unknown> {
895-
// Ignoring test coverage for abortion check since Node 14 doesn't support AbortSignal
896-
// and this condition is never true.
897-
/* c8 ignore next 3 */
899+
/* c8 ignore start */
898900
if (exeContext.abortion?.executionAbortSignal.aborted) {
899901
throw new GraphQLError('Execution aborted.');
900902
}
903+
/* c8 ignore stop */
901904

902905
// If result is an Error, throw a located error.
903906
if (result instanceof Error) {
@@ -1636,11 +1639,13 @@ export function subscribe(
16361639
> {
16371640
// Until we have execution cancelling support in Subscriptions,
16381641
// throw an error if client provides abort signal.
1642+
/* c8 ignore start */
16391643
if (args.signal) {
16401644
return {
16411645
errors: [new GraphQLError('Subscriptions do not support abort signals.')],
16421646
};
16431647
}
1648+
/* c8 ignore stop */
16441649

16451650
// If a valid execution context cannot be created due to incorrect arguments,
16461651
// a "Response" with only errors is returned.

src/jsutils/AbortController.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,9 @@ export const AbortController: new () => IAbortController =
2828
this._signal.aborted = true;
2929
}
3030
};
31+
32+
export const hasAbortControllerSupport =
33+
// eslint-disable-next-line no-undef
34+
Boolean(global.AbortController);
35+
3136
/* c8 ignore stop */

0 commit comments

Comments
 (0)