From 2cd98e34ffa37cbced0795aefb4f1d8d049749ec Mon Sep 17 00:00:00 2001 From: Michal Krzyzanowski Date: Thu, 14 Nov 2019 17:03:25 +0100 Subject: [PATCH 1/4] Updated docs regarding proxy, added integration test --- bb-integration-tests/pom.xml | 6 +++ ...java => RequestFilterRegistryTestOld.java} | 2 +- docs/_data/navigation.yml | 2 + docs/_docs/modules/core/proxy.md | 43 +++++++++++++++++++ 4 files changed, 52 insertions(+), 1 deletion(-) rename bb-integration-tests/src/test/java/com/cognifide/qa/bb/proxy/{RequestFilterRegistryTest.java => RequestFilterRegistryTestOld.java} (97%) create mode 100644 docs/_docs/modules/core/proxy.md diff --git a/bb-integration-tests/pom.xml b/bb-integration-tests/pom.xml index 5eb104a2..a1ef8410 100644 --- a/bb-integration-tests/pom.xml +++ b/bb-integration-tests/pom.xml @@ -88,6 +88,12 @@ 3.7.1 test + + com.github.tomakehurst + wiremock-jre8 + 2.25.1 + test + diff --git a/bb-integration-tests/src/test/java/com/cognifide/qa/bb/proxy/RequestFilterRegistryTest.java b/bb-integration-tests/src/test/java/com/cognifide/qa/bb/proxy/RequestFilterRegistryTestOld.java similarity index 97% rename from bb-integration-tests/src/test/java/com/cognifide/qa/bb/proxy/RequestFilterRegistryTest.java rename to bb-integration-tests/src/test/java/com/cognifide/qa/bb/proxy/RequestFilterRegistryTestOld.java index 023df665..102e2300 100644 --- a/bb-integration-tests/src/test/java/com/cognifide/qa/bb/proxy/RequestFilterRegistryTest.java +++ b/bb-integration-tests/src/test/java/com/cognifide/qa/bb/proxy/RequestFilterRegistryTestOld.java @@ -46,7 +46,7 @@ @ExtendWith(MockitoExtension.class) @Modules({CoreModule.class}) -public class RequestFilterRegistryTest extends AbstractProxyTest { +public class RequestFilterRegistryTestOld extends AbstractProxyTest { @Inject private RequestFilterRegistry requestFilterRegistry; diff --git a/docs/_data/navigation.yml b/docs/_data/navigation.yml index 21892531..2f1b97ae 100644 --- a/docs/_data/navigation.yml +++ b/docs/_data/navigation.yml @@ -42,6 +42,8 @@ docs: url: /docs/modules/core/actions/ - title: "Setting cookies" url: /docs/modules/core/cookies/ + - title: "Working with proxy" + url: /docs/modules/core/proxy/ - title: "AEM features" children: - title: "AEM modules" diff --git a/docs/_docs/modules/core/proxy.md b/docs/_docs/modules/core/proxy.md new file mode 100644 index 00000000..5c48ebef --- /dev/null +++ b/docs/_docs/modules/core/proxy.md @@ -0,0 +1,43 @@ +--- +title: "Working with proxy" +--- + +## Overview +Potentially, you might run into a case, when you want to modify HTTP requests during your test runs. +Selenium does not have an in-built solution for that, but provides an option to hook up a proxy to +the browser it drives. + +Bobcat uses `BrowserMobProxy` as a proxy solution. It can be controlled programmatically from your tests. + +### Enabling proxy +To enable proxy use dedicated properties in your config. + +Default config: +```yaml + proxy.enabled: false + proxy.ip: 127.0.0.1 + proxy.port: 9000 +``` + +- `proxy.enabled` - enable the proxy +- `proxy.ip` - define the IP on which the proxy listens (useful for external proxy) +- `proxy.port` - define the port used by the proxy + +### Modifying requests +Most common use case when working with proxy is modifying requests, to e.g. attach additional header. +This can be done by registering a `RequestFilter` in the `RequestFilterRegistry`. + +Example: +```java +@Inject +private RequestFilterRegistry filters; + +//... + +void setHeader() { + filters.add((request, contents, messageInfo) -> { + request.headers().add("headerName", "headerValue"); + return null; + }); +} +``` From 40acfe5017e610e72a619ca92ff1f5cdae391eb9 Mon Sep 17 00:00:00 2001 From: Michal Krzyzanowski Date: Thu, 14 Nov 2019 17:03:46 +0100 Subject: [PATCH 2/4] Cleanup of old test --- .../proxy/RequestFilterRegistryTestOld.java | 83 ------------------- 1 file changed, 83 deletions(-) delete mode 100644 bb-integration-tests/src/test/java/com/cognifide/qa/bb/proxy/RequestFilterRegistryTestOld.java diff --git a/bb-integration-tests/src/test/java/com/cognifide/qa/bb/proxy/RequestFilterRegistryTestOld.java b/bb-integration-tests/src/test/java/com/cognifide/qa/bb/proxy/RequestFilterRegistryTestOld.java deleted file mode 100644 index 102e2300..00000000 --- a/bb-integration-tests/src/test/java/com/cognifide/qa/bb/proxy/RequestFilterRegistryTestOld.java +++ /dev/null @@ -1,83 +0,0 @@ -/*- - * #%L - * Bobcat - * %% - * Copyright (C) 2016 Cognifide Ltd. - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * #L% - */ -package com.cognifide.qa.bb.proxy; - -import static org.junit.jupiter.api.Assertions.assertSame; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.verify; - -import java.io.IOException; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.openqa.selenium.remote.DesiredCapabilities; - -import com.cognifide.qa.bb.junit5.guice.Modules; -import com.cognifide.qa.bb.modules.CoreModule; -import com.google.inject.Inject; - -import io.netty.handler.codec.http.HttpRequest; -import net.lightbody.bmp.BrowserMobProxy; -import net.lightbody.bmp.BrowserMobProxyServer; -import net.lightbody.bmp.filters.RequestFilter; -import net.lightbody.bmp.util.HttpMessageContents; -import net.lightbody.bmp.util.HttpMessageInfo; - -@ExtendWith(MockitoExtension.class) -@Modules({CoreModule.class}) -public class RequestFilterRegistryTestOld extends AbstractProxyTest { - - @Inject - private RequestFilterRegistry requestFilterRegistry; - - @Inject - private RequestFilterRegistry requestFilterRegistryAlias; - - @Mock - private RequestFilter requestFilter; - - @Test - public void requestFilterRegistryShouldBeSingleton() { - assertSame(requestFilterRegistry, requestFilterRegistryAlias, - "RequestFilterRegistry should be thread-scoped"); - } - - @Disabled("TODO - some problems with timing (works in debug mode)") - @Test - public void shouldCallFilterByRegistry() throws IOException { - // given - BrowserMobProxy browserMobProxy = new BrowserMobProxyServer(); - startProxyServer(browserMobProxy); - requestFilterRegistry.add(requestFilter); - browserMobProxy.addRequestFilter(requestFilterRegistry); - // when - DesiredCapabilities capabilities = proxyCapabilities(browserMobProxy); - visitSamplePage(capabilities); - browserMobProxy.stop(); - // then - verify(requestFilter, atLeastOnce()).filterRequest(any(HttpRequest.class), - any(HttpMessageContents.class), any(HttpMessageInfo.class)); - - } -} From a283490fb8e357bb3f94614e24b6d27b198feff2 Mon Sep 17 00:00:00 2001 From: Michal Krzyzanowski Date: Thu, 14 Nov 2019 17:04:56 +0100 Subject: [PATCH 3/4] Added missing test --- .../bb/core/modules/ProxyEnabledModule.java | 32 +++++++ .../bb/proxy/RequestFilterRegistryTest.java | 83 +++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 bb-integration-tests/src/main/java/com/cognifide/qa/bb/core/modules/ProxyEnabledModule.java create mode 100644 bb-integration-tests/src/test/java/com/cognifide/qa/bb/proxy/RequestFilterRegistryTest.java diff --git a/bb-integration-tests/src/main/java/com/cognifide/qa/bb/core/modules/ProxyEnabledModule.java b/bb-integration-tests/src/main/java/com/cognifide/qa/bb/core/modules/ProxyEnabledModule.java new file mode 100644 index 00000000..fb4cb5c6 --- /dev/null +++ b/bb-integration-tests/src/main/java/com/cognifide/qa/bb/core/modules/ProxyEnabledModule.java @@ -0,0 +1,32 @@ +/*- + * #%L + * Bobcat + * %% + * Copyright (C) 2019 Cognifide Ltd. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.cognifide.qa.bb.core.modules; + +import com.cognifide.qa.bb.constants.ConfigKeys; +import com.cognifide.qa.bb.modules.CoreModule; +import com.google.inject.AbstractModule; + +public class ProxyEnabledModule extends AbstractModule { + @Override + protected void configure() { + System.setProperty(ConfigKeys.PROXY_ENABLED, "true"); + install(new CoreModule()); + } +} diff --git a/bb-integration-tests/src/test/java/com/cognifide/qa/bb/proxy/RequestFilterRegistryTest.java b/bb-integration-tests/src/test/java/com/cognifide/qa/bb/proxy/RequestFilterRegistryTest.java new file mode 100644 index 00000000..8dedea79 --- /dev/null +++ b/bb-integration-tests/src/test/java/com/cognifide/qa/bb/proxy/RequestFilterRegistryTest.java @@ -0,0 +1,83 @@ +/*- + * #%L + * Bobcat + * %% + * Copyright (C) 2019 Cognifide Ltd. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.cognifide.qa.bb.proxy; + +import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.openqa.selenium.WebDriver; + +import com.cognifide.qa.bb.core.modules.ProxyEnabledModule; +import com.cognifide.qa.bb.junit5.BobcatExtension; +import com.cognifide.qa.bb.junit5.guice.Modules; +import com.github.tomakehurst.wiremock.WireMockServer; +import com.google.inject.Inject; + +@BobcatExtension +@Modules({ProxyEnabledModule.class}) +class RequestFilterRegistryTest { + + @Inject + private WebDriver webDriver; + + @Inject + private RequestFilterRegistry filters; + + private WireMockServer wireMockServer; + + @BeforeEach + void setup() { + wireMockServer = new WireMockServer(); + wireMockServer.start(); + } + + @Test + void bobcatUserCanAddHeaderWhenUsingProxy() { + //given + stubFor(get(urlEqualTo("/proxy-test")) + .withHeader("Bobcat-Header", equalTo("present")) + .willReturn(aResponse() + .withStatus(200) + .withBody("works correctly"))); + + filters.add((request, contents, messageInfo) -> { + request.headers().add("Bobcat-Header", "present"); + return null; + }); + + //when + String url = String.format("http://%s:%s/proxy-test", wireMockServer.getOptions().bindAddress(), + wireMockServer.getOptions().portNumber()); + webDriver.get(url); + + //then + assertThat(webDriver.getPageSource()).contains("works correctly"); + } + + @AfterEach + void teardown() { + if (wireMockServer != null) { + wireMockServer.stop(); + } + } +} From a6f8a52759c0e28b9355241803c7cd72fe321c58 Mon Sep 17 00:00:00 2001 From: Michal Krzyzanowski Date: Fri, 15 Nov 2019 17:39:53 +0100 Subject: [PATCH 4/4] Refactored EnableProxy modifier; added additonal logging --- .../cognifide/qa/bb/modules/ProxyModule.java | 5 ++ .../modifiers/capabilities/EnableProxy.java | 22 +----- .../qa/bb/proxy/ProxyController.java | 2 + .../proxy/providers/DefaultProxyProvider.java | 68 +++++++++++++++++++ 4 files changed, 77 insertions(+), 20 deletions(-) create mode 100644 bb-core/src/main/java/com/cognifide/qa/bb/proxy/providers/DefaultProxyProvider.java diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/modules/ProxyModule.java b/bb-core/src/main/java/com/cognifide/qa/bb/modules/ProxyModule.java index 4fa93b11..3dd32386 100644 --- a/bb-core/src/main/java/com/cognifide/qa/bb/modules/ProxyModule.java +++ b/bb-core/src/main/java/com/cognifide/qa/bb/modules/ProxyModule.java @@ -19,9 +19,12 @@ */ package com.cognifide.qa.bb.modules; +import org.openqa.selenium.Proxy; + import com.cognifide.qa.bb.proxy.ProxyController; import com.cognifide.qa.bb.proxy.ProxyControllerProvider; import com.cognifide.qa.bb.proxy.ProxyEventListener; +import com.cognifide.qa.bb.proxy.providers.DefaultProxyProvider; import com.google.inject.AbstractModule; import com.google.inject.multibindings.Multibinder; @@ -31,5 +34,7 @@ public class ProxyModule extends AbstractModule { protected void configure() { bind(ProxyController.class).toProvider(ProxyControllerProvider.class); Multibinder.newSetBinder(binder(), ProxyEventListener.class); + + bind(Proxy.class).toProvider(DefaultProxyProvider.class); } } diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/provider/selenium/webdriver/modifiers/capabilities/EnableProxy.java b/bb-core/src/main/java/com/cognifide/qa/bb/provider/selenium/webdriver/modifiers/capabilities/EnableProxy.java index aeccc25f..20697ab3 100644 --- a/bb-core/src/main/java/com/cognifide/qa/bb/provider/selenium/webdriver/modifiers/capabilities/EnableProxy.java +++ b/bb-core/src/main/java/com/cognifide/qa/bb/provider/selenium/webdriver/modifiers/capabilities/EnableProxy.java @@ -19,22 +19,15 @@ */ package com.cognifide.qa.bb.provider.selenium.webdriver.modifiers.capabilities; -import java.net.InetAddress; -import java.net.UnknownHostException; - import org.openqa.selenium.Capabilities; import org.openqa.selenium.Proxy; import org.openqa.selenium.remote.CapabilityType; import org.openqa.selenium.remote.DesiredCapabilities; import com.cognifide.qa.bb.constants.ConfigKeys; -import com.cognifide.qa.bb.proxy.ProxyController; import com.google.inject.Inject; import com.google.inject.name.Named; -import net.lightbody.bmp.BrowserMobProxy; -import net.lightbody.bmp.client.ClientUtil; - public class EnableProxy implements CapabilitiesModifier { @Inject @@ -42,11 +35,7 @@ public class EnableProxy implements CapabilitiesModifier { private boolean proxyEnabled; @Inject - @Named(ConfigKeys.PROXY_IP) - private String proxyIp; - - @Inject - private ProxyController proxyController; + private Proxy proxy; @Override public boolean shouldModify() { @@ -60,14 +49,7 @@ public Capabilities modify(Capabilities capabilities) { private DesiredCapabilities enableProxy(Capabilities capabilities) { DesiredCapabilities caps = new DesiredCapabilities(capabilities); - try { - InetAddress proxyInetAddress = InetAddress.getByName(proxyIp); - BrowserMobProxy browserMobProxy = proxyController.startProxyServer(proxyInetAddress); - Proxy seleniumProxy = ClientUtil.createSeleniumProxy(browserMobProxy, proxyInetAddress); - caps.setCapability(CapabilityType.PROXY, seleniumProxy); - } catch (UnknownHostException e) { - throw new IllegalStateException(e); - } + caps.setCapability(CapabilityType.PROXY, proxy); return caps; } } diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/proxy/ProxyController.java b/bb-core/src/main/java/com/cognifide/qa/bb/proxy/ProxyController.java index a488864b..8281ba03 100644 --- a/bb-core/src/main/java/com/cognifide/qa/bb/proxy/ProxyController.java +++ b/bb-core/src/main/java/com/cognifide/qa/bb/proxy/ProxyController.java @@ -60,6 +60,7 @@ public class ProxyController { } public BrowserMobProxy startProxyServer(InetAddress proxyAddress) { + LOG.info("Starting BrowserMobProxy..."); if (!browserMobProxy.isStarted()) { try { browserMobProxy.start(port, proxyAddress); @@ -72,6 +73,7 @@ public BrowserMobProxy startProxyServer(InetAddress proxyAddress) { } public void stopProxyServer() { + LOG.info("Stopping BrowserMobProxy..."); if (browserMobProxy.isStarted()) { try { browserMobProxy.stop(); diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/proxy/providers/DefaultProxyProvider.java b/bb-core/src/main/java/com/cognifide/qa/bb/proxy/providers/DefaultProxyProvider.java new file mode 100644 index 00000000..07f670eb --- /dev/null +++ b/bb-core/src/main/java/com/cognifide/qa/bb/proxy/providers/DefaultProxyProvider.java @@ -0,0 +1,68 @@ +/*- + * #%L + * Bobcat + * %% + * Copyright (C) 2019 Cognifide Ltd. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.cognifide.qa.bb.proxy.providers; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +import org.openqa.selenium.Proxy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.cognifide.qa.bb.constants.ConfigKeys; +import com.cognifide.qa.bb.proxy.ProxyController; +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.name.Named; + +import net.lightbody.bmp.BrowserMobProxy; +import net.lightbody.bmp.client.ClientUtil; + +public class DefaultProxyProvider implements Provider { + private static final Logger LOG = LoggerFactory.getLogger(DefaultProxyProvider.class); + + @Inject + @Named(ConfigKeys.PROXY_IP) + private String proxyIp; + + @Inject + private ProxyController proxyController; + + private Proxy proxy; + + @Override + public Proxy get() { + if (proxy == null) { + proxy = createProxy(); + } + return proxy; + } + + private Proxy createProxy() { + InetAddress proxyInetAddress = null; + try { + proxyInetAddress = InetAddress.getByName(proxyIp); + } catch (UnknownHostException e) { + LOG.error("Failed to parse by name the provided IP address: {}", proxyIp, e); + } + BrowserMobProxy browserMobProxy = proxyController.startProxyServer(proxyInetAddress); + return ClientUtil.createSeleniumProxy(browserMobProxy, proxyInetAddress); + } +}