[remote-driver] support gutter line markers for ui tests

(cherry picked from commit 6825afc71fc2f340129cb042ca82931f357576f7)

GitOrigin-RevId: 1822e539f9d0dabacb8f78fef21481440965bf01
This commit is contained in:
Alexander.Danilov
2025-02-24 07:36:06 +01:00
committed by intellij-monorepo-bot
parent e9c1305003
commit 8f65843ba2
3 changed files with 57 additions and 3 deletions

View File

@@ -1237,6 +1237,33 @@ final class EditorGutterComponentImpl extends EditorGutterComponentEx
return list;
}
@VisibleForTesting
public @Nullable Rectangle getActiveGutterRendererRectangle(int lineNum, String accessibleName) {
int firstVisibleOffset = myEditor.visualLineStartOffset(lineNum);
int lastVisibleOffset = EditorUtil.getVisualLineEndOffset(myEditor, lineNum);
List<Pair<ActiveGutterRenderer, Rectangle>> rectangles = new ArrayList<>();
Rectangle[] rectangle = {null};
processRangeHighlighters(firstVisibleOffset, lastVisibleOffset, highlighter -> {
LineMarkerRenderer renderer = highlighter.getLineMarkerRenderer();
if (renderer instanceof ActiveGutterRenderer activeRenderer) {
if (!activeRenderer.getAccessibleName().equals(accessibleName) || rectangle[0] != null) return;
Rectangle rect = getLineRendererRectangle(highlighter);
if (rect != null) {
Rectangle bounds = activeRenderer.calcBounds(myEditor, lineNum, rect);
if (bounds != null) {
int[] lineToYRange = myEditor.visualLineToYRange(lineNum);
boolean isAtLine =
lineToYRange[0] >= bounds.y && lineToYRange[1] <= (bounds.y + bounds.height);
if (isAtLine) {
rectangle[0] = bounds;
}
}
}
}
});
return rectangle[0];
}
private boolean isHighlighterVisible(RangeHighlighter highlighter) {
return !FoldingUtil.isHighlighterFolded(myEditor, highlighter);
}

View File

@@ -26,6 +26,7 @@ interface Editor {
fun logicalPositionToOffset(logicalPosition: LogicalPosition): Int
fun getSelectionModel(): SelectionModel
fun getSoftWrapModel(): SoftWrapModel
fun visualLineToY(visualLine: Int): Int
}
@Remote("com.intellij.openapi.editor.VisualPosition")

View File

@@ -16,6 +16,7 @@ import com.intellij.driver.sdk.ui.components.UiComponent
import com.intellij.driver.sdk.ui.remote.Component
import org.intellij.lang.annotations.Language
import java.awt.Point
import java.awt.Rectangle
fun Finder.editor(@Language("xpath") xpath: String? = null): JEditorUiComponent {
return x(xpath ?: "//div[@class='EditorComponentImpl']",
@@ -232,7 +233,6 @@ class GutterUiComponent(data: ComponentData) : UiComponent(data) {
val iconAreaOffset
get() = gutter.getIconAreaOffset()
fun getGutterIcons(): List<GutterIcon> {
waitFor { this.icons.isNotEmpty() }
return this.icons
@@ -249,6 +249,29 @@ class GutterUiComponent(data: ComponentData) : UiComponent(data) {
rightClick(icons.firstOrNull { it.line == line - 1 }!!.location)
}
fun clickLineMarkerAtLine(lineNum: Int, accessibleName: String, lineY: Int? = null) {
val lineIndex = lineNum - 1
val rectangle = waitNotNull("No $accessibleName marker on line $lineNum") {
driver.withContext(OnDispatcher.EDT) {
gutter.getActiveGutterRendererRectangle(lineIndex, accessibleName)
}
}
val lineY = lineY ?: driver.withContext(OnDispatcher.EDT) {
val startY = gutter.getEditor().visualLineToY(lineIndex)
startY + (gutter.getEditor().getLineHeight() / 2)
}
click(Point(rectangle.centerX.toInt(), lineY))
}
fun clickVcsLineMarkerAtLine(line: Int) {
//to support a deleted block marker, click on the first third of the line
val lineY = driver.withContext(OnDispatcher.EDT) {
val startY = gutter.getEditor().visualLineToY(line - 1)
startY + (gutter.getEditor().getLineHeight() / 6)
}
clickLineMarkerAtLine(line, "VCS marker: changed line", lineY)
}
inner class GutterIcon(private val data: GutterIconWithLocation) {
val line: Int
get() = data.getLine()
@@ -269,6 +292,7 @@ class GutterUiComponent(data: ComponentData) : UiComponent(data) {
.findLast { it.trim().startsWith("path") }!!.split('=')[1]
}
}
}
enum class GutterIcon(val path: String) {
@@ -287,7 +311,6 @@ data class GutterState(
val iconPath: String = "",
)
class InlayHint(val offset: Int, val text: String)
fun List<InlayHint>.getHint(offset: Int): InlayHint {
@@ -298,12 +321,15 @@ fun List<InlayHint>.getHint(offset: Int): InlayHint {
return foundHint
}
@Remote("com.intellij.openapi.editor.impl.EditorGutterComponentImpl")
interface EditorGutterComponentImpl : Component {
fun getLineGutterMarks(): List<GutterIconWithLocation>
fun getIconAreaOffset(): Int
fun getActiveGutterRendererRectangle(lineNum: Int, accessibleName: String): Rectangle?
fun getEditor(): Editor
}
@Remote("com.intellij.openapi.editor.impl.GutterIconWithLocation")