Skip to content
Open
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
@@ -0,0 +1,127 @@
package com.testsigma.addons.mobileweb;

import com.testsigma.sdk.ApplicationType;
import com.testsigma.sdk.WebAction;
import com.testsigma.sdk.annotation.Action;
import com.testsigma.sdk.annotation.TestData;
import com.testsigma.sdk.Result;
import lombok.Data;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chromium.ChromiumDriver;
import org.openqa.selenium.devtools.Command;
import org.openqa.selenium.devtools.ConverterFunctions;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.HasDevTools;
import org.openqa.selenium.remote.Augmenter;
import org.openqa.selenium.remote.RemoteWebDriver;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

@Data
@Action(
actionText = "Switch Location to coordinates latitude: lat-val , longitude: long-val , accuracy: acc-val",
description = "Overrides geolocation using Chrome DevTools",
applicationType = ApplicationType.MOBILE_WEB,
useCustomScreenshot = false
)
public class MockGeoLocationAction extends WebAction {

@TestData(reference = "lat-val")
private com.testsigma.sdk.TestData latVal;

@TestData(reference = "long-val")
private com.testsigma.sdk.TestData longVal;

@TestData(reference = "acc-val")
private com.testsigma.sdk.TestData accVal;

@Override
public Result execute() throws NoSuchElementException {
Result result = Result.SUCCESS;

try {
// Input Validation
double latitude, longitude, accuracy;
try {
latitude = Double.parseDouble(latVal.getValue().toString());
logger.info("Parsed latitude: " + latitude);
} catch (NumberFormatException e) {
setErrorMessage("Invalid latitude format. Must be a number. Value provided: " + latVal.getValue());
return Result.FAILED;
}
Comment thread
ManojTestsigma marked this conversation as resolved.

try {
longitude = Double.parseDouble(longVal.getValue().toString());
logger.info("Parsed longitude: " + longitude);
} catch (NumberFormatException e) {
setErrorMessage("Invalid longitude format. Must be a number. Value provided: " + longVal.getValue());
return Result.FAILED;
}

try {
accuracy = Double.parseDouble(accVal.getValue().toString());
if (accuracy < 0) {
setErrorMessage("Invalid accuracy value. Must be a non-negative number. Value provided: " + accuracy);
return Result.FAILED;
}
logger.info("Parsed accuracy: " + accuracy);
} catch (NumberFormatException e) {
setErrorMessage("Invalid accuracy format. Must be a number. Value provided: " + accVal.getValue());
return Result.FAILED;
}

Map<String, Object> coordinates = new HashMap<>();
coordinates.put("latitude", latitude);
coordinates.put("longitude", longitude);
coordinates.put("accuracy", accuracy);

try {
// Enhance the driver to support DevTools
logger.info("Augmenting driver to support DevTools...");
WebDriver driver1 = new Augmenter().augment(this.driver);

// Initialize DevTools and create a session
logger.info("Initializing DevTools...");
DevTools devTool = ((HasDevTools) driver1).getDevTools();
devTool.createSessionIfThereIsNotOne();
logger.info("DevTools session successfully created.");

devTool.send(new Command<>("Emulation.setGeolocationOverride", coordinates, ConverterFunctions.empty()));
logger.info("Geolocation override applied successfully using DevTools.");
} catch (Exception e) {
logger.info("DevTools usage failed (" + e.getClass().getSimpleName() + "), attempting fallback...");

if (this.driver instanceof org.openqa.selenium.chromium.HasCdp) {
((org.openqa.selenium.chromium.HasCdp) this.driver).executeCdpCommand("Emulation.setGeolocationOverride",
coordinates);
logger.info("Fallback to HasCdp (Chrome/Edge) execution successful.");
} else if (this.driver instanceof ChromiumDriver) {
((ChromiumDriver) this.driver).executeCdpCommand("Emulation.setGeolocationOverride", coordinates);
logger.info("Fallback to ChromiumDriver (Chrome/Edge) execution successful.");
} else if (this.driver instanceof RemoteWebDriver) {
// Reflection hack for RemoteWebDriver to bypass HasDevTools/Augmenter
Method execute = RemoteWebDriver.class.getDeclaredMethod("execute", String.class, Map.class);
execute.setAccessible(true);
Map<String, Object> params = new HashMap<>();
params.put("cmd", "Emulation.setGeolocationOverride");
params.put("params", coordinates);
execute.invoke(this.driver, "executeCdpCommand", params);
logger.info("Fallback to RemoteWebDriver execution successful.");
} else {
throw e; // Rethrow if no fallback is possible
}
Comment on lines +105 to +116
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Reflection-based fallback is likely non-functional.

The RemoteWebDriver.execute() method is an internal method for W3C WebDriver protocol commands, not CDP commands. Passing "executeCdpCommand" as the command name won't work because it's not a recognized W3C command. The nested params structure also doesn't match the expected format.

If the driver doesn't implement HasCdp or isn't a ChromiumDriver, it likely doesn't support CDP at all. Consider removing this fallback or providing a clear error message indicating CDP is not supported.

Proposed fix to replace with clear error handling
         } else if (this.driver instanceof ChromiumDriver) {
           ((ChromiumDriver) this.driver).executeCdpCommand("Emulation.setGeolocationOverride", coordinates);
           logger.info("Fallback to ChromiumDriver (Chrome/Edge) execution successful.");
-        } else if (this.driver instanceof RemoteWebDriver) {
-          // Reflection hack for RemoteWebDriver to bypass HasDevTools/Augmenter
-          Method execute = RemoteWebDriver.class.getDeclaredMethod("execute", String.class, Map.class);
-          execute.setAccessible(true);
-          Map<String, Object> params = new HashMap<>();
-          params.put("cmd", "Emulation.setGeolocationOverride");
-          params.put("params", coordinates);
-          execute.invoke(this.driver, "executeCdpCommand", params);
-          logger.info("Fallback to RemoteWebDriver execution successful.");
         } else {
-          throw e; // Rethrow if no fallback is possible
+          throw new UnsupportedOperationException(
+              "Driver does not support CDP commands. Geolocation override requires Chrome/Chromium-based browser with DevTools support.");
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} else if (this.driver instanceof RemoteWebDriver) {
// Reflection hack for RemoteWebDriver to bypass HasDevTools/Augmenter
Method execute = RemoteWebDriver.class.getDeclaredMethod("execute", String.class, Map.class);
execute.setAccessible(true);
Map<String, Object> params = new HashMap<>();
params.put("cmd", "Emulation.setGeolocationOverride");
params.put("params", coordinates);
execute.invoke(this.driver, "executeCdpCommand", params);
logger.info("Fallback to RemoteWebDriver execution successful.");
} else {
throw e; // Rethrow if no fallback is possible
}
} else if (this.driver instanceof ChromiumDriver) {
((ChromiumDriver) this.driver).executeCdpCommand("Emulation.setGeolocationOverride", coordinates);
logger.info("Fallback to ChromiumDriver (Chrome/Edge) execution successful.");
} else {
throw new UnsupportedOperationException(
"Driver does not support CDP commands. Geolocation override requires Chrome/Chromium-based browser with DevTools support.");
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@mock_geo_location/src/main/java/com/testsigma/addons/mobileweb/MockGeoLocationAction.java`
around lines 105 - 116, The reflection-based RemoteWebDriver fallback in
MockGeoLocationAction (the block using
RemoteWebDriver.class.getDeclaredMethod("execute", ...) and invoking
"executeCdpCommand") is non-functional for CDP; remove this reflection hack and
replace it with clear error handling: detect lack of CDP support (check for
instances of HasCdp or ChromiumDriver earlier) and when neither is available
throw or log a descriptive UnsupportedOperationException/RuntimeException that
includes the driver class name and a message that CDP is not supported, ensuring
no silent fallback is attempted.

}

} catch (Exception e) {
logger.warn("Failed to override geolocation. Error: " + ExceptionUtils.getStackTrace(e));
setErrorMessage("Failed to override geolocation. Error: " + ExceptionUtils.getMessage(e));
result = Result.FAILED;
}

return result;
}
}