Skip to content

Commit 50bf3b6

Browse files
author
igor.luckenkov
committed
ignore coverage and skip abortion test if node doesn't support AbortController
1 parent 2e1d930 commit 50bf3b6

File tree

3 files changed

+80
-69
lines changed

3 files changed

+80
-69
lines changed

src/execution/__tests__/executor-test.ts

Lines changed: 71 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';
@@ -1277,59 +1280,60 @@ describe('Execute: Handles basic execution tasks', () => {
12771280
expect(possibleTypes).to.deep.equal([fooObject]);
12781281
});
12791282

1280-
it('stops execution and throws an error when signal is aborted', async () => {
1281-
/**
1282-
* This test has 3 resolvers nested in each other.
1283-
* Every resolve function waits 200ms before returning data.
1284-
*
1285-
* The test waits for the first resolver and half of the 2nd resolver execution time (200ms + 100ms)
1286-
* and then aborts the execution.
1287-
*
1288-
* 2nd resolver execution finishes, and we then expect to not execute the 3rd resolver
1289-
* and to get an error about aborted operation.
1290-
*/
1291-
1292-
const WAIT_MS_BEFORE_RESOLVING = 200;
1293-
const ABORT_IN_MS_AFTER_STARTING_EXECUTION =
1294-
WAIT_MS_BEFORE_RESOLVING + WAIT_MS_BEFORE_RESOLVING / 2;
1295-
1296-
const schema = new GraphQLSchema({
1297-
query: new GraphQLObjectType({
1298-
name: 'Query',
1299-
fields: {
1300-
resolvesIn500ms: {
1301-
type: new GraphQLObjectType({
1302-
name: 'ResolvesIn500ms',
1303-
fields: {
1304-
resolvesIn400ms: {
1305-
type: new GraphQLObjectType({
1306-
name: 'ResolvesIn400ms',
1307-
fields: {
1308-
shouldNotBeResolved: {
1309-
type: GraphQLString,
1310-
/* c8 ignore next 3 */
1311-
resolve: () => {
1312-
throw new Error('This should not be executed!');
1283+
if (hasAbortControllerSupport) {
1284+
it('stops execution and throws an error when signal is aborted', async () => {
1285+
/**
1286+
* This test has 3 resolvers nested in each other.
1287+
* Every resolve function waits 200ms before returning data.
1288+
*
1289+
* The test waits for the first resolver and half of the 2nd resolver execution time (200ms + 100ms)
1290+
* and then aborts the execution.
1291+
*
1292+
* 2nd resolver execution finishes, and we then expect to not execute the 3rd resolver
1293+
* and to get an error about aborted operation.
1294+
*/
1295+
1296+
const WAIT_MS_BEFORE_RESOLVING = 200;
1297+
const ABORT_IN_MS_AFTER_STARTING_EXECUTION =
1298+
WAIT_MS_BEFORE_RESOLVING + WAIT_MS_BEFORE_RESOLVING / 2;
1299+
1300+
const schema = new GraphQLSchema({
1301+
query: new GraphQLObjectType({
1302+
name: 'Query',
1303+
fields: {
1304+
resolvesIn500ms: {
1305+
type: new GraphQLObjectType({
1306+
name: 'ResolvesIn500ms',
1307+
fields: {
1308+
resolvesIn400ms: {
1309+
type: new GraphQLObjectType({
1310+
name: 'ResolvesIn400ms',
1311+
fields: {
1312+
shouldNotBeResolved: {
1313+
type: GraphQLString,
1314+
/* c8 ignore next 3 */
1315+
resolve: () => {
1316+
throw new Error('This should not be executed!');
1317+
},
13131318
},
13141319
},
1315-
},
1316-
}),
1317-
resolve: () =>
1318-
new Promise((resolve) => {
1319-
setTimeout(() => resolve({}), WAIT_MS_BEFORE_RESOLVING);
13201320
}),
1321+
resolve: () =>
1322+
new Promise((resolve) => {
1323+
setTimeout(() => resolve({}), WAIT_MS_BEFORE_RESOLVING);
1324+
}),
1325+
},
13211326
},
1322-
},
1323-
}),
1324-
resolve: () =>
1325-
new Promise((resolve) => {
1326-
setTimeout(() => resolve({}), WAIT_MS_BEFORE_RESOLVING);
13271327
}),
1328+
resolve: () =>
1329+
new Promise((resolve) => {
1330+
setTimeout(() => resolve({}), WAIT_MS_BEFORE_RESOLVING);
1331+
}),
1332+
},
13281333
},
1329-
},
1330-
}),
1331-
});
1332-
const document = parse(`
1334+
}),
1335+
});
1336+
const document = parse(`
13331337
query {
13341338
resolvesIn500ms {
13351339
resolvesIn400ms {
@@ -1339,22 +1343,23 @@ describe('Execute: Handles basic execution tasks', () => {
13391343
}
13401344
`);
13411345

1342-
const abortController = new AbortController();
1343-
const executionPromise = execute({
1344-
schema,
1345-
document,
1346-
signal: abortController.signal,
1347-
});
1348-
1349-
setTimeout(
1350-
() => abortController.abort(),
1351-
ABORT_IN_MS_AFTER_STARTING_EXECUTION,
1352-
);
1353-
1354-
const result = await executionPromise;
1355-
expect(result.errors?.[0].message).to.eq('Execution aborted.');
1356-
expect(result.data).to.eql({
1357-
resolvesIn500ms: { resolvesIn400ms: null },
1358-
});
1359-
});
1346+
const abortController = new AbortController();
1347+
const executionPromise = execute({
1348+
schema,
1349+
document,
1350+
signal: abortController.signal,
1351+
});
1352+
1353+
setTimeout(
1354+
() => abortController.abort(),
1355+
ABORT_IN_MS_AFTER_STARTING_EXECUTION,
1356+
);
1357+
1358+
const result = await executionPromise;
1359+
expect(result.errors?.[0].message).to.eq('Execution aborted.');
1360+
expect(result.data).to.eql({
1361+
resolvesIn500ms: { resolvesIn400ms: null },
1362+
});
1363+
});
1364+
}
13601365
});

src/execution/execute.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -886,12 +886,11 @@ function completeValue(
886886
result: unknown,
887887
asyncPayloadRecord?: AsyncPayloadRecord,
888888
): PromiseOrValue<unknown> {
889-
// Ignoring test coverage for abortion check since Node 14 doesn't support AbortSignal
890-
// and this condition is never true.
891-
/* c8 ignore next 3 */
889+
/* c8 ignore start */
892890
if (exeContext.abortion?.executionAbortSignal.aborted) {
893891
throw new GraphQLError('Execution aborted.');
894892
}
893+
/* c8 ignore stop */
895894

896895
// If result is an Error, throw a located error.
897896
if (result instanceof Error) {
@@ -1666,11 +1665,13 @@ export function experimentalSubscribeIncrementally(
16661665
> {
16671666
// Until we have execution cancelling support in Subscriptions,
16681667
// throw an error if client provides abort signal.
1668+
/* c8 ignore start */
16691669
if (args.signal) {
16701670
return {
16711671
errors: [new GraphQLError('Subscriptions do not support abort signals.')],
16721672
};
16731673
}
1674+
/* c8 ignore stop */
16741675

16751676
// If a valid execution context cannot be created due to incorrect arguments,
16761677
// 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)