github.com/99designs/gqlgen@v0.17.45/graphql/handler/transport/sse_test.go (about) 1 package transport_test 2 3 import ( 4 "bufio" 5 "io" 6 "net/http" 7 "net/http/httptest" 8 "strings" 9 "sync" 10 "testing" 11 12 "github.com/stretchr/testify/assert" 13 "github.com/stretchr/testify/require" 14 15 "github.com/99designs/gqlgen/graphql/handler/testserver" 16 "github.com/99designs/gqlgen/graphql/handler/transport" 17 ) 18 19 func TestSSE(t *testing.T) { 20 initialize := func() *testserver.TestServer { 21 h := testserver.New() 22 h.AddTransport(transport.SSE{}) 23 return h 24 } 25 26 initializeWithServer := func() (*testserver.TestServer, *httptest.Server) { 27 h := initialize() 28 return h, httptest.NewServer(h) 29 } 30 31 createHTTPTestRequest := func(query string) *http.Request { 32 req := httptest.NewRequest(http.MethodPost, "/graphql", strings.NewReader(query)) 33 req.Header.Set("Accept", "text/event-stream") 34 req.Header.Set("content-type", "application/json; charset=utf-8") 35 return req 36 } 37 38 createHTTPRequest := func(url string, query string) *http.Request { 39 req, err := http.NewRequest("POST", url, strings.NewReader(query)) 40 require.NoError(t, err, "Request threw error -> %s", err) 41 req.Header.Set("Accept", "text/event-stream") 42 req.Header.Set("content-type", "application/json; charset=utf-8") 43 return req 44 } 45 46 readLine := func(br *bufio.Reader) string { 47 bs, err := br.ReadString('\n') 48 require.NoError(t, err) 49 return bs 50 } 51 52 t.Run("stream failure", func(t *testing.T) { 53 h := initialize() 54 req := httptest.NewRequest(http.MethodPost, "/graphql", strings.NewReader(`{"query":"subscription { name }"}`)) 55 req.Header.Set("content-type", "application/json; charset=utf-8") 56 w := httptest.NewRecorder() 57 h.ServeHTTP(w, req) 58 assert.Equal(t, 400, w.Code, "Request return wrong status -> %d", w.Code) 59 assert.Equal(t, `{"errors":[{"message":"transport not supported"}],"data":null}`, w.Body.String()) 60 }) 61 62 t.Run("decode failure", func(t *testing.T) { 63 h := initialize() 64 req := createHTTPTestRequest("notjson") 65 w := httptest.NewRecorder() 66 h.ServeHTTP(w, req) 67 assert.Equal(t, 400, w.Code, "Request return wrong status -> %d", w.Code) 68 assert.Equal(t, `{"errors":[{"message":"json request body could not be decoded: invalid character 'o' in literal null (expecting 'u') body:notjson"}],"data":null}`, w.Body.String()) 69 }) 70 71 t.Run("parse failure", func(t *testing.T) { 72 h := initialize() 73 req := createHTTPTestRequest(`{"query":"subscription {{ name }"}`) 74 w := httptest.NewRecorder() 75 h.ServeHTTP(w, req) 76 77 assert.Equal(t, 200, w.Code, "Request return wrong status -> %d", w.Code) 78 assert.Equal(t, "keep-alive", w.Header().Get("Connection")) 79 assert.Equal(t, "text/event-stream", w.Header().Get("Content-Type")) 80 81 br := bufio.NewReader(w.Body) 82 83 assert.Equal(t, ":\n", readLine(br)) 84 assert.Equal(t, "\n", readLine(br)) 85 assert.Equal(t, "event: next\n", readLine(br)) 86 assert.Equal(t, "data: {\"errors\":[{\"message\":\"Expected Name, found {\",\"locations\":[{\"line\":1,\"column\":15}],\"extensions\":{\"code\":\"GRAPHQL_PARSE_FAILED\"}}],\"data\":null}\n", readLine(br)) 87 assert.Equal(t, "\n", readLine(br)) 88 assert.Equal(t, "event: complete\n", readLine(br)) 89 assert.Equal(t, "\n", readLine(br)) 90 91 _, err := br.ReadByte() 92 assert.Equal(t, err, io.EOF) 93 }) 94 95 t.Run("subscribe", func(t *testing.T) { 96 handler, srv := initializeWithServer() 97 defer srv.Close() 98 99 var wg sync.WaitGroup 100 wg.Add(1) 101 go func() { 102 defer wg.Done() 103 handler.SendNextSubscriptionMessage() 104 }() 105 106 client := &http.Client{} 107 req := createHTTPRequest(srv.URL, `{"query":"subscription { name }"}`) 108 res, err := client.Do(req) 109 require.NoError(t, err, "Request threw error -> %s", err) 110 defer func() { 111 require.NoError(t, res.Body.Close()) 112 }() 113 114 assert.Equal(t, 200, res.StatusCode, "Request return wrong status -> %d", res.Status) 115 assert.Equal(t, "keep-alive", res.Header.Get("Connection")) 116 assert.Equal(t, "text/event-stream", res.Header.Get("Content-Type")) 117 118 br := bufio.NewReader(res.Body) 119 120 assert.Equal(t, ":\n", readLine(br)) 121 assert.Equal(t, "\n", readLine(br)) 122 assert.Equal(t, "event: next\n", readLine(br)) 123 assert.Equal(t, "data: {\"data\":{\"name\":\"test\"}}\n", readLine(br)) 124 assert.Equal(t, "\n", readLine(br)) 125 126 wg.Add(1) 127 go func() { 128 defer wg.Done() 129 handler.SendNextSubscriptionMessage() 130 }() 131 132 assert.Equal(t, "event: next\n", readLine(br)) 133 assert.Equal(t, "data: {\"data\":{\"name\":\"test\"}}\n", readLine(br)) 134 assert.Equal(t, "\n", readLine(br)) 135 136 wg.Add(1) 137 go func() { 138 defer wg.Done() 139 handler.SendCompleteSubscriptionMessage() 140 }() 141 142 assert.Equal(t, "event: complete\n", readLine(br)) 143 assert.Equal(t, "\n", readLine(br)) 144 145 _, err = br.ReadByte() 146 assert.Equal(t, err, io.EOF) 147 148 wg.Wait() 149 }) 150 }