diff --git a/itests/org.openhab.binding.mielecloud.tests/src/main/java/org/openhab/binding/mielecloud/internal/config/ConfigFlowTest.java b/itests/org.openhab.binding.mielecloud.tests/src/main/java/org/openhab/binding/mielecloud/internal/config/ConfigFlowTest.java index 915baefc8..2a6c3e0ba 100644 --- a/itests/org.openhab.binding.mielecloud.tests/src/main/java/org/openhab/binding/mielecloud/internal/config/ConfigFlowTest.java +++ b/itests/org.openhab.binding.mielecloud.tests/src/main/java/org/openhab/binding/mielecloud/internal/config/ConfigFlowTest.java @@ -17,10 +17,13 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; import static org.openhab.binding.mielecloud.internal.util.ReflectionUtil.setPrivate; +import java.net.URL; +import java.net.URLDecoder; +import java.util.HashMap; +import java.util.Map; import java.util.Objects; import org.eclipse.jdt.annotation.NonNullByDefault; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.openhab.binding.mielecloud.internal.config.servlet.CreateBridgeServlet; import org.openhab.binding.mielecloud.internal.config.servlet.ForwardToLoginServlet; @@ -29,7 +32,6 @@ import org.openhab.binding.mielecloud.internal.handler.MieleHandlerFactory; import org.openhab.binding.mielecloud.internal.util.AbstractConfigFlowTest; import org.openhab.binding.mielecloud.internal.util.MieleCloudBindingIntegrationTestConstants; import org.openhab.binding.mielecloud.internal.util.Website; -import org.openhab.binding.mielecloud.internal.util.WebsiteCrawler; import org.openhab.binding.mielecloud.internal.webservice.MieleWebservice; import org.openhab.binding.mielecloud.internal.webservice.MieleWebserviceFactory; import org.openhab.core.thing.Thing; @@ -73,6 +75,22 @@ public class ConfigFlowTest extends AbstractConfigFlowTest { setPrivate(Objects.requireNonNull(handlerFactory), "webserviceFactory", webserviceFactory); } + private Map extractUrlParameters(String query) throws Exception { + var parameters = new HashMap(); + for (String param : query.split("&")) { + String[] pair = param.split("="); + String key = URLDecoder.decode(pair[0], "UTF-8"); + String value = ""; + if (pair.length > 1) { + value = URLDecoder.decode(pair[1], "UTF-8"); + } + + assertFalse(parameters.containsKey(key)); + parameters.put(key, value); + } + return parameters; + } + private Website configureBridgeWithConfigFlow() throws Exception { Website accountOverviewSite = getCrawler().doGetRelative("/mielecloud"); String pairAccountUrl = accountOverviewSite.getTargetOfLink("Pair Account"); @@ -80,7 +98,7 @@ public class ConfigFlowTest extends AbstractConfigFlowTest { Website pairAccountSite = getCrawler().doGetRelative(pairAccountUrl); String forwardToLoginUrl = pairAccountSite.getFormAction(); - Website mieleLoginSite = getCrawler().doGetRelative(forwardToLoginUrl + "?" + String mieleLoginSiteUrl = getCrawler().doGetRedirectUrlRelative(forwardToLoginUrl + "?" + ForwardToLoginServlet.CLIENT_ID_PARAMETER_NAME + "=" + MieleCloudBindingIntegrationTestConstants.CLIENT_ID + "&" + ForwardToLoginServlet.CLIENT_SECRET_PARAMETER_NAME + "=" @@ -88,11 +106,17 @@ public class ConfigFlowTest extends AbstractConfigFlowTest { + ForwardToLoginServlet.BRIDGE_ID_PARAMETER_NAME + "=" + MieleCloudBindingIntegrationTestConstants.BRIDGE_ID + "&" + ForwardToLoginServlet.EMAIL_PARAMETER_NAME + "=" + MieleCloudBindingIntegrationTestConstants.EMAIL); - String redirectionUrl = mieleLoginSite.getValueOfInput("redirect_uri") - .replace("http://127.0.0.1:" + WebsiteCrawler.getServerPort(), ""); - String state = mieleLoginSite.getValueOfInput("state"); - Website resultSite = getCrawler().doGetRelative(redirectionUrl + "?code=" + var loginSiteUrl = new URL(mieleLoginSiteUrl); + assertEquals(loginSiteUrl.getHost(), "api.mcs3.miele.com"); + assertEquals(loginSiteUrl.getPath(), "/thirdparty/login"); + + Map parameters = extractUrlParameters(loginSiteUrl.getQuery()); + + String redirectionUrl = parameters.get("redirect_uri"); + String state = parameters.get("state"); + + Website resultSite = getCrawler().doGet(redirectionUrl + "?code=" + MieleCloudBindingIntegrationTestConstants.AUTHORIZATION_CODE + "&state=" + state); String createBridgeUrl = resultSite.getFormAction(); @@ -104,7 +128,6 @@ public class ConfigFlowTest extends AbstractConfigFlowTest { } @Test - @Disabled public void configFlowHappyPathCreatesABridge() throws Exception { // given: setUpAuthorizationHandler(); @@ -122,7 +145,6 @@ public class ConfigFlowTest extends AbstractConfigFlowTest { } @Test - @Disabled public void configFlowWaitTimeoutExpiresWhenBridgeDoesNotComeOnline() throws Exception { // given: setUpAuthorizationHandler(); diff --git a/itests/org.openhab.binding.mielecloud.tests/src/main/java/org/openhab/binding/mielecloud/internal/util/AbstractConfigFlowTest.java b/itests/org.openhab.binding.mielecloud.tests/src/main/java/org/openhab/binding/mielecloud/internal/util/AbstractConfigFlowTest.java index edf68d265..b85b4387a 100644 --- a/itests/org.openhab.binding.mielecloud.tests/src/main/java/org/openhab/binding/mielecloud/internal/util/AbstractConfigFlowTest.java +++ b/itests/org.openhab.binding.mielecloud.tests/src/main/java/org/openhab/binding/mielecloud/internal/util/AbstractConfigFlowTest.java @@ -18,6 +18,7 @@ import java.util.Objects; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.openhab.binding.mielecloud.internal.config.MieleCloudConfigService; import org.openhab.binding.mielecloud.internal.config.servlet.AccountOverviewServlet; @@ -89,12 +90,12 @@ public abstract class AbstractConfigFlowTest extends OpenHabOsgiTest { } @BeforeEach - public final void setUpConfigFlowTest() { + public final void setUpConfigFlowTest() throws Exception { setUpCrawler(); setUpServlets(); } - private void setUpCrawler() { + private void setUpCrawler() throws Exception { HttpClientFactory clientFactory = getService(HttpClientFactory.class); assertNotNull(clientFactory); crawler = new WebsiteCrawler(Objects.requireNonNull(clientFactory)); @@ -110,4 +111,9 @@ public abstract class AbstractConfigFlowTest extends OpenHabOsgiTest { successServlet = configService.getSuccessServlet(); createBridgeServlet = configService.getCreateBridgeServlet(); } + + @AfterEach + public final void tearDown() throws Exception { + getCrawler().close(); + } } diff --git a/itests/org.openhab.binding.mielecloud.tests/src/main/java/org/openhab/binding/mielecloud/internal/util/WebsiteCrawler.java b/itests/org.openhab.binding.mielecloud.tests/src/main/java/org/openhab/binding/mielecloud/internal/util/WebsiteCrawler.java index 45d62deac..f07742f30 100644 --- a/itests/org.openhab.binding.mielecloud.tests/src/main/java/org/openhab/binding/mielecloud/internal/util/WebsiteCrawler.java +++ b/itests/org.openhab.binding.mielecloud.tests/src/main/java/org/openhab/binding/mielecloud/internal/util/WebsiteCrawler.java @@ -17,6 +17,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.http.HttpHeader; import org.openhab.core.io.net.http.HttpClientFactory; /** @@ -25,24 +26,54 @@ import org.openhab.core.io.net.http.HttpClientFactory; * @author Björn Lange - Initial Contribution */ @NonNullByDefault -public final class WebsiteCrawler { +public final class WebsiteCrawler implements AutoCloseable { private HttpClient httpClient; - public WebsiteCrawler(HttpClientFactory httpClientFactory) { - this.httpClient = httpClientFactory.getCommonHttpClient(); + public WebsiteCrawler(HttpClientFactory httpClientFactory) throws Exception { + this.httpClient = httpClientFactory.createHttpClient("mielecloud-int-tests"); + this.httpClient.start(); + } + + /** + * Gets a website during integration tests. + * The resulting website will be the one obtained after following all redirections. + * + * @param url The URL. + * @return The website. + * @throws Exception if anything goes wrong. + */ + public Website doGet(String url) throws Exception { + httpClient.setFollowRedirects(true); + ContentResponse response = httpClient.GET(url); + assertEquals(200, response.getStatus()); + return new Website(response.getContentAsString()); } /** * Gets a website relative to the address of the openHAB installation running in test mode during integration tests. + * The resulting website will be the one obtained after following all redirections. * * @param relativeUrl The relative URL. * @return The website. * @throws Exception if anything goes wrong. */ public Website doGetRelative(String relativeUrl) throws Exception { + return doGet("http://127.0.0.1:" + getServerPort() + relativeUrl); + } + + /** + * Gets a redirection URL from an URL relative to the address of the openHAB installation running in test mode + * during integration tests expecting to receive a 302 Found response. + * + * @param relativeUrl The relative URL. + * @return The website that the client was redirected to. + * @throws Exception if anything goes wrong. + */ + public String doGetRedirectUrlRelative(String relativeUrl) throws Exception { + httpClient.setFollowRedirects(false); ContentResponse response = httpClient.GET("http://127.0.0.1:" + getServerPort() + relativeUrl); - assertEquals(200, response.getStatus()); - return new Website(response.getContentAsString()); + assertEquals(302, response.getStatus()); + return response.getHeaders().get(HttpHeader.LOCATION); } /** @@ -52,4 +83,9 @@ public final class WebsiteCrawler { public static int getServerPort() { return Integer.getInteger("org.osgi.service.http.port", 8080); } + + @Override + public void close() throws Exception { + httpClient.stop(); + } }