You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@causeway.apache.org by da...@apache.org on 2024/03/05 08:56:26 UTC

(causeway) 01/01: CAUSEWAY-3676: adds docs on testing; minor renames

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

danhaywood pushed a commit to branch CAUSEWAY-3676
in repository https://gitbox.apache.org/repos/asf/causeway.git

commit 881e0264c5526e2005b3ff0fb751076560bc265e
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Tue Mar 5 08:55:35 2024 +0000

    CAUSEWAY-3676: adds docs on testing; minor renames
---
 .../core/config/CausewayConfiguration.java         |  76 +++--
 viewers/graphql/adoc/modules/ROOT/pages/about.adoc | 145 +--------
 .../ROOT/pages/setup-and-configuration.adoc        |   8 +-
 .../adoc/modules/ROOT/pages/testsupport.adoc       | 351 +++++++++++++++++++++
 .../model/domain/common/SchemaStrategy.java        |   8 +-
 .../domain/common/query/CommonDomainObject.java    |   8 +-
 .../domain/common/query/CommonDomainService.java   |   2 +-
 .../model/domain/rich/SchemaStrategyRich.java      |  12 +-
 .../model/domain/rich/query/RichTopLevelQuery.java |   2 +-
 .../model/domain/simple/SchemaStrategySimple.java  |  10 +-
 .../viewer/test/schema/PrintSchemaIntegTest.java   |   6 +
 .../src/test/resources/application-test.properties |   3 +-
 .../schema/PrintSchemaIntegTestAbstract.java       |   4 +-
 13 files changed, 435 insertions(+), 200 deletions(-)

