How to select a value in an autocompleted textbox (API)

Hello all,

I’m facing an issue that I can’t solve for now.
I have a textbox where the user can enter a city or a post code. Once some text is entered, an API is called and returns a list of matching " " couples. Those items appear in a dropdown list and can be selected.

I would like to automate the following actions:

  • Enter any post code in this textbox
  • Select the first (or any) matching result in the dropdown list

I tried to use the Keys.chord method to use down arrow to pick up the first element in the list. Textbox is empty after the actions.
I tried the list all elements under the root textbox after entering some text in the textbox, but the returned list is empty.

Here is the static textbox:

<input type="text" class="form-control ajax-cp-ville ui-autocomplete-input" id="souscripteur_codePostalVille-text" value=" " name="souscripteur[codePostalVille]" autocomplete="off">

When entering some text:

<ul class="ui-autocomplete ui-front ui-menu ui-widget ui-widget-content" id="ui-id-2" tabindex="0" style="display: block; top: 515px; left: 254px; width: 386px;">
	<li class="ui-menu-item" id="ui-id-400" tabindex="-1">AUXERRE 89000</li>
	<li class="ui-menu-item" id="ui-id-401" tabindex="-1">PERRIGNY 89000</li>
	<li class="ui-menu-item" id="ui-id-402" tabindex="-1">ST GEORGES SUR BAULCHE 89000</li>
</ul>

Could you please help me?

Thanks in advance :slight_smile:
Etienne

How about making a list of the dropdown choices and selecting one of the items at random?

Maybe like
Random rand = new Random();
def driver = DriverFactory.getWebDriver();

List<WebElement> menuItems = driver.findElements(By.xpath('//li[@class="ui-menu-item"]'));

'get the maximum number of items In list'
int upperLimit = menuItems.size(); 

int choice = rand.nextInt(upperLimit);

menuItems.get(choice).click();

If you don’t want to go with a random item, then just choose the first item of the list:

menuItems.get(0).click();

or

menuItems[0].click();

An alternative is to use clickOffset:

WebUI.clickOffset(findTestObject('yourTO'), 45, 45)

with the values being the X offset (going to the right) and the Y offset (going downwards). The starting position is supposed to be the TestObject’s upper left corner.

1 Like

Hello grylion54,

thanks a lot for your answer! :slight_smile:
I already tried this kind of code, but the returned list is empty :frowning_face:

The actual behavior seems to be the following:

// I enter some postal code in the text field, so the API is called and the autocomplete propositions are displayed
WebUI.setText(findTestObject('.../text_Souscripteur_CPVille'), post_code, FailureHandling.STOP_ON_FAILURE)

// At this time, the autocomplete propoositions are empty...
List<WebElement> menuItems = driver.findElements(By.xpath('//li[@class="ui-menu-item"]'))
menuItems.get(0).click()

I don’t know why, when executing next line of code, the textbox seems to be reinitialized.

Do you have any idea?

Thanks again for your help :slight_smile:

I think we are going too fast and the page needs to catch up. Try putting a wait or delay statement after the setText and before the autocomplete drop-down, like:

WebUI.setText(findTestObject('.../text_Souscripteur_CPVille'), post_code, FailureHandling.STOP_ON_FAILURE)
WebUI.sendKeys(findTestObject('.../text_Souscripteur_CPVille'), Keys.Chord(Keys.Tab))

WebUI.delay(2)

// now see if there are any items..
List<WebElement> menuItems = driver.findElements(By.xpath('//li[@class="ui-menu-item"]'))

WebUI.comment("We have " + menuItems.size().toString() + " items.")

menuItems.get(0).click()

Thanks for your answer.

I’ve tested your code, but the autocomplete dropdown is always empty.
While debugging, I noticed that every time I execute the “setText” code, the text field is reset when going to the next line of code… It seems that the textbox looses focus after the step is executed, but I’ve no idea why :frowning:

Copy and paste the value you have for “post_code” into the textbox manually and see if the same reaction occurs. Also, do you display the contents of “post_code” for your own verification somewhere? It may be the format of the postal code needs tweaking.

If you think you might need focus on the textbox, you can add a click before your setText.

WebUI.click(findTestObject('.../text_Souscripteur_CPVille'))
WebUI.setText(findTestObject('.../text_Souscripteur_CPVille'), post_code, FailureHandling.STOP_ON_FAILURE)
WebUI.sendKeys(findTestObject('.../text_Souscripteur_CPVille'), Keys.Chord(Keys.Tab))

WebUI.verifyElementAttributeValue(findTestObject('.../text_Souscripteur_CPVille'),
	'value', "${post_code}", 10)
1 Like

Copy and pasting the value into the textbox does display the expected dropdown list.
If I click into the textbox before entering the text, the focus seems to be kept, as the dropdown list stays displayed.

The only remaining issue is that the items list is always empty.
I tried the following codes:

List<WebElement> menuItems = driver.findElements(By.xpath('//li[@class="ui-menu-item"]'))

List<WebElement> menuItems = driver.findElements(By.id('ui-id-2'))

Execution log:

2021-09-20 10:34:22.255 DEBUG t.TC VAR - WF complet (variables)        - 19: click(findTestObject("Page_AxellianceSolution_Tarifer/text_Souscripteur_CPVille"), STOP_ON_FAILURE)
2021-09-20 10:34:36.172 DEBUG t.TC VAR - WF complet (variables)        - 20: setText(findTestObject("Page_AxellianceSolution_Tarifer/text_Souscripteur_CPVille"), "71000", STOP_ON_FAILURE)
2021-09-20 10:34:45.162 DEBUG t.TC VAR - WF complet (variables)        - 21: delay(2)
2021-09-20 10:34:48.784 DEBUG t.TC VAR - WF complet (variables)        - 22: menuItems = driver.findElements(By.id("ui-id-2"))
2021-09-20 10:34:51.562 DEBUG t.TC VAR - WF complet (variables)        - 23: comment("We have " + size().toString() + " items.")
2021-09-20 10:34:53.839 INFO  c.k.k.c.keyword.builtin.CommentKeyword   - We have 0 items.

Thanks again!

Hi - should be “comment(“We have " + menuItems.size().toString() + " items.”)”. Ie specify the size of what needs to be returned (menuItems), otherwise it will always be 0. Cheers

Hi Dan_Bown,

I didn’t remark the log, but the code is correct:

List<WebElement> menuItems = driver.findElements(By.id('ui-id-2'))
WebUI.comment("We have " + menuItems.size().toString() + " items.")
if (menuItems.size() > 0)
{
	menuItems.get(0).click()
}

Very weird…
Thank you for your answer!

We had a discussion on another forum question about em dash, en dash, hyphen and other dash characters looking similar but the computer sees them differently. So, how about copying the HTML of the class (double click on “ui-menu-item”, right click and select copy) and then paste this phrase (replace) in place of the contents that I typed. This just ensures we have the correct characters in the statement so our phrase matches the HTML.

Another idea is to merge the two:

List<WebElement> menuItems = driver.findElements(By.xpath('id("ui-id-2")/li'))
WebUI.comment("We have " + menuItems.size().toString() + " items.")

Hi grylion54,

I tried the 2 options copying and pasting the identifiers to be sure:

List<WebElement> menuItems = driver.findElements(By.xpath('//li[@class="ui-menu-item"]'))
List<WebElement> menuItems = driver.findElements(By.xpath('id("ui-id-2")/li'))

The code does not fail anymore but the list always seems to be empty (one item should be present in my example):

Thanks again :slight_smile:

Try the copy and paste of the class contents of the HTML . There may be some difference between “French” and “English” character sets on the keyboards…

And you can try to right click on the dropdown phrase, “LYON 69006” and select Inspect and see if we do have the correct information when it displays.

How about?
WebUI.click(findTestObject('.../text_Souscripteur_CPVille'))
WebUI.setText(findTestObject('.../text_Souscripteur_CPVille'), post_code, FailureHandling.STOP_ON_FAILURE)
// WebUI.sendKeys(findTestObject('.../text_Souscripteur_CPVille'), Keys.Chord(Keys.Tab))

TestObject menuItem = new TestObject()
menuItem.addProperty("xpath", ConditionType.EQUAL, 'id("ui-id-2")/li[1]')

// wait until get search result back
WebUI.waitForElementVisible(menuItem, 10)
WebUI.click(menuItem)

I tried your code, with 2 differents xpath identifiers:

Yours (I copied/pasted from the DevTools to be sure to get the right characters):

menuItem.addProperty("xpath", ConditionType.EQUALS, 'id("ui-id-2")/li[1]')

The one I get from DevTools (I removed the id in the “li” item as it is dynamic):

menuItem.addProperty("xpath", ConditionType.EQUALS, '//*[@id="ui-id-2"]/li[1]')

In both cases, I get the following error:

Web element with id: '' located by '//*[@id="ui-id-2"]/li[1]' not found

This is very strange as the dropdown list is present in the DOM:

<ul class="ui-autocomplete ui-front ui-menu ui-widget ui-widget-content" id="ui-id-2" tabindex="0" style="display: block; width: 386px; top: 605px; left: 254px;">
	<li class="ui-menu-item ui-state-focus" id="ui-id-3" tabindex="-1">MACON 71000</li>
	<li class="ui-menu-item" id="ui-id-4" tabindex="-1">FLACE LES MACON 71000</li>
	<li class="ui-menu-item" id="ui-id-5" tabindex="-1">LOCHE 71000</li>
	<li class="ui-menu-item" id="ui-id-6" tabindex="-1">SENNECE LES MACON 71000</li>
	<li class="ui-menu-item" id="ui-id-7" tabindex="-1">ST JEAN LE PRICHE 71000</li>
	<li class="ui-menu-item" id="ui-id-8" tabindex="-1">SANCE 71000</li>
	<li class="ui-menu-item" id="ui-id-9" tabindex="-1">VARENNES LES MACON 71000</li>
</ul>

Wow. That’s certainly weird. The only thing I can suggest is that we are going too fast again, so maybe insert another wait or delay statement in the code.
WebUI.delay(2)

How about using the alternative I suggested earlier?

So, maybe

WebUI.click(findTestObject('.../text_Souscripteur_CPVille'))
WebUI.setText(findTestObject('.../text_Souscripteur_CPVille'), post_code, FailureHandling.STOP_ON_FAILURE)

WebUI.delay(2)
WebUI.clickOffset(findTestObject('.../text_Souscripteur_CPVille'), 45, 45)

1 Like

Woops, sorry, I forgot to test this workaround!
This is working, thanks a lot!.. :grin: :grin:

Hi grylion54,

I just found the cause of my issue by resolving another one: my field is located in an iframe and I never thought to add a switchToFrame() method before trying to find the dropdown web element…

So your first code was correct:

WebUI.switchToFrame(findTestObject('.../iframe'), 10)

List<WebElement> menuItems = driver.findElements(By.id('ui-id-2'))
WebUI.comment("We have " + menuItems.size().toString() + " items.")
menuItems.get(0).click()

Hope this will help someone… Thanks again!