Commit e32ebbf8589ac977fa9e6d7a1dfba6b9b14d48c2

Authored by Jojo-1000
Committed by Moritz Wirger
1 parent 8bfb3741

Add documentation and tests for HueLightFactory.

include/hueplusplus/Group.h
@@ -40,7 +40,7 @@ namespace hueplusplus @@ -40,7 +40,7 @@ namespace hueplusplus
40 class Group 40 class Group
41 { 41 {
42 public: 42 public:
43 - //! Creates group with id 43 + //! \brief Creates group with id
44 //! \param id Group id in the bridge 44 //! \param id Group id in the bridge
45 //! \param commands HueCommandAPI for requests 45 //! \param commands HueCommandAPI for requests
46 //! \param refreshDuration Time between refreshing the cached state. 46 //! \param refreshDuration Time between refreshing the cached state.
include/hueplusplus/HueDeviceTypes.h
@@ -33,11 +33,28 @@ namespace hueplusplus @@ -33,11 +33,28 @@ namespace hueplusplus
33 class HueLightFactory 33 class HueLightFactory
34 { 34 {
35 public: 35 public:
  36 + //! \brief Create a factory for HueLight%s
  37 + //! \param commands HueCommandAPI for communication with the bridge
  38 + //! \param refreshDuration Time between refreshing the cached light state.
36 HueLightFactory(const HueCommandAPI& commands, std::chrono::steady_clock::duration refreshDuration); 39 HueLightFactory(const HueCommandAPI& commands, std::chrono::steady_clock::duration refreshDuration);
37 40
  41 + //! \brief Create a HueLight with the correct type from the JSON state.
  42 + //! \param lightState Light JSON as returned from the bridge (not only the "state" part of it).
  43 + //! \param id Light id.
  44 + //! \returns HueLight with matching id, strategies and \ref ColorType.
  45 + //! \throws std::system_error when system or socket operations fail
  46 + //! \throws HueException when light type is unknown
  47 + //! \throws HueAPIResponseException when response contains an error
  48 + //! \throws nlohmann::json::parse_error when response could not be parsed
38 HueLight createLight(const nlohmann::json& lightState, int id); 49 HueLight createLight(const nlohmann::json& lightState, int id);
39 50
40 private: 51 private:
  52 + //! \brief Get color type from light JSON.
  53 + //! \param lightState Light JSON as returned from the bridge (not only the "state" part of it).
  54 + //! \param hasCt Whether the light has color temperature control.
  55 + //! \returns The color gamut specified in the light capabilities or,
  56 + //! if that does not exist, from a set of known models. Returns GAMUT_X_TEMPERATURE when \ref hasCt is true.
  57 + //! \throws HueException when the light has no capabilities and the model is not known.
41 ColorType getColorType(const nlohmann::json& lightState, bool hasCt) const; 58 ColorType getColorType(const nlohmann::json& lightState, bool hasCt) const;
42 59
43 private: 60 private:
include/hueplusplus/HueLight.h
@@ -83,13 +83,13 @@ enum class ColorType @@ -83,13 +83,13 @@ enum class ColorType
83 { 83 {
84 UNDEFINED, //!< ColorType for this light is unknown or undefined 84 UNDEFINED, //!< ColorType for this light is unknown or undefined
85 NONE, //!< light has no specific ColorType 85 NONE, //!< light has no specific ColorType
86 - GAMUT_A,  
87 - GAMUT_B,  
88 - GAMUT_C,  
89 - TEMPERATURE,  
90 - GAMUT_A_TEMPERATURE,  
91 - GAMUT_B_TEMPERATURE,  
92 - GAMUT_C_TEMPERATURE 86 + GAMUT_A, //!< light uses Gamut A
  87 + GAMUT_B, //!< light uses Gamut B
  88 + GAMUT_C, //!< light uses Gamut C
  89 + TEMPERATURE, //!< light has color temperature control
  90 + GAMUT_A_TEMPERATURE, //!< light uses Gamut A and has color temperature control
  91 + GAMUT_B_TEMPERATURE, //!< light uses Gamut B and has color temperature control
  92 + GAMUT_C_TEMPERATURE //!< light uses Gamut C and has color temperature control
93 }; 93 };
94 94
95 //! \brief Class for Hue Light fixtures 95 //! \brief Class for Hue Light fixtures
test/CMakeLists.txt
@@ -37,6 +37,7 @@ set(TEST_SOURCES @@ -37,6 +37,7 @@ set(TEST_SOURCES
37 test_Group.cpp 37 test_Group.cpp
38 test_Hue.cpp 38 test_Hue.cpp
39 test_HueLight.cpp 39 test_HueLight.cpp
  40 + test_HueLightFactory.cpp
40 test_HueCommandAPI.cpp 41 test_HueCommandAPI.cpp
41 test_Main.cpp 42 test_Main.cpp
42 test_SimpleBrightnessStrategy.cpp 43 test_SimpleBrightnessStrategy.cpp
test/test_Group.cpp
@@ -270,12 +270,18 @@ TEST(CreateGroup, Entertainment) @@ -270,12 +270,18 @@ TEST(CreateGroup, Entertainment)
270 CreateGroup::Entertainment({2, 4}).getRequest()); 270 CreateGroup::Entertainment({2, 4}).getRequest());
271 } 271 }
272 272
  273 +TEST(CreateGroup, Zone)
  274 +{
  275 + EXPECT_EQ(nlohmann::json({{"lights", {"1"}}, {"type", "Zone"}, {"name", "Name"}}),
  276 + CreateGroup::Zone({1}, "Name").getRequest());
  277 + EXPECT_EQ(nlohmann::json({{"lights", {"2", "4"}}, {"type", "Zone"}}), CreateGroup::Zone({2, 4}).getRequest());
  278 +}
  279 +
273 TEST(CreateGroup, Room) 280 TEST(CreateGroup, Room)
274 { 281 {
275 EXPECT_EQ(nlohmann::json({{"lights", {"1"}}, {"type", "Room"}, {"name", "Name"}, {"class", "Bedroom"}}), 282 EXPECT_EQ(nlohmann::json({{"lights", {"1"}}, {"type", "Room"}, {"name", "Name"}, {"class", "Bedroom"}}),
276 CreateGroup::Room({1}, "Name", "Bedroom").getRequest()); 283 CreateGroup::Room({1}, "Name", "Bedroom").getRequest());
277 EXPECT_EQ(nlohmann::json({{"lights", {"1"}}, {"type", "Room"}, {"name", "Name"}}), 284 EXPECT_EQ(nlohmann::json({{"lights", {"1"}}, {"type", "Room"}, {"name", "Name"}}),
278 CreateGroup::Room({1}, "Name").getRequest()); 285 CreateGroup::Room({1}, "Name").getRequest());
279 - EXPECT_EQ(  
280 - nlohmann::json({{"lights", {"2", "4"}}, {"type", "Room"}}), CreateGroup::Room({2, 4}).getRequest()); 286 + EXPECT_EQ(nlohmann::json({{"lights", {"2", "4"}}, {"type", "Room"}}), CreateGroup::Room({2, 4}).getRequest());
281 } 287 }
282 \ No newline at end of file 288 \ No newline at end of file
test/test_Hue.cpp
@@ -296,101 +296,6 @@ TEST(Hue, getLight) @@ -296,101 +296,6 @@ TEST(Hue, getLight)
296 test_light_1 = test_bridge.getLight(1); 296 test_light_1 = test_bridge.getLight(1);
297 EXPECT_EQ(test_light_1.getName(), "Hue ambiance lamp 1"); 297 EXPECT_EQ(test_light_1.getName(), "Hue ambiance lamp 1");
298 EXPECT_EQ(test_light_1.getColorType(), ColorType::TEMPERATURE); 298 EXPECT_EQ(test_light_1.getColorType(), ColorType::TEMPERATURE);
299 -  
300 - // more coverage stuff  
301 - hue_bridge_state["lights"]["1"]["type"] = "Color light";  
302 - hue_bridge_state["lights"]["1"]["modelid"] = "LCT001";  
303 - EXPECT_CALL(  
304 - *handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort()))  
305 - .Times(1)  
306 - .WillOnce(Return(hue_bridge_state));  
307 -  
308 - EXPECT_CALL(*handler,  
309 - GETJson("/api/" + getBridgeUsername() + "/lights/1", nlohmann::json::object(), getBridgeIp(), getBridgePort()))  
310 - .Times(AtLeast(1))  
311 - .WillRepeatedly(Return(hue_bridge_state["lights"]["1"]));  
312 - test_bridge = Hue(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler);  
313 -  
314 - // Test when correct data is sent  
315 - test_light_1 = test_bridge.getLight(1);  
316 - EXPECT_EQ(test_light_1.getName(), "Hue ambiance lamp 1");  
317 - EXPECT_EQ(test_light_1.getColorType(), ColorType::GAMUT_B);  
318 -  
319 - hue_bridge_state["lights"]["1"]["modelid"] = "LCT010";  
320 - EXPECT_CALL(  
321 - *handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort()))  
322 - .Times(1)  
323 - .WillOnce(Return(hue_bridge_state));  
324 -  
325 - EXPECT_CALL(*handler,  
326 - GETJson("/api/" + getBridgeUsername() + "/lights/1", nlohmann::json::object(), getBridgeIp(), getBridgePort()))  
327 - .Times(AtLeast(1))  
328 - .WillRepeatedly(Return(hue_bridge_state["lights"]["1"]));  
329 - test_bridge = Hue(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler);  
330 -  
331 - // Test when correct data is sent  
332 - test_light_1 = test_bridge.getLight(1);  
333 - EXPECT_EQ(test_light_1.getName(), "Hue ambiance lamp 1");  
334 - EXPECT_EQ(test_light_1.getColorType(), ColorType::GAMUT_C);  
335 -  
336 - hue_bridge_state["lights"]["1"]["modelid"] = "LST001";  
337 - EXPECT_CALL(  
338 - *handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort()))  
339 - .Times(1)  
340 - .WillOnce(Return(hue_bridge_state));  
341 -  
342 - EXPECT_CALL(*handler,  
343 - GETJson("/api/" + getBridgeUsername() + "/lights/1", nlohmann::json::object(), getBridgeIp(), getBridgePort()))  
344 - .Times(AtLeast(1))  
345 - .WillRepeatedly(Return(hue_bridge_state["lights"]["1"]));  
346 - test_bridge = Hue(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler);  
347 -  
348 - // Test when correct data is sent  
349 - test_light_1 = test_bridge.getLight(1);  
350 - EXPECT_EQ(test_light_1.getName(), "Hue ambiance lamp 1");  
351 - EXPECT_EQ(test_light_1.getColorType(), ColorType::GAMUT_A);  
352 -  
353 - hue_bridge_state["lights"]["1"]["type"] = "Dimmable light";  
354 - EXPECT_CALL(  
355 - *handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort()))  
356 - .Times(1)  
357 - .WillOnce(Return(hue_bridge_state));  
358 -  
359 - EXPECT_CALL(*handler,  
360 - GETJson("/api/" + getBridgeUsername() + "/lights/1", nlohmann::json::object(), getBridgeIp(), getBridgePort()))  
361 - .Times(AtLeast(1))  
362 - .WillRepeatedly(Return(hue_bridge_state["lights"]["1"]));  
363 - test_bridge = Hue(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler);  
364 -  
365 - // Test when correct data is sent  
366 - test_light_1 = test_bridge.getLight(1);  
367 - EXPECT_EQ(test_light_1.getName(), "Hue ambiance lamp 1");  
368 - EXPECT_EQ(test_light_1.getColorType(), ColorType::NONE);  
369 -  
370 - hue_bridge_state["lights"]["1"]["type"] = "On/Off light";  
371 - EXPECT_CALL(  
372 - *handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort()))  
373 - .Times(1)  
374 - .WillOnce(Return(hue_bridge_state));  
375 -  
376 - EXPECT_CALL(*handler,  
377 - GETJson("/api/" + getBridgeUsername() + "/lights/1", nlohmann::json::object(), getBridgeIp(), getBridgePort()))  
378 - .Times(AtLeast(1))  
379 - .WillRepeatedly(Return(hue_bridge_state["lights"]["1"]));  
380 - test_bridge = Hue(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler);  
381 -  
382 - // Test when correct data is sent  
383 - test_light_1 = test_bridge.getLight(1);  
384 - EXPECT_EQ(test_light_1.getName(), "Hue ambiance lamp 1");  
385 - EXPECT_EQ(test_light_1.getColorType(), ColorType::NONE);  
386 -  
387 - hue_bridge_state["lights"]["1"]["type"] = "unknown light type";  
388 - EXPECT_CALL(  
389 - *handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort()))  
390 - .Times(1)  
391 - .WillOnce(Return(hue_bridge_state));  
392 - test_bridge = Hue(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler);  
393 - ASSERT_THROW(test_bridge.getLight(1), HueException);  
394 } 299 }
395 300
396 TEST(Hue, removeLight) 301 TEST(Hue, removeLight)
@@ -659,6 +564,9 @@ TEST(Hue, createGroup) @@ -659,6 +564,9 @@ TEST(Hue, createGroup)
659 { 564 {
660 using namespace ::testing; 565 using namespace ::testing;
661 std::shared_ptr<MockHttpHandler> handler = std::make_shared<MockHttpHandler>(); 566 std::shared_ptr<MockHttpHandler> handler = std::make_shared<MockHttpHandler>();
  567 + EXPECT_CALL(
  568 + *handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort()))
  569 + .Times(AtLeast(1));
662 Hue test_bridge(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler); 570 Hue test_bridge(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler);
663 CreateGroup create = CreateGroup::Room({2, 3}, "Nice room", "LivingRoom"); 571 CreateGroup create = CreateGroup::Room({2, 3}, "Nice room", "LivingRoom");
664 nlohmann::json request = create.getRequest(); 572 nlohmann::json request = create.getRequest();
test/test_HueLightFactory.cpp 0 โ†’ 100644
  1 +/**
  2 + \file test_HueLightFactory.cpp
  3 + Copyright Notice\n
  4 + Copyright (C) 2020 Jan Rogall - developer\n
  5 + Copyright (C) 2020 Moritz Wirger - developer\n
  6 +
  7 + This file is part of hueplusplus.
  8 +
  9 + hueplusplus is free software: you can redistribute it and/or modify
  10 + it under the terms of the GNU Lesser General Public License as published by
  11 + the Free Software Foundation, either version 3 of the License, or
  12 + (at your option) any later version.
  13 +
  14 + hueplusplus is distributed in the hope that it will be useful,
  15 + but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17 + GNU Lesser General Public License for more details.
  18 +
  19 + You should have received a copy of the GNU Lesser General Public License
  20 + along with hueplusplus. If not, see <http://www.gnu.org/licenses/>.
  21 +**/
  22 +
  23 +#include <gtest/gtest.h>
  24 +#include <hueplusplus/HueDeviceTypes.h>
  25 +
  26 +#include "testhelper.h"
  27 +
  28 +#include "mocks/mock_HttpHandler.h"
  29 +
  30 +using namespace hueplusplus;
  31 +
  32 +TEST(HueLightFactory, createLight_noGamut)
  33 +{
  34 + using namespace ::testing;
  35 + std::shared_ptr<MockHttpHandler> handler = std::make_shared<MockHttpHandler>();
  36 +
  37 + HueLightFactory factory(HueCommandAPI(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler),
  38 + std::chrono::steady_clock::duration::max());
  39 +
  40 + nlohmann::json lightState
  41 + = {{"state",
  42 + {{"on", true}, {"bri", 254}, {"ct", 366}, {"alert", "none"}, {"colormode", "ct"}, {"reachable", true}}},
  43 + {"swupdate", {{"state", "noupdates"}, {"lastinstall", nullptr}}}, {"type", "Color temperature light"},
  44 + {"name", "Hue ambiance lamp 1"}, {"modelid", "LTW001"}, {"manufacturername", "Philips"},
  45 + {"uniqueid", "00:00:00:00:00:00:00:00-00"}, {"swversion", "5.50.1.19085"}};
  46 +
  47 + EXPECT_CALL(*handler,
  48 + GETJson("/api/" + getBridgeUsername() + "/lights/1", nlohmann::json::object(), getBridgeIp(), getBridgePort()))
  49 + .Times(AtLeast(1))
  50 + .WillRepeatedly(Return(lightState));
  51 +
  52 + HueLight test_light_1 = factory.createLight(lightState, 1);
  53 + EXPECT_EQ(test_light_1.getColorType(), ColorType::TEMPERATURE);
  54 +
  55 + lightState["type"] = "Dimmable light";
  56 +
  57 + EXPECT_CALL(*handler,
  58 + GETJson("/api/" + getBridgeUsername() + "/lights/1", nlohmann::json::object(), getBridgeIp(), getBridgePort()))
  59 + .Times(AtLeast(1))
  60 + .WillRepeatedly(Return(lightState));
  61 +
  62 + test_light_1 = factory.createLight(lightState, 1);
  63 + EXPECT_EQ(test_light_1.getColorType(), ColorType::NONE);
  64 +
  65 + lightState["type"] = "On/Off light";
  66 +
  67 + EXPECT_CALL(*handler,
  68 + GETJson("/api/" + getBridgeUsername() + "/lights/1", nlohmann::json::object(), getBridgeIp(), getBridgePort()))
  69 + .Times(AtLeast(1))
  70 + .WillRepeatedly(Return(lightState));
  71 +
  72 + test_light_1 = factory.createLight(lightState, 1);
  73 + EXPECT_EQ(test_light_1.getColorType(), ColorType::NONE);
  74 +
  75 + lightState["type"] = "unknown light type";
  76 + ASSERT_THROW(factory.createLight(lightState, 1), HueException);
  77 +}
  78 +
  79 +TEST(HueLightFactory, createLight_gamutCapabilities)
  80 +{
  81 + using namespace ::testing;
  82 + std::shared_ptr<MockHttpHandler> handler = std::make_shared<MockHttpHandler>();
  83 +
  84 + HueLightFactory factory(HueCommandAPI(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler),
  85 + std::chrono::steady_clock::duration::max());
  86 +
  87 + nlohmann::json lightState
  88 + = { {"state",
  89 + {{"on", true}, {"bri", 254}, {"ct", 366}, {"alert", "none"}, {"colormode", "ct"}, {"reachable", true}}},
  90 + {"swupdate", {{"state", "noupdates"}, {"lastinstall", nullptr}}}, {"type", "Color light"},
  91 + {"name", "Hue ambiance lamp 1"}, {"modelid", "LTW001"}, {"manufacturername", "Philips"},
  92 + {"uniqueid", "00:00:00:00:00:00:00:00-00"}, {"swversion", "5.50.1.19085"},
  93 + {"capabilities", {{"control", {{"colorgamuttype", "A"}}}}} };
  94 +
  95 + EXPECT_CALL(*handler,
  96 + GETJson("/api/" + getBridgeUsername() + "/lights/1", nlohmann::json::object(), getBridgeIp(), getBridgePort()))
  97 + .Times(AtLeast(1))
  98 + .WillRepeatedly(Return(lightState));
  99 +
  100 + HueLight test_light_1 = factory.createLight(lightState, 1);
  101 + EXPECT_EQ(test_light_1.getColorType(), ColorType::GAMUT_A);
  102 +
  103 + lightState["capabilities"]["control"]["colorgamuttype"] = "B";
  104 +
  105 + EXPECT_CALL(*handler,
  106 + GETJson("/api/" + getBridgeUsername() + "/lights/1", nlohmann::json::object(), getBridgeIp(), getBridgePort()))
  107 + .Times(AtLeast(1))
  108 + .WillRepeatedly(Return(lightState));
  109 +
  110 + test_light_1 = factory.createLight(lightState, 1);
  111 + EXPECT_EQ(test_light_1.getColorType(), ColorType::GAMUT_B);
  112 +
  113 + lightState["capabilities"]["control"]["colorgamuttype"] = "C";
  114 +
  115 + EXPECT_CALL(*handler,
  116 + GETJson("/api/" + getBridgeUsername() + "/lights/1", nlohmann::json::object(), getBridgeIp(), getBridgePort()))
  117 + .Times(AtLeast(1))
  118 + .WillRepeatedly(Return(lightState));
  119 +
  120 + test_light_1 = factory.createLight(lightState, 1);
  121 + EXPECT_EQ(test_light_1.getColorType(), ColorType::GAMUT_C);
  122 +
  123 + lightState["capabilities"]["control"]["colorgamuttype"] = "Other";
  124 +
  125 + EXPECT_CALL(*handler,
  126 + GETJson("/api/" + getBridgeUsername() + "/lights/1", nlohmann::json::object(), getBridgeIp(), getBridgePort()))
  127 + .Times(AtLeast(1))
  128 + .WillRepeatedly(Return(lightState));
  129 +
  130 + test_light_1 = factory.createLight(lightState, 1);
  131 + EXPECT_EQ(test_light_1.getColorType(), ColorType::UNDEFINED);
  132 +
  133 + // With color temperature
  134 + lightState["type"] = "Extended color light";
  135 + lightState["capabilities"]["control"]["colorgamuttype"] = "A";
  136 + EXPECT_CALL(*handler,
  137 + GETJson("/api/" + getBridgeUsername() + "/lights/1", nlohmann::json::object(), getBridgeIp(), getBridgePort()))
  138 + .Times(AtLeast(1))
  139 + .WillRepeatedly(Return(lightState));
  140 +
  141 + test_light_1 = factory.createLight(lightState, 1);
  142 + EXPECT_EQ(test_light_1.getColorType(), ColorType::GAMUT_A_TEMPERATURE);
  143 +
  144 + lightState["capabilities"]["control"]["colorgamuttype"] = "B";
  145 + EXPECT_CALL(*handler,
  146 + GETJson("/api/" + getBridgeUsername() + "/lights/1", nlohmann::json::object(), getBridgeIp(), getBridgePort()))
  147 + .Times(AtLeast(1))
  148 + .WillRepeatedly(Return(lightState));
  149 +
  150 + test_light_1 = factory.createLight(lightState, 1);
  151 + EXPECT_EQ(test_light_1.getColorType(), ColorType::GAMUT_B_TEMPERATURE);
  152 +
  153 + lightState["capabilities"]["control"]["colorgamuttype"] = "C";
  154 + EXPECT_CALL(*handler,
  155 + GETJson("/api/" + getBridgeUsername() + "/lights/1", nlohmann::json::object(), getBridgeIp(), getBridgePort()))
  156 + .Times(AtLeast(1))
  157 + .WillRepeatedly(Return(lightState));
  158 +
  159 + test_light_1 = factory.createLight(lightState, 1);
  160 + EXPECT_EQ(test_light_1.getColorType(), ColorType::GAMUT_C_TEMPERATURE);
  161 +}
  162 +
  163 +TEST(HueLightFactory, createLight_gamutModelid)
  164 +{
  165 + using namespace ::testing;
  166 + std::shared_ptr<MockHttpHandler> handler = std::make_shared<MockHttpHandler>();
  167 +
  168 + HueLightFactory factory(HueCommandAPI(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler),
  169 + std::chrono::steady_clock::duration::max());
  170 +
  171 + const std::string gamutAModel = "LST001";
  172 + const std::string gamutBModel = "LCT001";
  173 + const std::string gamutCModel = "LCT010";
  174 +
  175 + nlohmann::json lightState
  176 + = {{"state",
  177 + {{"on", true}, {"bri", 254}, {"ct", 366}, {"alert", "none"}, {"colormode", "ct"}, {"reachable", true}}},
  178 + {"swupdate", {{"state", "noupdates"}, {"lastinstall", nullptr}}}, {"type", "Color light"},
  179 + {"name", "Hue ambiance lamp 1"}, {"modelid", gamutAModel}, {"manufacturername", "Philips"},
  180 + {"uniqueid", "00:00:00:00:00:00:00:00-00"}, {"swversion", "5.50.1.19085"}};
  181 +
  182 + EXPECT_CALL(*handler,
  183 + GETJson("/api/" + getBridgeUsername() + "/lights/1", nlohmann::json::object(), getBridgeIp(), getBridgePort()))
  184 + .Times(AtLeast(1))
  185 + .WillRepeatedly(Return(lightState));
  186 +
  187 + HueLight test_light_1 = factory.createLight(lightState, 1);
  188 + EXPECT_EQ(test_light_1.getColorType(), ColorType::GAMUT_A);
  189 +
  190 + lightState["modelid"] = gamutBModel;
  191 + EXPECT_CALL(*handler,
  192 + GETJson("/api/" + getBridgeUsername() + "/lights/1", nlohmann::json::object(), getBridgeIp(), getBridgePort()))
  193 + .Times(AtLeast(1))
  194 + .WillRepeatedly(Return(lightState));
  195 +
  196 + test_light_1 = factory.createLight(lightState, 1);
  197 + EXPECT_EQ(test_light_1.getColorType(), ColorType::GAMUT_B);
  198 +
  199 + lightState["modelid"] = gamutCModel;
  200 +
  201 + EXPECT_CALL(*handler,
  202 + GETJson("/api/" + getBridgeUsername() + "/lights/1", nlohmann::json::object(), getBridgeIp(), getBridgePort()))
  203 + .Times(AtLeast(1))
  204 + .WillRepeatedly(Return(lightState));
  205 +
  206 + test_light_1 = factory.createLight(lightState, 1);
  207 + EXPECT_EQ(test_light_1.getColorType(), ColorType::GAMUT_C);
  208 +
  209 + // With color temperature
  210 + lightState["type"] = "Extended color light";
  211 + lightState["modelid"] = gamutAModel;
  212 +
  213 + EXPECT_CALL(*handler,
  214 + GETJson("/api/" + getBridgeUsername() + "/lights/1", nlohmann::json::object(), getBridgeIp(), getBridgePort()))
  215 + .Times(AtLeast(1))
  216 + .WillRepeatedly(Return(lightState));
  217 +
  218 + test_light_1 = factory.createLight(lightState, 1);
  219 + EXPECT_EQ(test_light_1.getColorType(), ColorType::GAMUT_A_TEMPERATURE);
  220 +
  221 + lightState["modelid"] = gamutBModel;
  222 + EXPECT_CALL(*handler,
  223 + GETJson("/api/" + getBridgeUsername() + "/lights/1", nlohmann::json::object(), getBridgeIp(), getBridgePort()))
  224 + .Times(AtLeast(1))
  225 + .WillRepeatedly(Return(lightState));
  226 +
  227 + test_light_1 = factory.createLight(lightState, 1);
  228 + EXPECT_EQ(test_light_1.getColorType(), ColorType::GAMUT_B_TEMPERATURE);
  229 +
  230 + lightState["modelid"] = gamutCModel;
  231 +
  232 + EXPECT_CALL(*handler,
  233 + GETJson("/api/" + getBridgeUsername() + "/lights/1", nlohmann::json::object(), getBridgeIp(), getBridgePort()))
  234 + .Times(AtLeast(1))
  235 + .WillRepeatedly(Return(lightState));
  236 +
  237 + test_light_1 = factory.createLight(lightState, 1);
  238 + EXPECT_EQ(test_light_1.getColorType(), ColorType::GAMUT_C_TEMPERATURE);
  239 +
  240 + // Unknown model
  241 + lightState["modelid"] = "Unknown model";
  242 + EXPECT_THROW(factory.createLight(lightState, 1), HueException);
  243 +}