1
+ import { SSEClientTransport } from "./sse.js" ;
2
+ import { createServer , type Server } from "http" ;
3
+ import { JSONRPCMessage } from "../types.js" ;
4
+ import { AddressInfo } from "net" ;
5
+
6
+ describe ( "SSEClientTransport" , ( ) => {
7
+ let server : Server ;
8
+ let transport : SSEClientTransport ;
9
+ let baseUrl : URL ;
10
+
11
+ beforeEach ( ( done ) => {
12
+ // Create a test server that will receive the EventSource connection
13
+ server = createServer ( ( req , res ) => {
14
+ // Store the received headers for verification
15
+ ( server as any ) . lastRequest = req ;
16
+
17
+ // Send SSE headers
18
+ res . writeHead ( 200 , {
19
+ "Content-Type" : "text/event-stream" ,
20
+ "Cache-Control" : "no-cache" ,
21
+ "Connection" : "keep-alive"
22
+ } ) ;
23
+
24
+ // Send the endpoint event
25
+ res . write ( "event: endpoint\n" ) ;
26
+ res . write ( `data: ${ baseUrl . href } \n\n` ) ;
27
+ } ) ;
28
+
29
+ // Start server on random port
30
+ server . listen ( 0 , "127.0.0.1" , ( ) => {
31
+ const addr = server . address ( ) as AddressInfo ;
32
+ baseUrl = new URL ( `http://127.0.0.1:${ addr . port } ` ) ;
33
+ done ( ) ;
34
+ } ) ;
35
+ } ) ;
36
+
37
+ afterEach ( ( done ) => {
38
+ transport ?. close ( ) . then ( ( ) => {
39
+ server . close ( done ) ;
40
+ } ) ;
41
+ } ) ;
42
+
43
+ it ( "uses custom fetch implementation from EventSourceInit to add auth headers" , async ( ) => {
44
+ const authToken = "Bearer test-token" ;
45
+
46
+ // Create a fetch wrapper that adds auth header
47
+ const fetchWithAuth = ( url : string | URL , init ?: RequestInit ) => {
48
+ const headers = new Headers ( init ?. headers ) ;
49
+ headers . set ( "Authorization" , authToken ) ;
50
+ return fetch ( url . toString ( ) , { ...init , headers } ) ;
51
+ } ;
52
+
53
+ transport = new SSEClientTransport ( baseUrl , {
54
+ eventSourceInit : {
55
+ fetch : fetchWithAuth
56
+ }
57
+ } ) ;
58
+
59
+ await transport . start ( ) ;
60
+
61
+ // Verify the auth header was received by the server
62
+ const headers = ( server as any ) . lastRequest . headers ;
63
+ expect ( headers . authorization ) . toBe ( authToken ) ;
64
+ } ) ;
65
+
66
+ it ( "passes custom headers to fetch requests" , async ( ) => {
67
+ const customHeaders = {
68
+ Authorization : "Bearer test-token" ,
69
+ "X-Custom-Header" : "custom-value"
70
+ } ;
71
+
72
+ transport = new SSEClientTransport ( baseUrl , {
73
+ requestInit : {
74
+ headers : customHeaders
75
+ }
76
+ } ) ;
77
+
78
+ await transport . start ( ) ;
79
+
80
+ // Mock fetch for the message sending test
81
+ global . fetch = jest . fn ( ) . mockResolvedValue ( {
82
+ ok : true
83
+ } ) ;
84
+
85
+ const message : JSONRPCMessage = {
86
+ jsonrpc : "2.0" ,
87
+ id : "1" ,
88
+ method : "test" ,
89
+ params : { }
90
+ } ;
91
+
92
+ await transport . send ( message ) ;
93
+
94
+ // Verify fetch was called with correct headers
95
+ expect ( global . fetch ) . toHaveBeenCalledWith (
96
+ expect . any ( URL ) ,
97
+ expect . objectContaining ( {
98
+ headers : expect . any ( Headers )
99
+ } )
100
+ ) ;
101
+
102
+ const calledHeaders = ( global . fetch as jest . Mock ) . mock . calls [ 0 ] [ 1 ] . headers ;
103
+ expect ( calledHeaders . get ( "Authorization" ) ) . toBe ( customHeaders . Authorization ) ;
104
+ expect ( calledHeaders . get ( "X-Custom-Header" ) ) . toBe ( customHeaders [ "X-Custom-Header" ] ) ;
105
+ expect ( calledHeaders . get ( "content-type" ) ) . toBe ( "application/json" ) ;
106
+ } ) ;
107
+ } ) ;
0 commit comments