]> git.basschouten.com Git - openhab-addons.git/blob
2a4d451fd48df737d4216289e46108e7e70f3c53
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.mqtt.homeassistant.internal.handler;
14
15 import static org.hamcrest.MatcherAssert.assertThat;
16 import static org.mockito.Mockito.any;
17 import static org.mockito.Mockito.eq;
18 import static org.mockito.Mockito.never;
19 import static org.mockito.Mockito.spy;
20 import static org.mockito.Mockito.timeout;
21 import static org.mockito.Mockito.times;
22 import static org.mockito.Mockito.verify;
23 import static org.mockito.Mockito.when;
24
25 import java.util.Arrays;
26 import java.util.List;
27 import java.util.stream.Collectors;
28
29 import org.hamcrest.CoreMatchers;
30 import org.junit.jupiter.api.BeforeEach;
31 import org.junit.jupiter.api.Test;
32 import org.junit.jupiter.api.extension.ExtendWith;
33 import org.mockito.Mock;
34 import org.mockito.junit.jupiter.MockitoExtension;
35 import org.openhab.binding.mqtt.homeassistant.internal.AbstractHomeAssistantTests;
36 import org.openhab.binding.mqtt.homeassistant.internal.HaID;
37 import org.openhab.binding.mqtt.homeassistant.internal.HandlerConfiguration;
38 import org.openhab.binding.mqtt.homeassistant.internal.component.Climate;
39 import org.openhab.binding.mqtt.homeassistant.internal.component.Switch;
40 import org.openhab.core.thing.binding.ThingHandlerCallback;
41
42 /**
43  * Tests for {@link HomeAssistantThingHandler}
44  *
45  * @author Anton Kharuzhy - Initial contribution
46  */
47 @SuppressWarnings({ "ConstantConditions" })
48 @ExtendWith(MockitoExtension.class)
49 public class HomeAssistantThingHandlerTests extends AbstractHomeAssistantTests {
50     private final static int SUBSCRIBE_TIMEOUT = 10000;
51     private final static int ATTRIBUTE_RECEIVE_TIMEOUT = 2000;
52
53     private static final List<String> CONFIG_TOPICS = Arrays.asList("climate/0x847127fffe11dd6a_climate_zigbee2mqtt",
54             "switch/0x847127fffe11dd6a_auto_lock_zigbee2mqtt",
55
56             "sensor/0x1111111111111111_test_sensor_zigbee2mqtt", "camera/0x1111111111111111_test_camera_zigbee2mqtt",
57
58             "cover/0x2222222222222222_test_cover_zigbee2mqtt", "fan/0x2222222222222222_test_fan_zigbee2mqtt",
59             "light/0x2222222222222222_test_light_zigbee2mqtt", "lock/0x2222222222222222_test_lock_zigbee2mqtt");
60
61     private static final List<String> MQTT_TOPICS = CONFIG_TOPICS.stream()
62             .map(AbstractHomeAssistantTests::configTopicToMqtt).collect(Collectors.toList());
63
64     private @Mock ThingHandlerCallback callback;
65     private HomeAssistantThingHandler thingHandler;
66
67     @BeforeEach
68     public void setup() {
69         final var config = haThing.getConfiguration();
70
71         config.put(HandlerConfiguration.PROPERTY_BASETOPIC, HandlerConfiguration.DEFAULT_BASETOPIC);
72         config.put(HandlerConfiguration.PROPERTY_TOPICS, CONFIG_TOPICS);
73
74         when(callback.getBridge(eq(BRIDGE_UID))).thenReturn(bridgeThing);
75
76         thingHandler = new HomeAssistantThingHandler(haThing, channelTypeProvider, transformationServiceProvider,
77                 SUBSCRIBE_TIMEOUT, ATTRIBUTE_RECEIVE_TIMEOUT);
78         thingHandler.setConnection(bridgeConnection);
79         thingHandler.setCallback(callback);
80         thingHandler = spy(thingHandler);
81     }
82
83     @Test
84     public void testInitialize() {
85         // When initialize
86         thingHandler.initialize();
87
88         verify(callback).statusUpdated(eq(haThing), any());
89         // Expect a call to the bridge status changed, the start, the propertiesChanged method
90         verify(thingHandler).bridgeStatusChanged(any());
91         verify(thingHandler, timeout(SUBSCRIBE_TIMEOUT)).start(any());
92
93         // Expect subscription on each topic from config
94         MQTT_TOPICS.forEach(t -> {
95             verify(bridgeConnection, timeout(SUBSCRIBE_TIMEOUT)).subscribe(eq(t), any());
96         });
97
98         verify(thingHandler, never()).componentDiscovered(any(), any());
99         assertThat(haThing.getChannels().size(), CoreMatchers.is(0));
100         // Components discovered after messages in corresponding topics
101         var configTopic = "homeassistant/climate/0x847127fffe11dd6a_climate_zigbee2mqtt/config";
102         thingHandler.discoverComponents.processMessage(configTopic,
103                 getResourceAsByteArray("component/configTS0601ClimateThermostat.json"));
104         verify(thingHandler, times(1)).componentDiscovered(eq(new HaID(configTopic)), any(Climate.class));
105
106         thingHandler.delayedProcessing.forceProcessNow();
107         assertThat(haThing.getChannels().size(), CoreMatchers.is(6));
108         verify(channelTypeProvider, times(6)).setChannelType(any(), any());
109         verify(channelTypeProvider, times(1)).setChannelGroupType(any(), any());
110
111         configTopic = "homeassistant/switch/0x847127fffe11dd6a_auto_lock_zigbee2mqtt/config";
112         thingHandler.discoverComponents.processMessage(configTopic,
113                 getResourceAsByteArray("component/configTS0601AutoLock.json"));
114         verify(thingHandler, times(2)).componentDiscovered(any(), any());
115         verify(thingHandler, times(1)).componentDiscovered(eq(new HaID(configTopic)), any(Switch.class));
116
117         thingHandler.delayedProcessing.forceProcessNow();
118         assertThat(haThing.getChannels().size(), CoreMatchers.is(7));
119         verify(channelTypeProvider, times(7)).setChannelType(any(), any());
120         verify(channelTypeProvider, times(2)).setChannelGroupType(any(), any());
121     }
122
123     @Test
124     public void testDispose() {
125         thingHandler.initialize();
126
127         // Expect subscription on each topic from config
128         CONFIG_TOPICS.forEach(t -> {
129             var fullTopic = HandlerConfiguration.DEFAULT_BASETOPIC + "/" + t + "/config";
130             verify(bridgeConnection, timeout(SUBSCRIBE_TIMEOUT)).subscribe(eq(fullTopic), any());
131         });
132         thingHandler.discoverComponents.processMessage(
133                 "homeassistant/climate/0x847127fffe11dd6a_climate_zigbee2mqtt/config",
134                 getResourceAsByteArray("component/configTS0601ClimateThermostat.json"));
135         thingHandler.discoverComponents.processMessage(
136                 "homeassistant/switch/0x847127fffe11dd6a_auto_lock_zigbee2mqtt/config",
137                 getResourceAsByteArray("component/configTS0601AutoLock.json"));
138         thingHandler.delayedProcessing.forceProcessNow();
139         assertThat(haThing.getChannels().size(), CoreMatchers.is(7));
140         verify(channelTypeProvider, times(7)).setChannelType(any(), any());
141
142         // When dispose
143         thingHandler.dispose();
144
145         // Expect unsubscription on each topic from config
146         MQTT_TOPICS.forEach(t -> {
147             verify(bridgeConnection, timeout(SUBSCRIBE_TIMEOUT)).unsubscribe(eq(t), any());
148         });
149
150         // Expect channel types removed, 6 for climate and 1 for switch
151         verify(channelTypeProvider, times(7)).removeChannelType(any());
152         // Expect channel group types removed, 1 for each component
153         verify(channelTypeProvider, times(2)).removeChannelGroupType(any());
154     }
155 }