]> git.basschouten.com Git - openhab-addons.git/blob
6dd50a84e1317de7ceb9b60893050e68afe8c1ae
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 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.deutschebahn.internal;
14
15 import static org.mockito.ArgumentMatchers.*;
16 import static org.mockito.Mockito.*;
17
18 import java.util.ArrayList;
19 import java.util.Calendar;
20 import java.util.GregorianCalendar;
21 import java.util.List;
22
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.junit.jupiter.api.Test;
25 import org.openhab.binding.deutschebahn.internal.timetable.TimeproviderStub;
26 import org.openhab.binding.deutschebahn.internal.timetable.TimetablesV1ApiFactory;
27 import org.openhab.binding.deutschebahn.internal.timetable.TimetablesV1ApiStub;
28 import org.openhab.binding.deutschebahn.internal.timetable.TimetablesV1Impl.HttpCallable;
29 import org.openhab.binding.deutschebahn.internal.timetable.TimetablesV1ImplTestHelper;
30 import org.openhab.binding.deutschebahn.internal.timetable.dto.Event;
31 import org.openhab.binding.deutschebahn.internal.timetable.dto.Timetable;
32 import org.openhab.binding.deutschebahn.internal.timetable.dto.TimetableStop;
33 import org.openhab.core.config.core.Configuration;
34 import org.openhab.core.thing.Bridge;
35 import org.openhab.core.thing.Channel;
36 import org.openhab.core.thing.Thing;
37 import org.openhab.core.thing.ThingStatus;
38 import org.openhab.core.thing.ThingUID;
39 import org.openhab.core.thing.binding.ThingHandlerCallback;
40 import org.openhab.core.types.State;
41 import org.openhab.core.types.UnDefType;
42
43 /**
44  * Tests for {@link DeutscheBahnTimetableHandler}.
45  * 
46  * @author Sönke Küper - initial contribution.
47  */
48 @NonNullByDefault
49 public class DeutscheBahnTimetableHandlerTest implements TimetablesV1ImplTestHelper {
50
51     private static Configuration createConfig() {
52         final Configuration config = new Configuration();
53         config.put("accessToken", "letMeIn");
54         config.put("evaNo", "8000226");
55         config.put("trainFilter", "all");
56         return config;
57     }
58
59     private static Bridge mockBridge() {
60         final Bridge bridge = mock(Bridge.class);
61         when(bridge.getUID()).thenReturn(new ThingUID(DeutscheBahnBindingConstants.TIMETABLE_TYPE, "timetable"));
62         when(bridge.getConfiguration()).thenReturn(createConfig());
63
64         final List<Thing> things = new ArrayList<>();
65         things.add(DeutscheBahnTrainHandlerTest.mockThing(1));
66         things.add(DeutscheBahnTrainHandlerTest.mockThing(2));
67         things.add(DeutscheBahnTrainHandlerTest.mockThing(3));
68         when(things.get(0).getHandler()).thenReturn(mock(DeutscheBahnTrainHandler.class));
69         when(things.get(1).getHandler()).thenReturn(mock(DeutscheBahnTrainHandler.class));
70         when(things.get(2).getHandler()).thenReturn(mock(DeutscheBahnTrainHandler.class));
71
72         when(bridge.getThings()).thenReturn(things);
73
74         return bridge;
75     }
76
77     private DeutscheBahnTimetableHandler createAndInitHandler(final ThingHandlerCallback callback, final Bridge bridge)
78             throws Exception {
79         return createAndInitHandler(callback, bridge, createApiWithTestdata().getApiFactory());
80     }
81
82     private DeutscheBahnTimetableHandler createAndInitHandler( //
83             final ThingHandlerCallback callback, //
84             final Bridge bridge, //
85             final TimetablesV1ApiFactory apiFactory) throws Exception { //
86         final TimeproviderStub timeProvider = new TimeproviderStub();
87         timeProvider.time = new GregorianCalendar(2021, Calendar.AUGUST, 16, 9, 30);
88
89         final DeutscheBahnTimetableHandler handler = new DeutscheBahnTimetableHandler(bridge, apiFactory, timeProvider);
90         handler.setCallback(callback);
91         handler.initialize();
92         return handler;
93     }
94
95     @Test
96     public void testUpdateChannels() throws Exception {
97         final Bridge bridge = mockBridge();
98         final ThingHandlerCallback callback = mock(ThingHandlerCallback.class);
99
100         final DeutscheBahnTimetableHandler handler = createAndInitHandler(callback, bridge);
101
102         try {
103             verify(callback).statusUpdated(eq(bridge), argThat(arg -> arg.getStatus().equals(ThingStatus.UNKNOWN)));
104             verify(callback, timeout(1000)).statusUpdated(eq(bridge),
105                     argThat(arg -> arg.getStatus().equals(ThingStatus.ONLINE)));
106
107             verifyThingUpdated(bridge, 0, "-5296516961807204721-2108160906-5");
108             verifyThingUpdated(bridge, 1, "-8364795265993682073-2108160911-6");
109             verifyThingUpdated(bridge, 2, "-2949440726131702047-2108160858-10");
110         } finally {
111             handler.dispose();
112         }
113     }
114
115     private void verifyThingUpdated(final Bridge bridge, int offset, String stopId) {
116         final Thing train = bridge.getThings().get(offset);
117         final DeutscheBahnTrainHandler childHandler = (DeutscheBahnTrainHandler) train.getHandler();
118         verify(childHandler, timeout(1000))
119                 .updateChannels(argThat((TimetableStop stop) -> stop.getId().equals(stopId)));
120     }
121
122     @Test
123     public void testUpdateTrainsToUndefinedIfNoDataWasProvided() throws Exception {
124         final Bridge bridge = mockBridge();
125         final ThingHandlerCallback callback = mock(ThingHandlerCallback.class);
126
127         final TimetablesV1ApiStub stubWithError = TimetablesV1ApiStub.createWithException();
128
129         final DeutscheBahnTimetableHandler handler = createAndInitHandler(callback, bridge,
130                 (String authToken, HttpCallable httpCallable) -> stubWithError);
131
132         try {
133             verify(callback).statusUpdated(eq(bridge), argThat(arg -> arg.getStatus().equals(ThingStatus.UNKNOWN)));
134             verify(callback, timeout(1000)).statusUpdated(eq(bridge),
135                     argThat(arg -> arg.getStatus().equals(ThingStatus.OFFLINE)));
136
137             verifyChannelsUpdatedToUndef(bridge, 0, callback, UnDefType.UNDEF);
138             verifyChannelsUpdatedToUndef(bridge, 1, callback, UnDefType.UNDEF);
139             verifyChannelsUpdatedToUndef(bridge, 2, callback, UnDefType.UNDEF);
140
141         } finally {
142             handler.dispose();
143         }
144     }
145
146     private static void verifyChannelsUpdatedToUndef(Bridge bridge, int offset, ThingHandlerCallback callback,
147             State expectedState) {
148         final Thing thing = bridge.getThings().get(offset);
149         for (Channel channel : thing.getChannels()) {
150             verify(callback).stateUpdated(eq(channel.getUID()), eq(expectedState));
151         }
152     }
153
154     @Test
155     public void testUpdateTrainsToUndefinedIfNotEnoughDataWasProvided() throws Exception {
156         final Bridge bridge = mockBridge();
157         final ThingHandlerCallback callback = mock(ThingHandlerCallback.class);
158
159         // Bridge contains 3 trains, but Timetable contains only 1 items, so two trains has to be updated to undef
160         // value.
161         final Timetable timetable = new Timetable();
162         TimetableStop stop01 = new TimetableStop();
163         stop01.setId("stop01id");
164         Event dp = new Event();
165         dp.setPt("2108161000");
166         stop01.setDp(dp);
167         timetable.getS().add(stop01);
168
169         final TimetablesV1ApiStub stubWithData = TimetablesV1ApiStub.createWithResult(timetable);
170
171         final DeutscheBahnTimetableHandler handler = createAndInitHandler(callback, bridge,
172                 (String authToken, HttpCallable httpCallable) -> stubWithData);
173
174         try {
175             verify(callback).statusUpdated(eq(bridge), argThat(arg -> arg.getStatus().equals(ThingStatus.UNKNOWN)));
176             verify(callback, timeout(1000)).statusUpdated(eq(bridge),
177                     argThat(arg -> arg.getStatus().equals(ThingStatus.ONLINE)));
178
179             verifyThingUpdated(bridge, 0, stop01.getId());
180             verifyChannelsUpdatedToUndef(bridge, 1, callback, UnDefType.UNDEF);
181             verifyChannelsUpdatedToUndef(bridge, 2, callback, UnDefType.UNDEF);
182
183         } finally {
184             handler.dispose();
185         }
186     }
187 }