Clicking on two identical buttons in the same screen

Hello all,
I’m trying to auto-test a page that has various buttons with letters on them, and only certain buttons need to be clicked to spell a word.
All buttons have the same class, the only thing different is the text.
I defined each button by the text clicked (the letter) and the class, and used “click”:

WebUI.click(findTestObject(‘Object Repository/Page_/button_r’))
WebUI.click(findTestObject(‘Object Repository/Page_/button_e’))
WebUI.click(findTestObject(‘Object Repository/Page_/button_d’))
etc…

Everything worked fine until I got to a word with two identical letters (for example, “green”). Then It’s only clicking the first “e”, and not the other (it’s trying to click again on the first “e”) - even if I create two separate test objects and even if I separate their folders:
WebUI.click(findTestObject(‘Object Repository/Page_/button_e’))
WebUI.click(findTestObject(‘Object Repository/button_e_second’))

I tried to verify that the element is clickable before clicking it (because each button is disabled after use):
WebUI.verifyElementClickable(findTestObject(‘Object Repository/Page_/button_e’))
WebUI.click(findTestObject(‘Object Repository/Page_/button_e’))
WebUI.verifyElementClickable(findTestObject(‘Object Repository/button_e_second’))
WebUI.click(findTestObject(‘Object Repository/button_e_second’))
But then I get an error in the “verify element clickable” stage stating that the element is NOT clickable (cause it’s still referring to the previous one).
Here’s the log:
Reason:
com.kms.katalon.core.exception.StepFailedException: Unable to verify object ‘Object Repository/button_e_second’ to be clickable
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.VerifyElementClickableKeyword.verifyElementClickable(VerifyElementClickableKeyword.groovy:96)
at com.kms.katalon.core.webui.keyword.builtin.VerifyElementClickableKeyword.execute(VerifyElementClickableKeyword.groovy:67)
at com.kms.katalon.core.keyword.internal.KeywordExecutor.executeKeywordForPlatform(KeywordExecutor.groovy:60)
at com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords.verifyElementClickable(WebUiBuiltInKeywords.groovy:562)
at com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords$verifyElementClickable$2.call(Unknown Source)
at Imagegame temp.run(Imagegame temp:53)
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:337)
at com.kms.katalon.core.main.TestCaseExecutor.doExecute(TestCaseExecutor.java:328)
at com.kms.katalon.core.main.TestCaseExecutor.processExecutionPhase(TestCaseExecutor.java:307)
at com.kms.katalon.core.main.TestCaseExecutor.accessMainPhase(TestCaseExecutor.java:299)
at com.kms.katalon.core.main.TestCaseExecutor.execute(TestCaseExecutor.java:233)
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 TempTestCase1580125918488.run(TempTestCase1580125918488.groovy:23)
Caused by: com.kms.katalon.core.exception.StepFailedException: Object ‘Object Repository/button_e_second’ is NOT clickable

Does anybody knows how to make Katalon click two buttons one after the other, even if they are defined the same?
Thanks!

Actually, it didn’t work fine. Your algorithm didn’t cover the problem domain.

That’s because your choice of algorithm is fixed, it can’t “dynamically adapt” to the change in your head, and the code (and browser) really don’t care where you store these things in Katalon.

That’s right, because it’s the same algorithm which you’ve already proved is faulty.

Yes, we do. You made a good job of showing us the results of your trials but you didn’t show us the definitions of your Test Objects. Do they use CSS? XPath? How do the buttons fit into the structure of the HTML document in the page?

If you read this post, you’ll get some good advice about how to report errors:

Hi,
Thank you for your answer.
That’s my test object (it’s defined by text & class):


I also tried defining it by xpath with a regex (because the letters can appear under two possible parent IDs):

That’s the HTML relevant part (see the letter e that appears twice):
image

Thanks in advance!

If you were using CSS, I’d advise you to use an index, nth-child(n) to reach the correct/target button. But I don’t use XPath so I can’t help.

However, I think @Brandon_Hein knows a little bit about XPath… :wink:

Sit tight. Let him have his third cup of coffee, and wait for him to help. :slight_smile:

Is the word that you need to spell consistent between runs of your test (I would hope so, otherwise I’m not sure how you would test it)? If you know which word you need to spell every time, then I would ditch trying to use the text of the button, and just pass in an index. The xpath in your test object would look something like this:

//div[@id='spellingLetters0']/button[${index}]

Then your test code would click each button you’d like by passing an index like so:

WebUI.click(findTestObject(‘Object Repository/Page_/button’, ['index' : 1]))
WebUI.click(findTestObject(‘Object Repository/Page_/button’, ['index' : 2]))
.
.
.
WebUI.click(findTestObject(‘Object Repository/Page_/button’, ['index' : n]))

Hi,
Thanks @Brandon_Hein and @Russ_Thomas!
The word I’m spelling is always the same (for example “green”), but unfortunately, the order of the letters changes every time I open the game (there are 12 different letters that I should choose 5 of them to spell “green”, but the order changes and the redundant letters change), so I can’t use their location (if I understand what you mean by index).
Any other advice? Maybe using the fact that a letter that was used is disabled?

Thanks again for your time!

does the “game” distinguish between those letters? if not, you don’t need either … that means you can allways press letter_e_button[1] first and letter_e_button[2] second… game should not care (if yes, it’s bug)

@Andrej_Podhajsky There’s no difference between the two e buttons, as far as I can tell.
I tried to create two test objects, button_e and button_e_second, but Katalon says it clicked both, but actually only clicks one (In the log I see “click button_e”, “click button_e_second”, “click button_n”, but on the screen it only spells “gren” and then get stuck because the word wasn’t really completed).
Can you please show me how you would define the test objects?

Object button:
xpath=(//button[contains(@class,‘spelling_letter’) and contains(text(),’$LETTER’)])[$INDEX]

call will be:
WebUI.click(findTestObject(‘Object Repository/Page_/button’,[(‘LETTER’):‘e’, (‘INDEX’):1]))
WebUI.click(findTestObject(‘Object Repository/Page_/button’,[(‘LETTER’):‘e’, (‘INDEX’):2]))

also you need to adjust xpath to fit your need

Thanks @Andrej_Podhajsky , I tried to use your structure but Katalon can’t click the button when I get to this part, I get this error:
Reason:
com.kms.katalon.core.exception.StepFailedException: Unable to click on object ‘Object Repository/Page_/button_e’
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.ClickKeyword.click(ClickKeyword.groovy:103)
at com.kms.katalon.core.webui.keyword.builtin.ClickKeyword.execute(ClickKeyword.groovy:43)
at com.kms.katalon.core.keyword.internal.KeywordExecutor.executeKeywordForPlatform(KeywordExecutor.groovy:60)
at com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords.click(WebUiBuiltInKeywords.groovy:616)
at com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords$click$1.call(Unknown Source)
at Imagegame temp.run(Imagegame temp: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:337)
at com.kms.katalon.core.main.TestCaseExecutor.doExecute(TestCaseExecutor.java:328)
at com.kms.katalon.core.main.TestCaseExecutor.processExecutionPhase(TestCaseExecutor.java:307)
at com.kms.katalon.core.main.TestCaseExecutor.accessMainPhase(TestCaseExecutor.java:299)
at com.kms.katalon.core.main.TestCaseExecutor.execute(TestCaseExecutor.java:233)
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 TempTestCase1580289842403.run(TempTestCase1580289842403.groovy:23)
Caused by: com.kms.katalon.core.webui.exception.WebElementNotFoundException: Web element with id: ‘Object Repository/Page_/button_e’ located by ‘By.xpath: (//button[contains(@class,‘spelling_letter’) and contains(text(),’$LETTER’)])[$INDEX]’ not found

This is how I defined the test object:
image

I’m not quite sure what the “index” part means - is it the location of the letter? Because if so, it’s a problem to use index1 and index2, because these e’s can be anywhere between the 12 buttons.

use attributes as selection method … variables are not working in XPath Selection method

I’m not quite sure what the “index” part means - is it the location of the letter? Because if so, it’s a problem to use index1 and index2, because these e’s can be anywhere between the 12 buttons.

index is occurance:
xpath like :
//button[contains(@class,‘spelling_letter’) and contains(text(),’e’)]
will return 2 objects - this is not allowed in OR
therefore you need to pinpoint which of those 2 object you want to use … it’s not about position on screen (simplification) but about position on DOM.
so (//button[contains(@class,‘spelling_letter’) and contains(text(),’e’)])[1] will adress 1st button with letter ‘e’ (//button[contains(@class,‘spelling_letter’) and contains(text(),’e’)])[2] will address 2nd object

to better understand how xpath works i suggest to install any plugin to browser that will allow you to test your xpath and will show results of xpath query

1 Like

@Andrej_Podhajsky thank you so much!
I created two test objects for e:
//button[contains(@class,‘spelling_letter’) and contains(text(),’e’)])[1]
//button[contains(@class,‘spelling_letter’) and contains(text(),’e’)])[2]
And it worked perfectly!

It didn’t work when I tried the first suggestion, to define the object like this: xpath=(//button[contains(@class,‘spelling_letter’) and contains(text(),’$LETTER’)])[$INDEX] and then in the test case do the call like this: WebUI.click(findTestObject(‘Object Repository/Page_/button’,[(‘LETTER’):‘e’, (‘INDEX’):1])), maybe I have some mistake somewhere, but since I don’t have a lot of these doubles, I can just duplicate the necessary buttons.

Thanks again for your patience and help! :slight_smile:

to get work parameters use Attributes as Selection method on Object definition:
image

Yeah I did this, but it didn’t work. Maybe there was something wrong with the test case itself?

can you share code/call you used when it fails?

I would get the code changed in the game and assign unique ID’s to each button like “e1” and “e2”. This would be easy on the game code side and greatly simplify what you are trying to do.

Ok, so dev should implement every word separately?
try to force them to impement Popocatepetl…

I tried this definition for the test object (using Attribute as selection method):
(//button[contains(@class,‘spelling_letter’) and contains(text(),’$LETTER’)])[$INDEX]

And then the call was:
WebUI.click(findTestObject(‘Object Repository/Page_/button’,[(‘LETTER’):‘e’, (‘INDEX’):1]))
WebUI.click(findTestObject(‘Object Repository/Page_/button’,[(‘LETTER’):‘e’, (‘INDEX’):2]))

And I got an error that object was not found.

OK so the order of the buttons changes, and it sounds like you cannot click the same button twice. In this case, you would need to identify the buttons using text AND position (index):

//div[@id='spellingLetters0']/button[text()='${text}'][${index}]

WebUI.click(findTestObject(‘Object Repository/Page_/button’, ['text' : 'e', 'index' : 1]))
WebUI.click(findTestObject(‘Object Repository/Page_/button’, ['text' : 'e', 'index' : 2]))

Although, as others have suggested, if you have any say in the implementation of the HTML/JS, I would try get an ID in there that would make your life easier.

My fault … sorry …

should be

xpath=(//button[contains(@class,‘spelling_letter’) and contains(text(),"${LETTER}")])[${INDEX}]

i missed curly brackets …