Old input text still appears even with SetText or ClearText

Hey Guys, I have encountered a very weird situation:

Imagine you automate a profile edit. You want to change the field “firstname” from abc to def.

Regardless of what I try, setText(), clearText() or even harder solutions like this very good one I´ve found in the forum: Deleting text of an input field, Solution that works in all the browsers - #3 by Russ_Thomas, it ends the same way:

abc gets cleared, and instead of just putting “def” in the input, it puts “abcdef”. Regardless of how I cleared the text before (or use of setText() which also clears it before putting in new text).
In the logs it states: “Testobject” gets cleared

and also

“Text ‘def’ is set on Object”, but what really happens is what I´ve written above.

I´ve tried 4 browsers, the outcome is the same. Has anyone encountered this?

Thanks :slight_smile:

Point us to example AUT plz

I would love to, but it´s behind a VPN and not reachable easily :confused:

String randomFirstname = CustomKeywords.'customFunctions.commons.randomNameGenerator'()
String randomLastname = CustomKeywords.'customFunctions.commons.randomNameGenerator'()
String randomStreet = CustomKeywords.'customFunctions.commons.randomNameGenerator'()
String randomCity = CustomKeywords.'customFunctions.commons.randomNameGenerator'()



String js = 'document.querySelector("#input-vue-text-firstname").value = "";'
WebUI.executeJavaScript(js, null)

WebUI.setText(findTestObject('Object Repository/iShop/Profil/input_AdresseAendern_Vorname'), randomFirstname)

js = 'document.querySelector("#input-vue-text-lastname").value = "";'
WebUI.executeJavaScript(js, null)

WebUI.setText(findTestObject('Object Repository/iShop/Profil/input_AdresseAendern_Nachname'), randomLastname)

js = 'document.querySelector("#input-vue-text-street").value = "";'
WebUI.executeJavaScript(js, null)

WebUI.setText(findTestObject('Object Repository/iShop/Profil/input_AdresseAendern_Strasse'), randomStreet)

js = 'document.querySelector("#input-vue-text-city").value = "";'
WebUI.executeJavaScript(js, null)

WebUI.setText(findTestObject('Object Repository/iShop/Profil/input_AdresseAendern_Stadt'), randomCity)

But I can show you the code, maybe that helps, but I don´t think theres a problem in the code.

Hey @patrick5

First, let’s have a look at the events attached to element. In the following, use Firefox’s devtools:

Right-click on the element and choose “Inspect”. Make sure you can see the element itself and plenty of the DOM above the element.

We’re looking for the event button displayed next the the <input> element – if it’s not there, it may appear somewhere above in the DOM hierarchy. It’s not impossible for it to be on both

Once you have at least one, click it. Take a screenshot of what you see and post it here.

Hey,

first thank you very much, I knew nothing about the function!
So it looks like this:

What I´ve found out (which is VERY weird):
When I execute the test via Chrome, the exact same wrong behaviour as described in my entry post happens.
When I execute the test afterwards on Firefox, also the same wrong thing happens.
When I execute the test on the 2nd time on a row on Firefox the expected (right) behaviour happens!!!

When I then try it out via Chrome, everything repeats again.

I really cannot understand it, as there are all incognito tabs, so there shouldn´t occur any cache / or similar issues. Very weird o_O?

As you’ve figured out, both change and input are likely to be messing with your intentions. On rare occasions, when I’ve had to use JavaScript to force a value property to update, I’ve had to make sure the onchange handler is called. Whether it will work for you, I can’t say for sure.

String js = '''
var el = document.querySelector("your-selector-here");
el.value = "something";

// either...
el.onchange()
// or
el.change()
'''
WebUI.executeJavaScript(js, null);

To maybe help you whittling this down, try the individual js lines in the browser console first (that will save you the round trip in Katalon).

First, highlight the input element in the Firefox DevTools inspector (like you did before) and make sure the console panel is visible below the inspector (press Esc to toggle it). Then try these lines in sequence:

