Visual Testing, cannot take screenshot, Double cannot be cast to java.lang.Long

When trying to take a screenshot as a checkpoint I’m getting an error, it worked on the first run and I managed to save the screenshot in the Baseline Collection in Analytics. Now each time I run the same test suite it just fails on this step:

WebUI.takeScreenshotAsCheckpoint('test image')

Here is the error I’m getting

=============== ROOT CAUSE =====================
Caused by: java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Long

For trouble shooting, please visit: https://docs.katalon.com/katalon-studio/docs/troubleshooting.html
================================================

01-11-2023 11:52:20 AM takeScreenshotAsCheckpoint("test image")

Elapsed time: 0,664s

Cannot take screenshot (Root cause: com.kms.katalon.core.exception.StepFailedException: Cannot take screenshot
	at com.kms.katalon.core.webui.keyword.internal.WebUIKeywordMain.stepFailed(WebUIKeywordMain.groovy:64)
	at com.kms.katalon.core.webui.keyword.internal.WebUIKeywordMain.runKeyword(WebUIKeywordMain.groovy:26)
	at com.kms.katalon.core.webui.keyword.builtin.TakeScreenshotKeyword.takeScreenshot(TakeScreenshotKeyword.groovy:126)
	at com.kms.katalon.core.webui.keyword.builtin.TakeScreenshotKeyword.execute(TakeScreenshotKeyword.groovy:84)
	at com.kms.katalon.core.keyword.internal.KeywordExecutor.executeKeywordForPlatform(KeywordExecutor.groovy:74)
	at com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords.takeScreenshotAsCheckpoint(WebUiBuiltInKeywords.groovy:3093)
	at com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords$takeScreenshotAsCheckpoint$9.call(Unknown Source)
	at FX Forwards - Compare dealers Q1 2020- Q2 2020.run(FX Forwards - Compare dealers Q1 2020- Q2 2020:95)
	at com.kms.katalon.core.main.ScriptEngine.run(ScriptEngine.java:194)
	at com.kms.katalon.core.main.ScriptEngine.runScriptAsRawText(ScriptEngine.java:119)
	at com.kms.katalon.core.main.TestCaseExecutor.runScript(TestCaseExecutor.java:448)
	at com.kms.katalon.core.main.TestCaseExecutor.doExecute(TestCaseExecutor.java:439)
	at com.kms.katalon.core.main.TestCaseExecutor.processExecutionPhase(TestCaseExecutor.java:418)
	at com.kms.katalon.core.main.TestCaseExecutor.accessMainPhase(TestCaseExecutor.java:410)
	at com.kms.katalon.core.main.TestCaseExecutor.execute(TestCaseExecutor.java:285)
	at com.kms.katalon.core.common.CommonExecutor.accessTestCaseMainPhase(CommonExecutor.java:65)
	at com.kms.katalon.core.main.TestSuiteExecutor.accessTestSuiteMainPhase(TestSuiteExecutor.java:151)
	at com.kms.katalon.core.main.TestSuiteExecutor.execute(TestSuiteExecutor.java:106)
	at com.kms.katalon.core.main.TestCaseMain.startTestSuite(TestCaseMain.java:185)
	at com.kms.katalon.core.main.TestCaseMain$startTestSuite$0.call(Unknown Source)
	at TempTestSuite1673434245975.run(TempTestSuite1673434245975.groovy:36)
Caused by: java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Long

Hi,

This issue is quite strange. Let me investigate to see if can help

Which version of Katalon Studio are you using?

Please show the log that follows this line.

Please show the code of your test case “FX Forwards - Compare dealers Q1 2020- Q2 2020” around line#95

The version I am using is the latest 8.5.5

Some more log about the error:

Caused by: java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Long
	at com.kms.katalon.core.webui.util.FileUtil.getScrollY(FileUtil.java:355)
	at com.kms.katalon.core.webui.util.FileUtil.takesScreenshot(FileUtil.java:68)
	at com.kms.katalon.core.webui.keyword.builtin.TakeScreenshotKeyword$_takeScreenshot_closure1.doCall(TakeScreenshotKeyword.groovy:127)
	at com.kms.katalon.core.webui.keyword.builtin.TakeScreenshotKeyword$_takeScreenshot_closure1.call(TakeScreenshotKeyword.groovy)
	at com.kms.katalon.core.webui.keyword.internal.WebUIKeywordMain.runKeyword(WebUIKeywordMain.groovy:20)
	at com.kms.katalon.core.webui.keyword.builtin.TakeScreenshotKeyword.takeScreenshot(TakeScreenshotKeyword.groovy:126)
	at com.kms.katalon.core.webui.keyword.builtin.TakeScreenshotKeyword.execute(TakeScreenshotKeyword.groovy:84)
	at com.kms.katalon.core.keyword.internal.KeywordExecutor.executeKeywordForPlatform(KeywordExecutor.groovy:74)
	at com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords.takeScreenshotAsCheckpoint(WebUiBuiltInKeywords.groovy:3093)
	at com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords$takeScreenshotAsCheckpoint$10.call(Unknown Source)
	at Script1666484051934.run(Script1666484051934.groovy:107)
	... 13 more
)

