]> git.basschouten.com Git - openhab-addons.git/blob
b640abc09394ea4d0be852e2d87d16d0510a513a
[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.groupepsa.internal.things;
14
15 import static org.mockito.ArgumentMatchers.*;
16 import static org.mockito.Mockito.*;
17
18 import java.io.BufferedReader;
19 import java.io.InputStream;
20 import java.io.InputStreamReader;
21 import java.time.ZoneId;
22 import java.util.stream.Collectors;
23
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.eclipse.jetty.client.HttpClient;
26 import org.eclipse.jetty.client.HttpContentResponse;
27 import org.eclipse.jetty.client.HttpResponse;
28 import org.junit.jupiter.api.AfterEach;
29 import org.junit.jupiter.api.BeforeEach;
30 import org.junit.jupiter.api.Test;
31 import org.mockito.Mock;
32 import org.mockito.MockitoAnnotations;
33 import org.openhab.binding.groupepsa.internal.bridge.GroupePSABridgeHandler;
34 import org.openhab.binding.groupepsa.internal.rest.api.GroupePSAConnectApi;
35 import org.openhab.binding.groupepsa.internal.rest.exceptions.GroupePSACommunicationException;
36 import org.openhab.core.auth.client.oauth2.OAuthFactory;
37 import org.openhab.core.config.core.Configuration;
38 import org.openhab.core.i18n.TimeZoneProvider;
39 import org.openhab.core.library.types.DateTimeType;
40 import org.openhab.core.library.types.StringType;
41 import org.openhab.core.thing.Bridge;
42 import org.openhab.core.thing.ChannelUID;
43 import org.openhab.core.thing.Thing;
44 import org.openhab.core.thing.ThingStatus;
45 import org.openhab.core.thing.ThingStatusDetail;
46 import org.openhab.core.thing.ThingUID;
47 import org.openhab.core.thing.binding.ThingHandlerCallback;
48 import org.openhab.core.types.State;
49
50 /**
51  * The {@link GroupePSAHandlerTest} is responsible for testing the binding
52  *
53  * @author Arjan Mels - Initial contribution
54  */
55 @NonNullByDefault
56 public class GroupePSAHandlerTest {
57     private @NonNullByDefault({}) AutoCloseable closeable;
58
59     private @NonNullByDefault({}) GroupePSAConnectApi api;
60     private @NonNullByDefault({}) GroupePSABridgeHandler bridgeHandler;
61     private @NonNullByDefault({}) GroupePSAHandler thingHandler;
62
63     private @NonNullByDefault({}) @Mock ThingHandlerCallback thingCallback;
64     private @NonNullByDefault({}) @Mock ThingHandlerCallback bridgeCallback;
65     private @NonNullByDefault({}) @Mock Thing thing;
66     private @NonNullByDefault({}) @Mock Bridge bridge;
67
68     private @NonNullByDefault({}) @Mock OAuthFactory oAuthFactory;
69     private @NonNullByDefault({}) @Mock HttpClient httpClient;
70     private @NonNullByDefault({}) @Mock TimeZoneProvider timeZoneProvider;
71
72     static String getResourceFileAsString(String fileName) throws GroupePSACommunicationException {
73         try (InputStream is = GroupePSAConnectApi.class.getResourceAsStream(fileName)) {
74             try (InputStreamReader isr = new InputStreamReader(is); BufferedReader reader = new BufferedReader(isr)) {
75                 return reader.lines().collect(Collectors.joining(System.lineSeparator()));
76             }
77         } catch (Exception e) {
78             throw new GroupePSACommunicationException(e);
79         }
80     }
81
82     static HttpContentResponse createHttpResponse(String file) throws GroupePSACommunicationException {
83         return new HttpContentResponse(new HttpResponse(null, null).status(200),
84                 getResourceFileAsString("/" + file).getBytes(), "json", "UTF-8");
85     }
86
87     @BeforeEach
88     public void setUp() throws GroupePSACommunicationException {
89         closeable = MockitoAnnotations.openMocks(this);
90
91         // Create real objects
92         bridgeHandler = spy(new GroupePSABridgeHandler(bridge, oAuthFactory, httpClient));
93         thingHandler = spy(new GroupePSAHandler(thing, timeZoneProvider));
94         api = spy(new GroupePSAConnectApi(httpClient, bridgeHandler, "clientId", "realm"));
95
96         // Setup API mock
97         doReturn(createHttpResponse("dummy_user.json")).when(api).executeRequest(contains("user"), anyString());
98         doReturn(createHttpResponse("dummy_vehiclestatus3.json")).when(api).executeRequest(contains("status"),
99                 anyString());
100
101         // Setup bridge handler mock
102         bridgeHandler.setCallback(bridgeCallback);
103         doReturn(api).when(bridgeHandler).getAPI();
104
105         // Setup bridge mock
106         Configuration bridgeConfig = new Configuration();
107         bridgeConfig.put("vendor", "OPEL");
108         bridgeConfig.put("userName", "user");
109         bridgeConfig.put("password", "pwd");
110         bridgeConfig.put("clientId", "clientIdValue");
111         bridgeConfig.put("clientSecret", "clientSecretValue");
112         doReturn(bridgeConfig).when(bridge).getConfiguration();
113         doReturn(ThingStatus.ONLINE).when(bridge).getStatus();
114         doReturn(bridgeHandler).when(bridge).getHandler();
115         doReturn(new ThingUID("a:b:c")).when(bridge).getUID();
116
117         // Setup thing mock
118         Configuration thingConfig = new Configuration();
119         thingConfig.put("id", "mock_id");
120         doReturn(thingConfig).when(thing).getConfiguration();
121         doReturn(new ThingUID("a:b:c")).when(thing).getUID();
122
123         // Setup thing handler mock
124         thingHandler.setCallback(thingCallback);
125         doReturn(bridge).when(thingHandler).getBridge();
126         doNothing().when(thingHandler).buildDoorChannels(any());
127         doReturn(ZoneId.systemDefault()).when(timeZoneProvider).getTimeZone();
128     }
129
130     @AfterEach
131     public void tearDown() throws Exception {
132         // Free any resources, like open database connections, files etc.
133         thingHandler.dispose();
134         bridgeHandler.dispose();
135         closeable.close();
136     }
137
138     @Test
139     public void intializeAndCheckChannels() throws InterruptedException {
140         // Initialize the bridge
141         bridgeHandler.initialize();
142
143         // check that the bridge is online
144         verify(bridgeCallback, timeout(10000)).statusUpdated(eq(bridge),
145                 argThat(arg -> arg.getStatus().equals(ThingStatus.ONLINE)));
146
147         // Initialize the thing
148         thingHandler.initialize();
149
150         // check that the thing is offline without detail (last update time is not
151         // within 15 minutes)
152         verify(thingCallback, timeout(10000)).statusUpdated(eq(thing),
153                 argThat(arg -> arg.getStatus().equals(ThingStatus.OFFLINE)
154                         && arg.getStatusDetail().equals(ThingStatusDetail.NONE)));
155
156         // check that the channels are updated
157         verify(thingCallback, atLeast(30)).stateUpdated(any(ChannelUID.class), any(State.class));
158         verify(thingCallback).stateUpdated(eq(new ChannelUID("a:b:c:electric#chargingStatus")),
159                 eq(new StringType("Disconnected")));
160         verify(thingCallback).stateUpdated(eq(new ChannelUID("a:b:c:various#lastUpdated")), any(DateTimeType.class));
161     }
162 }