Skip to content

Commit

Permalink
Add SSE test coverage
Browse files Browse the repository at this point in the history
Add a Stream type that handle the request to /events/:event and write tests for event stream

Add a test for the events/:event endpoint that actually tests the endpoint response

Using <-time.After in a 'select' creates one channel every time, let's use a time.Timer instead so that we reuse the same channel
  • Loading branch information
rafmagana authored and zankich committed Apr 7, 2015
1 parent bc8bb36 commit 1f09fb0
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 19 deletions.
11 changes: 4 additions & 7 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,15 +224,12 @@ func (a *API) robotDevice(res http.ResponseWriter, req *http.Request) {
}
}

// robotDeviceEvent returns device event route handler.
// Creates an event stream connection
// and queries event data to be written when received
func (a *API) robotDeviceEvent(res http.ResponseWriter, req *http.Request) {
f, _ := res.(http.Flusher)
c, _ := res.(http.CloseNotifier)

dataChan := make(chan string)
closer := c.CloseNotify()
msg := make(chan string)

res.Header().Set("Content-Type", "text/event-stream")
res.Header().Set("Cache-Control", "no-cache")
Expand All @@ -243,12 +240,12 @@ func (a *API) robotDeviceEvent(res http.ResponseWriter, req *http.Request) {
Event(req.URL.Query().Get(":event")); event != nil {
gobot.On(event, func(data interface{}) {
d, _ := json.Marshal(data)
msg <- string(d)
dataChan <- string(d)
})

for {
select {
case data := <-msg:
case data := <-dataChan:
fmt.Fprintf(res, "data: %v\n\n", data)
f.Flush()
case <-closer:
Expand All @@ -258,7 +255,7 @@ func (a *API) robotDeviceEvent(res http.ResponseWriter, req *http.Request) {
}
} else {
a.writeJSON(map[string]interface{}{
"error": errors.New("No Event found with the name " + req.URL.Query().Get(":event")),
"error": "No Event found with the name " + req.URL.Query().Get(":event"),
}, res)
}
}
Expand Down
51 changes: 51 additions & 0 deletions api/api_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package api

import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
"net/http/httptest"
"testing"
"time"

"github.com/hybridgroup/gobot"
)
Expand Down Expand Up @@ -363,6 +365,55 @@ func TestRobotConnection(t *testing.T) {
gobot.Assert(t, body["error"], "No Connection found with the name UnknownConnection1")
}

func TestRobotDeviceEvent(t *testing.T) {
a := initTestAPI()
server := httptest.NewServer(a)
defer server.Close()

eventsUrl := "/api/robots/Robot1/devices/Device1/events/"

// known event
respc := make(chan *http.Response, 1)
go func() {
resp, _ := http.Get(server.URL + eventsUrl + "TestEvent")
respc <- resp
}()

event := a.gobot.Robot("Robot1").
Device("Device1").(gobot.Eventer).
Event("TestEvent")

go func() {
time.Sleep(time.Millisecond * 5)
gobot.Publish(event, "event-data")
}()

done := false
timer := time.NewTimer(time.Millisecond * 10)

for !done {
select {
case resp := <-respc:
reader := bufio.NewReader(resp.Body)
data, _ := reader.ReadString('\n')
gobot.Assert(t, data, "data: \"event-data\"\n")
done = true
case <-timer.C:
t.Error("Not receiving data")
done = true
}
}

server.CloseClientConnections()

// unknown event
response, _ := http.Get(server.URL + eventsUrl + "UnknownEvent")

var body map[string]interface{}
json.NewDecoder(response.Body).Decode(&body)
gobot.Assert(t, body["error"], "No Event found with the name UnknownEvent")
}

func TestAPIRouter(t *testing.T) {
a := initTestAPI()

Expand Down
4 changes: 4 additions & 0 deletions api/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type testDriver struct {
pin string
connection gobot.Connection
gobot.Commander
gobot.Eventer
}

func (t *testDriver) Start() (errs []error) { return }
Expand All @@ -38,9 +39,12 @@ func newTestDriver(adaptor *testAdaptor, name string, pin string) *testDriver {
name: name,
connection: adaptor,
pin: pin,
Eventer: gobot.NewEventer(),
Commander: gobot.NewCommander(),
}

t.AddEvent("TestEvent")

t.AddCommand("TestDriverCommand", func(params map[string]interface{}) interface{} {
name := params["name"].(string)
return fmt.Sprintf("hello %v", name)
Expand Down
13 changes: 1 addition & 12 deletions helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ type testDriver struct {
name string
pin string
connection Connection
Eventer
Commander
}

Expand All @@ -36,24 +35,14 @@ func newTestDriver(adaptor *testAdaptor, name string, pin string) *testDriver {
name: name,
connection: adaptor,
pin: pin,
Eventer: NewEventer(),
Commander: NewCommander(),
}

t.AddEvent("DriverCommand")

t.AddCommand("DriverCommand", func(params map[string]interface{}) interface{} {
return t.DriverCommand()
})
t.AddCommand("DriverCommand", func(params map[string]interface{}) interface{} { return nil })

return t
}

func (t *testDriver) DriverCommand() string {
Publish(t.Event("DriverCommand"), "DriverCommand")
return "DriverCommand"
}

type testAdaptor struct {
name string
port string
Expand Down

0 comments on commit 1f09fb0

Please sign in to comment.