]> git.basschouten.com Git - openhab-addons.git/blob
1f16da6af07128c5521e5bd546a5658f6caa9a32
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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;
14
15 import static org.junit.jupiter.api.Assertions.*;
16 import static org.mockito.Mockito.*;
17
18 import java.nio.charset.StandardCharsets;
19 import java.util.concurrent.ExecutionException;
20 import java.util.concurrent.TimeUnit;
21 import java.util.concurrent.TimeoutException;
22
23 import org.eclipse.jetty.client.HttpClient;
24 import org.eclipse.jetty.client.api.ContentResponse;
25 import org.eclipse.jetty.client.api.Request;
26 import org.eclipse.jetty.http.HttpMethod;
27 import org.junit.jupiter.api.BeforeEach;
28 import org.junit.jupiter.api.Test;
29 import org.junit.jupiter.api.extension.ExtendWith;
30 import org.mockito.Mock;
31 import org.mockito.junit.jupiter.MockitoExtension;
32 import org.openhab.binding.robonect.internal.model.ErrorList;
33 import org.openhab.binding.robonect.internal.model.MowerInfo;
34 import org.openhab.binding.robonect.internal.model.Name;
35 import org.openhab.binding.robonect.internal.model.VersionInfo;
36
37 /**
38  * The goal of this class is to test the functionality of the RobonectClient,
39  * by mocking the module responses.
40  *
41  * @author Marco Meyer - Initial contribution
42  */
43 @ExtendWith(MockitoExtension.class)
44 public class RobonectClientTest {
45
46     private RobonectClient subject;
47
48     private @Mock HttpClient httpClientMock;
49     private @Mock ContentResponse responseMock;
50     private @Mock Request requestMock;
51
52     @BeforeEach
53     public void init() {
54         RobonectEndpoint dummyEndPoint = new RobonectEndpoint("123.456.789.123", null, null);
55         subject = new RobonectClient(httpClientMock, dummyEndPoint);
56     }
57
58     @Test
59     public void shouldCallStatusCommand() throws InterruptedException, ExecutionException, TimeoutException {
60         when(httpClientMock.newRequest("http://123.456.789.123/json?cmd=status")).thenReturn(requestMock);
61         when(requestMock.method(HttpMethod.GET)).thenReturn(requestMock);
62         when(requestMock.timeout(30000L, TimeUnit.MILLISECONDS)).thenReturn(requestMock);
63         when(requestMock.send()).thenReturn(responseMock);
64         when(responseMock.getEncoding()).thenReturn("utf8");
65         when(responseMock.getContentAsString()).thenReturn(
66                 "{\"successful\": true, \"name\": \"Mein Automower\", \"status\": {\"status\": 17, \"stopped\": false, \"duration\": 4359, \"mode\": 0, \"battery\": 100, \"hours\": 29}, \"timer\": {\"status\": 2, \"next\": {\"date\": \"01.05.2017\", \"time\": \"19:00:00\", \"unix\": 1493665200}}, \"wlan\": {\"signal\": -76}}");
67         subject.getMowerInfo();
68         verify(httpClientMock, times(1)).newRequest("http://123.456.789.123/json?cmd=status");
69     }
70
71     @Test
72     public void shouldCallStartCommand() throws InterruptedException, ExecutionException, TimeoutException {
73         when(httpClientMock.newRequest("http://123.456.789.123/json?cmd=start")).thenReturn(requestMock);
74         when(requestMock.method(HttpMethod.GET)).thenReturn(requestMock);
75         when(requestMock.timeout(30000L, TimeUnit.MILLISECONDS)).thenReturn(requestMock);
76         when(requestMock.send()).thenReturn(responseMock);
77         when(responseMock.getEncoding()).thenReturn("utf8");
78         when(responseMock.getContentAsString()).thenReturn("{\"successful\": true}");
79         subject.start();
80         verify(httpClientMock, times(1)).newRequest("http://123.456.789.123/json?cmd=start");
81     }
82
83     @Test
84     public void shouldCallStopCommand() throws InterruptedException, ExecutionException, TimeoutException {
85         when(httpClientMock.newRequest("http://123.456.789.123/json?cmd=stop")).thenReturn(requestMock);
86         when(requestMock.method(HttpMethod.GET)).thenReturn(requestMock);
87         when(requestMock.timeout(30000L, TimeUnit.MILLISECONDS)).thenReturn(requestMock);
88         when(requestMock.send()).thenReturn(responseMock);
89         when(responseMock.getEncoding()).thenReturn("utf8");
90         when(responseMock.getContentAsString()).thenReturn("{\"successful\": true}");
91         subject.stop();
92         verify(httpClientMock, times(1)).newRequest("http://123.456.789.123/json?cmd=stop");
93     }
94
95     @Test
96     public void shouldResetErrors() throws InterruptedException, ExecutionException, TimeoutException {
97         when(httpClientMock.newRequest("http://123.456.789.123/json?cmd=error&reset")).thenReturn(requestMock);
98         when(requestMock.method(HttpMethod.GET)).thenReturn(requestMock);
99         when(requestMock.timeout(30000L, TimeUnit.MILLISECONDS)).thenReturn(requestMock);
100         when(requestMock.send()).thenReturn(responseMock);
101         when(responseMock.getEncoding()).thenReturn("utf8");
102         when(responseMock.getContentAsString()).thenReturn("{\"successful\": true}");
103         subject.resetErrors();
104         verify(httpClientMock, times(1)).newRequest("http://123.456.789.123/json?cmd=error&reset");
105     }
106
107     @Test
108     public void shouldRetrieveName() throws InterruptedException, ExecutionException, TimeoutException {
109         when(httpClientMock.newRequest("http://123.456.789.123/json?cmd=name")).thenReturn(requestMock);
110         when(requestMock.method(HttpMethod.GET)).thenReturn(requestMock);
111         when(requestMock.timeout(30000L, TimeUnit.MILLISECONDS)).thenReturn(requestMock);
112         when(requestMock.send()).thenReturn(responseMock);
113         when(responseMock.getEncoding()).thenReturn("utf8");
114         when(responseMock.getContentAsString()).thenReturn("{\"successful\": true, \"name\": \"hugo\"}");
115         Name name = subject.getName();
116         assertEquals("hugo", name.getName());
117         verify(httpClientMock, times(1)).newRequest("http://123.456.789.123/json?cmd=name");
118     }
119
120     @Test
121     public void shouldSetNewName() throws InterruptedException, ExecutionException, TimeoutException {
122         when(httpClientMock.newRequest("http://123.456.789.123/json?cmd=name&name=MyRobo")).thenReturn(requestMock);
123         when(requestMock.method(HttpMethod.GET)).thenReturn(requestMock);
124         when(requestMock.timeout(30000L, TimeUnit.MILLISECONDS)).thenReturn(requestMock);
125         when(requestMock.send()).thenReturn(responseMock);
126         when(responseMock.getEncoding()).thenReturn("utf8");
127         when(responseMock.getContentAsString()).thenReturn("{\"successful\": true, \"name\": \"MyRobo\"}");
128         Name name = subject.setName("MyRobo");
129         assertEquals("MyRobo", name.getName());
130         verify(httpClientMock, times(1)).newRequest("http://123.456.789.123/json?cmd=name&name=MyRobo");
131     }
132
133     @Test
134     public void shouldListErrors() throws InterruptedException, ExecutionException, TimeoutException {
135         when(httpClientMock.newRequest("http://123.456.789.123/json?cmd=error")).thenReturn(requestMock);
136         when(requestMock.method(HttpMethod.GET)).thenReturn(requestMock);
137         when(requestMock.timeout(30000L, TimeUnit.MILLISECONDS)).thenReturn(requestMock);
138         when(requestMock.send()).thenReturn(responseMock);
139         when(responseMock.getEncoding()).thenReturn("utf8");
140         when(responseMock.getContentAsString()).thenReturn(
141                 "{\"errors\": [{\"error_code\": 33, \"error_message\": \"Grasi ist gekippt\", \"date\": \"04.05.2017\", \"time\": \"22:22:17\", \"unix\": 1493936537}, {\"error_code\": 15, \"error_message\": \"Grasi ist angehoben\", \"date\": \"02.05.2017\", \"time\": \"20:36:43\", \"unix\": 1493757403}, {\"error_code\": 33, \"error_message\": \"Grasi ist gekippt\", \"date\": \"26.04.2017\", \"time\": \"21:31:18\", \"unix\": 1493242278}, {\"error_code\": 13, \"error_message\": \"Kein Antrieb\", \"date\": \"21.04.2017\", \"time\": \"20:17:22\", \"unix\": 1492805842}, {\"error_code\": 10, \"error_message\": \"Grasi ist umgedreht\", \"date\": \"20.04.2017\", \"time\": \"20:14:37\", \"unix\": 1492719277}, {\"error_code\": 1, \"error_message\": \"Grasi hat Arbeitsbereich überschritten\", \"date\": \"12.04.2017\", \"time\": \"19:10:09\", \"unix\": 1492024209}, {\"error_code\": 33, \"error_message\": \"Grasi ist gekippt\", \"date\": \"10.04.2017\", \"time\": \"22:59:35\", \"unix\": 1491865175}, {\"error_code\": 1, \"error_message\": \"Grasi hat Arbeitsbereich überschritten\", \"date\": \"10.04.2017\", \"time\": \"21:21:55\", \"unix\": 1491859315}, {\"error_code\": 33, \"error_message\": \"Grasi ist gekippt\", \"date\": \"10.04.2017\", \"time\": \"20:26:13\", \"unix\": 1491855973}, {\"error_code\": 1, \"error_message\": \"Grasi hat Arbeitsbereich überschritten\", \"date\": \"09.04.2017\", \"time\": \"14:50:36\", \"unix\": 1491749436}, {\"error_code\": 33, \"error_message\": \"Grasi ist gekippt\", \"date\": \"09.04.2017\", \"time\": \"14:23:27\", \"unix\": 1491747807}], \"successful\": true}");
142         ErrorList list = subject.errorList();
143         assertEquals(11, list.getErrors().size());
144         verify(httpClientMock, times(1)).newRequest("http://123.456.789.123/json?cmd=error");
145     }
146
147     @Test
148     public void shouldRetrieveVersionInfo() throws InterruptedException, ExecutionException, TimeoutException {
149         when(httpClientMock.newRequest("http://123.456.789.123/json?cmd=version")).thenReturn(requestMock);
150         when(requestMock.method(HttpMethod.GET)).thenReturn(requestMock);
151         when(requestMock.timeout(30000L, TimeUnit.MILLISECONDS)).thenReturn(requestMock);
152         when(requestMock.send()).thenReturn(responseMock);
153         when(responseMock.getEncoding()).thenReturn("utf8");
154         when(responseMock.getContentAsString()).thenReturn(
155                 "{\"robonect\": {\"serial\": \"05D92D32-38355048-43203030\", \"version\": \"V0.9\", \"compiled\": \"2017-03-25 20:10:00\", \"comment\": \"V0.9c\"}, \"successful\": true}");
156         VersionInfo info = subject.getVersionInfo();
157         assertEquals("05D92D32-38355048-43203030", info.getRobonect().getSerial());
158         verify(httpClientMock, times(1)).newRequest("http://123.456.789.123/json?cmd=version");
159     }
160
161     @Test
162     public void shouldHandleProperEncoding() throws InterruptedException, ExecutionException, TimeoutException {
163         byte[] responseBytesISO88591 = "{\"successful\": true, \"name\": \"Mein Automower\", \"status\": {\"status\": 7, \"stopped\": true, \"duration\": 192, \"mode\": 1, \"battery\": 95, \"hours\": 41}, \"timer\": {\"status\": 2}, \"error\" : {\"error_code\": 15, \"error_message\": \"Utanför arbetsområdet\", \"date\": \"02.05.2017\", \"time\": \"20:36:43\", \"unix\": 1493757403}, \"wlan\": {\"signal\": -75}}"
164                 .getBytes(StandardCharsets.ISO_8859_1);
165         when(httpClientMock.newRequest("http://123.456.789.123/json?cmd=status")).thenReturn(requestMock);
166         when(requestMock.method(HttpMethod.GET)).thenReturn(requestMock);
167         when(requestMock.timeout(30000L, TimeUnit.MILLISECONDS)).thenReturn(requestMock);
168         when(requestMock.send()).thenReturn(responseMock);
169         when(responseMock.getEncoding()).thenReturn(null);
170         when(responseMock.getContent()).thenReturn(responseBytesISO88591);
171         MowerInfo info = subject.getMowerInfo();
172         assertEquals("Utanför arbetsområdet", info.getError().getErrorMessage());
173         verify(httpClientMock, times(1)).newRequest("http://123.456.789.123/json?cmd=status");
174     }
175
176     @Test
177     public void shouldReceiveErrorAnswerOnInterruptedException()
178             throws InterruptedException, ExecutionException, TimeoutException {
179         when(httpClientMock.newRequest("http://123.456.789.123/json?cmd=status")).thenReturn(requestMock);
180         when(requestMock.method(HttpMethod.GET)).thenReturn(requestMock);
181         when(requestMock.timeout(30000L, TimeUnit.MILLISECONDS)).thenReturn(requestMock);
182         when(requestMock.send()).thenThrow(new InterruptedException("Mock Interrupted Exception"));
183         assertThrows(RobonectCommunicationException.class, () -> subject.getMowerInfo());
184     }
185
186     @Test
187     public void shouldReceiveErrorAnswerOnExecutionException()
188             throws InterruptedException, ExecutionException, TimeoutException {
189         when(httpClientMock.newRequest("http://123.456.789.123/json?cmd=status")).thenReturn(requestMock);
190         when(requestMock.method(HttpMethod.GET)).thenReturn(requestMock);
191         when(requestMock.timeout(30000L, TimeUnit.MILLISECONDS)).thenReturn(requestMock);
192         when(requestMock.send()).thenThrow(new ExecutionException(new Exception("Mock Exception")));
193         assertThrows(RobonectCommunicationException.class, () -> subject.getMowerInfo());
194     }
195
196     @Test
197     public void shouldReceiveErrorAnswerOnTimeoutException()
198             throws InterruptedException, ExecutionException, TimeoutException {
199         when(httpClientMock.newRequest("http://123.456.789.123/json?cmd=status")).thenReturn(requestMock);
200         when(requestMock.method(HttpMethod.GET)).thenReturn(requestMock);
201         when(requestMock.timeout(30000L, TimeUnit.MILLISECONDS)).thenReturn(requestMock);
202         when(requestMock.send()).thenThrow(new TimeoutException("Mock Timeout Exception"));
203         assertThrows(RobonectCommunicationException.class, () -> subject.getMowerInfo());
204     }
205 }