From 1df8b31553cfb2683b7f1f9a948ec7b7349dad90 Mon Sep 17 00:00:00 2001 From: Jonas Pammer Date: Wed, 5 Mar 2025 07:48:26 +0100 Subject: [PATCH 1/6] boolean inheritance --- .../org/demo/spock/InheritedConfigSpec.groovy | 72 +++++++++++++++++++ .../groovy/org/demo/spock/RootPageSpec.groovy | 2 + .../geb/ContainerGebConfiguration.groovy | 9 +++ .../geb/WebDriverContainerHolder.groovy | 37 ++++++++-- 4 files changed, 116 insertions(+), 4 deletions(-) create mode 100644 spock-container-test-app/src/integration-test/groovy/org/demo/spock/InheritedConfigSpec.groovy diff --git a/spock-container-test-app/src/integration-test/groovy/org/demo/spock/InheritedConfigSpec.groovy b/spock-container-test-app/src/integration-test/groovy/org/demo/spock/InheritedConfigSpec.groovy new file mode 100644 index 00000000..272ff477 --- /dev/null +++ b/spock-container-test-app/src/integration-test/groovy/org/demo/spock/InheritedConfigSpec.groovy @@ -0,0 +1,72 @@ +package org.demo.spock + +import grails.plugin.geb.ContainerGebConfiguration +import grails.plugin.geb.ContainerGebSpec +import grails.testing.mixin.integration.Integration +import spock.lang.FailsWith + +/** + * Adaptation of {@link ServerNameControllerSpec} + */ +@Integration +@ContainerGebConfiguration(hostName = 'super.example.com', inherited = true) +class SuperSpec extends ContainerGebSpec {} +@Integration +@ContainerGebConfiguration(hostName = 'not.example.com') +class NotSuperSpec extends ContainerGebSpec {} + +@Integration +class InheritedConfigSpec extends SuperSpec { + void 'should show the right server name when visiting /serverName'() { + when: 'visiting the server name controller' + go '/serverName' + + then: 'the emitted hostname is correct' + $('p').text() == 'Server name: super.example.com' + } +} + +@Integration +class NotInheritedConfigSpec extends NotSuperSpec { + void 'should show the right server name when visiting /serverName'() { + when: 'visiting the server name controller' + go '/serverName' + + then: 'the emitted hostname is correct' + $('p').text() != 'Server name: not.example.com' + } +} + +@Integration +@ContainerGebConfiguration(hostName = 'child.example.com') +class ChildPreferenceInheritedConfigSpec extends SuperSpec { + void 'should show the right server name when visiting /serverName'() { + when: 'visiting the server name controller' + go '/serverName' + + then: 'the emitted hostname is correct' + $('p').text() == 'Server name: child.example.com' + + when: + report('whatever') + + then: + // geb.test.GebTestManager: "Reporting has not been enabled on this GebTestManager yet report() was called" + Throwable t = thrown(Exception) + t.message.contains("not been enabled") + } +} + +// No sane person would do this, but lets test anyway +@Integration +@ContainerGebConfiguration(reporting=true, inherited = true) +class MultipleInheritedConfigSpec extends SuperSpec { + void 'should show the right server name when visiting /serverName'() { + when: 'visiting the server name controller' + go '/serverName' + + then: 'the emitted hostname is correct' + $('p').text() == 'Server name: super.example.com' + report('multi inheritance report') + } +} diff --git a/spock-container-test-app/src/integration-test/groovy/org/demo/spock/RootPageSpec.groovy b/spock-container-test-app/src/integration-test/groovy/org/demo/spock/RootPageSpec.groovy index 766b52aa..4683f308 100644 --- a/spock-container-test-app/src/integration-test/groovy/org/demo/spock/RootPageSpec.groovy +++ b/spock-container-test-app/src/integration-test/groovy/org/demo/spock/RootPageSpec.groovy @@ -6,6 +6,7 @@ import geb.report.Reporter import grails.plugin.geb.ContainerGebConfiguration import grails.plugin.geb.ContainerGebSpec import grails.testing.mixin.integration.Integration +import spock.lang.Ignore /** * See https://docs.grails.org/latest/guide/testing.html#functionalTesting and https://www.gebish.org/manual/current/ @@ -16,6 +17,7 @@ import grails.testing.mixin.integration.Integration class RootPageSpec extends ContainerGebSpec { @Override + @Ignore Reporter createReporter() { // Override the default reporter to demonstrate how this can be customized new CompositeReporter(new PageSourceReporter()) diff --git a/src/testFixtures/groovy/grails/plugin/geb/ContainerGebConfiguration.groovy b/src/testFixtures/groovy/grails/plugin/geb/ContainerGebConfiguration.groovy index a24ce27b..2cf4ba10 100644 --- a/src/testFixtures/groovy/grails/plugin/geb/ContainerGebConfiguration.groovy +++ b/src/testFixtures/groovy/grails/plugin/geb/ContainerGebConfiguration.groovy @@ -34,6 +34,15 @@ import java.lang.annotation.Target static final String DEFAULT_HOSTNAME_FROM_CONTAINER = GenericContainer.INTERNAL_HOST_HOSTNAME static final String DEFAULT_PROTOCOL = 'http' + + /** + * Whether this annotation should be inherited by child classes. + * Children overwrites only work for non-default values. + * + * If the scenario concludes a multiple inheritance chain, the search stops when this is false. + * @since 4.2 + */ + boolean inherited() default false; /** * The protocol that the container's browser will use to access the server under test. diff --git a/src/testFixtures/groovy/grails/plugin/geb/WebDriverContainerHolder.groovy b/src/testFixtures/groovy/grails/plugin/geb/WebDriverContainerHolder.groovy index ef601bcb..1cb31c9c 100644 --- a/src/testFixtures/groovy/grails/plugin/geb/WebDriverContainerHolder.groovy +++ b/src/testFixtures/groovy/grails/plugin/geb/WebDriverContainerHolder.groovy @@ -206,13 +206,42 @@ class WebDriverContainerHolder { boolean reporting WebDriverContainerConfiguration(SpecInfo spec) { - ContainerGebConfiguration configuration = spec.annotations.find { + def configs = collectConfigurations(spec) + + // Merge configurations, later configs (child specs) override earlier ones (parent specs) + protocol = configs.findResult { it?.protocol() != ContainerGebConfiguration.DEFAULT_PROTOCOL ? it?.protocol() : null } ?: + ContainerGebConfiguration.DEFAULT_PROTOCOL + hostName = configs.findResult { it?.hostName() != ContainerGebConfiguration.DEFAULT_HOSTNAME_FROM_CONTAINER ? it?.hostName() : null } ?: + ContainerGebConfiguration.DEFAULT_HOSTNAME_FROM_CONTAINER + reporting = configs.any { it?.reporting() } + } + + private static List collectConfigurations(SpecInfo spec) { + List configs = [] + + // Add current spec's configuration + ContainerGebConfiguration current = spec.annotations.find { it.annotationType() == ContainerGebConfiguration } as ContainerGebConfiguration + + configs << current + + // If current config allows inheritance or doesn't exist, look at parent specs + if (current == null || current.inherited()) { + SpecInfo superSpec = spec.superSpec + while (superSpec != null) { + ContainerGebConfiguration parentConfig = superSpec.annotations.find { + it.annotationType() == ContainerGebConfiguration + } as ContainerGebConfiguration + + if (parentConfig?.inherited()) { + configs << parentConfig + } + superSpec = superSpec.superSpec + } + } - protocol = configuration?.protocol() ?: ContainerGebConfiguration.DEFAULT_PROTOCOL - hostName = configuration?.hostName() ?: ContainerGebConfiguration.DEFAULT_HOSTNAME_FROM_CONTAINER - reporting = configuration?.reporting() ?: false + return configs.findAll { it != null } } } } From 8172b43d5af236f25df1286728f13fa3b0a1767d Mon Sep 17 00:00:00 2001 From: Jonas Pammer Date: Wed, 5 Mar 2025 08:15:03 +0100 Subject: [PATCH 2/6] array inheritance --- .../org/demo/spock/InheritedConfigSpec.groovy | 8 ++++--- .../geb/ContainerGebConfiguration.groovy | 10 ++++----- .../geb/WebDriverContainerHolder.groovy | 21 ++++++++++++------- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/spock-container-test-app/src/integration-test/groovy/org/demo/spock/InheritedConfigSpec.groovy b/spock-container-test-app/src/integration-test/groovy/org/demo/spock/InheritedConfigSpec.groovy index 272ff477..9cfb3baf 100644 --- a/spock-container-test-app/src/integration-test/groovy/org/demo/spock/InheritedConfigSpec.groovy +++ b/spock-container-test-app/src/integration-test/groovy/org/demo/spock/InheritedConfigSpec.groovy @@ -9,7 +9,7 @@ import spock.lang.FailsWith * Adaptation of {@link ServerNameControllerSpec} */ @Integration -@ContainerGebConfiguration(hostName = 'super.example.com', inherited = true) +@ContainerGebConfiguration(hostName = 'super.example.com', inherited = ['hostName']) class SuperSpec extends ContainerGebSpec {} @Integration @ContainerGebConfiguration(hostName = 'not.example.com') @@ -59,8 +59,10 @@ class ChildPreferenceInheritedConfigSpec extends SuperSpec { // No sane person would do this, but lets test anyway @Integration -@ContainerGebConfiguration(reporting=true, inherited = true) -class MultipleInheritedConfigSpec extends SuperSpec { +@ContainerGebConfiguration(reporting=true, inherited=['reporting']) +class SuperSuperInheritedConfigSpec extends SuperSpec {} +@Integration +class MultipleInheritanceSpec extends SuperSuperInheritedConfigSpec { void 'should show the right server name when visiting /serverName'() { when: 'visiting the server name controller' go '/serverName' diff --git a/src/testFixtures/groovy/grails/plugin/geb/ContainerGebConfiguration.groovy b/src/testFixtures/groovy/grails/plugin/geb/ContainerGebConfiguration.groovy index 2cf4ba10..7312bb35 100644 --- a/src/testFixtures/groovy/grails/plugin/geb/ContainerGebConfiguration.groovy +++ b/src/testFixtures/groovy/grails/plugin/geb/ContainerGebConfiguration.groovy @@ -36,13 +36,13 @@ import java.lang.annotation.Target static final String DEFAULT_PROTOCOL = 'http' /** - * Whether this annotation should be inherited by child classes. - * Children overwrites only work for non-default values. - * - * If the scenario concludes a multiple inheritance chain, the search stops when this is false. + * List of properties that should be inherited by child classes. + * Valid values are: "protocol", "hostName", "reporting" + * An empty array means no properties are inherited. + * * @since 4.2 */ - boolean inherited() default false; + String[] inherited() default []; /** * The protocol that the container's browser will use to access the server under test. diff --git a/src/testFixtures/groovy/grails/plugin/geb/WebDriverContainerHolder.groovy b/src/testFixtures/groovy/grails/plugin/geb/WebDriverContainerHolder.groovy index 1cb31c9c..8fa8041d 100644 --- a/src/testFixtures/groovy/grails/plugin/geb/WebDriverContainerHolder.groovy +++ b/src/testFixtures/groovy/grails/plugin/geb/WebDriverContainerHolder.groovy @@ -216,26 +216,33 @@ class WebDriverContainerHolder { reporting = configs.any { it?.reporting() } } - private static List collectConfigurations(SpecInfo spec) { + private static List collectConfigurations(SpecInfo spec) { List configs = [] - + // Add current spec's configuration ContainerGebConfiguration current = spec.annotations.find { it.annotationType() == ContainerGebConfiguration } as ContainerGebConfiguration - + configs << current - // If current config allows inheritance or doesn't exist, look at parent specs - if (current == null || current.inherited()) { + // Look at parent specs if needed + if (current == null || current.inherited().length != 0) { + Set inheritedProps = current?.inherited()?.toList()?.toSet() ?: [] as Set SpecInfo superSpec = spec.superSpec while (superSpec != null) { ContainerGebConfiguration parentConfig = superSpec.annotations.find { it.annotationType() == ContainerGebConfiguration } as ContainerGebConfiguration - if (parentConfig?.inherited()) { - configs << parentConfig + if (parentConfig != null) { + // Only include parent config if it has properties we want to inherit + String[] parentInherited = parentConfig.inherited() + if (!inheritedProps.isEmpty() || parentInherited.length > 0) { + configs << parentConfig + // Update inherited props to include parent's inherited props + inheritedProps.addAll(Arrays.asList(parentInherited)) + } } superSpec = superSpec.superSpec } From 2c97a27350e66a240dd6c4c6b5411ddaf50ab31e Mon Sep 17 00:00:00 2001 From: Jonas Pammer Date: Wed, 5 Mar 2025 08:25:24 +0100 Subject: [PATCH 3/6] Revert annotation inheritance This reverts commit cfd896c954f2f4e387eefe78447cc66ad36c1d85. This reverts commit d98f80d1faf40d59aab33f4ff2763e7ade8cdddf. --- .../org/demo/spock/InheritedConfigSpec.groovy | 74 ------------------- .../groovy/org/demo/spock/RootPageSpec.groovy | 2 - .../geb/ContainerGebConfiguration.groovy | 9 --- .../geb/WebDriverContainerHolder.groovy | 44 +---------- 4 files changed, 4 insertions(+), 125 deletions(-) delete mode 100644 spock-container-test-app/src/integration-test/groovy/org/demo/spock/InheritedConfigSpec.groovy diff --git a/spock-container-test-app/src/integration-test/groovy/org/demo/spock/InheritedConfigSpec.groovy b/spock-container-test-app/src/integration-test/groovy/org/demo/spock/InheritedConfigSpec.groovy deleted file mode 100644 index 9cfb3baf..00000000 --- a/spock-container-test-app/src/integration-test/groovy/org/demo/spock/InheritedConfigSpec.groovy +++ /dev/null @@ -1,74 +0,0 @@ -package org.demo.spock - -import grails.plugin.geb.ContainerGebConfiguration -import grails.plugin.geb.ContainerGebSpec -import grails.testing.mixin.integration.Integration -import spock.lang.FailsWith - -/** - * Adaptation of {@link ServerNameControllerSpec} - */ -@Integration -@ContainerGebConfiguration(hostName = 'super.example.com', inherited = ['hostName']) -class SuperSpec extends ContainerGebSpec {} -@Integration -@ContainerGebConfiguration(hostName = 'not.example.com') -class NotSuperSpec extends ContainerGebSpec {} - -@Integration -class InheritedConfigSpec extends SuperSpec { - void 'should show the right server name when visiting /serverName'() { - when: 'visiting the server name controller' - go '/serverName' - - then: 'the emitted hostname is correct' - $('p').text() == 'Server name: super.example.com' - } -} - -@Integration -class NotInheritedConfigSpec extends NotSuperSpec { - void 'should show the right server name when visiting /serverName'() { - when: 'visiting the server name controller' - go '/serverName' - - then: 'the emitted hostname is correct' - $('p').text() != 'Server name: not.example.com' - } -} - -@Integration -@ContainerGebConfiguration(hostName = 'child.example.com') -class ChildPreferenceInheritedConfigSpec extends SuperSpec { - void 'should show the right server name when visiting /serverName'() { - when: 'visiting the server name controller' - go '/serverName' - - then: 'the emitted hostname is correct' - $('p').text() == 'Server name: child.example.com' - - when: - report('whatever') - - then: - // geb.test.GebTestManager: "Reporting has not been enabled on this GebTestManager yet report() was called" - Throwable t = thrown(Exception) - t.message.contains("not been enabled") - } -} - -// No sane person would do this, but lets test anyway -@Integration -@ContainerGebConfiguration(reporting=true, inherited=['reporting']) -class SuperSuperInheritedConfigSpec extends SuperSpec {} -@Integration -class MultipleInheritanceSpec extends SuperSuperInheritedConfigSpec { - void 'should show the right server name when visiting /serverName'() { - when: 'visiting the server name controller' - go '/serverName' - - then: 'the emitted hostname is correct' - $('p').text() == 'Server name: super.example.com' - report('multi inheritance report') - } -} diff --git a/spock-container-test-app/src/integration-test/groovy/org/demo/spock/RootPageSpec.groovy b/spock-container-test-app/src/integration-test/groovy/org/demo/spock/RootPageSpec.groovy index 4683f308..766b52aa 100644 --- a/spock-container-test-app/src/integration-test/groovy/org/demo/spock/RootPageSpec.groovy +++ b/spock-container-test-app/src/integration-test/groovy/org/demo/spock/RootPageSpec.groovy @@ -6,7 +6,6 @@ import geb.report.Reporter import grails.plugin.geb.ContainerGebConfiguration import grails.plugin.geb.ContainerGebSpec import grails.testing.mixin.integration.Integration -import spock.lang.Ignore /** * See https://docs.grails.org/latest/guide/testing.html#functionalTesting and https://www.gebish.org/manual/current/ @@ -17,7 +16,6 @@ import spock.lang.Ignore class RootPageSpec extends ContainerGebSpec { @Override - @Ignore Reporter createReporter() { // Override the default reporter to demonstrate how this can be customized new CompositeReporter(new PageSourceReporter()) diff --git a/src/testFixtures/groovy/grails/plugin/geb/ContainerGebConfiguration.groovy b/src/testFixtures/groovy/grails/plugin/geb/ContainerGebConfiguration.groovy index 7312bb35..a24ce27b 100644 --- a/src/testFixtures/groovy/grails/plugin/geb/ContainerGebConfiguration.groovy +++ b/src/testFixtures/groovy/grails/plugin/geb/ContainerGebConfiguration.groovy @@ -34,15 +34,6 @@ import java.lang.annotation.Target static final String DEFAULT_HOSTNAME_FROM_CONTAINER = GenericContainer.INTERNAL_HOST_HOSTNAME static final String DEFAULT_PROTOCOL = 'http' - - /** - * List of properties that should be inherited by child classes. - * Valid values are: "protocol", "hostName", "reporting" - * An empty array means no properties are inherited. - * - * @since 4.2 - */ - String[] inherited() default []; /** * The protocol that the container's browser will use to access the server under test. diff --git a/src/testFixtures/groovy/grails/plugin/geb/WebDriverContainerHolder.groovy b/src/testFixtures/groovy/grails/plugin/geb/WebDriverContainerHolder.groovy index 8fa8041d..ef601bcb 100644 --- a/src/testFixtures/groovy/grails/plugin/geb/WebDriverContainerHolder.groovy +++ b/src/testFixtures/groovy/grails/plugin/geb/WebDriverContainerHolder.groovy @@ -206,49 +206,13 @@ class WebDriverContainerHolder { boolean reporting WebDriverContainerConfiguration(SpecInfo spec) { - def configs = collectConfigurations(spec) - - // Merge configurations, later configs (child specs) override earlier ones (parent specs) - protocol = configs.findResult { it?.protocol() != ContainerGebConfiguration.DEFAULT_PROTOCOL ? it?.protocol() : null } ?: - ContainerGebConfiguration.DEFAULT_PROTOCOL - hostName = configs.findResult { it?.hostName() != ContainerGebConfiguration.DEFAULT_HOSTNAME_FROM_CONTAINER ? it?.hostName() : null } ?: - ContainerGebConfiguration.DEFAULT_HOSTNAME_FROM_CONTAINER - reporting = configs.any { it?.reporting() } - } - - private static List collectConfigurations(SpecInfo spec) { - List configs = [] - - // Add current spec's configuration - ContainerGebConfiguration current = spec.annotations.find { + ContainerGebConfiguration configuration = spec.annotations.find { it.annotationType() == ContainerGebConfiguration } as ContainerGebConfiguration - configs << current - - // Look at parent specs if needed - if (current == null || current.inherited().length != 0) { - Set inheritedProps = current?.inherited()?.toList()?.toSet() ?: [] as Set - SpecInfo superSpec = spec.superSpec - while (superSpec != null) { - ContainerGebConfiguration parentConfig = superSpec.annotations.find { - it.annotationType() == ContainerGebConfiguration - } as ContainerGebConfiguration - - if (parentConfig != null) { - // Only include parent config if it has properties we want to inherit - String[] parentInherited = parentConfig.inherited() - if (!inheritedProps.isEmpty() || parentInherited.length > 0) { - configs << parentConfig - // Update inherited props to include parent's inherited props - inheritedProps.addAll(Arrays.asList(parentInherited)) - } - } - superSpec = superSpec.superSpec - } - } - - return configs.findAll { it != null } + protocol = configuration?.protocol() ?: ContainerGebConfiguration.DEFAULT_PROTOCOL + hostName = configuration?.hostName() ?: ContainerGebConfiguration.DEFAULT_HOSTNAME_FROM_CONTAINER + reporting = configuration?.reporting() ?: false } } } From 9b505e26260f7320ae52c66f79dd2e6e11c71429 Mon Sep 17 00:00:00 2001 From: Jonas Pammer Date: Wed, 5 Mar 2025 08:41:46 +0100 Subject: [PATCH 4/6] actual implementation, by me the previous two reverted showcase things were claude lol (only committed as interesting) --- .../org/demo/spock/InheritedConfigSpec.groovy | 88 +++++++++++++++++++ .../geb/ContainerGebConfiguration.groovy | 17 ++++ .../geb/WebDriverContainerHolder.groovy | 14 ++- 3 files changed, 116 insertions(+), 3 deletions(-) create mode 100644 spock-container-test-app/src/integration-test/groovy/org/demo/spock/InheritedConfigSpec.groovy diff --git a/spock-container-test-app/src/integration-test/groovy/org/demo/spock/InheritedConfigSpec.groovy b/spock-container-test-app/src/integration-test/groovy/org/demo/spock/InheritedConfigSpec.groovy new file mode 100644 index 00000000..6dcbc6f3 --- /dev/null +++ b/spock-container-test-app/src/integration-test/groovy/org/demo/spock/InheritedConfigSpec.groovy @@ -0,0 +1,88 @@ +package org.demo.spock + +import grails.plugin.geb.ContainerGebConfiguration +import grails.plugin.geb.IContainerGebConfiguration +import grails.plugin.geb.ContainerGebSpec +import grails.testing.mixin.integration.Integration + +/** + * Adaptation of {@link ServerNameControllerSpec} + */ +@Integration +class SuperSpec extends ContainerGebSpec implements IContainerGebConfiguration { + @Override + String hostName() { + return 'super.example.com' + } +} +@Integration +@ContainerGebConfiguration(hostName = 'not.example.com') +class NotSuperSpec extends ContainerGebSpec { + +} + +@Integration +class InheritedConfigSpec extends SuperSpec { + void 'should show the right server name when visiting /serverName'() { + when: 'visiting the server name controller' + go '/serverName' + + then: 'the emitted hostname is correct' + $('p').text() == 'Server name: super.example.com' + } +} + +@Integration +class NotInheritedConfigSpec extends NotSuperSpec { + void 'should show the right server name when visiting /serverName'() { + when: 'visiting the server name controller' + go '/serverName' + + then: 'the emitted hostname is correct' + $('p').text() != 'Server name: not.example.com' + } +} + +@Integration +class ChildPreferenceInheritedConfigSpec extends SuperSpec { + @Override + String hostName() { + return 'child.example.com' + } + + void 'should show the right server name when visiting /serverName'() { + when: 'visiting the server name controller' + go '/serverName' + + then: 'the emitted hostname is correct' + $('p').text() == 'Server name: child.example.com' + + when: + report('whatever') + + then: + // geb.test.GebTestManager: "Reporting has not been enabled on this GebTestManager yet report() was called" + Throwable t = thrown(Exception) + t.message.contains("not been enabled") + } +} + +// No sane person would do this, but lets test anyway +@Integration +class SuperSuperInheritedConfigSpec extends SuperSpec { + @Override + boolean reporting() { + return true + } +} +@Integration +class MultipleInheritanceSpec extends SuperSuperInheritedConfigSpec { + void 'should show the right server name when visiting /serverName'() { + when: 'visiting the server name controller' + go '/serverName' + + then: 'the emitted hostname is correct' + $('p').text() == 'Server name: super.example.com' + report('multi inheritance report') + } +} diff --git a/src/testFixtures/groovy/grails/plugin/geb/ContainerGebConfiguration.groovy b/src/testFixtures/groovy/grails/plugin/geb/ContainerGebConfiguration.groovy index a24ce27b..80fa2367 100644 --- a/src/testFixtures/groovy/grails/plugin/geb/ContainerGebConfiguration.groovy +++ b/src/testFixtures/groovy/grails/plugin/geb/ContainerGebConfiguration.groovy @@ -52,4 +52,21 @@ import java.lang.annotation.Target * Whether reporting should be enabled for this test. Add a `GebConfig.groovy` to customize the reporter configuration. */ boolean reporting() default false +} + +/** + * Inheritable version of {@link ContainerGebConfiguration} + */ +interface IContainerGebConfiguration { + default String protocol() { + return ContainerGebConfiguration.DEFAULT_PROTOCOL + } + + default String hostName() { + return ContainerGebConfiguration.DEFAULT_HOSTNAME_FROM_CONTAINER + } + + default boolean reporting() { + return false + } } \ No newline at end of file diff --git a/src/testFixtures/groovy/grails/plugin/geb/WebDriverContainerHolder.groovy b/src/testFixtures/groovy/grails/plugin/geb/WebDriverContainerHolder.groovy index ef601bcb..9393d88f 100644 --- a/src/testFixtures/groovy/grails/plugin/geb/WebDriverContainerHolder.groovy +++ b/src/testFixtures/groovy/grails/plugin/geb/WebDriverContainerHolder.groovy @@ -206,9 +206,17 @@ class WebDriverContainerHolder { boolean reporting WebDriverContainerConfiguration(SpecInfo spec) { - ContainerGebConfiguration configuration = spec.annotations.find { - it.annotationType() == ContainerGebConfiguration - } as ContainerGebConfiguration + ContainerGebConfiguration configuration + + // Check if the class implements the interface + if (IContainerGebConfiguration.isAssignableFrom(spec.reflection)) { + configuration = spec.reflection.getConstructor().newInstance() as ContainerGebConfiguration + } else { + // Check for the annotation + configuration = spec.annotations.find { + it.annotationType() == ContainerGebConfiguration + } as ContainerGebConfiguration + } protocol = configuration?.protocol() ?: ContainerGebConfiguration.DEFAULT_PROTOCOL hostName = configuration?.hostName() ?: ContainerGebConfiguration.DEFAULT_HOSTNAME_FROM_CONTAINER From 9e1a3481c4363ca18ca2607ec3159d7a2aa83969 Mon Sep 17 00:00:00 2001 From: Jonas Pammer Date: Sun, 16 Mar 2025 08:01:28 +0100 Subject: [PATCH 5/6] reviewed --- .../groovy/org/demo/spock/InheritedConfigSpec.groovy | 6 +++--- .../plugin/geb/ContainerGebConfiguration.groovy | 11 +++++++---- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/spock-container-test-app/src/integration-test/groovy/org/demo/spock/InheritedConfigSpec.groovy b/spock-container-test-app/src/integration-test/groovy/org/demo/spock/InheritedConfigSpec.groovy index 6dcbc6f3..a7c10c4b 100644 --- a/spock-container-test-app/src/integration-test/groovy/org/demo/spock/InheritedConfigSpec.groovy +++ b/spock-container-test-app/src/integration-test/groovy/org/demo/spock/InheritedConfigSpec.groovy @@ -15,11 +15,10 @@ class SuperSpec extends ContainerGebSpec implements IContainerGebConfiguration { return 'super.example.com' } } + @Integration @ContainerGebConfiguration(hostName = 'not.example.com') -class NotSuperSpec extends ContainerGebSpec { - -} +class NotSuperSpec extends ContainerGebSpec {} @Integration class InheritedConfigSpec extends SuperSpec { @@ -75,6 +74,7 @@ class SuperSuperInheritedConfigSpec extends SuperSpec { return true } } + @Integration class MultipleInheritanceSpec extends SuperSuperInheritedConfigSpec { void 'should show the right server name when visiting /serverName'() { diff --git a/src/testFixtures/groovy/grails/plugin/geb/ContainerGebConfiguration.groovy b/src/testFixtures/groovy/grails/plugin/geb/ContainerGebConfiguration.groovy index 80fa2367..5d7e38f1 100644 --- a/src/testFixtures/groovy/grails/plugin/geb/ContainerGebConfiguration.groovy +++ b/src/testFixtures/groovy/grails/plugin/geb/ContainerGebConfiguration.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2024 original author or authors + * Copyright 2024-2025 original author or authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -56,17 +56,20 @@ import java.lang.annotation.Target /** * Inheritable version of {@link ContainerGebConfiguration} + * + * @since 4.2 */ interface IContainerGebConfiguration { + default String protocol() { - return ContainerGebConfiguration.DEFAULT_PROTOCOL + ContainerGebConfiguration.DEFAULT_PROTOCOL } default String hostName() { - return ContainerGebConfiguration.DEFAULT_HOSTNAME_FROM_CONTAINER + ContainerGebConfiguration.DEFAULT_HOSTNAME_FROM_CONTAINER } default boolean reporting() { - return false + false } } \ No newline at end of file From 37d45faa72eacaa30e407ec185ca547664f468ed Mon Sep 17 00:00:00 2001 From: Jonas Pammer Date: Sun, 16 Mar 2025 08:06:33 +0100 Subject: [PATCH 6/6] mention in documentation --- README.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 65fdc037..800fd047 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,18 @@ Just run `./gradlew integrationTest` and a container will be started and configu #### Custom Host Configuration -The annotation `ContainerGebConfiguration` exists to customize the connection the container will use to access the application under test. The annotation is not required and `ContainerGebSpec` will use the default values in this annotation if it's not present. +The annotation `ContainerGebConfiguration` exists to customize the connection the container will use to access the application under test. +The annotation is not required and `ContainerGebSpec` will use the default values in this annotation if it's not present. + +The interface `IContainerGebConfiguration` exists as an inheritable version of the annotation. + +#### Reporting + +To configure reporting, enable it using the `recording` property on the annotation `ContainerGebConfiguration`. The following system properties exist for reporting configuration: + +* `grails.geb.reporting.directory` + * purpose: if the test enables reporting, the directory to save the reports relative to the project directory + * defaults to `build/gebContainer/reports` #### Recording By default, no test recording will be performed. Here are the system properties available to change the recording behavior: