From 0a7561598bd61c7bf686559e2b89d8c7598499ed Mon Sep 17 00:00:00 2001 From: Anastasia Katsman Date: Thu, 28 Mar 2024 13:26:51 +0100 Subject: [PATCH] [rdct-tests]: GTW-8200: use jmx robot in all ui tests + wait for indexing disabled when needed GitOrigin-RevId: e223917bb3c8f38accf016ee55aa7fb10b6765db --- .../sdk/ui/components/JChangesListViewUi.kt | 20 ++++++ .../driver/sdk/ui/components/JCheckBoxUi.kt | 30 +++++++++ .../driver/sdk/ui/components/JComboBoxUi.kt | 1 + .../driver/sdk/ui/components/JEditorUi.kt | 4 ++ .../driver/sdk/ui/components/JTreeUI.kt | 8 ++- .../driver/sdk/ui/components/UiComponent.kt | 10 +++ .../intellij/driver/sdk/ui/remote/Robot.kt | 2 + .../driver/sdk/ui/remote/RobotService.kt | 2 +- .../remotedriver/RobotService.kt | 7 ++- .../fixtures/JChangesListViewFixture.kt | 61 +++++++++++++++++++ .../remotedriver/fixtures/JTreeTextFixture.kt | 6 +- .../remotedriver/robot/SmoothRobot.kt | 21 +++++++ 12 files changed, 166 insertions(+), 6 deletions(-) create mode 100644 platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/JChangesListViewUi.kt create mode 100644 platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/JCheckBoxUi.kt create mode 100644 plugins/performanceTesting/remote-driver/src/com/jetbrains/performancePlugin/remotedriver/fixtures/JChangesListViewFixture.kt diff --git a/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/JChangesListViewUi.kt b/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/JChangesListViewUi.kt new file mode 100644 index 000000000000..aa8e7756d371 --- /dev/null +++ b/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/JChangesListViewUi.kt @@ -0,0 +1,20 @@ +package com.intellij.driver.sdk.ui.components + +import com.intellij.driver.client.Remote +import com.intellij.driver.sdk.ui.remote.REMOTE_ROBOT_MODULE_ID + +class JChangesListViewUi(data: ComponentData) : JTreeUiComponent(data) { + val changesFixture = driver.new(JChangesListViewFixtureRef::class, robotService.robot, component) + fun addFileName(fileName: String) { + changesFixture.addFileName(fileName) + } + fun removeFileName(fileName: String) { + changesFixture.removeFileName(fileName) + } +} + +@Remote("com.jetbrains.performancePlugin.remotedriver.fixtures.JChangesListViewFixture", plugin = REMOTE_ROBOT_MODULE_ID) +interface JChangesListViewFixtureRef { + fun addFileName(fileName: String) + fun removeFileName(fileName: String) +} \ No newline at end of file diff --git a/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/JCheckBoxUi.kt b/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/JCheckBoxUi.kt new file mode 100644 index 000000000000..ed34befb30ef --- /dev/null +++ b/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/JCheckBoxUi.kt @@ -0,0 +1,30 @@ +package com.intellij.driver.sdk.ui.components + +import com.intellij.driver.client.Remote +import com.intellij.driver.sdk.ui.Finder +import com.intellij.driver.sdk.ui.remote.REMOTE_ROBOT_MODULE_ID +import org.intellij.lang.annotations.Language + +fun Finder.checkBox(@Language("xpath") xpath: String? = null) = x(xpath ?: "//div[@class='JCheckBox']", + JCheckBoxUi::class.java) + +class JCheckBoxUi(data: ComponentData) : UiComponent(data) { + private val checkboxComponent by lazy { driver.cast(component, JCheckBox::class) } + + fun check() { + if (!isSelected()) { + click() + } + } + fun uncheck() { + if (isSelected()) { + click() + } + } + fun isSelected() = checkboxComponent.isSelected() +} + +@Remote("javax.swing.JCheckBox", plugin = REMOTE_ROBOT_MODULE_ID) +interface JCheckBox { + fun isSelected(): Boolean +} \ No newline at end of file diff --git a/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/JComboBoxUi.kt b/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/JComboBoxUi.kt index f3ba1ea62271..243215924c1b 100644 --- a/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/JComboBoxUi.kt +++ b/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/JComboBoxUi.kt @@ -18,6 +18,7 @@ class JComboBoxUiComponent(data: ComponentData) : UiComponent(data) { } fixture.select(fixture.listValues().single { it.contains(text) }) } + fun listValues() = fixture.listValues() } @Remote("com.jetbrains.performancePlugin.remotedriver.fixtures.JComboBoxTextFixture", plugin = REMOTE_ROBOT_MODULE_ID) diff --git a/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/JEditorUi.kt b/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/JEditorUi.kt index b03e3a99a220..c0256b95a2ab 100644 --- a/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/JEditorUi.kt +++ b/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/JEditorUi.kt @@ -23,6 +23,10 @@ class JEditorUiComponent(data: ComponentData) : UiComponent(data) { private val caretPosition get() = editor.getCaretModel().getLogicalPosition() + fun selectAndDrag(from: Point, to: Point, delayMs: Int) { + robotService.robot.selectAndDrag(component, to, from, delayMs) + } + var text: String get() = document.getText() set(value) { diff --git a/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/JTreeUI.kt b/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/JTreeUI.kt index 8f35361d09b9..6dc6936e1a07 100644 --- a/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/JTreeUI.kt +++ b/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/JTreeUI.kt @@ -17,7 +17,8 @@ fun Finder.tree(@Language("xpath") xpath: String? = null) = x(xpath ?: Locators. JTreeUiComponent::class.java) open class JTreeUiComponent(data: ComponentData) : UiComponent(data) { - protected val fixture by lazy { driver.new(JTreeFixtureRef::class, robotService.robot, component) } + protected val fixture: JTreeFixtureRef + get() = driver.new(JTreeFixtureRef::class, robotService.robot, component) fun clickRow(row: Int) = fixture.clickRow(row) fun rightClickRow(row: Int) = fixture.rightClickRow(row) @@ -43,6 +44,10 @@ open class JTreeUiComponent(data: ComponentData) : UiComponent(data) { } ?: throw PathNotFoundException(path.toList()) } + fun expandAll(timeoutMs: Int) { + fixture.expandAll(timeoutMs) + } + private fun expandPath(vararg path: String, fullMatch: Boolean = true) = waitFor(10.seconds, errorMessage = "Failed find ${path.toList()}") { try { val expandedPath = mutableListOf() @@ -107,4 +112,5 @@ interface JTreeFixtureRef : Component { fun valueAt(path: String): String fun collectExpandedPaths(): TreePathToRowList fun selectRow(row: Int): JTreeFixtureRef? + fun expandAll(timeoutMs: Int) } \ No newline at end of file diff --git a/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/UiComponent.kt b/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/UiComponent.kt index bcb7297a3c11..3af7ebcd1a57 100644 --- a/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/UiComponent.kt +++ b/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/UiComponent.kt @@ -168,4 +168,14 @@ open class UiComponent(private val data: ComponentData) : Finder, WithKeyboard { fun hasFocus(): Boolean { return component.isFocusOwner() } + + fun mousePressMoveRelease(from: Point, to: Point) { + robotService.robot.apply { + moveMouse(component, from) + pressMouse(RemoteMouseButton.LEFT) + + moveMouse(component, to) + releaseMouse(RemoteMouseButton.LEFT) + } + } } \ No newline at end of file diff --git a/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/remote/Robot.kt b/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/remote/Robot.kt index 0b9a4ace7066..f12f85702819 100644 --- a/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/remote/Robot.kt +++ b/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/remote/Robot.kt @@ -25,6 +25,7 @@ interface Robot { fun pressMouse(component: Component, point: Point, mouseButton: RemoteMouseButton) fun pressMouse(point: Point, mouseButton: RemoteMouseButton) fun pressKey(p0: Int) + fun doubleKey(p0: Int) fun releaseKey(p0: Int) fun type(char: Char) fun enterText(text: String) @@ -42,4 +43,5 @@ interface Robot { fun rotateMouseWheel(p0: Int) fun pressAndReleaseKeys(vararg p0: Int) fun waitForIdle() + fun selectAndDrag(component: Component, to: Point, from: Point, delayMs: Int) } \ No newline at end of file diff --git a/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/remote/RobotService.kt b/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/remote/RobotService.kt index 6a6bac9c392e..59cb6264f842 100644 --- a/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/remote/RobotService.kt +++ b/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/remote/RobotService.kt @@ -13,5 +13,5 @@ interface RobotService { fun findAll(@Language("xpath") xpath: String): List fun findAll(@Language("xpath") xpath: String, component: Component): List fun findAllText(component: Component): TextDataList - fun saveHierarchy(path: String) + fun saveHierarchy(folderPath: String, fileName: String = "ui") } \ No newline at end of file diff --git a/plugins/performanceTesting/remote-driver/src/com/jetbrains/performancePlugin/remotedriver/RobotService.kt b/plugins/performanceTesting/remote-driver/src/com/jetbrains/performancePlugin/remotedriver/RobotService.kt index 4281cd11bf86..dc3570aec2f9 100644 --- a/plugins/performanceTesting/remote-driver/src/com/jetbrains/performancePlugin/remotedriver/RobotService.kt +++ b/plugins/performanceTesting/remote-driver/src/com/jetbrains/performancePlugin/remotedriver/RobotService.kt @@ -31,16 +31,17 @@ internal class RobotService { return TextParser.parseComponent(component, TextToKeyCache).let { TextDataList().apply { addAll(it) } } } - fun saveHierarchy(path: String) { + fun saveHierarchy(folderPath: String, fileName: String = "ui.html") { val html = xpathSearcher.modelCreator.create(null).convertToHtml() - Paths.get(path).resolve("ui.html").toFile().writeText(html) + Paths.get(folderPath).resolve(fileName).toFile().writeText(html) staticFiles.forEach { staticFilePath -> this::class.java.classLoader.getResource(staticFilePath)?.let { resource -> - Paths.get(path).resolve(staticFilePath).toFile().apply { resolve("..").mkdirs() }.writeBytes(resource.readBytes()) + Paths.get(folderPath).resolve(staticFilePath).toFile().apply { resolve("..").mkdirs() }.writeBytes(resource.readBytes()) } } } + private val staticFiles = listOf( "static/scripts.js", "static/styles.css", diff --git a/plugins/performanceTesting/remote-driver/src/com/jetbrains/performancePlugin/remotedriver/fixtures/JChangesListViewFixture.kt b/plugins/performanceTesting/remote-driver/src/com/jetbrains/performancePlugin/remotedriver/fixtures/JChangesListViewFixture.kt new file mode 100644 index 000000000000..488419bc2d60 --- /dev/null +++ b/plugins/performanceTesting/remote-driver/src/com/jetbrains/performancePlugin/remotedriver/fixtures/JChangesListViewFixture.kt @@ -0,0 +1,61 @@ +package com.jetbrains.performancePlugin.remotedriver.fixtures + +import com.intellij.util.ui.tree.TreeUtil +import com.jetbrains.performancePlugin.remotedriver.dataextractor.computeOnEdt +import org.assertj.swing.core.Robot +import java.awt.Point +import java.awt.Rectangle +import javax.swing.JCheckBox +import javax.swing.JPanel +import javax.swing.JTree +import javax.swing.tree.DefaultMutableTreeNode +import javax.swing.tree.TreePath + +class JChangesListViewFixture(private val robot: Robot, private val component: JTree) : JTreeTextFixture(robot, component) { + + fun addFileName(fileName: String) { + handleCheckBoxWithFileName(fileName, true) + } + + fun removeFileName(fileName: String) { + handleCheckBoxWithFileName(fileName, false) + } + + private fun handleCheckBoxWithFileName(fileName: String, setEnabled: Boolean) { + val root = component.model.root as DefaultMutableTreeNode + val node = TreeUtil.findNode(root) { it.toString().contains(fileName) } + + val fileTreePath = TreePath(node!!.path) + val checkbox = getCheckBoxForNode(node, fileTreePath) + + if (checkbox.isSelected != setEnabled) { + val fileTrePathLocation = computeOnEdt { + component.getPathBounds(fileTreePath) ?: error("Have not found bounds") + } + clickOnCheckbox(checkbox, fileTrePathLocation) + } + } + + private fun clickOnCheckbox(checkbox: JCheckBox, fileTrePathLocation: Rectangle) { + val checkBoxBounds = checkbox.bounds + + val clickX = fileTrePathLocation.x + checkBoxBounds.width / 2 + val clickY = fileTrePathLocation.y + checkBoxBounds.height / 2 + + robot.click(component, Point(clickX, clickY)) + } + + private fun getCheckBoxForNode(node: DefaultMutableTreeNode?, fileTreePath: TreePath): JCheckBox { + val renderer = computeOnEdt { + component.cellRenderer.getTreeCellRendererComponent(component, node, + component.isPathSelected(fileTreePath), component.isExpanded(fileTreePath), + component.model.isLeaf(node), + component.getRowForPath(fileTreePath), + component.isPathEditable(fileTreePath)) + } + + val jpanel = renderer as? JPanel ?: error("Only JPanel is currently supported") + val checkbox = jpanel.components.singleOrNull { it is JCheckBox } as? JCheckBox ?: error("Only JCheckBox is currently supported") + return checkbox + } +} \ No newline at end of file diff --git a/plugins/performanceTesting/remote-driver/src/com/jetbrains/performancePlugin/remotedriver/fixtures/JTreeTextFixture.kt b/plugins/performanceTesting/remote-driver/src/com/jetbrains/performancePlugin/remotedriver/fixtures/JTreeTextFixture.kt index d7bc3d67fc78..5ff1c20baf40 100644 --- a/plugins/performanceTesting/remote-driver/src/com/jetbrains/performancePlugin/remotedriver/fixtures/JTreeTextFixture.kt +++ b/plugins/performanceTesting/remote-driver/src/com/jetbrains/performancePlugin/remotedriver/fixtures/JTreeTextFixture.kt @@ -9,7 +9,7 @@ import org.assertj.swing.core.Robot import org.assertj.swing.fixture.JTreeFixture import javax.swing.JTree -class JTreeTextFixture(robot: Robot, private val component: JTree) : JTreeFixture(robot, component) { +open class JTreeTextFixture(robot: Robot, private val component: JTree) : JTreeFixture(robot, component) { private val cellReader = JTreeTextCellReader() init { @@ -35,4 +35,8 @@ class JTreeTextFixture(robot: Robot, private val component: JTree) : JTreeFixtur } return result } + + fun expandAll(timeoutMs: Int) { + TreeUtil.promiseExpandAll(component).blockingGet(timeoutMs) + } } \ No newline at end of file diff --git a/plugins/performanceTesting/remote-driver/src/com/jetbrains/performancePlugin/remotedriver/robot/SmoothRobot.kt b/plugins/performanceTesting/remote-driver/src/com/jetbrains/performancePlugin/remotedriver/robot/SmoothRobot.kt index b298fbbeb6c8..de15bdd96d8a 100644 --- a/plugins/performanceTesting/remote-driver/src/com/jetbrains/performancePlugin/remotedriver/robot/SmoothRobot.kt +++ b/plugins/performanceTesting/remote-driver/src/com/jetbrains/performancePlugin/remotedriver/robot/SmoothRobot.kt @@ -190,6 +190,14 @@ internal class SmoothRobot : Robot { basicRobot.pressKey(p0) } + fun doubleKey(p0:Int) { + fastRobot.keyPress(p0) + fastRobot.keyRelease(p0) + Thread.sleep(10) + fastRobot.keyPress(p0) + fastRobot.keyRelease(p0) + } + override fun settings(): Settings = basicRobot.settings() override fun enterText(text: String) { @@ -459,4 +467,17 @@ internal class SmoothRobot : Robot { } return unified } + + fun selectAndDrag(component: Component, from: Point, to: Point, delayMs: Int) { + moveMouse(component, from) + + click(component, from) + pressMouse(RemoteMouseButton.LEFT) + + Thread.sleep(delayMs.toLong()) + moveMouse(component, to) + + Thread.sleep(delayMs.toLong()) + releaseMouse(RemoteMouseButton.LEFT) + } } \ No newline at end of file