0

I have a Quarkus webservice that used oidc to perform auth, and handle the login flow.

This works great in devmode. However, tests make this a bit harder.

I'm leveraging a Selenium testcontainer to provide a browser instance within a docker container. This works fine for pages that don't need a login, with the caveat that the service being tested needs to be hit using the host.testcontainers.internal hostname, as opposed to localhost. It is this fact that seems to be keeping keycloak from working;

The devservice spins up a Keycloak instance at localhost, and that is what is set for quarkus.oidc.auth-server-url, and thus the url that a user gets redirected to for login. Unfortunately, since in the testcontainers browser, localhost refers to the seelenium container, and can't connect to Keycloak.

I have tried setting a consistent port for keycloak, and setting the host directly, but then it seems that the running service instance doesn't have access to host.testcontainers.internal, meaning it can't do its required rest calls anyways. In simpler terms, when localhost is the host configured for keycloak, the user in the browser cannot access keycloak. When host.testcontainers.internal is, the service being tested can't. This leaves me a little stuck. I could see a path forward if these were integration tests run in container mode, but this is in the normal test scope...

How I am setting up the selenium testcontainer:

https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/blob/f7746ae91d3cb9a15dd3e281f07df866dcad484d/software/open-qm-base-station/src/test/java/tech/ebp/oqm/baseStation/testResources/lifecycleManagers/SeleniumGridServerManager.java

@Slf4j
public class SeleniumGridServerManager implements QuarkusTestResourceLifecycleManager {
    
    public static final boolean RECORD = true;
    
    private BrowserWebDriverContainer<?> browserWebDriverContainer = null;
    
    private boolean uiTest = false;
    
    @Getter
    private WebDriver driver = null;
    
    @Override
    public Map<String, String> start() {
        if (!uiTest) {
            log.info("Test not calling for ui.");
            return Map.of();
        }
        if (this.browserWebDriverContainer == null || !this.browserWebDriverContainer.isRunning()) {
            log.info("Starting Selenium WebGrid server.");
            StopWatch sw = StopWatch.createStarted();
            
            this.browserWebDriverContainer = new BrowserWebDriverContainer<>()
                                                 .withCapabilities(new FirefoxOptions())
                                                 .withReuse(false)
                                                 .withAccessToHost(true)
//                                               .withNetworkAliases("host.docker.internal:localhost")
            ;
            
            if (RECORD) {
                File recordingDir = new File(
                    "build/seleniumRecordings/"
                    + new SimpleDateFormat("yyyy-MM-dd_HH-mm").format(new Date())
                );
                recordingDir.mkdirs();
                this.browserWebDriverContainer = this.browserWebDriverContainer.withRecordingMode(
                    RECORD_ALL,
                    recordingDir,
                    VncRecordingContainer.VncRecordingFormat.MP4
                );
                
            }
            this.browserWebDriverContainer.start();
            
            sw.stop();
            
            log.info(
                "Started selenium testcontainer in {}: {}; {}",
                sw,
                this.browserWebDriverContainer.getDockerImageName(),
                this.browserWebDriverContainer.isCreated() && this.browserWebDriverContainer.isRunning()
            );
            log.info("Getting web driver");
            this.driver = this.browserWebDriverContainer.getWebDriver();
            log.info("Got web driver.");
        } else {
            log.info("Selenium grid server already running.");
        }
        return Map.of(
            "runningInfo.hostname",
            Utils.HOST_TESTCONTAINERS_INTERNAL,
            

            "quarkus.keycloak.devservices.enabled",
            "true",
            "quarkus.oidc.auth-server-url",
            "http://"+Utils.HOST_TESTCONTAINERS_INTERNAL+":8089/realms/oqm"
        );
    }
    
    @Override
    public void stop() {
        if (this.browserWebDriverContainer == null) {
            log.info("Web browser container never started.");
            return;
        }
        
        log.info("Stopping web driver container.");
        
        if (this.driver != null) {
            this.driver.close();
        }
        if (this.browserWebDriverContainer != null) {
            this.browserWebDriverContainer.close();
            this.browserWebDriverContainer.stop();
        }
        
        this.driver = null;
        this.browserWebDriverContainer = null;
        
        log.info("Stopped web driver server.");
    }
    
    public void triggerRecord(TestDescription description, Optional<Throwable> throwable) {
        if (this.browserWebDriverContainer != null) {
            log.info("Triggering browser container to save recording of test.");
            this.browserWebDriverContainer.afterTest(description, throwable);
        }
    }
    
    public void beforeTest(TestDescription description) {
        if (this.browserWebDriverContainer != null) {
            this.browserWebDriverContainer.beforeTest(description);
            
        }
    }
    
    @Override
    public void init(Map<String, String> initArgs) {
        QuarkusTestResourceLifecycleManager.super.init(initArgs);
        this.uiTest = Boolean.parseBoolean(initArgs.getOrDefault(TestResourceLifecycleManager.UI_TEST_ARG, Boolean.toString(this.uiTest)));
    }
    
    //  public WebDriver getDriver() {
    //      return this.browserWebDriverContainer.getWebDriver();
    //  }
}

Is there any way to resolve this? Also thinking if host.testcontainers.internal was accessible from the host, could be a solution, but unsure of the best way to acomplish this; I would rather not have to have my hosts modified for automated tests.

Snappawapa
  • 1,697
  • 3
  • 20
  • 42

0 Answers0