Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import java.util.UUID;
import java.util.stream.IntStream;

import static com.checkmarx.intellij.ui.BaseUITest.focusCxWindow;
import static com.checkmarx.intellij.ui.utils.RemoteRobotUtils.*;
import static com.checkmarx.intellij.ui.utils.TestConstants.*;
import static com.checkmarx.intellij.ui.utils.UIHelper.*;
Expand Down Expand Up @@ -67,15 +68,14 @@ public static void openScanResultsPanel() {
*/
public static void resetProjectSelection(int maxAttempts) {
//Need to set focus on reset by clicking
locateAndClickOnButton(RESET_PROJECT_SELECTION);
pollingWaitForElement(PROJECT_NAME_NULL,false);

// Early return optimization: Check if project, branch, and scan are already set to 'none'
// This prevents unnecessary UI interactions when selections are already in the reset state
boolean projectAlreadyNone = hasAnyComponent(SELECTED_PROJECT_NAME_NONE);
boolean branchAlreadyNone = hasAnyComponent(SELECTED_BRANCH_NAME_NONE);
boolean scanAlreadyNone = hasAnyComponent(SELECTED_SCAN_ID_NONE);
boolean isReset = checkProjctBranchScanSelectionIsReset();

if (projectAlreadyNone && branchAlreadyNone && scanAlreadyNone) {
if (isReset) {
log("Project, branch, and scan are already reset to 'none'. No action needed.");
return;
}
Expand Down Expand Up @@ -178,27 +178,89 @@ public static void collapseAllNodesInTree() {

/**
* Enters the scan ID in the scan field and selects it in the UI.
* Implements retry logic to handle transient network/timeout issues and focus problems in CI environments.
*
* @param validScanId If true, enters a valid scan ID; otherwise, enters an invalid scan ID.
*/
public static void enterScanIdAndSelect(boolean validScanId) {
String scanId = validScanId ? Environment.SCAN_ID : "invalid-scan-id";

waitFor(() -> {
List<JTextFieldFixture> fields =
findAll(JTextFieldFixture.class, SCAN_FIELD);

if (fields.size() != 1) {
return false;
int maxRetries = 3;
int retryCount = 0;

while (retryCount < maxRetries) {
try {
// Ensure Checkmarx window has focus before attempting to interact with scan field
focusCxWindow();

waitFor(() -> {
List<JTextFieldFixture> fields =
findAll(JTextFieldFixture.class, SCAN_FIELD);

if (fields.size() != 1) {
log("Expected 1 scan field, found: " + fields.size());
return false;
}

JTextFieldFixture field = fields.get(0);

// Check if field is visible and showing before attempting to interact
if (!field.isShowing()) {
log("Scan field is not showing, waiting...");
return false;
}

try {
// Click on the field first to ensure it gains focus
field.click();

// Small delay to let the UI stabilize after click
try {
Thread.sleep(300);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}

// Now set the text
field.setText(scanId);
String currentText = field.getText();
boolean textMatches = scanId.equals(currentText);
if (!textMatches) {
log("Text mismatch - expected: '" + scanId + "', actual: '" + currentText + "'");
}
return textMatches;
} catch (Exception e) {
log("Error setting text in scan field: " + e.getMessage());
return false;
}
});

Keyboard keyboard = new Keyboard(remoteRobot);
keyboard.enter();
log("Successfully entered scan ID: " + scanId);
return; // Success - exit method

} catch (Exception e) {
retryCount++;
log("Attempt " + retryCount + " failed to enter scan ID. Error: " + e.getMessage());

if (retryCount >= maxRetries) {
log("Max retries reached. Throwing exception.");
throw e;
}

// Wait before retry to let UI recover
try {
Thread.sleep(3000);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new RuntimeException("Interrupted while waiting to retry", ie);
}

// Try to refocus the window before retry
log("Refocusing Checkmarx window before retry...");
focusCxWindow();
}

JTextFieldFixture field = fields.get(0);
field.setText(scanId);
return scanId.equals(field.getText());
});

Keyboard keyboard = new Keyboard(remoteRobot);
keyboard.enter();
}
}

/**
Expand Down Expand Up @@ -397,4 +459,12 @@ public static void verifyLearnMore() {
public static void findLatestScanSelection() {
waitFor(() -> hasAnyComponent(String.format(LATEST_SCAN, Utils.formatLatest(true), Utils.formatLatest(true))));
}

public static boolean checkProjctBranchScanSelectionIsReset() {
boolean project = hasAnyComponent(SELECTED_PROJECT_NAME_NONE);
boolean branch = hasAnyComponent(SELECTED_BRANCH_NAME_NONE);
boolean scan = hasAnyComponent(SELECTED_SCAN_ID_NONE);

return project && branch && scan;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,25 @@
import com.intellij.remoterobot.fixtures.ComponentFixture;
import com.intellij.remoterobot.search.locators.Locators;
import com.intellij.remoterobot.utils.UtilsKt;
import okhttp3.OkHttpClient;
import org.intellij.lang.annotations.Language;
import org.jetbrains.annotations.NotNull;

import java.time.Duration;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class RemoteRobotUtils {

public static final RemoteRobot remoteRobot = new RemoteRobot("http://127.0.0.1:8580");
// Create OkHttpClient with extended timeouts to prevent SocketTimeoutException in CI environments
private static final OkHttpClient customHttpClient = new OkHttpClient.Builder()
.connectTimeout(120, TimeUnit.SECONDS) // 2 minutes for connection
.readTimeout(120, TimeUnit.SECONDS) // 2 minutes for read operations
.writeTimeout(120, TimeUnit.SECONDS) // 2 minutes for write operations
.callTimeout(180, TimeUnit.SECONDS) // 3 minutes for entire call
.build();

public static final RemoteRobot remoteRobot = new RemoteRobot("http://127.0.0.1:8580", customHttpClient);

public static boolean hasAnyComponent(@Language("XPath") String xpath) {
System.out.println("Checking hasAnyComponent: " + xpath);
Expand Down
Loading