$0.value = "something"

Then…

$0.change()

Repeat: First, highlight the input element. Whatever is highlighted will be addressed by $0.

If you see the correct behavior, you know you’re on the right track and you can build the relevant code correctly in Katalon.

I faced the same issue, with the datepicker widgets in this Zoho app I have to test. Here’s how I handle it:

My datepicker-update boilerplate code

public final class GeneralWebUIUtils {
	public static final String VALUE = "value";

	public static String GetTextValue(TestObject to) {
		return WebUI.getAttribute(to, this.VALUE)
	}

	public static void UpdateDateField(TestObject to, Date newDate) {
		this.WaitForTextFieldNonEmpty(to, 1, FailureHandling.CONTINUE_ON_FAILURE)

		if (newDate == null) {
			WebUI.clearText(to, FailureHandling.STOP_ON_FAILURE);
			return;
		}

		final String fieldTextValue = this.GetTextValue(to),
		newDateTextValue = SMDDateUtils.ToDateString(newDate);

		if ((!newDateTextValue.isEmpty()) && (!fieldTextValue.equals(newDateTextValue))) {
			this.ClearAndEnterText(to, newDateTextValue);

			KeywordUtil.logInfo("'${newDateTextValue}' written to the date field")
		}

		WebUI.sendKeys(to, Keys.TAB.toString());
		KeywordUtil.logInfo("After trying to write to the field, it has value '${this.GetTextValue(to)}'")
	}

	public static boolean WaitForElementCondition(Closure<Boolean> onCheckCondition, Closure onContinue, TestObject to, int timeOut, FailureHandling failureHandling = FailureHandling.STOP_ON_FAILURE) {
		final long startTime = System.currentTimeMillis()
		boolean isConditionSatisfied = false;
		while ((System.currentTimeMillis() < startTime + timeOut * 1000) && (!isConditionSatisfied)) {
			isConditionSatisfied = WebUI.waitForElementPresent(to, 1, failureHandling) && onCheckCondition(to);
			if (onContinue != null)
				onContinue(isConditionSatisfied, to);
		}
		if ((!isConditionSatisfied) && (failureHandling.equals(FailureHandling.STOP_ON_FAILURE))) {
			KeywordUtil.markFailedAndStop("Condition for TestObject '${to.getObjectId()}' not met after ${(System.currentTimeMillis() - startTime) / 1000} seconds");
		}
		return isConditionSatisfied;
	}

	public static boolean WaitForTextFieldNonEmpty(TestObject to, int timeOut, FailureHandling failureHandling = FailureHandling.STOP_ON_FAILURE) {
		return this.WaitForElementCondition({ TestObject testObj ->
			return (!this.GetTextValue(testObj).isEmpty());
		},
		null,
		to,
		timeOut,
		failureHandling);
	}

	public static void ClearAndEnterText(TestObject to, String text) {
		WebUI.sendKeys(to,
				Keys.chord("${this.GetCommandKey().toString()}A"),
				FailureHandling.STOP_ON_FAILURE);

		WebUI.sendKeys(to, text, FailureHandling.STOP_ON_FAILURE);
	}

	public static Keys GetCommandKey() {
		final String os = System.getProperty("os.name")

		if (os.toUpperCase().contains("WINDOWS"))
			return Keys.CONTROL;

		return Keys.COMMAND;
	}
}

This is the boilerplate code for updating a date field. I would suggest adapting it to your use-case.

The method UpdateDateField should give you some clues on how to solve your issue. The best part? No JavaScript manipulation, or deep understanding of event listeners (part of the AUT) required!

Breakdown of the code

First, you want to wait for the text field to be not-empty. Yes, if the text field is supposed to be empty (i.e. not filled in already with some value), it will effectively pause for a second.

Next, you clear the field and enter the text value, if it is different from what is already in the text field.

Hope this helps!