2 * Copyright (c) 2010-2023 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.mielecloud.internal.config;
15 import static org.junit.jupiter.api.Assertions.*;
16 import static org.mockito.ArgumentMatchers.any;
17 import static org.mockito.Mockito.*;
18 import static org.openhab.binding.mielecloud.internal.util.ReflectionUtil.setPrivate;
21 import java.net.URLDecoder;
22 import java.util.HashMap;
24 import java.util.Objects;
26 import org.eclipse.jdt.annotation.NonNullByDefault;
27 import org.junit.jupiter.api.Test;
28 import org.openhab.binding.mielecloud.internal.config.servlet.CreateBridgeServlet;
29 import org.openhab.binding.mielecloud.internal.config.servlet.ForwardToLoginServlet;
30 import org.openhab.binding.mielecloud.internal.handler.MieleBridgeHandler;
31 import org.openhab.binding.mielecloud.internal.handler.MieleHandlerFactory;
32 import org.openhab.binding.mielecloud.internal.util.AbstractConfigFlowTest;
33 import org.openhab.binding.mielecloud.internal.util.MieleCloudBindingIntegrationTestConstants;
34 import org.openhab.binding.mielecloud.internal.util.Website;
35 import org.openhab.binding.mielecloud.internal.webservice.MieleWebservice;
36 import org.openhab.binding.mielecloud.internal.webservice.MieleWebserviceFactory;
37 import org.openhab.core.thing.Thing;
38 import org.openhab.core.thing.ThingStatus;
39 import org.openhab.core.thing.binding.ThingHandler;
40 import org.openhab.core.thing.binding.ThingHandlerFactory;
43 * @author Björn Lange - Initial Contribution
46 public class ConfigFlowTest extends AbstractConfigFlowTest {
47 private void setUpAuthorizationHandler() throws NoSuchFieldException, IllegalAccessException {
48 OAuthAuthorizationHandler authorizationHandler = mock(OAuthAuthorizationHandler.class);
49 when(authorizationHandler.getAccessToken(MieleCloudBindingIntegrationTestConstants.EMAIL))
50 .thenReturn(MieleCloudBindingIntegrationTestConstants.ACCESS_TOKEN);
51 when(authorizationHandler.getBridgeUid())
52 .thenReturn(MieleCloudBindingIntegrationTestConstants.BRIDGE_THING_UID);
53 when(authorizationHandler.getEmail()).thenReturn(MieleCloudBindingIntegrationTestConstants.EMAIL);
55 setPrivate(getResultServlet(), "authorizationHandler", authorizationHandler);
58 private void setUpWebservice() throws Exception {
59 MieleWebservice webservice = mock(MieleWebservice.class);
60 doAnswer(invocation -> {
61 Thing bridge = getThingRegistry().get(MieleCloudBindingIntegrationTestConstants.BRIDGE_THING_UID);
62 assertNotNull(bridge);
63 ThingHandler handler = bridge.getHandler();
64 if (handler instanceof MieleBridgeHandler) {
65 ((MieleBridgeHandler) handler).onConnectionAlive();
68 }).when(webservice).addConnectionStatusListener(any());
70 MieleWebserviceFactory webserviceFactory = mock(MieleWebserviceFactory.class);
71 when(webserviceFactory.create(any())).thenReturn(webservice);
73 MieleHandlerFactory handlerFactory = getService(ThingHandlerFactory.class, MieleHandlerFactory.class);
74 assertNotNull(handlerFactory);
75 setPrivate(Objects.requireNonNull(handlerFactory), "webserviceFactory", webserviceFactory);
78 private Map<String, String> extractUrlParameters(String query) throws Exception {
79 var parameters = new HashMap<String, String>();
80 for (String param : query.split("&")) {
81 String[] pair = param.split("=");
82 String key = URLDecoder.decode(pair[0], "UTF-8");
84 if (pair.length > 1) {
85 value = URLDecoder.decode(pair[1], "UTF-8");
88 assertFalse(parameters.containsKey(key));
89 parameters.put(key, value);
94 private Website configureBridgeWithConfigFlow() throws Exception {
95 Website accountOverviewSite = getCrawler().doGetRelative("/mielecloud");
96 String pairAccountUrl = accountOverviewSite.getTargetOfLink("Pair Account");
98 Website pairAccountSite = getCrawler().doGetRelative(pairAccountUrl);
99 String forwardToLoginUrl = pairAccountSite.getFormAction();
101 String mieleLoginSiteUrl = getCrawler().doGetRedirectUrlRelative(forwardToLoginUrl + "?"
102 + ForwardToLoginServlet.CLIENT_ID_PARAMETER_NAME + "="
103 + MieleCloudBindingIntegrationTestConstants.CLIENT_ID + "&"
104 + ForwardToLoginServlet.CLIENT_SECRET_PARAMETER_NAME + "="
105 + MieleCloudBindingIntegrationTestConstants.CLIENT_SECRET + "&"
106 + ForwardToLoginServlet.BRIDGE_ID_PARAMETER_NAME + "="
107 + MieleCloudBindingIntegrationTestConstants.BRIDGE_ID + "&" + ForwardToLoginServlet.EMAIL_PARAMETER_NAME
108 + "=" + MieleCloudBindingIntegrationTestConstants.EMAIL);
110 var loginSiteUrl = new URL(mieleLoginSiteUrl);
111 assertEquals(loginSiteUrl.getHost(), "api.mcs3.miele.com");
112 assertEquals(loginSiteUrl.getPath(), "/thirdparty/login");
114 Map<String, String> parameters = extractUrlParameters(loginSiteUrl.getQuery());
116 String redirectionUrl = parameters.get("redirect_uri");
117 String state = parameters.get("state");
119 Website resultSite = getCrawler().doGet(redirectionUrl + "?code="
120 + MieleCloudBindingIntegrationTestConstants.AUTHORIZATION_CODE + "&state=" + state);
121 String createBridgeUrl = resultSite.getFormAction();
123 Website finalOverview = getCrawler().doGetRelative(createBridgeUrl + "?"
124 + CreateBridgeServlet.BRIDGE_UID_PARAMETER_NAME + "="
125 + MieleCloudBindingIntegrationTestConstants.BRIDGE_THING_UID.toString() + "&"
126 + CreateBridgeServlet.EMAIL_PARAMETER_NAME + "=" + MieleCloudBindingIntegrationTestConstants.EMAIL);
127 return finalOverview;
131 public void configFlowHappyPathCreatesABridge() throws Exception {
133 setUpAuthorizationHandler();
137 Website finalOverview = configureBridgeWithConfigFlow();
140 assertTrue(finalOverview.contains("<span class=\"status online\">ONLINE</span>"));
142 Thing bridge = getThingRegistry().get(MieleCloudBindingIntegrationTestConstants.BRIDGE_THING_UID);
143 assertNotNull(bridge);
144 assertEquals(ThingStatus.ONLINE, bridge.getStatus());
148 public void configFlowWaitTimeoutExpiresWhenBridgeDoesNotComeOnline() throws Exception {
150 setUpAuthorizationHandler();
151 getCreateBridgeServlet().setOnlineWaitTimeoutInMilliseconds(0);
154 configureBridgeWithConfigFlow();
157 Thing bridge = getThingRegistry().get(MieleCloudBindingIntegrationTestConstants.BRIDGE_THING_UID);
158 assertNotNull(bridge);