Using waitForElementPresent without an Object

In both cases, findTestObject is failing to find an element to click on. You are using an xpath that clearly does not work.

Strictly speaking, debugging and fixing xpath expressions is not my forte, FWIW. And it’s a little off topic for this thread. Try reposting a new thread “What’s wrong with my XPATH?”, maybe someone with more xpath experience will chime in.

Russ Thomas said:

In both cases, findTestObject is failing to find an element to click on. You are using an xpath that clearly does not work.

Strictly speaking, debugging and fixing xpath expressions is not my forte, FWIW. And it’s a little off topic for this thread. Try reposting a new thread “What’s wrong with my XPATH?”, maybe someone with more xpath experience will chime in.

Russ

It is nothing to do with xpath. Actually it is not off topic. I am facing the same issue.

I have tried with each parameter individually or combined.
Modified an existing object captured by Spy Object.
Or have created a new Test Object from scratch - as per your recommendation i think.

I am also not clear why would i use this: def myModifiedObject = WebUI.modifyObjectProperty(…)

I know object name, or xpath or id. Why specifying it directly - it is not recognized by KS?

I am just not sure what is going on.

Thanks
Andrew

Okay, let’s try something else. Referring back to your last image…

You have a name setting checked. But the name setting has a time value. Wouldn’t that change per email?

Try this: turn off everything except the xpath.

Russ Thomas said:

Okay, let’s try something else. Referring back to your last image…

You have a name setting checked. But the name setting has a time value. Wouldn’t that change per email?

Try this: turn off everything except the xpath.

Thank you Russ!

I will try leaving just xpath. I thought i tried on my test object created manually - but will try again.

I tried something else though.

The Name Test Object is basically “from” name - that appears in the Inbox. And for my testing purposes, i make it be the same thing. Say Email1, and another email will have “from” name
will be **Email2.
**
Of course it would be nice to parametrize such objects with solutions you recommended. But this is kind of far ahead. I thought if it doesn’t work in a simple way - i did not want to even try with making modifications to the object. Besides - the NAME - always stays the same. Tag is always stays the same. And i think even the xpath stays the same all the time.

In any case - i will try with **xpath **only and will report back.

Thank you so much for your guidance!
Andrew

Russ Thomas said:

Okay, let’s try something else. Referring back to your last image…

You have a name setting checked. But the name setting has a time value. Wouldn’t that change per email?

Try this: turn off everything except the xpath.

Good Evening Russ

I have tried and still my object is not being recognized.
Here are some more details. Maybe i am blind and do not see something obvious?

Sorry for the long post.

I found a good example to demonstrate. It is a “From” link in the inbox. In this specific case - the “xpath” is being changed every time user clicks on the object. However the “name” property always stays the same.

Modifying test object:

new_email = WebUI.modifyObjectProperty(findTestObject(‘Page_Gmail/span_CPC410437’), ‘name’, ‘equals’, ‘CPC410437’, false)

WebUI.waitForElementVisible(new_email, 15)

WebUI.click(new_email)