Here is a code around line #95 of the test case

WebUI.verifyElementPresent(findTestObject('Object Repository/Page_/jpeg54'), 
    0)

WebUI.scrollToElement(findTestObject('Object Repository/Page_/select_All sizes'), 
    0, FailureHandling.STOP_ON_FAILURE)

WebUI.callTestCase(findTestCase('Set viewport size'), [:], FailureHandling.STOP_ON_FAILURE)

WebUI.takeScreenshotAsCheckpoint('test image')

The funny thing that I noticed now is that when I run the test suite and Katalon retries running this test case again it always passes on the second try.

Thank you for providing more info.

Caused by: java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Long
	at com.kms.katalon.core.webui.util.FileUtil.getScrollY(FileUtil.java:355)

I wanted to read the source of com.kms.katalon.core.webui.util.FileUtil.getScrollY, so I visited the GitHub repository at https://github.com/katalon-studio/katalon-studio-testing-framework/blob/master/Include/scripts/groovy/com/kms/katalon/core/webui/util/FileUtil.java.
I looked at the Line#355 and around:

355         return (Long) ((JavascriptExecutor) driver)
                    .executeScript("return (window.pageYOffset !== undefined)\n" + "  ? window.pageYOffset\n"
                            + "  : (document.documentElement || document.body.parentNode || document.body).scrollTop;");

Yes, the line#355 is explicitly casting something to the the type java.lang.Long.

On the other hand, the message said “java.lang.Double cannot be cast to java.lang.Long”. Is the value of type Double?

I checked the doc of JavaScript window object: Window: pageYOffset property - Web APIs | MDN, which wrotes:

Value
A double-precision floating-point number specifying the number of pixels the Document is scrolled vertically within its containing Window.

Well, the message seems telling us a fact that the line#355 of com.kms.katalon.core.webui.util.FileUtil.getScrollY is buggy. It should not carelessly cast a Double value to Long.

I think we need someone in Katalon team to look at this issue. @vu.tran

I personally have ever encountered a similar problem. My test case called:

((JavascriptExecutor)driver).executeScrpipt("return window.devicePixcelRatio")

it sometimes returned a value of java.lang.Double to my Test Case script; but in other situation returned a value of type java.lang.Long. I was confused with this finding. I guess that, if the value returned by window.xxxxxx returns a double-precesion floating-point number with non-zero under the decimal point (e.g, 1.75), then the value is returned as a Double value, but when the source number has all-zero under the decimal point (e.g, 2.0), then the value is returned as a Long value: e.g, 2L.


JavaScript has Number type; JavaScript does not have Double and Long (these are Java types). The Number type of JavaScript can be either of an integer or floating point value.

According to the Javadoc, JavascriptExecutor#executeScript() method returns java.lang.Object, which could be in fact any type. As @wolczoskar reported, the message

Caused by: java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Long

proves that JavascriptExecutor actually returned a value of java.lang.Double.

So, the implementation of com.kms.katalon.core.webui.util.FileUtil.getScrollY should be more defensive. It should convert the value returned by ((JavascriptExecutor)driver).executeScript(...) to Long more carefully; for example:

def val = ((JavascriptExecutor)driver).executeScript(...)
if (val instaceof Long) {
    return val;
} else if (val instanceof Double) {
   return Double.valueOf(val).longValue();
}
...