Unable to use iFrame parent to differentiate between identical objects in the page

Hello,

I have a web page with 3 checkboxes. The checkboxes look identical. The only difference are labels. So, when i try to verify a specific checkbox status, Katalon can’t recognize the checkbox. I don’t want to go with creating array of checkbox, since I want to keep script more general in case of more checkboxes are added in the future.

I tried to create an iFrame object and use it as a parent for a checkbox. However, Katalon does not recognize an object inside iFrame. I am wondering what did I do wrong.

This is how I identified the iFrame:

and the object:

//*[contains(@class, ‘checkbox__box’) and @ref_element = ‘Object Repository/Dashboard/MenuBuilder/ItemsAndModsPage/ItemsDetailsPage/InStock_iFrame’]

Both objects are uniquely identified with WebSpy and xpath extension.

This is the script:
// Frame
def res = false
if (GlobalVariable.DebugMode)
System.out.println(’****** res ’ + res)
res=WebUI.verifyElementPresent(findTestObject(‘Object Repository/Dashboard/MenuBuilder/ItemsAndModsPage/ItemsDetailsPage/InStock_iFrame’), 10)
if (GlobalVariable.DebugMode)
System.out.println('
* iFrame presented ’ + res)
res=false
res = WebUI.switchToFrame(findTestObject(‘Object Repository/Dashboard/MenuBuilder/ItemsAndModsPage/ItemsDetailsPage/InStock_iFrame’), 10, FailureHandling.STOP_ON_FAILURE)
if (GlobalVariable.DebugMode)
System.out.println('
* inside inStock iFrame ’ + res)
res = false
if (GlobalVariable.DebugMode)
System.out.println('
* res ’ + res)
res WebUI.verifyElementPresent(findTestObject(‘Object Repository/Dashboard/MenuBuilder/ItemsAndModsPage/ItemsDetailsPage/InStock_Chckbx’), 10, FailureHandling.OPTIONAL)
if (GlobalVariable.DebugMode)
System.out.println('
* InStock_Chckbx presented *****’ + res)

It looks like an iFrame object is presented, but I can’t switch to this iFrame. It returns the following error:

****** res *****false
****** iFrame presented *****true
****** res *****false
2021-06-16 10:44:41.507 ERROR c.k.k.core.keyword.internal.KeywordMain - :x: Unable to verify image ‘Object Repository/Dashboard/MenuBuilder/ItemsAndModsPage/ItemsDetailsPage/InStock_iFrame’ present (Root cause: com.kms.katalon.core.exception.StepFailedException: Unable to verify image ‘Object Repository/Dashboard/MenuBuilder/ItemsAndModsPage/ItemsDetailsPage/InStock_iFrame’ present
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.SwitchToFrameKeyword.switchToFrame(SwitchToFrameKeyword.groovy:84)
at com.kms.katalon.core.webui.keyword.builtin.SwitchToFrameKeyword.execute(SwitchToFrameKeyword.groovy:68)
at com.kms.katalon.core.keyword.internal.KeywordExecutor.executeKeywordForPlatform(KeywordExecutor.groovy:73)
at com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords.switchToFrame(WebUiBuiltInKeywords.groovy:2879)
at com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords$switchToFrame$11.call(Unknown Source)
at dashboard.menu.builder.AddItemOrModifier.AddNewItemOrModifier(AddItemOrModifier.groovy:156)
at dashboard.menu.builder.AddItemOrModifier.invokeMethod(AddItemOrModifier.groovy)
at com.kms.katalon.core.main.CustomKeywordDelegatingMetaClass.invokeStaticMethod(CustomKeywordDelegatingMetaClass.java:50)
at TC - AddNewItemWithKeyword.run(TC - AddNewItemWithKeyword:24)
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:398)
at com.kms.katalon.core.main.TestCaseExecutor.doExecute(TestCaseExecutor.java:389)
at com.kms.katalon.core.main.TestCaseExecutor.processExecutionPhase(TestCaseExecutor.java:368)
at com.kms.katalon.core.main.TestCaseExecutor.accessMainPhase(TestCaseExecutor.java:360)
at com.kms.katalon.core.main.TestCaseExecutor.execute(TestCaseExecutor.java:255)
at com.kms.katalon.core.main.TestSuiteExecutor.accessTestCaseMainPhase(TestSuiteExecutor.java:203)
at com.kms.katalon.core.main.TestSuiteExecutor.accessTestSuiteMainPhase(TestSuiteExecutor.java:152)
at com.kms.katalon.core.main.TestSuiteExecutor.execute(TestSuiteExecutor.java:95)
at com.kms.katalon.core.main.TestCaseMain.startTestSuite(TestCaseMain.java:157)
at com.kms.katalon.core.main.TestCaseMain$startTestSuite$0.call(Unknown Source)
at TempTestSuite1623858245486.run(TempTestSuite1623858245486.groovy:39)
Caused by: org.openqa.selenium.NoSuchFrameException: no such frame: element is not a frame
(Session info: chrome=91.0.4472.101)

If I will comment switchToFrameout, i still can’t see the ckeckbox object:

2021-06-16 10:53:01.032 WARN c.k.k.core.keyword.internal.KeywordMain - Unable to verify object ‘Object Repository/Dashboard/MenuBuilder/ItemsAndModsPage/ItemsDetailsPage/InStock_Chckbx’ is present (Root cause: com.kms.katalon.core.exception.StepFailedException: Unable to verify object ‘Object Repository/Dashboard/MenuBuilder/ItemsAndModsPage/ItemsDetailsPage/InStock_Chckbx’ is present
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.VerifyElementPresentKeyword.verifyElementPresent(VerifyElementPresentKeyword.groovy:92)
at com.kms.katalon.core.webui.keyword.builtin.VerifyElementPresentKeyword.execute(VerifyElementPresentKeyword.groovy:68)
at com.kms.katalon.core.keyword.internal.KeywordExecutor.executeKeywordForPlatform(KeywordExecutor.groovy:73)
at com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords.verifyElementPresent(WebUiBuiltInKeywords.groovy:1447)
at com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords$verifyElementPresent$8.call(Unknown Source)
at dashboard.menu.builder.AddItemOrModifier.AddNewItemOrModifier(AddItemOrModifier.groovy:162)
at dashboard.menu.builder.AddItemOrModifier.invokeMethod(AddItemOrModifier.groovy)
at com.kms.katalon.core.main.CustomKeywordDelegatingMetaClass.invokeStaticMethod(CustomKeywordDelegatingMetaClass.java:50)
at TC - AddNewItemWithKeyword.run(TC - AddNewItemWithKeyword:24)
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:398)
at com.kms.katalon.core.main.TestCaseExecutor.doExecute(TestCaseExecutor.java:389)
at com.kms.katalon.core.main.TestCaseExecutor.processExecutionPhase(TestCaseExecutor.java:368)
at com.kms.katalon.core.main.TestCaseExecutor.accessMainPhase(TestCaseExecutor.java:360)
at com.kms.katalon.core.main.TestCaseExecutor.execute(TestCaseExecutor.java:255)
at com.kms.katalon.core.main.TestSuiteExecutor.accessTestCaseMainPhase(TestSuiteExecutor.java:203)
at com.kms.katalon.core.main.TestSuiteExecutor.accessTestSuiteMainPhase(TestSuiteExecutor.java:152)
at com.kms.katalon.core.main.TestSuiteExecutor.execute(TestSuiteExecutor.java:95)
at com.kms.katalon.core.main.TestCaseMain.startTestSuite(TestCaseMain.java:157)
at com.kms.katalon.core.main.TestCaseMain$startTestSuite$0.call(Unknown Source)
at TempTestSuite1623858750407.run(TempTestSuite1623858750407.groovy:39)
Caused by: org.openqa.selenium.NoSuchFrameException: no such frame: element is not a frame
(Session info: chrome=91.0.4472.101)

Possibly you do not need iframe stuff at all.

Please go back to your initial question.

I suppose you can solve this problem by writing a bit sophisticated XPath using axis: preceding-sibling::, following-sibling::, parent::, etc.

Let us see

  1. the HTML source where we can see the 3 checkboxes look like.
  2. the TestObject definition (especially XPath) you tried to identified the 3 checkboxes.
  3. the Test Case script source.

