Skip to content

Commit da07820

Browse files
authored
Bootstrap the Flutter IJ with integrations tests (#8487)
The additional STARTER test framework is added, see https://github.com/JetBrains/intellij-ide-starter Thanks to others here who trailblazed, @jonathan1983, JetBrains/intellij-platform-plugin-template#537 and @helinx, #8338
1 parent 6311bce commit da07820

File tree

6 files changed

+581
-34
lines changed

6 files changed

+581
-34
lines changed

build.gradle.kts

Lines changed: 112 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ allprojects {
2828

2929
repositories {
3030
mavenCentral()
31+
maven("https://cache-redirector.jetbrains.com/packages.jetbrains.team/maven/p/ij/intellij-ide-starter")
32+
maven("https://mvnrepository.com/artifact/com.jetbrains.intellij.tools/ide-starter-driver")
3133
intellijPlatform {
3234
defaultRepositories()
3335
}
@@ -41,6 +43,7 @@ plugins {
4143
id("org.jetbrains.intellij.platform") version "2.7.2" // IntelliJ Platform Gradle Plugin
4244
id("org.jetbrains.kotlin.jvm") version "2.2.0" // Kotlin support
4345
id("org.jetbrains.changelog") version "2.2.0" // Gradle Changelog Plugin
46+
idea // IntelliJ IDEA support
4447
}
4548

4649
// By default (e.g. when we call `runIde` during development), the plugin version is SNAPSHOT
@@ -96,11 +99,18 @@ jvmVersion = when (javaVersion) {
9699
throw IllegalArgumentException("javaVersion must be defined in the product matrix as either \"17\" or \"21\", but is not for $ideaVersion")
97100
}
98101
}
102+
99103
kotlin {
100104
compilerOptions {
101105
apiVersion.set(KotlinVersion.KOTLIN_2_1)
102106
jvmTarget = jvmVersion
103107
}
108+
// This is how you specify the specific JVM requirements, this may be a requirement for the Starter test framework
109+
// jvmToolchain {
110+
// languageVersion = JavaLanguageVersion.of(21)
111+
// @Suppress("UnstableApiUsage")
112+
// vendor = JvmVendorSpec.JETBRAINS
113+
// }
104114
}
105115

106116
var javaCompatibilityVersion: JavaVersion
@@ -117,18 +127,79 @@ javaCompatibilityVersion = when (javaVersion) {
117127
throw IllegalArgumentException("javaVersion must be defined in the product matrix as either \"17\" or \"21\", but is not for $ideaVersion")
118128
}
119129
}
130+
120131
java {
121132
sourceCompatibility = javaCompatibilityVersion
122133
targetCompatibility = javaCompatibilityVersion
123134
}
124135

136+
sourceSets {
137+
main {
138+
java.srcDirs(
139+
listOf(
140+
"src",
141+
"third_party/vmServiceDrivers"
142+
)
143+
)
144+
// Add kotlin.srcDirs if we start using Kotlin in the main plugin.
145+
resources.srcDirs(
146+
listOf(
147+
"src",
148+
"resources"
149+
)
150+
)
151+
}
152+
test {
153+
java.srcDirs(
154+
listOf(
155+
"src",
156+
"testSrc/unit",
157+
"third_party/vmServiceDrivers"
158+
)
159+
)
160+
resources.srcDirs(
161+
listOf(
162+
"resources",
163+
"testData",
164+
"testSrc/unit"
165+
)
166+
)
167+
}
168+
169+
create("integration", Action<SourceSet> {
170+
java.srcDirs("testSrc/integration")
171+
kotlin.srcDirs("testSrc/integration")
172+
resources.srcDirs("testSrc/integration")
173+
compileClasspath += sourceSets["main"].output + sourceSets["test"].output
174+
runtimeClasspath += sourceSets["main"].output + sourceSets["test"].output
175+
})
176+
}
177+
178+
// Configure IntelliJ IDEA to recognize integration as test sources
179+
idea {
180+
module {
181+
testSources.from(sourceSets["integration"].kotlin.srcDirs)
182+
testResources.from(sourceSets["integration"].resources.srcDirs)
183+
}
184+
}
185+
186+
val integrationImplementation: Configuration by configurations.getting {
187+
extendsFrom(configurations.testImplementation.get())
188+
}
189+
190+
val integrationRuntimeOnly: Configuration by configurations.getting {
191+
extendsFrom(configurations.testRuntimeOnly.get())
192+
}
193+
125194
dependencies {
126195
intellijPlatform {
127196
// Documentation on the default target platform methods:
128197
// https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-dependencies-extension.html#default-target-platforms
129198
// Android Studio versions can be found at: https://plugins.jetbrains.com/docs/intellij/android-studio-releases-list.html
130199
androidStudio(ideaVersion)
131200
testFramework(TestFrameworkType.Platform)
201+
testFramework(TestFrameworkType.Starter, configurationName = "integrationImplementation")
202+
testFramework(TestFrameworkType.JUnit5, configurationName = "integrationImplementation")
132203

133204
// Plugin dependency documentation:
134205
// https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-dependencies-extension.html#plugins
@@ -172,6 +243,14 @@ dependencies {
172243
)
173244
)
174245
)
246+
247+
// UI Test dependencies
248+
integrationImplementation("org.kodein.di:kodein-di-jvm:7.26.1")
249+
integrationImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0")
250+
251+
// JUnit 5 is required for UI tests
252+
integrationImplementation("org.junit.jupiter:junit-jupiter:5.11.4")
253+
integrationRuntimeOnly("org.junit.platform:junit-platform-launcher")
175254
}
176255

