If ranorex recalculate XPath and how work with it?

Ask general questions here.
Maria
Posts: 6
Joined: Wed Jun 20, 2018 11:34 am

If ranorex recalculate XPath and how work with it?

Post by Maria » Wed Jun 20, 2018 12:10 pm

I have noticed one thing:
When I find element with Find or FindSingle function like:
WebElement first = {some element from repo with given XPath};
WebElement second = first.FindSingle("/{pathToFind}");

Then print path of second element like:
Report.Log(ReportLevel.Info, "Info", second.getPath());

I get almost completely different path from I used for looking.

Seems when ranorex create new instance of WebElement it calculate path with some specific algorithm and store it. And I get this calculated by Ranorex path instead of my.

The problem is:
we have project with same id inside html (we can't change it because use some library and shadow dom also allows same ids).
I find some element -> do click -> other element gets this click.
If I check my found element's path it is not the same as I used for searching. And seems like ranorex while calculate path uses ids to make specific path. But in case with many same ids in html it won't work.
So when I try to click -> ranorex find element by some calculated path (what I can't influence on) -> find wrong element (first with this wrong calculated path) -> click it.

So seems like ranorex isn't able to guarantee that element I found with some path and store in some WebElement variable will be the same when I will click on it or do other things.

Is there way to say Ranorex store exact path I wrote for searching element?

User avatar
odklizec
Ranorex Guru
Ranorex Guru
Posts: 3908
Joined: Mon Aug 13, 2012 9:54 am
Location: Zilina, Slovakia

Re: If ranorex recalculate XPath and how work with it?

Post by odklizec » Fri Jun 22, 2018 8:15 am

Hi,

Could you please post an example of xpath returned by FindSingle and expected xapth (as stored in repo)? Are you sure, that the xpath of repo element (for first webelement) was not manually edited? I mean, is the xpath in repo generated by Ranorex (recording or track) and not entered manually?

I see no reason why would FindSingle return different xpath, than is stored in repo (unless the repo xpath has been manually manipulated)?

BTW, I just noticed that the GetPath method offers some overloads, where you can define the PathBuildMode. So what you should do is to verify your actual xpath build mode (Settings >> Advanced tab >> xpath generation mode) and use the same mode for GetPath, like this:
this uses actual xpath generation mode from settings:

Code: Select all

Report.Log(ReportLevel.Info, "Info", second.Element.GetPath(PathBuildMode.Default).ToString());
or use specific build mode:

Code: Select all

Report.Log(ReportLevel.Info, "Info", second.Element.GetPath(PathBuildMode.StepCostReduce).ToString());
Pavel Kudrys
Ranorex explorer at Descartes Systems

Please add these details to your questions:
  • Ranorex Snapshot. Learn how to create one >here<
  • Ranorex xPath of problematic element(s)
  • Ranorex version
  • OS version
  • HW configuration

Maria
Posts: 6
Joined: Wed Jun 20, 2018 11:34 am

Re: If ranorex recalculate XPath and how work with it?

Post by Maria » Fri Jun 22, 2018 11:50 am

I mean this situation:

Code: Select all

//propertyPanel is element from repo

WebElement targetProperty = propertyPanel.FindSingle(propertyPanel.GetPath() + "//tag[@data-property-name='"+propName+"']");
WebElement actionsBtn = targetProperty.FindSingle(targetProperty.GetPath() + "//ancestor-or-self::tag[@data-property-name='"+propName+"']//ancestor::div//tag[@data-purpose='show-actions' ]");
      
Report.Log(ReportLevel.Info, "Debug/info", "GIVEN PATH for actionsBtn element: " + targetProperty.GetPath() + "//ancestor-or-self::tag[@data-property-name='"+propName+"']//ancestor::div//tag[@data-purpose='show-actions' and @data-property-name='"+propName+"']");
Report.Log(ReportLevel.Info, "Debug/info", "FOUND actionsBtn element: " + actionsBtn.GetPath());
As a result I get:
GIVEN PATH for actionsBtn element: /dom[@domain='localhost:8082']//div[#'propertyPanel']/tag[2]/tag[@tagname='core-collapse']/tag[5]//ancestor-or-self::tag[@data-property-name='font-size']//ancestor::div//tag[@data-purpose='show-actions' and @data-property-name='font-size']

FOUND actionsBtn element: /dom[@domain='localhost:8082']//div[#'propertyPanel']/?/?/tag[@tagname='core-collapse']/tag[5]/div/div[2]/tag[@tagname='core-icon-button']


What I expect:
path for found element should be: path for propertyPanel element from repo + path what I passed to first FindSingle() + path what I passed to second FindSingle()
(this entire path calculate for "GIVEN PATH" print)

User avatar
odklizec
Ranorex Guru
Ranorex Guru
Posts: 3908
Joined: Mon Aug 13, 2012 9:54 am
Location: Zilina, Slovakia

Re: If ranorex recalculate XPath and how work with it?

Post by odklizec » Mon Jun 25, 2018 8:07 am

Hi,

Well, I'm afraid, that the things like 'ancestor' or 'ancestor-or-self' are manually added xpath operators and there is no option neither in Find or GetPath method to preserve them? The GetPath method simply builds the path from the provided element, using selected PathBuildMode. I don't see a practical reason insisting on keeping the xpath as used in repo? I mean, what is the practical reason for this?

The best you can probably do, is to get only the xpath of found element, starting from provided element, e.g. like this:

Code: Select all

WebElement targetProperty = propertyPanel.FindSingle(".//tag[@data-property-name='"+propName+"']");
// this should return only the xpath from targetElement (e.g. "//tag[@data-property-name='PropertyName']"...
string pathFromTargetProperty = targetProperty.Element.GetPath(PathBuildMode.Default, targetProperty.Element).ToString();
Then you can merge the repo xpath (passed as a plain string) with path returned by GetPath...

Code: Select all

string pathFromRepo = "/dom[@domain='localhost:8082']//div[#'propertyPanel']/tag[2]/tag[@tagname='core-collapse']/tag[5]//ancestor-or-self::tag[@data-property-name='font-size']//ancestor::div//tag[@data-purpose='show-actions' and @data-property-name='font-size']";
string mergedPath = pathFromRepo + pathFromTargetProperty; 
But it's not very practical to use the xpath in method as a plain string, because if you change the original xpath in repo, you must manually change the passed xpath in method too. I would personally pass the element as Adapter or RepoItemInfo and don't really care about the format/content of path returned by GetPath ;)
Pavel Kudrys
Ranorex explorer at Descartes Systems

Please add these details to your questions:
  • Ranorex Snapshot. Learn how to create one >here<
  • Ranorex xPath of problematic element(s)
  • Ranorex version
  • OS version
  • HW configuration

Maria
Posts: 6
Joined: Wed Jun 20, 2018 11:34 am

Re: If ranorex recalculate XPath and how work with it?

Post by Maria » Mon Jun 25, 2018 7:00 pm

Pavel, thank you for your answers!

I can't store this elements (like target property) in repo.
propName and other variables for create entire path I have only in runtime.

I don't see a practical reason insisting on keeping the xpath as used in repo?
- just because ranorex finds wrong element in some cases :)

