Connecting Selenium Test to AWS Desktop Browser through cooperate proxy

Viewed 62

I am trying to connect to the AWS device farm for desktop browser testing with Selenium 4 through a cooperate proxy, with no luck.

Here is the code I am using:

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>My Selenium Tests</groupId>
    <artifactId>Selenium</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>software.amazon.awssdk</groupId>
                <artifactId>bom</artifactId>
                <version>2.17.209</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <!-- TestNG -->
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>7.6.0</version>
            <scope>compile</scope>
        </dependency>

        <!-- AWS -->
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>apache-client</artifactId>
            <version>2.17.209</version>
        </dependency>
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>devicefarm</artifactId>
            <version>2.17.209</version>
        </dependency>
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>aws-sdk-java</artifactId>
            <version>2.17.209</version>
        </dependency>

        <!-- Selenium -->
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>4.2.2</version>
        </dependency>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-remote-driver</artifactId>
            <version>4.2.2</version>
        </dependency>
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.10.0</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>
    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>

</project>

SeleniumTest.java

package Selenium;

import okhttp3.*;
import okhttp3.Authenticator;
import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.remote.HttpCommandExecutor;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.remote.http.ClientConfig;
import org.openqa.selenium.remote.http.HttpClient;
import org.openqa.selenium.remote.http.HttpClient.Factory;
import org.testng.annotations.Test;
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
import software.amazon.awssdk.http.apache.ApacheHttpClient;
import software.amazon.awssdk.http.apache.ProxyConfiguration;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.devicefarm.DeviceFarmClient;
import software.amazon.awssdk.services.devicefarm.model.CreateTestGridUrlRequest;
import software.amazon.awssdk.services.devicefarm.model.CreateTestGridUrlResponse;

import java.io.IOException;
import java.net.*;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

public class SeleniumTest {

    @Test
    public void search() throws MalformedURLException, URISyntaxException, UnknownHostException {

        ProxyConfiguration.Builder proxyConfiguration = ProxyConfiguration.builder();
        proxyConfiguration.endpoint(new URI("http://myProxyUrl:8080"));
        proxyConfiguration.username("myProxyUsername");
        proxyConfiguration.password("myProxyPassword");
        ApacheHttpClient.Builder httpClientBuilder = ApacheHttpClient.builder().proxyConfiguration(proxyConfiguration.build());

        String projectARN = "arn:aws:devicefarm:someString:testgrid-project:someUid";
        DeviceFarmClient deviceFarmClient = DeviceFarmClient.builder()
                        .credentialsProvider(DefaultCredentialsProvider.create())
                        .httpClientBuilder(httpClientBuilder)
                        .overrideConfiguration(ClientOverrideConfiguration.builder().build())
                        .region(Region.US_WEST_2)
                        .build();
        CreateTestGridUrlRequest testGridUrlrequest = CreateTestGridUrlRequest.builder()
                        .expiresInSeconds(300)
                        .projectArn(projectARN)
                        .build();
        CreateTestGridUrlResponse response = deviceFarmClient.createTestGridUrl(testGridUrlrequest);
        URL testGridUrl = new URL(response.url());

        Authenticator proxyAuthenticator = new Authenticator() {

            public Request authenticate(Route route, Response response) throws IOException {
                String credential = Credentials.basic("myProxyUsername", "myProxyPassword");
                return response.request().newBuilder()
                                .header("Proxy-Authorization", credential)
                                .build();
            }
        };

        Builder okHttpClientBuilder = new Builder()
                        .connectTimeout(60, TimeUnit.SECONDS)
                        .writeTimeout(60, TimeUnit.SECONDS)
                        .readTimeout(60, TimeUnit.SECONDS)
                        .proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("myProxyUrl", 8080)))
                        .proxyAuthenticator(proxyAuthenticator);

        FirefoxOptions browserOptions = new FirefoxOptions();
        browserOptions.addPreference("network.proxy.type", 0);

        Factory factory = new MyHttpClientFactory(new OkHttpClient(okHttpClientBuilder));
        HttpCommandExecutor executor = new HttpCommandExecutor(new HashMap<>(), testGridUrl, factory);
        RemoteWebDriver remoteWebDriver = new RemoteWebDriver(executor, browserOptions);

        remoteWebDriver.navigate().to("https://www.google.de");
        remoteWebDriver.quit();
    }

    public class MyHttpClientFactory implements HttpClient.Factory {

        final OkHttpClient okHttpClient;

        public MyHttpClientFactory(OkHttpClient okHttpClient) {
            this.okHttpClient = okHttpClient;
        }

        @Override
        public HttpClient createClient(URL url) {
            return (HttpClient) okHttpClient;
        }

        @Override
        public HttpClient createClient(ClientConfig config) {
            return (HttpClient) okHttpClient;
        }

        @Override
           public void cleanupIdleClients() {
        }
    }
}

As you can see, I used the ApacheHttpClient as HTTPClient for the AWS DeviceFarmClient, so I can authenticate with the cooperate proxy - which works like a charm. I get the testGridUrl, which I can use in the second step to send commands via the RemoteWebDriver to the AWS Desktop Browser.

This is where the problems start. I use the OkHttpClient (recommended by Selenium) as HTTPClient for the RemoteWebDriver - here also to enable proxy authentication (which I think is not possible with the built in HTTPClient).

But when the test is run, I get a class cast exception - it seems the okHttpCLient cannot be cast to HttpClient.

java.lang.ClassCastException: class okhttp3.OkHttpClient cannot be cast to class org.openqa.selenium.remote.http.HttpClient (okhttp3.OkHttpClient and org.openqa.selenium.remote.http.HttpClient are in unnamed module of loader 'app')

    at Selenium.SeleniumTest$MyHttpClientFactory.createClient(SeleniumTest.java:103)
    at org.openqa.selenium.remote.HttpCommandExecutor.<init>(HttpCommandExecutor.java:107)
    at org.openqa.selenium.remote.HttpCommandExecutor.<init>(HttpCommandExecutor.java:94)
    at Selenium.SeleniumTest.search(SeleniumTest.java:77)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.testng.internal.invokers.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:139)
    at org.testng.internal.invokers.TestInvoker.invokeMethod(TestInvoker.java:677)
    at org.testng.internal.invokers.TestInvoker.invokeTestMethod(TestInvoker.java:221)
    at org.testng.internal.invokers.MethodRunner.runInSequence(MethodRunner.java:50)
    at org.testng.internal.invokers.TestInvoker$MethodInvocationAgent.invoke(TestInvoker.java:962)
    at org.testng.internal.invokers.TestInvoker.invokeTestMethods(TestInvoker.java:194)
    at org.testng.internal.invokers.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:148)
    at org.testng.internal.invokers.TestMethodWorker.run(TestMethodWorker.java:128)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
    at org.testng.TestRunner.privateRun(TestRunner.java:806)
    at org.testng.TestRunner.run(TestRunner.java:601)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:433)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:427)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:387)
    at org.testng.SuiteRunner.run(SuiteRunner.java:330)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:95)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1256)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1176)
    at org.testng.TestNG.runSuites(TestNG.java:1099)
    at org.testng.TestNG.run(TestNG.java:1067)

Did anyone use a proxy for connection to the AWS DeviceFarm before with Selenium 4 and can give me some hints on how to procede (replace the HTTPClient? Cast possible?)

All the best, Pita.

0 Answers
Related