gobot.io/x/gobot/v2@v2.1.0/platforms/particle/adaptor_test.go (about) 1 package particle 2 3 import ( 4 "errors" 5 "net/http" 6 "net/http/httptest" 7 "net/url" 8 "strings" 9 "testing" 10 11 "github.com/donovanhide/eventsource" 12 "gobot.io/x/gobot/v2" 13 "gobot.io/x/gobot/v2/gobottest" 14 ) 15 16 // HELPERS 17 18 func createTestServer(handler func(w http.ResponseWriter, r *http.Request)) *httptest.Server { 19 return httptest.NewServer(http.HandlerFunc(handler)) 20 } 21 22 func getDummyResponseForPath(path string, dummy_response string, t *testing.T) *httptest.Server { 23 dummy_data := []byte(dummy_response) 24 25 return createTestServer(func(w http.ResponseWriter, r *http.Request) { 26 actualPath := "/v1/devices" + path 27 if r.URL.Path != actualPath { 28 t.Errorf("Path doesn't match, expected %#v, got %#v", actualPath, r.URL.Path) 29 } 30 w.Write(dummy_data) 31 }) 32 } 33 34 func getDummyResponseForPathWithParams(path string, params []string, dummy_response string, t *testing.T) *httptest.Server { 35 dummy_data := []byte(dummy_response) 36 37 return createTestServer(func(w http.ResponseWriter, r *http.Request) { 38 actualPath := "/v1/devices" + path 39 if r.URL.Path != actualPath { 40 t.Errorf("Path doesn't match, expected %#v, got %#v", actualPath, r.URL.Path) 41 } 42 43 r.ParseForm() 44 45 for key, value := range params { 46 if r.Form["params"][key] != value { 47 t.Error("Expected param to be " + r.Form["params"][key] + " but was " + value) 48 } 49 } 50 w.Write(dummy_data) 51 }) 52 } 53 54 func initTestAdaptor() *Adaptor { 55 return NewAdaptor("myDevice", "token") 56 } 57 58 func initTestAdaptorWithServo() *Adaptor { 59 a := NewAdaptor("myDevice", "token") 60 a.servoPins["1"] = true 61 return a 62 } 63 64 // TESTS 65 66 func TestAdaptor(t *testing.T) { 67 var a interface{} = initTestAdaptor() 68 _, ok := a.(gobot.Adaptor) 69 if !ok { 70 t.Errorf("Adaptor{} should be a gobot.Adaptor") 71 } 72 } 73 74 func TestNewAdaptor(t *testing.T) { 75 // does it return a pointer to an instance of Adaptor? 76 var a interface{} = initTestAdaptor() 77 core, ok := a.(*Adaptor) 78 if !ok { 79 t.Errorf("NewAdaptor() should have returned a *Adaptor") 80 } 81 82 gobottest.Assert(t, core.APIServer, "https://api.particle.io") 83 gobottest.Assert(t, strings.HasPrefix(core.Name(), "Particle"), true) 84 85 core.SetName("sparkie") 86 gobottest.Assert(t, core.Name(), "sparkie") 87 } 88 89 func TestAdaptorConnect(t *testing.T) { 90 a := initTestAdaptor() 91 gobottest.Assert(t, a.Connect(), nil) 92 } 93 94 func TestAdaptorFinalize(t *testing.T) { 95 a := initTestAdaptor() 96 a.Connect() 97 gobottest.Assert(t, a.Finalize(), nil) 98 } 99 100 func TestAdaptorAnalogRead(t *testing.T) { 101 // When no error 102 response := `{"return_value": 5.2}` 103 params := []string{"A1"} 104 105 a := initTestAdaptor() 106 testServer := getDummyResponseForPathWithParams("/"+a.DeviceID+"/analogread", params, response, t) 107 108 a.setAPIServer(testServer.URL) 109 defer testServer.Close() 110 111 val, _ := a.AnalogRead("A1") 112 gobottest.Assert(t, val, 5) 113 } 114 115 func TestAdaptorAnalogReadError(t *testing.T) { 116 a := initTestAdaptor() 117 // When error 118 testServer := createTestServer(func(w http.ResponseWriter, r *http.Request) { 119 http.NotFound(w, r) 120 }) 121 defer testServer.Close() 122 a.setAPIServer(testServer.URL) 123 124 val, _ := a.AnalogRead("A1") 125 gobottest.Assert(t, val, 0) 126 } 127 128 func TestAdaptorPwmWrite(t *testing.T) { 129 response := `{}` 130 params := []string{"A1,1"} 131 132 a := initTestAdaptor() 133 testServer := getDummyResponseForPathWithParams("/"+a.DeviceID+"/analogwrite", params, response, t) 134 defer testServer.Close() 135 136 a.setAPIServer(testServer.URL) 137 a.PwmWrite("A1", 1) 138 } 139 140 func TestAdaptorAnalogWrite(t *testing.T) { 141 response := `{}` 142 params := []string{"A1,1"} 143 144 a := initTestAdaptor() 145 testServer := getDummyResponseForPathWithParams("/"+a.DeviceID+"/analogwrite", params, response, t) 146 defer testServer.Close() 147 148 a.setAPIServer(testServer.URL) 149 a.AnalogWrite("A1", 1) 150 } 151 152 func TestAdaptorDigitalWrite(t *testing.T) { 153 // When HIGH 154 response := `{}` 155 params := []string{"D7,HIGH"} 156 157 a := initTestAdaptor() 158 testServer := getDummyResponseForPathWithParams("/"+a.DeviceID+"/digitalwrite", params, response, t) 159 160 a.setAPIServer(testServer.URL) 161 a.DigitalWrite("D7", 1) 162 163 testServer.Close() 164 // When LOW 165 params = []string{"D7,LOW"} 166 167 testServer = getDummyResponseForPathWithParams("/"+a.DeviceID+"/digitalwrite", params, response, t) 168 defer testServer.Close() 169 170 a.setAPIServer(testServer.URL) 171 a.DigitalWrite("D7", 0) 172 } 173 174 func TestAdaptorServoOpen(t *testing.T) { 175 response := `{}` 176 params := []string{"1"} 177 178 a := initTestAdaptor() 179 testServer := getDummyResponseForPathWithParams("/"+a.DeviceID+"/servoOpen", params, response, t) 180 defer testServer.Close() 181 182 a.setAPIServer(testServer.URL) 183 a.servoPinOpen("1") 184 } 185 186 func TestAdaptorServoWrite(t *testing.T) { 187 response := `{}` 188 params := []string{"1,128"} 189 190 a := initTestAdaptorWithServo() 191 testServer := getDummyResponseForPathWithParams("/"+a.DeviceID+"/servoSet", params, response, t) 192 defer testServer.Close() 193 194 a.setAPIServer(testServer.URL) 195 a.ServoWrite("1", 128) 196 } 197 198 func TestAdaptorDigitalRead(t *testing.T) { 199 // When HIGH 200 response := `{"return_value": 1}` 201 params := []string{"D7"} 202 203 a := initTestAdaptor() 204 testServer := getDummyResponseForPathWithParams("/"+a.DeviceID+"/digitalread", params, response, t) 205 206 a.setAPIServer(testServer.URL) 207 208 val, _ := a.DigitalRead("D7") 209 gobottest.Assert(t, val, 1) 210 testServer.Close() 211 212 // When LOW 213 response = `{"return_value": 0}` 214 215 testServer = getDummyResponseForPathWithParams("/"+a.DeviceID+"/digitalread", params, response, t) 216 217 a.setAPIServer(testServer.URL) 218 defer testServer.Close() 219 220 val, _ = a.DigitalRead("D7") 221 gobottest.Assert(t, val, 0) 222 } 223 224 func TestAdaptorDigitalReadError(t *testing.T) { 225 a := initTestAdaptor() 226 // When error 227 testServer := createTestServer(func(w http.ResponseWriter, r *http.Request) { 228 http.NotFound(w, r) 229 }) 230 defer testServer.Close() 231 232 a.setAPIServer(testServer.URL) 233 234 val, _ := a.DigitalRead("D7") 235 gobottest.Assert(t, val, -1) 236 } 237 238 func TestAdaptorFunction(t *testing.T) { 239 response := `{"return_value": 1}` 240 241 a := initTestAdaptor() 242 testServer := getDummyResponseForPath("/"+a.DeviceID+"/hello", response, t) 243 244 a.setAPIServer(testServer.URL) 245 246 val, _ := a.Function("hello", "100,200") 247 gobottest.Assert(t, val, 1) 248 testServer.Close() 249 250 // When not existent 251 response = `{"ok": false, "error": "timeout"}` 252 testServer = getDummyResponseForPath("/"+a.DeviceID+"/hello", response, t) 253 254 a.setAPIServer(testServer.URL) 255 256 _, err := a.Function("hello", "") 257 gobottest.Assert(t, err.Error(), "timeout") 258 259 testServer.Close() 260 } 261 262 func TestAdaptorVariable(t *testing.T) { 263 // When String 264 response := `{"result": "1"}` 265 266 a := initTestAdaptor() 267 testServer := getDummyResponseForPath("/"+a.DeviceID+"/variable_name", response, t) 268 269 a.setAPIServer(testServer.URL) 270 271 val, _ := a.Variable("variable_name") 272 gobottest.Assert(t, val, "1") 273 testServer.Close() 274 275 // When float 276 response = `{"result": 1.1}` 277 testServer = getDummyResponseForPath("/"+a.DeviceID+"/variable_name", response, t) 278 279 a.setAPIServer(testServer.URL) 280 281 val, _ = a.Variable("variable_name") 282 gobottest.Assert(t, val, "1.1") 283 testServer.Close() 284 285 // When int 286 response = `{"result": 1}` 287 testServer = getDummyResponseForPath("/"+a.DeviceID+"/variable_name", response, t) 288 289 a.setAPIServer(testServer.URL) 290 291 val, _ = a.Variable("variable_name") 292 gobottest.Assert(t, val, "1") 293 testServer.Close() 294 295 // When bool 296 response = `{"result": true}` 297 testServer = getDummyResponseForPath("/"+a.DeviceID+"/variable_name", response, t) 298 299 a.setAPIServer(testServer.URL) 300 301 val, _ = a.Variable("variable_name") 302 gobottest.Assert(t, val, "true") 303 testServer.Close() 304 305 // When not existent 306 response = `{"ok": false, "error": "Variable not found"}` 307 testServer = getDummyResponseForPath("/"+a.DeviceID+"/not_existent", response, t) 308 309 a.setAPIServer(testServer.URL) 310 311 _, err := a.Variable("not_existent") 312 gobottest.Assert(t, err.Error(), "Variable not found") 313 314 testServer.Close() 315 } 316 317 func TestAdaptorSetAPIServer(t *testing.T) { 318 a := initTestAdaptor() 319 apiServer := "new_api_server" 320 gobottest.Refute(t, a.APIServer, apiServer) 321 322 a.setAPIServer(apiServer) 323 gobottest.Assert(t, a.APIServer, apiServer) 324 } 325 326 func TestAdaptorDeviceURL(t *testing.T) { 327 // When APIServer is set 328 a := initTestAdaptor() 329 a.setAPIServer("http://server") 330 a.DeviceID = "devID" 331 gobottest.Assert(t, a.deviceURL(), "http://server/v1/devices/devID") 332 333 // When APIServer is not set 334 a = &Adaptor{name: "particleie", DeviceID: "myDevice", AccessToken: "token"} 335 gobottest.Assert(t, a.deviceURL(), "https://api.particle.io/v1/devices/myDevice") 336 } 337 338 func TestAdaptorPinLevel(t *testing.T) { 339 a := initTestAdaptor() 340 341 gobottest.Assert(t, a.pinLevel(1), "HIGH") 342 gobottest.Assert(t, a.pinLevel(0), "LOW") 343 gobottest.Assert(t, a.pinLevel(5), "LOW") 344 } 345 346 func TestAdaptorPostToparticle(t *testing.T) { 347 a := initTestAdaptor() 348 349 // When error on request 350 vals := url.Values{} 351 vals.Add("error", "error") 352 resp, err := a.request("POST", "http://invalid%20host.com", vals) 353 if err == nil { 354 t.Error("request() should return an error when request was unsuccessful but returned", resp) 355 } 356 357 // When error reading body 358 // Pending 359 360 // When response.Status is not 200 361 testServer := createTestServer(func(w http.ResponseWriter, r *http.Request) { 362 http.NotFound(w, r) 363 }) 364 defer testServer.Close() 365 366 resp, err = a.request("POST", testServer.URL+"/existent", vals) 367 if err == nil { 368 t.Error("request() should return an error when status is not 200 but returned", resp) 369 } 370 } 371 372 type testEventSource struct { 373 event string 374 data string 375 } 376 377 func (testEventSource) Id() string { return "" } 378 func (t testEventSource) Event() string { return t.event } 379 func (t testEventSource) Data() string { return t.data } 380 381 func TestAdaptorEventStream(t *testing.T) { 382 a := initTestAdaptor() 383 var url string 384 eventSource = func(u string) (chan eventsource.Event, chan error, error) { 385 url = u 386 return nil, nil, nil 387 } 388 a.EventStream("all", "ping") 389 gobottest.Assert(t, url, "https://api.particle.io/v1/events/ping?access_token=token") 390 391 a.EventStream("devices", "ping") 392 gobottest.Assert(t, url, "https://api.particle.io/v1/devices/events/ping?access_token=token") 393 394 a.EventStream("device", "ping") 395 gobottest.Assert(t, url, "https://api.particle.io/v1/devices/myDevice/events/ping?access_token=token") 396 397 _, err := a.EventStream("nothing", "ping") 398 gobottest.Assert(t, err.Error(), "source param should be: all, devices or device") 399 400 eventSource = func(u string) (chan eventsource.Event, chan error, error) { 401 return nil, nil, errors.New("error connecting sse") 402 } 403 404 _, err = a.EventStream("devices", "") 405 gobottest.Assert(t, err.Error(), "error connecting sse") 406 407 eventChan := make(chan eventsource.Event) 408 errorChan := make(chan error) 409 410 eventSource = func(u string) (chan eventsource.Event, chan error, error) { 411 return eventChan, errorChan, nil 412 } 413 414 _, err = a.EventStream("devices", "") 415 gobottest.Assert(t, err, nil) 416 }