1
1
import request from 'supertest' ;
2
+ import { eventStream } from '../../../packages/graphql-yoga/__tests__/utilities.js' ;
2
3
import { buildApp } from '../src/app.js' ;
3
4
4
5
describe ( 'fastify example integration' , ( ) => {
@@ -180,6 +181,7 @@ event: complete
180
181
data"
181
182
` ) ;
182
183
} ) ;
184
+
183
185
it ( 'handles subscription operations via POST' , async ( ) => {
184
186
const [ app ] = buildApp ( false ) ;
185
187
await app . ready ( ) ;
@@ -235,6 +237,7 @@ event: complete
235
237
data"
236
238
` ) ;
237
239
} ) ;
240
+
238
241
it ( 'should handle file uploads' , async ( ) => {
239
242
const [ app ] = buildApp ( false ) ;
240
243
await app . ready ( ) ;
@@ -259,6 +262,7 @@ data"
259
262
} ,
260
263
} ) ;
261
264
} ) ;
265
+
262
266
it ( 'request cancelation' , async ( ) => {
263
267
const [ app ] = buildApp ( false ) ;
264
268
await app . ready ( ) ;
@@ -308,6 +312,55 @@ data"
308
312
app . log . info = info ;
309
313
}
310
314
} ) ;
315
+
316
+ it ( 'subscription cancelation' , async ( ) => {
317
+ const [ app ] = buildApp ( false ) ;
318
+ await app . ready ( ) ;
319
+ const cancelationIsLoggedPromise = createDeferred ( ) ;
320
+ const address = await app . listen ( {
321
+ port : 0 ,
322
+ } ) ;
323
+
324
+ // we work with logger statements to detect when the subscription source is cleaned up.
325
+ const loggerOverwrite = ( part : unknown ) => {
326
+ if ( part === 'countdown aborted' ) {
327
+ cancelationIsLoggedPromise . resolve ( ) ;
328
+ }
329
+ } ;
330
+
331
+ const info = app . log . info ;
332
+ app . log . info = loggerOverwrite ;
333
+
334
+ try {
335
+ const abortController = new AbortController ( ) ;
336
+ const url = new URL ( `${ address } /graphql` ) ;
337
+ url . searchParams . set (
338
+ 'query' ,
339
+ /* GraphQL */ `
340
+ subscription {
341
+ countdown(from: 10, interval: 5)
342
+ }
343
+ ` ,
344
+ ) ;
345
+ const response = await fetch ( url , {
346
+ method : 'GET' ,
347
+ headers : {
348
+ 'content-type' : 'application/json' ,
349
+ accept : 'text/event-stream' ,
350
+ } ,
351
+ signal : abortController . signal ,
352
+ } ) ;
353
+
354
+ const iterator = eventStream ( response . body ! ) ;
355
+ const next = await iterator . next ( ) ;
356
+ expect ( next . value ) . toEqual ( { data : { countdown : 10 } } ) ;
357
+ abortController . abort ( ) ;
358
+ await expect ( iterator . next ( ) ) . rejects . toMatchInlineSnapshot ( `DOMException {}` ) ;
359
+ await cancelationIsLoggedPromise . promise ;
360
+ } finally {
361
+ app . log . info = info ;
362
+ }
363
+ } ) ;
311
364
} ) ;
312
365
313
366
type Deferred < T = void > = {
0 commit comments