diff --git a/core/config/src/main/java/org/apache/causeway/core/config/CausewayConfiguration.java b/core/config/src/main/java/org/apache/causeway/core/config/CausewayConfiguration.java
index ab7631151b..6ee570bb3d 100644
--- a/core/config/src/main/java/org/apache/causeway/core/config/CausewayConfiguration.java
+++ b/core/config/src/main/java/org/apache/causeway/core/config/CausewayConfiguration.java
@@ -2364,7 +2364,7 @@ public class CausewayConfiguration {
                  *
                  * <p>
                  *     Optionally, fields for Scenario (given/when/then) testing may also be added if the
-                 *     {@link #isIncludeTestingFieldInRich()} config property is set.
+                 *     {@link #isEnableScenarioTestingForRich()} config property is set.
                  * </p>
                  * <p>
                  *     Suitable for clients where the application logic and state remains in the backend, within the
@@ -2407,34 +2407,52 @@ public class CausewayConfiguration {
              */
             private SchemaStyle schemaStyle = SchemaStyle.RICH_AND_SIMPLE;
 
-            /**
-             * If the {@link #getSchemaStyle()} is set to {@link SchemaStyle#SIMPLE_AND_RICH}, defines the name of the
-             * top-level field under which the &quot;simple&quot; schema resides.
-             *
-             * <p>
-             *     Ignored for any other {@link #getSchemaStyle()}.
-             * </p>
-             */
-            private String topLevelFieldNameForSimple = "simple";
-            /**
-             * If the {@link #getSchemaStyle()} is set to {@link SchemaStyle#SIMPLE_AND_RICH}, defines the name of the
-             * top-level field under which the &quot;rich&quot; schema resides.
-             *
-             * <p>
-             *     Ignored for any other {@link #getSchemaStyle()}.
-             * </p>
-             */
-            private String topLevelFieldNameForRich = "rich";
-            /**
-             * If the {@link #getSchemaStyle()} is set to either {@link SchemaStyle#RICH_ONLY} or
-             * {@link SchemaStyle#SIMPLE_AND_RICH}, then determines whether the &quot;Scenario&quot; field is included
-             * in order to allow given/when/then tests to be expressed.
-             *
-             * <p>
-             *     Ignored if the {@link #getSchemaStyle()} is {@link SchemaStyle#SIMPLE_ONLY}.
-             * </p>
-             */
-            private boolean includeTestingFieldInRich = true;
+            private final Schema schema = new Schema();
+            @Data
+            public static class Schema {
+
+                private final Simple simple = new Simple();
+                @Data
+                public static class Simple {
+
+                    /**
+                     * If the {@link #getSchemaStyle()} is set to {@link SchemaStyle#SIMPLE_AND_RICH}, defines the name of the
+                     * top-level field under which the &quot;simple&quot; schema resides.
+                     *
+                     * <p>
+                     *     Ignored for any other {@link #getSchemaStyle()}.
+                     * </p>
+                     */
+                    private String topLevelFieldName = "simple";
+                }
+
+                private final Rich rich = new Rich();
+                @Data
+                public static class Rich {
+
+                    /**
+                     * If the {@link #getSchemaStyle()} is set to {@link SchemaStyle#SIMPLE_AND_RICH}, defines the name of the
+                     * top-level field under which the &quot;rich&quot; schema resides.
+                     *
+                     * <p>
+                     *     Ignored for any other {@link #getSchemaStyle()}.
+                     * </p>
+                     */
+                    private String topLevelFieldName = "rich";
+
+                    /**
+                     * If the {@link #getSchemaStyle()} is set to either {@link SchemaStyle#RICH_ONLY} or
+                     * {@link SchemaStyle#SIMPLE_AND_RICH}, then determines whether the &quot;Scenario&quot; field is included
+                     * in order to allow given/when/then tests to be expressed.
+                     *
+                     * <p>
+                     *     Ignored if the {@link #getSchemaStyle()} is {@link SchemaStyle#SIMPLE_ONLY}.
+                     * </p>
+                     */
+                    private boolean enableScenarioTesting = false;
+                }
+            }
+
 
             public enum ApiVariant {
                 /**
diff --git a/viewers/graphql/adoc/modules/ROOT/pages/about.adoc b/viewers/graphql/adoc/modules/ROOT/pages/about.adoc
index f3aae783d5..6349df0b61 100644
--- a/viewers/graphql/adoc/modules/ROOT/pages/about.adoc
+++ b/viewers/graphql/adoc/modules/ROOT/pages/about.adoc
@@ -41,6 +41,7 @@ In summary, the API variant therefore relates to whether and how mutating (non-s
 
 
 
+[#rich-vs-simple-schemas]
 === Rich vs Simple Schemas
 
 The viewer can represent the domain model as either a "rich" GraphQL schema, or a "simple" GraphQL schema; or indeed both can be supported ath the same time.
@@ -238,7 +239,7 @@ These can only be downloaded if configured, see xref:#resources-blobs-clobs-layo
 
 * `cssClass` (as per the xref:userguide:ROOT:ui-layout-and-hints.adoc#object-css-styling[cssClass()] supporting method)
 
-There is also one additional field, `saveAs`; this is discussed in the xref:#testing[testing] section below.
+There is also one additional field, `saveAs`; this is discussed in the xref:testsupport.adoc[Test Support].
 
 
 [#queries-that-lookup-a-domain-object]
@@ -732,145 +733,3 @@ If you do this, then you should also make sure that the resource controller is m
 
 
 
-[#testing]
-== Testing
-
-Because the "rich" schema exposes pretty much all the behaviour of the domain model, it's possible to use GraphQL queries as a way to write end-to-end tests.
-This works especially well with link:https://github.com/approvals/ApprovalTests.Java[approval tests], which can be used to efficiently assert the contents of the returned response.
-
-Testing support is enabled with the xref:refguide:config:sections/causeway.viewer.graphql.adoc#causeway.viewer.graphql.include-testing-field-in-rich[causeway.viewer.graphql.include-testing-field-in-rich] configuration property.
-This then allows the "`rich`" schema to include a new field "`Scenario`", which in turn can have three further fields, "`Given`", "`When`" and "`Then`".
-The scenario can also be named.
-
-Moreover, the testing support introduces a "saveAs" capability (within the xref:#the-meta-fieldtype[meta] field) to tag objects and then use them at a later stage.
-
-This is all probably most easily explained with an example:
-
-[source,graphql]
-----
-{
-  rich {
-    Scenario(name: "Find department and change its name"){    #<.>
-      Name                                                    #<1>
-
-      Given {                                                 #<.>
-        university_dept_Departments {
-          findDepartmentByName {
-            invoke(name: "Classics") {
-              args {
-                name
-              }
-              results {
-                _meta {
-                  saveAs(ref: "dept#1")                       #<.>
-                }
-              }
-            }
-          }
-        }
-      }
-
-      When {                                                  #<.>
-        university_dept_Department(
-            object: {ref: "dept#1"}                           #<.>
-        ) {
-          name {
-            get
-          }
-          changeName {
-            invokeIdempotent(newName: "Ancient History") {
-              args {
-                newName                                       #<.>
-              }
-              results {                                       #<.>
-                name {
-                  get
-                }
-              }
-            }
-          }
-        }
-      }
-
-      Then {
-        university_dept_Department(object: {ref: "dept#1"}) {
-          name {
-            get                                               #<.>
-          }
-        }
-      }
-    }
-  }
-}
-----
-<.> We name the scenario.
-The `Name` field means that the scenario's name will be printed out in the response.
-<.> Under the `Given` field, we set up or locate the objects that are to be interacted with within the scenario.
-<.> Having found an object, we save it with some meaningful name.
-<.> Under the `When` field, we interact with the object.
-<.> We use the tag from before to locate the object
-<.> We request to print out the arguments
-<.> The object is changed
-<.> We assert on the results
-
-This will result in a response such as:
-
-[source,json]
-----
-{
-  "data" : {
-    "rich" : {
-      "Scenario" : {
-        "Name" : "Find department and change its name",
-        "Given" : {
-          "university_dept_Departments" : {
-            "findDepartmentByName" : {
-              "invoke" : {
-                "args" : {
-                  "name" : "Classics"
-                },
-                "results" : {
-                  "_meta" : {
-                    "saveAs" : "dept#1  "
-                  }
-                }
-              }
-            }
-          }
-        },
-        "When" : {
-          "university_dept_Department" : {
-            "name": {
-              "get": "Classics"
-            },
-            "changeName" : {
-              "invokeIdempotent" : {
-                "args" : {
-                  "newName" : "Ancient History"
-                },
-                "results" : {
-                  "name" : {
-                    "get" : "Ancient History"
-                  }
-                }
-              }
-            }
-          }
-        },
-        "Then" : {
-          "university_dept_Department" : {
-            "name" : {
-              "get" : "Ancient History"
-            }
-          }
-        }
-      }
-    }
-  }
-}
-----
-
-In this case you'll notice that the `Then` field doesn't actually show any additional assertions to those already in the `When` clause, so it could have been omitted.
-
-
-
diff --git a/viewers/graphql/adoc/modules/ROOT/pages/setup-and-configuration.adoc b/viewers/graphql/adoc/modules/ROOT/pages/setup-and-configuration.adoc
index bbd80022c2..aaea8254bd 100644
--- a/viewers/graphql/adoc/modules/ROOT/pages/setup-and-configuration.adoc
+++ b/viewers/graphql/adoc/modules/ROOT/pages/setup-and-configuration.adoc
@@ -52,14 +52,14 @@ These were discussed on the xref:gqlv:ROOT:about.adoc[main page for GraphQL view
 A number of other configuration properties can customize the schema in various ways.
 Normally these can be left as their default:
 
-* xref:refguide:config:sections/causeway.viewer.graphql.adoc#causeway.viewer.graphql.top-level-field-name-for-simple[top-level-field-name-for-simple]
+* xref:refguide:config:sections/causeway.viewer.graphql.adoc#causeway.viewer.graphql.schema.simple.top-level-field-name[schema.simple.top-level-field-name]
 +
 If using the `SIMPLE_AND_RICH` or `RICH_AND_SIMPLE` schema styles, this configuration defines the name of the top-level field that holds the rest of the _simple_ schema.
 +
 It defaults to "`simple`".
 
 
-* xref:refguide:config:sections/causeway.viewer.graphql.adoc#causeway.viewer.graphql.top-level-field-name-for-rich[top-level-field-name-for-rich]
+* xref:refguide:config:sections/causeway.viewer.graphql.adoc#causeway.viewer.graphql.schema.simple.top-level-field-name[schema.simple.top-level-field-name]
 +
 If using the `SIMPLE_AND_RICH` or `RICH_AND_SIMPLE` schema styles, this configuration defines the name of the top-level field that holds the rest of the _rich_ schema.
 +
@@ -108,9 +108,9 @@ The remaining configuration properties are explained in more detail elsewhere:
 +
 Control whether the xref:about.adoc#resources-blobs-clobs-layouts-icons[Resource controller] is enabled
 
-* xref:refguide:config:sections/causeway.viewer.graphql.adoc#causeway.viewer.graphql.include-testing-field-in-rich[include-testing-field-in-rich]
+* xref:refguide:config:sections/causeway.viewer.graphql.adoc#causeway.viewer.graphql.schema.rich.enable-scenario-testing[schema.rich.enable-scenario-testing]
 +
-Enable xref:about.adoc#testing[testing support].
+Enable xref:testsupport.adoc#scenario-tests[scenario testing].
 
 * xref:refguide:config:sections/causeway.viewer.graphql.adoc#causeway.viewer.graphql.authentication.fallback.username[authentication.fallback.username] and xref:refguide:config:sections/causeway.viewer.graphql.adoc#causeway.viewer.graphql.authentication.fallback.roles[authentication.fallback.roles]
 +
diff --git a/viewers/graphql/adoc/modules/ROOT/pages/testsupport.adoc b/viewers/graphql/adoc/modules/ROOT/pages/testsupport.adoc
new file mode 100644
index 0000000000..bb019a8a6e
--- /dev/null
+++ b/viewers/graphql/adoc/modules/ROOT/pages/testsupport.adoc
@@ -0,0 +1,351 @@
+= Test Support
+
+:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you 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 ag [...]
+
+
+Because the xref:about.adoc#rich-vs-simple-schemas[rich] schema exposes pretty much all the behaviour of the domain model, it's possible to use GraphQL queries as a way to write end-to-end tests.
+This works especially well with link:https://github.com/approvals/ApprovalTests.Java[approval tests], which can be used to efficiently assert the contents of the returned response.
+
+
+== Print Schema
+
+When writing tests, it can be useful to first generate the schema.
+You can then register the schema with a dedicated editor; this can then provide code-completion.
+Some IDEs (for example IntelliJ IDEA) also provide this capability.
+
+The `PrintSchemaIntegTestAbstract`
+To generate the schema, just include
+
+[source,java]
+----
+import org.springframework.test.context.DynamicPropertyRegistry;
+import org.springframework.test.context.DynamicPropertySource;
+
+import org.apache.causeway.viewer.graphql.viewer.testsupport.schema.PrintSchemaIntegTestAbstract;
+
+import static org.apache.causeway.core.config.CausewayConfiguration.Viewer.Graphql.ApiVariant;
+
+@Import({
+        UniversityModule.class                                      // <.>
+})
+public class PrintSchemaIntegTest
+    extends PrintSchemaIntegTestAbstract {                          // <.>
+
+    @DynamicPropertySource
+    static void apiVariant(DynamicPropertyRegistry registry) {      // <.>
+        registry.add("causeway.viewer.graphql.api-variant",
+            ApiVariant.QUERY_WITH_MUTATIONS_NON_SPEC_COMPLIANT::name);
+    }
+}
+----
+<.> specifies the domain module(s) to test
+<.> subclass from the superclass
+<.> optionally specify the API variant.
+You could also use `application-test.properties` or `application-test.yml`
+
+This will then write out a `schema.gql` file into `src/test/resources` of the maven module containing the test class.
+
+== Integration Test Support
+
+The `CausewayViewerGraphqlIntegTestAbstract` class is intended to be used as the base class for your integration tests.
+It spins up an instance of the app (listening on a random port), and then allows you to submit queries and mutations against the backend.
+
+Since most tests consist of a query and then checking a response, the superclass also provides some sophisticated support here.
+All you need to do is to save your queries in the same package as your subclass.
+These are automatically picked by the test class, submitted, and then the approval tests assertion library is used to compare the results.
+
+The first time you run the tests, they will of course fail because you will be missing the "approved" responses.
+Check that the received response is as expect, and then approve it.
+
+To use it subclass it, use `@Import` to specify the modules to be tested, and then save queries or mutations as files in the same package.
+
+For example:
+
+[source,java]
+.Calculator.java
+----
+@Named("calculator.Calculator")
+@DomainService(nature= NatureOfService.VIEW)
+@RequiredArgsConstructor(onConstructor_ = {@Inject})
+public class Calculator {
+
+    @Action(semantics = SemanticsOf.SAFE)
+    public boolean and(boolean x, boolean y) {
+        return x & y;
+    }
+
+    @Action(semantics = SemanticsOf.SAFE)
+    public String concat( String prefix, String suffix) {
+        return prefix + suffix;
+    }
+}
+----
+
+To test this service, we would use:
+
+[source,java]
+.Calculator_IntegTest.java
+----
+import org.apache.causeway.viewer.graphql.viewer.testsupport.PrintSchemaIntegTestAbstract;
+
+@Import({
+        CalculatorModule.class                              // <.>
+})
+public class Calculator_IntegTest
+    extends CausewayViewerGraphqlIntegTestAbstract {        // <.>
+
+    protected Calculator_IntegTest() {
+        super(Calculator_IntegTest.class);                  // <.>
+    }
+
+    @Override
+    @TestFactory
+    public Iterable<DynamicTest> each() throws Exception {  // <.>
+        return super.each();
+    }
+}
+----
+<.> specifies the domain module(s) to test
+<.> subclass from the superclass
+<.> indicates which package to pick up the queries
+<.> dynamically generates tests for each query
+
+Then include the following tests in the same package, using the naming convention:
+
+__class_name__``.each.``__anything_you_want__``._.gql``
+
+The word "each" comes from the name of the overridden method.
+If you want to change the "_.gql" suffix, you can pass an additional argument in the constructor.
+
+For example:
+
+* to exhaustively test the `Calculator#and()` action:
++
+[source,graphql]
+.Calculator_IntegTest.each.and_1._.gql
+----
+{
+  rich {
+    university_calc_Calculator {
+      and {
+        invoke(x: true, y: true) {
+          results
+        }
+      }
+    }
+  }
+}
+----
++
+[source,graphql]
+.Calculator_IntegTest.each.and_2._.gql
+----
+{
+  rich {
+    university_calc_Calculator {
+      and {
+        invoke(x: true, y: false) {
+          results
+        }
+      }
+    }
+  }
+}
+----
++
+[source,graphql]
+.Calculator_IntegTest.each.and_3._.gql
+----
+{
+  rich {
+    university_calc_Calculator {
+      and {
+        invoke(x: false, y: true) {
+          results
+        }
+      }
+    }
+  }
+}
+----
++
+[source,graphql]
+.Calculator_IntegTest.each.and_4._.gql
+----
+{
+  rich {
+    university_calc_Calculator {
+      and {
+        invoke(x: false, y: false) {
+          results
+        }
+      }
+    }
+  }
+}
+----
+
+* or, to test the `concat` action:
++
+[source,graphql]
+.Calculator_IntegTest.each.and_1._.gql
+----
+{
+  rich {
+    university_calc_Calculator {
+      concat {
+        invoke(prefix: "Fizz", suffix: "Buzz") {
+          results
+        }
+      }
+    }
+  }
+}
+----
+
+
+For further examples, take a look at the link:https://github.com/apache/causeway/tree/master/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e[tests for the GraphQL viewer itself], which use this class extensively.
+
+
+
+
+
+[#scenario-tests]
+== Scenario Tests
+
+The GraphQL viewer also supports what we call scenario tests.
+This is an extension to the rich schema, to include a new field "`Scenario`" which in turn can have three further fields, "`Given`", "`When`" and "`Then`".
+The scenario can also be named.
+
+Moreover, scenario test enables introduces a "saveAs" capability (within the xref:about.adoc#the-meta-fieldtype[meta] field) to tag objects and then use them at a later stage.
+
+This is all probably most easily explained with an example:
+
+[source,graphql]
+----
+{
+  rich {
+    Scenario(name: "Find department and change its name"){    #<.>
+      Name                                                    #<1>
+
+      Given {                                                 #<.>
+        university_dept_Departments {
+          findDepartmentByName {
+            invoke(name: "Classics") {
+              args {
+                name
+              }
+              results {
+                _meta {
+                  saveAs(ref: "dept#1")                       #<.>
+                }
+              }
+            }
+          }
+        }
+      }
+
+      When {                                                  #<.>
+        university_dept_Department(
+            object: {ref: "dept#1"}                           #<.>
+        ) {
+          name {
+            get
+          }
+          changeName {
+            invokeIdempotent(newName: "Ancient History") {
+              args {
+                newName                                       #<.>
+              }
+              results {                                       #<.>
+                name {
+                  get
+                }
+              }
+            }
+          }
+        }
+      }
+
+      Then {
+        university_dept_Department(object: {ref: "dept#1"}) {
+          name {
+            get                                               #<.>
+          }
+        }
+      }
+    }
+  }
+}
+----
+<.> We name the scenario.
+The `Name` field means that the scenario's name will be printed out in the response.
+<.> Under the `Given` field, we set up or locate the objects that are to be interacted with within the scenario.
+<.> Having found an object, we save it with some meaningful name.
+<.> Under the `When` field, we interact with the object.
+<.> We use the tag from before to locate the object
+<.> We request to print out the arguments
+<.> The object is changed
+<.> We assert on the results
+
+This will result in a response such as:
+
+[source,json]
+----
+{
+  "data" : {
+    "rich" : {
+      "Scenario" : {
+        "Name" : "Find department and change its name",
+        "Given" : {
+          "university_dept_Departments" : {
+            "findDepartmentByName" : {
+              "invoke" : {
+                "args" : {
+                  "name" : "Classics"
+                },
+                "results" : {
+                  "_meta" : {
+                    "saveAs" : "dept#1  "
+                  }
+                }
+              }
+            }
+          }
+        },
+        "When" : {
+          "university_dept_Department" : {
+            "name": {
+              "get": "Classics"
+            },
+            "changeName" : {
+              "invokeIdempotent" : {
+                "args" : {
+                  "newName" : "Ancient History"
+                },
+                "results" : {
+                  "name" : {
+                    "get" : "Ancient History"
+                  }
+                }
+              }
+            }
+          }
+        },
+        "Then" : {
+          "university_dept_Department" : {
+            "name" : {
+              "get" : "Ancient History"
+            }
+          }
+        }
+      }
+    }
+  }
+}
+----
+
+In this case you'll notice that the `Then` field doesn't actually show any additional assertions to those already in the `When` clause, so it could have been omitted.
+
+
+Testing support is enabled with the xref:refguide:config:sections/causeway.viewer.graphql.adoc#causeway.viewer.graphql.schema.rich.enable-scenario-testing[causeway.viewer.graphql.schema.rich.enable-scenario-testing] configuration property.
diff --git a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/common/SchemaStrategy.java b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/common/SchemaStrategy.java
index cb7e0b1d94..fb37b7003a 100644
--- a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/common/SchemaStrategy.java
+++ b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/common/SchemaStrategy.java
@@ -64,25 +64,25 @@ public interface SchemaStrategy {
 
     String topLevelFieldNameFrom(CausewayConfiguration.Viewer.Graphql graphqlConfiguration);
 
-    Element newGqlvProperty(
+    Element newProperty(
             final ObjectInteractor holder,
             final OneToOneAssociation otoa,
             final Context context
     );
 
-    Element newGqlvCollection(
+    Element newCollection(
             final ObjectInteractor holder,
             final OneToManyAssociation otma,
             final Context context
     );
 
-    Element newGqlvAction(
+    Element newAction(
             final ObjectInteractor holder,
             final ObjectAction objectAction,
             final Context context
     );
 
-    ElementCustom newGqlvMeta(
+    ElementCustom newMeta(
             final CommonDomainObject commonDomainObject,
             final Context context);
 
diff --git a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/common/query/CommonDomainObject.java b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/common/query/CommonDomainObject.java
index 4241d512e1..6e96e08c94 100644
--- a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/common/query/CommonDomainObject.java
+++ b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/common/query/CommonDomainObject.java
@@ -86,7 +86,7 @@ public class CommonDomainObject
 
         gqlObjectTypeBuilder.description(objectSpecification.getDescription());
 
-        addChildFieldFor(this.meta = schemaStrategy.newGqlvMeta(this, context));
+        addChildFieldFor(this.meta = schemaStrategy.newMeta(this, context));
 
         val inputObjectTypeBuilder = newInputObject().name(TypeNames.inputTypeNameFor(objectSpecification, getSchemaType()));
         inputObjectTypeBuilder
@@ -160,12 +160,12 @@ public class CommonDomainObject
     private void addMembers() {
 
         objectSpecification.streamProperties(MixedIn.INCLUDED)
-                .forEach(prop -> properties.add(addChildFieldFor(schemaStrategy.newGqlvProperty(this, prop, context))));
+                .forEach(prop -> properties.add(addChildFieldFor(schemaStrategy.newProperty(this, prop, context))));
         objectSpecification.streamCollections(MixedIn.INCLUDED)
-                .forEach(coll -> collections.add(addChildFieldFor(schemaStrategy.newGqlvCollection(this, coll, context))));
+                .forEach(coll -> collections.add(addChildFieldFor(schemaStrategy.newCollection(this, coll, context))));
         objectSpecification.streamActions(context.getActionScope(), MixedIn.INCLUDED)
                 .filter(act -> schemaStrategy.shouldInclude(graphqlConfiguration.getApiVariant(), act))
-                .forEach(act -> actions.add(addChildFieldFor(schemaStrategy.newGqlvAction(this, act, context))));
+                .forEach(act -> actions.add(addChildFieldFor(schemaStrategy.newAction(this, act, context))));
     }
 
     @SuppressWarnings("unused")
diff --git a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/common/query/CommonDomainService.java b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/common/query/CommonDomainService.java
index 6acb6529c3..be21351628 100644
--- a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/common/query/CommonDomainService.java
+++ b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/common/query/CommonDomainService.java
@@ -93,7 +93,7 @@ public class CommonDomainService
                 .filter(objectAction -> objectAction.getSemantics().isSafeInNature() ||
                         apiVariant != CausewayConfiguration.Viewer.Graphql.ApiVariant.QUERY_ONLY    // the other variants have an entry for all actions.
                 )
-                .forEach(act -> actions.add(addChildFieldFor(schemaStrategy.newGqlvAction(this, act, context))));
+                .forEach(act -> actions.add(addChildFieldFor(schemaStrategy.newAction(this, act, context))));
     }
 
 
diff --git a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/SchemaStrategyRich.java b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/SchemaStrategyRich.java
index e0f84f0288..a0142551db 100644
--- a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/SchemaStrategyRich.java
+++ b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/SchemaStrategyRich.java
@@ -42,24 +42,24 @@ public class SchemaStrategyRich implements SchemaStrategy {
 
     @Override
     public String topLevelFieldNameFrom(CausewayConfiguration.Viewer.Graphql graphqlConfiguration) {
-        return graphqlConfiguration.getTopLevelFieldNameForRich();
+        return graphqlConfiguration.getSchema().getRich().getTopLevelFieldName();
     }
 
-    public ElementCustom newGqlvProperty(
+    public ElementCustom newProperty(
             final ObjectInteractor holder,
             final OneToOneAssociation otoa,
             final Context context
     ) {
         return new RichProperty(holder, otoa, context);
-    };
-    public ElementCustom newGqlvCollection(
+    }
+    public ElementCustom newCollection(
             final ObjectInteractor holder,
             final OneToManyAssociation otma,
             final Context context
     ) {
         return new RichCollection(holder, otma, context);
     }
-    public ElementCustom newGqlvAction(
+    public ElementCustom newAction(
             final ObjectInteractor holder,
             final ObjectAction objectAction,
             final Context context
@@ -68,7 +68,7 @@ public class SchemaStrategyRich implements SchemaStrategy {
     }
 
     @Override
-    public ElementCustom newGqlvMeta(CommonDomainObject commonDomainObject, Context context) {
+    public ElementCustom newMeta(CommonDomainObject commonDomainObject, Context context) {
         return new CommonMeta(commonDomainObject, context);
     }
 
diff --git a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichTopLevelQuery.java b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichTopLevelQuery.java
index e3853e40f1..4759fe43a5 100644
--- a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichTopLevelQuery.java
+++ b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichTopLevelQuery.java
@@ -37,7 +37,7 @@ public class RichTopLevelQuery
 
         var graphqlConfiguration = context.causewayConfiguration.getViewer().getGraphql();
 
-        if (graphqlConfiguration.isIncludeTestingFieldInRich()) {
+        if (graphqlConfiguration.getSchema().getRich().isEnableScenarioTesting()) {
             addChildFieldFor(scenario = new Scenario(SCHEMA_STRATEGY, context));
         } else {
             scenario = null;
diff --git a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/simple/SchemaStrategySimple.java b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/simple/SchemaStrategySimple.java
index 8ab6530c3d..e9b8c20da5 100644
--- a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/simple/SchemaStrategySimple.java
+++ b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/simple/SchemaStrategySimple.java
@@ -43,24 +43,24 @@ public class SchemaStrategySimple implements SchemaStrategy {
 
     @Override
     public String topLevelFieldNameFrom(CausewayConfiguration.Viewer.Graphql graphqlConfiguration) {
-        return graphqlConfiguration.getTopLevelFieldNameForSimple();
+        return graphqlConfiguration.getSchema().getSimple().getTopLevelFieldName();
     }
 
-    public Element newGqlvProperty(
+    public Element newProperty(
             final ObjectInteractor holder,
             final OneToOneAssociation otoa,
             final Context context
     ) {
         return new SimpleProperty(holder, otoa, context);
     };
-    public Element newGqlvCollection(
+    public Element newCollection(
             final ObjectInteractor holder,
             final OneToManyAssociation otma,
             final Context context
     ) {
         return new SimpleCollection(holder, otma, context);
     }
-    public Element newGqlvAction(
+    public Element newAction(
             final ObjectInteractor holder,
             final ObjectAction objectAction,
             final Context context
@@ -69,7 +69,7 @@ public class SchemaStrategySimple implements SchemaStrategy {
     }
 
     @Override
-    public ElementCustom newGqlvMeta(CommonDomainObject commonDomainObject, Context context) {
+    public ElementCustom newMeta(CommonDomainObject commonDomainObject, Context context) {
         return new CommonMeta(commonDomainObject, context);
     }
 
diff --git a/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/schema/PrintSchemaIntegTest.java b/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/schema/PrintSchemaIntegTest.java
index ef2fa41ede..01040634f7 100644
--- a/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/schema/PrintSchemaIntegTest.java
+++ b/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/schema/PrintSchemaIntegTest.java
@@ -18,6 +18,9 @@
  */
 package org.apache.causeway.viewer.graphql.viewer.test.schema;
 
+import org.apache.causeway.viewer.graphql.viewer.test.domain.UniversityModule;
+
+import org.springframework.context.annotation.Import;
 import org.springframework.test.context.DynamicPropertyRegistry;
 import org.springframework.test.context.DynamicPropertySource;
 
@@ -25,6 +28,9 @@ import org.apache.causeway.viewer.graphql.viewer.testsupport.schema.PrintSchemaI
 
 import static org.apache.causeway.core.config.CausewayConfiguration.Viewer.Graphql.ApiVariant;
 
+@Import({
+        UniversityModule.class
+})
 public class PrintSchemaIntegTest extends PrintSchemaIntegTestAbstract {
 
     @DynamicPropertySource
diff --git a/viewers/graphql/test/src/test/resources/application-test.properties b/viewers/graphql/test/src/test/resources/application-test.properties
index 514fd18e07..6fc91d972b 100644
--- a/viewers/graphql/test/src/test/resources/application-test.properties
+++ b/viewers/graphql/test/src/test/resources/application-test.properties
@@ -28,4 +28,5 @@ decorator.datasource.datasource-proxy.json-format=false
 # Enable Query Metrics
 decorator.datasource.datasource-proxy.count-query=false
 
-causeway.viewer.graphql.resources.responseType=ATTACHMENT
\ No newline at end of file
+causeway.viewer.graphql.resources.response-type=ATTACHMENT
+causeway.viewer.graphql.schema.rich.enable-schema-support=true
\ No newline at end of file
diff --git a/viewers/graphql/testsupport/src/main/java/org/apache/causeway/viewer/graphql/viewer/testsupport/schema/PrintSchemaIntegTestAbstract.java b/viewers/graphql/testsupport/src/main/java/org/apache/causeway/viewer/graphql/viewer/testsupport/schema/PrintSchemaIntegTestAbstract.java
index 3461a27357..77c10512ff 100644
--- a/viewers/graphql/testsupport/src/main/java/org/apache/causeway/viewer/graphql/viewer/testsupport/schema/PrintSchemaIntegTestAbstract.java
+++ b/viewers/graphql/testsupport/src/main/java/org/apache/causeway/viewer/graphql/viewer/testsupport/schema/PrintSchemaIntegTestAbstract.java
@@ -102,9 +102,9 @@ public abstract class PrintSchemaIntegTestAbstract extends CausewayViewerGraphql
 
         val submit = printer.print(graphQLSchema);
 
-        File targetFile1 = new File("src/test/resources/schema.gql");
+        val targetFile = new File("src/test/resources/schema.gql");
 
-        Files.write(Paths.get(targetFile1.getPath()), submit.getBytes());
+        Files.write(Paths.get(targetFile.getPath()), submit.getBytes());
     }
 
 }