jmj
June 24, 2022, 12:08pm
1
When trying to get context handles in iOS, throws an exception.
java.lang.ClassCastException: class com.google.common.collect.Maps$TransformedEntriesMap cannot be cast to class java.lang.String (com.google.common.collect.Maps$TransformedEntriesMap is in unnamed module of loader 'app'; java.lang.String is in module java.base of loader 'bootstrap')
Steps I m trying to achieve
Open the app and perform some operations
Then switch to Safari browser and perform operations
Below is the sample code snippet
((IOSDriver)driver).activateApp("com.apple.mobilesafari");
Set<String> contexts = ((IOSDriver) driver).getContextHandles();
for(String handle:contexts)
{
System.out.println(handle);
}
I have also added capabilities related to webview as well
capabilities.setCapability("fullContextList", true);
capabilities.setCapability("includeSafariInWebviews","true");
Appium java client version 8.0.0
Appium version 1.22.0
wreed
June 24, 2022, 4:26pm
2
I think you are running into a bug in java-client:
opened 08:01AM - 03 Sep 21 UTC
## Description
I use the image comparison feature of appium and since last up… date of appium, saving the comparison result picture when a failure occure is broken and throws an exception. The comparison itself does work correctly.
It throws the ecception on this function
res.storeVisualization(failViz);
I have checked the code in github and it looks like that in the class "ComparisonResult.java" line 63
a map is casted to String.
return ((String) getCommandResult().get(VISUALIZATION)).getBytes(StandardCharsets.UTF_8);
## Environment
* Java client build version : 7.4.1
* Appium server version or git revision : 1.21.0
* Desktop OS/version used to run Appium if necessary: MacOs Big Sur
* Node.js : 12.19.1
* Mobile platform/version under test: ios / Android
* Real device or emulator/simulator: Simulator
## Details
Please provide more details, if necessary.
## Code To Reproduce Issue [ Good To Have ]
```
public static void doVisualCheckByELement(String locatorType, String locator, String checkName, double MATCH_THRESHOLD, String baseline) throws Exception {
waitTime(1000);
final String dir = System.getProperty("user.dir");
File VALIDATION_PATH = new File(dir+"/src/test/resources/TestData/compareScrn");
// File VALIDATION_ERROR_PATH = new File(dir+"/src/test/resources/TestData/compareScrn");
File f = new File(dir+"/appium_screenshots/"+NameOfClass);
File folder = new File(dir+"/appium_screenshots");
try
{
if(folder.mkdir())
{
sysLogger("debug", "Appium_screenshots Directory Created for screenComparison Failures");
}
else
{
sysLogger("debug", "Appium_screenshots Directory is not created for screenComparison Failures");
}
} catch(Exception e)
{
e.printStackTrace();
}
try
{
if(f.mkdir())
{
sysLogger("debug", "Directory Created for screenComparison Failures");
}
else
{
sysLogger("debug", "Directory is not created for screenComparison Failures");
}
} catch(Exception e)
{
e.printStackTrace();
}
String baselineFilename = VALIDATION_PATH + "/" + NameOfClass+"_"+baseline +"_"+ checkName + ".png";
File baselineImg = new File(baselineFilename);
// If no baseline image exists for this check, we should create a baseline image
if (!baselineImg.exists()) {
sysLogger("debug", String.format("No baseline found for '%s' check; capturing baseline instead of checking", checkName));
File newBaseline = TestFlow.driver.getScreenshotAs(OutputType.FILE);
MobileElement element = (MobileElement) Helpers.find(locatorType, locator, 3, false);
BufferedImage newBase= Helpers.generateImage(element, newBaseline);
File outputfile = new File(baselineFilename);
ImageIO.write(newBase, "png", outputfile); // FileUtils.copyFile(newBase, new File(baselineFilename));
return;
}
// Otherwise, if we found a baseline, get the image similarity from Appium. In getting the similarity,
// we also turn on visualization so we can see what went wrong if something did.
SimilarityMatchingOptions opts = new SimilarityMatchingOptions();
opts.withEnabledVisualization();
File newBaseline = TestFlow.driver.getScreenshotAs(OutputType.FILE);
MobileElement element = (MobileElement) Helpers.find(locatorType, locator, 3, false);
BufferedImage newBase=Helpers.generateImage(element, newBaseline);
SimilarityMatchingResult res = TestFlow.driver.getImagesSimilarity(baselineImg, newBaseline, opts);
// If the similarity is not high enough, consider the check to have failed
if (res.getScore() < MATCH_THRESHOLD)
{
File failViz = new File(dir+"/appium_screenshots/"+NameOfClass+"/FAIL_" + NameOfClass + "_" + baseline +"_"+ checkName + ".png");
try {
res.storeVisualization(failViz);
} catch (ClassCastException e) {
e.printStackTrace();
}
TestFlow.lastScreenshotSaveDir=dir+"/appium_screenshots/"+NameOfClass+"/FAIL_" + NameOfClass + "_" +baseline +"_"+ checkName + ".png";
String abc= String.format("Visual check of '%s' failed; similarity match was only %f, and below the threshold of %f. Visualization written to %s.",
checkName, res.getScore(), MATCH_THRESHOLD, failViz.getAbsolutePath());
Assert.fail(abc);
}
// Otherwise, it passed!
sysLogger("debug", String.format("Visual check of '%s' passed; similarity match was %f",checkName, res.getScore()));
}
```
## Exception Stacktraces
`
java.lang.ClassCastException: com.google.common.collect.Maps$TransformedEntriesMap cannot be cast to java.lang.String
at io.appium.java_client.imagecomparison.ComparisonResult.getVisualization(ComparisonResult.java:63)
at io.appium.java_client.imagecomparison.ComparisonResult.storeVisualization(ComparisonResult.java:73)
at iOS_ross.helpers.ImageCompare.doVisualCheckByELement(ImageCompare.java:168)
at iOS_ross.Promotions_Test.promotion_multiplePictures_zoom(Promotions_Test.java:201)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:365)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:272)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:236)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:159)
at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:386)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:323)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:143)
`
## Link To Appium Logs
logs don't give any more informations
I assume this is expected with strict typing. Try to use https://github.com/appium/appium-xcuitest-driver#mobile-getcontexts instead to fetch extended contexts info
1 Like
jmj
June 27, 2022, 7:39am
4
in one of the comments, it says
In v2.0 this code has been moved to a separate plugin and the recent version of it should have the fix
Where can I find this plugin?
wreed
June 27, 2022, 2:58pm
5
I don’t know what plugin/where it is, but perhaps you should direct your question to the commenter, who happens to be a commenter in this thread too.
1 Like
buseco
January 11, 2023, 5:19pm
8
Removing this capability will solve it:
You’ll get a plain string without this. This capability will include more information for each context.