If we take example from my last post and add:

Code: Select all

actionsBtn.Click();
what will happen?

As I understand:
1) ranorex find element using some internal calculated path (I can assume this path I can get with GetPath())
2) click on it

Before we have seen that my path and path created by ranorex is two different pathes. So there are cases and danger to get click on wrong element.

Why it can be?
When on page we have many elements with same id but different othere paramenets. I can include other parameters(like some special attribute value) to path to identify correct element, but ranorex will change it. As long as id have big weight for path (it is my suggestion) my addition parameters will be ignore. So I get click on wrong element.

I tried to check ranorex code, but don't know how does it works, so I don't know how can I correct it:

Code: Select all

<>c__DisplayClass142_.findSingle
it is from TryFindInternal method of Element class.
I tried to find out it from support but had no luck there :(

ahoisl
Certified Professional
Certified Professional
Posts: 125
Joined: Fri Sep 07, 2007 8:16 am

Re: If ranorex recalculate XPath and how work with it?

Post by ahoisl » Mon Jun 25, 2018 8:23 pm

I want to jump into that conversation and add a few things...
Maria wrote:I can't store this elements (like target property) in repo.
propName and other variables for create entire path I have only in runtime.
You could still store everything in a repository with variables for RanoreXPaths and change the repository variables at runtime. The repository provides a nice code interface to set the variables and will accordingly use the variable values when searching for the individual repository items. IMHO this is the best and recommended way to go in Ranorex. For more information, see the following chapter in the user guide:
https://www.ranorex.com/help/latest/les ... en-testing

The alternative way (IMHO not recommended) is to get the RanoreXPaths from the repository and add your own parts. This approach lacks help from Ranorex Spy to edit the paths, i.e. you need to do everything manually in code.
The way you tried to get the parent path with the Adapter.GetPath method will get you a newly generated RanoreXPath for the element, though, not the one you used in the repository. This path will still be correct/unique at that time, so it should IMHO work in theory.

To get the real path from the repository item, use the RepositoryItem.AbsolutePath of the corresponding repository item info object instead, e.g.:
var propertyPanelPath = repo.Folder.propertyPanelInfo.AbsolutePath;
Still, I would urge you to stick with the Ranorex repository approach with repository variables to get all benefits from the Ranorex tools.

Regards,
Alex
Ranorex Team

User avatar
odklizec
Ranorex Guru
Ranorex Guru
Posts: 3908
Joined: Mon Aug 13, 2012 9:54 am
Location: Zilina, Slovakia

Re: If ranorex recalculate XPath and how work with it?

Post by odklizec » Tue Jun 26, 2018 7:53 am

Maria wrote: I don't see a practical reason insisting on keeping the xpath as used in repo?
- just because ranorex finds wrong element in some cases :)
If Ranorex finds other than expected element, the problem is most probably with the xpath (either the repo one) or more probably the one you are using for Find. It's most probably not unique enough and hence Ranorex finds something else than expected.

