'Click a button in a table, but all rows contain automatically generated identical buttons in Selenium
I am currently doing QA Automation on a web application with Selenium WebDriver, and the language I decided to use is Python 3. Everything was going great until I got stuck on reaching a specific element in a table.
Some context:
This table allows for User Management. It means that new rows with users and their permissions are automatically added. The permissions are also buttons and can be easily removed just by a single click by the admin (for example, he will click on the LOGIN permission of test01 and he will revoke his permissions to login). There is also the "+" button to add a permission. Here is the example table:
+----------+-------------+--------------------+
| username | displayName | Permission |
+----------+-------------+--------------------+
| test01 | Test, User | LOGIN ( + ) |
+----------+-------------+--------------------+
| test02 | User, Test | LOGIN ADMIN ( + ) |
+----------+-------------+--------------------+
The thing is, I want Selenium to click on the LOGIN button of test01, so his permissions to login will be revoked. However, I am having difficulties pointing Selenium to that specific element. When I click "inspect" this is the browser information.
<table id="permissions" class="rounded-large">
<tbody>
<tr>
<td>test01</td>
<td>Selenium User</td>
<td> #i want this
<span class="perm-control perm clickable rounded-small">LOGIN</span>
<span class="perm-control add-perm clickable rounded-small">+</span>
</td>
</tr>
<tr>
<td>test02</td>
<td>Selenium Admin</td>
<td>
<span class="perm-control perm clickable rounded-small">LOGIN</span>
<span class="perm-control add-perm clickable rounded-small">+</span>
</td>
</tr>
<thead>
<tr>
<th>Username</th>
<th>Display Name</th>
<th class="centered">Permissions</th>
</tr>
</thead>
<tbody>
</tbody>
There is no id, or class to this element (which is auto generated, as this table can expand with 30-40 users) and I am not sure how to click this exact LOGIN button and not the one of test02 for example. It is not an option to change the source code currently. Thank you!
Solution 1:[1]
To click on Selenium User
LOGIN
button induce WebDriverWait
and element_to_be_clickable
and following xpath
WebDriverWait(driver,20).until(EC.element_to_be_clickable((By.XPATH,"//table[@id='permissions']//td[text()='Selenium User']/following::td[1]/span[text()='LOGIN']"))).click()
OR
WebDriverWait(driver,20).until(EC.element_to_be_clickable((By.XPATH,"//table[@id='permissions']//td[text()='test01']/following::td[2]/span[text()='LOGIN']"))).click()
To execute above code you need to imports followings.
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
Solution 2:[2]
you can try looping through the table rows, lookup the username, based on your table, the only way the rows can be distinguished is by the username and click the 'LOGIN'. My code is untested.
permission_table = driver.find_element_by_id('permissions')
permission_table_body = permission_table.find_element_by_tag_name('tbody')
permission_table_rows = permission_table_body.find_elements_by_tag_name('tr')
for row in permission_table_rows:
# you can also find the individual cells in a row
# for cell in row.find_elements_by_tag_name('td'):
# cell[0].text == 'test01':
if 'test01' in row.text:
spans = row.find_elements_by_tag_name('span')
for span in spans:
if span.text == 'LOGIN':
span.click()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | KunduK |
Solution 2 | Satish |