Skip to content

Add IntelliJ IDEA 2026.2 UI test harness and cross-platform helpers - #9209

Open
cj-radcliff wants to merge 7 commits into
flutter:mainfrom
cj-radcliff:ui-test-harness-iu262
Open

cj-radcliff wants to merge 7 commits into
flutter:mainfrom
cj-radcliff:ui-test-harness-iu262

Conversation

@cj-radcliff

@cj-radcliff cj-radcliff commented Nov 3, 2026 •

Copy link
Copy Markdown
Collaborator

Description

Adds the shared IntelliJ IDEA 2026.2 UI test harness, cross-platform helpers, and the record-test-walkthrough skill as the foundation for upcoming IDE Starter UI tests:

  • build.gradle.kts:
    • Resolves buildPlugin.archiveFile lazily via CommandLineArgumentProvider so archiveFileName overrides apply.
    • Passes -Djava.awt.headless=true to the test runner JVM so JBR does not start Wayland toolkit threads (WLKeyboard.KeyRepeatManager) that IDE Starter's ThreadLeakTracker reports as leaks.
  • Setup.kt:
    • Adds setupTestContextIU262 for IntelliJ IDEA 2026.2.3 (262.10968.63), with configurable dartPluginVersion (default 509.0.0) and DART_PLUGIN_ZIP environment override for testing local Dart plugin builds.
    • Suppresses JetBrains feedback survey popups (platform.feedback, csat.survey.enabled, editor.ux.survey.enabled).
    • Configures -Dawt.robot.screenshotMethod=dbusRemoteDesktop when running directly on a Linux Wayland desktop session so synthetic java.awt.Robot input routes through the xdg-desktop-portal RemoteDesktop interface.
  • ExistingProjectUITest.kt:
    • Base class for UI tests that open IntelliJ IDEA 2026.2.3 on a pre-created Flutter project (flutter create), wait for indexing, dismiss the Ultimate Trial tab and survey interruptions, select devices, wait for console output, and stop running apps.
  • utils/Platform.kt:
    • Centralizes Linux, macOS, and Windows paths (FLUTTER_SDK, ANDROID_HOME / ANDROID_SDK_ROOT, short Windows %USERPROFILE%\ft test project directory, retry-based recursive deletion for locked Windows files, and display-mode detection).
  • utils/WalkthroughSteps.kt & utils/NewProject.kt:
    • Adds lightweight walkthrough step markers, waits for the Welcome screen before clicking (waitFound()), drains flutter create stdout before waitFor() so the pipe buffer cannot deadlock, and uses Platform helpers.
  • .agents/skills/record-test-walkthrough/ & .agents/AGENTS.md:
    • Adds the record-test-walkthrough skill (SKILL.md and scripts/*) to record any automated UI test on its own Xvfb/Xephyr display and render a self-contained HTML + Markdown step-by-step walkthrough.
  • testSrc/integration/README.md:
    • Documents prerequisites, cross-platform commands, walkthrough recording, environment variables (FLUTTER_SDK, DART_PLUGIN_ZIP, KEEP_TEST_PROJECT, KEEP_IDE_OPEN_MINUTES), and troubleshooting.

Verification

  • Verified compileIntegrationKotlin compiles cleanly against main.
  • Verified tool/validate_skills.sh (skills_lint) passes on .agents/skills/record-test-walkthrough.
  • Exercised by the existing-project UI test suite on IntelliJ IDEA 2026.2.3.

Review the contribution guidelines below:

  • I’ve reviewed the contributor guide and applied the relevant portions to this PR.
  • I've included the required information in the description above.
  • My up-to-date information is in the AUTHORS file.
  • I've updated CHANGELOG.md if appropriate.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request establishes a robust local integration testing setup for the Flutter IntelliJ plugin across Linux, macOS, and Windows. It introduces a base class ExistingProjectUITest for UI tests on existing projects, a platform-specific utility layer Platform, and a walkthrough step-recording helper WalkthroughSteps, alongside updated documentation. The review feedback highlights several opportunities to improve test speed and reliability: utilizing Gradle's native lazy systemProperty support, avoiding an unconditional 15-second delay when the trial tab is missing, preventing a division-by-zero crash in selectDevice when no arguments are passed, replacing a hardcoded sleep with dynamic polling when stopping the app, and defensively checking for blank FLUTTER_SDK values.

Comment thread build.gradle.kts Resolved
@cj-radcliff

Copy link
Copy Markdown
Collaborator Author

Also note that this includes agent skills and files to run and record UI tests in intellij

@cj-radcliff
cj-radcliff force-pushed the ui-test-harness-iu262 branch from 7374c97 to 4694549 Compare November 4, 2026 00:32
@cj-radcliff
cj-radcliff marked this pull request as ready for review November 4, 2026 00:47

@pq pq left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool!

Is the plan to wire this into the CI or just for local runs? If the latter, maybe document it somewhere?

`DISPLAY` and `WAYLAND_DISPLAY` are both set:

```bash
FLUTTER_SDK=~/develop/flutter ./gradlew --no-daemon integration --tests io.flutter.integrationTest.ColorGutterPreviewUITest

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure ColorGutterPreviewUITest and NewProjectIU262UITest (also on lines 68–76, 324 and 352) exist in the repo? If that's true, maybe point these at NewProjectUITest? Or are they coming in a follow up?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I intend it to be for local runs for now. I think eventually it can be done as part of CI or a release process, but its not there yet. My goal is to get to a point where someone can iterate pretty rapidly with an agent to build out various test flows.

fun String.matches() = names.any { startsWith(it, ignoreCase = true) }
val selector = x(
"//div[@class='JBLabel' and (contains(@text, '(desktop)') or contains(@text, '(web)') or " +
"contains(@text, '(mobile)') or contains(@text, 'device') or contains(@text, 'Device'))]"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: matching any label that contains device/Device, plus the fixed sleeps below, feels like we're inviting flakes. Could we target the device selector component and waitFor its state instead?

}

/** The Dart plugin version installed with IntelliJ IDEA 2026.2 unless a test asks for another one. */
const val DART_PLUGIN_VERSION_IU262 = "509.0.0"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gradle.properties specifies dartPluginVersion=510.0.0. Pin 510 here too (or read it from there) so they agree and don't drift?

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants