Optional variables Map Value

Hi Fellas,
I made a validation (in a testcase) and it received parameters from another testcase.
Attached some screenshot.

My question is :
How do I make some map value or variables to be optional?
or set a default value maybe?

I already tried to pass only selected map and katalon raise an error (have to pass the whole variables).
So, I made a tricky way to pass 0 (zero) in order to eliminate the error.

But, this way is not practical since another validation would be added later and I had to update the all TC which using this validation.

Looking forward for the solution… Thanks!

I’m not sure if the below is what you were thinking of, however, you can give parameters a “default” value. Start your parameters with those that do not have “default” and then have the “default” ones afterwards.

You want Groovy’s “Elvis operator”.

https://groovy-lang.org/operators.html#_elvis_operator

String postingNumberFrom = $npostingNumberFrom ?: "default value"

Please mind that you should not enclose the $npostingNumberFrom with double quotes, like

String postingNumberFrom = "$npostingNumberFrom" ?: "default value"

which will fall into a zero-length string "" rather than "default value".

Hi. Thank you for replying.
Unfortunately, this is not what I want to achieve.

Hi, Thank you for replying.
Sounds promising actually. I remove the zero value from map value and apply your suggestion. But here’s what I’ve got :

Its like forcing me to input the map value. Do you know why this happen?

How do you think you declare the variable nGLAccountNumber? Please describe your idea.

Sorry I did not catch your question. Could you please elaborate more?
I already tried to use single quote and double quote

You showed a screenshot of you test case in Manual mode, but most portion of the image is scratched unreadable. So I do not understand how a variable nGLAccountNumber is declared. Please show the source code copy and pasted from Script mode.

Please use the Code Formatting syntax in the forum post

I do not understand why you prepend a $ before a variable reference nGLAccountNumber.

String GLAccountNumber = $nGLAccountNumber ?: '0';

What do you mean by $?

How about this?

String GLAccountNumber = nGLAccountNumber ?: '0';

As I mention before, I passed some map value when I called this validation test case

From my knowledge, $ is needed in order to retrieve thrown map value.
Am I wrong? Please let me know if I made a mistakes

How about this?

String GLAccountNumber = nGLAccountNumber ?: '0';

$dictionary is PHP syntax.

No, we do not use PHP in Katalon Studio. Katalon Studio uses Groovy language.

I already try your suggestion, and remove the map value.
It failed as shown below :

the process stop before line 33. So, the declaration on line 32 is the issue.

Is there another way around to make this optional?

Please read the whole error log carefully. There must be a line “Caused by …” which tells you why you got errror.

Here is the log

=============== ROOT CAUSE =====================


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

04-01-2022 05:18:56 PM maxRowItem = (nmaxRowItem) ? nmaxRowItem : 5

Elapsed time: 0.012s

