@@ -45,7 +45,7 @@ async function complete(
45
45
const schema = buildSchema ( `
46
46
type Todo {
47
47
id: ID
48
- text: String
48
+ items: [ String]
49
49
author: User
50
50
}
51
51
@@ -91,7 +91,6 @@ describe('Execute: Cancellation', () => {
91
91
todo : async ( ) =>
92
92
Promise . resolve ( {
93
93
id : '1' ,
94
- text : 'Hello, World!' ,
95
94
/* c8 ignore next */
96
95
author : ( ) => expect . fail ( 'Should not be called' ) ,
97
96
} ) ,
@@ -186,7 +185,6 @@ describe('Execute: Cancellation', () => {
186
185
todo : async ( ) =>
187
186
Promise . resolve ( {
188
187
id : '1' ,
189
- text : 'Hello, World!' ,
190
188
/* c8 ignore next */
191
189
author : ( ) => expect . fail ( 'Should not be called' ) ,
192
190
} ) ,
@@ -235,7 +233,6 @@ describe('Execute: Cancellation', () => {
235
233
todo : async ( ) =>
236
234
Promise . resolve ( {
237
235
id : '1' ,
238
- text : 'Hello, World!' ,
239
236
/* c8 ignore next */
240
237
author : ( ) => expect . fail ( 'Should not be called' ) ,
241
238
} ) ,
@@ -280,7 +277,6 @@ describe('Execute: Cancellation', () => {
280
277
rootValue : {
281
278
todo : {
282
279
id : '1' ,
283
- text : 'Hello, World!' ,
284
280
/* c8 ignore next 3 */
285
281
author : async ( ) =>
286
282
Promise . resolve ( ( ) => expect . fail ( 'Should not be called' ) ) ,
@@ -354,6 +350,56 @@ describe('Execute: Cancellation', () => {
354
350
} ) ;
355
351
} ) ;
356
352
353
+ it ( 'should stop the execution when aborted despite a hanging item' , async ( ) => {
354
+ const abortController = new AbortController ( ) ;
355
+ const document = parse ( `
356
+ query {
357
+ todo {
358
+ id
359
+ items
360
+ }
361
+ }
362
+ ` ) ;
363
+
364
+ const resultPromise = execute ( {
365
+ document,
366
+ schema,
367
+ abortSignal : abortController . signal ,
368
+ rootValue : {
369
+ todo : ( ) => ( {
370
+ id : '1' ,
371
+ items : [
372
+ new Promise ( ( ) => {
373
+ /* will never resolve */
374
+ } ) ,
375
+ ] ,
376
+ } ) ,
377
+ } ,
378
+ } ) ;
379
+
380
+ abortController . abort ( ) ;
381
+
382
+ const result = await resultPromise ;
383
+
384
+ expect ( result . errors ?. [ 0 ] . originalError ?. name ) . to . equal ( 'AbortError' ) ;
385
+
386
+ expectJSON ( result ) . toDeepEqual ( {
387
+ data : {
388
+ todo : {
389
+ id : '1' ,
390
+ items : [ null ] ,
391
+ } ,
392
+ } ,
393
+ errors : [
394
+ {
395
+ message : 'This operation was aborted' ,
396
+ path : [ 'todo' , 'items' , 0 ] ,
397
+ locations : [ { line : 5 , column : 11 } ] ,
398
+ } ,
399
+ ] ,
400
+ } ) ;
401
+ } ) ;
402
+
357
403
it ( 'should stop the execution when aborted with proper null bubbling' , async ( ) => {
358
404
const abortController = new AbortController ( ) ;
359
405
const document = parse ( `
@@ -375,7 +421,6 @@ describe('Execute: Cancellation', () => {
375
421
nonNullableTodo : async ( ) =>
376
422
Promise . resolve ( {
377
423
id : '1' ,
378
- text : 'Hello, World!' ,
379
424
/* c8 ignore next */
380
425
author : ( ) => expect . fail ( 'Should not be called' ) ,
381
426
} ) ,
@@ -407,7 +452,6 @@ describe('Execute: Cancellation', () => {
407
452
todo {
408
453
id
409
454
... on Todo @defer {
410
- text
411
455
author {
412
456
id
413
457
}
@@ -423,7 +467,6 @@ describe('Execute: Cancellation', () => {
423
467
todo : async ( ) =>
424
468
Promise . resolve ( {
425
469
id : '1' ,
426
- text : 'hello world' ,
427
470
/* c8 ignore next */
428
471
author : ( ) => expect . fail ( 'Should not be called' ) ,
429
472
} ) ,
@@ -456,7 +499,6 @@ describe('Execute: Cancellation', () => {
456
499
... on Query @defer {
457
500
todo {
458
501
id
459
- text
460
502
author {
461
503
id
462
504
}
@@ -471,7 +513,6 @@ describe('Execute: Cancellation', () => {
471
513
todo : async ( ) =>
472
514
Promise . resolve ( {
473
515
id : '1' ,
474
- text : 'hello world' ,
475
516
/* c8 ignore next 2 */
476
517
author : async ( ) =>
477
518
Promise . resolve ( ( ) => expect . fail ( 'Should not be called' ) ) ,
@@ -512,6 +553,63 @@ describe('Execute: Cancellation', () => {
512
553
] ) ;
513
554
} ) ;
514
555
556
+ it ( 'should stop streamed execution when aborted' , async ( ) => {
557
+ const abortController = new AbortController ( ) ;
558
+ const document = parse ( `
559
+ query {
560
+ todo {
561
+ id
562
+ items @stream
563
+ }
564
+ }
565
+ ` ) ;
566
+
567
+ const resultPromise = complete (
568
+ document ,
569
+ {
570
+ todo : {
571
+ id : '1' ,
572
+ items : [ Promise . resolve ( 'item' ) ] ,
573
+ } ,
574
+ } ,
575
+ abortController . signal ,
576
+ ) ;
577
+
578
+ abortController . abort ( ) ;
579
+
580
+ const result = await resultPromise ;
581
+
582
+ expectJSON ( result ) . toDeepEqual ( [
583
+ {
584
+ data : {
585
+ todo : {
586
+ id : '1' ,
587
+ items : [ ] ,
588
+ } ,
589
+ } ,
590
+ pending : [ { id : '0' , path : [ 'todo' , 'items' ] } ] ,
591
+ hasNext : true ,
592
+ } ,
593
+ {
594
+ incremental : [
595
+ {
596
+ items : [ null ] ,
597
+ errors : [
598
+ {
599
+ message : 'This operation was aborted' ,
600
+ path : [ 'todo' , 'items' , 0 ] ,
601
+ locations : [ { line : 5 , column : 11 } ] ,
602
+ } ,
603
+ ] ,
604
+ id : '0' ,
605
+ } ,
606
+ ] ,
607
+ completed : [ { id : '0' } ] ,
608
+ hasNext : false ,
609
+ } ,
610
+ ] ) ;
611
+ } ) ;
612
+
515
613
it ( 'should stop the execution when aborted mid-mutation' , async ( ) => {
516
614
const abortController = new AbortController ( ) ;
517
615
const document = parse ( `
0 commit comments