This is an automated email from the ASF dual-hosted git repository.

cmarcum pushed a commit to branch task/geb-testcontainers
in repository https://gitbox.apache.org/repos/asf/groovy-geb.git

commit 0036f2ca9bfe1921be634341b5043a3a8f594478
Author: Carl Marcum <[email protected]>
AuthorDate: Sat Feb 14 16:01:02 2026 -0500

    fix codenarc violations.
---
 .../grails/plugin/geb/ContainerFileDetector.groovy |   2 +-
 .../plugin/geb/ContainerGebTestDescription.groovy  |   4 +-
 .../plugin/geb/DefaultContainerFileDetector.groovy |   4 +-
 .../plugin/geb/GrailsContainerGebExtension.groovy  |  18 +-
 .../grails/plugin/geb/GrailsGebSettings.groovy     |  45 ++-
 .../plugin/geb/WebDriverContainerHolder.groovy     | 387 +++++++++++----------
 .../geb/serviceloader/ServiceRegistry.groovy       |   4 +-
 .../grails/plugin/geb/support/BrowserType.groovy   |  14 +-
 .../geb/support/ContainerGebFileInputSource.groovy |   1 -
 .../geb/support/LocalhostDownloadSupport.groovy    |   4 +-
 .../geb/support/delegate/BrowserDelegate.groovy    |   2 +-
 .../geb/support/delegate/PageDelegate.groovy       |   2 +-
 12 files changed, 251 insertions(+), 236 deletions(-)

diff --git 
a/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/ContainerFileDetector.groovy
 
b/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/ContainerFileDetector.groovy
index 0b824738..f271c209 100644
--- 
a/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/ContainerFileDetector.groovy
+++ 
b/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/ContainerFileDetector.groovy
@@ -23,7 +23,7 @@ import org.openqa.selenium.remote.FileDetector
 
 /**
  * An extension of {@link org.openqa.selenium.remote.FileDetector}
- * that will get passed additional parameters from the webdriver container 
holder. 
+ * that will get passed additional parameters from the webdriver container 
holder.
  * <p>
  * Implementations must provide a zero-argument constructor to ensure 
compatibility
  * with {@link java.util.ServiceLoader}.
diff --git 
a/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/ContainerGebTestDescription.groovy
 
b/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/ContainerGebTestDescription.groovy
index 65bb5f15..71251bcd 100644
--- 
a/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/ContainerGebTestDescription.groovy
+++ 
b/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/ContainerGebTestDescription.groovy
@@ -39,8 +39,8 @@ class ContainerGebTestDescription implements TestDescription {
         testId = [
                 testInfo.feature.spec.displayName,
                 testInfo.feature.displayName,
-                testInfo.displayName != testInfo.feature.displayName ? 
testInfo.displayName : null,
-                testInfo.displayName != testInfo.feature.displayName ? 
testInfo.iterationIndex : null
+                testInfo.displayName == testInfo.feature.displayName ? null : 
testInfo.displayName,
+                testInfo.displayName == testInfo.feature.displayName ? null : 
testInfo.iterationIndex
         ].findAll(/* Remove nulls */).join(' ')
 
         def safeName = testId.replaceAll('\\W+', '_')
diff --git 
a/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/DefaultContainerFileDetector.groovy
 
b/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/DefaultContainerFileDetector.groovy
index a15a7e4c..c4472a36 100644
--- 
a/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/DefaultContainerFileDetector.groovy
+++ 
b/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/DefaultContainerFileDetector.groovy
@@ -23,7 +23,7 @@ import org.openqa.selenium.remote.UselessFileDetector
 
 /**
  * Detects files on the local disk.
- * 
+ *
  * @since 4.2
  */
 class DefaultContainerFileDetector extends LocalFileDetector implements 
