Locate element text with continually changing id's and classes

Hi,

Am I missing an easy way to check a text value appearing at elements without using class or id.

e.g. I want to check “mytext” appears on the page at a given element:

<td _ngcontent-ng-cli-universal-c123="">mytext</td>

…below is the XPATH and script but will not work consistently as the generated HTML id or class/css are always random (but the text is always the same at this location):

Element Should Contain    //*[@id="random_id_123"]/div/table/tbody/tr[1]/td[3]    mytext

I don’t really want to use:

Page Should Contain    mytext



Angular 12
Python 3.7.8
requests                               2.26.0
robotframework                         4.1.1
robotframework-extendedrequestslibrary 0.5.5
robotframework-pythonlibcore           3.0.0
robotframework-seleniumlibrary         5.1.3
selenium                               4.0.0
urllib3                                1.26.7

I would search for a slightly different xpath than

//*[@id="random_id_123"]/div/table/tbody/tr[1]/td[3]

Just some questions I would ask … Is there some sort of stable page structure before //*[@id="random_id_123"]? Is there any other tables within the page?

Hi. There are no other tables on this page and this is the same situation for all HTML other than tables where the id and css class now change every time the app loads a page. I wonder if this is a limitation of Robot Famework to work with an SPA built with Angular.

Then you could just target the table element and the specific row and cell?

1 Like

It’s all HTML markup at the end of the day. The underlying markup generator implementation does not really matter. It could be Angular, React, Vue…

If you are dealing with a very dynamic web application, Robot Framework Browser could be interesting. It can automatically wait for elements to appear, etc. Less code to write compared to SeleniumLibrary in many cases.

1 Like

I would recommend using the “contains” function in your xpath, usually all randomly generated id’s have some part that does not change

So

//element[contains(@id,“part-of-id-that-is-allways-same”]

If it catches some secondary element just add “and not”

//element[contains(@id,“stuff”) and not(contains(@class, id, whatever,“part-thats-present-in-that-other-element”)]

And you should avoid using *

2 Likes

Thank you thats very useful