Documenting integration tests - #9051
Conversation
Add documentation for integration testing and the IntelliJ IDE Starter framework. - Create a new docs/integration-testing.md file to document the integration testing process. - Create a new docs/intellij-ide-starter.md file to document the IntelliJ IDE Starter framework. - Link to the new documentation from the README.md and docs/integration-testing.md files.
There was a problem hiding this comment.
Code Review
This pull request introduces documentation and automated integration tests for creating a new Flutter application using the IntelliJ IDE Starter framework. This includes a new test plan, checklist, and test files (CreateNewFlutterMobileAppTest and a commented-out WindowsDebugOutputTest), along with helper classes in NewProject.kt. Feedback on the changes highlights several critical issues: platform checkboxes are clicked blindly without checking their initial state; a syntax error exists where kotlinRadioButton.isSelected is missing parentheses; the test workflow is incomplete, ending with a hardcoded 30-second wait instead of verifying that the project opened successfully; the new test file is missing the required copyright header; there is an undocumented TODO comment; actionButtonByXpath is incorrectly used for locating labels and text fields in NewProject.kt; and the WindowsDebugOutputTest file is entirely commented out and should instead use the @Disabled annotation.
| linuxButton.click() | ||
| macOsButton.click() | ||
| webButton.click() | ||
| windowsButton.click() | ||
| Assertions.assertTrue(!linuxButton.isSelected()) |
There was a problem hiding this comment.
[MUST-FIX] Blindly clicking platform checkboxes can toggle them to an incorrect state depending on their default selection. Check their state using isSelected() before clicking to ensure they are robustly deselected.
| linuxButton.click() | |
| macOsButton.click() | |
| webButton.click() | |
| windowsButton.click() | |
| Assertions.assertTrue(!linuxButton.isSelected()) | |
| if (linuxButton.isSelected()) linuxButton.click() | |
| if (macOsButton.isSelected()) macOsButton.click() | |
| if (webButton.isSelected()) webButton.click() | |
| if (windowsButton.isSelected()) windowsButton.click() | |
| Assertions.assertFalse(linuxButton.isSelected(), "Linux platform should be deselected.") |
| //Assertions.assertTrue(applicationTypeDropDown.getSelectedItem() == "Application") | ||
|
|
||
| // 9. Ensure that the android language is Kotlin | ||
| Assertions.assertTrue(kotlinRadioButton.isSelected) |
There was a problem hiding this comment.
[MUST-FIX] kotlinRadioButton.isSelected is missing parentheses. It should be a method call isSelected() to match the other radio buttons and checkboxes, otherwise it may cause a compilation or runtime error.
| Assertions.assertTrue(kotlinRadioButton.isSelected) | |
| Assertions.assertTrue(kotlinRadioButton.isSelected()) |
| // 10. Click create | ||
| createButton.click() | ||
|
|
||
|
|
||
|
|
||
| wait(30.seconds) |
There was a problem hiding this comment.
[MUST-FIX] The test is incomplete. It clicks the "Create" button and then performs a hardcoded 30-second wait before ending, completely skipping steps 11 and 12 of the test plan (verifying that the project opened and that main.dart and README.md are open in editor tabs). Hardcoded waits should also be replaced with conditional waits.
| // 10. Click create | |
| createButton.click() | |
| wait(30.seconds) | |
| // 10. Click create | |
| createButton.click() | |
| // TODO: Implement steps 11 and 12 to verify the project opened successfully | |
| // and that main.dart and README.md are open in editor tabs instead of a hardcoded wait. |
| @@ -0,0 +1,111 @@ | |||
| package io.flutter.integrationTest | |||
There was a problem hiding this comment.
[MUST-FIX] Missing copyright header. All new source code files must have a proper copyright header as per the repository style guide.
| package io.flutter.integrationTest | |
| /* | |
| * Copyright 2026 The Chromium Authors. All rights reserved. | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| package io.flutter.integrationTest |
References
- Ensure all new source code files (.java, .kt, .dart, .sh) have a proper copyright header (e.g., Copyright 2026 The Chromium Authors). Flag any missing headers on source code files as [MUST-FIX]. (link)
| // Todo Fix this | ||
| //Assertions.assertTrue(applicationTypeDropDown.getSelectedItem() == "Application") |
There was a problem hiding this comment.
[CONCERN] Stray TODO comment without justification. The repository style guide discourages leaving undocumented TODOs or commented-out assertions without explanation.
| // Todo Fix this | |
| //Assertions.assertTrue(applicationTypeDropDown.getSelectedItem() == "Application") | |
| // TODO: Implement application type verification once the driver API supports it. | |
| // Assertions.assertTrue(applicationTypeDropDown.getSelectedItem() == "Application") |
References
- Avoid stray TODO or FIXME comments without justification. (link)
| // Locates the "Project name" label. | ||
| val projectNameLabel = actionButtonByXpath(xQuery { byVisibleText("Project name:") }) | ||
|
|
||
| // Locates the "Project name" input field. | ||
| //val projectNameInput = x("//div[@class='LabeledComponent' and ./div[text()='Project name:']]//div[@class='ExtendableTextField']") | ||
| val projectNameInput = actionButtonByXpath(xQuery { byVisibleText("untitled") }) | ||
|
|
||
| // Locates the "Project location" label. | ||
| val projectLocationLabel = actionButtonByXpath(xQuery { byVisibleText("Project location:") }) |
There was a problem hiding this comment.
[CONCERN] Incorrect and fragile use of actionButtonByXpath for labels and text fields. Labels are not action buttons and should be located using generic x(...) finders, while text fields should use the textField(...) helper to ensure semantic correctness and prevent runtime casting issues.
| // Locates the "Project name" label. | |
| val projectNameLabel = actionButtonByXpath(xQuery { byVisibleText("Project name:") }) | |
| // Locates the "Project name" input field. | |
| //val projectNameInput = x("//div[@class='LabeledComponent' and ./div[text()='Project name:']]//div[@class='ExtendableTextField']") | |
| val projectNameInput = actionButtonByXpath(xQuery { byVisibleText("untitled") }) | |
| // Locates the "Project location" label. | |
| val projectLocationLabel = actionButtonByXpath(xQuery { byVisibleText("Project location:") }) | |
| // Locates the "Project name" label. | |
| val projectNameLabel = x("//div[@text='Project name:']") | |
| // Locates the "Project name" input field. | |
| val projectNameInput = textField(xQuery { byType("JTextField") }) | |
| // Locates the "Project location" label. | |
| val projectLocationLabel = x("//div[@text='Project location:']") |
| @@ -0,0 +1,109 @@ | |||
| /* | |||
Thanks for your contribution! Please replace this text with:
Review the contribution guidelines below:
AUTHORSfile.CHANGELOG.mdif appropriate.Contribution guidelines:
our contributor guide and
the Flutter organization contributor guide
for general expectations for PRs.
dart format.practices (discussion).