Commit aec7baeb0d8eaa177c7d487237f221eb77738d0a

Authored by Jojo-1000
Committed by Moritz Wirger
1 parent 11a2c0bf

Add tests for Scene.

src/Scene.cpp
... ... @@ -319,6 +319,7 @@ void Scene::sendPutRequest(const std::string& path, const nlohmann::json& reques
319 319  
320 320 CreateScene& CreateScene::setName(const std::string& name)
321 321 {
  322 + request["name"] = name;
322 323 return *this;
323 324 }
324 325  
... ...
test/CMakeLists.txt
... ... @@ -42,6 +42,7 @@ set(TEST_SOURCES
42 42 test_Main.cpp
43 43 test_UPnP.cpp
44 44 test_ResourceList.cpp
  45 + test_Scene.cpp
45 46 test_Schedule.cpp
46 47 test_SimpleBrightnessStrategy.cpp
47 48 test_SimpleColorHueStrategy.cpp
... ...
test/test_Scene.cpp 0 → 100644
  1 +/**
  2 + \file test_Scene.cpp
  3 + Copyright Notice\n
  4 + Copyright (C) 2020 Jan Rogall - developer\n
  5 +
  6 + This file is part of hueplusplus.
  7 +
  8 + hueplusplus is free software: you can redistribute it and/or modify
  9 + it under the terms of the GNU Lesser General Public License as published by
  10 + the Free Software Foundation, either version 3 of the License, or
  11 + (at your option) any later version.
  12 +
  13 + hueplusplus is distributed in the hope that it will be useful,
  14 + but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16 + GNU Lesser General Public License for more details.
  17 +
  18 + You should have received a copy of the GNU Lesser General Public License
  19 + along with hueplusplus. If not, see <http://www.gnu.org/licenses/>.
  20 +**/
  21 +
  22 +#include <hueplusplus/Scene.h>
  23 +
  24 +#include <gtest/gtest.h>
  25 +
  26 +#include "testhelper.h"
  27 +
  28 +#include "mocks/mock_HttpHandler.h"
  29 +
  30 +using namespace hueplusplus;
  31 +using namespace testing;
  32 +
  33 +TEST(LightState, On)
  34 +{
  35 + EXPECT_FALSE(LightState(nlohmann::json::object()).isOn());
  36 + EXPECT_TRUE(LightState(nlohmann::json {{"on", true}}).isOn());
  37 + EXPECT_FALSE(LightState(nlohmann::json {{"on", false}}).isOn());
  38 +}
  39 +
  40 +TEST(LightState, Brightness)
  41 +{
  42 + EXPECT_FALSE(LightState(nlohmann::json::object()).hasBrightness());
  43 + const int bri = 125;
  44 + nlohmann::json json {{"bri", bri}};
  45 + const LightState state {json};
  46 + EXPECT_TRUE(state.hasBrightness());
  47 + EXPECT_EQ(bri, state.getBrightness());
  48 +}
  49 +
  50 +TEST(LightState, HueSat)
  51 +{
  52 + EXPECT_FALSE(LightState(nlohmann::json::object()).hasHueSat());
  53 + EXPECT_FALSE(LightState(nlohmann::json {{"hue", 0}}).hasHueSat());
  54 + EXPECT_FALSE(LightState(nlohmann::json {{"sat", 0}}).hasHueSat());
  55 + const int hue = 12553;
  56 + const int sat = 240;
  57 + nlohmann::json json {{"hue", hue}, {"sat", sat}};
  58 + const LightState state {json};
  59 + EXPECT_TRUE(state.hasHueSat());
  60 + EXPECT_EQ(hue, state.getHueSat().hue);
  61 + EXPECT_EQ(sat, state.getHueSat().saturation);
  62 +}
  63 +
  64 +TEST(LightState, XY)
  65 +{
  66 + EXPECT_FALSE(LightState(nlohmann::json::object()).hasXY());
  67 + const float x = 0.6f;
  68 + const float y = 0.3f;
  69 + nlohmann::json json {{"xy", {x, y}}};
  70 + const LightState state {json};
  71 + EXPECT_TRUE(state.hasXY());
  72 + EXPECT_FLOAT_EQ(x, state.getXY().x);
  73 + EXPECT_FLOAT_EQ(y, state.getXY().y);
  74 +}
  75 +
  76 +TEST(LightState, Ct)
  77 +{
  78 + EXPECT_FALSE(LightState(nlohmann::json::object()).hasCt());
  79 + const int ct = 260;
  80 + nlohmann::json json {{"ct", ct}};
  81 + const LightState state {json};
  82 + EXPECT_TRUE(state.hasCt());
  83 + EXPECT_EQ(ct, state.getCt());
  84 +}
  85 +
  86 +TEST(LightState, Effect)
  87 +{
  88 + EXPECT_FALSE(LightState(nlohmann::json::object()).hasEffect());
  89 + nlohmann::json json {{"effect", "colorloop"}};
  90 + const LightState state {json};
  91 + EXPECT_TRUE(state.hasEffect());
  92 + EXPECT_TRUE(state.getColorloop());
  93 + EXPECT_FALSE(LightState(nlohmann::json {{"effect", "none"}}).getColorloop());
  94 +}
  95 +
  96 +TEST(LightState, TransitionTime)
  97 +{
  98 + EXPECT_EQ(4, LightState(nlohmann::json::object()).getTransitionTime());
  99 + EXPECT_EQ(0, LightState(nlohmann::json {{"transitiontime", 0}}).getTransitionTime());
  100 +}
  101 +
  102 +TEST(LightState, toJson)
  103 +{
  104 + const nlohmann::json json {{"on", false}, {"bri", 254}, {"ct", 400}};
  105 + EXPECT_EQ(json, LightState(json).toJson());
  106 +}
  107 +
  108 +TEST(LightStateBuilder, create)
  109 +{
  110 + {
  111 + const nlohmann::json json {{"on", false}, {"bri", 254}, {"ct", 400}, {"effect", "colorloop"}};
  112 + EXPECT_EQ(
  113 + json, LightStateBuilder().setOn(false).setBrightness(254).setCt(400).setColorloop(true).create().toJson());
  114 + }
  115 + {
  116 + const nlohmann::json json {{"xy", {0.5f, 0.5f}}, {"effect", "none"}};
  117 + EXPECT_EQ(json, LightStateBuilder().setXY({0.5f, 0.5f}).setColorloop(false).create().toJson());
  118 + }
  119 + {
  120 + const nlohmann::json json {{"hue", 360}, {"sat", 230}, {"transitiontime", 4}};
  121 + EXPECT_EQ(json, LightStateBuilder().setHueSat({360, 230}).setTransitionTime(4).create().toJson());
  122 + }
  123 +}
  124 +
  125 +class SceneTest : public Test
  126 +{
  127 +public:
  128 + std::shared_ptr<MockHttpHandler> handler;
  129 + HueCommandAPI commands;
  130 + nlohmann::json sceneState;
  131 +
  132 + SceneTest()
  133 + : handler(std::make_shared<MockHttpHandler>()),
  134 + commands(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler),
  135 + sceneState({{"name", "Test scene"}, {"type", "GroupScene"}, {"group", "4"}, {"lights", {"3", "4", "5"}},
  136 + {"owner", "testowner"}, {"recycle", false}, {"locked", false},
  137 + {"appdata", {{"data", "test-data"}, {"version", 2}}}, {"picture", ""},
  138 + {"lastupdated", "2020-04-23T12:00:04"}, {"version", 2},
  139 + {"lightstates",
  140 + {{"3", {{"on", false}, {"bri", 100}, {"xy", {0.3, 0.2}}}},
  141 + {"4", {{"on", true}, {"bri", 200}, {"xy", {0.3, 0.2}}, {"effect", "colorloop"}}},
  142 + {"5", {{"on", true}, {"bri", 100}, {"xy", {0.3, 0.2}}}}}}})
  143 + {}
  144 +
  145 + void expectGetState(const std::string& id)
  146 + {
  147 + EXPECT_CALL(*handler,
  148 + GETJson("/api/" + getBridgeUsername() + "/scenes/" + id, nlohmann::json::object(), getBridgeIp(),
  149 + getBridgePort()))
  150 + .WillOnce(Return(sceneState));
  151 + }
  152 +};
  153 +
  154 +TEST_F(SceneTest, Constructor)
  155 +{
  156 + const std::string id = "asd89263";
  157 + expectGetState(id);
  158 + const Scene scene(id, commands, std::chrono::seconds(0));
  159 + EXPECT_EQ(id, scene.getId());
  160 +}
  161 +
  162 +TEST_F(SceneTest, getName)
  163 +{
  164 + const std::string id = "125abets8912";
  165 + const std::string name = "Scene name";
  166 + sceneState["name"] = name;
  167 + expectGetState(id);
  168 + const Scene scene(id, commands, std::chrono::seconds(0));
  169 + EXPECT_EQ(name, scene.getName());
  170 +}
  171 +
  172 +TEST_F(SceneTest, getType)
  173 +{
  174 + const std::string id = "125abets8912";
  175 + {
  176 + sceneState["type"] = "GroupScene";
  177 + expectGetState(id);
  178 + const Scene scene(id, commands, std::chrono::seconds(0));
  179 + EXPECT_EQ(Scene::Type::groupScene, scene.getType());
  180 + }
  181 + {
  182 + sceneState["type"] = "LightScene";
  183 + expectGetState(id);
  184 + const Scene scene(id, commands, std::chrono::seconds(0));
  185 + EXPECT_EQ(Scene::Type::lightScene, scene.getType());
  186 + }
  187 +}
  188 +
  189 +TEST_F(SceneTest, getGroupId)
  190 +{
  191 + const std::string id = "125abets8912";
  192 + {
  193 + sceneState["group"] = "3";
  194 + expectGetState(id);
  195 + const Scene scene(id, commands, std::chrono::seconds(0));
  196 + EXPECT_EQ(3, scene.getGroupId());
  197 + }
  198 + {
  199 + sceneState["type"] = "LightScene";
  200 + sceneState.erase("group");
  201 + expectGetState(id);
  202 + const Scene scene(id, commands, std::chrono::seconds(0));
  203 + EXPECT_EQ(0, scene.getGroupId());
  204 + }
  205 +}
  206 +
  207 +TEST_F(SceneTest, getLightIds)
  208 +{
  209 + const std::string id = "125asav3";
  210 + sceneState["lights"] = {"3", "4", "5"};
  211 + expectGetState(id);
  212 + const Scene scene(id, commands, std::chrono::seconds(0));
  213 + EXPECT_THAT(scene.getLightIds(), UnorderedElementsAre(3, 4, 5));
  214 +}
  215 +
  216 +TEST_F(SceneTest, getOwner)
  217 +{
  218 + const std::string id = "125asav3";
  219 + const std::string owner = "testowner";
  220 + sceneState["owner"] = owner;
  221 + expectGetState(id);
  222 + const Scene scene(id, commands, std::chrono::seconds(0));
  223 + EXPECT_EQ(owner, scene.getOwner());
  224 +}
  225 +
  226 +TEST_F(SceneTest, getRecycle)
  227 +{
  228 + const std::string id = "125asav3";
  229 + const bool recycle = true;
  230 + sceneState["recycle"] = recycle;
  231 + expectGetState(id);
  232 + const Scene scene(id, commands, std::chrono::seconds(0));
  233 + EXPECT_EQ(recycle, scene.getRecycle());
  234 +}
  235 +
  236 +TEST_F(SceneTest, isLocked)
  237 +{
  238 + const std::string id = "125asav3";
  239 + const bool locked = true;
  240 + sceneState["locked"] = locked;
  241 + expectGetState(id);
  242 + const Scene scene(id, commands, std::chrono::seconds(0));
  243 + EXPECT_EQ(locked, scene.isLocked());
  244 +}
  245 +
  246 +TEST_F(SceneTest, getAppdata)
  247 +{
  248 + const std::string id = "125asav3";
  249 + const std::string appdata = "some data";
  250 + const int version = 10;
  251 + sceneState["appdata"] = {{"version", version}, {"data", appdata}};
  252 + expectGetState(id);
  253 + const Scene scene(id, commands, std::chrono::seconds(0));
  254 + EXPECT_EQ(version, scene.getAppdataVersion());
  255 + EXPECT_EQ(appdata, scene.getAppdata());
  256 +}
  257 +
  258 +TEST_F(SceneTest, getPicture)
  259 +{
  260 + const std::string id = "125asav3";
  261 + const std::string picture = "abcpicture";
  262 + sceneState["picture"] = picture;
  263 + expectGetState(id);
  264 + const Scene scene(id, commands, std::chrono::seconds(0));
  265 + EXPECT_EQ(picture, scene.getPicture());
  266 +}
  267 +
  268 +TEST_F(SceneTest, getLastUpdated)
  269 +{
  270 + const std::string id = "125asav3";
  271 + expectGetState(id);
  272 + const Scene scene(id, commands, std::chrono::seconds(0));
  273 + const time::AbsoluteTime lastUpdated = scene.getLastUpdated();
  274 + EXPECT_EQ(std::chrono::seconds(0), lastUpdated.getRandomVariation());
  275 +}
  276 +
  277 +TEST_F(SceneTest, getVersion)
  278 +{
  279 + const std::string id = "125asav3";
  280 + const int version = 2;
  281 + sceneState["version"] = version;
  282 + expectGetState(id);
  283 + const Scene scene(id, commands, std::chrono::seconds(0));
  284 + EXPECT_EQ(version, scene.getVersion());
  285 +}
  286 +
  287 +TEST_F(SceneTest, getLightstates)
  288 +{
  289 + const std::string id = "125asav3";
  290 + {
  291 + const std::map<int, LightState> lightstates{
  292 + {3, LightStateBuilder().setOn(false).setBrightness(100).setXY({0.3, 0.2}).create()},
  293 + {4, LightStateBuilder().setOn(false).setBrightness(200).setXY({0.3, 0.2}).setColorloop(true).create()},
  294 + {5, LightStateBuilder().setOn(true).setBrightness(100).setXY({0.3, 0.2}).create()} };
  295 + nlohmann::json lightstatesJson;
  296 + for (const auto& entry : lightstates)
  297 + {
  298 + lightstatesJson[std::to_string(entry.first)] = entry.second.toJson();
  299 + }
  300 + sceneState["lightstates"] = lightstatesJson;
  301 + expectGetState(id);
  302 + const Scene scene(id, commands, std::chrono::seconds(0));
  303 + const std::map<int, LightState> result = scene.getLightStates();
  304 + EXPECT_EQ(lightstates, result);
  305 + }
  306 + // No lightstates (old scene)
  307 + {
  308 + sceneState.erase("lightstates");
  309 + expectGetState(id);
  310 + const Scene scene(id, commands, std::chrono::seconds(0));
  311 + EXPECT_TRUE(scene.getLightStates().empty());
  312 + }
  313 +}
  314 +
  315 +TEST_F(SceneTest, refresh)
  316 +{
  317 + const std::string id = "125asav3";
  318 + expectGetState(id);
  319 + Scene scene(id, commands, std::chrono::seconds(0));
  320 + expectGetState(id);
  321 + scene.refresh();
  322 +}
  323 +
  324 +TEST_F(SceneTest, setName)
  325 +{
  326 + const std::string id = "125asav3";
  327 + expectGetState(id);
  328 + Scene scene(id, commands, std::chrono::seconds(0));
  329 + const std::string name = "Scene name";
  330 + nlohmann::json request = {{"name", name}};
  331 + nlohmann::json response = {{"success", {"/scenes/" + id + "/name", name}}};
  332 + EXPECT_CALL(
  333 + *handler, PUTJson("/api/" + getBridgeUsername() + "/scenes/" + id, request, getBridgeIp(), getBridgePort()))
  334 + .WillOnce(Return(response));
  335 + expectGetState(id);
  336 + scene.setName(name);
  337 +}
  338 +
  339 +TEST_F(SceneTest, setLightIds)
  340 +{
  341 + const std::string id = "125asav3";
  342 + expectGetState(id);
  343 + Scene scene(id, commands, std::chrono::seconds(0));
  344 + const std::vector<int> lightIds = {3, 4, 6, 8};
  345 + nlohmann::json request = {{"lights", {"3", "4", "6", "8"}}};
  346 + nlohmann::json response = {{"success", {"/scenes/" + id + "/lights", {"3", "4", "6", "8"}}}};
  347 + EXPECT_CALL(
  348 + *handler, PUTJson("/api/" + getBridgeUsername() + "/scenes/" + id, request, getBridgeIp(), getBridgePort()))
  349 + .WillOnce(Return(response));
  350 + expectGetState(id);
  351 + scene.setLightIds(lightIds);
  352 +}
  353 +
  354 +TEST_F(SceneTest, setAppdata)
  355 +{
  356 + const std::string id = "125asav3";
  357 + expectGetState(id);
  358 + Scene scene(id, commands, std::chrono::seconds(0));
  359 + const std::string appdata = "New appdata";
  360 + const int version = 3;
  361 + nlohmann::json request = {{"appdata", {{"version", version}, {"data", appdata}}}};
  362 + nlohmann::json response = {{"success", {"/scenes/" + id + "/appdata/version", version}},
  363 + {"success", {"/scenes/" + id + "/appdata/data", appdata}}};
  364 + EXPECT_CALL(
  365 + *handler, PUTJson("/api/" + getBridgeUsername() + "/scenes/" + id, request, getBridgeIp(), getBridgePort()))
  366 + .WillOnce(Return(response));
  367 + expectGetState(id);
  368 + scene.setAppdata(appdata, version);
  369 +}
  370 +
  371 +TEST_F(SceneTest, setLightStates)
  372 +{
  373 + const std::string id = "125asav3";
  374 + const std::map<int, LightState> lightstates {
  375 + {3, LightStateBuilder().setOn(false).setBrightness(100).setCt(200).create()},
  376 + {5, LightStateBuilder().setOn(true).setBrightness(200).setXY({0.3, 0.2}).create()}};
  377 + nlohmann::json lightstatesJson;
  378 + for (const auto& entry : lightstates)
  379 + {
  380 + lightstatesJson[std::to_string(entry.first)] = entry.second.toJson();
  381 + }
  382 + expectGetState(id);
  383 + Scene scene(id, commands, std::chrono::seconds(0));
  384 + nlohmann::json request = {{"lightstates", lightstatesJson}};
  385 + nlohmann::json response = {{"success", {"/scenes/" + id + "/lights/3/state/on", false}},
  386 + {"success", {"/scenes/" + id + "/lights/3/state/bri", 100}},
  387 + {"success", {"/scenes/" + id + "/lights/3/state/ct", 200}},
  388 + {"success", {"/scenes/" + id + "/lights/5/state/on", true}},
  389 + {"success", {"/scenes/" + id + "/lights/5/state/bri", 200}},
  390 + {"success", {"/scenes/" + id + "/lights/5/state/xy", {0.3, 0.2}}}};
  391 + EXPECT_CALL(
  392 + *handler, PUTJson("/api/" + getBridgeUsername() + "/scenes/" + id, request, getBridgeIp(), getBridgePort()))
  393 + .WillOnce(Return(response));
  394 + expectGetState(id);
  395 + scene.setLightStates(lightstates);
  396 +}
  397 +
  398 +TEST_F(SceneTest, storeCurrentLightState)
  399 +{
  400 + const std::string id = "125asav3";
  401 + expectGetState(id);
  402 + Scene scene(id, commands, std::chrono::seconds(0));
  403 + {
  404 + nlohmann::json request = {{"storelightstate", true}};
  405 + nlohmann::json response = {{"success", {"/scenes/" + id + "/storelightstate", true}}};
  406 + EXPECT_CALL(
  407 + *handler, PUTJson("/api/" + getBridgeUsername() + "/scenes/" + id, request, getBridgeIp(), getBridgePort()))
  408 + .WillOnce(Return(response));
  409 + expectGetState(id);
  410 + scene.storeCurrentLightState();
  411 + }
  412 + {
  413 + const int transitiontime = 3;
  414 + nlohmann::json request = {{"storelightstate", true}, {"transitiontime", 3}};
  415 + nlohmann::json response = {{"success", {"/scenes/" + id + "/storelightstate", true}}};
  416 + EXPECT_CALL(
  417 + *handler, PUTJson("/api/" + getBridgeUsername() + "/scenes/" + id, request, getBridgeIp(), getBridgePort()))
  418 + .WillOnce(Return(response));
  419 + expectGetState(id);
  420 + scene.storeCurrentLightState(transitiontime);
  421 + }
  422 +}
  423 +
  424 +TEST_F(SceneTest, recall)
  425 +{
  426 + const std::string id = "125asav3";
  427 + // LightScene
  428 + {
  429 + sceneState["type"] = "LightScene";
  430 + expectGetState(id);
  431 + nlohmann::json request = {{"scene", id}};
  432 + nlohmann::json response = {{"success", {"/groups/0/action/scene", id}}};
  433 + Scene scene(id, commands, std::chrono::seconds(0));
  434 + EXPECT_CALL(*handler,
  435 + PUTJson("/api/" + getBridgeUsername() + "/groups/0/action", request, getBridgeIp(), getBridgePort()))
  436 + .WillOnce(Return(response));
  437 + scene.recall();
  438 + Mock::VerifyAndClearExpectations(handler.get());
  439 + }
  440 + // GroupScene
  441 + {
  442 + sceneState["type"] = "GroupScene";
  443 + std::string groupId = "3";
  444 + sceneState["group"] = groupId;
  445 + expectGetState(id);
  446 + nlohmann::json request = {{"scene", id}};
  447 + nlohmann::json response = {{"success", {"/groups/" + groupId + "/action/scene", id}}};
  448 + Scene scene(id, commands, std::chrono::seconds(0));
  449 + EXPECT_CALL(*handler,
  450 + PUTJson("/api/" + getBridgeUsername() + "/groups/" + groupId + "/action", request, getBridgeIp(),
  451 + getBridgePort()))
  452 + .WillOnce(Return(response));
  453 + scene.recall();
  454 + }
  455 +}
  456 +
  457 +TEST(CreateScene, setName)
  458 +{
  459 + const std::string name = "New scene";
  460 + const nlohmann::json request = {{"name", name}};
  461 + EXPECT_EQ(request, CreateScene().setName(name).getRequest());
  462 +}
  463 +
  464 +TEST(CreateScene, setGroupId)
  465 +{
  466 + const int groupId = 23;
  467 + const nlohmann::json request = {{"group", "23"}, {"type", "GroupScene"}};
  468 + EXPECT_EQ(request, CreateScene().setGroupId(groupId).getRequest());
  469 + EXPECT_THROW(CreateScene().setGroupId(2).setLightIds({1}), HueException);
  470 +}
  471 +
  472 +TEST(CreateScene, setLightIds)
  473 +{
  474 + const std::vector<int> lightIds = {3, 4, 5, 9};
  475 + const nlohmann::json request = {{"lights", {"3", "4", "5", "9"}}, {"type", "LightScene"}};
  476 + EXPECT_EQ(request, CreateScene().setLightIds(lightIds).getRequest());
  477 + EXPECT_THROW(CreateScene().setLightIds(lightIds).setGroupId(1), HueException);
  478 +}
  479 +
  480 +TEST(CreateScene, setRecycle)
  481 +{
  482 + const nlohmann::json request = {{"recycle", true}};
  483 + EXPECT_EQ(request, CreateScene().setRecycle(true).getRequest());
  484 +}
  485 +
  486 +TEST(CreateScene, setAppdata)
  487 +{
  488 + const std::string data = "testdata";
  489 + const int version = 3;
  490 + const nlohmann::json request = {{"appdata", {{"data", data}, {"version", version}}}};
  491 + EXPECT_EQ(request, CreateScene().setAppdata(data, version).getRequest());
  492 +}
  493 +
  494 +TEST(CreateScene, setLightStates)
  495 +{
  496 + const std::map<int, LightState> lightStates
  497 + = {{1, LightStateBuilder().setOn(true).create()}, {5, LightStateBuilder().setCt(300).create()}};
  498 + const nlohmann::json request = {{"lightstates", {{"1", {{"on", true}}}, {"5", {{"ct", 300}}}}}};
  499 + EXPECT_EQ(request, CreateScene().setLightStates(lightStates).getRequest());
  500 +}
0 501 \ No newline at end of file
... ...