ContainerFileDetector {
@@ -31,7 +31,7 @@ class DefaultContainerFileDetector extends LocalFileDetector 
implements Containe
 
 /**
  * A file detector that never finds anything.
- * 
+ *
  * @since 4.2
  */
 class UselessContainerFileDetector extends UselessFileDetector implements 
ContainerFileDetector {
diff --git 
a/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/GrailsContainerGebExtension.groovy
 
b/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/GrailsContainerGebExtension.groovy
index b976aebd..28584375 100644
--- 
a/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/GrailsContainerGebExtension.groovy
+++ 
b/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/GrailsContainerGebExtension.groovy
@@ -70,7 +70,7 @@ class GrailsContainerGebExtension implements IGlobalExtension 
{
 
     @Override
     void visitSpec(SpecInfo spec) {
-        if (isContainerGebSpec(spec) ) {
+        if (isContainerGebSpec(spec)) {
             // Do not allow parallel execution since there's only 1 set of 
containers in testcontainers
             spec.addExclusiveResource(exclusiveResource)
 
@@ -122,6 +122,13 @@ class GrailsContainerGebExtension implements 
IGlobalExtension {
         }
     }
 
+    private static void addGebExtensionOnFailureReporter(SpecInfo spec) {
+        List<MethodInfo> methods = spec.allFeatures*.featureMethod + 
spec.allFixtureMethods.toList()
+        methods.each {
+            it.addInterceptor(new GebOnFailureReporter())
+        }
+    }
+
     @TailRecursive
     private boolean isContainerGebSpec(SpecInfo spec) {
         if (spec) {
@@ -132,14 +139,5 @@ class GrailsContainerGebExtension implements 
IGlobalExtension {
         }
         return false
     }
-
-
-
-    private static void addGebExtensionOnFailureReporter(SpecInfo spec) {
-        List<MethodInfo> methods = spec.allFeatures*.featureMethod + 
spec.allFixtureMethods.toList()
-        methods.each {
-            it.addInterceptor(new GebOnFailureReporter())
-        }
-    }
 }
 
diff --git 
a/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/GrailsGebSettings.groovy
 
b/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/GrailsGebSettings.groovy
index 55b6bd2e..5326866c 100644
--- 
a/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/GrailsGebSettings.groovy
+++ 
b/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/GrailsGebSettings.groovy
@@ -89,12 +89,32 @@ class GrailsGebSettings {
         this.startTime = startTime
     }
 
+    boolean isRecordingEnabled() {
+        recordingMode != VncRecordingMode.SKIP
+    }
+
+    @Memoized
+    File getRecordingDirectory() {
+        if (!recordingEnabled) {
+            return null
+        }
+        createDirectory(recordingDirectoryName, 'recording')
+    }
+
+    @Memoized
+    File getReportingDirectory() {
+        if (!reportingDirectoryName) {
+            return null
+        }
+        createDirectory(reportingDirectoryName, 'reporting')
+    }
+
     private static boolean getBooleanProperty(String propertyName, boolean 
defaultValue) {
         Boolean.parseBoolean(System.getProperty(propertyName, 
defaultValue.toString()))
     }
 
     private static int getIntProperty(String propertyName, int defaultValue) {
-        Integer.getInteger(propertyName, defaultValue) ?: defaultValue
+        System.getProperty(propertyName)?.toInteger() ?: defaultValue
     }
 
     private static Number getNumberProperty(String propertyName, Number 
defaultValue) {
@@ -103,9 +123,8 @@ class GrailsGebSettings {
             try {
                 if (propValue.contains('.')) {
                     return new BigDecimal(propValue)
-                } else {
-                    return Integer.parseInt(propValue)
                 }
+                return Integer.parseInt(propValue)
             } catch (NumberFormatException ignored) {
                 log.warn(
                         'Could not parse property [{}] with value [{}] as a 
Number. Using default value [{}] instead.',
@@ -118,26 +137,6 @@ class GrailsGebSettings {
         return defaultValue
     }
 
-    boolean isRecordingEnabled() {
-        recordingMode != VncRecordingMode.SKIP
-    }
-
-    @Memoized
-    File getRecordingDirectory() {
-        if (!recordingEnabled) {
-            return null
-        }
-        createDirectory(recordingDirectoryName, 'recording')
-    }
-
-    @Memoized
-    File getReportingDirectory() {
-        if (!reportingDirectoryName) {
-            return null
-        }
-        createDirectory(reportingDirectoryName, 'reporting')
-    }
-
     private File createDirectory(String directoryName, String useCase) {
         def dir = new File(
                 
"$directoryName$File.separator${DateTimeFormatter.ofPattern('yyyyMMdd_HHmmss').format(startTime)}"
diff --git 
a/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/WebDriverContainerHolder.groovy
 
b/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/WebDriverContainerHolder.groovy
index 9beaa695..bab7e1d4 100644
--- 
a/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/WebDriverContainerHolder.groovy
+++ 
b/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/WebDriverContainerHolder.groovy
@@ -18,7 +18,6 @@
  */
 package grails.plugin.geb
 
-
 import org.openqa.selenium.firefox.FirefoxOptions
 
 import java.time.Duration
@@ -76,6 +75,8 @@ class WebDriverContainerHolder {
 
     private static final String DEFAULT_HOSTNAME_FROM_HOST = 'localhost'
     private static final String REMOTE_ADDRESS_PROPERTY = 
'webdriver.remote.server'
+    private static final String HOST_PORT_PROPERTY = 'hostPort'
+    private static final String BASE_URL_PROPERTY = 'baseUrl'
     private static final String DEFAULT_BROWSER = 'firefox'
 
     GrailsGebSettings settings
@@ -102,85 +103,13 @@ class WebDriverContainerHolder {
 
     boolean 
matchesCurrentContainerConfiguration(WebDriverContainerConfiguration specConf) {
         specConf == containerConf &&
-                settings.recordingMode == 
BrowserWebDriverContainer.VncRecordingMode.SKIP
-    }
-
-    /**
-     * Returns a host port to use for the container in this order:
-     * Class field 'hostPort' if found in the invocation (Spec).
-     * A 'hostPort' property in the GebConfig configuration.
-     * @param methodInvocation
-     * @return
-     */
-    private static int findServerPort(IMethodInvocation methodInvocation) {
-        // use the test class hostPort if specified
-        try {
-            return (int) methodInvocation.instance.metaClass.getProperty(
-                    methodInvocation.instance,
-                    'hostPort'
-            )
-        } catch (ignored) {
-            // Grails throws an IllegalStateException about their annotation 
here.  We do not.
-            log.info("no hostPort from methodInvocation")
-        }
-
-        try {
-            // use geb config setting or default 8080
-            Configuration gebConfig = new ConfigurationLoader().conf
-            return (int) gebConfig.rawConfig.getProperty('hostPort')
-        } catch (ignored) {
-            log.info("no hostPort in config")
-        }
-
-        log.info("using default hostPort 8080")
-        return 8080
-    }
-
-    /**
-     * Returns a baseUrl from a setting if found in this order:
-     * A class field 'baseUrl' if found in the invocation (Spec).
-     * A 'baseUrl' property in the GebConfig configuration.
-     * Or an empty String if not found.
-     * @param methodInvocation
-     * @return
-     */
-    private static String findBaseUrl(IMethodInvocation methodInvocation) {
-        // use the test class baseUrl if specified
-        try {
-            String baseUrl =  methodInvocation.instance.metaClass.getProperty(
-                    methodInvocation.instance,
-                    'baseUrl'
-            )
-            if (baseUrl) {
-                log.info("using baseUrl: ${baseUrl} from method invocation.")
-                return baseUrl
-            }
-        } catch (ignored) {
-            log.info("no baseUrl from methodInvocation")
-        }
-
-        try {
-            // use geb config setting or default
-            Configuration gebConfig = new ConfigurationLoader().conf
-            String baseUrl = gebConfig.getProperty('baseUrl') ?: ""
-            if (baseUrl != "") {
-                log.info("using baseUrl: ${baseUrl} from configuration.")
-                return baseUrl
-            }
-        } catch (ignored) {
-            log.info("no baseUrl in config.")
-        }
-
-        log.info("no configured baseUrl found.")
-        return ""
-
+            settings.recordingMode == 
BrowserWebDriverContainer.VncRecordingMode.SKIP
     }
 
-
     @PackageScope
     boolean reinitialize(IMethodInvocation methodInvocation) {
         def specConf = new WebDriverContainerConfiguration(
-                methodInvocation.spec
+            methodInvocation.spec
         )
         if (matchesCurrentContainerConfiguration(specConf)) {
             return false
@@ -200,25 +129,25 @@ class WebDriverContainerHolder {
             validateDriverConf(gebConf)
             if (customBrowser) {
                 log.info(
-                        'A \'containerBrowser\' property was found in 
GebConfig. ' +
-                                "Using [$customBrowser] container image."
+                    'A \'containerBrowser\' property was found in GebConfig. ' 
+
+                        "Using [$customBrowser] container image."
                 )
                 // Prepare for creating a container matching
                 // the GebConfig `containerBrowser` property.
                 dockerImageName = createDockerImageName(customBrowser)
             } else {
                 log.info(
-                        'No \'containerBrowser\' property found in GebConfig. 
' +
-                                "Using default [$DEFAULT_BROWSER] container 
image."
+                    'No \'containerBrowser\' property found in GebConfig. ' +
+                        "Using default [$DEFAULT_BROWSER] container image."
                 )
             }
         }
 
         containerConf = specConf
         container = new 
BrowserWebDriverContainer(dockerImageName).withRecordingMode(
-                settings.recordingMode,
-                settings.recordingDirectory,
-                settings.recordingFormat
+            settings.recordingMode,
+            settings.recordingDirectory,
+            settings.recordingFormat
         )
 
         container.with {
@@ -230,11 +159,10 @@ class WebDriverContainerHolder {
 
         startContainer(container, dockerImageName, customBrowser)
 
-
         if (hostnameChanged) {
             container.execInContainer(
-                    '/bin/sh', '-c',
-                    "echo '$hostIp\t$containerConf.hostName' | sudo tee -a 
/etc/hosts"
+                '/bin/sh', '-c',
+                "echo '$hostIp\t$containerConf.hostName' | sudo tee -a 
/etc/hosts"
             )
         }
 
@@ -256,9 +184,9 @@ class WebDriverContainerHolder {
             // the `RemoteWebDriver` will be instantiated using the 
`webdriver.remote.server`
             // system property. We set that property to inform the driver of 
the container address.
             gebConf.driverConf = ClosureDecorators.withSystemProperty(
-                    gebConf.driverConf as Closure,
-                    REMOTE_ADDRESS_PROPERTY,
-                    container.seleniumAddress
+                gebConf.driverConf as Closure,
+                REMOTE_ADDRESS_PROPERTY,
+                container.seleniumAddress
             )
         } else {
             // If no driver was set in GebConfig, create a Firefox driver
@@ -284,6 +212,144 @@ class WebDriverContainerHolder {
         return true
     }
 
+    void setupBrowserUrl(IMethodInvocation methodInvocation) {
+        if (!browser) {
+            return
+        }
+
+        // use a configured baseUrl if found, otherwise use localhost and 
hostPort
+        def baseUrl = findBaseUrl(methodInvocation)
+        if (baseUrl != "") {
+            browser.baseUrl = baseUrl
+        } else {
+            int hostPort = findServerPort(methodInvocation)
+            Testcontainers.exposeHostPorts(hostPort)
+            browser.baseUrl = 
"$containerConf.protocol://$containerConf.hostName:$hostPort"
+        }
+    }
+
+    /**
+     * Returns the hostname that the server under test is available on from 
the host.
+     * <p>This is useful when using any of the {@code download*()} methods as 
they will
+     * connect from the host, and not from within the container.
+     *
+     * <p>Defaults to {@code localhost}. If the value returned by {@code 
webDriverContainer.getHost()}
+     * is different from the default, this method will return the same value 
same as
+     * {@code webDriverContainer.getHost()}.
+     *
+     * @return the hostname for accessing the server under test from the host
+     */
+    String getHostNameFromHost() {
+        hostNameChanged ? container.host : DEFAULT_HOSTNAME_FROM_HOST
+    }
+
+    /**
+     * Workaround for 
https://github.com/testcontainers/testcontainers-java/issues/3998
+     * <p>
+     * Restarts the VNC recording container to enable separate recording files 
for each
+     * test method. This method uses reflection to access the VNC recording 
container
+     * field in BrowserWebDriverContainer. Should be called BEFORE each test 
starts.
+     */
+    void restartVncRecordingContainer() {
+        if (!settings.recordingEnabled || 
!settings.restartRecordingContainerPerTest || !container) {
+            return
+        }
+        try {
+            // Use reflection to access the VNC recording container field
+            def field = 
BrowserWebDriverContainer.getDeclaredField('vncRecordingContainer').tap {
+                accessible = true
+            }
+
+            def vncContainer = field.get(container) as VncRecordingContainer
+            if (vncContainer) {
+                // Stop the current VNC recording container
+                vncContainer.stop()
+                // Create and start a new VNC recording container for the next 
test
+                def newVncContainer = new VncRecordingContainer(container)
+                    .withVncPassword('secret')
+                    .withVncPort(5900)
+                    .withVideoFormat(settings.recordingFormat)
+                field.set(container, newVncContainer)
+                newVncContainer.start()
+
+                log.debug('Successfully restarted VNC recording container')
+            }
+        } catch (Exception e) {
+            log.warn("Failed to restart VNC recording container: $e.message", 
e)
+            // Don't throw the exception to avoid breaking the test execution
+        }
+    }
+
+    /**
+     * Returns a host port to use for the container in this order:
+     * Class field 'hostPort' if found in the invocation (Spec).
+     * A 'hostPort' property in the GebConfig configuration.
+     * @param methodInvocation The method invocation.
+     * @return int The server port.
+     */
+    private static int findServerPort(IMethodInvocation methodInvocation) {
+        // use the test class hostPort if specified
+        try {
+            return (int) methodInvocation.instance.metaClass.getProperty(
+                    methodInvocation.instance,
+                    HOST_PORT_PROPERTY
+            )
+        } catch (ignored) {
+            // Grails throws an IllegalStateException about their annotation 
here.  We do not.
+            log.info("no ${HOST_PORT_PROPERTY} from methodInvocation")
+        }
+
+        try {
+            // use geb config setting or default 8080
+            Configuration gebConfig = new ConfigurationLoader().conf
+            return (int) gebConfig.rawConfig.getProperty(HOST_PORT_PROPERTY)
+        } catch (ignored) {
+            log.info("no ${HOST_PORT_PROPERTY} in config")
+        }
+
+        log.info("using default ${HOST_PORT_PROPERTY} 8080")
+        return 8080
+    }
+
+    /**
+     * Returns a baseUrl from a setting if found in this order:
+     * A class field 'baseUrl' if found in the invocation (Spec).
+     * A 'baseUrl' property in the GebConfig configuration.
+     * Or an empty String if not found.
+     * @param methodInvocation The method invocation.
+     * @return String The base URL.
+     */
+    private static String findBaseUrl(IMethodInvocation methodInvocation) {
+        // use the test class baseUrl if specified
+        try {
+            String baseUrl =  methodInvocation.instance.metaClass.getProperty(
+                    methodInvocation.instance,
+                    BASE_URL_PROPERTY
+            )
+            if (baseUrl) {
+                log.info("using ${BASE_URL_PROPERTY}: ${baseUrl} from method 
invocation.")
+                return baseUrl
+            }
+        } catch (ignored) {
+            log.info("no ${BASE_URL_PROPERTY} from methodInvocation")
+        }
+
+        try {
+            // use geb config setting or default
+            Configuration gebConfig = new ConfigurationLoader().conf
+            String baseUrl = gebConfig.getProperty(BASE_URL_PROPERTY) ?: ""
+            if (baseUrl != "") {
+                log.info("using ${BASE_URL_PROPERTY}: ${baseUrl} from 
configuration.")
+                return baseUrl
+            }
+        } catch (ignored) {
+            log.info("no ${BASE_URL_PROPERTY} in config.")
+        }
+
+        log.info("no configured ${BASE_URL_PROPERTY} found.")
+        return ""
+    }
+
     private static Browser createBrowser(Configuration gebConf) {
         def browser = new Browser(gebConf)
         try {
@@ -313,18 +379,24 @@ class WebDriverContainerHolder {
     private static void applyTimeouts(Browser browser, GrailsGebSettings 
settings) {
         // Overwrite `GebConfig` timeouts with values explicitly set in
         // `GrailsGebSettings` (via system properties)
-        if (settings.implicitlyWait != DEFAULT_TIMEOUT_IMPLICITLY_WAIT)
+        if (settings.implicitlyWait != DEFAULT_TIMEOUT_IMPLICITLY_WAIT) {
             
browser.driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(settings.implicitlyWait))
-        if (settings.pageLoadTimeout != DEFAULT_TIMEOUT_PAGE_LOAD)
+        }
+        if (settings.pageLoadTimeout != DEFAULT_TIMEOUT_PAGE_LOAD) {
             
browser.driver.manage().timeouts().pageLoadTimeout(Duration.ofSeconds(settings.pageLoadTimeout))
-        if (settings.scriptTimeout != DEFAULT_TIMEOUT_SCRIPT)
+        }
+        if (settings.scriptTimeout != DEFAULT_TIMEOUT_SCRIPT) {
             
browser.driver.manage().timeouts().scriptTimeout(Duration.ofSeconds(settings.scriptTimeout))
-        if (settings.atCheckWaiting != DEFAULT_AT_CHECK_WAITING)
+        }
+        if (settings.atCheckWaiting != DEFAULT_AT_CHECK_WAITING) {
             browser.config.atCheckWaiting = settings.atCheckWaiting
-        if (settings.timeout != Wait.DEFAULT_TIMEOUT)
+        }
+        if (settings.timeout != Wait.DEFAULT_TIMEOUT) {
             (browser.config.rawConfig.waiting as ConfigObject).timeout = 
settings.timeout
-        if (settings.retryInterval != Wait.DEFAULT_RETRY_INTERVAL)
+        }
+        if (settings.retryInterval != Wait.DEFAULT_RETRY_INTERVAL) {
             (browser.config.rawConfig.waiting as ConfigObject).retryInterval = 
settings.retryInterval
+        }
     }
 
     private static void startContainer(BrowserWebDriverContainer container, 
DockerImageName dockerImageName, String customBrowser) {
@@ -344,39 +416,6 @@ class WebDriverContainerHolder {
         }
     }
 
-    void setupBrowserUrl(IMethodInvocation methodInvocation) {
-        if (!browser) return
-
-        // use a configured baseUrl if found, otherwise use localhost and 
hostPort
-        def baseUrl = findBaseUrl(methodInvocation)
-        if (baseUrl != "") {
-            browser.baseUrl = baseUrl
-        } else {
-            int hostPort = findServerPort(methodInvocation)
-            Testcontainers.exposeHostPorts(hostPort)
-            browser.baseUrl = 
"$containerConf.protocol://$containerConf.hostName:$hostPort"
-        }
-
-    }
-
-    private GebTestManager createTestManager() {
-        new SpockGebTestManagerBuilder()
-                .withReportingEnabled(containerConf.reporting)
-                .withBrowserCreator(
-                        new Supplier<Browser>() {
-                            @Override
-                            Browser get() {
-                                browser
-                            }
-                        }
-                )
-                .build()
-    }
-
-    private boolean isHostnameChanged() {
-        containerConf.hostName != 
ContainerGebConfiguration.DEFAULT_HOSTNAME_FROM_CONTAINER
-    }
-
     private static String getHostIp() {
         try {
             PortForwardingContainer.getDeclaredMethod('getNetwork').with {
@@ -393,25 +432,6 @@ class WebDriverContainerHolder {
         }
     }
 
-    /**
-     * Returns the hostname that the server under test is available on from 
the host.
-     * <p>This is useful when using any of the {@code download*()} methods as 
they will
-     * connect from the host, and not from within the container.
-     *
-     * <p>Defaults to {@code localhost}. If the value returned by {@code 
webDriverContainer.getHost()}
-     * is different from the default, this method will return the same value 
same as
-     * {@code webDriverContainer.getHost()}.
-     *
-     * @return the hostname for accessing the server under test from the host
-     */
-    String getHostNameFromHost() {
-        hostNameChanged ? container.host : DEFAULT_HOSTNAME_FROM_HOST
-    }
-
-    private boolean isHostNameChanged() {
-        container.host != 
ContainerGebConfiguration.DEFAULT_HOSTNAME_FROM_CONTAINER
-    }
-
     private static DockerImageName createDockerImageName(Object browserName) {
         DockerImageName.parse(
                 "selenium/standalone-$browserName:$seleniumVersion"
@@ -431,6 +451,28 @@ class WebDriverContainerHolder {
         SeleniumUtils.determineClasspathSeleniumVersion()
     }
 
+    private GebTestManager createTestManager() {
+        new SpockGebTestManagerBuilder()
+                .withReportingEnabled(containerConf.reporting)
+                .withBrowserCreator(
+                        new Supplier<Browser>() {
+                            @Override
+                            Browser get() {
+                                browser
+                            }
+                        }
+                )
+                .build()
+    }
+
+    private boolean isHostnameChanged() {
+        containerConf.hostName != 
ContainerGebConfiguration.DEFAULT_HOSTNAME_FROM_CONTAINER
+    }
+
+    private boolean isHostNameChanged() {
+        container.host != 
ContainerGebConfiguration.DEFAULT_HOSTNAME_FROM_CONTAINER
+    }
+
     @CompileStatic
     @EqualsAndHashCode
     private static class WebDriverContainerConfiguration {
@@ -460,43 +502,6 @@ class WebDriverContainerHolder {
         }
     }
 
-    /**
-     * Workaround for 
https://github.com/testcontainers/testcontainers-java/issues/3998
-     * <p>
-     * Restarts the VNC recording container to enable separate recording files 
for each
-     * test method. This method uses reflection to access the VNC recording 
container
-     * field in BrowserWebDriverContainer. Should be called BEFORE each test 
starts.
-     */
-    void restartVncRecordingContainer() {
-        if (!settings.recordingEnabled || 
!settings.restartRecordingContainerPerTest || !container) {
-            return
-        }
-        try {
-            // Use reflection to access the VNC recording container field
-            def field = 
BrowserWebDriverContainer.getDeclaredField('vncRecordingContainer').tap {
-                accessible = true
-            }
-
-            def vncContainer = field.get(container) as VncRecordingContainer
-            if (vncContainer) {
-                // Stop the current VNC recording container
-                vncContainer.stop()
-                // Create and start a new VNC recording container for the next 
test
-                def newVncContainer = new VncRecordingContainer(container)
-                        .withVncPassword('secret')
-                        .withVncPort(5900)
-                        .withVideoFormat(settings.recordingFormat)
-                field.set(container, newVncContainer)
-                newVncContainer.start()
-
-                log.debug('Successfully restarted VNC recording container')
-            }
-        } catch (Exception e) {
-            log.warn("Failed to restart VNC recording container: $e.message", 
e)
-            // Don't throw the exception to avoid breaking the test execution
-        }
-    }
-
     @CompileStatic
     private static class ClosureDecorators {
 
@@ -521,7 +526,7 @@ class WebDriverContainerHolder {
         private static class SysPropScope {
 
             private static final ThreadLocal<Map<String,String>> 
OVERRIDDEN_SYSTEM_PROPERTIES =
-                    ThreadLocal.withInitial { [:] as Map<String,String> }
+                ThreadLocal.withInitial { [:] } as ThreadLocal<Map<String, 
String>>
 
             @Lazy // Thread-safe wrapping of system properties
             private static Properties propertiesWrappedOnFirstAccess = {
@@ -538,8 +543,14 @@ class WebDriverContainerHolder {
                 try {
                     return body.call()
                 } finally {
-                    if (prev == null) map.remove(key) else map[key] = prev
-                    if (map.isEmpty()) OVERRIDDEN_SYSTEM_PROPERTIES.remove()
+                    if (prev == null) {
+                        map.remove(key)
+                    } else {
+                        map[key] = prev
+                    }
+                    if (map.isEmpty()) {
+                        OVERRIDDEN_SYSTEM_PROPERTIES.remove()
+                    }
                 }
             }
 
@@ -554,8 +565,4 @@ class WebDriverContainerHolder {
         }
     }
 
-
-
-
-
 }
diff --git 
a/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/serviceloader/ServiceRegistry.groovy
 
b/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/serviceloader/ServiceRegistry.groovy
index 7b18c118..0d2b15a6 100644
--- 
a/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/serviceloader/ServiceRegistry.groovy
+++ 
b/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/serviceloader/ServiceRegistry.groovy
@@ -42,8 +42,8 @@ import groovy.transform.CompileStatic
 class ServiceRegistry {
 
     private static final ThreadLocal<HashMap<Class<?>, Object>> INSTANCES = 
ThreadLocal.withInitial {
-        new HashMap<Class<?>, Object>()
-    }
+        [:]
+    } as ThreadLocal<HashMap<Class<?>, Object>>
 
     /**
      * Returns the service instance of the given service type, loading it using
diff --git 
a/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/support/BrowserType.groovy
 
b/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/support/BrowserType.groovy
index 4ebefd32..b6ec9c49 100644
--- 
a/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/support/BrowserType.groovy
+++ 
b/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/support/BrowserType.groovy
@@ -19,12 +19,24 @@
 package grails.plugin.geb.support
 
 /**
+ * Represents the supported browser types.
  *
+ * <p>This enum defines the available browser options that can be used.</p>
  */
 enum BrowserType {
 
+    /**
+     * Google Chrome browser.
+     */
+
     CHROME,
+    /**
+     * Mozilla Firefox browser.
+     */
     FIREFOX,
-    EDGE
 
+    /**
+     * Microsoft Edge browser.
+     */
+    EDGE
 }
\ No newline at end of file
diff --git 
a/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/support/ContainerGebFileInputSource.groovy
 
b/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/support/ContainerGebFileInputSource.groovy
index 5ec39d57..23c11650 100644
--- 
a/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/support/ContainerGebFileInputSource.groovy
+++ 
b/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/support/ContainerGebFileInputSource.groovy
@@ -16,7 +16,6 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-
 package grails.plugin.geb.support
 
 /**
diff --git 
a/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/support/LocalhostDownloadSupport.groovy
 
b/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/support/LocalhostDownloadSupport.groovy
index 8f782c97..f2167fc9 100644
--- 
a/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/support/LocalhostDownloadSupport.groovy
+++ 
b/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/support/LocalhostDownloadSupport.groovy
@@ -31,7 +31,7 @@ import java.util.regex.Pattern
 @CompileStatic
 class LocalhostDownloadSupport extends DefaultDownloadSupport {
 
-    private final static Pattern urlPattern = 
~/(https?:\/\/)([^\/:]+)(:\d+\/.*)/
+    private final static Pattern URL_PATTERN = 
~/(https?:\/\/)([^\/:]+)(:\d+\/.*)/
 
     private final String hostNameFromHost
     private final Browser browser
@@ -48,7 +48,7 @@ class LocalhostDownloadSupport extends DefaultDownloadSupport 
{
     }
 
     private String resolveBase(Map options) {
-        return options.base ?: 
browser.driver.currentUrl.replaceAll(urlPattern) { match, proto, host, rest ->
+        return options.base ?: 
browser.driver.currentUrl.replaceAll(URL_PATTERN) { match, proto, host, rest ->
             "${proto}${hostNameFromHost}${rest}"
         }
     }
diff --git 
a/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/support/delegate/BrowserDelegate.groovy
 
b/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/support/delegate/BrowserDelegate.groovy
index 0ad9763a..4809047c 100644
--- 
a/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/support/delegate/BrowserDelegate.groovy
+++ 
b/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/support/delegate/BrowserDelegate.groovy
@@ -386,7 +386,7 @@ trait BrowserDelegate {
      * Delegates to {@link geb.Browser#setNetworkLatency(Duration)}.
      */
     void setNetworkLatency(Duration duration) {
-        browser.setNetworkLatency(duration)
+        browser.networkLatency = duration
     }
 
     /**
diff --git 
a/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/support/delegate/PageDelegate.groovy
 
b/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/support/delegate/PageDelegate.groovy
index 1706abe5..cbd5f259 100644
--- 
a/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/support/delegate/PageDelegate.groovy
+++ 
b/integration/geb-testcontainers/src/main/groovy/grails/plugin/geb/support/delegate/PageDelegate.groovy
@@ -409,7 +409,7 @@ trait PageDelegate implements Navigable, 
AlertAndConfirmSupport, WaitingSupport,
     }
 
     @Override
-    void interact(@DelegatesTo(strategy = 1, value = InteractDelegate.class) 
Closure interactionClosure) {
+    void interact(@DelegatesTo(strategy = 1, value = InteractDelegate) Closure 
interactionClosure) {
         page.interact(interactionClosure)
     }
 }
\ No newline at end of file


Reply via email to