Could you please upload a Ranorex snapshot of the problematic element (the one you want to find) and also the Ranorex snapshot, taken at a time of incorrect find? Simply add Report.Snapshot method to your code, before/after Find. Then please post both snapshots and complete xpath from repo and xpath as found by Find method. Only this way we may find what's really wrong and how to improve your xpaths. Thanks.
Pavel Kudrys
Ranorex explorer at Descartes Systems

Please add these details to your questions:
  • Ranorex Snapshot. Learn how to create one >here<
  • Ranorex xPath of problematic element(s)
  • Ranorex version
  • OS version
  • HW configuration

Maria
Posts: 6
Joined: Wed Jun 20, 2018 11:34 am

Re: If ranorex recalculate XPath and how work with it?

Post by Maria » Tue Jun 26, 2018 9:17 am

Hi, Alex and Pavel

Thank you for you attention to my question.

Alex, I have tried store elements with variables in repo, but got issues. Most of the base elements I store in repo, but in my case there are elements that works not so good if I store it in repo.
Will try again store them in repo and write here more information.

Pavel, my path is unique, but calculated by Ranorex isn't enough unique in my case. I sent code example above:

Code: Select all

WebElement targetProperty = propertyPanel.FindSingle(propertyPanel.GetPath() + "//tag[@data-property-name='"+propName+"']");

WebElement actionsBtn = targetProperty.FindSingle(targetProperty.GetPath() + "//ancestor-or-self::tag[@data-property-name='"+propName+"']//ancestor::div//tag[@data-purpose='show-actions']");

Report.Log(ReportLevel.Info, "Debug/info", "GIVEN PATH for actionsBtn element: " + targetProperty.GetPath() + "//ancestor-or-self::tag[@data-property-name='"+propName+"']//ancestor::div//tag[@data-purpose='show-actions' and @data-property-name='"+propName+"']");
Report.Log(ReportLevel.Info, "Debug/info", "FOUND actionsBtn element: " + actionsBtn.GetPath());
actionsBtn.Click();
it is part of method from code library.
If I pass different propNames I still get click for the same element.
Log will look like this:

Code: Select all