@kazurayam Thank you for taking time to help me with this.

This is how checkboxes looks in html:

<div class="container checkbox-container" style="">
	<label class="checkbox  checkbox--checked  " style="">
		<span class="checkbox__box" style="">
			<i class="icon-dashboard-icons_checkmark" style=""></i>
		</span>
		<span class="checkbox__label" style="">In Stock</span>
		<input type="checkbox" checked="" style="">
	</label>
</div>

<div class="container checkbox-container" style="">
	<label class="checkbox    " style="">
		<span class="checkbox__box" style="">
			<i class="icon-dashboard-icons_checkmark" style=""></i>
		</span>
		<span class="checkbox__label" style="">Add to popular item list</span><input type="checkbox" style="">
	</label>
</div>

The only different in the code is checkbox__label.
The checkboxes look absolutely the same in the code:

As well checked checkbox looks different than unchecked checkbox:

I tried to use different XPaths, but none of the XPaths I’ve got allowed me to verify the status of a specific checkbox or to click the object. I am very new in XPaths and Katalon, so I might did it wrong.

Currently, I have 3 objects for each checkbox, one for unchecked checkbox, another one for checked checkbox, and the 3rd one for label to click on a checkbox object .

This is how I identified them:
Checked In Stock checkbox:
//label[@class ="checkbox checkbox--checked "] | //*[@class='checkbox__label'] //*[text()="In Stock"]

Unchecked In Stock checkbox:
//label[@class='checkbox ']//span[@class='checkbox__label'][contains(text(), 'In Stock')]

Label:
//*[(text() = 'In Stock' or . = 'In Stock') and @class = 'checkbox__label']

This is the keyword to verify if checkbox is checked or not:

public class Checkboxes {
	@Keyword
	public boolean IsSelected (String checked_relativeID, String unchecked_relativeID) {
		boolean checkbox_status = false

		// Verify if 'checked' element is presented
		checkbox_status = WebUI.verifyElementPresent(findTestObject(checked_relativeID), 10, FailureHandling.OPTIONAL)

		if (checkbox_status)
			return  checkbox_status

		// Verify if 'unchecked' element is presented
		checkbox_status = WebUI.verifyElementPresent(findTestObject(unchecked_relativeID), 10, FailureHandling.STOP_ON_FAILURE)
		if (checkbox_status)
			// Unchecked element is presented. We need ot return false
			return  (!checkbox_status)
               
               return null
	}
}

The test script:

// Stock Status. If StockStaus is NA, manually setting is not allowed
if (NewItemData.getValue('StockStatus', index) != "NA")
{
	// Check current status of the Stock Status checkbox
	stock_status = (new dashboard.DashboardGeneral.Checkboxes()).IsSelected( 
'Dashboard/MenuBuilder/ItemsAndModsPage/ItemsDetailsPage/InStock_Status_ChckBx_Checked', 'Dashboard/MenuBuilder/ItemsAndModsPage/ItemsDetailsPage/InStock_Status_ChckBx_Unchecked')

	if (((!stock_status) && (NewItemData.getValue('StockStatus', index) == "On")) ||
	(stock_status && (NewItemData.getValue('StockStatus', index) == "Off"))){
	// We need to click on In Stock Check box
        WebUI.click(findTestObject( 
         'Dashboard/MenuBuilder/ItemsAndModsPage/ItemsDetailsPage/inStock_Label'))
	}
}

Sorry for so long post

Could you save the HTML source code from browser to file, and share the file here?

Or even better, please save the page into MHTML and share it. See the following how to.

@ipotashnik

Your long post contains many code fragments. The code fragments should be formatted for better readability. I would like to see the code in a fixed width font, without any escaping.

So please do the following:

In the original post you wrote:

but in the screenshots you provided, I found only 2 checkboxes. One is labeled with In Stock. Another is labeled with Add to popular item list. What is the 3rd one? I can not find it.

Thank you so much for a lot of valuable information. I was looking for a way to make script code more readable. I got the plugin for MHTML, but it will take some time to understand how to save it as MHTML.

