2 * Copyright (c) 2010-2024 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.pegelonline.internal.handler;
15 import static org.junit.jupiter.api.Assertions.*;
16 import static org.mockito.Mockito.*;
17 import static org.openhab.binding.pegelonline.internal.PegelOnlineBindingConstants.*;
19 import java.util.concurrent.ExecutionException;
20 import java.util.concurrent.TimeoutException;
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.eclipse.jetty.client.HttpClient;
24 import org.eclipse.jetty.client.api.ContentResponse;
25 import org.junit.jupiter.api.Test;
26 import org.openhab.binding.pegelonline.internal.config.PegelOnlineConfiguration;
27 import org.openhab.binding.pegelonline.internal.dto.Measure;
28 import org.openhab.binding.pegelonline.internal.dto.Station;
29 import org.openhab.binding.pegelonline.internal.util.FileReader;
30 import org.openhab.binding.pegelonline.internal.utils.Utils;
31 import org.openhab.core.config.core.Configuration;
32 import org.openhab.core.library.types.DecimalType;
33 import org.openhab.core.thing.ThingStatus;
34 import org.openhab.core.thing.ThingStatusDetail;
35 import org.openhab.core.thing.ThingStatusInfo;
36 import org.openhab.core.thing.ThingTypeUID;
37 import org.openhab.core.thing.internal.ThingImpl;
38 import org.openhab.core.types.State;
41 * The {@link PegelTest} Test helper utils
43 * @author Bernd Weymann - Initial contribution
47 public static final String TEST_STATION_UUID = "1ebd0f94-cc06-445c-8e73-43fe2b8c72dc";
50 void testConfigurationValidations() {
51 PegelOnlineConfiguration config = new PegelOnlineConfiguration();
52 assertFalse(config.uuidCheck(), config.uuid);
54 assertFalse(config.uuidCheck(), config.uuid);
55 config.uuid = "abc d";
56 assertFalse(config.uuidCheck(), config.uuid);
57 config.uuid = "1234567a-abc1-efd9-cdf3-0123456789ab";
58 assertTrue(config.uuidCheck(), config.uuid);
59 assertTrue(config.warningCheck(), "Warnings");
61 String content = FileReader.readFileInString("src/test/resources/stations.json");
62 Station[] stationArray = GSON.fromJson(content, Station[].class);
63 assertNotNull(stationArray);
64 for (Station station : stationArray) {
65 config.uuid = station.uuid;
66 assertTrue(config.uuidCheck(), config.uuid);
71 void testNameConversion() {
72 String stationName = "EIDER-SPERRWERK BP";
73 String conversion = Utils.toTitleCase(stationName);
74 assertEquals("Eider-Sperrwerk Bp", conversion, "Station Name");
76 String content = FileReader.readFileInString("src/test/resources/stations.json");
77 Station[] stationArray = GSON.fromJson(content, Station[].class);
78 assertNotNull(stationArray);
79 for (Station station : stationArray) {
80 assertTrue(Character.isUpperCase(Utils.toTitleCase(station.shortname).charAt(0)),
81 "First Character Upper Case");
82 assertTrue(Character.isUpperCase(Utils.toTitleCase(station.water.shortname).charAt(0)),
83 "First Character Upper Case");
89 // Frankfurt Main: 50.117461111005, 8.639069127891485
90 String content = FileReader.readFileInString("src/test/resources/stations.json");
91 Station[] stationArray = GSON.fromJson(content, Station[].class);
92 assertNotNull(stationArray);
94 for (Station station : stationArray) {
95 double distance = Utils.calculateDistance(50.117461111005, 8.639069127891485, station.latitude,
99 assertTrue(station.water.shortname.equals("RHEIN") || station.water.shortname.equals("MAIN"),
103 assertEquals(11, hitCounter, "Meassurement Stations around FRA");
107 void testMeasureObject() {
108 String content = FileReader.readFileInString("src/test/resources/measure.json");
109 Measure measure = GSON.fromJson(content, Measure.class);
110 if (measure != null) {
111 assertEquals("2021-08-01T16:00:00+02:00", measure.timestamp, "Timestamp");
112 assertEquals(238, measure.value, "Level");
113 assertEquals(-1, measure.trend, "Trend");
120 void test404Status() {
121 String stationContent = FileReader.readFileInString("src/test/resources/stations.json");
122 ContentResponse stationResponse = mock(ContentResponse.class);
123 when(stationResponse.getStatus()).thenReturn(200);
124 when(stationResponse.getContentAsString()).thenReturn(stationContent);
126 String content = "{}";
127 ContentResponse measureResponse = mock(ContentResponse.class);
128 when(measureResponse.getStatus()).thenReturn(404);
129 when(measureResponse.getContentAsString()).thenReturn(content);
131 HttpClient httpClientMock = mock(HttpClient.class);
133 when(httpClientMock.GET(STATIONS_URI + "/" + TEST_STATION_UUID + "/W/currentmeasurement.json"))
134 .thenReturn(measureResponse);
135 when(httpClientMock.GET(STATIONS_URI)).thenReturn(stationResponse);
136 } catch (InterruptedException | ExecutionException | TimeoutException e) {
140 CallbackMock callback = new CallbackMock();
141 ThingImpl ti = new ThingImpl(new ThingTypeUID("pegelonline:station"), "test");
142 PegelOnlineHandler handler = new PegelOnlineHandler(ti, httpClientMock);
143 Configuration config = new Configuration();
144 config.put("uuid", TEST_STATION_UUID);
145 handler.setCallback(callback);
146 handler.updateConfiguration(config);
147 handler.initialize();
148 handler.performMeasurement();
149 ThingStatusInfo tsi = callback.getThingStatus();
151 assertEquals(ThingStatus.OFFLINE, tsi.getStatus(), "Status");
152 assertEquals(ThingStatusDetail.CONFIGURATION_ERROR, tsi.getStatusDetail(), "Detail");
153 String description = tsi.getDescription();
154 assertNotNull(description);
155 assertEquals("@text/pegelonline.handler.status.uuid-not-found [\"" + TEST_STATION_UUID + "\"]", description,
160 void testWrongContent() {
161 String stationContent = FileReader.readFileInString("src/test/resources/stations.json");
162 ContentResponse stationResponse = mock(ContentResponse.class);
163 when(stationResponse.getStatus()).thenReturn(200);
164 when(stationResponse.getContentAsString()).thenReturn(stationContent);
166 String content = "{}";
167 ContentResponse measureResponse = mock(ContentResponse.class);
168 when(measureResponse.getStatus()).thenReturn(200);
169 when(measureResponse.getContentAsString()).thenReturn(content);
171 HttpClient httpClientMock = mock(HttpClient.class);
173 when(httpClientMock.GET(STATIONS_URI + "/" + TEST_STATION_UUID + "/W/currentmeasurement.json"))
174 .thenReturn(measureResponse);
175 when(httpClientMock.GET(STATIONS_URI)).thenReturn(stationResponse);
176 } catch (InterruptedException | ExecutionException | TimeoutException e) {
180 CallbackMock callback = new CallbackMock();
181 ThingImpl ti = new ThingImpl(new ThingTypeUID("pegelonline:station"), "test");
182 PegelOnlineHandler handler = new PegelOnlineHandler(ti, httpClientMock);
183 Configuration config = new Configuration();
184 config.put("uuid", TEST_STATION_UUID);
185 handler.setCallback(callback);
186 handler.updateConfiguration(config);
187 handler.initialize();
188 handler.performMeasurement();
189 ThingStatusInfo tsi = callback.getThingStatus();
191 assertEquals(ThingStatus.OFFLINE, tsi.getStatus(), "Status");
192 assertEquals(ThingStatusDetail.COMMUNICATION_ERROR, tsi.getStatusDetail(), "Detail");
193 String description = tsi.getDescription();
194 assertNotNull(description);
195 assertEquals("@text/pegelonline.handler.status.json-error [\"{}\"]", description, "Description");
199 public void testWrongConfiguration() {
200 CallbackMock callback = new CallbackMock();
201 PegelOnlineHandler handler = getConfiguredHandler(callback, 99);
203 Configuration config = new Configuration();
204 config.put("uuid", " ");
205 handler.updateConfiguration(new Configuration(config));
206 handler.initialize();
208 ThingStatusInfo tsi = callback.getThingStatus();
210 assertEquals(ThingStatus.OFFLINE, tsi.getStatus(), "Status");
211 assertEquals(ThingStatusDetail.CONFIGURATION_ERROR, tsi.getStatusDetail(), "Detail");
212 String description = tsi.getDescription();
213 assertNotNull(description);
214 assertEquals("@text/pegelonline.handler.status.uuid [\" \"]", description, "Description");
218 public void testInconsistentLevels() {
219 CallbackMock callback = new CallbackMock();
220 PegelOnlineHandler handler = getConfiguredHandler(callback, 99);
222 Configuration config = new Configuration();
223 config.put("uuid", TEST_STATION_UUID);
224 config.put("warningLevel1", 100);
225 config.put("warningLevel2", 200);
226 config.put("warningLevel3", 150);
227 handler.updateConfiguration(config);
228 handler.initialize();
230 ThingStatusInfo tsi = callback.getThingStatus();
232 assertEquals(ThingStatus.OFFLINE, tsi.getStatus(), "Status");
233 assertEquals(ThingStatusDetail.CONFIGURATION_ERROR, tsi.getStatusDetail(), "Detail");
234 String description = tsi.getDescription();
235 assertNotNull(description);
236 assertEquals("@text/pegelonline.handler.status.warning", description, "Description");
239 config = new Configuration();
240 config.put("uuid", TEST_STATION_UUID);
241 config.put("warningLevel1", 100);
242 config.put("warningLevel2", 200);
243 config.put("warningLevel3", 300);
244 config.put("hqExtreme", 600);
245 handler.updateConfiguration(new Configuration(config));
246 handler.initialize();
248 tsi = callback.getThingStatus();
250 assertEquals(ThingStatus.UNKNOWN, tsi.getStatus(), "Status");
251 assertEquals(ThingStatusDetail.NONE, tsi.getStatusDetail(), "Detail");
252 description = tsi.getDescription();
253 assertNotNull(description);
254 assertEquals("@text/pegelonline.handler.status.wait-feedback", description, "Description");
257 config = new Configuration();
258 config.put("uuid", TEST_STATION_UUID);
259 config.put("warningLevel1", 100);
260 config.put("warningLevel2", 200);
261 config.put("warningLevel3", 300);
262 config.put("hq10", 100);
263 config.put("hq100", 200);
264 config.put("hqExtreme", 150);
265 handler.updateConfiguration(new Configuration(config));
266 handler.initialize();
268 tsi = callback.getThingStatus();
270 assertEquals(ThingStatus.OFFLINE, tsi.getStatus(), "Status");
271 assertEquals(ThingStatusDetail.CONFIGURATION_ERROR, tsi.getStatusDetail(), "Detail");
272 description = tsi.getDescription();
273 assertNotNull(description);
274 assertEquals("@text/pegelonline.handler.status.warning", description, "Description");
278 public void testWrongResponse() {
279 String measureContent = "{}";
280 ContentResponse measureResponse = mock(ContentResponse.class);
281 when(measureResponse.getStatus()).thenReturn(500);
282 when(measureResponse.getContentAsString()).thenReturn(measureContent);
283 HttpClient httpClientMock = mock(HttpClient.class);
285 when(httpClientMock.GET(STATIONS_URI + "/" + TEST_STATION_UUID + "/W/currentmeasurement.json"))
286 .thenReturn(measureResponse);
287 } catch (InterruptedException | ExecutionException | TimeoutException e) {
291 CallbackMock callback = new CallbackMock();
292 ThingImpl ti = new ThingImpl(new ThingTypeUID("pegelonline:station"), "test");
293 PegelOnlineHandler handler = new PegelOnlineHandler(ti, httpClientMock);
294 Configuration config = new Configuration();
295 config.put("uuid", TEST_STATION_UUID);
296 handler.setCallback(callback);
297 handler.updateConfiguration(config);
298 handler.initialize();
299 handler.performMeasurement();
300 ThingStatusInfo tsi = callback.getThingStatus();
302 assertEquals(ThingStatus.OFFLINE, tsi.getStatus(), "Status");
303 assertEquals(ThingStatusDetail.COMMUNICATION_ERROR, tsi.getStatusDetail(), "Detail");
304 String description = tsi.getDescription();
305 assertNotNull(description);
306 assertEquals("@text/pegelonline.handler.status.http-status [\"500\"]", description, "Description");
310 public void testWarnings() {
311 CallbackMock callback = new CallbackMock();
312 PegelOnlineHandler handler = getConfiguredHandler(callback, 99);
313 handler.initialize();
314 handler.performMeasurement();
315 State state = callback.getState("pegelonline:station:test:warning");
316 assertTrue(state instanceof DecimalType);
317 assertEquals(NO_WARNING, ((DecimalType) state).intValue(), "No warning");
319 handler = getConfiguredHandler(callback, 100);
320 handler.initialize();
321 handler.performMeasurement();
322 state = callback.getState("pegelonline:station:test:warning");
323 assertTrue(state instanceof DecimalType);
324 assertEquals(WARN_LEVEL_1, ((DecimalType) state).intValue(), "Warn Level 1");
326 handler = getConfiguredHandler(callback, 299);
327 handler.initialize();
328 handler.performMeasurement();
329 state = callback.getState("pegelonline:station:test:warning");
330 assertTrue(state instanceof DecimalType);
331 assertEquals(WARN_LEVEL_2, ((DecimalType) state).intValue(), "Warn Level 2");
333 handler = getConfiguredHandler(callback, 1000);
334 handler.initialize();
335 handler.performMeasurement();
336 state = callback.getState("pegelonline:station:test:warning");
337 assertTrue(state instanceof DecimalType);
338 assertEquals(HQ_EXTREME, ((DecimalType) state).intValue(), "HQ extreme");
341 private PegelOnlineHandler getConfiguredHandler(CallbackMock callback, int levelSimulation) {
342 String stationContent = FileReader.readFileInString("src/test/resources/stations.json");
343 ContentResponse stationResponse = mock(ContentResponse.class);
344 when(stationResponse.getStatus()).thenReturn(200);
345 when(stationResponse.getContentAsString()).thenReturn(stationContent);
347 String measureContent = "{ \"timestamp\": \"2021-08-01T16:00:00+02:00\", \"value\": " + levelSimulation
348 + ", \"trend\": -1}";
349 ContentResponse measureResponse = mock(ContentResponse.class);
350 when(measureResponse.getStatus()).thenReturn(200);
351 when(measureResponse.getContentAsString()).thenReturn(measureContent);
352 HttpClient httpClientMock = mock(HttpClient.class);
354 when(httpClientMock.GET(STATIONS_URI + "/" + TEST_STATION_UUID + "/W/currentmeasurement.json"))
355 .thenReturn(measureResponse);
356 when(httpClientMock.GET(STATIONS_URI)).thenReturn(stationResponse);
357 } catch (InterruptedException | ExecutionException | TimeoutException e) {
361 ThingImpl ti = new ThingImpl(new ThingTypeUID("pegelonline:station"), "test");
362 PegelOnlineHandler handler = new PegelOnlineHandler(ti, httpClientMock);
363 Configuration config = new Configuration();
364 config.put("uuid", TEST_STATION_UUID);
365 config.put("warningLevel1", 100);
366 config.put("warningLevel2", 200);
367 config.put("warningLevel3", 300);
368 config.put("hq10", 400);
369 config.put("hq100", 500);
370 config.put("hqExtreme", 600);
371 handler.setCallback(callback);
372 handler.updateConfiguration(config);