Home > Back-end >  How to iterate a values in the table including column headers and cells in Java Selenium to select a
How to iterate a values in the table including column headers and cells in Java Selenium to select a

Time:03-10

I'm trying to click any cell value by matching title.The title can be present in any position. In this instance "Robert".

<div tabindex="-1" role="gridcell" aria-selected="false" aria-readonly="true" aria-required="false"  data-id="cell-0-4" id="Grid1271ed7b-3f36-d12c-803a-d560961d8724-id-cell-0-4" data-lp-id="MscrmControls.Grid.ReadOnlyGrid|entity_control|account|00000000-0000-0000-00aa-000010001210|contact|contact_customer_accounts|cc-grid|cc-grid-cell|cell-0-4" aria-colindex="4" title="---" style="left: 343px; top: 0px; width: 124px; height: 40px; padding-left: 7px !important; padding-right: 10px; padding-bottom: 2px; padding-top: 2px; line-height: 35px; background: rgb(255, 255, 255);"><span role="presentation" style="color: rgb(51, 51, 51);">---</span></div>
Robert ---

    <div tabindex="-1" role="gridcell" aria-selected="false" aria-readonly="true" aria-required="false"  data-id="cell-0-4" id="Grid1271ed7b-3f36-d12c-803a-d560961d8724-id-cell-0-4" data-lp-id="MscrmControls.Grid.ReadOnlyGrid|entity_control|account|00000000-0000-0000-00aa-000010001210|contact|contact_customer_accounts|cc-grid|cc-grid-cell|cell-0-4" aria-colindex="4" title="---" style="left: 343px; top: 0px; width: 124px; height: 40px; padding-left: 7px !important; padding-right: 10px; padding-bottom: 2px; padding-top: 2px; line-height: 35px; background: rgb(255, 255, 255);"><span role="presentation" style="color: rgb(51, 51, 51);">---</span></div>
<div tabindex="0" role="gridcell" aria-selected="false" aria-readonly="true" aria-required="false"  data-id="cell-0-2" id="Grid1271ed7b-3f36-d12c-803a-d560961d8724-id-cell-0-2" data-lp-id="MscrmControls.Grid.ReadOnlyGrid|entity_control|account|00000000-0000-0000-00aa-000010001210|contact|contact_customer_accounts|cc-grid|cc-grid-cell|cell-0-2" aria-colindex="2" title="Robert" style="left: 45px; top: 0px; width: 149px; height: 40px; padding-left: 7px !important; padding-right: 10px; padding-bottom: 2px; padding-top: 2px; line-height: 35px; background: rgb(255, 255, 255);"><span role="presentation" style="color: rgb(51, 51, 51);">Robert</span></div>
<div tabindex="-1" role="gridcell" aria-selected="false" aria-readonly="true" aria-required="false"  data-id="cell-0-4" id="Grid1271ed7b-3f36-d12c-803a-d560961d8724-id-cell-0-4" data-lp-id="MscrmControls.Grid.ReadOnlyGrid|entity_control|account|00000000-0000-0000-00aa-000010001210|contact|contact_customer_accounts|cc-grid|cc-grid-cell|cell-0-4" aria-colindex="4" title="---" style="left: 343px; top: 0px; width: 124px; height: 40px; padding-left: 7px !important; padding-right: 10px; padding-bottom: 2px; padding-top: 2px; line-height: 35px; background: rgb(255, 255, 255);"><span role="presentation" style="color: rgb(51, 51, 51);">---</span></div>

CodePudding user response:

Do you mean finding by the title or some text e.g //[text()[contains(.,'Robert')]] or like //[contains(@title, 'Robert')] to get the element?

Or to grab a particular cell that is nested above or below? - it may be possible to use some sort of selector using ancestor / descendant or to narrow in on the cell based on the particular text but like hfontanez says you will need to create selectors that rely on something like the title or some pattern to return the cell or grid row/column relative to where the title is in the DOM.

CodePudding user response:

There is simply not enough information to precisely answer the question. So I will provide two general solutions. One of them should work.

Working with iframes

It is possible your "table" is rendered inside an iframe. Elements contained within an iframe cannot be located unless your web driver is focusing on the iframe first. With Selenium, to switch to iframe you must do something like this to wait a maximum time of 10 seconds, polling every 100 milliseconds

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(x), Duration.ofMillis(100)); // Selenium 4.x 
wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(LOCATOR)));

If the above succeeds, you are ready to interact with the desired component. Of course, in the above snippet, LOCATOR is whichever type of locator you wish to use. For example, By.xpath("some_xpath_string_here").

Once you are finished interacting with the components inside the iframe, you MUST switch out of it to interact with the components on the page. To do this, you instruct the driver to switch to the parent frame in the DOM.

driver.switchTo().parentFrame();

You must do this even if you refresh the current page or load a new one. Because of this, it is typically a good idea to put this inside a finally block.

Locating the elements

Whether the elements you need to interact with are inside of an iframe or not, creating a strategy for locating elements on a page is not always trivial. For example, one of the easiest ways to locate components on a page is by id. The problem is that IDs are not always easy to predict. For example, in the OPs case, it seems like UUID is used to generate the ID. So, in this case, it is unlikely that locating by ID is an option. Although there are cases when obtaining multiple results is desirable, in this case, our locator should yield a single result. An XPath expression such as //div[@tabindex=0] (in this page) will locate at the moment of this post, 5 results. However, there is only one match inside the iframe. While testing this XPath expression using Chrome dev tools doesn't make this distinction, the WebDriver API does because this is how the specification is written. Therefore, if I switch to the iframe and then attempt to locate the table row with that given tab index, the code will only locate one. If we attempt the same without switching to the iframe, the code will locate 4 components, but will return the very first one it encountered in the DOM from the top of the document. In this case, that will be the question upvote/downvote count.

But, even though the XPath expression I created for this example is unique for the elements rendered inside the iframe, in a more realistic case it might be necessary to further refine out expression to match a more specific case. I believe in this case, that will be the name in the cell. Therefore, my refined expression should be //div[@tabindex=0]/span[text()='Robert'].

  • Related