0

I have HTML that looks like this:

<table id="data-table" class="table table-striped table-bordered table-hover dataTable no-footer" role="grid" style="width: 100%;">
    <thead>
        <tr role="row" style="height: 0px;"><th scope="col" class="sorting" aria-controls="data-table" rowspan="1" colspan="1" style="width: 277px; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px;"><div class="dataTables_sizing" style="height:0;overflow:hidden;">Store Number</div></th><th scope="col" class="sorting" aria-controls="data-table" rowspan="1" colspan="1" style="width: 241px; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px;"><div class="dataTables_sizing" style="height:0;overflow:hidden;">Store Name</div></th><th scope="col" class="sorting" aria-controls="data-table" rowspan="1" colspan="1" style="width: 156px; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px;"><div class="dataTables_sizing" style="height:0;overflow:hidden;">Active</div></th><th scope="col" class="sorting" aria-controls="data-table" rowspan="1" colspan="1" style="width: 237px; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px;"><div class="dataTables_sizing" style="height:0;overflow:hidden;">Action</div></th></tr>
    </thead>

    <tbody>







    <tr id="store-3" data-model="{&quot;Id&quot;:3,&quot;Name&quot;:&quot;a&quot;,&quot;IsActive&quot;:true,&quot;DBVersion&quot;:&quot;&quot;,&quot;Address&quot;:{&quot;Address&quot;:&quot;&quot;,&quot;Address2&quot;:&quot;&quot;,&quot;State&quot;:&quot;&quot;,&quot;City&quot;:&quot;&quot;,&quot;Zip&quot;:0},&quot;Phone&quot;:&quot;&quot;}" role="row" class="odd">
            <th scope="row" class="sorting_1">3</th>
            <td>a</td>
            <td>
                <label class="tgl">
                    <input onclick="ToggleStoreActive(this,event)" class="form-isactive" type="checkbox" checked="">
                    <span class="tgl_body">
                        <span class="tgl_switch"></span>
                        <span class="tgl_track">
                            <span class="tgl_bgd"></span>
                            <span class="tgl_bgd tgl_bgd-negative"></span>
                        </span>
                    </span>
                </label>
            </td>
            <td>
                <button class="btn btn-danger" onclick="DeleteStore(this)">
                    <i class="fa fa-trash-o" aria-hidden="true"></i>
                </button>
                <button class="btn btn-primary" onclick="PopModel(this)">
                    <i class="fa fa-pencil" aria-hidden="true"></i>
                </button>
            </td>
        </tr><tr id="store-4" data-model="{&quot;Id&quot;:4,&quot;Name&quot;:&quot;b&quot;,&quot;IsActive&quot;:true,&quot;DBVersion&quot;:&quot;&quot;,&quot;Address&quot;:{&quot;Address&quot;:&quot;&quot;,&quot;Address2&quot;:&quot;&quot;,&quot;State&quot;:&quot;&quot;,&quot;City&quot;:&quot;&quot;,&quot;Zip&quot;:0},&quot;Phone&quot;:&quot;&quot;}" role="row" class="even">
            <th scope="row" class="sorting_1">4</th>
            <td>b</td>
            <td>
                <label class="tgl">
                    <input onclick="ToggleStoreActive(this,event)" class="form-isactive" type="checkbox" checked="">
                    <span class="tgl_body">
                        <span class="tgl_switch"></span>
                        <span class="tgl_track">
                            <span class="tgl_bgd"></span>
                            <span class="tgl_bgd tgl_bgd-negative"></span>
                        </span>
                    </span>
                </label>
            </td>
            <td>
                <button class="btn btn-danger" onclick="DeleteStore(this)">
                    <i class="fa fa-trash-o" aria-hidden="true"></i>
                </button>
                <button class="btn btn-primary" onclick="PopModel(this)">
                    <i class="fa fa-pencil" aria-hidden="true"></i>
                </button>
            </td>
        </tr><tr id="store-5" data-model="{&quot;Id&quot;:5,&quot;Name&quot;:&quot;c&quot;,&quot;IsActive&quot;:true,&quot;DBVersion&quot;:&quot;&quot;,&quot;Address&quot;:{&quot;Address&quot;:&quot;&quot;,&quot;Address2&quot;:&quot;&quot;,&quot;State&quot;:&quot;&quot;,&quot;City&quot;:&quot;&quot;,&quot;Zip&quot;:0},&quot;Phone&quot;:&quot;&quot;}" role="row" class="odd">
            <th scope="row" class="sorting_1">5</th>
            <td>c</td>
            <td>
                <label class="tgl">
                    <input onclick="ToggleStoreActive(this,event)" class="form-isactive" type="checkbox" checked="">
                    <span class="tgl_body">
                        <span class="tgl_switch"></span>
                        <span class="tgl_track">
                            <span class="tgl_bgd"></span>
                            <span class="tgl_bgd tgl_bgd-negative"></span>
                        </span>
                    </span>
                </label>
            </td>
            <td>
                <button class="btn btn-danger" onclick="DeleteStore(this)">
                    <i class="fa fa-trash-o" aria-hidden="true"></i>
                </button>
                <button class="btn btn-primary" onclick="PopModel(this)">
                    <i class="fa fa-pencil" aria-hidden="true"></i>
                </button>
            </td>
        </tr></tbody>
</table>

and am attempting to get the second row (the one with "Store Number" 4 and "Store Name" 'b'), with the following Groovy code:

'get the initial number of data rows'
String dataRowsSelector = '//table[contains(@id, "data-table")]/tbody/tr'

List<WebElement> dataRows = driver.findElements(By.xpath(dataRowsSelector))

int initialRowCount = dataRows.size()

assertNotEquals(index, 0)

'find the row pointed to by the index'
String rowSelector = String.format('//table[contains(@id, "data-table")]/tbody/tr[%d]', (index + 1))

assertEquals(rowSelector, '//table[contains(@id, "data-table")]/tbody/tr[2]')

WebElement rowToDelete = driver.findElement(By.xpath(rowSelector))

'get the delete button'
String deleteButtonSelector = '//button[./i[contains(concat(" ", @class, " "), " fa-trash-o ")]]'

WebElement deleteButton = rowToDelete.findElement(By.xpath(deleteButtonSelector))

println(rowToDelete.findElement(By.xpath('//td[1]')).getAttribute('innerText'))

assertTrue(rowToDelete.findElement(By.xpath('//td[1]')).getAttribute('innerText').contains('b'))

I run that code, and rowToDelete becomes the first data row instead of the second (I try again with 3 for the index, and it is still the first row), even though the assertion against the target xpath worked. Also, the first <td> for that WebElement contains a and not b. (When I tried with 3 as the index, I get a again, even though I was expecting c.

How do I fix this weird behavior?

Mike Warren
  • 3,796
  • 5
  • 47
  • 99

1 Answers1

0

The problem was with my XPath itself, apparently. When attempting to select WebElements relative to other WebElements, using XPath, I should put a dot in front of the // to give it the scope.

Mike Warren
  • 3,796
  • 5
  • 47
  • 99
  • 1
    Don't forget to come back and accept this as the answer when you can so the question doesn't get left unanswered. – JeffC Jun 21 '18 at 20:26