github.com/amimof/huego@v1.2.1/huego_test.go (about) 1 package huego 2 3 import ( 4 "fmt" 5 "os" 6 "path" 7 "testing" 8 9 "github.com/jarcoal/httpmock" 10 "github.com/stretchr/testify/assert" 11 ) 12 13 // I'm too lazy to have this elsewhere 14 // export HUE_USERNAME=9D6iHMbM-Bt7Kd0Cwh9Quo4tE02FMnmrNrnFAdAq 15 // export HUE_HOSTNAME=192.168.1.59 16 17 var username string 18 var hostname string 19 var badHostname = "bad-hue-config" 20 21 func init() { 22 23 hostname = os.Getenv("HUE_HOSTNAME") 24 username = os.Getenv("HUE_USERNAME") 25 26 tests := []struct { 27 method string 28 path string 29 data string 30 url string 31 }{ 32 // DISCOVERY 33 { 34 method: "GET", 35 url: "https://discovery.meethue.com", 36 data: `[{"id":"001788fffe73ff19","internalipaddress":"192.168.13.112"}]`, 37 }, 38 39 // CONFIG 40 { 41 method: "GET", 42 path: "/config", 43 data: `{"name":"Philipshue","zigbeechannel":15,"mac":"00:17:88:00:00:00","dhcp":true,"ipaddress":"192.168.1.7","netmask":"255.255.255.0","gateway":"192.168.1.1","proxyaddress":"none","proxyport":0,"UTC":"2014-07-17T09:27:35","localtime":"2014-07-17T11:27:35","timezone":"Europe/Madrid","whitelist":{"ffffffffe0341b1b376a2389376a2389":{"lastusedate":"2014-07-17T07:21:38","createdate":"2014-04-08T08:55:10","name":"PhilipsHueAndroidApp#TCTALCATELONETOU"},"pAtwdCV8NZId25Gk":{"lastusedate":"2014-05-07T18:28:29","createdate":"2014-04-09T17:29:16","name":"MyApplication"},"gDN3IaPYSYNPWa2H":{"lastusedate":"2014-05-07T09:15:21","createdate":"2014-05-07T09:14:38","name":"iPhoneWeb1"}},"swversion":"01012917","apiversion":"1.3.0","swupdate":{"updatestate":2,"checkforupdate":false,"devicetypes":{"bridge":true,"lights":["1","2","3"], "sensors":["4","5","6"]},"url":"","text":"010000000","notify":false},"linkbutton":false,"portalservices":false,"portalconnection":"connected","portalstate":{"signedon":true,"incoming":false,"outgoing":true,"communication":"disconnected"}}`, 44 }, 45 { 46 method: "PUT", 47 path: "/config", 48 data: `[{"success":{"/config/name":"My bridge"}}]`, 49 }, 50 { 51 method: "GET", 52 path: path.Join("/invalid_password", "/lights"), 53 data: `[{"error":{"type":1,"address":"/lights","description":"unauthorized user"}}]`, 54 }, 55 { 56 method: "GET", 57 path: "", 58 data: `{"lights":{"1":{"state":{"on":false,"bri":0,"hue":0,"sat":0,"xy":[0.0000,0.0000],"ct":0,"alert":"none","effect":"none","colormode":"hs","reachable":true},"type":"Extendedcolorlight","name":"HueLamp1","modelid":"LCT001","swversion":"65003148"},"2":{"state":{"on":true,"bri":254,"hue":33536,"sat":144,"xy":[0.3460,0.3568],"ct":201,"alert":"none","effect":"none","colormode":"hs","reachable":true},"type":"Extendedcolorlight","name":"HueLamp2","modelid":"LCT001","swversion":"65003148"}},"groups":{"1":{"action":{"on":true,"bri":254,"hue":33536,"sat":144,"xy":[0.3460,0.3568],"ct":201,"effect":"none","colormode":"xy"},"lights":["1","2"],"name":"Group1"}},"config":{"name":"Philipshue","mac":"00:00:88:00:bb:ee","dhcp":true,"ipaddress":"192.168.1.74","netmask":"255.255.255.0","gateway":"192.168.1.254","proxyaddress":"","proxyport":0,"UTC":"2012-10-29T12:00:00","whitelist":{"1028d66426293e821ecfd9ef1a0731df":{"lastusedate":"2012-10-29T12:00:00","createdate":"2012-10-29T12:00:00","name":"testuser"}},"swversion":"01003372","swupdate":{"updatestate":2,"checkforupdate":false,"devicetypes":{"bridge":true,"lights":["1","2","3"], "sensors":["4","5","6"]},"url":"","text":"010000000","notify":false},"swupdate2":{"checkforupdate":false,"lastchange":"2017-06-21T19:44:36","bridge":{"state":"noupdates","lastinstall":"2017-06-21T19:44:18"},"state":"noupdates","autoinstall":{"updatetime":"T14:00:00","on":false}},"schedules":{"1":{"name":"schedule","description":"","command":{"address":"/api/<username>/groups/0/action","body":{"on":true},"method":"PUT"},"time":"2012-10-29T12:00:00"}}}}`, 59 }, 60 { 61 method: "POST", 62 path: "", 63 data: `[{"success":{"username": "83b7780291a6ceffbe0bd049104df", "clientkey": "33DDF493992908E3D97AAAA5A6F189E1"}}]`, 64 }, 65 { 66 method: "DELETE", 67 path: "/config/whitelist/ffffffffe0341b1b376a2389376a2389", 68 data: `[{"success": "/config/whitelist/ffffffffe0341b1b376a2389376a2389 deleted."}]`, 69 }, 70 71 // LIGHT 72 { 73 method: "GET", 74 path: path.Join(username, "/lights"), 75 data: `{"1":{"state":{"on":false,"bri":1,"hue":33761,"sat":254,"effect":"none","xy":[0.3171,0.3366],"ct":159,"alert":"none","colormode":"xy","mode":"homeautomation","reachable":true},"swupdate":{"state":"noupdates","lastinstall":"2017-10-15T12:07:34"},"type":"Extendedcolorlight","name":"Huecolorlamp7","modelid":"LCT001","manufacturername":"Philips","productname":"Huecolorlamp","capabilities":{"certified":true,"control":{"mindimlevel":5000,"maxlumen":600,"colorgamuttype":"B","colorgamut":[[0.675,0.322],[0.409,0.518],[0.167,0.04]],"ct":{"min":153,"max":500}},"streaming":{"renderer":true,"proxy":false}},"config":{"archetype":"sultanbulb","function":"mixed","direction":"omnidirectional"},"uniqueid":"00:17:88:01:00:bd:c7:b9-0b","swversion":"5.105.0.21169"},"2":{"state":{"on":false,"bri":1,"hue":35610,"sat":237,"effect":"none","xy":[0.1768,0.395],"ct":153,"alert":"none","colormode":"xy","mode":"homeautomation","reachable":true},"swupdate":{"state":"noupdates","lastinstall":"2017-10-18T12:50:40"},"type":"Extendedcolorlight","name":"Huelightstripplus1","modelid":"LST002","manufacturername":"Philips","productname":"Huelightstripplus","capabilities":{"certified":true,"control":{"mindimlevel":40,"maxlumen":1600,"colorgamuttype":"C","colorgamut":[[0.6915,0.3083],[0.17,0.7],[0.1532,0.0475]],"ct":{"min":153,"max":500}},"streaming":{"renderer":true,"proxy":true}},"config":{"archetype":"huelightstrip","function":"mixed","direction":"omnidirectional"},"uniqueid":"00:17:88:01:02:15:97:46-0b","swversion":"5.105.0.21169"}}`, 76 }, 77 { 78 method: "GET", 79 path: path.Join(username, "/lights/1"), 80 data: `{"state":{"on":false,"bri":1,"hue":12594,"sat":251,"effect":"none","xy":[0.5474,0.4368],"alert":"none","colormode":"xy","mode":"homeautomation","reachable":true},"swupdate":{"state":"noupdates","lastinstall":"2017-12-13T01:59:13"},"type":"Colorlight","name":"Huebloom1","modelid":"LLC011","manufacturername":"Philips","productname":"Huebloom","capabilities":{"certified":true,"control":{"mindimlevel":10000,"maxlumen":120,"colorgamuttype":"A","colorgamut":[[0.704,0.296],[0.2151,0.7106],[0.138,0.08]]},"streaming":{"renderer":true,"proxy":false}},"config":{"archetype":"huebloom","function":"decorative","direction":"upwards"},"uniqueid":"00:17:88:01:00:c5:3b:e3-0b","swversion":"5.105.1.21778"}`, 81 }, 82 { 83 method: "GET", 84 path: path.Join(username, "/lights/new"), 85 data: `{"7":{"name":"HueLamp7"},"8":{"name":"HueLamp8"},"lastscan":"2012-10-29T12:00:00"}`, 86 }, 87 { 88 method: "POST", 89 path: path.Join(username, "/lights"), 90 data: `[{"success":{"/lights":"Searching for new devices"}}]`, 91 }, 92 { 93 method: "PUT", 94 path: path.Join(username, "/lights/1/state"), 95 data: `[{"success":{"/lights/1/state/bri":200}},{"success":{"/lights/1/state/on":true}},{"success":{"/lights/1/state/hue":50000}}]`, 96 }, 97 { 98 // Second route for identifying light testing 99 method: "PUT", 100 path: path.Join(username, "/lights/2/state"), 101 data: `[{"success":{"/lights/2/state/alert":"select"}}]`, 102 }, 103 { 104 method: "PUT", 105 path: path.Join(username, "/lights/1"), 106 data: `[{"success":{"/lights/1/name":"Bedroom Light"}}]`, 107 }, 108 { 109 method: "DELETE", 110 path: path.Join(username, "/lights/1"), 111 data: `[{"success":"/lights/<id> deleted"}]`, 112 }, 113 114 // GROUP 115 { 116 method: "GET", 117 path: "/groups", 118 data: `{"1":{"name":"Group 1","lights":["1","2"],"type":"LightGroup","state":{"all_on":true,"any_on":true},"action":{"on":true,"bri":254,"hue":10000,"sat":254,"effect":"none","xy":[0.5,0.5],"ct":250,"alert":"select","colormode":"ct"}},"2":{"name":"Group 2","lights":["3","4","5"],"type":"LightGroup","state":{"all_on":true,"any_on":true},"action":{"on":true,"bri":153,"hue":4345,"sat":254,"effect":"none","xy":[0.5,0.5],"ct":250,"alert":"select","colormode":"ct"}},"3":{"name":"Group 3","lights":["1","2","3","4","5"],"sensors":[],"type":"Entertainment","state":{"all_on":true,"any_on":true},"recycle":false,"class":"TV","stream":{"proxymode":"auto","proxynode":"/lights/3","active":false,"owner":null},"locations":{"1":[0.93,-0.92,0.00],"2":[0.13,-0.85,1.00],"3":[-0.03,-0.86,1.00],"4":[-0.40,1.00,0.00],"5":[0.43,1.00,0.00]},"action":{"on":true,"bri":62,"hue":43749,"sat":189,"effect":"none","xy":[0.2133,0.2075],"ct":153,"alert":"select","colormode":"xy"}}}`, 119 }, 120 { 121 method: "GET", 122 path: "/groups/1", 123 data: `{"action":{"on":true,"hue":0,"effect":"none","bri":100,"sat":100,"ct":500,"xy":[0.5,0.5]},"lights":["1","2"],"state":{"any_on":true,"all_on":true},"type":"Room","class":"Bedroom","name":"Masterbedroom"}`, 124 }, 125 { 126 method: "PUT", 127 path: "/groups/1", 128 data: `[{"success":{"/groups/1/lights":["1"]}},{"success":{"/groups/1/name":"Bedroom"}}]`, 129 }, 130 { 131 method: "PUT", 132 path: "/groups/1/action", 133 data: `[{"success":{"address":"/groups/1/action/on","value":true}},{"success":{"address":"/groups/1/action/effect","value":"colorloop"}},{"success":{"address":"/groups/1/action/hue","value":6000}}]`, 134 }, 135 { 136 method: "POST", 137 path: "/groups", 138 data: `[{"success":{"id":"1"}}]`, 139 }, 140 { 141 method: "DELETE", 142 path: "/groups/1", 143 data: `[{"success":"/groups/1 deleted."}]`, 144 }, 145 146 // NON-ENTERTAINMENT GROUP 147 { 148 method: "GET", 149 path: "/groups/2", 150 data: `{"name":"Office","lights":["4","5","1","2","3"],"sensors":[],"type":"Room","state":{"all_on":true,"any_on":true},"recycle":false,"class":"Office","action":{"on":true,"bri":92,"hue":53702,"sat":82,"effect":"none","xy":[ 0.3693, 0.3006],"ct":233,"alert":"select","colormode":"xy"}}`, 151 }, 152 { 153 method: "PUT", 154 path: "/groups/2", 155 data: `[{"error":{"type":6,"address":"/groups/2/stream","description":"parameter, /groups/2/stream, not available"}}]`, 156 }, 157 158 // INACTIVE ENTERTAINMENT GROUP 159 { 160 method: "GET", 161 path: "/groups/3", 162 data: `{"name":"Group 3","lights":["1","2","3","4","5"],"sensors":[],"type":"Entertainment","state":{"all_on":true,"any_on":true},"recycle":false,"class":"TV","stream":{"proxymode":"auto","proxynode":"/lights/3","active":false,"owner":null},"locations":{"1":[0.93,-0.92,0.00],"2":[0.13,-0.85,1.00],"3":[-0.03,-0.86,1.00],"4":[-0.40,1.00,0.00],"5":[0.43,1.00,0.00]},"action":{"on":true,"bri":62,"hue":43749,"sat":189,"effect":"none","xy":[0.2133,0.2075],"ct":153,"alert":"select","colormode":"xy"}}`, 163 }, 164 { 165 method: "PUT", 166 path: "/groups/3", 167 data: `[{"success":{"/groups/3/stream/active":true}}]`, 168 }, 169 170 // ACTIVE ENTERTAINMENT GROUP 171 { 172 method: "GET", 173 path: "/groups/4", 174 data: `{"name":"Group 4","lights":["1","2","3","4","5"],"sensors":[],"type":"Entertainment","state":{"all_on":true,"any_on":true},"recycle":false,"class":"TV","stream":{"proxymode":"auto","proxynode":"/lights/3","active":true,"owner":"QZTPWY1ADZDM8IG188LBVOB5YV5O5OPZNCKTQPQB"},"locations":{"1":[0.93,-0.92,0.00],"2":[0.13,-0.85,1.00],"3":[-0.03,-0.86,1.00],"4":[-0.40,1.00,0.00],"5":[0.43,1.00,0.00]},"action":{"on":true,"bri":62,"hue":43749,"sat":189,"effect":"none","xy":[0.2133,0.2075],"ct":153,"alert":"select","colormode":"xy"}}`, 175 }, 176 { 177 method: "PUT", 178 path: "/groups/4", 179 data: `[{"success":{"/groups/3/stream/active":false}}]`, 180 }, 181 182 // ACTIVE ENTERTAINMENT GROUP FOR ENABLE ERROR 183 { 184 method: "GET", 185 path: "/groups/5", 186 data: `{"name":"Group 5","lights":["1","2","3","4","5"],"sensors":[],"type":"Entertainment","state":{"all_on":true,"any_on":true},"recycle":false,"class":"TV","stream":{"proxymode":"auto","proxynode":"/lights/3","active":true,"owner":"QZTPWY1ADZDM8IG188LBVOB5YV5O5OPZNCKTQPQB"},"locations":{"1":[0.93,-0.92,0.00],"2":[0.13,-0.85,1.00],"3":[-0.03,-0.86,1.00],"4":[-0.40,1.00,0.00],"5":[0.43,1.00,0.00]},"action":{"on":true,"bri":62,"hue":43749,"sat":189,"effect":"none","xy":[0.2133,0.2075],"ct":153,"alert":"select","colormode":"xy"}}`, 187 }, 188 { 189 method: "PUT", 190 path: "/groups/5", 191 data: `[{"error":{"type":307,"address":"/groups/5/stream/active","description":"Cannot claim stream ownership"}}]`, 192 }, 193 194 // ACTIVE ENTERTAINMENT GROUP FOR DISABLE ERROR 195 { 196 method: "GET", 197 path: "/groups/6", 198 data: `{"name":"Group 6","lights":["1","2","3","4","5"],"sensors":[],"type":"Entertainment","state":{"all_on":true,"any_on":true},"recycle":false,"class":"TV","stream":{"proxymode":"auto","proxynode":"/lights/3","active":true,"owner":"QZTPWY1ADZDM8IG188LBVOB5YV5O5OPZNCKTQPQB"},"locations":{"1":[0.93,-0.92,0.00],"2":[0.13,-0.85,1.00],"3":[-0.03,-0.86,1.00],"4":[-0.40,1.00,0.00],"5":[0.43,1.00,0.00]},"action":{"on":true,"bri":62,"hue":43749,"sat":189,"effect":"none","xy":[0.2133,0.2075],"ct":153,"alert":"select","colormode":"xy"}}`, 199 }, 200 { 201 method: "PUT", 202 path: "/groups/6", 203 data: `[{"error":{"type":999,"address":"/groups/6/stream/active","description":"unspecified error"}}]`, 204 }, 205 206 // SCENE 207 { 208 method: "GET", 209 path: "/scenes", 210 data: `{"4e1c6b20e-on-0":{"name":"Kathyon1449133269486","lights":["2","3"],"owner":"ffffffffe0341b1b376a2389376a2389","recycle":true,"locked":false,"appdata":{},"picture":"","lastupdated":"2015-12-03T08:57:13","version":1},"3T2SvsxvwteNNys":{"name":"Cozydinner","type":"GroupScene","group":"1","lights":["1","2"],"owner":"ffffffffe0341b1b376a2389376a2389","recycle":true,"locked":false,"appdata":{"version":1,"data":"myAppData"},"picture":"","lastupdated":"2015-12-03T10:09:22","version":2}}`, 211 }, 212 { 213 method: "GET", 214 path: "/scenes/4e1c6b20e-on-0", 215 data: `{"name":"Cozy dinner","type":"GroupScene","group":"1","lights":["1"],"owner":"newdeveloper","recycle":true,"locked":false,"appdata":{},"picture":"","lastupdated":"2015-12-03T10:09:22","version":2,"lightstates":{"1":{"on":true,"bri":237,"xy":[0.5806,0.3903]}}}`, 216 }, 217 { 218 method: "POST", 219 path: "/scenes", 220 data: `[{"success":{"address":"/scenes/ab341ef24/name","value":"Romanticdinner"}},{"success":{"address":"/scenes/ab3C41ef24/lights","value":["1","2"]}}]`, 221 }, 222 { 223 method: "PUT", 224 path: "/scenes/4e1c6b20e-on-0", 225 data: `[{"success":{"/scenes/74bc26d5f-on-0/name":"Cozydinner"}},{"success":{"/scenes/74bc26d5f-on-0/storelightstate":true}},{"success":{"/scenes/74bc26d5f-on-0/lights":["2","3"]}}]`, 226 }, 227 { 228 method: "PUT", 229 path: "/scenes/4e1c6b20e-on-0/lightstates/1", 230 data: `[{"success":{"address":"/scenes/ab341ef24/lights/1/state/on","value":true}},{"success":{"address":"/scenes/ab341ef24/lights/1/state/ct","value":200}}]`, 231 }, 232 { 233 method: "DELETE", 234 path: "/scenes/4e1c6b20e-on-0", 235 data: `[{"success":"/scenes/3T2SvsxvwteNNys deleted"}]`, 236 }, 237 238 // RULE 239 { 240 method: "GET", 241 path: "/rules", 242 data: `{ "1": { "name": "Wall Switch Rule", "lasttriggered": "2013-10-17T01:23:20", "creationtime": "2013-10-10T21:11:45", "timestriggered": 27, "owner": "78H56B12BA", "status": "enabled", "conditions": [ { "address": "/sensors/2/state/buttonevent", "operator": "eq", "value": "16" }, { "address": "/sensors/2/state/lastupdated", "operator": "dx" } ], "actions": [ { "address": "/groups/0/action", "method": "PUT", "body": { "scene": "S3" } } ] }, "2": { "name": "Wall Switch Rule 2" }} `, 243 }, 244 { 245 method: "GET", 246 path: "/rules/1", 247 data: `{ "name": "Wall Switch Rule", "owner": "ruleOwner", "created": "2014-07-23T15:02:56", "lasttriggered": "none", "timestriggered": 0, "status": "enabled", "conditions": [ { "address": "/sensors/2/state/buttonevent", "operator": "eq", "value": "16" }, { "address": "/sensors/2/state/lastupdated", "operator": "dx" } ], "actions": [ { "address": "/groups/0/action", "method": "PUT", "body": { "scene": "S3" } } ] }`, 248 }, 249 { 250 method: "POST", 251 path: "/rules", 252 data: `[{"success":{"id": "3"}}]`, 253 }, 254 { 255 method: "PUT", 256 path: "/rules/1", 257 data: `[ { "success": { "/rules/1/actions": [ { "address": "/groups/0/action", "method": "PUT", "body": { "scene": "S3" } } ] } } ]`, 258 }, 259 { 260 method: "DELETE", 261 path: "/rules/1", 262 data: `[{"success": "/rules/1 deleted."}]`, 263 }, 264 265 // SCHEDULE 266 { 267 method: "GET", 268 path: "/schedules", 269 data: `{ "1": { "name": "Timer", "description": "", "command": { "address": "/api/s95jtYH8HUVWNkCO/groups/0/action", "body": { "scene": "02b12e930-off-0" }, "method": "PUT" }, "time": "PT00:01:00", "created": "2014-06-23T13:39:16", "status": "disabled", "autodelete": false, "starttime": "2014-06-23T13:39:16" }, "2": { "name": "Alarm", "description": "", "command": { "address": "/api/s95jtYH8HUVWNkCO/groups/0/action", "body": { "scene": "02b12e930-off-0" }, "method": "PUT" }, "localtime": "2014-06-23T19:52:00", "time": "2014-06-23T13:52:00", "created": "2014-06-23T13:38:57", "status": "disabled", "autodelete": false } }`, 270 }, 271 { 272 method: "GET", 273 path: "/schedules/1", 274 data: `{ "name": "Wake up", "description": "My wake up alarm", "command": { "address": "/api/<username>/groups/1/action", "method": "PUT", "body": { "on": true } }, "time": "W124/T06:00:00" }`, 275 }, 276 { 277 method: "POST", 278 path: "/schedules", 279 data: `[{"success":{"id": "2"}}]`, 280 }, 281 { 282 method: "PUT", 283 path: "/schedules/1", 284 data: `[{ "success": {"/schedules/1/name": "Wake up"}}]`, 285 }, 286 { 287 method: "DELETE", 288 path: "/schedules/1", 289 data: `[{"success": "/schedules/1 deleted."}]`, 290 }, 291 292 // SENSOR 293 { 294 method: "GET", 295 path: "/sensors", 296 data: `{ "1": { "state": { "daylight": false, "lastupdated": "2014-06-27T07:38:51" }, "config": { "on": true, "long": "none", "lat": "none", "sunriseoffset": 50, "sunsetoffset": 50 }, "name": "Daylight", "type": "Daylight", "modelid": "PHDL00", "manufacturername": "Philips", "swversion": "1.0" }, "2": { "state": { "buttonevent": 0, "lastupdated": "none" }, "config": { "on": true }, "name": "Tap Switch 2", "type": "ZGPSwitch", "modelid": "ZGPSWITCH", "manufacturername": "Philips", "uniqueid": "00:00:00:00:00:40:03:50-f2" } }`, 297 }, 298 { 299 method: "GET", 300 path: "/sensors/1", 301 data: `{ "state":{ "buttonevent": 34, "lastupdated":"2013-03-25T13:32:34" }, "name": "Wall tap 1", "modelid":"ZGPSWITCH", "uniqueid":"01:23:45:67:89:AB-12", "manufacturername": "Philips", "swversion":"1.0", "type": "ZGPSwitch" }`, 302 }, 303 { 304 method: "POST", 305 path: "/sensors", 306 data: `[ { "success": { "/sensors": "Searching for new devices"}}]`, 307 }, 308 { 309 method: "POST", 310 path: "/sensors", 311 data: `[{"success":{"id": "4"}}]`, 312 }, 313 { 314 method: "GET", 315 path: "/sensors/new", 316 data: `{ "7": {"name": "Hue Tap 1"}, "8": {"name": "Button 3"}, "lastscan":"2013-05-22T10:24:00" }`, 317 }, 318 { 319 method: "PUT", 320 path: "/sensors/1", 321 data: `[{"success":{"/sensors/2/name":"Bedroom Tap"}}]`, 322 }, 323 { 324 method: "DELETE", 325 path: "/sensors/1", 326 data: `[{"success": "/sensors/1 deleted."}]`, 327 }, 328 { 329 method: "PUT", 330 path: "/sensors/1/config", 331 data: `[{"success":{"/sensors/2/config/on":true}}]`, 332 }, 333 { 334 method: "PUT", 335 path: "/sensors/1/state", 336 data: `[{"success":{"/sensors/1/state/presence": false}}]`, 337 }, 338 339 // CAPABILITIES 340 { 341 method: "GET", 342 path: "/capabilities", 343 data: `{ "lights":{ "available": 10 }, "sensors":{ "available": 60, "clip": { "available": 60 }, "zll": { "available": 60 }, "zgp": { "available": 60 } }, "groups": {}, "scenes": { "available": 100, "lightstates": { "available": 1500 } }, "rules": {}, "schedules": {}, "resourcelinks": {}, "whitelists": {}, "timezones": { "values":[ "Africa/Abidjan", "Africa/Accra", "Pacific/Wallis", "US/Pacific-New" ] } }`, 344 }, 345 346 // RESOURCELINK 347 { 348 method: "GET", 349 path: "/resourcelinks", 350 data: `{ "1": { "name": "Sunrise", "description": "Carla's wakeup experience", "class": 1, "owner": "78H56B12BAABCDEF", "links": ["/schedules/2", "/schedules/3", "/scenes/ABCD", "/scenes/EFGH", "/groups/8"] }, "2": { "name": "Sunrise 2" } }`, 351 }, 352 { 353 method: "GET", 354 path: "/resourcelinks/1", 355 data: `{ "name": "Sunrise", "description": "Carla's wakeup experience", "type":"Link", "class": 1, "owner": "78H56B12BAABCDEF", "links": ["/schedules/2", "/schedules/3", "/scenes/ABCD", "/scences/EFGH", "/groups/8"] }`, 356 }, 357 { 358 method: "POST", 359 path: "/resourcelinks", 360 data: `[{"success":{"id": "3"}}]`, 361 }, 362 { 363 method: "PUT", 364 path: "/resourcelinks/1", 365 data: `[{ "success": { "/resourcelinks/1/name": "Sunrise" } }, { "success": { "/resourcelinks/1/description": "Carla's wakeup experience" } }]`, 366 }, 367 { 368 method: "DELETE", 369 path: "/resourcelinks/1", 370 data: `[{"success": "/resourcelinks/1 deleted."}]`, 371 }, 372 } 373 374 httpmock.Activate() 375 376 for _, test := range tests { 377 if test.url == "" { 378 test.url = fmt.Sprintf("http://%s/api%s", hostname, test.path) 379 } 380 httpmock.RegisterResponder(test.method, test.url, httpmock.NewStringResponder(200, test.data)) 381 } 382 383 // Register a responder for bad requests 384 paths := []string{ 385 "", 386 "config", 387 "/config", 388 "/config", 389 "/config/whitelist/ffffffffe0341b1b376a2389376a2389", 390 path.Join("/invalid_password", "/lights"), 391 path.Join(username, "/lights"), 392 path.Join(username, "/lights/1"), 393 path.Join(username, "/lights/new"), 394 path.Join(username, "/lights"), 395 path.Join(username, "/lights/1/state"), 396 path.Join(username, "/lights/1"), 397 path.Join(username, "/lights/1"), 398 "/groups", 399 "/groups/1", 400 "/groups/1", 401 "/groups/1/action", 402 "/groups", 403 "/groups/1", 404 "/scenes", 405 "/scenes/4e1c6b20e-on-0", 406 "/scenes", 407 "/scenes/4e1c6b20e-on-0", 408 "/scenes/4e1c6b20e-on-0/lightstates/1", 409 "/scenes/4e1c6b20e-on-0", 410 "/rules", 411 "/rules/1", 412 "/rules", 413 "/rules/1", 414 "/rules/1", 415 "/schedules", 416 "/schedules/1", 417 "/schedules", 418 "/schedules/1", 419 "/schedules/1", 420 "/sensors", 421 "/sensors/1", 422 "/sensors", 423 "/sensors", 424 "/sensors/new", 425 "/sensors/1", 426 "/sensors/1", 427 "/sensors/1/config", 428 "/sensors/1/state", 429 "/capabilities", 430 "/resourcelinks", 431 "/resourcelinks/1", 432 "/resourcelinks", 433 "/resourcelinks/1", 434 "/resourcelinks/1", 435 } 436 437 // Register responder for errors 438 for _, p := range paths { 439 response := []byte("not json") 440 httpmock.RegisterResponder("GET", fmt.Sprintf("http://%s/api%s", badHostname, p), httpmock.NewBytesResponder(200, response)) 441 httpmock.RegisterResponder("POST", fmt.Sprintf("http://%s/api%s", badHostname, p), httpmock.NewBytesResponder(200, response)) 442 httpmock.RegisterResponder("PUT", fmt.Sprintf("http://%s/api%s", badHostname, p), httpmock.NewBytesResponder(200, response)) 443 httpmock.RegisterResponder("DELETE", fmt.Sprintf("http://%s/api%s", badHostname, p), httpmock.NewBytesResponder(200, response)) 444 } 445 446 } 447 448 func TestDiscoverAndLogin(t *testing.T) { 449 bridge, err := Discover() 450 if err != nil { 451 t.Fatal(err) 452 } 453 bridge = bridge.Login(username) 454 t.Logf("Successfully logged in to bridge") 455 } 456 457 func TestDiscoverAllBridges(t *testing.T) { 458 bridges, err := DiscoverAll() 459 if err != nil { 460 t.Fatal(err) 461 } 462 t.Logf("Discovered %d bridge(s)", len(bridges)) 463 for i, bridge := range bridges { 464 t.Logf("%d: ", i) 465 t.Logf(" Host: %s", bridge.Host) 466 t.Logf(" User: %s", bridge.User) 467 t.Logf(" ID: %s", bridge.ID) 468 } 469 } 470 471 func Test_unmarshalError(t *testing.T) { 472 s := struct { 473 Name string `json:"name"` 474 }{ 475 Name: "amimof", 476 } 477 err := unmarshal([]byte(`not json`), s) 478 assert.NotNil(t, err) 479 }