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