Error:
_Unable to click on object ‘Object Repository/Page_Gmail/span_CPC410437’ (Root cause: com.kms.katalon.core.webui.exception.WebElementNotFoundException: Web element with id: ‘Object Repository/Page_Gmail/span_CPC410437’ located by 'By.xpath: ’ not found)
_
Note: At this point the test object property does get modified.

Adding a new test object:

TestObject dynamicObject = new TestObject(‘Page_Gmail/dynamicObject’).addProperty(‘name’, com.kms.katalon.core.testobject.ConditionType.EQUALS, ‘span_CPC410437’, false)

WebUI.waitForElementVisible(dynamicObject, 5)

WebUI.click(dynamicObject)

Error:
Unable to click on object ‘Page_Gmail/dynamicObject’ (Root cause: com.kms.katalon.core.webui.exception.WebElementNotFoundException: Web element with id: ‘Page_Gmail/dynamicObject’ located by 'By.xpath: ’ not found)

Here is the properties of this object:

Thank you
Andrew

Maybe i am blind and do not see something obvious?

Then that makes two of us :frowning: And as a reminder, read my first response to you again - xpath is not my thing!

That said…

Can you paste some of the HTML surrounding the span(s) in question? I’m now concerned you are trying to click on the wrong element entirely (spans do not have a name attributes: https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes). If some JavaScript is adding a name property, then there is much more going on with that page than meets the eye.

Note: in HTML, property and attribute are different things. In Katalon they may or may not reflect the same things and they may or may not be consistent with each other (one reason why I steer clear of TestObjects and xpaths).

Paste a copy of the HTML and make a list of things that STAY THE SAME before and after a click.

Russ Thomas said:

Maybe i am blind and do not see something obvious?

Then that makes two of us :frowning: And as a reminder, read my first response to you again - xpath is not my thing!

That said…

Can you paste some of the HTML surrounding the span(s) in question? I’m now concerned you are trying to click on the wrong element entirely (spans do not have a name attributes: https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes). If some JavaScript is adding a name property, then there is much more going on with that page than meets the eye.

Note: in HTML, property and attribute are different things. In Katalon they may or may not reflect the same things and they may or may not be consistent with each other (one reason why I steer clear of TestObjects and xpaths).

Paste a copy of the HTML and make a list of things that STAY THE SAME before and after a click.

Good Evening Russ

This time i did some more research on my own. Hence did not want to bother you or anyone else.

Here is the html behind the object. I have highlighted attributes that stay same in Bold.

BEFORE CLICK:

<span class=“bqe” data-thread-id="#thread-f:1603299835216060460"
data-legacy-thread-id=“164010b49a7ee02c”
data-legacy-last-message-id=“164010b49a7ee02c”>CPL413000

<span
class=“zF” email="finmc@e.finmc.com"
name=“CPL413000” data-hovercard-id="finmc@e.finmc.com" data-hovercard-owner-id=“26”>CPL413000

AFTER CLICK:

<span data-thread-id="#thread-f:1603299835216060460"
data-legacy-thread-id=“164010b49a7ee02c”
data-legacy-last-message-id=“164010b49a7ee02c”>CPL413000

<span class=“yP” email="finmc@e.finmc.com"
name=“CPL413000” data-hovercard-id="finmc@e.finmc.com"
data-hovercard-owner-id=“26”>CPL413000

Note:

- Once you mentioned before and after click - i started looking into this and i think i made it work.

I mean it runs for me in this code below:

WebUI.waitForElementPresent(findTestObject(‘Page_Inbox/span_CPL413000’), 15)
WebUI.click(findTestObject(‘Page_Inbox/span_CPL413000’))

However only if this TO has the following enabled:

tag = "span"

class = "zF"

name= "CPL413000"

text = "CPL413000"

xpath = “id(”:2w")/span[@class=“bA4”]/span[@class=“zF”]"

And i read your article above - and would like to have the TO being recognized with just few attributes needed… This is what makes me really sad and confused.

I know you can say - “hey Andrew - it runs, so forget about it”.

Unfortunately (or fortunately) - i always attempt to learn better…

Thank you very much!

Andrew

Well, at least now we have a better picture as to what is going on.

To me, this test scenario is ideally suited to building a dynamic test object “live” during the test case’s execution. The (bad) name attribute is consistent, so therefore I’d build the dynamic TO using just CSS (leave out the rest of that stuff which just causes confusion).

The CSS you need is:

span[name='CPL413000']

Read this article about modifying properties of TOs:

https://docs.katalon.com/display/KD/[WebUI]+Modify+Object+Property

Then create a dummy TO and modify its “css” property:

def tempTO = WebUI.modifyObjectProperty(findTestObject("dummy"), 
    "css", "equals", "span[name='CPL413000']", true)
WebUI.doSomething(tempTO)

(I typed that out from memory – double check for typos/errors)

I know you can say - “hey Andrew - it runs, so forget about it”.
Unfortunately (or fortunately) - i always attempt to learn better…

No, you’re absolutely right to keep going and not give up. If you shrug and walk away, what would you learn? B)

Good luck!

Russ

p.s. I’m surprised the developers are “good enough” to use data-* attributes for custom attributes yet they seem to have no issues with using a name attribute where it doesn’t belong (i.e. in a span). name attributes are typically applied to html form elements (and children) to create name/value pairs for http submission to a server – but spans are not submitted elements.

Furthermore, were you (or anyone) to devise a piece of css/jQuery selector/DOM selector using “[name]” e.g. document.querySelectorAll("[name]") , you’d get all the things you’re expecting (inputs, selects, etc) and a bunch of spans you are certainly not expecting. See? BAD. And like you said earlier, it works, forget about it… nope, I’d be scared that’s going to bite me one day and cost me a ton of time to figure what the hell is going on.

You might mention that to the developers and send them the MDN link. Suggest they use data-email-name, or similar. Thing is, the spec is what it is - a spec. It’s not a secret and it’s not a moving target (unlike bad code!)

End of rant B)

1 Like

Russ Thomas said:

Well, at least now we have a better picture as to what is going on.

To me, this test scenario is ideally suited to building a dynamic test object “live” during the test case’s execution. The (bad) name attribute is consistent, so therefore I’d build the dynamic TO using just CSS (leave out the rest of that stuff which just causes confusion).

The CSS you need is:

span[name='CPL413000']

Read this article about modifying properties of TOs:

https://docs.katalon.com/display/KD/[WebUI]+Modify+Object+Property

Then create a dummy TO and modify its “css” property:

def tempTO = WebUI.modifyObjectProperty(findTestObject("dummy"), 
"css", "equals", "span[name='CPL413000']", true)

WebUI.doSomething(tempTO)


(I typed that out from memory -- double check for typos/errors)  
  

> I know you can say - "hey Andrew - it runs, so forget about it".  
> Unfortunately (or fortunately) - i always attempt to learn better...  

  
No, you're absolutely right to keep going and not give up.  If you shrug and walk away, what would you learn?  B)  
  
Good luck!  
  
Russ  
  
p.s. I'm surprised the developers are "good enough" to use **data-*** attributes for custom attributes yet they seem to have no issues with using a **name** attribute where it doesn't belong (i.e. in a span). **name** attributes are typically applied to html form elements (and children) to create name/value pairs for http submission to a server -- _but spans are not submitted elements_.   
  
Furthermore, were you (or anyone) to devise a piece of css/jQuery selector/DOM selector using "\[name\]" e.g. document.querySelectorAll("\[name\]") , you'd get all the things you're expecting (inputs, selects, etc) and a bunch of spans you are certainly not expecting.  See? BAD.  And like you said earlier, it works, forget about it...  nope, I'd be scared that's going to bite me one day and cost me a ton of time to figure what the hell is going on.  
  
You might mention that to the developers and send them the MDN link.  Suggest they use **data-email-name**, or similar.  Thing is, the spec is what it is - a spec.  It's not a secret and it's not a moving target (unlike bad code!)  
  
End of rant B)  

  
  
  

  

