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 0744fee4b846..14c0f33f8ab1 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 @@ -429,11 +429,15 @@ open class UiComponent(private val data: ComponentData) : Finder, WithKeyboard { } } - fun tripleClick(point: Point) { + fun tripleClick(point: Point? = null) { LOG.info("Triple click at $this${point?.let { ": $it" } ?: ""}") - withComponent { robot.click(it, point, RemoteMouseButton.LEFT, 3) } + if (point != null) { + withComponent { robot.click(it, point, RemoteMouseButton.LEFT, 3) } + } + else { + withComponent { robot.tripleClick(it) } + } } - fun rightClick(point: Point? = null) { LOG.info("Right click at $this${point?.let { ": $it" } ?: ""}") if (point != null) { diff --git a/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/common/toolwindows/ToolWindowsToolbars.kt b/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/common/toolwindows/ToolWindowsToolbars.kt index 7385d7b5fc3d..5216d4560c36 100644 --- a/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/common/toolwindows/ToolWindowsToolbars.kt +++ b/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/common/toolwindows/ToolWindowsToolbars.kt @@ -25,7 +25,6 @@ class ToolWindowLeftToolbarUi(data: ComponentData) : ToolWindowToolbarUi(data) { val servicesButton = stripeButton("Services") val terminalButton = stripeButton("Terminal") val problemsButton = stripeButton("Problems") - val jupyterButton = stripeButton("Jupyter") val moreButton = stripeButton("More") val debugButton = stripeButton("Debug") val findButton = stripeButton("Find") diff --git a/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/kotlin/NotebookEditorComponent.kt b/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/notebooks/NotebookEditorComponent.kt similarity index 72% rename from platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/kotlin/NotebookEditorComponent.kt rename to platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/notebooks/NotebookEditorComponent.kt index b936fc6036a1..aae03d06f779 100644 --- a/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/kotlin/NotebookEditorComponent.kt +++ b/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/notebooks/NotebookEditorComponent.kt @@ -1,19 +1,33 @@ -package com.intellij.driver.sdk.ui.components.kotlin +package com.intellij.driver.sdk.ui.components.notebooks +import com.intellij.driver.client.Driver import com.intellij.driver.client.service -import com.intellij.driver.sdk.* +import com.intellij.driver.sdk.PsiFile +import com.intellij.driver.sdk.PsiManager +import com.intellij.driver.sdk.invokeAction +import com.intellij.driver.sdk.invokeActionWithRetries +import com.intellij.driver.sdk.singleProject +import com.intellij.driver.sdk.step import com.intellij.driver.sdk.ui.Finder import com.intellij.driver.sdk.ui.components.ComponentData import com.intellij.driver.sdk.ui.components.UiComponent import com.intellij.driver.sdk.ui.components.common.EditorComponentImpl import com.intellij.driver.sdk.ui.components.common.JEditorUiComponent import com.intellij.driver.sdk.ui.components.common.editor +import com.intellij.driver.sdk.ui.components.common.ideFrame +import com.intellij.driver.sdk.ui.components.common.toolwindows.ToolWindowRightToolbarUi +import com.intellij.driver.sdk.ui.components.common.toolwindows.projectView import com.intellij.driver.sdk.ui.components.elements.JLabelUiComponent +import com.intellij.driver.sdk.ui.components.elements.JTextFieldUI import com.intellij.driver.sdk.ui.components.elements.JcefOffScreenViewComponent import com.intellij.driver.sdk.ui.components.elements.LetsPlotComponent import com.intellij.driver.sdk.ui.components.elements.NotebookTableOutputUi +import com.intellij.driver.sdk.ui.components.elements.popup import com.intellij.driver.sdk.ui.pasteText +import com.intellij.driver.sdk.ui.should import com.intellij.driver.sdk.ui.ui +import com.intellij.driver.sdk.waitFor +import com.intellij.driver.sdk.waitForCodeAnalysis import org.intellij.lang.annotations.Language import kotlin.time.Duration import kotlin.time.Duration.Companion.milliseconds @@ -57,6 +71,20 @@ class NotebookEditorUiComponent(private val data: ComponentData) : JEditorUiComp get() = x("//div[@myicon='restartKernel.svg']") private val interruptKernel get() = x("//div[@myicon='stop.svg']") + val notebookCellOutputs: List + get() = xx("//div[@class='FullEditorWidthRenderer']//div[@class='EditorComponentImpl']").list() + val jcefOffScreens: List + get() = xx("//div[@class='JcefOffScreenViewComponent']", JcefOffScreenViewComponent::class.java).list() + val notebookCellExecutionInfos: List + get() = xx("//div[@accessiblename='ExecutionLabel']", JLabelUiComponent::class.java).list() + val notebookTables: List + get() = xx("//div[@class='LoadingDecoratorLayeredPaneImpl']/div[@class='JPanel'][descendant::div[@class='TableResultView']][descendant::div[@class='TwoSideComponent']]", NotebookTableOutputUi::class.java).list() + val notebookPlots: List + get() = xx("//div[@class='LetsPlotComponent']", LetsPlotComponent::class.java).list() + val toolbar: UiComponent + get() = x("//div[@class='JupyterFileEditorToolbar']") + val imagePanel: List + get() = xx("//div[@class='FullEditorWidthRenderer']//div[@class='ImagePanel']").list() override val editorComponent: EditorComponentImpl get() = when { @@ -161,24 +189,6 @@ class NotebookEditorUiComponent(private val data: ComponentData) : JEditorUiComp """.trimIndent() ).list() - val notebookCellOutputs: List - get() = xx("//div[@class='FullEditorWidthRenderer']//div[@class='EditorComponentImpl']").list() - - val notebookMdCellsAsHtml: List - get() = xx("//div[@class='JcefOffScreenViewComponent']", JcefOffScreenViewComponent::class.java).list() - - val notebookCellExecutionInfos: List - get() = xx("//div[@accessiblename='ExecutionLabel']", JLabelUiComponent::class.java).list() - - val notebookTables: List - get() = xx("//div[@class='LoadingDecoratorLayeredPaneImpl']/div[@class='JPanel'][descendant::div[@class='TableResultView']][descendant::div[@class='TwoSideComponent']]", NotebookTableOutputUi::class.java).list() - - val notebookPlots: List - get() = xx("//div[@class='LetsPlotComponent']", LetsPlotComponent::class.java).list() - - val toolbar: UiComponent - get() = x("//div[@class='JupyterFileEditorToolbar']") - fun JLabelUiComponent.getExecutionTimeInMs(): Long = step("Get cell execution time") { this.getText().run { val matchSeconds = Regex("\\d+s").find(this)?.value?.substringBefore("s")?.toLong() ?: 0 @@ -188,3 +198,56 @@ class NotebookEditorUiComponent(private val data: ComponentData) : JEditorUiComp } } } + +enum class NotebookType(val typeName: String, val newNotebookActionId: String) { + KOTLIN("Kotlin", "NewKotlinNotebookAction"), + JUPYTER("Jupyter", "NewJupyterNotebookAction"); +} + +/** + * Creates a new Kotlin or Jupyter notebook in the IDE. + * + * @param name The name for the new notebook. Defaults to "New Notebook". + * @param type The type of notebook to create. + */ +fun Driver.createNewNotebook(name: String = "New Notebook", type: NotebookType) { + ideFrame { + projectView { + projectViewTree.run { + waitFor("wait for project tree to load", 30.seconds) { + getAllTexts().isNotEmpty() + } + getAllTexts().first().click() + } + } + + invokeAction(type.newNotebookActionId, false) + + popup().run { + x("//div[@accessiblename='Name']", JTextFieldUI::class.java).click() + + keyboard { + driver.ui.pasteText(name) + should("expect $name in the popup") { + getAllTexts().any { it.text == name } + } + enter() // submit the popup + } + } + + waitFor("the editor is present") { + notebookEditor().present() + } + } +} + +fun Driver.closeJupyterVariablesToolwindow() { + ideFrame { + val rightToolbar = xx(ToolWindowRightToolbarUi::class.java) { byClass("ToolWindowRightToolbar") }.list().firstOrNull() + ?: return@ideFrame + val varsButton = rightToolbar.stripeButton("Jupyter Variables") + if (varsButton.present()) { + varsButton.close() + } + } +} 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 7a5a71c0de9f..9aab7bed9f70 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 @@ -38,6 +38,14 @@ interface Robot { fun rightClick(component: Component) fun focus(component: Component) fun doubleClick(component: Component) + /** + * Performs a left mouse triple-click on the given component. + * + * Triple-click is commonly used to select a whole line or statement. + + * @param c the target component to receive the triple-click + */ + fun tripleClick(component: Component) fun cleanUpWithoutDisposingWindows() fun isReadyForInput(component: Component): Boolean fun focusAndWaitForFocusGain(component: Component) 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 25bd57ac4077..31e32b16e794 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 @@ -134,6 +134,10 @@ internal class SmoothRobot @JvmOverloads constructor( click(c, MouseButton.LEFT_BUTTON, 2) } + fun tripleClick(c: Component) { + click(c, MouseButton.LEFT_BUTTON, 3) + } + fun pressMouse(mouseButton: RemoteMouseButton) { pressMouse(mouseButton.toAssertJ()) }