/**
\file test_Bridge.cpp
Copyright Notice\n
Copyright (C) 2017 Jan Rogall - developer\n
Copyright (C) 2017 Moritz Wirger - developer\n
This file is part of hueplusplus.
hueplusplus is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
hueplusplus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with hueplusplus. If not, see .
**/
#include
#include
#include
#include
#include "testhelper.h"
#include "hueplusplus/Bridge.h"
#include "hueplusplus/LibConfig.h"
#include "json/json.hpp"
#include "mocks/mock_HttpHandler.h"
using namespace hueplusplus;
class BridgeFinderTest : public ::testing::Test
{
protected:
std::shared_ptr handler;
protected:
BridgeFinderTest() : handler(std::make_shared())
{
using namespace ::testing;
EXPECT_CALL(*handler,
sendMulticast("M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nMAN: "
"\"ssdp:discover\"\r\nMX: 5\r\nST: ssdp:all\r\n\r\n",
"239.255.255.250", 1900, Config::instance().getUPnPTimeout()))
.Times(AtLeast(1))
.WillRepeatedly(Return(getMulticastReply()));
EXPECT_CALL(*handler, GETString("/description.xml", "application/xml", "", "192.168.2.1", getBridgePort()))
.Times(0);
EXPECT_CALL(*handler, GETString("/description.xml", "application/xml", "", getBridgeIp(), getBridgePort()))
.Times(AtLeast(1))
.WillRepeatedly(Return(getBridgeXml()));
}
~BridgeFinderTest() {};
};
TEST_F(BridgeFinderTest, findBridges)
{
BridgeFinder finder(handler);
std::vector bridges = finder.findBridges();
BridgeFinder::BridgeIdentification bridge_to_comp;
bridge_to_comp.ip = getBridgeIp();
bridge_to_comp.port = getBridgePort();
bridge_to_comp.mac = getBridgeMac();
EXPECT_EQ(bridges.size(), 1) << "BridgeFinder found more than one Bridge";
EXPECT_EQ(bridges[0].ip, bridge_to_comp.ip) << "BridgeIdentification ip does not match";
EXPECT_EQ(bridges[0].port, bridge_to_comp.port) << "BridgeIdentification port does not match";
EXPECT_EQ(bridges[0].mac, bridge_to_comp.mac) << "BridgeIdentification mac does not match";
// Test invalid description
EXPECT_CALL(*handler, GETString("/description.xml", "application/xml", "", getBridgeIp(), getBridgePort()))
.Times(1)
.WillOnce(::testing::Return("invalid stuff"));
bridges = finder.findBridges();
EXPECT_TRUE(bridges.empty());
}
TEST_F(BridgeFinderTest, getBridge)
{
using namespace ::testing;
nlohmann::json request {{"devicetype", "HuePlusPlus#User"}, {"generateclientkey", true}};
nlohmann::json errorResponse
= {{{"error", {{"type", 101}, {"address", ""}, {"description", "link button not pressed"}}}}};
EXPECT_CALL(*handler, POSTJson("/api", request, getBridgeIp(), getBridgePort()))
.Times(AtLeast(1))
.WillRepeatedly(Return(errorResponse));
BridgeFinder finder(handler);
std::vector bridges = finder.findBridges();
ASSERT_THROW(finder.getBridge(bridges[0]), HueException);
nlohmann::json successResponse = {{{"success", {{"username", getBridgeUsername()}}}}};
EXPECT_CALL(*handler, POSTJson("/api", request, getBridgeIp(), getBridgePort()))
.Times(1)
.WillOnce(Return(successResponse));
finder = BridgeFinder(handler);
bridges = finder.findBridges();
Bridge test_bridge = finder.getBridge(bridges[0]);
EXPECT_EQ(test_bridge.getBridgeIP(), getBridgeIp()) << "Bridge IP not matching";
EXPECT_EQ(test_bridge.getBridgePort(), getBridgePort()) << "Bridge Port not matching";
EXPECT_EQ(test_bridge.getUsername(), getBridgeUsername()) << "Bridge username not matching";
Mock::VerifyAndClearExpectations(handler.get());
}
TEST_F(BridgeFinderTest, addUsername)
{
BridgeFinder finder(handler);
std::vector bridges = finder.findBridges();
finder.addUsername(bridges[0].mac, getBridgeUsername());
Bridge test_bridge = finder.getBridge(bridges[0]);
EXPECT_EQ(test_bridge.getBridgeIP(), getBridgeIp()) << "Bridge IP not matching";
EXPECT_EQ(test_bridge.getBridgePort(), getBridgePort()) << "Bridge Port not matching";
EXPECT_EQ(test_bridge.getUsername(), getBridgeUsername()) << "Bridge username not matching";
}
TEST_F(BridgeFinderTest, getAllUsernames)
{
BridgeFinder finder(handler);
std::vector bridges = finder.findBridges();
finder.addUsername(bridges[0].mac, getBridgeUsername());
std::map users = finder.getAllUsernames();
EXPECT_EQ(users[getBridgeMac()], getBridgeUsername()) << "Username of MAC:" << getBridgeMac() << "not matching";
}
TEST(Bridge, Constructor)
{
std::shared_ptr handler = std::make_shared();
Bridge test_bridge(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler);
EXPECT_EQ(test_bridge.getBridgeIP(), getBridgeIp()) << "Bridge IP not matching";
EXPECT_EQ(test_bridge.getBridgePort(), getBridgePort()) << "Bridge Port not matching";
EXPECT_EQ(test_bridge.getUsername(), getBridgeUsername()) << "Bridge username not matching";
}
TEST(Bridge, requestUsername)
{
using namespace ::testing;
std::shared_ptr handler = std::make_shared();
nlohmann::json request {{"devicetype", "HuePlusPlus#User"}, {"generateclientkey", true}};
{
nlohmann::json errorResponse
= {{{"error", {{"type", 101}, {"address", ""}, {"description", "link button not pressed"}}}}};
EXPECT_CALL(*handler, POSTJson("/api", request, getBridgeIp(), getBridgePort()))
.Times(AtLeast(1))
.WillRepeatedly(Return(errorResponse));
Bridge test_bridge(getBridgeIp(), getBridgePort(), "", handler);
std::string username = test_bridge.requestUsername();
EXPECT_EQ(username, "") << "Returned username not matching";
EXPECT_EQ(test_bridge.getUsername(), "") << "Bridge username not matching";
}
{
// Other error code causes exception
int otherError = 1;
nlohmann::json exceptionResponse
= {{{"error", {{"type", otherError}, {"address", ""}, {"description", "some error"}}}}};
Bridge testBridge(getBridgeIp(), getBridgePort(), "", handler);
EXPECT_CALL(*handler, POSTJson("/api", request, getBridgeIp(), getBridgePort()))
.WillOnce(Return(exceptionResponse));
try
{
testBridge.requestUsername();
FAIL() << "requestUsername did not throw";
}
catch (const HueAPIResponseException& e)
{
EXPECT_EQ(e.GetErrorNumber(), otherError);
}
catch (const std::exception& e)
{
FAIL() << "wrong exception: " << e.what();
}
}
{
nlohmann::json successResponse = {{{"success", {{"username", getBridgeUsername()}}}}};
EXPECT_CALL(*handler, POSTJson("/api", request, getBridgeIp(), getBridgePort()))
.Times(1)
.WillRepeatedly(Return(successResponse));
Bridge test_bridge(getBridgeIp(), getBridgePort(), "", handler);
nlohmann::json hue_bridge_state {{"lights", {}}};
EXPECT_CALL(
*handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort()))
.Times(1)
.WillOnce(Return(hue_bridge_state));
std::string username = test_bridge.requestUsername();
EXPECT_EQ(username, test_bridge.getUsername()) << "Returned username not matching";
EXPECT_EQ(test_bridge.getBridgeIP(), getBridgeIp()) << "Bridge IP not matching";
EXPECT_EQ(test_bridge.getUsername(), getBridgeUsername()) << "Bridge username not matching";
}
}
TEST(Bridge, setIP)
{
std::shared_ptr handler = std::make_shared();
Bridge test_bridge(getBridgeIp(), getBridgePort(), "", handler);
EXPECT_EQ(test_bridge.getBridgeIP(), getBridgeIp()) << "Bridge IP not matching after initialization";
test_bridge.setIP("192.168.2.112");
EXPECT_EQ(test_bridge.getBridgeIP(), "192.168.2.112") << "Bridge IP not matching after setting it";
}
TEST(Bridge, setPort)
{
std::shared_ptr handler = std::make_shared();
Bridge test_bridge = Bridge(getBridgeIp(), getBridgePort(), "", handler);
EXPECT_EQ(test_bridge.getBridgePort(), getBridgePort()) << "Bridge Port not matching after initialization";
test_bridge.setPort(81);
EXPECT_EQ(test_bridge.getBridgePort(), 81) << "Bridge Port not matching after setting it";
}
TEST(Bridge, getLight)
{
using namespace ::testing;
std::shared_ptr handler = std::make_shared();
EXPECT_CALL(
*handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort()))
.Times(1);
Bridge test_bridge(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler);
// Test exception
ASSERT_THROW(test_bridge.lights().get(1), HueException);
nlohmann::json hue_bridge_state {{"lights",
{{"1",
{{"state",
{{"on", true}, {"bri", 254}, {"ct", 366}, {"alert", "none"}, {"colormode", "ct"},
{"reachable", true}}},
{"swupdate", {{"state", "noupdates"}, {"lastinstall", nullptr}}}, {"type", "Color temperature light"},
{"name", "Hue ambiance lamp 1"}, {"modelid", "LTW001"}, {"manufacturername", "Philips"},
{"uniqueid", "00:00:00:00:00:00:00:00-00"}, {"swversion", "5.50.1.19085"}}}}}};
EXPECT_CALL(
*handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort()))
.Times(1)
.WillOnce(Return(hue_bridge_state));
// Refresh cache
test_bridge = Bridge(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler);
// Test when correct data is sent
Light test_light_1 = test_bridge.lights().get(1);
EXPECT_EQ(test_light_1.getName(), "Hue ambiance lamp 1");
EXPECT_EQ(test_light_1.getColorType(), ColorType::TEMPERATURE);
// Test again to check whether light is returned directly -> interesting for
// code coverage test
test_light_1 = test_bridge.lights().get(1);
EXPECT_EQ(test_light_1.getName(), "Hue ambiance lamp 1");
EXPECT_EQ(test_light_1.getColorType(), ColorType::TEMPERATURE);
}
TEST(Bridge, SharedState)
{
using namespace ::testing;
std::shared_ptr handler = std::make_shared();
nlohmann::json hue_bridge_state {{"lights",
{{"1",
{{"state",
{{"on", true}, {"bri", 254}, {"ct", 366}, {"alert", "none"}, {"colormode", "ct"},
{"reachable", true}}},
{"swupdate", {{"state", "noupdates"}, {"lastinstall", nullptr}}}, {"type", "Color temperature light"},
{"name", "Hue ambiance lamp 1"}, {"modelid", "LTW001"}, {"manufacturername", "Philips"},
{"uniqueid", "00:00:00:00:00:00:00:00-00"}, {"swversion", "5.50.1.19085"}}}}}};
EXPECT_CALL(
*handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort()))
.Times(1)
.WillOnce(Return(hue_bridge_state));
Bridge test_bridge(
getBridgeIp(), getBridgePort(), getBridgeUsername(), handler, "", std::chrono::seconds(10), true);
// Test when correct data is sent
Light test_light_1 = test_bridge.lights().get(1);
Light test_light_copy = test_bridge.lights().get(1);
const std::string newName = "New light name";
EXPECT_CALL(*handler, PUTJson("/api/" + getBridgeUsername() + "/lights/1/name", _, getBridgeIp(), getBridgePort()))
.WillOnce(Return(nlohmann::json({{"success", {{{"/lights/1/name", newName}}}}})));
test_light_1.setName(newName);
hue_bridge_state["lights"]["1"]["name"] = newName;
EXPECT_CALL(*handler,
GETJson("/api/" + getBridgeUsername() + "/lights/1", nlohmann::json::object(), getBridgeIp(), getBridgePort()))
.Times(1)
.WillOnce(Return(hue_bridge_state["lights"]["1"]));
test_light_1.refresh(true);
EXPECT_EQ(newName, test_light_copy.getName());
}
TEST(Bridge, removeLight)
{
using namespace ::testing;
std::shared_ptr handler = std::make_shared();
nlohmann::json hue_bridge_state {{"lights",
{{"1",
{{"state",
{{"on", true}, {"bri", 254}, {"ct", 366}, {"alert", "none"}, {"colormode", "ct"},
{"reachable", true}}},
{"swupdate", {{"state", "noupdates"}, {"lastinstall", nullptr}}}, {"type", "Color temperature light"},
{"name", "Hue ambiance lamp 1"}, {"modelid", "LTW001"}, {"manufacturername", "Philips"},
{"uniqueid", "00:00:00:00:00:00:00:00-00"}, {"swversion", "5.50.1.19085"}}}}}};
EXPECT_CALL(
*handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort()))
.Times(1)
.WillOnce(Return(hue_bridge_state));
Bridge test_bridge(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler);
nlohmann::json return_answer;
return_answer = nlohmann::json::array();
return_answer[0] = nlohmann::json::object();
return_answer[0]["success"] = "/lights/1 deleted";
EXPECT_CALL(*handler,
DELETEJson(
"/api/" + getBridgeUsername() + "/lights/1", nlohmann::json::object(), getBridgeIp(), getBridgePort()))
.Times(2)
.WillOnce(Return(return_answer))
.WillOnce(Return(nlohmann::json()));
// Test when correct data is sent
Light test_light_1 = test_bridge.lights().get(1);
EXPECT_EQ(test_bridge.lights().remove(1), true);
EXPECT_EQ(test_bridge.lights().remove(1), false);
}
TEST(Bridge, getAllLights)
{
using namespace ::testing;
std::shared_ptr handler = std::make_shared();
nlohmann::json hue_bridge_state {{"lights",
{{"1",
{{"state",
{{"on", true}, {"bri", 254}, {"ct", 366}, {"alert", "none"}, {"colormode", "ct"},
{"reachable", true}}},
{"swupdate", {{"state", "noupdates"}, {"lastinstall", nullptr}}}, {"type", "Color temperature light"},
{"name", "Hue ambiance lamp 1"}, {"modelid", "LTW001"}, {"manufacturername", "Philips"},
{"uniqueid", "00:00:00:00:00:00:00:00-00"}, {"swversion", "5.50.1.19085"}}}}}};
EXPECT_CALL(
*handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort()))
.Times(AtLeast(1))
.WillRepeatedly(Return(hue_bridge_state));
Bridge test_bridge(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler);
std::vector test_lights = test_bridge.lights().getAll();
ASSERT_EQ(1, test_lights.size());
EXPECT_EQ(test_lights[0].getName(), "Hue ambiance lamp 1");
EXPECT_EQ(test_lights[0].getColorType(), ColorType::TEMPERATURE);
}
TEST(Bridge, lightExists)
{
using namespace ::testing;
std::shared_ptr handler = std::make_shared();
nlohmann::json hue_bridge_state {{"lights",
{{"1",
{{"state",
{{"on", true}, {"bri", 254}, {"ct", 366}, {"alert", "none"}, {"colormode", "ct"},
{"reachable", true}}},
{"swupdate", {{"state", "noupdates"}, {"lastinstall", nullptr}}}, {"type", "Color temperature light"},
{"name", "Hue ambiance lamp 1"}, {"modelid", "LTW001"}, {"manufacturername", "Philips"},
{"uniqueid", "00:00:00:00:00:00:00:00-00"}, {"swversion", "5.50.1.19085"}}}}}};
EXPECT_CALL(
*handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort()))
.Times(AtLeast(1))
.WillRepeatedly(Return(hue_bridge_state));
Bridge test_bridge(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler);
test_bridge.refresh();
EXPECT_TRUE(Const(test_bridge).lights().exists(1));
EXPECT_FALSE(Const(test_bridge).lights().exists(2));
}
TEST(Bridge, getGroup)
{
using namespace ::testing;
std::shared_ptr handler = std::make_shared();
EXPECT_CALL(
*handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort()))
.Times(1);
Bridge test_bridge(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler);
// Test exception
ASSERT_THROW(test_bridge.groups().get(1), HueException);
nlohmann::json hue_bridge_state {{"groups",
{{"1",
{{"name", "Group 1"}, {"type", "LightGroup"}, {"lights", {"1", "2", "3"}},
{"action",
{{"on", true}, {"bri", 254}, {"ct", 366}, {"alert", "none"}, {"colormode", "ct"}, {"hue", 200},
{"sat", 254}, {"effect", "none"}, {"xy", {0.f, 0.f}}}},
{"state", {{"any_on", true}, {"all_on", true}}}}}}}};
EXPECT_CALL(
*handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort()))
.Times(1)
.WillOnce(Return(hue_bridge_state));
// Refresh cache
test_bridge = Bridge(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler);
// Test when correct data is sent
Group test_group_1 = test_bridge.groups().get(1);
EXPECT_EQ(test_group_1.getName(), "Group 1");
EXPECT_EQ(test_group_1.getType(), "LightGroup");
// Test again to check whether group is returned directly
test_group_1 = test_bridge.groups().get(1);
EXPECT_EQ(test_group_1.getName(), "Group 1");
EXPECT_EQ(test_group_1.getType(), "LightGroup");
}
TEST(Bridge, removeGroup)
{
using namespace ::testing;
std::shared_ptr handler = std::make_shared();
nlohmann::json hue_bridge_state {{"groups",
{{"1",
{{"name", "Group 1"}, {"type", "LightGroup"}, {"lights", {"1", "2", "3"}},
{"action",
{{"on", true}, {"bri", 254}, {"ct", 366}, {"alert", "none"}, {"colormode", "ct"}, {"hue", 200},
{"sat", 254}, {"effect", "none"}, {"xy", {0.f, 0.f}}}},
{"state", {{"any_on", true}, {"all_on", true}}}}}}}};
EXPECT_CALL(
*handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort()))
.Times(1)
.WillOnce(Return(hue_bridge_state));
Bridge test_bridge(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler);
nlohmann::json return_answer;
return_answer = nlohmann::json::array();
return_answer[0] = nlohmann::json::object();
return_answer[0]["success"] = "/groups/1 deleted";
EXPECT_CALL(*handler,
DELETEJson(
"/api/" + getBridgeUsername() + "/groups/1", nlohmann::json::object(), getBridgeIp(), getBridgePort()))
.Times(2)
.WillOnce(Return(return_answer))
.WillOnce(Return(nlohmann::json()));
// Test when correct data is sent
Group test_group_1 = test_bridge.groups().get(1);
EXPECT_EQ(test_bridge.groups().remove(1), true);
EXPECT_EQ(test_bridge.groups().remove(1), false);
}
TEST(Bridge, groupExists)
{
using namespace ::testing;
std::shared_ptr handler = std::make_shared();
nlohmann::json hue_bridge_state {{"groups",
{{"1",
{{"name", "Group 1"}, {"type", "LightGroup"}, {"lights", {"1", "2", "3"}},
{"action",
{{"on", true}, {"bri", 254}, {"ct", 366}, {"alert", "none"}, {"colormode", "ct"}, {"hue", 200},
{"sat", 254}, {"effect", "none"}, {"xy", {0.f, 0.f}}}},
{"state", {{"any_on", true}, {"all_on", true}}}}}}}};
EXPECT_CALL(
*handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort()))
.Times(AtLeast(1))
.WillRepeatedly(Return(hue_bridge_state));
Bridge test_bridge(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler);
test_bridge.refresh();
EXPECT_EQ(true, Const(test_bridge).groups().exists(1));
EXPECT_EQ(false, Const(test_bridge).groups().exists(2));
}
TEST(Bridge, getAllGroups)
{
using namespace ::testing;
std::shared_ptr handler = std::make_shared();
nlohmann::json hue_bridge_state {{"groups",
{{"1",
{{"name", "Group 1"}, {"type", "LightGroup"}, {"lights", {"1", "2", "3"}},
{"action",
{{"on", true}, {"bri", 254}, {"ct", 366}, {"alert", "none"}, {"colormode", "ct"}, {"hue", 200},
{"sat", 254}, {"effect", "none"}, {"xy", {0.f, 0.f}}}},
{"state", {{"any_on", true}, {"all_on", true}}}}}}}};
EXPECT_CALL(
*handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort()))
.Times(AtLeast(1))
.WillRepeatedly(Return(hue_bridge_state));
Bridge test_bridge(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler);
std::vector test_groups = test_bridge.groups().getAll();
ASSERT_EQ(1, test_groups.size());
EXPECT_EQ(test_groups[0].getName(), "Group 1");
EXPECT_EQ(test_groups[0].getType(), "LightGroup");
}
TEST(Bridge, createGroup)
{
using namespace ::testing;
std::shared_ptr handler = std::make_shared();
EXPECT_CALL(
*handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort()))
.Times(AtLeast(1));
Bridge test_bridge(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler);
CreateGroup create = CreateGroup::Room({2, 3}, "Nice room", "LivingRoom");
nlohmann::json request = create.getRequest();
const int id = 4;
nlohmann::json response = {{{"success", {{"id", std::to_string(id)}}}}};
EXPECT_CALL(*handler, POSTJson("/api/" + getBridgeUsername() + "/groups", request, getBridgeIp(), getBridgePort()))
.WillOnce(Return(response));
EXPECT_EQ(id, test_bridge.groups().create(create));
response = {};
EXPECT_CALL(*handler, POSTJson("/api/" + getBridgeUsername() + "/groups", request, getBridgeIp(), getBridgePort()))
.WillOnce(Return(response));
EXPECT_EQ(0, test_bridge.groups().create(create));
}
#define IGNORE_EXCEPTIONS(statement) \
try \
{ \
statement; \
} \
catch (...) \
{ }
TEST(Bridge, instantiateResourceLists)
{
// Instantiate all methods on the resource lists, so that compile errors become visible
using namespace ::testing;
nlohmann::json bridgeState {{"lights", nlohmann::json::object()}, {"groups", nlohmann::json::object()},
{"schedules", nlohmann::json::object()}, {"scenes", nlohmann::json::object()},
{"sensors", nlohmann::json::object()}, {"rules", nlohmann::json::object()}};
std::shared_ptr handler = std::make_shared();
EXPECT_CALL(*handler, GETJson(_, _, getBridgeIp(), getBridgePort())).Times(AnyNumber());
EXPECT_CALL(*handler, POSTJson(_, _, getBridgeIp(), getBridgePort())).Times(AnyNumber());
EXPECT_CALL(*handler, DELETEJson(_, _, getBridgeIp(), getBridgePort())).Times(AnyNumber());
EXPECT_CALL(
*handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort()))
.Times(AtLeast(1))
.WillRepeatedly(Return(bridgeState));
Bridge bridge(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler);
IGNORE_EXCEPTIONS(bridge.lights().getAll());
IGNORE_EXCEPTIONS(bridge.lights().get(1));
IGNORE_EXCEPTIONS(bridge.lights().exists(1));
IGNORE_EXCEPTIONS(bridge.lights().search());
IGNORE_EXCEPTIONS(bridge.lights().getNewDevices());
IGNORE_EXCEPTIONS(bridge.lights().remove(1));
IGNORE_EXCEPTIONS(bridge.groups().getAll());
IGNORE_EXCEPTIONS(bridge.groups().get(1));
IGNORE_EXCEPTIONS(bridge.groups().exists(1));
IGNORE_EXCEPTIONS(bridge.groups().create(CreateGroup::Entertainment({}, "")));
IGNORE_EXCEPTIONS(bridge.groups().remove(1));
IGNORE_EXCEPTIONS(bridge.schedules().getAll());
IGNORE_EXCEPTIONS(bridge.schedules().get(1));
IGNORE_EXCEPTIONS(bridge.schedules().exists(1));
IGNORE_EXCEPTIONS(bridge.schedules().create(CreateSchedule()));
IGNORE_EXCEPTIONS(bridge.schedules().remove(1));
IGNORE_EXCEPTIONS(bridge.scenes().getAll());
IGNORE_EXCEPTIONS(bridge.scenes().get("1"));
IGNORE_EXCEPTIONS(bridge.scenes().exists("1"));
IGNORE_EXCEPTIONS(bridge.scenes().create(CreateScene()));
IGNORE_EXCEPTIONS(bridge.scenes().remove("1"));
IGNORE_EXCEPTIONS(bridge.sensors().getAll());
IGNORE_EXCEPTIONS(bridge.sensors().get(1));
IGNORE_EXCEPTIONS(bridge.sensors().exists(1));
IGNORE_EXCEPTIONS(bridge.sensors().create(CreateSensor("", "", "", "", "", "")));
IGNORE_EXCEPTIONS(bridge.sensors().search());
IGNORE_EXCEPTIONS(bridge.sensors().getNewDevices());
IGNORE_EXCEPTIONS(bridge.sensors().remove(1));
IGNORE_EXCEPTIONS(bridge.rules().getAll());
IGNORE_EXCEPTIONS(bridge.rules().get(1));
IGNORE_EXCEPTIONS(bridge.rules().exists(1));
IGNORE_EXCEPTIONS(bridge.rules().create(CreateRule({}, {})));
IGNORE_EXCEPTIONS(bridge.rules().remove(1));
}