Can't get value from field

Hi guys! I came across another issue. When I try to get the text from this field, it returns nothing.
Result returns nothing in the example below. Any ideas/comments? Note that I cannot use getAttribute since I do not have a value attribute for that object.Thanks.

String result = WebUI.getText(findTestObject(‘Object Id’))

image

@mgrandillo It’s never a good idea to change to a new question/topic without creating a New Topic - :slight_smile: - make sense?

I’ll move this…

I’ll need to see the HTML behind that element. Make sure you provide enough of it from ABOVE the element.

A screenshot from DevTools is fine.

@Russ_Thomas let me know if the snapshot below is sufficient, thanks!

<input data-bind="value: xxxx">

This code snippet reminds me of a JavaScript framework Knockout.js or jQuery.

Do you use Knockout.js?

You may not believe it, but try this:

String result = WebUI.getAttribute(findTestObject('Object Id'), 'value')
println result

You will see WPD0H8E in the console message.

Puzzled?

In your HTML source code, of course, you did not type a value attribute. But JavaScript framework on the page — jQuery or Knockout — dynamically creates the value attribute in the DOM. The attribute is invisible even in the Chrome DevTools view, but is actually there runtime. So you can retrieve the value attribute by WebUI.getAttribute(TestObject, 'value').

That’s because the attribute does not exist, period.

WebUI, and Selenium, and DevTools, will retrieve the value property.

Definitive test - try this for any similar element in the browser console:

document.querySelector("#element-id").getAttribute("value")

There’s one like it on this page:

But the value property always exists:

Still I have a question. Please be kind enough to let me talk about it here.

I have made a GitHub project to study this topic.

The Test Case TC1 opens a local HTML file in browser. The HTML file uses Knockout.js.

Here is the demo video of TC1

The TC1 has a fragment like this:

WebUI.openBrowser('')
WebUI.setViewPortSize(800, 600)
WebUI.navigateToUrl(url)
WebUI.delay(1)

// TestObject that points the <input id="nm"> field
TestObject nmTObj = new TestObject("nm").addProperty("css", ConditionType.EQUALS, "#nm")

// try to get the prepopulated value in the <input id="nm"> filed
println "nmValue=${WebUI.getAttribute(nmTObj, 'value')}"

I expected to see when I run TC1:

nmValue=null

But in fact, to my surprise, I got

2021-02-09 17:00:30.940 DEBUG testcase.TC1  - 8: println(nmValue=$WebUI.getAttribute(nmTObj, value))
nmValue=myUsername

This would prove that WebUI.getAttribute(nmTObj, 'value') returned a string just the same as the userName property of the viewModel object in JavaScript in the web page.

I think that Knockout.js binds the custom javascript object viewModel’s userName property to the DOM node’s value property. I mean, data is copied bidrectionally between the 2 properties.

So I thought that the Chrome DevTools should show the value attribute in the “Elements” view like:
<input value="myUsername">

But actually it doesn’t.

Why ?

I understand it.

document.querySelector("#element-id to input element") will return an instance of HTMLInputElement :
https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement

And, as the specification denotes, a HTMLInputElement always has a value property.

element.property exists. It’s part of the DOM interface HTMLElement API.

<element attributename=x> is optional, down to the author, always.

Forget knockout. Forget jQuery. There’s no magic here. There’s no secret formulae. There’s only http and HTML Form APIs.

<input value=x> is specified at the server, sent to the browser. When the property changes the attribute remains as specified by the server. When the form is submitted, the property is sent as the name/value pair. When the form is reset, the attribute is copied to the property.

WebUI and ANY OTHER WRAPPER LIBRARY reads the property. They’re “lying” to you if they say they’re reading the attribute. They’re correctly telling you the LIVE VALUE <<< the PROPERTY.

The only 100% reliable way to get the attribute value is element.getAttribute() - but 99% of the time that’s NOT what you want anyway, you want the .property. :expressionless:

Don’t take my word for it, try form.reset() and watch a value attribute suddenly “reappear” and wipe out a live value property. form.submit() and form.reset() tell you everything you need to know.

And like I said, these are not secrets, they’re published web standards, openly available to everyone. Doesn’t matter what jQuery does. Doesn’t matter how sexy Knockout is. Doesn’t matter what happens anywhere in the UI in the browser. Once you understand http form submit (and reset) you know everything about value attrs and properties.

HTTP form submit & reset does not answer to my question, I think.

Let me describe my question again.

In the following screenshot, I can see a string myUsername is displayed in the <input> element. This picture is just the same as the case where the element looks like <input value="myUsername">. But in the Chrome DevTool’s Elements view, I do not find the string myUsername at all. I wonder why DevTool behave like this.

If the DevTool shows a literal value="myUsername" in the Elements view, I am happy. I would find everything work as they should. But in fact the DevTool behaves slightly different from what I expect.

I suppose that this is a small / harmless / insignificant bug of the Chrome DevTool.

Well, in Firefox, what will I see? … let me check it later.

@kazurayam the result returns null below.

            WebUI.waitForElementVisible(findTestObject(activationCode),50) 
	String result = WebUI.getAttribute(findTestObject(activationCode), 'value')
	println(result) 

2021-02-09 08:10:16.309 DEBUG testcase.SCP - Enroll Mobotix camera - 8: cameraManagement.CameraManagement.activateSCP(result, mobotixUsername, mobotixPassword)
result = null
2021-02-09 08:10:22.327 ERROR c.k.k.core.keyword.internal.KeywordMain - :x: Unable to set text ‘null’ of object ‘Object Repository/Page_Device enrolment/input_Enter your camera activation code_code’ (Root cause: com.kms.katalon.core.exception.StepFailedException: Unable to set text ‘null’ of object ‘Object Repository/Page_Device enrolment/input_Enter your camera activation code_code’
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.SetTextKeyword.setText(SetTextKeyword.groovy:66)
at com.kms.katalon.core.webui.keyword.builtin.SetTextKeyword.execute(SetTextKeyword.groovy:37)
at com.kms.katalon.core.keyword.internal.KeywordExecutor.executeKeywordForPlatform(KeywordExecutor.groovy:73)
at com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords.setText(WebUiBuiltInKeywords.groovy:979)
at com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords$setText$3.call(Unknown Source)
at cameraManagement.CameraManagement.activateSCP(CameraManagement.groovy:230)
at cameraManagement.CameraManagement.invokeMethod(CameraManagement.groovy)
at com.kms.katalon.core.main.CustomKeywordDelegatingMetaClass.invokeStaticMethod(CustomKeywordDelegatingMetaClass.java:50)
at SCP - Enroll Mobotix camera.run(SCP - Enroll Mobotix camera:51)
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.TestCaseMain.runTestCase(TestCaseMain.java:114)
at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:105)
at com.kms.katalon.core.main.TestCaseMain$runTestCase$0.call(Unknown Source)
at TempTestCase1612876162062.run(TempTestCase1612876162062.groovy:25)
Caused by: java.lang.IllegalArgumentException: Text is null
at com.kms.katalon.core.webui.keyword.builtin.SetTextKeyword$_setText_closure1.doCall(SetTextKeyword.groovy:48)
at com.kms.katalon.core.webui.keyword.builtin.SetTextKeyword$_setText_closure1.call(SetTextKeyword.groovy)
at com.kms.katalon.core.webui.keyword.internal.WebUIKeywordMain.runKeyword(WebUIKeywordMain.groovy:20)
at com.kms.katalon.core.webui.keyword.builtin.SetTextKeyword.setText(SetTextKeyword.groovy:66)
at com.kms.katalon.core.webui.keyword.builtin.SetTextKeyword.execute(SetTextKeyword.groovy:37)
at com.kms.katalon.core.keyword.internal.KeywordExecutor.executeKeywordForPlatform(KeywordExecutor.groovy:73)
at com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords.setText(WebUiBuiltInKeywords.groovy:979)
at com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords$setText$3.call(Unknown Source)
at cameraManagement.CameraManagement.activateSCP(CameraManagement.groovy:230)
at cameraManagement.CameraManagement.invokeMethod(CameraManagement.groovy)
at com.kms.katalon.core.main.CustomKeywordDelegatingMetaClass.invokeStaticMethod(CustomKeywordDelegatingMetaClass.java:50)
at Script1612729828555.run(Script1612729828555.groovy:51)
… 11 more
)

This message indicates that an Exception is raised at some line containing a fragment:

WebUI.setText(TestObject, null)

No. This is not the place where the Exception is raised from.

Then you’re going to be unhappy for a long time, is my guess. The value is in the property, not the attribute. DevTools does NOT display the property. DevTools displays the DOM which is the current view of the HTML WITH MODIFICATIONS since it left the server - roughly speaking.

Repeat - stick to DOM APIs and run them in the console. Treat the elements view as a guide.

Aside: I just tested Chrome with the input #share-link like I did in Firefox. They behave the same. Which is exactly what I would expect. DOM APIs don’t lie.

@kazurayam I was suspecting the null value to be the cause of the other exception. So i modified the script below. It does not throw the exception. Basically i commented out the getAttribute stuff and replaced with a string “ABCD” instead. It does set the text correctly in the field and does not throw an exception. So the exception is caused by the null result.

@Keyword
def addScpCamera(model,manufacturer,serial,activationURL,deviceListView) {
//numberOfDevices(deviceListView)
WebUI.click(findTestObject(enrollDeviceButton))
WebUI.click(findTestObject(nextButton))
WebUI.setText(findTestObject(cameraName),model)
WebUI.selectOptionByValue(findTestObject(cameraManufacturer),manufacturer, true)
WebUI.click(findTestObject(nextButton))
WebUI.setText(findTestObject(macAddress),serial)
WebUI.click(findTestObject(nextButton))

	//get the activation code
	WebUI.waitForElementVisible(findTestObject(activationCode),350) 
	 // String result = WebUI.getText(findTestObject('Object Repository/Page_Stratocast portal - clientAcct1s devices/input_Copy this activation code to the activation page of your camera._ActivationCode'))
	//String result = WebUI.getAttribute(findTestObject(activationCode), 'value')
	//println(result)
      // println("result in addSCpCamera = " + result)
	   //return result
	//}

@Keyword
def activateSCP(result,username,password){
//Enter username and password
WebUI.executeJavaScript(‘window.open();’, [])
String currentWindow = WebUI.getWindowIndex()
//Go in to new tab
WebUI.switchToWindowIndex(currentWindow + 1)
WebUI.delay(2)
//WebUI.navigateToUrl(GlobalVariable.mobotixActivationURL)
WebUI.authenticate(GlobalVariable.mobotixActivationURL, username, password, 12)
WebUI.delay(3)
//Click on Start Activation button
//WebUI.click(findTestObject(‘Object Repository/Page_Device enrolment/startActivation’))
//WebUI.delay(5)
//println("result = " + result)
WebUI.setText(findTestObject(inputActivationCode),“ABCD”)
WebUI.click(findTestObject(activateButton))
}

Of course, but that’s not the topic here! (Apols to @mgrandillo, we’re getting seriously off-topic re the OP). We’re talking about input element ATTRS and PROPERTIES. Please understand them and the difference between them!

element.property != <element attr>

Can they have the same values? YES.

Can they have different values? YES.

Are they the same “thing”? NO.

I’m done here.

Yes, of course.

Yes, I agree.

Is your problem solved or not?

@mgrandillo Try this:

 //String result = WebUI.getAttribute(findTestObject(activationCode), 'value')
// Let's get the value property directly
String js = 'return document.querySelector("#ActivationCode").value;'
String result = (String) WebUI.executeJavaScript(js, null);
println(result) 

Make sure the #ActivationCode input element is present/visible.