Good Evening Russ

I have decided to take this one step forward and create Test Object via script.

TestObject dummy = new TestObject(‘dummy’)

dummy.addProperty(“css”, ConditionType.EQUALS, ‘span[name=“CPL413000”]’)

WebUI.verifyElementPresent(dummy, 10, FailureHandling.STOP_ON_FAILURE)

WebUI.verifyElementVisible(dummy, FailureHandling.STOP_ON_FAILURE)

However i believe i am missing an import package (i think), i am getting this command flagged:

ConditionType.EQUALS

So it errors this way:
Test Cases/TO_TEST FAILED because (of) Variable ‘ConditionType’ is not defined for test case.

Going to add a separate post for this.

Thank you
Andrew

AddProperty1.png

Actually - i went ahead and added the “dummy” Test Object manually.

And i have this command:
def tempTO = WebUI.modifyObjectProperty(findTestObject(‘dummy’, ‘css’, ‘equals’, ‘span[name=“CPL413000”]’, true))

However somehow it errors out:

Test Cases/TO_TEST FAILED because (of) groovy.lang.MissingMethodException: No signature of method: Script1529369104841.findTestObject() is applicable for argument types: (java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.Boolean) values: [dummy, css, equals, span[name=“CPL413000”], true]

Thank you
Andrew