There are 3 checkboxes in one of the screenshots. The 3rd one is Alcohol. If I learn how to distinguish between 2 checkboxes, I will know how to do the same for the 3rd checkbox.

So, for now I have only html file for this page.

dashboard-checkboxes.html (59.0 KB)

For some reason I can’t upload text file. :frowning:

Update:

I was able to uniquely locate each checkbox in the page using axis in the XPath. This knowledge for sure will make my life easier.

Katalon is able to click on an object, yet still not able to verify if the object is checked or unchecked. As I understand it’s a known issue with REACT. Luckily, verify attributes works.

@kazurayam, thank you so much for your help.

Hi , maybe you can try this xpaths :
//[text()=‘In Stock’]/preceding-sibling::span
//
[text()=‘Add to popular item list’]/preceding-sibling::span

I would suggest to learn more about identifying elements with xpaths here: https://www.guru99.com/xpath-selenium.html

@ipotashnik

Thank you for sharing the HTML.

I have made a new Katalon Studio project, I saved the HTML into the <projectDir>/dashboard-checkboxes.html; and I made a sample Test Case as follows:

import java.nio.file.Path
import java.nio.file.Paths

import com.kms.katalon.core.configuration.RunConfiguration
import com.kms.katalon.core.model.FailureHandling
import com.kms.katalon.core.testobject.ConditionType
import com.kms.katalon.core.testobject.TestObject
import com.kms.katalon.core.util.KeywordUtil
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI

Path projectDir = Paths.get(RunConfiguration.getProjectDir())
Path html = projectDir.resolve('dashboard-checkboxes.html')
URL url = html.toFile().toURI().toURL()

WebUI.openBrowser('')
WebUI.navigateToUrl(url.toString())

/*
 * Let's check if the checkbox "In Stock" is checked. If not, this test will fail.
 * 
 * <div class="container checkbox-container" style="">
 *   <label class="checkbox  checkbox--checked  " style="">
 *     <span class="checkbox__box" style="">
 *       <i class="icon-dashboard-icons_checkmark" style=""></i>
 *     </span>
 *     <span class="checkbox__label" style="">In Stock</span>
 *     <input type="checkbox" checked="" style="">
 *   </label>
 * </div>
 */
TestObject input_In_Stock = createTestObject('//span[text()="In Stock"]//following-sibling::input')
WebUI.verifyElementChecked(input_In_Stock, 3)

/*
 * Let's check if the checkbox "Contains Alcohol" is NOT checked. If is checked, this test will fails.
 *
 * <div class="container checkbox-container" style="">
 *   <label class="checkbox  checkbox--checked  " style="">
 *     <span class="checkbox__box" style="">
 *       <i class="icon-dashboard-icons_checkmark" style=""></i>
 *     </span>
 *     <span class="checkbox__label" style="">Contails Alcohol</span>
 *     <input type="checkbox" style="">
 *   </label>
 * </div>
 */
TestObject input_Contains_Alcohol = createTestObject('//span[text()="Contains Alcohol"]//following-sibling::input')
WebUI.verifyElementNotChecked(input_Contains_Alcohol, 3)

WebUI.closeBrowser()

/**
 * utility to create an instance of TestObject with XPath
 * @param xpath
 * @return
 */
TestObject createTestObject(String xpath) {
	TestObject tObj = new TestObject(xpath)
	tObj.addProperty("xpath", ConditionType.EQUALS, xpath)
	return tObj
}

This Test Case does: when the page has been loaded,

  1. check if the checkbox “In Stock” is checked. If it is not, the test will fail.
  2. check if the checkbox “Contains Alcohol” is NOT checked. If it is checked, the test will fail.

Please read the source and find something.

I don’t know how the checked attribute becomes when a user manually toggles it off/on after the initial page loading. Please find it yourself.

Recent version of Chrome browser supports saving pages into MTHML natively. You do not need any plugin.

@francorebu

This code doesn’t look valid as XPath at all.

I know you meant:

//*[text()='In Stock']/preceding-sibling::span
//*[text()='Add to popular item list']/preceding-sibling::span

It is unfortunate that you failed to express yourself correctly. Please enclose your codes in a pair of triple backticks for better readability.

1 Like