The "xpath" for the url is correct but not visible if added via addProperty

Hello

I created this topic as it was suggested to open a new one.

Here is the scenario - and posting becuase did not find the specific case like this.

CASE 1:

- Added a TO “LinkTest” into Object Repository and only 1 attribute: xpath

//a[@href=‘Problem Encountered’]

WebUI.click(findTestObject(‘Page_Inbox/LinkTest’))

RESULT: Works without issue.

CASE 2:

- Added a TO on the fly without adding it to Object Repository

- The “xpath” is stored in the .csv and it is the same as in case # 1

CSVData data = findTestData(“DDT1”)

for (def index : (0…data.getRowNumbers() - 1)) {

def EmailPath = new TestObject(“Link in the email”)

def exprURL = data.internallyGetValue(“xPath”, index)

println(exprURL)

EmailPath.addProperty(“xpath”, ConditionType.EQUALS, exprURL)

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

WebUI.click(EmailPath)}

RESULT: Errors with this message:

_Unable to verify object ‘Link in the email’ is present _

_(Root cause: com.kms.katalon.core.webui.exception.WebElementNotFoundException: _

_Web element with id: ‘Link in the email’ located by _

'By.xpath: //a[@href='Problem Encountered not found)

Thank you

Andrew

Hello Andrew,
just to be sure: you are trying to find same DOM object in both cases (no change on page). Because x-paths you send as examples are not same at all.
Sorry i just want to be sure that i get it correctly.

Andrew,

I think you need to make sure your xpath is valid. You do not need Katalon Studio to verify your xpath. You should get used to alternative xpath tool. Google Chrome and Firefox has built-in function. See

Try the following steps:

1. Open Chrome and navigate to your target URL
2. Press F12 to open up Chrome DevTools
3. Switch to Console pane
4. Type

$x("//a[@href='http://clickplus103.com/clk.trk?CID=410486&AFID=423399&dwi_e=8a4030fb-3dec-4cf2-8de8-ed059b79b454']")

5. Check if the xpath expression selects what you intended or not.

3 Likes

Andrej Podhajský said:

Hello Andrew,
just to be sure: you are trying to find same DOM object in both cases (no change on page). Because x-paths you send as examples are not same at all.
Sorry i just want to be sure that i get it correctly.

Hi Andrej

This is correct - i use the same xpath in both cases. If interested i can add screen shots. But here it is in both situations:
//a[@href='http://clickplus103.com/clk.trk?CID=413000&AFID=423399&ADID=2103604’]

Please let me know if you see the some difference.

Thank you,
Andrew

kazurayam said:

Andrew,

I think you need to make sure your xpath is valid. You do not need Katalon Studio to verify your xpath. You should get used to alternative xpath tool. Google Chrome and Firefox has built-in function. See

Try the following steps:

1. Open Chrome and navigate to your target URL
2. Press F12 to open up Chrome DevTools
3. Switch to Console pane
4. Type

$x("//a[@href='http://clickplus103.com/clk.trk?CID=410486&AFID=423399&dwi_e=8a4030fb-3dec-4cf2-8de8-ed059b79b454']")

5. Check if the xpath expression selects what you intended or not.

Good Day kazurayam

Well - you are correct and it won’t recognize it via developer F12 tools.
In such case it strange it recognizes it when i define as a TO in Object Repositiory.


Thank you!
Andrew

TO-xpath-manual.png

kazurayam said:

Andrew,

I think you need to make sure your xpath is valid. You do not need Katalon Studio to verify your xpath. You should get used to alternative xpath tool. Google Chrome and Firefox has built-in function. See

Try the following steps:

1. Open Chrome and navigate to your target URL
2. Press F12 to open up Chrome DevTools
3. Switch to Console pane
4. Type

$x("//a[@href='http://clickplus103.com/clk.trk?CID=410486&AFID=423399&dwi_e=8a4030fb-3dec-4cf2-8de8-ed059b79b454']")

5. Check if the xpath expression selects what you intended or not.

Kazurayam,

OK - at this point when i run this in Chrome Dev tools console - the link being recognized.