Test Cases/Scenario/SINC-12845 - As a Cashier, View n Maintain GL Line Account/mod/verify GL Line Data Result 2 FAILED.
Reason:
groovy.lang.MissingPropertyException: No such property: nmaxRowItem for class: Script1648795974575
	at verify GL Line Data Result 2.run(verify GL Line Data Result 2:32)
	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:442)
	at com.kms.katalon.core.main.TestCaseExecutor.doExecute(TestCaseExecutor.java:433)
	at com.kms.katalon.core.main.TestCaseExecutor.processExecutionPhase(TestCaseExecutor.java:412)
	at com.kms.katalon.core.main.TestCaseExecutor.accessMainPhase(TestCaseExecutor.java:404)
	at com.kms.katalon.core.main.TestCaseExecutor.execute(TestCaseExecutor.java:281)
	at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:142)
	at com.kms.katalon.core.keyword.builtin.CallTestCaseKeyword$_callTestCase_closure1.doCall(CallTestCaseKeyword.groovy:59)
	at com.kms.katalon.core.keyword.builtin.CallTestCaseKeyword$_callTestCase_closure1.call(CallTestCaseKeyword.groovy)
	at com.kms.katalon.core.keyword.internal.KeywordMain.runKeyword(KeywordMain.groovy:74)
	at com.kms.katalon.core.keyword.builtin.CallTestCaseKeyword.callTestCase(CallTestCaseKeyword.groovy:81)
	at com.kms.katalon.core.keyword.builtin.CallTestCaseKeyword.execute(CallTestCaseKeyword.groovy:44)
	at com.kms.katalon.core.keyword.internal.KeywordExecutor.executeKeywordForPlatform(KeywordExecutor.groovy:74)
	at com.kms.katalon.core.keyword.BuiltinKeywords.callTestCase(BuiltinKeywords.groovy:334)
	at TCMSTAR-14387 - As a Cashier, limit Max Item Row only show 10 row result.run(TCMSTAR-14387 - As a Cashier, limit Max Item Row only show 10 row result:60)
	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:442)
	at com.kms.katalon.core.main.TestCaseExecutor.doExecute(TestCaseExecutor.java:433)
	at com.kms.katalon.core.main.TestCaseExecutor.processExecutionPhase(TestCaseExecutor.java:412)
	at com.kms.katalon.core.main.TestCaseExecutor.accessMainPhase(TestCaseExecutor.java:404)
	at com.kms.katalon.core.main.TestCaseExecutor.execute(TestCaseExecutor.java:281)
	at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:142)
	at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:133)
	at com.kms.katalon.core.main.TestCaseMain$runTestCase$0.call(Unknown Source)
	at TempTestCase1648808268233.run(TempTestCase1648808268233.groovy:25)

You have at least 2 Test Case script. One is the “caller”, another is the “callee”.
You showed the source code of the “callee”, but you haven’t showed us the source of the “caller”.
I need to see how your script is calling WebUI.callTestCase() keyword.
Please show the Groovy source code of the “caller” test case by copy & pasting from the Script mode; not a screenshot of Manual mode display.

@yuri.barru If i understand it right, your testcase variable is actually a map named ‘binding’ which may have or not have some elements.

So, in your code you have to refer to them either by using map[key] or use get().

See here some examples, with or without defaults:
https://blog.mrhaki.com/2009/11/groovy-goodness-get-value-from-map-or.html#:~:text=The%20get()%20method%20in,no%20value%20for%20the%20key.

something like this perhaps:

GLAccountNumber = binding.get(nGLAccountNumber, '0')

here is the result.


Honestly, I did not understand why this happen. What do you think?

Here is the caller

import static com.kms.katalon.core.checkpoint.CheckpointFactory.findCheckpoint
import static com.kms.katalon.core.testcase.TestCaseFactory.findTestCase
import static com.kms.katalon.core.testdata.TestDataFactory.findTestData
import static com.kms.katalon.core.testobject.ObjectRepository.findTestObject
import static com.kms.katalon.core.testobject.ObjectRepository.findWindowsObject
import com.kms.katalon.core.checkpoint.Checkpoint as Checkpoint
import com.kms.katalon.core.cucumber.keyword.CucumberBuiltinKeywords as CucumberKW
import com.kms.katalon.core.mobile.keyword.MobileBuiltInKeywords as Mobile
import com.kms.katalon.core.model.FailureHandling as FailureHandling
import com.kms.katalon.core.testcase.TestCase as TestCase
import com.kms.katalon.core.testdata.TestData as TestData
import com.kms.katalon.core.testng.keyword.TestNGBuiltinKeywords as TestNGKW
import com.kms.katalon.core.testobject.TestObject as TestObject
import com.kms.katalon.core.webservice.keyword.WSBuiltInKeywords as WS
import com.kms.katalon.core.webui.common.WebUiCommonHelper as Helper
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
import com.kms.katalon.core.windows.keyword.WindowsBuiltinKeywords as Windows
import internal.GlobalVariable as GlobalVariable
import org.openqa.selenium.Keys as Keys
import org.openqa.selenium.WebElement as WebElement
import com.kms.katalon.core.util.KeywordUtil as KeywordUtil

WebUI.callTestCase(findTestCase('Scenario/SINC-11865 - As a Cashier, use the Advanced Search filter/TCMSTAR-14128 - As a Cashier, click Advanced Search button'), 
    [:], FailureHandling.STOP_ON_FAILURE)

WebUI.callTestCase(findTestCase('Scenario/SINC-11865 - As a Cashier, use the Advanced Search filter/mod/tickDebitCredit'), 
    [('nKeyword') : 'DebitCredit'], FailureHandling.STOP_ON_FAILURE)

WebUI.click(findTestObject('Sider/Sider Inc Payment Menu/Inc - MR - Mon GL Line Item/btn Advanced Search modal/button Terapkan Filter enabled'))

WebUI.click(findTestObject('Sider/Sider Inc Payment Menu/Inc - MR - Mon GL Line Item/input Max Row Item'))

WebUI.setText(findTestObject('Sider/Sider Inc Payment Menu/Inc - MR - Mon GL Line Item/input Max Row Item'), '10')

WebUI.sendKeys(findTestObject('Sider/Sider Inc Payment Menu/Inc - MR - Mon GL Line Item/input Max Row Item'), Keys.chord(
        Keys.ENTER))

String el = 'return document.querySelector("input[name=\'maxRowItem\']").value;'

String result = WebUI.executeJavaScript(el, null, FailureHandling.OPTIONAL)

System.out.println(result)

if (!(result.equals('10'))) {
    KeywordUtil.logInfo('Field input \'Max Row Item\' gagal diisi')

    KeywordUtil.markFailedAndStop('Field input \'Max Row Item\' gagal diisi')
} else {
    KeywordUtil.markPassed('Field \'Max Row Item\' berhasil diisi')
}

WebUI.click(findTestObject('Sider/Sider Inc Payment Menu/Inc - MR - Mon GL Line Item/button Show Result Enable'))

WebUI.verifyElementNotPresent(findTestObject('Sider/Sider Inc Payment Menu/Inc - MR - Mon GL Line Item/btn Show Result/div no data'), 
    5)

WebUI.verifyElementNotPresent(findTestObject('Sider/Sider Inc Payment Menu/Inc - MR - Mon GL Line Item/btn Show Result/btn next page disabled'), 
    5)

WebUI.callTestCase(findTestCase('Scenario/SINC-12845 - As a Cashier, View n Maintain GL Line Account/mod/verify GL Line Data Result - Max Row Item'), 
    [('nmaxRowItem') : '10'], FailureHandling.STOP_ON_FAILURE)

and the callee :

import static com.kms.katalon.core.checkpoint.CheckpointFactory.findCheckpoint
import static com.kms.katalon.core.testcase.TestCaseFactory.findTestCase
import static com.kms.katalon.core.testdata.TestDataFactory.findTestData
import static com.kms.katalon.core.testobject.ObjectRepository.findTestObject
import static com.kms.katalon.core.testobject.ObjectRepository.findWindowsObject

import java.time.LocalDate
import java.time.format.DateTimeFormatter

import com.github.kklisura.cdt.protocol.types.runtime.Evaluate as Evaluate
import com.kms.katalon.core.checkpoint.Checkpoint as Checkpoint
import com.kms.katalon.core.cucumber.keyword.CucumberBuiltinKeywords as CucumberKW
import com.kms.katalon.core.mobile.keyword.MobileBuiltInKeywords as Mobile
import com.kms.katalon.core.model.FailureHandling as FailureHandling
import com.kms.katalon.core.testcase.TestCase as TestCase
import com.kms.katalon.core.testdata.TestData as TestData
import com.kms.katalon.core.testng.keyword.TestNGBuiltinKeywords as TestNGKW
import com.kms.katalon.core.testobject.TestObject as TestObject
import com.kms.katalon.core.util.KeywordUtil as KeywordUtil
import com.kms.katalon.core.webservice.keyword.WSBuiltInKeywords as WS
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
import com.kms.katalon.core.windows.keyword.WindowsBuiltinKeywords as Windows
import internal.GlobalVariable as GlobalVariable
import org.openqa.selenium.Keys as Keys
import org.openqa.selenium.By as By
import org.openqa.selenium.WebElement as WebElement
import com.kms.katalon.core.testobject.ConditionType as ConditionType

WebUI.verifyElementNotPresent(findTestObject('Sider/Sider Inc Payment Menu/Inc - MR - Mon GL Line Item/btn Show Result/span dot spinning_fetching data'),
	GlobalVariable.waitPresentTimeout)

String maxRowItem = nmaxRowItem ?: '5'

/*
println(binding.nmaxRowItem) //printed 10 on console
//def binding2 = binding
maxRowItem = binding.get(nmaxRowItem, '10')
*/

//count table rows, can be reuse
//count table rows, can be reuse
//count table rows, can be reuse
TestObject selectorContentGLTable = new TestObject()
selectorContentGLTable.addProperty('xpath', ConditionType.EQUALS, '//table//tbody/tr')

// find the row header of result table elements
List<WebElement> selectorContentGLTableList = WebUI.findWebElements(selectorContentGLTable, 30)

println(selectorContentGLTableList.size())

public static void maxRowItemValidation(String paramMaxRowItem, List<WebElement> paramSelectorContentGLTableList) {
	
	Integer row_counter = 0
	Boolean checkPreviousPage = false
	Boolean checkNextPage = false
	
	try {
		checkPreviousPage = WebUI.verifyElementVisible(findTestObject('Sider/Sider Inc Payment Menu/Inc - MR - Mon GL Line Item/btn Show Result/btn previous page enabled'))
	} catch (Exception e) {
		checkPreviousPage = false
	}
	
	//if not the first page, system will click previous until the first one
	while (checkPreviousPage.equals(true)) {

//		String el = 'return document.querySelector("//li[contains(@class, \'ant-pagination-next\')]/button[@class=\'ant-pagination-item-link\']")[0].click();'
//		WebUI.executeJavaScript(el, null, FailureHandling.OPTIONAL)
		WebUI.click(findTestObject('Sider/Sider Inc Payment Menu/Inc - MR - Mon GL Line Item/btn Show Result/btn previous page enabled'))
		
		try {
			checkPreviousPage = WebUI.verifyElementVisible(findTestObject('Sider/Sider Inc Payment Menu/Inc - MR - Mon GL Line Item/btn Show Result/btn previous page enabled'))
		} catch (Exception e) {
			checkPreviousPage = false
		}
	}
	
	row_counter = row_counter + paramSelectorContentGLTableList.size()
	
	
	try {
		checkNextPage = WebUI.verifyElementVisible(findTestObject('Sider/Sider Inc Payment Menu/Inc - MR - Mon GL Line Item/btn Show Result/btn next page enabled'))
	} catch (Exception e) {
		checkNextPage = false
	}
	
	//if button next enable
	while (checkNextPage.equals(true)) {		
		WebUI.click(findTestObject('Sider/Sider Inc Payment Menu/Inc - MR - Mon GL Line Item/btn Show Result/btn next page enabled'))
		
		try {
			checkNextPage = WebUI.verifyElementVisible(findTestObject('Sider/Sider Inc Payment Menu/Inc - MR - Mon GL Line Item/btn Show Result/btn next page enabled'))
		} catch (Exception e) {
			checkNextPage = false
		}
		row_counter = row_counter + paramSelectorContentGLTableList.size()
		
		println(row_counter)
	}
	
	if (row_counter - 1 > Integer.parseInt(paramMaxRowItem)) {
		KeywordUtil.markFailedAndStop('Max Row Item Count Validation : Expected Result and rendered table head are NOT equal')
	} else {
		KeywordUtil.markPassed('Max Row Item Validation : Expected Result and rendered table head are equal')
	}
}

if (!maxRowItem.equals('0')) {
	maxRowItemValidation(maxRowItem, selectorContentGLTableList)
}