Try …

... findTestObject("dummy") ...

But you could also dispense with the OR and create the TO “live”…

static TestObject makeTO(String css) {
  TestObject to = new TestObject()
  to.addProperty("css", ConditionType.EQUALS, css)
  return to
}

Source is “me” B) here: https://docs.katalon.com/display/KD/Creation+of+Test+Object+in+Object+Repository+in+Runtime

Andrew,

On 11/June/2018 you raised following question in the post:

The scenario is very simple. Click on the email arrived.

Created my own test object and called it Email1.

Xpath: id(":38")/span[@class=“bA4”]/span[@class=“yP”]

I get this error:

Unable to click on object ‘Object Repository/Page_Inbox (479) - andrewkhomskigma/Email1’ (Root cause: com.kms.katalon.core.webui.exception.WebElementNotFoundException: Web element with id: ‘Object Repository/Page_Inbox (479) - andrewkhomskigma/Email1’ located by ‘By.xpath: id(":38")/span[@class=“bA4”]/span[@class=“yP”]’ not found)

What you called ‘email’ here is the Google Mail.

## What I did

I made a Katalon Studio project for my experiment. This project logs into GMail with my personal credential. The test case checks the gmail page where a list of incoming mails are displayed. The test case selects the row of 1st incoming mail, then click the sender name to jump to the content page. The test case works.

My test case is as follows:

import static com.kms.katalon.core.testcase.TestCaseFactory.findTestCase
import com.kms.katalon.core.model.FailureHandling as FailureHandling
import com.kms.katalon.core.testobject.ConditionType as ConditionType
import com.kms.katalon.core.testobject.TestObject as TestObject
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
// login into GMail with my account
WebUI.callTestCase(findTestCase('Login'), ['userid':'','password':''], FailureHandling.STOP_ON_FAILURE)
// create a Test Object on the fly. We do not use the Object Repository here.
def testobject = new TestObject("1st mail sender")
// The Gmail, list of inbox, 1st row, sender name
def expr = '//table/tbody/tr[1]/td[5]/div[2]/span/span'
testobject.addProperty("xpath", ConditionType.EQUALS, expr)
WebUI.verifyElementPresent(testobject, 10, FailureHandling.STOP_ON_FAILURE)
def content = WebUI.getText(testobject, FailureHandling.OPTIONAL)
WebUI.comment("content=${content}")
// now click the sender name to see the indivisual mail content  
WebUI.click(testobject)
Thread.sleep(5000)
WebUI.closeBrowser()

## What I found

Andrew, you could not click the 1st email. But I could do it. What is the difference? — we use different XPath expressions.

Andrew used the following XPath expression:

id(":38")/span[@class="bA4"]/span[@class="yP"]

I used the following expression:

//table/tbody/tr[1]/td[5]/div[2]/span/span

I observed HTML DOM of the Google Mail page carefully. For example, the table tag as the list of email was once marked up as follows:

<table id=":2p">    ....</table> 

I thought that the values of id attributes (:2p in the above example) is dynamically allocated by the server-side application. I thought the markup MAY (likely to) change as follows:

<table id=":2q">    ....</table>

I thought that the id value in Gmail page is unstable so that my XPath should not rely on the id values.

## Answer to the original question

I think, Andrew’s XPath expression id(":38") was once valid but it turned invalid sometime after the id value is reassigned by the Gmail server app.

1 Like

kazurayam said:

Andrew,

On 11/June/2018 you raised following question in the post:

The scenario is very simple. Click on the email arrived.

