├── .gitignore ├── .travis.yml ├── Gopkg.lock ├── Gopkg.toml ├── LICENSE ├── README.md ├── go.mod ├── go.sum ├── requester.go ├── response.go ├── testflight.go ├── testflight_test.go └── ws ├── connection.go ├── errors.go ├── ws.go └── ws_test.go /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - "1.10" 4 | install: 5 | - go get -u golang.org/x/vgo 6 | script: 7 | - $GOPATH/bin/vgo test -v ./... 8 | -------------------------------------------------------------------------------- /Gopkg.lock: -------------------------------------------------------------------------------- 1 | # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. 2 | 3 | 4 | [[projects]] 5 | branch = "master" 6 | name = "github.com/bmizerany/assert" 7 | packages = ["."] 8 | revision = "b7ed37b82869576c289d7d97fb2bbd8b64a0cb28" 9 | 10 | [[projects]] 11 | branch = "master" 12 | name = "github.com/bmizerany/pat" 13 | packages = ["."] 14 | revision = "6226ea591a40176dd3ff9cd8eff81ed6ca721a00" 15 | 16 | [[projects]] 17 | branch = "master" 18 | name = "github.com/kr/pretty" 19 | packages = ["."] 20 | revision = "cfb55aafdaf3ec08f0db22699ab822c50091b1c4" 21 | 22 | [[projects]] 23 | branch = "master" 24 | name = "github.com/kr/text" 25 | packages = ["."] 26 | revision = "7cafcd837844e784b526369c9bce262804aebc60" 27 | 28 | [[projects]] 29 | branch = "master" 30 | name = "golang.org/x/net" 31 | packages = ["websocket"] 32 | revision = "c73622c77280266305273cb545f54516ced95b93" 33 | 34 | [solve-meta] 35 | analyzer-name = "dep" 36 | analyzer-version = 1 37 | inputs-digest = "91dbae46b3311aeb65253e60ba0cf1d931d4ad00ee82e41afd1ce33f974d53f0" 38 | solver-name = "gps-cdcl" 39 | solver-version = 1 40 | -------------------------------------------------------------------------------- /Gopkg.toml: -------------------------------------------------------------------------------- 1 | [[constraint]] 2 | branch = "master" 3 | name = "github.com/bmizerany/assert" 4 | 5 | [[constraint]] 6 | branch = "master" 7 | name = "github.com/bmizerany/pat" 8 | 9 | [[constraint]] 10 | branch = "master" 11 | name = "golang.org/x/net" 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2012, 2013, 2014, 2015 Andrew Olson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # testflight 2 | 3 | [![Build Status](https://travis-ci.org/drewolson/testflight.png?branch=master)](https://travis-ci.org/drewolson/testflight) 4 | 5 | ## Installation 6 | 7 | ```bash 8 | go get github.com/drewolson/testflight 9 | ``` 10 | 11 | ```go 12 | import "github.com/drewolson/testflight" 13 | ``` 14 | 15 | ## Usage 16 | 17 | testflight makes it simple to test your http servers in Go. Suppose you're using [pat](https://github.com/bmizerany/pat) to create a simple http handler, like so: 18 | 19 | ```go 20 | func Handler() http.Handler { 21 | m := pat.New() 22 | 23 | m.Get("/hello/:name", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { 24 | io.WriteString(w, "hello, "+req.URL.Query().Get(":name")) 25 | })) 26 | 27 | m.Post("/post/form", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { 28 | req.ParseForm() 29 | name := req.Form.Get("name") 30 | w.WriteHeader(201) 31 | io.WriteString(w, name+" created") 32 | })) 33 | 34 | return m 35 | } 36 | ``` 37 | 38 | Let's use testflight to test our handler. Keep in mind that testflight is doing full-stack http tests. We're also using assert for test assertions. 39 | 40 | ```go 41 | func TestGet(t *testing.T) { 42 | testflight.WithServer(Handler(), func(r *testflight.Requester) { 43 | response := r.Get("/hello/drew") 44 | 45 | assert.Equal(t, 200, response.StatusCode) 46 | assert.Equal(t, "hello, drew", response.Body) 47 | }) 48 | } 49 | 50 | func TestPostWithForm(t *testing.T) { 51 | testflight.WithServer(Handler(), func(r *testflight.Requester) { 52 | response := r.Post("/post/form", testflight.FORM_ENCODED, "name=Drew") 53 | 54 | assert.Equal(t, 201, response.StatusCode) 55 | assert.Equal(t, "Drew created", response.Body) 56 | }) 57 | } 58 | ``` 59 | 60 | The testflight.Requester struct has the following methods: Get, Post, Put, Delete and Do. Do accepts an *http.Request for times when you need more explicit control of your request. See testflight_test.go for more usage information. 61 | 62 | ## Testing Websockets 63 | 64 | Testflight also allows you to perform full-stack testing of websockets. You'll want to import both the testflight and testflight/ws packages. 65 | 66 | ```go 67 | import ( 68 | "github.com/drewolson/testflight" 69 | "github.com/drewolson/testflight/ws" 70 | ) 71 | ``` 72 | 73 | Now, let's make a handler with a websocket route. 74 | 75 | ```go 76 | func Handler() http.Handler { 77 | mux := http.NewServeMux() 78 | 79 | mux.Handle("/websocket", websocket.Handler(func(ws *websocket.Conn) { 80 | var name string 81 | websocket.Message.Receive(ws, &name) 82 | websocket.Message.Send(ws, "Hello, "+name) 83 | })) 84 | 85 | return mux 86 | } 87 | ``` 88 | 89 | Finally, let's write the test. 90 | 91 | ```go 92 | func TestWebSocket(t *testing.T) { 93 | testflight.WithServer(Handler(), func(r *testflight.Requester) { 94 | connection := ws.Connect(r, "/websocket") 95 | 96 | connection.SendMessage("Drew") 97 | message, _ := connection.ReceiveMessage() 98 | assert.Equal(t, "Hello, Drew", message) 99 | }) 100 | } 101 | ``` 102 | 103 | ## Contributing 104 | 105 | Requires go `>= 1.11`. 106 | 107 | Run the tests. 108 | 109 | ```bash 110 | go test -v ./... 111 | ``` 112 | 113 | Now write new tests, fix them and send me a pull request! 114 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/drewolson/testflight 2 | 3 | require ( 4 | github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 5 | github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40 6 | github.com/kr/pretty v0.0.0-20160823170715-cfb55aafdaf3 7 | github.com/kr/text v0.0.0-20160504234017-7cafcd837844 8 | golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01 9 | ) 10 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= 2 | github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= 3 | github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40 h1:y4B3+GPxKlrigF1ha5FFErxK+sr6sWxQovRMzwMhejo= 4 | github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= 5 | github.com/kr/pretty v0.0.0-20160823170715-cfb55aafdaf3 h1:dhwb1Ev84SKKVBfLuhR4bw/29yYHzwtTyTLUWWnvYxI= 6 | github.com/kr/pretty v0.0.0-20160823170715-cfb55aafdaf3/go.mod h1:Bvhd+E3laJ0AVkG0c9rmtZcnhV0HQ3+c3YxxqTvc/gA= 7 | github.com/kr/text v0.0.0-20160504234017-7cafcd837844 h1:kpzneEBeC0dMewP3gr/fADv1OlblH9r1goWVwpOt3TU= 8 | github.com/kr/text v0.0.0-20160504234017-7cafcd837844/go.mod h1:sjUstKUATFIcff4qlB53Kml0wQPtJVc/3fWrmuUmcfA= 9 | golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01 h1:po1f06KS05FvIQQA2pMuOWZAUXiy1KYdIf0ElUU2Hhc= 10 | golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 11 | -------------------------------------------------------------------------------- /requester.go: -------------------------------------------------------------------------------- 1 | package testflight 2 | 3 | import ( 4 | "net/http" 5 | "net/http/httptest" 6 | "net/url" 7 | "strings" 8 | ) 9 | 10 | type Requester struct { 11 | server *httptest.Server 12 | } 13 | 14 | func (requester *Requester) Get(route string) *Response { 15 | return requester.performRequest("GET", route, "", "") 16 | } 17 | 18 | func (requester *Requester) Post(route, contentType, body string) *Response { 19 | return requester.performRequest("POST", route, contentType, body) 20 | } 21 | 22 | func (requester *Requester) Put(route, contentType, body string) *Response { 23 | return requester.performRequest("PUT", route, contentType, body) 24 | } 25 | 26 | func (requester *Requester) Patch(route, contentType, body string) *Response { 27 | return requester.performRequest("PATCH", route, contentType, body) 28 | } 29 | 30 | func (requester *Requester) Delete(route, contentType, body string) *Response { 31 | return requester.performRequest("DELETE", route, contentType, body) 32 | } 33 | 34 | func (requester *Requester) Do(request *http.Request) *Response { 35 | fullUrl, err := url.Parse(requester.httpUrl(request.URL.String())) 36 | if err != nil { 37 | panic(err) 38 | } 39 | 40 | request.URL = fullUrl 41 | return requester.sendRequest(request) 42 | } 43 | 44 | func (requester *Requester) Url(route string) string { 45 | return requester.server.Listener.Addr().String() + route 46 | } 47 | 48 | func (requester *Requester) performRequest(httpAction, route, contentType, body string) *Response { 49 | request, err := http.NewRequest(httpAction, requester.httpUrl(route), strings.NewReader(body)) 50 | if err != nil { 51 | panic(err) 52 | } 53 | 54 | request.Header.Add("Content-Type", contentType) 55 | return requester.sendRequest(request) 56 | } 57 | 58 | func (requester *Requester) sendRequest(request *http.Request) *Response { 59 | client := http.Client{} 60 | response, err := client.Do(request) 61 | if err != nil { 62 | panic(err) 63 | } 64 | 65 | return newResponse(response) 66 | } 67 | 68 | func (requester *Requester) httpUrl(route string) string { 69 | return "http://" + requester.Url(route) 70 | } 71 | -------------------------------------------------------------------------------- /response.go: -------------------------------------------------------------------------------- 1 | package testflight 2 | 3 | import ( 4 | "io/ioutil" 5 | "net/http" 6 | ) 7 | 8 | type Response struct { 9 | Body string 10 | RawBody []byte 11 | RawResponse *http.Response 12 | StatusCode int 13 | Header http.Header 14 | } 15 | 16 | func newResponse(response *http.Response) *Response { 17 | body, _ := ioutil.ReadAll(response.Body) 18 | return &Response{ 19 | Body: string(body), 20 | RawBody: body, 21 | RawResponse: response, 22 | StatusCode: response.StatusCode, 23 | Header: response.Header, 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /testflight.go: -------------------------------------------------------------------------------- 1 | package testflight 2 | 3 | import ( 4 | "net/http" 5 | "net/http/httptest" 6 | ) 7 | 8 | const ( 9 | JSON = "application/json" 10 | FORM_ENCODED = "application/x-www-form-urlencoded" 11 | ) 12 | 13 | func WithServer(handler http.Handler, context func(*Requester)) { 14 | server := httptest.NewServer(handler) 15 | defer server.Close() 16 | 17 | requester := &Requester{server: server} 18 | context(requester) 19 | } 20 | -------------------------------------------------------------------------------- /testflight_test.go: -------------------------------------------------------------------------------- 1 | package testflight 2 | 3 | import ( 4 | "encoding/json" 5 | "io" 6 | "io/ioutil" 7 | "net/http" 8 | "strings" 9 | "testing" 10 | 11 | "github.com/bmizerany/assert" 12 | "github.com/bmizerany/pat" 13 | ) 14 | 15 | type person struct { 16 | Name string `json:"name"` 17 | } 18 | 19 | func handler() http.Handler { 20 | m := pat.New() 21 | 22 | m.Get("/hello/:name", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { 23 | io.WriteString(w, "hello, "+req.URL.Query().Get(":name")) 24 | })) 25 | 26 | m.Post("/post/json", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { 27 | person := &person{} 28 | body, _ := ioutil.ReadAll(req.Body) 29 | json.Unmarshal(body, person) 30 | w.WriteHeader(201) 31 | io.WriteString(w, person.Name+" created") 32 | })) 33 | 34 | m.Post("/post/form", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { 35 | req.ParseForm() 36 | name := req.Form.Get("name") 37 | w.WriteHeader(201) 38 | io.WriteString(w, name+" created") 39 | })) 40 | 41 | m.Put("/put/json", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { 42 | person := &person{} 43 | body, _ := ioutil.ReadAll(req.Body) 44 | json.Unmarshal(body, person) 45 | w.WriteHeader(200) 46 | io.WriteString(w, person.Name+" updated") 47 | })) 48 | 49 | m.Add("PATCH", "/patch/json", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { 50 | person := &person{} 51 | body, _ := ioutil.ReadAll(req.Body) 52 | json.Unmarshal(body, person) 53 | w.WriteHeader(200) 54 | io.WriteString(w, person.Name+" updated") 55 | })) 56 | 57 | m.Del("/delete/json", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { 58 | person := &person{} 59 | body, _ := ioutil.ReadAll(req.Body) 60 | json.Unmarshal(body, person) 61 | w.WriteHeader(200) 62 | io.WriteString(w, person.Name+" deleted") 63 | })) 64 | 65 | return m 66 | } 67 | 68 | func TestGet(t *testing.T) { 69 | WithServer(handler(), func(r *Requester) { 70 | response := r.Get("/hello/drew") 71 | 72 | assert.Equal(t, 200, response.StatusCode) 73 | assert.Equal(t, "hello, drew", response.Body) 74 | assert.Equal(t, []byte("hello, drew"), response.RawBody) 75 | }) 76 | } 77 | 78 | func TestPostWithJson(t *testing.T) { 79 | WithServer(handler(), func(r *Requester) { 80 | response := r.Post("/post/json", JSON, `{"name": "Drew"}`) 81 | 82 | assert.Equal(t, 201, response.StatusCode) 83 | assert.Equal(t, "Drew created", response.Body) 84 | }) 85 | } 86 | 87 | func TestPostWithForm(t *testing.T) { 88 | WithServer(handler(), func(r *Requester) { 89 | response := r.Post("/post/form", FORM_ENCODED, "name=Drew") 90 | 91 | assert.Equal(t, 201, response.StatusCode) 92 | assert.Equal(t, "Drew created", response.Body) 93 | }) 94 | } 95 | 96 | func TestPut(t *testing.T) { 97 | WithServer(handler(), func(r *Requester) { 98 | response := r.Put("/put/json", JSON, `{"name": "Drew"}`) 99 | 100 | assert.Equal(t, 200, response.StatusCode) 101 | assert.Equal(t, "Drew updated", response.Body) 102 | }) 103 | } 104 | 105 | func TestPatch(t *testing.T) { 106 | WithServer(handler(), func(r *Requester) { 107 | response := r.Patch("/patch/json", JSON, `{"name": "Yograterol"}`) 108 | 109 | assert.Equal(t, 200, response.StatusCode) 110 | assert.Equal(t, "Yograterol updated", response.Body) 111 | }) 112 | } 113 | 114 | func TestDelete(t *testing.T) { 115 | WithServer(handler(), func(r *Requester) { 116 | response := r.Delete("/delete/json", JSON, `{"name": "Drew"}`) 117 | 118 | assert.Equal(t, 200, response.StatusCode) 119 | assert.Equal(t, "Drew deleted", response.Body) 120 | }) 121 | } 122 | 123 | func TestResponeHeaders(t *testing.T) { 124 | WithServer(handler(), func(r *Requester) { 125 | response := r.Get("/hello/again_drew") 126 | assert.Equal(t, 200, response.StatusCode) 127 | header := response.Header 128 | assert.NotEqual(t, nil, header) 129 | assert.Equal(t, "text/plain; charset=utf-8", header.Get("Content-Type")) 130 | }) 131 | } 132 | 133 | func TestDo(t *testing.T) { 134 | WithServer(handler(), func(r *Requester) { 135 | request, _ := http.NewRequest("DELETE", "/delete/json", strings.NewReader(`{"name": "Drew"}`)) 136 | request.Header.Add("Content-Type", JSON) 137 | 138 | response := r.Do(request) 139 | 140 | assert.Equal(t, 200, response.StatusCode) 141 | assert.Equal(t, "Drew deleted", response.Body) 142 | }) 143 | } 144 | -------------------------------------------------------------------------------- /ws/connection.go: -------------------------------------------------------------------------------- 1 | package ws 2 | 3 | import ( 4 | "time" 5 | 6 | "golang.org/x/net/websocket" 7 | ) 8 | 9 | type Connection struct { 10 | RawConn *websocket.Conn 11 | ReceivedMessages []string 12 | Timeout time.Duration 13 | } 14 | 15 | func newConnection(conn *websocket.Conn) *Connection { 16 | connection := &Connection{ 17 | RawConn: conn, 18 | Timeout: 1 * time.Second, 19 | } 20 | return connection 21 | } 22 | 23 | func (connection *Connection) Close() { 24 | connection.RawConn.Close() 25 | } 26 | 27 | func (connection *Connection) FlushMessages(number int) *TimeoutError { 28 | for i := 0; i < number; i++ { 29 | _, err := connection.ReceiveMessage() 30 | if err != nil { 31 | return err 32 | } 33 | } 34 | return nil 35 | } 36 | 37 | func (connection *Connection) ReceiveMessage() (string, *TimeoutError) { 38 | messageChan := make(chan string) 39 | 40 | go connection.receiveMessage(messageChan) 41 | 42 | select { 43 | case <-time.After(connection.Timeout): 44 | return "", &TimeoutError{} 45 | case message := <-messageChan: 46 | connection.ReceivedMessages = append(connection.ReceivedMessages, message) 47 | 48 | if message != "" { 49 | return message, nil 50 | } 51 | } 52 | 53 | return "", nil 54 | } 55 | 56 | func (connection *Connection) SendMessage(message string) { 57 | websocket.Message.Send(connection.RawConn, message) 58 | } 59 | 60 | func (connection *Connection) receiveMessage(messageChan chan string) { 61 | for { 62 | var message string 63 | websocket.Message.Receive(connection.RawConn, &message) 64 | 65 | if message != "" { 66 | messageChan <- message 67 | return 68 | } else { 69 | time.Sleep(100 * time.Millisecond) 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /ws/errors.go: -------------------------------------------------------------------------------- 1 | package ws 2 | 3 | type TimeoutError struct { 4 | } 5 | 6 | func (e TimeoutError) Error() string { 7 | return "Timeout receiving from websocket" 8 | } 9 | -------------------------------------------------------------------------------- /ws/ws.go: -------------------------------------------------------------------------------- 1 | package ws 2 | 3 | import ( 4 | "github.com/drewolson/testflight" 5 | "golang.org/x/net/websocket" 6 | ) 7 | 8 | func Connect(r *testflight.Requester, route string) *Connection { 9 | connection, err := websocket.Dial(websocketRoute(r, route), "", "http://localhost/") 10 | if err != nil { 11 | panic(err) 12 | } 13 | 14 | return newConnection(connection) 15 | } 16 | 17 | func websocketRoute(r *testflight.Requester, route string) string { 18 | return "ws://" + r.Url(route) 19 | } 20 | -------------------------------------------------------------------------------- /ws/ws_test.go: -------------------------------------------------------------------------------- 1 | package ws 2 | 3 | import ( 4 | "net/http" 5 | "testing" 6 | "time" 7 | 8 | "github.com/bmizerany/assert" 9 | "github.com/drewolson/testflight" 10 | "golang.org/x/net/websocket" 11 | ) 12 | 13 | func pollingHandler() http.Handler { 14 | mux := http.NewServeMux() 15 | 16 | mux.Handle("/websocket", websocket.Handler(func(ws *websocket.Conn) { 17 | for { 18 | var name string 19 | err := websocket.Message.Receive(ws, &name) 20 | 21 | if err != nil { 22 | break 23 | } 24 | 25 | websocket.Message.Send(ws, "Hello, "+name) 26 | } 27 | })) 28 | 29 | return mux 30 | } 31 | 32 | func multiResponseHandler() http.Handler { 33 | mux := http.NewServeMux() 34 | 35 | mux.Handle("/websocket", websocket.Handler(func(ws *websocket.Conn) { 36 | for i := 0; i < 2; i++ { 37 | var name string 38 | websocket.Message.Receive(ws, &name) 39 | websocket.Message.Send(ws, "Hello, "+name) 40 | } 41 | })) 42 | 43 | return mux 44 | } 45 | 46 | func websocketHandler() http.Handler { 47 | mux := http.NewServeMux() 48 | 49 | mux.Handle("/websocket", websocket.Handler(func(ws *websocket.Conn) { 50 | var name string 51 | websocket.Message.Receive(ws, &name) 52 | websocket.Message.Send(ws, "Hello, "+name) 53 | })) 54 | 55 | return mux 56 | } 57 | 58 | func doNothingHandler() http.Handler { 59 | mux := http.NewServeMux() 60 | 61 | mux.Handle("/websocket", websocket.Handler(func(ws *websocket.Conn) { 62 | var name string 63 | websocket.Message.Receive(ws, &name) 64 | })) 65 | 66 | return mux 67 | } 68 | 69 | func TestWebSocket(t *testing.T) { 70 | testflight.WithServer(websocketHandler(), func(r *testflight.Requester) { 71 | connection := Connect(r, "/websocket") 72 | 73 | connection.SendMessage("Drew") 74 | message, _ := connection.ReceiveMessage() 75 | assert.Equal(t, "Hello, Drew", message) 76 | }) 77 | } 78 | 79 | func TestWebSocketReceiveMessageTimesOut(t *testing.T) { 80 | 81 | testflight.WithServer(doNothingHandler(), func(r *testflight.Requester) { 82 | connection := Connect(r, "/websocket") 83 | 84 | connection.SendMessage("Drew") 85 | _, err := connection.ReceiveMessage() 86 | assert.Equal(t, TimeoutError{}, *err) 87 | }) 88 | } 89 | 90 | func TestWebSocketTimeoutIsConfigurable(t *testing.T) { 91 | testflight.WithServer(websocketHandler(), func(r *testflight.Requester) { 92 | connection := Connect(r, "/websocket") 93 | connection.Timeout = 2 * time.Second 94 | 95 | go func() { 96 | time.Sleep(1 * time.Second) 97 | connection.SendMessage("Drew") 98 | }() 99 | 100 | message, _ := connection.ReceiveMessage() 101 | assert.Equal(t, "Hello, Drew", message) 102 | }) 103 | } 104 | 105 | func TestWebSocketRecordsReceivedMessages(t *testing.T) { 106 | testflight.WithServer(websocketHandler(), func(r *testflight.Requester) { 107 | connection := Connect(r, "/websocket") 108 | 109 | connection.SendMessage("Drew") 110 | connection.ReceiveMessage() 111 | assert.Equal(t, "Hello, Drew", connection.ReceivedMessages[0]) 112 | }) 113 | } 114 | 115 | func TestWebSocketFlushesMessages(t *testing.T) { 116 | testflight.WithServer(multiResponseHandler(), func(r *testflight.Requester) { 117 | connection := Connect(r, "/websocket") 118 | 119 | connection.SendMessage("Drew") 120 | connection.SendMessage("Bob") 121 | connection.FlushMessages(2) 122 | assert.Equal(t, 2, len(connection.ReceivedMessages)) 123 | }) 124 | } 125 | 126 | func TestClosingConnections(t *testing.T) { 127 | testflight.WithServer(pollingHandler(), func(r *testflight.Requester) { 128 | connection := Connect(r, "/websocket") 129 | 130 | connection.SendMessage("Drew") 131 | connection.SendMessage("Bob") 132 | connection.FlushMessages(2) 133 | connection.Close() 134 | assert.Equal(t, 2, len(connection.ReceivedMessages)) 135 | }) 136 | } 137 | 138 | func TestWebSocketTimesOutWhileFlushingMessages(t *testing.T) { 139 | testflight.WithServer(doNothingHandler(), func(r *testflight.Requester) { 140 | connection := Connect(r, "/websocket") 141 | connection.SendMessage("Drew") 142 | 143 | err := connection.FlushMessages(2) 144 | assert.Equal(t, TimeoutError{}, *err) 145 | }) 146 | } 147 | --------------------------------------------------------------------------------