diff --git a/rewrite-gradle/src/main/java/org/openrewrite/gradle/AddDependency.java b/rewrite-gradle/src/main/java/org/openrewrite/gradle/AddDependency.java index 59084bd7cec..06edd29bb53 100644 --- a/rewrite-gradle/src/main/java/org/openrewrite/gradle/AddDependency.java +++ b/rewrite-gradle/src/main/java/org/openrewrite/gradle/AddDependency.java @@ -21,6 +21,7 @@ import org.openrewrite.*; import org.openrewrite.gradle.marker.GradleDependencyConfiguration; import org.openrewrite.gradle.marker.GradleProject; +import org.openrewrite.gradle.search.FindJVMTestSuites; import org.openrewrite.groovy.GroovyIsoVisitor; import org.openrewrite.groovy.tree.G; import org.openrewrite.internal.StringUtils; @@ -33,8 +34,9 @@ import org.openrewrite.semver.Semver; import java.util.*; +import java.util.function.Predicate; -import static java.util.Collections.*; +import static java.util.Collections.singletonList; import static java.util.Objects.requireNonNull; @Value @@ -56,9 +58,9 @@ public class AddDependency extends ScanningRecipe { @Option(displayName = "Version", description = "An exact version number or node-style semver selector used to select the version number. " + - "You can also use `latest.release` for the latest available version and `latest.patch` if " + - "the current version is a valid semantic version. For more details, you can look at the documentation " + - "page of [version selectors](https://docs.openrewrite.org/reference/dependency-version-selectors).", + "You can also use `latest.release` for the latest available version and `latest.patch` if " + + "the current version is a valid semantic version. For more details, you can look at the documentation " + + "page of [version selectors](https://docs.openrewrite.org/reference/dependency-version-selectors).", example = "29.X", required = false) @Nullable @@ -66,7 +68,7 @@ public class AddDependency extends ScanningRecipe { @Option(displayName = "Version pattern", description = "Allows version selection to be extended beyond the original Node Semver semantics. So for example, " + - "Setting 'version' to \"25-29\" can be paired with a metadata pattern of \"-jre\" to select Guava 29.0-jre", + "Setting 'version' to \"25-29\" can be paired with a metadata pattern of \"-jre\" to select Guava 29.0-jre", example = "-jre", required = false) @Nullable @@ -74,7 +76,7 @@ public class AddDependency extends ScanningRecipe { @Option(displayName = "Configuration", description = "A configuration to use when it is not what can be inferred from usage. Most of the time this will be left empty, but " + - "is used when adding a new as of yet unused dependency.", + "is used when adding a new as of yet unused dependency.", example = "implementation", required = false) @Nullable @@ -103,7 +105,7 @@ public class AddDependency extends ScanningRecipe { @Option(displayName = "Family pattern", description = "A pattern, applied to groupIds, used to determine which other dependencies should have aligned version numbers. " + - "Accepts '*' as a wildcard character.", + "Accepts '*' as a wildcard character.", example = "com.fasterxml.jackson*", required = false) @Nullable @@ -143,6 +145,7 @@ public Validated validate() { public static class Scanned { boolean usingType; Map> configurationsByProject = new HashMap<>(); + Map> customJvmTestSuitesWithDependencies = new HashMap<>(); } @Override @@ -156,11 +159,12 @@ public TreeVisitor getScanner(Scanned acc) { @Nullable UsesType usesType = null; + private boolean usesType(SourceFile sourceFile, ExecutionContext ctx) { - if(onlyIfUsing == null) { + if (onlyIfUsing == null) { return true; } - if(usesType == null) { + if (usesType == null) { usesType = new UsesType<>(onlyIfUsing, true); } return usesType.isAcceptable(sourceFile, ctx) && usesType.visit(sourceFile, ctx) != sourceFile; @@ -176,6 +180,11 @@ private boolean usesType(SourceFile sourceFile, ExecutionContext ctx) { if (usesType(sourceFile, ctx)) { acc.usingType = true; } + + acc.customJvmTestSuitesWithDependencies + .computeIfAbsent(javaProject, ignored -> new HashSet<>()) + .addAll(FindJVMTestSuites.jvmTestSuiteNames(tree, true)); + Set configurations = acc.configurationsByProject.computeIfAbsent(javaProject, ignored -> new HashSet<>()); sourceFile.getMarkers().findFirst(JavaSourceSet.class).ifPresent(sourceSet -> configurations.add("main".equals(sourceSet.getName()) ? "implementation" : sourceSet.getName() + "Implementation")); @@ -248,8 +257,13 @@ public TreeVisitor getVisitor(Scanned acc) { G.CompilationUnit g = (G.CompilationUnit) s; for (String resolvedConfiguration : resolvedConfigurations) { - g = (G.CompilationUnit) new AddDependencyVisitor(groupId, artifactId, version, versionPattern, resolvedConfiguration, - classifier, extension, metadataFailures, this::isTopLevel).visitNonNull(g, ctx); + if (targetsCustomJVMTestSuite(resolvedConfiguration, acc.customJvmTestSuitesWithDependencies.get(jp))) { + g = (G.CompilationUnit) new AddDependencyVisitor(groupId, artifactId, version, versionPattern, purgeSourceSet(configuration), + classifier, extension, metadataFailures, isMatchingJVMTestSuite(resolvedConfiguration)).visitNonNull(g, ctx); + } else { + g = (G.CompilationUnit) new AddDependencyVisitor(groupId, artifactId, version, versionPattern, resolvedConfiguration, + classifier, extension, metadataFailures, this::isTopLevel).visitNonNull(g, ctx); + } } return g; @@ -258,6 +272,61 @@ public TreeVisitor getVisitor(Scanned acc) { private boolean isTopLevel(Cursor cursor) { return cursor.getParentOrThrow().firstEnclosing(J.MethodInvocation.class) == null; } + + private Predicate isMatchingJVMTestSuite(String resolvedConfiguration) { + return cursor -> { + String sourceSet = purgeConfigurationSuffix(resolvedConfiguration); + J.MethodInvocation methodInvocation = cursor.getParentOrThrow().firstEnclosing(J.MethodInvocation.class); + return methodInvocation != null && sourceSet.equals(methodInvocation.getSimpleName()); + }; + } + + private final Set gradleStandardConfigurations = new HashSet<>(Arrays.asList( + "api", + "implementation", + "compileOnly", + "compileOnlyApi", + "runtimeOnly", + "testImplementation", + "testCompileOnly", + "testRuntimeOnly")); + + boolean targetsCustomJVMTestSuite(String configuration, Set customJvmTestSuites) { + if (gradleStandardConfigurations.contains(configuration) || "default".equals(configuration)) { + return false; + } + + String sourceSet = purgeConfigurationSuffix(configuration); + return customJvmTestSuites.contains(sourceSet); + } + + private String purgeConfigurationSuffix(String configuration) { + if (configuration.endsWith("Implementation")) { + return configuration.substring(0, configuration.length() - 14); + } else if (configuration.endsWith("CompileOnly")) { + return configuration.substring(0, configuration.length() - 11); + } else if (configuration.endsWith("RuntimeOnly")) { + return configuration.substring(0, configuration.length() - 11); + } else if (configuration.endsWith("AnnotationProcessor")) { + return configuration.substring(0, configuration.length() - 19); + } else { + return configuration; + } + } + + private String purgeSourceSet(@Nullable String configuration) { + if (StringUtils.isBlank(configuration) || configuration.endsWith("Implementation")) { + return "implementation"; + } else if (configuration.endsWith("CompileOnly")) { + return "compileOnly"; + } else if (configuration.endsWith("RuntimeOnly")) { + return "runtimeOnly"; + } else if (configuration.endsWith("AnnotationProcessor")) { + return "annotationProcessor"; + } else { + return configuration; + } + } }) ); } diff --git a/rewrite-gradle/src/main/java/org/openrewrite/gradle/search/FindJVMTestSuites.java b/rewrite-gradle/src/main/java/org/openrewrite/gradle/search/FindJVMTestSuites.java new file mode 100644 index 00000000000..4f76d21ed0c --- /dev/null +++ b/rewrite-gradle/src/main/java/org/openrewrite/gradle/search/FindJVMTestSuites.java @@ -0,0 +1,116 @@ +/* + * Copyright 2025 the 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. + * You may obtain a copy of the License at + *

+ * https://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.gradle.search; + +import lombok.EqualsAndHashCode; +import lombok.Value; +import org.jspecify.annotations.Nullable; +import org.openrewrite.*; +import org.openrewrite.gradle.table.JVMTestSuitesDefined; +import org.openrewrite.groovy.GroovyIsoVisitor; +import org.openrewrite.java.tree.Expression; +import org.openrewrite.java.tree.J; +import org.openrewrite.java.tree.Statement; +import org.openrewrite.marker.SearchResult; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import java.util.stream.Collectors; + +@Value +@EqualsAndHashCode(callSuper = false) +public class FindJVMTestSuites extends Recipe { + + transient JVMTestSuitesDefined jvmTestSuitesDefined = new JVMTestSuitesDefined(this); + + @Option(displayName = "Requires dependencies", + description = "Whether the test suite configuration defines dependencies to be resolved. Defaults to false.") + @Nullable + Boolean definesDependencies; + + @Option(displayName = "Insert rows", + description = "Whether to insert rows into the table. Defaults to true.") + @Nullable + Boolean insertRows; + + @Override + public String getDisplayName() { + return "Find Gradle JVMTestSuite plugin configuration"; + } + + @Override + public String getDescription() { + return "Find Gradle JVMTestSuite plugin configurations and produce a data table."; + } + + @Override + public TreeVisitor getVisitor() { + boolean requireDependencies = definesDependencies != null && definesDependencies; + boolean tableAvailable = this.insertRows == null || this.insertRows; + return new GroovyIsoVisitor() { + private boolean isJVMTestSuitesBlock() { + Cursor parent = getCursor().getParent(); + if (parent != null) { + Iterator path = parent.getPath(J.MethodInvocation.class::isInstance); + if (path.hasNext() && "suites".equals(((J.MethodInvocation) path.next()).getSimpleName())) { + return path.hasNext() && "testing".equals(((J.MethodInvocation) path.next()).getSimpleName()); + } + } + return false; + } + + private boolean definesDependencies(J.MethodInvocation suite) { + for (Expression suiteDefinition : suite.getArguments()) { + if (suiteDefinition instanceof J.Lambda) { + for (Statement statement : ((J.Block) ((J.Lambda) suiteDefinition).getBody()).getStatements()) { + if (statement instanceof J.Return) { + Expression expression = ((J.Return) statement).getExpression(); + if (expression instanceof J.MethodInvocation) { + if ("dependencies".equals(((J.MethodInvocation) expression).getSimpleName())) { + return true; + } + } + } + } + } + } + return false; + } + + @Override + public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) { + if (isJVMTestSuitesBlock()) { + if (tableAvailable) { + jvmTestSuitesDefined.insertRow(ctx, new JVMTestSuitesDefined.Row(method.getSimpleName())); + } + return !requireDependencies || definesDependencies(method) ? SearchResult.found(method) : method; + } + return super.visitMethodInvocation(method, ctx); + } + }; + } + + public static Set jvmTestSuiteNames(Tree tree, boolean definesDependencies) { + return TreeVisitor.collect(new FindJVMTestSuites(definesDependencies, false).getVisitor(), tree, new HashSet<>()) + .stream() + .filter(J.MethodInvocation.class::isInstance) + .map(J.MethodInvocation.class::cast) + .filter(m -> m.getMarkers().findFirst(SearchResult.class).isPresent()) + .map(J.MethodInvocation::getSimpleName) + .collect(Collectors.toSet()); + } +} diff --git a/rewrite-gradle/src/main/java/org/openrewrite/gradle/table/JVMTestSuitesDefined.java b/rewrite-gradle/src/main/java/org/openrewrite/gradle/table/JVMTestSuitesDefined.java new file mode 100644 index 00000000000..fbaafed4186 --- /dev/null +++ b/rewrite-gradle/src/main/java/org/openrewrite/gradle/table/JVMTestSuitesDefined.java @@ -0,0 +1,40 @@ +/* + * Copyright 2025 the 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. + * You may obtain a copy of the License at + *

+ * https://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.gradle.table; + +import com.fasterxml.jackson.annotation.JsonIgnoreType; +import lombok.Value; +import org.openrewrite.Column; +import org.openrewrite.DataTable; +import org.openrewrite.Recipe; + +@JsonIgnoreType +public class JVMTestSuitesDefined extends DataTable { + public JVMTestSuitesDefined(Recipe recipe) { + super(recipe, Row.class, + JVMTestSuitesDefined.class.getName(), + "JVMTestSuites defined", + "JVMTestSuites defined."); + } + + @Value + public static class Row { + + @Column(displayName = "JVMTestSuite name", + description = "Name of the defined JVMTestSuite.") + String name; + } +} diff --git a/rewrite-gradle/src/test/java/org/openrewrite/gradle/AddDependencyTest.java b/rewrite-gradle/src/test/java/org/openrewrite/gradle/AddDependencyTest.java index cb1da2ffe4a..9f112b539a7 100644 --- a/rewrite-gradle/src/test/java/org/openrewrite/gradle/AddDependencyTest.java +++ b/rewrite-gradle/src/test/java/org/openrewrite/gradle/AddDependencyTest.java @@ -17,8 +17,10 @@ import org.intellij.lang.annotations.Language; import org.jspecify.annotations.Nullable; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.ValueSource; import org.openrewrite.Issue; import org.openrewrite.gradle.marker.GradleDependencyConfiguration; @@ -36,12 +38,7 @@ import static org.openrewrite.gradle.toolingapi.Assertions.withToolingApi; import static org.openrewrite.groovy.Assertions.groovy; import static org.openrewrite.groovy.Assertions.srcMainGroovy; -import static org.openrewrite.java.Assertions.java; -import static org.openrewrite.java.Assertions.mavenProject; -import static org.openrewrite.java.Assertions.srcMainJava; -import static org.openrewrite.java.Assertions.srcMainResources; -import static org.openrewrite.java.Assertions.srcSmokeTestJava; -import static org.openrewrite.java.Assertions.srcTestJava; +import static org.openrewrite.java.Assertions.*; import static org.openrewrite.properties.Assertions.properties; @SuppressWarnings("GroovyUnusedAssignment") @@ -687,7 +684,7 @@ class A { dependencies { implementation "commons-lang:commons-lang:2.6" - + testImplementation "junit:junit:4.13" } """, @@ -733,7 +730,7 @@ void addDependenciesToExistingGrouping() { dependencies { implementation group: "commons-lang", name: "commons-lang", version: "1.0" - + def junitVersion = "4.12" testImplementation group: "junit", name: "junit", version: junitVersion } @@ -935,7 +932,7 @@ void matchesDependencyDeclarationStyle() { dependencies { implementation group: "commons-lang", name: "commons-lang", version: "1.0" - + testImplementation group: "com.google.guava", name: "guava", version: "29.0-jre" } """ @@ -1345,6 +1342,244 @@ void addUnconditionally() { ); } + @Nested + @Issue("https://github.com/moderneinc/customer-requests/issues/792") + class AddToJVMTestSuite { + @Test + void addToJVMSuite() { + rewriteRun( + spec -> spec.recipe(addDependency("com.google.guava:guava:29.0-jre")), + mavenProject("project", + srcMainJava( + java(usingGuavaIntMath, sourceSpecs -> sourceSet(sourceSpecs, "integrationTest"))), + buildGradle( + //language=groovy + """ + plugins { + id "java-library" + id 'jvm-test-suite' + } + + repositories { + mavenCentral() + } + + dependencies { + implementation "org.apache.logging.log4j:log4j-core:2.22.1" + } + + testing { + suites { + integrationTest(JvmTestSuite) { + dependencies { + } + } + } + } + """, + """ + plugins { + id "java-library" + id 'jvm-test-suite' + } + + repositories { + mavenCentral() + } + + dependencies { + implementation "org.apache.logging.log4j:log4j-core:2.22.1" + } + + testing { + suites { + integrationTest(JvmTestSuite) { + dependencies { + implementation "com.google.guava:guava:29.0-jre" + } + } + } + } + """ + ))); + } + + @Test + void actNormalForDefaultTestWithoutSuiteDefinition() { + rewriteRun( + spec -> spec.recipe(addDependency("com.google.guava:guava:29.0-jre")), + mavenProject("project", + srcMainJava( + java(usingGuavaIntMath, sourceSpecs -> sourceSet(sourceSpecs, "test"))), + buildGradle( + //language=groovy + """ + plugins { + id "java-library" + id 'jvm-test-suite' + } + + repositories { + mavenCentral() + } + + dependencies { + implementation "org.apache.logging.log4j:log4j-core:2.22.1" + } + + testing { + suites { + integrationTest(JvmTestSuite) { + dependencies { + } + } + } + } + """, + """ + plugins { + id "java-library" + id 'jvm-test-suite' + } + + repositories { + mavenCentral() + } + + dependencies { + implementation "org.apache.logging.log4j:log4j-core:2.22.1" + + testImplementation "com.google.guava:guava:29.0-jre" + } + + testing { + suites { + integrationTest(JvmTestSuite) { + dependencies { + } + } + } + } + """ + ))); + } + + @Test + void actNormalForSuiteWithoutDependencyBlock() { + rewriteRun( + spec -> spec.recipe(addDependency("com.google.guava:guava:29.0-jre")), + mavenProject("project", + srcMainJava( + java(usingGuavaIntMath, sourceSpecs -> sourceSet(sourceSpecs, "integrationTest"))), + buildGradle( + //language=groovy + """ + plugins { + id "java-library" + id 'jvm-test-suite' + } + + repositories { + mavenCentral() + } + + testing { + suites { + integrationTest(JvmTestSuite) { + } + } + } + """, + """ + plugins { + id "java-library" + id 'jvm-test-suite' + } + + repositories { + mavenCentral() + } + + testing { + suites { + integrationTest(JvmTestSuite) { + } + } + } + + dependencies { + integrationTestImplementation "com.google.guava:guava:29.0-jre" + } + """ + ))); + } + + @ParameterizedTest + @CsvSource({ + "integrationTestImplementation,implementation", + "integrationTestCompileOnly,compileOnly", + "integrationTestRuntimeOnly,runtimeOnly", + "integrationTestAnnotationProcessor,annotationProcessor"}) + void withExplicitConfiguration(String recipeConfiguration, String gradleConfiguration) { + rewriteRun( + spec -> spec.recipe(addDependency("com.google.guava:guava:29.0-jre", null, recipeConfiguration)), + mavenProject("project", + srcMainJava( + java(usingGuavaIntMath, sourceSpecs -> sourceSet(sourceSpecs, "integrationTest"))), + buildGradle( + //language=groovy + """ + plugins { + id "java-library" + id 'jvm-test-suite' + } + + repositories { + mavenCentral() + } + + dependencies { + implementation "org.apache.logging.log4j:log4j-core:2.22.1" + } + + testing { + suites { + integrationTest(JvmTestSuite) { + dependencies { + } + } + } + } + """, + //language=groovy + """ + plugins { + id "java-library" + id 'jvm-test-suite' + } + + repositories { + mavenCentral() + } + + dependencies { + implementation "org.apache.logging.log4j:log4j-core:2.22.1" + } + + testing { + suites { + integrationTest(JvmTestSuite) { + dependencies { + %s "com.google.guava:guava:29.0-jre" + } + } + } + } + """.formatted(gradleConfiguration) + ))); + } + } + private AddDependency addDependency(@SuppressWarnings("SameParameterValue") String gav) { return addDependency(gav, null, null); } diff --git a/rewrite-gradle/src/test/java/org/openrewrite/gradle/search/FindJVMTestSuitesTest.java b/rewrite-gradle/src/test/java/org/openrewrite/gradle/search/FindJVMTestSuitesTest.java new file mode 100644 index 00000000000..f8e34ed5d69 --- /dev/null +++ b/rewrite-gradle/src/test/java/org/openrewrite/gradle/search/FindJVMTestSuitesTest.java @@ -0,0 +1,216 @@ +/* + * Copyright 2025 the 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. + * You may obtain a copy of the License at + *

+ * https://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.gradle.search; + +import org.intellij.lang.annotations.Language; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.openrewrite.test.RecipeSpec; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.gradle.Assertions.buildGradle; +import static org.openrewrite.gradle.toolingapi.Assertions.withToolingApi; + +class FindJVMTestSuitesTest implements RewriteTest { + + @Override + public void defaults(RecipeSpec spec) { + spec.beforeRecipe(withToolingApi()); + } + + @Nested + class NoDependency { + @Test + void configNull() { + rewriteRun( + spec -> spec.recipe(new FindJVMTestSuites(null, null)), + buildGradle( + withoutDependency, + withoutDependencyFound + ) + ); + } + + @Test + void configFalse() { + rewriteRun( + spec -> spec.recipe(new FindJVMTestSuites(false, null)), + buildGradle( + withoutDependency, + withoutDependencyFound + ) + ); + } + + @Test + void configTrue() { + rewriteRun( + spec -> spec.recipe(new FindJVMTestSuites(true, null)), + buildGradle(withoutDependency) + ); + } + } + + @Nested + class WithDependency { + @Test + void configNull() { + rewriteRun( + spec -> spec.recipe(new FindJVMTestSuites(null, null)), + buildGradle( + withDependency, + withDependencyFound + ) + ); + } + + @Test + void configFalse() { + rewriteRun( + spec -> spec.recipe(new FindJVMTestSuites(false, null)), + buildGradle( + withDependency, + withDependencyFound + ) + ); + } + + @Test + void configTrue() { + rewriteRun( + spec -> spec.recipe(new FindJVMTestSuites(true, null)), + buildGradle( + withDependency, + withDependencyFound + ) + ); + } + } + + @Nested + class NoPlugin { + @Test + void noSuiteDefined() { + rewriteRun( + spec -> spec.recipe(new FindJVMTestSuites(null, null)), + buildGradle(noSuiteDefined) + ); + rewriteRun( + spec -> spec.recipe(new FindJVMTestSuites(false, null)), + buildGradle(noSuiteDefined) + ); + rewriteRun( + spec -> spec.recipe(new FindJVMTestSuites(true, null)), + buildGradle(noSuiteDefined) + ); + } + } + + @Language("groovy") + private static final String withDependency = """ + plugins { + id "java-library" + id 'jvm-test-suite' + } + + repositories { + mavenCentral() + } + + testing { + suites { + integrationTest(JvmTestSuite) { + dependencies {} + } + } + } + """; + + @Language("groovy") + private static final String withDependencyFound = """ + plugins { + id "java-library" + id 'jvm-test-suite' + } + + repositories { + mavenCentral() + } + + testing { + suites { + /*~~>*/integrationTest(JvmTestSuite) { + dependencies {} + } + } + } + """; + + @Language("groovy") + private static final String withoutDependency = """ + plugins { + id "java-library" + id 'jvm-test-suite' + } + + repositories { + mavenCentral() + } + + testing { + suites { + integrationTest(JvmTestSuite) { + } + } + } + """; + + @Language("groovy") + private static final String withoutDependencyFound = """ + plugins { + id "java-library" + id 'jvm-test-suite' + } + + repositories { + mavenCentral() + } + + testing { + suites { + /*~~>*/integrationTest(JvmTestSuite) { + } + } + } + """; + + @Language("groovy") + private static final String noSuiteDefined = """ + plugins { + id "java-library" + id 'jvm-test-suite' + } + + repositories { + mavenCentral() + } + + testing { + suites { + } + } + """; +}