Created my own test object and called it Email1.

Xpath: id(":38")/span[@class=“bA4”]/span[@class=“yP”]

I get this error:

Unable to click on object ‘Object Repository/Page_Inbox (479) - andrewkhomskigma/Email1’ (Root cause: com.kms.katalon.core.webui.exception.WebElementNotFoundException: Web element with id: ‘Object Repository/Page_Inbox (479) - andrewkhomskigma/Email1’ located by ‘By.xpath: id(":38")/span[@class=“bA4”]/span[@class=“yP”]’ not found)

What you called ‘email’ here is the Google Mail.

## What I did

I made a Katalon Studio project for my experiment. This project logs into GMail with my personal credential. The test case checks the gmail page where a list of incoming mails are displayed. The test case selects the row of 1st incoming mail, then click the sender name to jump to the content page. The test case works.

My test case is as follows:

import static com.kms.katalon.core.testcase.TestCaseFactory.findTestCase

import com.kms.katalon.core.model.FailureHandling as FailureHandling
import com.kms.katalon.core.testobject.ConditionType as ConditionType
import com.kms.katalon.core.testobject.TestObject as TestObject
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
// login into GMail with my account
WebUI.callTestCase(findTestCase(‘Login’), [‘userid’:’’,‘password’:’’], FailureHandling.STOP_ON_FAILURE)
// create a Test Object on the fly. We do not use the Object Repository here.
def testobject = new TestObject(“1st mail sender”)
// The Gmail, list of inbox, 1st row, sender name
def expr = ‘//table/tbody/tr[1]/td[5]/div[2]/span/span’
testobject.addProperty(“xpath”, ConditionType.EQUALS, expr)
WebUI.verifyElementPresent(testobject, 10, FailureHandling.STOP_ON_FAILURE)
def content = WebUI.getText(testobject, FailureHandling.OPTIONAL)
WebUI.comment(“content=${content}”)
// now click the sender name to see the indivisual mail content
WebUI.click(testobject)
Thread.sleep(5000)
WebUI.closeBrowser()


  

**\## What I found**

  

Andrew, you could not click the 1st email. But I could do it. What is the difference? --- we use different XPath expressions.

Andrew used the following XPath expression:

id(":38")/span[@class=“bA4”]/span[@class=“yP”]


I used the following expression:

//table/tbody/tr[1]/td[5]/div[2]/span/span


  
  

I observed HTML DOM of the Google Mail page carefully. For example, the table tag as the list of email was once marked up as follows:

  
  

....
```

I thought that the values of id attributes (:2p in the above example) is dynamically allocated by the server-side application. I thought the markup MAY (likely to) change as follows:

<table id=":2q">    ....</table>

I thought that the id value in Gmail page is unstable so that my XPath should not rely on the id values.

## Answer to the original question

I think, Andrew’s XPath expression id(":38") was once valid but it turned invalid sometimes after the id value is reassigned by the Gmail server app.

Thank you kazurayam!!!

I am still “compiling” this information.

Actually since that time i was able to make it work.

However - i am getting all the emails info (from, subject, content) from the DDT.

And it works.

**BUT… **i am trying to add the TOs straight from the .csv - and this is where i bang my head against the wall for now… :frowning: :frowning:

I will “compile” your code in my head first and next will respond with more details.

**But really appreciate your help!!! **

Thank you
Andrew

**BUT… **i am trying to add the TOs straight from the .csv - and this is where i bang my head against the wall for now…

The following tip might help you:

Here I use Groovy’s SimpleTemplateEngine
http://docs.groovy-lang.org/latest/html/api/groovy/text/SimpleTemplateEngine.html

1 Like

I will “compile” your code in my head first and next will respond with more details.

If you are going to continue, please create a new topic with appropriate title.

kazurayam said:

I will “compile” your code in my head first and next will respond with more details.

If you are going to continue, please create a new topic with appropriate title.

kazurayam

All worked. Thank you!

I am going to add a new topic.

Andrew