@@ -2,11 +2,14 @@ import { AUTH_TYPE } from "aws-appsync-auth-link";
22import { execute } from "@apollo/client/core" ;
33import gql from 'graphql-tag' ;
44import { AppSyncRealTimeSubscriptionHandshakeLink } from '../../src/realtime-subscription-handshake-link' ;
5+ import { MESSAGE_TYPES } from "../../src/types" ;
6+ import { v4 as uuid } from "uuid" ;
7+ jest . mock ( 'uuid' , ( ) => ( { v4 : jest . fn ( ) } ) ) ;
58
69const query = gql `subscription { someSubscription { aField } }`
710
811class myWebSocket implements WebSocket {
9- binaryType : BinaryType ;
12+ binaryType : BinaryType ;
1013 bufferedAmount : number ;
1114 extensions : string ;
1215 onclose : ( this : WebSocket , ev : CloseEvent ) => any ;
@@ -359,6 +362,164 @@ describe("RealTime subscription link", () => {
359362 }
360363
361364 } ) ;
362- } )
365+ } ) ;
366+
367+ test ( "Can use a custom keepAliveTimeoutMs" , ( done ) => {
368+ const id = "abcd-efgh-ijkl-mnop" ;
369+ uuid . mockImplementationOnce ( ( ) => id ) ;
370+
371+ expect . assertions ( 5 ) ;
372+ jest . spyOn ( Date . prototype , 'toISOString' ) . mockImplementation ( jest . fn ( ( ) => {
373+ return "2019-11-13T18:47:04.733Z" ;
374+ } ) ) ;
375+ AppSyncRealTimeSubscriptionHandshakeLink . createWebSocket = jest . fn ( ( url , protocol ) => {
376+ expect ( url ) . toBe ( 'wss://apikeytest.testcustomdomain.com/graphql/realtime?header=eyJob3N0IjoiYXBpa2V5dGVzdC50ZXN0Y3VzdG9tZG9tYWluLmNvbSIsIngtYW16LWRhdGUiOiIyMDE5MTExM1QxODQ3MDRaIiwieC1hcGkta2V5IjoieHh4eHgifQ==&payload=e30=' ) ;
377+ expect ( protocol ) . toBe ( 'graphql-ws' ) ;
378+ const socket = new myWebSocket ( ) ;
379+
380+ setTimeout ( ( ) => {
381+ socket . close = ( ) => { } ;
382+ socket . onopen . call ( socket , ( undefined as unknown as Event ) ) ;
383+ socket . send = ( msg : string ) => {
384+ const { type } = JSON . parse ( msg ) ;
385+
386+ switch ( type ) {
387+ case MESSAGE_TYPES . GQL_CONNECTION_INIT :
388+ socket . onmessage . call ( socket , {
389+ data : JSON . stringify ( {
390+ type : MESSAGE_TYPES . GQL_CONNECTION_ACK ,
391+ payload : {
392+ connectionTimeoutMs : 99999 ,
393+ } ,
394+ } )
395+ } as MessageEvent ) ;
396+ setTimeout ( ( ) => {
397+ socket . onmessage . call ( socket , {
398+ data : JSON . stringify ( {
399+ id,
400+ type : MESSAGE_TYPES . GQL_DATA ,
401+ payload : {
402+ data : { something : 123 } ,
403+ } ,
404+ } )
405+ } as MessageEvent ) ;
406+
407+ } , 100 ) ;
408+ break ;
409+ }
410+ } ;
411+ } , 100 ) ;
412+
413+ return socket ;
414+ } ) ;
415+ const link = new AppSyncRealTimeSubscriptionHandshakeLink ( {
416+ auth : {
417+ type : AUTH_TYPE . API_KEY ,
418+ apiKey : 'xxxxx'
419+ } ,
420+ region : 'us-west-2' ,
421+ url : 'https://apikeytest.testcustomdomain.com/graphql' ,
422+ keepAliveTimeoutMs : 123456 ,
423+ } ) ;
424+
425+ expect ( link ) . toBeInstanceOf ( AppSyncRealTimeSubscriptionHandshakeLink ) ;
426+ expect ( ( link as any ) . keepAliveTimeout ) . toBe ( 123456 ) ;
427+
428+ const sub = execute ( link , { query } ) . subscribe ( {
429+ error : ( err ) => {
430+ console . log ( JSON . stringify ( err ) ) ;
431+ fail ( ) ;
432+ } ,
433+ next : ( data ) => {
434+ expect ( ( link as any ) . keepAliveTimeout ) . toBe ( 123456 ) ;
435+ done ( ) ;
436+ sub . unsubscribe ( ) ;
437+ } ,
438+ complete : ( ) => {
439+ console . log ( 'done with this' ) ;
440+ fail ( ) ;
441+ }
442+
443+ } ) ;
444+ } ) ;
445+
446+ test ( "Uses service-provided timeout when no custom keepAliveTimeoutMs is configured" , ( done ) => {
447+ const id = "abcd-efgh-ijkl-mnop" ;
448+ uuid . mockImplementationOnce ( ( ) => id ) ;
449+
450+ expect . assertions ( 5 ) ;
451+ jest . spyOn ( Date . prototype , 'toISOString' ) . mockImplementation ( jest . fn ( ( ) => {
452+ return "2019-11-13T18:47:04.733Z" ;
453+ } ) ) ;
454+ AppSyncRealTimeSubscriptionHandshakeLink . createWebSocket = jest . fn ( ( url , protocol ) => {
455+ expect ( url ) . toBe ( 'wss://apikeytest.testcustomdomain.com/graphql/realtime?header=eyJob3N0IjoiYXBpa2V5dGVzdC50ZXN0Y3VzdG9tZG9tYWluLmNvbSIsIngtYW16LWRhdGUiOiIyMDE5MTExM1QxODQ3MDRaIiwieC1hcGkta2V5IjoieHh4eHgifQ==&payload=e30=' ) ;
456+ expect ( protocol ) . toBe ( 'graphql-ws' ) ;
457+ const socket = new myWebSocket ( ) ;
458+
459+ setTimeout ( ( ) => {
460+ socket . close = ( ) => { } ;
461+ socket . onopen . call ( socket , ( undefined as unknown as Event ) ) ;
462+ socket . send = ( msg : string ) => {
463+ const { type } = JSON . parse ( msg ) ;
464+
465+ switch ( type ) {
466+ case MESSAGE_TYPES . GQL_CONNECTION_INIT :
467+ socket . onmessage . call ( socket , {
468+ data : JSON . stringify ( {
469+ type : MESSAGE_TYPES . GQL_CONNECTION_ACK ,
470+ payload : {
471+ connectionTimeoutMs : 99999 ,
472+ } ,
473+ } )
474+ } as MessageEvent ) ;
475+ setTimeout ( ( ) => {
476+ socket . onmessage . call ( socket , {
477+ data : JSON . stringify ( {
478+ id,
479+ type : MESSAGE_TYPES . GQL_DATA ,
480+ payload : {
481+ data : { something : 123 } ,
482+ } ,
483+ } )
484+ } as MessageEvent ) ;
485+
486+ } , 100 ) ;
487+ break ;
488+ }
489+ } ;
490+ } , 100 ) ;
491+
492+ return socket ;
493+ } ) ;
494+ const link = new AppSyncRealTimeSubscriptionHandshakeLink ( {
495+ auth : {
496+ type : AUTH_TYPE . API_KEY ,
497+ apiKey : 'xxxxx'
498+ } ,
499+ region : 'us-west-2' ,
500+ url : 'https://apikeytest.testcustomdomain.com/graphql' ,
501+ } ) ;
502+
503+ expect ( link ) . toBeInstanceOf ( AppSyncRealTimeSubscriptionHandshakeLink ) ;
504+ expect ( ( link as any ) . keepAliveTimeout ) . toBeUndefined ( ) ;
505+
506+ const sub = execute ( link , { query } ) . subscribe ( {
507+ error : ( err ) => {
508+ console . log ( JSON . stringify ( err ) ) ;
509+ fail ( ) ;
510+ } ,
511+ next : ( data ) => {
512+ expect ( ( link as any ) . keepAliveTimeout ) . toBe ( 99999 ) ;
513+ done ( ) ;
514+ sub . unsubscribe ( ) ;
515+ } ,
516+ complete : ( ) => {
517+ console . log ( 'done with this' ) ;
518+ fail ( ) ;
519+ }
520+
521+ } ) ;
522+ } ) ;
523+
363524
364525} ) ;
0 commit comments