177256
intellijPlatform {
@@ -219,37 +298,41 @@ intellijPlatform {
219298
}
220299
}
221300

222-
sourceSets {
223-
main {
224-
java.srcDirs(
225-
listOf(
226-
"src",
227-
"third_party/vmServiceDrivers"
228-
)
229-
)
230-
// Add kotlin.srcDirs if we start using Kotlin in the main plugin.
231-
resources.srcDirs(
232-
listOf(
233-
"src",
234-
"resources"
235-
)
236-
)
237-
}
238-
test {
239-
java.srcDirs(
240-
listOf(
241-
"src",
242-
"testSrc/unit",
243-
"third_party/vmServiceDrivers"
244-
)
301+
tasks {
302+
register<Test>("integration") {
303+
description = "Runs only the UI integration tests that start the IDE"
304+
group = "verification"
305+
testClassesDirs = sourceSets["integration"].output.classesDirs
306+
classpath = sourceSets["integration"].runtimeClasspath
307+
useJUnitPlatform {
308+
includeTags("ui")
309+
}
310+
311+
// UI tests should run sequentially (not in parallel) to avoid conflicts
312+
maxParallelForks = 1
313+
314+
// Increase memory for UI tests
315+
minHeapSize = "1g"
316+
maxHeapSize = "4g"
317+
318+
systemProperty("path.to.build.plugin", buildPlugin.get().archiveFile.get().asFile.absolutePath)
319+
systemProperty("idea.home.path", prepareTestSandbox.get().getDestinationDir().parentFile.absolutePath)
320+
systemProperty(
321+
"allure.results.directory", project.layout.buildDirectory.get().asFile.absolutePath + "/allure-results"
245322
)
246-
resources.srcDirs(
247-
listOf(
248-
"resources",
249-
"testData",
250-
"testSrc/unit"
323+
324+
// Disable IntelliJ test listener that conflicts with standard JUnit
325+
systemProperty("idea.test.cyclic.buffer.size", "0")
326+
327+
// Add required JVM arguments
328+
jvmArgumentProviders += CommandLineArgumentProvider {
329+
mutableListOf(
330+
"--add-opens=java.base/java.lang=ALL-UNNAMED",
331+
"--add-opens=java.desktop/javax.swing=ALL-UNNAMED"
251332
)
252-
)
333+
}
334+
335+
dependsOn(buildPlugin)
253336
}
254337
}
255338

src/io/flutter/module/FlutterGeneratorPeer.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
import com.intellij.openapi.ui.Messages;
1414
import com.intellij.openapi.ui.TextComponentAccessor;
1515
import com.intellij.openapi.ui.ValidationInfo;
16-
import com.intellij.openapi.util.text.StringUtil;
1716
import com.intellij.openapi.util.io.FileUtilRt;
17+
import com.intellij.openapi.util.text.StringUtil;
1818
import com.intellij.ui.ComboboxWithBrowseButton;
1919
import com.intellij.ui.DocumentAdapter;
2020
import com.intellij.ui.components.JBLabel;
@@ -23,6 +23,8 @@
2323
import io.flutter.module.settings.SettingsHelpForm;
2424
import io.flutter.sdk.FlutterSdk;
2525
import io.flutter.sdk.FlutterSdkUtil;
26+
import org.jetbrains.annotations.NotNull;
27+
import org.jetbrains.annotations.Nullable;
2628

2729
import javax.swing.ComboBoxEditor;
2830
import javax.swing.JComponent;
@@ -33,9 +35,6 @@
3335
import javax.swing.event.DocumentEvent;
3436
import javax.swing.text.JTextComponent;
3537

36-
import org.jetbrains.annotations.NotNull;
37-
import org.jetbrains.annotations.Nullable;
38-
3938
public class FlutterGeneratorPeer {
4039
private final WizardContext myContext;
4140
private JPanel myMainPanel;
@@ -65,6 +64,16 @@ public FlutterGeneratorPeer(WizardContext context) {
6564
private void init() {
6665
mySdkPathComboWithBrowse.getComboBox().setEditable(true);
6766
FlutterSdkUtil.addKnownSDKPathsToCombo(mySdkPathComboWithBrowse.getComboBox());
67+
if (mySdkPathComboWithBrowse.getComboBox().getModel().getSize() == 0) {
68+
// If no SDKs are found, try to use the one from the FLUTTER_SDK environment variable.
69+
// This ensures the SDK path is pre-filled when the combo box is empty, not requiring
70+
// a running Application which is the case for users and bots on the initial startup
71+
// experience.
72+
final String flutterSDKPath = System.getenv("FLUTTER_SDK");
73+
if (StringUtil.isNotEmpty(flutterSDKPath)) {
74+
mySdkPathComboWithBrowse.getComboBox().setSelectedItem(flutterSDKPath);
75+
}
76+
}
6877

6978
mySdkPathComboWithBrowse.addBrowseFolderListener(null, FileChooserDescriptorFactory.createSingleFolderDescriptor()
7079
.withTitle(FlutterBundle.message("flutter.sdk.browse.path.label")), TextComponentAccessor.STRING_COMBOBOX_WHOLE_TEXT);

0 commit comments

Comments
 (0)