@@ -648,76 +648,6 @@ describe("ConversationService", () => {
648648 expect ( commentPromise ) . resolves . toBeUndefined ( ) ;
649649 } ) ;
650650
651- it ( "appends custom fetch options" , async ( ) => {
652- const conversationService = new ConversationService ( {
653- serverUrl,
654- fetchOptions : {
655- headers : new Headers ( {
656- foo : "bar" ,
657- } ) ,
658- credentials : "include" ,
659- } ,
660- } ) ;
661- let getOptions = mockFetchResponse ( {
662- data : {
663- _id : "650b4b260f975ef031016c8d" ,
664- messages : [ ] ,
665- createdAt : new Date ( ) . getTime ( ) ,
666- } ,
667- } ) ;
668- await conversationService . createConversation ( ) ;
669- const createOptions = getOptions ( ) ;
670-
671- expect ( createOptions . headers ?. get ( "foo" ) ) . toBe ( "bar" ) ;
672- expect ( createOptions . headers ?. get ( "content-type" ) ) . toBe ( "application/json" ) ;
673- expect ( createOptions . credentials ) . toBe ( "include" ) ;
674-
675- await conversationService . addMessage ( { conversationId : "" , message : "" } ) ;
676- const addOptions = getOptions ( ) ;
677- expect ( addOptions . headers ?. get ( "foo" ) ) . toBe ( "bar" ) ;
678- expect ( addOptions . headers ?. get ( "content-type" ) ) . toBe ( "application/json" ) ;
679- expect ( addOptions . credentials ) . toBe ( "include" ) ;
680-
681- await conversationService . addMessageStreaming ( {
682- conversationId : "" ,
683- message : "" ,
684- onResponseDelta : vi . fn ( ) ,
685- onResponseFinished : vi . fn ( ) ,
686- onReferences : vi . fn ( ) ,
687- onMetadata : vi . fn ( ) ,
688- } ) ;
689- const addStreamingOptions = getOptions ( ) ;
690- expect ( addStreamingOptions . headers ?. get ( "foo" ) ) . toBe ( "bar" ) ;
691- expect ( addStreamingOptions . headers ?. get ( "content-type" ) ) . toBe (
692- "application/json"
693- ) ;
694- expect ( addStreamingOptions . credentials ) . toBe ( "include" ) ;
695-
696- // Updating the mock fetch to return 204, which is used by the following two calls.
697- getOptions = mockFetchResponse ( { data : { } , status : 204 } ) ;
698- await conversationService . rateMessage ( {
699- conversationId : "a" ,
700- messageId : "b" ,
701- rating : true ,
702- } ) ;
703- const ratingOptions = getOptions ( ) ;
704- expect ( ratingOptions . headers ?. get ( "foo" ) ) . toBe ( "bar" ) ;
705- expect ( ratingOptions . headers ?. get ( "content-type" ) ) . toBe ( "application/json" ) ;
706- expect ( ratingOptions . credentials ) . toBe ( "include" ) ;
707-
708- await conversationService . commentMessage ( {
709- conversationId : "" ,
710- comment : "" ,
711- messageId : "" ,
712- } ) ;
713- const commentOptions = getOptions ( ) ;
714- expect ( commentOptions . headers ?. get ( "foo" ) ) . toBe ( "bar" ) ;
715- expect ( commentOptions . headers ?. get ( "content-type" ) ) . toBe (
716- "application/json"
717- ) ;
718- expect ( commentOptions . credentials ) . toBe ( "include" ) ;
719- } ) ;
720-
721651 it ( "throws on invalid inputs" , async ( ) => {
722652 const conversationId = "650b4b260f975ef031016c8d" ;
723653 const messageId = "650b4be0d5a57dd66be2ccb9" ;
@@ -789,6 +719,172 @@ describe("ConversationService", () => {
789719 } ) ;
790720 } ) . rejects . toThrow ( internalServerErrorMessage ) ;
791721 } ) ;
722+
723+ describe ( "fetchOptions" , ( ) => {
724+ it ( "supports static fetchOptions" , async ( ) => {
725+ const conversationService = new ConversationService ( {
726+ serverUrl,
727+ fetchOptions : {
728+ headers : new Headers ( {
729+ foo : "bar" ,
730+ } ) ,
731+ credentials : "include" ,
732+ } ,
733+ } ) ;
734+ let getOptions = mockFetchResponse ( {
735+ data : {
736+ _id : "650b4b260f975ef031016c8d" ,
737+ messages : [ ] ,
738+ createdAt : new Date ( ) . getTime ( ) ,
739+ } ,
740+ } ) ;
741+ await conversationService . createConversation ( ) ;
742+ const createOptions = getOptions ( ) ;
743+ const createOptionsHeaders = new Headers ( createOptions . headers ) ;
744+
745+ expect ( createOptionsHeaders . get ( "foo" ) ) . toBe ( "bar" ) ;
746+ expect ( createOptionsHeaders . get ( "content-type" ) ) . toBe ( "application/json" ) ;
747+ expect ( createOptions . credentials ) . toBe ( "include" ) ;
748+
749+ await conversationService . addMessage ( { conversationId : "" , message : "" } ) ;
750+ const addOptions = getOptions ( ) ;
751+ const addOptionsHeaders = new Headers ( addOptions . headers ) ;
752+ expect ( addOptionsHeaders . get ( "foo" ) ) . toBe ( "bar" ) ;
753+ expect ( addOptionsHeaders . get ( "content-type" ) ) . toBe ( "application/json" ) ;
754+ expect ( addOptions . credentials ) . toBe ( "include" ) ;
755+
756+ await conversationService . addMessageStreaming ( {
757+ conversationId : "" ,
758+ message : "" ,
759+ onResponseDelta : vi . fn ( ) ,
760+ onResponseFinished : vi . fn ( ) ,
761+ onReferences : vi . fn ( ) ,
762+ onMetadata : vi . fn ( ) ,
763+ } ) ;
764+ const addStreamingOptions = getOptions ( ) ;
765+ const addStreamingOptionsHeaders = new Headers (
766+ addStreamingOptions . headers
767+ ) ;
768+ expect ( addStreamingOptionsHeaders . get ( "foo" ) ) . toBe ( "bar" ) ;
769+ expect ( addStreamingOptionsHeaders . get ( "content-type" ) ) . toBe (
770+ "application/json"
771+ ) ;
772+ expect ( addStreamingOptions . credentials ) . toBe ( "include" ) ;
773+
774+ // Updating the mock fetch to return 204, which is used by the following two calls.
775+ getOptions = mockFetchResponse ( { data : { } , status : 204 } ) ;
776+ await conversationService . rateMessage ( {
777+ conversationId : "a" ,
778+ messageId : "b" ,
779+ rating : true ,
780+ } ) ;
781+ const ratingOptions = getOptions ( ) ;
782+ const ratingOptionsHeaders = new Headers ( ratingOptions . headers ) ;
783+ expect ( ratingOptionsHeaders . get ( "foo" ) ) . toBe ( "bar" ) ;
784+ expect ( ratingOptionsHeaders . get ( "content-type" ) ) . toBe ( "application/json" ) ;
785+ expect ( ratingOptions . credentials ) . toBe ( "include" ) ;
786+
787+ await conversationService . commentMessage ( {
788+ conversationId : "" ,
789+ comment : "" ,
790+ messageId : "" ,
791+ } ) ;
792+ const commentOptions = getOptions ( ) ;
793+ const commentOptionsHeaders = new Headers ( commentOptions . headers ) ;
794+ expect ( commentOptionsHeaders . get ( "foo" ) ) . toBe ( "bar" ) ;
795+ expect ( commentOptionsHeaders . get ( "content-type" ) ) . toBe (
796+ "application/json"
797+ ) ;
798+ expect ( commentOptions . credentials ) . toBe ( "include" ) ;
799+ } ) ;
800+
801+ it ( "generates new headers on every request with dynamic fetchOptions" , async ( ) => {
802+ let callCount = 0 ;
803+ const conversationService = new ConversationService ( {
804+ serverUrl,
805+ fetchOptions : ( ) => ( {
806+ headers : new Headers ( {
807+ foo : `dynamic-${ ++ callCount } ` ,
808+ } ) ,
809+ credentials : "include" ,
810+ } ) ,
811+ } ) ;
812+ let getOptions = mockFetchResponse ( {
813+ data : {
814+ _id : "650b4b260f975ef031016c8d" ,
815+ messages : [ ] ,
816+ createdAt : new Date ( ) . getTime ( ) ,
817+ } ,
818+ } ) ;
819+ await conversationService . createConversation ( ) ;
820+ const createOptions = getOptions ( ) ;
821+ const createOptionsHeaders = new Headers ( createOptions . headers ) ;
822+
823+ expect ( createOptionsHeaders . get ( "foo" ) ) . toBe ( "dynamic-1" ) ;
824+ expect ( createOptionsHeaders . get ( "content-type" ) ) . toBe ( "application/json" ) ;
825+ expect ( createOptions . credentials ) . toBe ( "include" ) ;
826+
827+ await conversationService . addMessage ( { conversationId : "" , message : "" } ) ;
828+ const addOptions = getOptions ( ) ;
829+ const addOptionsHeaders = new Headers ( addOptions . headers ) ;
830+ expect ( addOptionsHeaders . get ( "foo" ) ) . toBe ( "dynamic-2" ) ;
831+ expect ( addOptionsHeaders . get ( "content-type" ) ) . toBe ( "application/json" ) ;
832+ expect ( addOptions . credentials ) . toBe ( "include" ) ;
833+
834+ // For addMessageStreaming, we need to mock fetchEventSource to capture headers
835+ let streamingOptions : any ;
836+ ( FetchEventSource . fetchEventSource as jest . Mock ) . mockImplementation (
837+ async ( _url , options ) => {
838+ streamingOptions = options ;
839+ return {
840+ ok : true ,
841+ status : 200 ,
842+ headers : new Headers ( { "content-type" : "text/event-stream" } ) ,
843+ } ;
844+ }
845+ ) ;
846+
847+ await conversationService . addMessageStreaming ( {
848+ conversationId : "" ,
849+ message : "" ,
850+ onResponseDelta : vi . fn ( ) ,
851+ onResponseFinished : vi . fn ( ) ,
852+ onReferences : vi . fn ( ) ,
853+ onMetadata : vi . fn ( ) ,
854+ } ) ;
855+
856+ // Check the headers from fetchEventSource
857+ expect ( streamingOptions . headers . foo ) . toBe ( "dynamic-3" ) ;
858+ expect ( streamingOptions . headers [ "content-type" ] ) . toBe ( "application/json" ) ;
859+ expect ( streamingOptions . credentials ) . toBe ( "include" ) ;
860+
861+ // Updating the mock fetch to return 204, which is used by the following two calls.
862+ getOptions = mockFetchResponse ( { data : { } , status : 204 } ) ;
863+ await conversationService . rateMessage ( {
864+ conversationId : "a" ,
865+ messageId : "b" ,
866+ rating : true ,
867+ } ) ;
868+ const ratingOptions = getOptions ( ) ;
869+ const ratingOptionsHeaders = new Headers ( ratingOptions . headers ) ;
870+ expect ( ratingOptionsHeaders . get ( "foo" ) ) . toBe ( "dynamic-4" ) ;
871+ expect ( ratingOptionsHeaders . get ( "content-type" ) ) . toBe ( "application/json" ) ;
872+ expect ( ratingOptions . credentials ) . toBe ( "include" ) ;
873+
874+ await conversationService . commentMessage ( {
875+ conversationId : "" ,
876+ comment : "" ,
877+ messageId : "" ,
878+ } ) ;
879+ const commentOptions = getOptions ( ) ;
880+ const commentOptionsHeaders = new Headers ( commentOptions . headers ) ;
881+ expect ( commentOptionsHeaders . get ( "foo" ) ) . toBe ( "dynamic-5" ) ;
882+ expect ( commentOptionsHeaders . get ( "content-type" ) ) . toBe (
883+ "application/json"
884+ ) ;
885+ expect ( commentOptions . credentials ) . toBe ( "include" ) ;
886+ } ) ;
887+ } ) ;
792888} ) ;
793889
794890describe ( "getCustomRequestOrigin" , ( ) => {
0 commit comments