2 * Copyright (c) 2010-2022 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.deutschebahn.internal;
15 import static org.mockito.ArgumentMatchers.*;
16 import static org.mockito.Mockito.*;
18 import java.util.ArrayList;
19 import java.util.Calendar;
20 import java.util.GregorianCalendar;
21 import java.util.List;
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.junit.jupiter.api.Disabled;
25 import org.junit.jupiter.api.Test;
26 import org.openhab.binding.deutschebahn.internal.timetable.TimeproviderStub;
27 import org.openhab.binding.deutschebahn.internal.timetable.TimetablesV1ApiFactory;
28 import org.openhab.binding.deutschebahn.internal.timetable.TimetablesV1ApiStub;
29 import org.openhab.binding.deutschebahn.internal.timetable.TimetablesV1Impl.HttpCallable;
30 import org.openhab.binding.deutschebahn.internal.timetable.TimetablesV1ImplTestHelper;
31 import org.openhab.binding.deutschebahn.internal.timetable.dto.Event;
32 import org.openhab.binding.deutschebahn.internal.timetable.dto.Timetable;
33 import org.openhab.binding.deutschebahn.internal.timetable.dto.TimetableStop;
34 import org.openhab.core.config.core.Configuration;
35 import org.openhab.core.thing.Bridge;
36 import org.openhab.core.thing.Channel;
37 import org.openhab.core.thing.Thing;
38 import org.openhab.core.thing.ThingStatus;
39 import org.openhab.core.thing.ThingUID;
40 import org.openhab.core.thing.binding.ThingHandlerCallback;
41 import org.openhab.core.types.State;
42 import org.openhab.core.types.UnDefType;
45 * Tests for {@link DeutscheBahnTimetableHandler}.
47 * @author Sönke Küper - initial contribution.
50 @Disabled("https://github.com/openhab/openhab-addons/issues/12235")
51 public class DeutscheBahnTimetableHandlerTest implements TimetablesV1ImplTestHelper {
53 private static Configuration createConfig() {
54 final Configuration config = new Configuration();
55 config.put("accessToken", "letMeIn");
56 config.put("evaNo", "8000226");
57 config.put("trainFilter", "all");
61 private static Bridge mockBridge() {
62 final Bridge bridge = mock(Bridge.class);
63 when(bridge.getUID()).thenReturn(new ThingUID(DeutscheBahnBindingConstants.TIMETABLE_TYPE, "timetable"));
64 when(bridge.getConfiguration()).thenReturn(createConfig());
66 final List<Thing> things = new ArrayList<>();
67 things.add(DeutscheBahnTrainHandlerTest.mockThing(1));
68 things.add(DeutscheBahnTrainHandlerTest.mockThing(2));
69 things.add(DeutscheBahnTrainHandlerTest.mockThing(3));
70 when(things.get(0).getHandler()).thenReturn(mock(DeutscheBahnTrainHandler.class));
71 when(things.get(1).getHandler()).thenReturn(mock(DeutscheBahnTrainHandler.class));
72 when(things.get(2).getHandler()).thenReturn(mock(DeutscheBahnTrainHandler.class));
74 when(bridge.getThings()).thenReturn(things);
79 private DeutscheBahnTimetableHandler createAndInitHandler(final ThingHandlerCallback callback, final Bridge bridge)
81 return createAndInitHandler(callback, bridge, createApiWithTestdata().getApiFactory());
84 private DeutscheBahnTimetableHandler createAndInitHandler( //
85 final ThingHandlerCallback callback, //
86 final Bridge bridge, //
87 final TimetablesV1ApiFactory apiFactory) throws Exception { //
88 final TimeproviderStub timeProvider = new TimeproviderStub();
89 timeProvider.time = new GregorianCalendar(2021, Calendar.AUGUST, 16, 9, 30);
91 final DeutscheBahnTimetableHandler handler = new DeutscheBahnTimetableHandler(bridge, apiFactory, timeProvider);
92 handler.setCallback(callback);
98 public void testUpdateChannels() throws Exception {
99 final Bridge bridge = mockBridge();
100 final ThingHandlerCallback callback = mock(ThingHandlerCallback.class);
102 final DeutscheBahnTimetableHandler handler = createAndInitHandler(callback, bridge);
105 verify(callback).statusUpdated(eq(bridge), argThat(arg -> arg.getStatus().equals(ThingStatus.UNKNOWN)));
106 verify(callback, timeout(1000)).statusUpdated(eq(bridge),
107 argThat(arg -> arg.getStatus().equals(ThingStatus.ONLINE)));
109 verifyThingUpdated(bridge, 0, "-5296516961807204721-2108160906-5");
110 verifyThingUpdated(bridge, 1, "-8364795265993682073-2108160911-6");
111 verifyThingUpdated(bridge, 2, "-2949440726131702047-2108160858-10");
117 private void verifyThingUpdated(final Bridge bridge, int offset, String stopId) {
118 final Thing train = bridge.getThings().get(offset);
119 final DeutscheBahnTrainHandler childHandler = (DeutscheBahnTrainHandler) train.getHandler();
120 verify(childHandler, timeout(1000))
121 .updateChannels(argThat((TimetableStop stop) -> stop.getId().equals(stopId)));
125 public void testUpdateTrainsToUndefinedIfNoDataWasProvided() throws Exception {
126 final Bridge bridge = mockBridge();
127 final ThingHandlerCallback callback = mock(ThingHandlerCallback.class);
129 final TimetablesV1ApiStub stubWithError = TimetablesV1ApiStub.createWithException();
131 final DeutscheBahnTimetableHandler handler = createAndInitHandler(callback, bridge,
132 (String authToken, HttpCallable httpCallable) -> stubWithError);
135 verify(callback).statusUpdated(eq(bridge), argThat(arg -> arg.getStatus().equals(ThingStatus.UNKNOWN)));
136 verify(callback, timeout(1000)).statusUpdated(eq(bridge),
137 argThat(arg -> arg.getStatus().equals(ThingStatus.OFFLINE)));
139 verifyChannelsUpdatedToUndef(bridge, 0, callback, UnDefType.UNDEF);
140 verifyChannelsUpdatedToUndef(bridge, 1, callback, UnDefType.UNDEF);
141 verifyChannelsUpdatedToUndef(bridge, 2, callback, UnDefType.UNDEF);
148 private static void verifyChannelsUpdatedToUndef(Bridge bridge, int offset, ThingHandlerCallback callback,
149 State expectedState) {
150 final Thing thing = bridge.getThings().get(offset);
151 for (Channel channel : thing.getChannels()) {
152 verify(callback).stateUpdated(eq(channel.getUID()), eq(expectedState));
157 public void testUpdateTrainsToUndefinedIfNotEnoughDataWasProvided() throws Exception {
158 final Bridge bridge = mockBridge();
159 final ThingHandlerCallback callback = mock(ThingHandlerCallback.class);
161 // Bridge contains 3 trains, but Timetable contains only 1 items, so two trains has to be updated to undef
163 final Timetable timetable = new Timetable();
164 TimetableStop stop01 = new TimetableStop();
165 stop01.setId("stop01id");
166 Event dp = new Event();
167 dp.setPt("2108161000");
169 timetable.getS().add(stop01);
171 final TimetablesV1ApiStub stubWithData = TimetablesV1ApiStub.createWithResult(timetable);
173 final DeutscheBahnTimetableHandler handler = createAndInitHandler(callback, bridge,
174 (String authToken, HttpCallable httpCallable) -> stubWithData);
177 verify(callback).statusUpdated(eq(bridge), argThat(arg -> arg.getStatus().equals(ThingStatus.UNKNOWN)));
178 verify(callback, timeout(1000)).statusUpdated(eq(bridge),
179 argThat(arg -> arg.getStatus().equals(ThingStatus.ONLINE)));
181 verifyThingUpdated(bridge, 0, stop01.getId());
182 verifyChannelsUpdatedToUndef(bridge, 1, callback, UnDefType.UNDEF);
183 verifyChannelsUpdatedToUndef(bridge, 2, callback, UnDefType.UNDEF);