//for first method run with propName = "font-size"
GIVEN PATH for actionsBtn element: /dom[@domain='localhost:8082'']//div[#'propertyPanel']/tag[2]/tag[@tagname='core-collapse']/tag[5]//ancestor-or-self::tag[@data-property-name='font-size']//ancestor::div//tag[@data-purpose='show-actions' and @data-property-name='font-size']  

FOUND actionsBtn element: /dom[@domain='localhost:8082'']//div[#'propertyPanel']/?/?/tag[@tagname='core-collapse']/tag[5]/div/div[2]/tag[@tagname='core-icon-button']  

//for second method run with propName = "font-family"
GIVEN PATH for actionsBtn element: /dom[@domain='localhost:8082']//div[#'propertyPanel']/tag[2]/tag[@tagname='core-collapse']/tag[6]//ancestor-or-self::tag[@data-property-name='font-family']//ancestor::div//tag[@data-purpose='show-actions' and @data-property-name='font-family'] 

FOUND actionsBtn element: /dom[@domain='localhost:8082']//div[#'propertyPanel']/?/?/tag[@tagname='core-collapse']/tag[5]/div/div[2]/tag[@tagname='core-icon-button'] 

As you can see found pathes for both cases same (and wrong in my case). And exactly element with path from "found" part get click in both cases.

I just want to explain that I don't need result of GetPath() here for my test logic, but it is way to see what element get click.
GetPath() it is just way for me to understand what element will get click, because it is obvious it is not element whith path I used for Find or FindSingle function.

Do you need snapshoot still? I can do it little bit later. Will think how beter do it more informative.

User avatar
odklizec
Ranorex Guru
Ranorex Guru
Posts: 3908
Joined: Mon Aug 13, 2012 9:54 am
Location: Zilina, Slovakia

Re: If ranorex recalculate XPath and how work with it?

Post by odklizec » Tue Jun 26, 2018 9:39 am

Yes, the snapshot would be most helpful. It would give us a better picture of your GUI and we may eventually suggest better xpaths ;)
Pavel Kudrys
Ranorex explorer at Descartes Systems

Please add these details to your questions:
  • Ranorex Snapshot. Learn how to create one >here<
  • Ranorex xPath of problematic element(s)
  • Ranorex version
  • OS version
  • HW configuration

Maria
Posts: 6
Joined: Wed Jun 20, 2018 11:34 am

Re: If ranorex recalculate XPath and how work with it?

Post by Maria » Fri Jun 29, 2018 11:55 am

Pavel,
started to do snapsot. I have to pass element to Report.Snapsot(). I can't do it before I find it =)

I think I explained not so clear.
I have to find element not from repo but from code using FindSingle() function.

I have like chane in code:
baseElement from repo
then: newElement = baseElement.FindSingle("some additional path")
and so on


then I do (for debug) newElement.GetPath() and expect: baseElement path (from repo) + "some additional path".
But have different value. And this path can point to other element then path what I expect.
No questions about baseElement path. It is correct before and after FindSingle() and doesn't change.



Alex,
thank you for notice about variable in repo. I tried to use it when started learn Ranorex and then forgot about it. Changed to element from repo + variables. It works good for this case.
But I still have questions how Ranorex works with elements not from repo

ahoisl
Certified Professional
Certified Professional
Posts: 125
Joined: Fri Sep 07, 2007 8:16 am

Re: If ranorex recalculate XPath and how work with it?

Post by ahoisl » Fri Jun 29, 2018 12:01 pm

Maria wrote:Alex,
thank you for notice about variable in repo. I tried to use it when started learn Ranorex and then forgot about it. Changed to element from repo + variables. It works good for this case.
But I still have questions how Ranorex works with elements not from repo
Ranorex works the same way for repository and code items/elements. However, what you maybe misunderstood is that elements don't have a path assigned, nor do they store a path. The "GetPath" method will newly generate a path for the element and this can be different to the path you searched the element with - just because the path generation does not necessarily do the same things as you in code :-)

If you really want to get the paths from the repository, use the RepoItemInfo object associated with the repository item as explained in my previous post. And one thing to add: if you manipulate paths in code, you can use the RxPath.Concat method to combine them.

Regards,
Alex
Ranorex Team

Maria
Posts: 6
Joined: Wed Jun 20, 2018 11:34 am

Re: If ranorex recalculate XPath and how work with it?

Post by Maria » Mon Jul 02, 2018 10:44 am

Alex, thank you for your answer!

You are right, I thought path is stored for each element and it is newly generated path.
Do you know how ranorex stores element without path? I think should be some unique identifier there.

ahoisl
Certified Professional
Certified Professional
Posts: 125
Joined: Fri Sep 07, 2007 8:16 am

Re: If ranorex recalculate XPath and how work with it?

Post by ahoisl » Mon Jul 02, 2018 11:07 am

Maria wrote:Do you know how ranorex stores element without path? I think should be some unique identifier there.
When you search for a RanoreXPath, Ranorex returns an Element or Adapter instance (Adapters just wrap Elements with additional information/API). You can then just use that instance and Ranorex will internally keep the connection to the actual UI element in your AUT - how this works is technology dependent and part of our internal know-how :D

Regards,
Alex
Ranorex Team