2

I am writing a selenium test to test a crud application where you can add, update, or delete a user. I have a table that dynamically displays all of the fields. When I add a new user, a new edit button is also added and when clicked edits that particular user. When trying to test this with selenium, I am not sure how to edit a specific user. I would like to edit the 4th user in the list, which would be index 3. I tried this,

var edit = wait.Until((d) => d.FindElements(By.Id("edit")));
edit[3].Click();

but get an index out of range error. If I do this:

var edit = wait.Until((d) => d.FindElement(By.Id("edit")));
edit.Click();

It allows me to edit the first person in the table.

<tr>
    <td>Ray Peterson</td>
    <td>deleted_0_rpeterson@aol.com</td>
    <td>Developer</td>
    <td>
        <div class="pointer">
            <div class="sprk-o-Stack sprk-o-Stack--split@xs" data-id="">
                <div class="sprk-o-Stack__item sprk-o-Stack__item--half@xs sprk-o-Box" data-id="">
                    <div class="updateUser">
                        <svg class="sprk-c-Icon sprk-c-Icon--l" viewBox="0 0 64 64" data-id="" id="edit">
                            <use xlink:href="#editable"></use>
                        </svg>
                    </div>
                </div>
                <div class="sprk-o-Stack__item sprk-o-Stack__item--half@xs sprk-o-Box" data-id="">
                    <svg class="sprk-c-Icon sprk-c-Icon--l" viewBox="0 0 64 64" data-id="" id="deleted_0_rpeterson@aol.com">
                        <use xlink:href="#trash"></use>
                    </svg>
                </div>
            </div>
        </div>
    </td>
</tr>
<tr>
    <td>Fredo Corleone</td>
    <td>godfather88@gmail.com</td>
    <td>Developer</td>
    <td>
        <div class="pointer">
            <div class="sprk-o-Stack sprk-o-Stack--split@xs" data-id="">
                <div class="sprk-o-Stack__item sprk-o-Stack__item--half@xs sprk-o-Box" data-id="">
                    <div class="updateUser">
                        <svg class="sprk-c-Icon sprk-c-Icon--l" viewBox="0 0 64 64" data-id="" id="edit">
                            <use xlink:href="#editable"></use>
                        </svg>
                    </div>
                </div>
                <div class="sprk-o-Stack__item sprk-o-Stack__item--half@xs sprk-o-Box" data-id="">
                    <svg class="sprk-c-Icon sprk-c-Icon--l" viewBox="0 0 64 64" data-id="" id="godfather88@gmail.com">
                        <use xlink:href="#trash"></use>
                    </svg>
                </div>
            </div>
        </div>
    </td>
</tr>
<tr>
    <td>Try Again</td>
    <td>tryagain@gmail.com</td>
    <td>Developer</td>
    <td>
        <div class="pointer">
            <div class="sprk-o-Stack sprk-o-Stack--split@xs" data-id="">
                <div class="sprk-o-Stack__item sprk-o-Stack__item--half@xs sprk-o-Box" data-id="">
                    <div class="updateUser">
                        <svg class="sprk-c-Icon sprk-c-Icon--l" viewBox="0 0 64 64" data-id="" id="edit">
                            <use xlink:href="#editable"></use>
                        </svg>
                    </div>
                </div>
                <div class="sprk-o-Stack__item sprk-o-Stack__item--half@xs sprk-o-Box" data-id="">
                    <svg class="sprk-c-Icon sprk-c-Icon--l" viewBox="0 0 64 64" data-id="" id="tryagain@gmail.com">
                        <use xlink:href="#trash"></use>
                    </svg>
                </div>
            </div>
        </div>
    </td>
</tr>
JeffC
  • 22,180
  • 5
  • 32
  • 55
dev_in_training
  • 333
  • 5
  • 16
  • What if you wait until the page fully loads first? See this post: https://stackoverflow.com/questions/5868439/wait-for-page-load-in-selenium – CoolBots Mar 04 '21 at 00:42
  • Post the HTML for a row for a couple users in your question. We should be able to write a locator that finds that particular user based on any column value you want, e.g. username, etc. – JeffC Mar 04 '21 at 02:30
  • @JeffC I added a screen shot of my html. The edit button is an icon within the div with class "updateUser". The icon has an id of "edit" – dev_in_training Mar 04 '21 at 13:09
  • Please read why [a screenshot of code is a bad idea](https://meta.stackoverflow.com/questions/303812/discourage-screenshots-of-code-and-or-errors). Paste the code and properly format it instead. This includes HTML. We can't easily create a locator from a screenshot or test it. – JeffC Mar 04 '21 at 14:35
  • @JeffC I removed the screenshot and the code for my table – dev_in_training Mar 04 '21 at 15:08
  • I appreciate the HTML as text but we need the rendered HTML from the browser. If I paste your HTML that contains code to generate the HTML, it won't render in the browser so it doesn't display correctly and I can't create locators from it. I don't need the entire table, just a couple rows as example should be enough. Thanks. – JeffC Mar 04 '21 at 16:48
  • @JeffC thank you trying to help me. I appreciate it. I hope I added what you were looking for. Sorry for the poor formatting, it wasn't cooperating with me. – dev_in_training Mar 04 '21 at 17:28
  • @dev_in_training Did you see my answer below? Did you get a chance to try it? – JeffC Mar 04 '21 at 18:32
  • Also, when I post HTML I use an HTML beautifier like https://beautifytools.com/html-beautifier.php. It makes cleaning up HTML *much* easier. I fixed the formatting of the HTML you posted using it. – JeffC Mar 04 '21 at 18:34
  • @JeffC Yes I just tried it and it works perfectly! Thank you so much for your help. I really appreciate it. – dev_in_training Mar 04 '21 at 18:54

2 Answers2

1

You can go with the XPath for identifying the specific field Xpath for identifying the input field Xpath for identifying the input field

I hope you have similar page, please try XPath

Rahul Das
  • 46
  • 6
1

If you want to edit a specific user, I've found the best way to do this is to create a locator that uses data from the table to find a specific table row and then click the Edit button in that row. Since we are searching the table to find elements based on contained text, our only locator option is XPath.

I can't test this with the current HTML that contains rendering code but I mocked up something based on what you posted and these should work or at least be close.

If you want to search by firstName lastName, you can use

//tr[./td[1][.='John Smith']]//*[name()='svg'][@id='edit']

If you want to search by email, you can use

//tr[./td[2][.='address@email.com']]//*[name()='svg'][@id='edit']

Ideally you would put these into methods and pass in the search criteria and have it click the Edit button for you so that they are reusable.

/// <summary>
/// Finds the user by the supplied email and clicks Edit
/// </summary>
/// <param name="email">The email address of the user to be edited</param>
public void EditUserByEmail(string email)
{
    By locator = By.XPath($"//tr[./td[2][.='{email}']]//*[name()='svg'][@id='edit']");
    WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
    wait.Until(ExpectedConditions.ElementToBeClickable(locator)).Click();
}

/// <summary>
/// Finds the user by the supplied full name and clicks Edit
/// </summary>
/// <param name="fullName">The full name of the user to be edited in the format "firstName lastName"</param>
public void EditUserByName(string fullName)
{
    By locator = By.XPath($"//tr[./td[1][.='{fullName}']]//*[name()='svg'][@id='edit']");
    WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
    wait.Until(ExpectedConditions.ElementToBeClickable(locator)).Click();
}

and you could call it like

EditUserByEmail("pinocchio@aol.com");
JeffC
  • 22,180
  • 5
  • 32
  • 55