document.querySelector(“a[href=‘http://clickplus103.com/clk.trk?CID=413000&AFID=423399&ADID=2103604’]”)

However it still won’t recognize it during the run.

com.kms.katalon.core.webui.exception.WebElementNotFoundException: Web element with id: ‘Link in the email’ located by 'By.xpath: //a[href='http://clickplus103.com/clk.trk?CID=413000&AFID=423399&ADID=2103604’\]’ not found

Note:
If i run this in console it says it is invalid function:
$x(“//a[@href=‘http://clickplus103.com/clk.trk?CID=413000&AFID=423399&ADID=2103604’]”)

Uncaught TypeError: this.oj.apply is not a function

Thank you
Andrew

Console-Verify.png

Andrew,

You should be aware which technology you are using: CSS selector or XPath.

-----------

You reported the following command succeeded:

document.querySelector("a[href='http://clickplus103.com/clk.trk?CID=413000&AFID=423399&ADID=2103604']")

The document.querySelector function accepts a string argument, which is interpreted as a CSS Selector (not as a XPath). See https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector

Your string

a[href='http://clickplus103.com/clk.trk?CID=413000&AFID=423399&ADID=2103604']

is a valid CSS Selector; it selects element with a href attribute of the specified value.

--------------------

Howerver,

com.kms.katalon.core.webui.exception.WebElementNotFoundException: Web element with id: ‘Link in the email’ located by 'By.xpath: //a[href='http://clickplus103.com/clk.trk?CID=413000&AFID=423399&ADID=2103604']' not found

this messages tells me that you are asking Katalon to interprete your string

a[href='http://clickplus103.com/clk.trk?CID=413000&AFID=423399&ADID=2103604']

as a XPath expression. Beware, your string is invalid as a XPath expression. Why invalid? Let me interprete this string as a XPath:

- The root element of your target should be (this is never the case. you should rather write ‘//a’ to seek for in the document)

- You want to select element(s) which has a child element. (this is never the case. in the Hyper Text Markup Languge specificication, there is no element defined.)

- a[href=“…”] is not legal as XPath syntax. Rather you may write a[href/text()=‘…’], which is syntactically correct, but would select nothing.

-------------------------------------

You have a few choices:

1. Change your Test Obect ‘Link in the email’; of which selector now has ‘xpath’. Change from ‘xpath’ to ‘css’. I mean, you can tell your Test Object ‘Link in the email’ to interprete your string as CSS selector, rather than XPath expression.

or

2. Keep you Test Object ‘Link in the email’ to interprete you string as a xpath expression; and change your string to be a valid XPath expression. I would presume the following string is a valid xpath for you.

//a[@href='http://clickplus103.com/clk.trk?CID=413000&AFID=423399&ADID=2103604']

-----------------------------------

If i run this in console it says it is invalid function:
**_$x(“//a[
@href='http://clickplus103.com/clk.trk?CID=413000&AFID=423399&ADID=2103604’]”)
_**Uncaught TypeError: this.oj.apply is not a function

I tried a similar $x() against the GMail page in the Chrome’s DevTool, I encountered Uncaught TypeError as well. I do not know why.

I tried $x tool in the Firefox’ F12 dev tool, and it functioned well.

So you should rather use Firefox instead of Chrome for XPath verification by $x() function

When I open other URLs in Chrome and tried DevTools $x, it functioned OK. Wow. This makes me guess that the GMail page is a very special case for $x. $x seems getting somewhat confused with the GMail page and can not deal with properly.

1 Like

kazurayam said:

Andrew,

You should be aware which technology you are using: CSS selector or XPath.

-----------

You reported the following command succeeded:

document.querySelector("a[href='http://clickplus103.com/clk.trk?CID=413000&AFID=423399&ADID=2103604']")

The document.querySelector function accepts a string argument, which is interpreted as a CSS Selector (not as a XPath). See https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector

Your string

a[href='http://clickplus103.com/clk.trk?CID=413000&AFID=423399&ADID=2103604']

is a valid CSS Selector; it selects element with a href attribute of the specified value.

--------------------

Howerver,

com.kms.katalon.core.webui.exception.WebElementNotFoundException: Web element with id: ‘Link in the email’ located by 'By.xpath: //a[href='http://clickplus103.com/clk.trk?CID=413000&AFID=423399&ADID=2103604']' not found

this messages tells me that you are asking Katalon to interprete your string

a[href='http://clickplus103.com/clk.trk?CID=413000&AFID=423399&ADID=2103604']

as a XPath expression. Beware, your string is invalid as a XPath expression. Why invalid? Let me interprete this string as a XPath:

- The root element of your target should be (this is never the case. you should rather write ‘//a’ to seek for in the document)

- You want to select element(s) which has a child element. (this is never the case. in the Hyper Text Markup Languge specificication, there is no element defined.)

- a[href=“…”] is not legal as XPath syntax. Rather you may write a[href/text()=‘…’], which is syntactically correct, but would select nothing.

-------------------------------------

You have a few choices:

1. Change your Test Obect ‘Link in the email’; of which selector now has ‘xpath’. Change from ‘xpath’ to ‘css’. I mean, you can tell your Test Object ‘Link in the email’ to interprete your string as CSS selector, rather than XPath expression.

or

2. Keep you Test Object ‘Link in the email’ to interprete you string as a xpath expression; and change your string to be a valid XPath expression. I would presume the following string is a valid xpath for you.

//a[@href='http://clickplus103.com/clk.trk?CID=413000&AFID=423399&ADID=2103604']

-----------------------------------

If i run this in console it says it is invalid function:
**_$x(“//a[
@href='http://clickplus103.com/clk.trk?CID=413000&AFID=423399&ADID=2103604’]”)
_**Uncaught TypeError: this.oj.apply is not a function

I tried a similar $x() against the GMail page in the Chrome’s DevTool, I encountered Uncaught TypeError as well. I do not know why.

I tried $x tool in the Firefox’ F12 dev tool, and it functioned well.

So you should rather use Firefox instead of Chrome for XPath verification by $x() function

When I open other URLs in Chrome and tried DevTools $x, it functioned OK. Wow. This makes me guess that the GMail page is a very special case for $x. $x seems getting somewhat confused with the GMail page and can not deal with properly.

Hi kazurayam

Actually i have several updates since the last several days.

You are correct with xpath syntax provided and this was my mistake.
Here is what worked (in case someone else needs to address same question):

//a[@href=‘url’]

Here is the exact part of the code:

def EmailPath = new TestObject(“Link in the email”)

def exprURL = data.internallyGetValue(“xPath”, reverse)

EmailPath.addProperty(“xpath”, ConditionType.EQUALS, exprURL)

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

WebUI.click(EmailPath)

I also had to add some logic for the going thru emails sent and order they are arrived.
Not perfect but it works for now. Let me know if you have a better or precise solution.

Problem to Resolve:

Emails sent from the .csv in this order:
- email 1
- email 2
- email **n

**Emails shown in opposite order in the Inbox:
- email n
- email 2
- email 1
I used the same .csv and same loop. Just have 2 variables. One starts from the 1st row of the file and increments all the way to the last record in the file. The other variable works in opposite direction.
Probably trivial for many advance folks here, but i did it by myself and first time.

Thank you for all your guidance!
Andrew

Andrew,

Let me know if you have a better or precise solution.

Please have a look at the following tips:

http://forum.katalon.com/discussion/7578/a-custom-keyword-which-returns-a-list-of-selenium-webelement-from-a-web-page?new=1

1 Like

kazurayam said:

Andrew,

Let me know if you have a better or precise solution.

Please have a look at the following tips:

http://forum.katalon.com/discussion/7578/a-custom-keyword-which-returns-a-list-of-selenium-webelement-from-a-web-page?new=1

Good Evening kazurayam

I reviewed your solution. Also downloaded and executed and i think i understand and could follow.
Anyways - if you feel it is a different topic, i can create one.

Seems it resolve the problem on the single element validation (multiple data).
Here is the case below and i feel it will require different approach.

I have a table that has withing sub-table with multiple columns and rows. Well, i care only about 3 columns (per row).


Expected_Result (string) = “415074 Money Map Press (Crypto C)… 1”.

The goal is to read the values from each row (from the above 3 columns) also into a string.
Say Actual_Result.

Here is the xpath for each item:

/html/body/table/tbody/tr[1]/td/div/div[8]/div/table/tbody/tr[6]/td[3]

/html/body/table/tbody/tr[1]/td/div/div[8]/div/table/tbody/tr[6]/td[4]/div/div/a

/html/body/table/tbody/tr[1]/td/div/div[8]/div/table/tbody/tr[6]/td[7]/a

And this is where i’m lost

List<String> cs = CustomKeywords.'com.kazurayam.ksbackyard.FindElementsByXPath.getElementContentsAsList'('//select[@name="facility"]/option')
for (int i = 0; i < cs.size(); i++) {
    WebUI.verifyEqual(cs[i], expectedContents[i])} 

Thank you
Andrew

Table-Row-As-String-Verify.png

Please try the following snippet as a Test Case

import org.openqa.selenium.By
import org.openqa.selenium.WebElement
List<Map<String,String> expectedContents = [
    ["CID":"415074", "Campain":"Money Map Press", "Clicks":"1"]
]
List<WebElement> trList = CustomKeywords.    'com.kazurayam.ksbackyard.FindElementsByXPath.getWebElementsAsList'(        '/html/body/table/tbody/tr[1]/td/div/div[8]/div/table/tbody/tr')
for (int i = 0; i < trList.size(); i++) {
    String cid = trList[i].findElement(By.xpath('td[3]')).getText()
    String campain = trList[i].findElement(By.xpath('td[4]/div/div/a')).getText()
    String clicks = trList[i].findElement(By.xpath('td[7]/a')).getText()
    WebUI.verifyEqual(cid, expectedContents[i].CID)
    WebUI.verifyEqual(campain, expectedContents[i].Campain)
    WebUI.verifyEqual(clicks, expectedContents[i].Clicks)
}
1 Like

kazurayam said:

Please try the following snippet as a Test Case

import org.openqa.selenium.By

import org.openqa.selenium.WebElement
List<Map<String,String> expectedContents = [
[“CID”:“415074”, “Campain”:“Money Map Press”, “Clicks”:“1”]
]
List trList = CustomKeywords. ‘com.kazurayam.ksbackyard.FindElementsByXPath.getElementContentsAsList’( ‘/html/body/table/tbody/tr[1]/td/div/div[8]/div/table/tbody/tr’)
for (int i = 0; i < trList.size(); i++) {
String cid = trList[i].findElement(By.xpath(‘td[3]’)).getText()
String campain = trList[i].findElement(By.xpath(‘td[4]/div/div/a’)).getText()
String clicks = trList[i].findElement(By.xpath(‘td[7]/a’)).getText()
WebUI.verifyEqual(cid, expectedContents[i].CID)
WebUI.verifyEqual(campain, expectedContents[i].Campain)
WebUI.verifyEqual(clicks, expectedContents[i].Clicks)
}


  
  

  

Thank you kazurayam!

It won’t execute because of **_because (of) java.lang.ClassNotFoundException: com.kazurayam.ksbackyard.FindElementsByXPath

_**I found the class source code you listed in the other post, but still get this error.
I will have to figure out why it won’t let me even including **package com.kazurayam.ksbackyard

**Thank you!
Andrew

This screenshot shows how the source code of the com.kazurayam.ksbackyard.FindElementsByXPath is laid in my environment

17864.png

1 Like

kazurayam said:

This screenshot shows how the source code of the com.kazurayam.ksbackyard.FindElementsByXPath is laid in my environment

Thank you Kazurayam!

Trying it now…

Andrew

kazurayam said:

This screenshot shows how the source code of the com.kazurayam.ksbackyard.FindElementsByXPath is laid in my environment

Kazurayam

I have your entire class in the “FindElementsByXPath.groovy”.

But the test fails on this line within the loop:

String cid = trList[i].findElement(By.xpath(‘td[3]’)).getText()

...cid = trList\[i\].findElement(org.openqa.selenium.By.xpath("td\[3\]")).getText()  

“groovy.lang.MissingMethodException: No signature of method: java.lang.String.findElement() is applicable for argument types: (org.openqa.selenium.By$ByXPath) values: [By.xpath: td[3]]”

I have tried to make changes in the above section, but no luck.

Appreciate!!
Andrew

I guess you have

List<String> trList = CustomKeywords.....................

This is wrong.
trList must be an instance of List<WebElement>, not List<String>.

So, change it to:

List<WebElement> trList = CustomKeywords...................

kazurayam said:

I guess you have

List<String> trList = CustomKeywords.....................

This is wrong.
trList must be an instance of List<WebElement>, not List<String>.

So, change it to:

List<WebElement> trList = CustomKeywords...................

Kazurayam

I have this:

List trList = CustomKeywords.

'com.kazurayam.ksbackyard.FindElementsByXPath.getElementContentsAsList'(

    '/html/body/table/tbody/tr\[1\]/td/div/div\[8\]/div/table/tbody/tr')  

Thank you
Andrew

debug062718.png

Andrew,

I made one more GitHub repository which demonstrates how to make use of a List<org.openqa.selenium.WebElement> in a Katalon test case. See

or directly

I intended this new example to be informative for you.

1 Like

Andrew,

“groovy.lang.MissingMethodException: No signature of method: java.lang.String.findElement() is applicable for argument types: (org.openqa.selenium.By$ByXPath) values: [By.xpath: td[3]]”

It is difficult for me to find an answer straight to your problem because I do not have access to your Application Under Test and your codes. Please have a look at my new study mentioned above. I hope my study may give you a clue.

Andrew,

I thought I can abstract your requirement to a simpler case. You just want to iterate over a elements and elements of a : 2 dimensional iteration.

Then there is a much simpler approach. You do not need to study org.openqa.selenium.WebElement. You just want to use Parameterized Test Object in Katalon Studio.

The Web Page as testbed is like this:

<html>
<body>
    <table class="table">
        <thead>
            <tr><th>found</th><th>A</th><th>B</th><th>C</th></tr>
        </thead>
        <tbody>
            <tr><th>1</th><td>A1</td><td><span>B1</span></td><td><a href="#">C1</a></td></tr>
            <tr><th>2</th><td>A2</td><td><span>B2</span></td><td><a href="#">C2</a></td></tr>
            <tr><th>3</th><td>A3</td><td><span>B3</span></td><td><a href="#">c3</a></td></tr>
        </tbody>
    </table>
</div>
</body>
</html>

I made a test case is like this:

import static com.kms.katalon.core.testobject.ObjectRepository.findTestObject
import com.kms.katalon.core.model.FailureHandling as FailureHandling
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
WebUI.openBrowser('')
WebUI.setViewPortSize(703, 347)
WebUI.navigateToUrl('http://demoaut-mimic.kazurayam.com/7520_simpler_testbed.html')
WebUI.verifyElementPresent(findTestObject('Page_Discussion 7520/table'),
    10, FailureHandling.STOP_ON_FAILURE)
List<List<String>> expectedContents = [
    ["A1", "B1", "C1"],
    ["A2", "B2", "C2"],
    ["A3", "B3", "C3"],
]
for (int i = 0; i < expectedContents.size(); i++) {
    for (int j = 0; j < expectedContents[i].size(); j++) {
        String cellValue = WebUI.getText(findTestObject(
            'Page_Discussion 7520/cell', ['trIndex':i + 1, 'tdIndex':j + 1]))
        WebUI.verifyEqual(expectedContents[i][j], cellValue)
    }
}
WebUI.closeBrowser()

I wanted to check if the Web page displays A1, B1, C1, A2, B2, C2, A3, B3, C3 in table as I wrote in the testcase.

I made a Test Object ‘Page_Discussion 7520/cell’ like this:


Please note this Test Object has such XPath as selector:

//table/tbody/tr[${trIndex}]/td[${tdIndex}]

${trIndex} is the place holder for the index of the

elements in the
.
${tdIndex} is the place holder for the index of the .

These place holders will be interpolated by the Test Case runtime.
When executed, I got following log:

[INFO]   - Found 1 web elements with id: 'Object Repository/Page_Discussion 7520/cell' located by 'By.xpath: //table/tbody/tr[1]/td[1]' in '30' second(s)
...
[PASSED] - Text of object 'Object Repository/Page_Discussion 7520/cell' is: 'A1'
...
[INFO] - Found 1 web elements with id: 'Object Repository/Page_Discussion 7520/cell' located by 'By.xpath: //table/tbody/tr[1]/td[2]' in '30' second(s)
...
[INFO]   - Found 1 web elements with id: 'Object Repository/Page_Discussion 7520/cell' located by 'By.xpath: //table/tbody/tr[1]/td[3]' in '30' second(s)
...
[PASSED] - Text of object 'Object Repository/Page_Discussion 7520/cell' is: 'C1'
...
[INFO]   - Found 1 web elements with id: 'Object Repository/Page_Discussion 7520/cell' located by 'By.xpath: //table/tbody/tr[3]/td[3]' in '30' second(s)
...
[FAILED] - Unable to verify equal between actual object 'C3' and expected object 'c3' (Root cause: Actual object 'C3' and expected object 'c3' are not equal)

I expected ‘C3’ but the page displayed ‘c3’, therefore the test case failed.

You can clone out this demo form GitHub repository: GitHub - kazurayam/KatalonDiscussion7520 and see Test Case ‘TC2’

# Disucssion

Paremetarizing feature of Test Object is flexible enough; You can make more deeply nested iteration. You can write as many dimensional parameterized XPath expression as you want.

For example, if you have 2 or more in the target page, you need 3 dimensional parameterized XPath like this:

//table[$tblIndex]/tbody/tr[${trIndex}]/td[${tdIndex}]

or if you have a table which contains inner tables, you need 4 dimensional parameterized XPath like this:

//table[@id="T1"]/tbody/tr[${outerTrIndex}]/td[${outerTdIndex}]//table/tbody/tr[${innerTrIndex}]/td[${innerTdIndex}]

# Performance issue

The above approach has a performance issue. It make frequent call to WebUI.getText(TestObject). Every single WebUI.getText() makes a request/reply session between Katalon Studio and Browser. It can be very slow.
If you find this approach too slow, then you should look at using

List WebUI.findWebElements(TestObject)

https://api-docs.katalon.com/com/kms/katalon/core/webui/keyword/WebUiBuiltInKeywords.html#findWebElements(TestObject,%20int)

testobject_cell.png

7520.PNG

elements in a
2 Likes