]> git.basschouten.com Git - openhab-addons.git/blob
ec6fe820c24438f31e8602baf7c0309218405cb5
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 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.robonect.internal.handler;
14
15 import static org.junit.Assert.*;
16 import static org.mockito.ArgumentMatchers.eq;
17 import static org.mockito.Mockito.*;
18
19 import java.time.Month;
20 import java.time.ZoneId;
21 import java.time.ZonedDateTime;
22
23 import org.eclipse.jetty.client.HttpClient;
24 import org.junit.Before;
25 import org.junit.Test;
26 import org.mockito.ArgumentCaptor;
27 import org.mockito.Mock;
28 import org.mockito.Mockito;
29 import org.mockito.MockitoAnnotations;
30 import org.openhab.binding.robonect.internal.RobonectBindingConstants;
31 import org.openhab.binding.robonect.internal.RobonectClient;
32 import org.openhab.binding.robonect.internal.model.ErrorEntry;
33 import org.openhab.binding.robonect.internal.model.ErrorList;
34 import org.openhab.binding.robonect.internal.model.MowerInfo;
35 import org.openhab.binding.robonect.internal.model.MowerMode;
36 import org.openhab.binding.robonect.internal.model.MowerStatus;
37 import org.openhab.binding.robonect.internal.model.NextTimer;
38 import org.openhab.binding.robonect.internal.model.Status;
39 import org.openhab.binding.robonect.internal.model.Timer;
40 import org.openhab.binding.robonect.internal.model.Wlan;
41 import org.openhab.core.i18n.TimeZoneProvider;
42 import org.openhab.core.library.types.DateTimeType;
43 import org.openhab.core.library.types.DecimalType;
44 import org.openhab.core.library.types.OnOffType;
45 import org.openhab.core.library.types.QuantityType;
46 import org.openhab.core.library.types.StringType;
47 import org.openhab.core.thing.ChannelUID;
48 import org.openhab.core.thing.Thing;
49 import org.openhab.core.thing.ThingUID;
50 import org.openhab.core.thing.binding.ThingHandlerCallback;
51 import org.openhab.core.types.RefreshType;
52 import org.openhab.core.types.State;
53 import org.openhab.core.types.UnDefType;
54
55 /**
56  * The goal of this class is to test RobonectHandler in isolation.
57  *
58  * @author Marco Meyer - Initial contribution
59  */
60 public class RobonectHandlerTest {
61
62     private RobonectHandler subject;
63
64     @Mock
65     private Thing robonectThingMock;
66
67     @Mock
68     private RobonectClient robonectClientMock;
69
70     @Mock
71     private ThingHandlerCallback callbackMock;
72
73     @Mock
74     private HttpClient httpClientMock;
75
76     @Mock
77     private TimeZoneProvider timezoneProvider;
78
79     @Before
80     public void setUp() {
81         MockitoAnnotations.initMocks(this);
82         subject = new RobonectHandler(robonectThingMock, httpClientMock, timezoneProvider);
83         subject.setCallback(callbackMock);
84         subject.setRobonectClient(robonectClientMock);
85
86         Mockito.when(timezoneProvider.getTimeZone()).thenReturn(ZoneId.of("Europe/Berlin"));
87     }
88
89     @Test
90     public void shouldUpdateNextTimerChannelWithDateTimeState() throws InterruptedException {
91         ArgumentCaptor<State> stateCaptor = ArgumentCaptor.forClass(State.class);
92
93         // given
94         MowerInfo mowerInfo = createSuccessfulMowerInfoResponse();
95         Timer timer = new Timer();
96         timer.setStatus(Timer.TimerMode.ACTIVE);
97         NextTimer nextTimer = new NextTimer();
98         nextTimer.setDate("01.05.2017");
99         nextTimer.setTime("19:00:00");
100         nextTimer.setUnix("1493665200");
101         timer.setNext(nextTimer);
102
103         // when
104         when(robonectClientMock.getMowerInfo()).thenReturn(mowerInfo);
105         when(robonectThingMock.getUID()).thenReturn(new ThingUID("1:2:3"));
106
107         subject.handleCommand(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_TIMER_NEXT_TIMER),
108                 RefreshType.REFRESH);
109
110         // then
111         verify(callbackMock, times(1)).stateUpdated(
112                 eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_TIMER_NEXT_TIMER)),
113                 stateCaptor.capture());
114
115         State value = stateCaptor.getValue();
116         assertTrue(value instanceof DateTimeType);
117
118         ZonedDateTime zdt = ((DateTimeType) value).getZonedDateTime();
119         assertEquals(1, zdt.getDayOfMonth());
120         assertEquals(2017, zdt.getYear());
121         assertEquals(Month.MAY, zdt.getMonth());
122         assertEquals(19, zdt.getHour());
123         assertEquals(0, zdt.getMinute());
124         assertEquals(0, zdt.getSecond());
125     }
126
127     @Test
128     public void shouldUpdateErrorChannelsIfErrorStatusReturned() throws InterruptedException {
129         ArgumentCaptor<State> errorCodeCaptor = ArgumentCaptor.forClass(State.class);
130         ArgumentCaptor<State> errorMessageCaptor = ArgumentCaptor.forClass(State.class);
131         ArgumentCaptor<State> errorDateCaptor = ArgumentCaptor.forClass(State.class);
132
133         // given
134         MowerInfo mowerInfo = createSuccessfulMowerInfoResponse();
135         ErrorEntry error = new ErrorEntry();
136         error.setDate("01.05.2017");
137         error.setTime("19:00:00");
138         error.setUnix("1493665200");
139         error.setErrorCode(Integer.valueOf(22));
140         error.setErrorMessage("Dummy Message");
141         mowerInfo.getStatus().setStatus(MowerStatus.ERROR_STATUS);
142         mowerInfo.setError(error);
143         ErrorList errorList = new ErrorList();
144         errorList.setSuccessful(true);
145
146         // when
147         when(robonectClientMock.getMowerInfo()).thenReturn(mowerInfo);
148         when(robonectClientMock.errorList()).thenReturn(errorList);
149         when(robonectThingMock.getUID()).thenReturn(new ThingUID("1:2:3"));
150
151         subject.handleCommand(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS),
152                 RefreshType.REFRESH);
153
154         // then
155         verify(callbackMock, times(1)).stateUpdated(
156                 eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_ERROR_CODE)),
157                 errorCodeCaptor.capture());
158         verify(callbackMock, times(1)).stateUpdated(
159                 eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_ERROR_MESSAGE)),
160                 errorMessageCaptor.capture());
161         verify(callbackMock, times(1)).stateUpdated(
162                 eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_ERROR_DATE)),
163                 errorDateCaptor.capture());
164
165         State errorDate = errorDateCaptor.getValue();
166         assertTrue(errorDate instanceof DateTimeType);
167
168         ZonedDateTime zdt = ((DateTimeType) errorDate).getZonedDateTime();
169         assertEquals(1, zdt.getDayOfMonth());
170         assertEquals(2017, zdt.getYear());
171         assertEquals(Month.MAY, zdt.getMonth());
172         assertEquals(19, zdt.getHour());
173         assertEquals(0, zdt.getMinute());
174         assertEquals(0, zdt.getSecond());
175
176         State errorMessage = errorMessageCaptor.getValue();
177         assertTrue(errorMessage instanceof StringType);
178         StringType msgStringType = (StringType) errorMessage;
179         assertEquals("Dummy Message", msgStringType.toFullString());
180
181         State errorCode = errorCodeCaptor.getValue();
182         assertTrue(errorCode instanceof DecimalType);
183         DecimalType codeDecimaltype = (DecimalType) errorCode;
184         assertEquals(22, codeDecimaltype.intValue());
185     }
186
187     @Test
188     public void shouldResetErrorStateIfNoErrorInStatusUpdate() throws InterruptedException {
189         ArgumentCaptor<State> errorCodeCaptor = ArgumentCaptor.forClass(State.class);
190         ArgumentCaptor<State> errorMessageCaptor = ArgumentCaptor.forClass(State.class);
191         ArgumentCaptor<State> errorDateCaptor = ArgumentCaptor.forClass(State.class);
192
193         // given
194         MowerInfo mowerInfo = createSuccessfulMowerInfoResponse();
195         mowerInfo.getStatus().setStatus(MowerStatus.MOWING);
196         mowerInfo.setError(null);
197
198         // when
199         when(robonectClientMock.getMowerInfo()).thenReturn(mowerInfo);
200         when(robonectThingMock.getUID()).thenReturn(new ThingUID("1:2:3"));
201
202         subject.handleCommand(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS),
203                 RefreshType.REFRESH);
204
205         // then
206         verify(callbackMock, times(1)).stateUpdated(
207                 eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_ERROR_CODE)),
208                 errorCodeCaptor.capture());
209         verify(callbackMock, times(1)).stateUpdated(
210                 eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_ERROR_MESSAGE)),
211                 errorMessageCaptor.capture());
212         verify(callbackMock, times(1)).stateUpdated(
213                 eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_ERROR_DATE)),
214                 errorDateCaptor.capture());
215
216         assertEquals(errorCodeCaptor.getValue(), UnDefType.UNDEF);
217         assertEquals(errorMessageCaptor.getValue(), UnDefType.UNDEF);
218         assertEquals(errorDateCaptor.getValue(), UnDefType.UNDEF);
219     }
220
221     @Test
222     public void shouldUpdateNumericStateOnMowerStatusRefresh() throws InterruptedException {
223         ArgumentCaptor<State> stateCaptor = ArgumentCaptor.forClass(State.class);
224
225         // given
226         MowerInfo mowerInfo = createSuccessfulMowerInfoResponse();
227         mowerInfo.getStatus().setStatus(MowerStatus.MOWING);
228
229         // when
230         when(robonectClientMock.getMowerInfo()).thenReturn(mowerInfo);
231         when(robonectThingMock.getUID()).thenReturn(new ThingUID("1:2:3"));
232
233         subject.handleCommand(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS),
234                 RefreshType.REFRESH);
235
236         // then
237         verify(callbackMock, times(1)).stateUpdated(
238                 eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS)),
239                 stateCaptor.capture());
240
241         State value = stateCaptor.getValue();
242         assertTrue(value instanceof DecimalType);
243         DecimalType status = (DecimalType) value;
244
245         assertEquals(MowerStatus.MOWING.getStatusCode(), status.intValue());
246     }
247
248     @Test
249     public void shouldUpdateAllChannels() {
250         ArgumentCaptor<State> stateCaptorName = ArgumentCaptor.forClass(State.class);
251         ArgumentCaptor<State> stateCaptorBattery = ArgumentCaptor.forClass(State.class);
252         ArgumentCaptor<State> stateCaptorStatus = ArgumentCaptor.forClass(State.class);
253         ArgumentCaptor<State> stateCaptorDuration = ArgumentCaptor.forClass(State.class);
254         ArgumentCaptor<State> stateCaptorHours = ArgumentCaptor.forClass(State.class);
255         ArgumentCaptor<State> stateCaptorMode = ArgumentCaptor.forClass(State.class);
256         ArgumentCaptor<State> stateCaptorStarted = ArgumentCaptor.forClass(State.class);
257         ArgumentCaptor<State> stateCaptorWlan = ArgumentCaptor.forClass(State.class);
258
259         // given
260         MowerInfo mowerInfo = createSuccessfulMowerInfoResponse();
261         ErrorList errorList = new ErrorList();
262         errorList.setSuccessful(true);
263
264         // when
265         when(robonectClientMock.getMowerInfo()).thenReturn(mowerInfo);
266         when(robonectClientMock.errorList()).thenReturn(errorList);
267         when(robonectThingMock.getUID()).thenReturn(new ThingUID("1:2:3"));
268
269         subject.handleCommand(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS),
270                 RefreshType.REFRESH);
271
272         // then
273         verify(callbackMock, times(1)).stateUpdated(
274                 eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_MOWER_NAME)),
275                 stateCaptorName.capture());
276         verify(callbackMock, times(1)).stateUpdated(
277                 eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS_BATTERY)),
278                 stateCaptorBattery.capture());
279         verify(callbackMock, times(1)).stateUpdated(
280                 eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS)),
281                 stateCaptorStatus.capture());
282         verify(callbackMock, times(1)).stateUpdated(
283                 eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS_DURATION)),
284                 stateCaptorDuration.capture());
285         verify(callbackMock, times(1)).stateUpdated(
286                 eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS_HOURS)),
287                 stateCaptorHours.capture());
288         verify(callbackMock, times(1)).stateUpdated(
289                 eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS_MODE)),
290                 stateCaptorMode.capture());
291         verify(callbackMock, times(1)).stateUpdated(
292                 eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_MOWER_START)),
293                 stateCaptorStarted.capture());
294         verify(callbackMock, times(1)).stateUpdated(
295                 eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_WLAN_SIGNAL)),
296                 stateCaptorWlan.capture());
297
298         assertEquals("Mowy", stateCaptorName.getValue().toFullString());
299         assertEquals(99, ((DecimalType) stateCaptorBattery.getValue()).intValue());
300         assertEquals(4, ((DecimalType) stateCaptorStatus.getValue()).intValue());
301         assertEquals(55, ((QuantityType<?>) stateCaptorDuration.getValue()).intValue());
302         assertEquals(22, ((QuantityType<?>) stateCaptorHours.getValue()).intValue());
303         assertEquals(MowerMode.AUTO.name(), stateCaptorMode.getValue().toFullString());
304         assertEquals(OnOffType.ON, stateCaptorStarted.getValue());
305         assertEquals(-88, ((DecimalType) stateCaptorWlan.getValue()).intValue());
306     }
307
308     private MowerInfo createSuccessfulMowerInfoResponse() {
309         MowerInfo mowerInfo = new MowerInfo();
310         Timer timer = new Timer();
311         timer.setStatus(Timer.TimerMode.ACTIVE);
312         NextTimer nextTimer = new NextTimer();
313         nextTimer.setDate("01.05.2017");
314         nextTimer.setTime("19:00:00");
315         nextTimer.setUnix("1493665200");
316         timer.setNext(nextTimer);
317         mowerInfo.setTimer(timer);
318         Status status = new Status();
319         status.setBattery(99);
320         status.setDuration(55);
321         status.setHours(22);
322         status.setMode(MowerMode.AUTO);
323         status.setStatus(MowerStatus.CHARGING);
324         mowerInfo.setStatus(status);
325         mowerInfo.setName("Mowy");
326         Wlan wlan = new Wlan();
327         wlan.setSignal(-88);
328         mowerInfo.setWlan(wlan);
329         mowerInfo.setSuccessful(true);
330         mowerInfo.getStatus().setStopped(false);
331         return mowerInfo;
332     }
333 }