-1

I'm kinda new to python and I have a question I have a table and in the table, there are multiple rows and in the table row there are two table columns One contains a text and the other contains a button What I want to do is based on the containing text I want to click the button next to it.

HTML:

<td class="leaf" style="max-height: 40px; min-height: 40px; height: 40px;">
<table><tbody><tr>
<td class="tree-col col-lhs">
<div class="fullHeight">
<i class="fa fa-truck outsideIcon" style="position:absolute;left:6px;top:10px;"></i>
<i class="fa fa-truck innerIcon" style="color:Silver;position:absolute;left:9px;top:10px;"></i>
</div>
</td>
<td class="tree-col col-center"><div><span class="leaf-primary-name">ABC123</span><span class="leaf-subname"></span>
</div>
<div class="leaf-address">
<span>3:08 PM 3-5 Anthony rd West Ryde Zone</span>
</div>
</td>
<td class="tree-col col-rhs" style="width: 0px;"></td>
<td class="tree-col col-checkbox">
<input type="checkbox" class="k-radio" id="chk_tree_206_196_2156">
<label class="k-radio-label" for="chk_tree_206_196_2156"></label>
</td>
<td class="tree-col col-color"></td>
</tr>
</tbody>
</table>
</td>

My Action code as below

root_elm = "//td[@class='leaf']"
sub_elm_one = "//td/div/span"
sub_elm_two = "//input"

list_data = self.driver.find_elements_by_xpath(root_elm)
            time.sleep(5)
            for group in list_data:
                data = group.find_elements_by_xpath(sub_elm_one)
                inputs = group.find_elements_by_xpath(sub_elm_two)
                for row, radio in zip(data, inputs):
                    logging.info("Found Data : " + row.text)
                    if text in row.text:
                        radio.click()
                        logging.info("Clicked on element input :" + row.text)

When I execute this code I'm getting an error from radio.click().

157, in click_element_in_element
          radio.click()
        File "e:\software installers\python\lib\site-packages\selenium\webdriver\remote\webelement.py", line 80, in click
          self._execute(Command.CLICK_ELEMENT)
        File "e:\software installers\python\lib\site-packages\selenium\webdriver\remote\webelement.py", line 633, in _execute
          return self._parent.execute(command, params)
        File "e:\software installers\python\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 321, in execute
          self.error_handler.check_response(response)
        File "e:\software installers\python\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 242, in check_response
          raise exception_class(message, screen, stacktrace)
      selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable
        (Session info: chrome=88.0.4324.150)
DebanjanB
  • 118,661
  • 30
  • 168
  • 217

2 Answers2

0

When you look up an element basing on some other element you should not start your xpath locator from // or from / because they ignore searching context and start from the root.

Thus when you do inputs = group.find_elements_by_xpath(sub_elm_two) you might be locating an element that is not in the group you expect.

You should have your locators like:

root_elm = "//td[@class='leaf']"
sub_elm_one = ".//td/div/span"
sub_elm_two = ".//input"

However if you do not need to verify that text exists spearatly from verifying the button exists I would recommend to build a single xpath that would be locating your button relatively to the required text. Let xpath parser do the thing, do not code the logic on your own.

Alexey R.
  • 4,490
  • 1
  • 7
  • 22
0

Keeping it simple to click on the <input> tag associated with the username e.g. ABC123 you can use the following Locator Strategies:

  • Using variable in XPATH:

    username = 'ABC123'
    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//td[@class='leaf']//span[@class='leaf-primary-name'][text()='" +username+ "']//following::td[2]//input[@class='k-radio']"))).click()
    
  • Using %s in XPATH:

    username = 'ABC123'
    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//td[@class='leaf']//span[@class='leaf-primary-name'][text()='%s']//following::td[2]//input[@class='k-radio']"% str(username)))).click()
    
  • Using format() in XPATH:

    username = 'ABC123'
    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//td[@class='leaf']//span[@class='leaf-primary-name'][text()='{}']//following::td[2]//input[@class='k-radio']".format(str(username)))).click()
    
  • Note: You have to add the following imports :

    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    

References

You can find a couple of relevant detailed discussions in:

DebanjanB
  • 118,661
  • 30
  • 168
  • 217