2 * Copyright (c) 2010-2020 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.robonect.internal;
15 import static org.junit.Assert.assertEquals;
16 import static org.mockito.Mockito.times;
17 import static org.mockito.Mockito.verify;
18 import static org.mockito.Mockito.when;
20 import java.nio.charset.StandardCharsets;
21 import java.util.concurrent.ExecutionException;
22 import java.util.concurrent.TimeUnit;
23 import java.util.concurrent.TimeoutException;
25 import org.eclipse.jetty.client.HttpClient;
26 import org.eclipse.jetty.client.api.ContentResponse;
27 import org.eclipse.jetty.client.api.Request;
28 import org.eclipse.jetty.http.HttpMethod;
29 import org.junit.Before;
30 import org.junit.Test;
31 import org.mockito.Mock;
32 import org.mockito.MockitoAnnotations;
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.Name;
36 import org.openhab.binding.robonect.internal.model.VersionInfo;
39 * The goal of this class is to test the functionality of the RobonectClient,
40 * by mocking the module responses.
42 * @author Marco Meyer - Initial contribution
44 public class RobonectClientTest {
46 private RobonectClient subject;
49 private HttpClient httpClientMock;
52 private ContentResponse responseMock;
55 private Request requestMock;
59 MockitoAnnotations.initMocks(this);
60 RobonectEndpoint dummyEndPoint = new RobonectEndpoint("123.456.789.123", null, null);
61 subject = new RobonectClient(httpClientMock, dummyEndPoint);
65 public void shouldCallStatusCommand() throws InterruptedException, ExecutionException, TimeoutException {
66 when(httpClientMock.newRequest("http://123.456.789.123/json?cmd=status")).thenReturn(requestMock);
67 when(requestMock.method(HttpMethod.GET)).thenReturn(requestMock);
68 when(requestMock.timeout(30000L, TimeUnit.MILLISECONDS)).thenReturn(requestMock);
69 when(requestMock.send()).thenReturn(responseMock);
70 when(responseMock.getEncoding()).thenReturn("utf8");
71 when(responseMock.getContentAsString()).thenReturn(
72 "{\"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}}");
73 subject.getMowerInfo();
74 verify(httpClientMock, times(1)).newRequest("http://123.456.789.123/json?cmd=status");
78 public void shouldCallStartCommand() throws InterruptedException, ExecutionException, TimeoutException {
79 when(httpClientMock.newRequest("http://123.456.789.123/json?cmd=start")).thenReturn(requestMock);
80 when(requestMock.method(HttpMethod.GET)).thenReturn(requestMock);
81 when(requestMock.timeout(30000L, TimeUnit.MILLISECONDS)).thenReturn(requestMock);
82 when(requestMock.send()).thenReturn(responseMock);
83 when(responseMock.getEncoding()).thenReturn("utf8");
84 when(responseMock.getContentAsString()).thenReturn("{\"successful\": true}");
86 verify(httpClientMock, times(1)).newRequest("http://123.456.789.123/json?cmd=start");
90 public void shouldCallStopCommand() throws InterruptedException, ExecutionException, TimeoutException {
91 when(httpClientMock.newRequest("http://123.456.789.123/json?cmd=stop")).thenReturn(requestMock);
92 when(requestMock.method(HttpMethod.GET)).thenReturn(requestMock);
93 when(requestMock.timeout(30000L, TimeUnit.MILLISECONDS)).thenReturn(requestMock);
94 when(requestMock.send()).thenReturn(responseMock);
95 when(responseMock.getEncoding()).thenReturn("utf8");
96 when(responseMock.getContentAsString()).thenReturn("{\"successful\": true}");
98 verify(httpClientMock, times(1)).newRequest("http://123.456.789.123/json?cmd=stop");
102 public void shouldResetErrors() throws InterruptedException, ExecutionException, TimeoutException {
103 when(httpClientMock.newRequest("http://123.456.789.123/json?cmd=error&reset")).thenReturn(requestMock);
104 when(requestMock.method(HttpMethod.GET)).thenReturn(requestMock);
105 when(requestMock.timeout(30000L, TimeUnit.MILLISECONDS)).thenReturn(requestMock);
106 when(requestMock.send()).thenReturn(responseMock);
107 when(responseMock.getEncoding()).thenReturn("utf8");
108 when(responseMock.getContentAsString()).thenReturn("{\"successful\": true}");
109 subject.resetErrors();
110 verify(httpClientMock, times(1)).newRequest("http://123.456.789.123/json?cmd=error&reset");
114 public void shouldRetrieveName() throws InterruptedException, ExecutionException, TimeoutException {
115 when(httpClientMock.newRequest("http://123.456.789.123/json?cmd=name")).thenReturn(requestMock);
116 when(requestMock.method(HttpMethod.GET)).thenReturn(requestMock);
117 when(requestMock.timeout(30000L, TimeUnit.MILLISECONDS)).thenReturn(requestMock);
118 when(requestMock.send()).thenReturn(responseMock);
119 when(responseMock.getEncoding()).thenReturn("utf8");
120 when(responseMock.getContentAsString()).thenReturn("{\"successful\": true, \"name\": \"hugo\"}");
121 Name name = subject.getName();
122 assertEquals("hugo", name.getName());
123 verify(httpClientMock, times(1)).newRequest("http://123.456.789.123/json?cmd=name");
127 public void shouldSetNewName() throws InterruptedException, ExecutionException, TimeoutException {
128 when(httpClientMock.newRequest("http://123.456.789.123/json?cmd=name&name=MyRobo")).thenReturn(requestMock);
129 when(requestMock.method(HttpMethod.GET)).thenReturn(requestMock);
130 when(requestMock.timeout(30000L, TimeUnit.MILLISECONDS)).thenReturn(requestMock);
131 when(requestMock.send()).thenReturn(responseMock);
132 when(responseMock.getEncoding()).thenReturn("utf8");
133 when(responseMock.getContentAsString()).thenReturn("{\"successful\": true, \"name\": \"MyRobo\"}");
134 Name name = subject.setName("MyRobo");
135 assertEquals("MyRobo", name.getName());
136 verify(httpClientMock, times(1)).newRequest("http://123.456.789.123/json?cmd=name&name=MyRobo");
140 public void shouldListErrors() throws InterruptedException, ExecutionException, TimeoutException {
141 when(httpClientMock.newRequest("http://123.456.789.123/json?cmd=error")).thenReturn(requestMock);
142 when(requestMock.method(HttpMethod.GET)).thenReturn(requestMock);
143 when(requestMock.timeout(30000L, TimeUnit.MILLISECONDS)).thenReturn(requestMock);
144 when(requestMock.send()).thenReturn(responseMock);
145 when(responseMock.getEncoding()).thenReturn("utf8");
146 when(responseMock.getContentAsString()).thenReturn(
147 "{\"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}");
148 ErrorList list = subject.errorList();
149 assertEquals(11, list.getErrors().size());
150 verify(httpClientMock, times(1)).newRequest("http://123.456.789.123/json?cmd=error");
154 public void shouldRetrieveVersionInfo() throws InterruptedException, ExecutionException, TimeoutException {
155 when(httpClientMock.newRequest("http://123.456.789.123/json?cmd=version")).thenReturn(requestMock);
156 when(requestMock.method(HttpMethod.GET)).thenReturn(requestMock);
157 when(requestMock.timeout(30000L, TimeUnit.MILLISECONDS)).thenReturn(requestMock);
158 when(requestMock.send()).thenReturn(responseMock);
159 when(responseMock.getEncoding()).thenReturn("utf8");
160 when(responseMock.getContentAsString()).thenReturn(
161 "{\"robonect\": {\"serial\": \"05D92D32-38355048-43203030\", \"version\": \"V0.9\", \"compiled\": \"2017-03-25 20:10:00\", \"comment\": \"V0.9c\"}, \"successful\": true}");
162 VersionInfo info = subject.getVersionInfo();
163 assertEquals("05D92D32-38355048-43203030", info.getRobonect().getSerial());
164 verify(httpClientMock, times(1)).newRequest("http://123.456.789.123/json?cmd=version");
168 public void shouldHandleProperEncoding() throws InterruptedException, ExecutionException, TimeoutException {
169 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}}"
170 .getBytes(StandardCharsets.ISO_8859_1);
171 when(httpClientMock.newRequest("http://123.456.789.123/json?cmd=status")).thenReturn(requestMock);
172 when(requestMock.method(HttpMethod.GET)).thenReturn(requestMock);
173 when(requestMock.timeout(30000L, TimeUnit.MILLISECONDS)).thenReturn(requestMock);
174 when(requestMock.send()).thenReturn(responseMock);
175 when(responseMock.getEncoding()).thenReturn(null);
176 when(responseMock.getContent()).thenReturn(responseBytesISO88591);
177 MowerInfo info = subject.getMowerInfo();
178 assertEquals("Utanför arbetsområdet", info.getError().getErrorMessage());
179 verify(httpClientMock, times(1)).newRequest("http://123.456.789.123/json?cmd=status");
182 @Test(expected = RobonectCommunicationException.class)
183 public void shouldReceiveErrorAnswerOnInterruptedException()
184 throws InterruptedException, ExecutionException, TimeoutException {
185 when(httpClientMock.newRequest("http://123.456.789.123/json?cmd=status")).thenReturn(requestMock);
186 when(requestMock.method(HttpMethod.GET)).thenReturn(requestMock);
187 when(requestMock.timeout(30000L, TimeUnit.MILLISECONDS)).thenReturn(requestMock);
188 when(requestMock.send()).thenThrow(new InterruptedException("Mock Interrupted Exception"));
189 MowerInfo answer = subject.getMowerInfo();
192 @Test(expected = RobonectCommunicationException.class)
193 public void shouldReceiveErrorAnswerOnExecutionException()
194 throws InterruptedException, ExecutionException, TimeoutException {
195 when(httpClientMock.newRequest("http://123.456.789.123/json?cmd=status")).thenReturn(requestMock);
196 when(requestMock.method(HttpMethod.GET)).thenReturn(requestMock);
197 when(requestMock.timeout(30000L, TimeUnit.MILLISECONDS)).thenReturn(requestMock);
198 when(requestMock.send()).thenThrow(new ExecutionException(new Exception("Mock Exception")));
199 MowerInfo answer = subject.getMowerInfo();
202 @Test(expected = RobonectCommunicationException.class)
203 public void shouldReceiveErrorAnswerOnTimeoutException()
204 throws InterruptedException, ExecutionException, TimeoutException {
205 when(httpClientMock.newRequest("http://123.456.789.123/json?cmd=status")).thenReturn(requestMock);
206 when(requestMock.method(HttpMethod.GET)).thenReturn(requestMock);
207 when(requestMock.timeout(30000L, TimeUnit.MILLISECONDS)).thenReturn(requestMock);
208 when(requestMock.send()).thenThrow(new TimeoutException("Mock Timeout Exception"));
209 MowerInfo answer = subject.getMowerInfo();