Выберите родительский дочерний элемент, когда дочерний элемент соответствует тексту, используя селен - PullRequest
0 голосов
/ 20 мая 2019

У меня есть html примерно так:

<div class="card">
  <div>Foo</div>
  <a>View Item</a>
</div>
<div class="card">
  <div>Bar</div>
  <a>View Item</a>
</div>

Я хочу выбрать карточку, соответствующую "Бар", и нажать ссылку "Просмотреть элемент".Я пытался

cards = browser.find_elements_by_class_name('card')
for card in cards:
  if card.find_element_by_partial_link_text('Bar'):
     item_anchor = card.find_element_by_partial_link_text('View Item')
     item_anchor.click()

Однако я получаю сообщение об ошибке:

selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"partial link text","selector":"Bar"}

Ответы [ 4 ]

0 голосов
/ 20 мая 2019

Этого можно достичь одной строкой кода, используя правильный xpath.

driver.findElement(By.xpath("//div[text()='Bar']/following-sibling::a[text()='View Item']")).click();
0 голосов
/ 20 мая 2019

Если вы хотите нажать на View Item из Bar, вы можете напрямую использовать этот xpath:

//div[text()='Bar']/following-sibling::a[text()='View Item']  

Однако введение ожидания веб-драйвера будет отличной идеей для стабильности, как упомянуто @supputuri

0 голосов
/ 20 мая 2019
There are two ways to handle this situation based on your UI behavior:

1) If UI is fixed, use this xpath to identify and use click() to click on it.

//*[@class='card']/div[.='Bar']/following-sibling::a

2) If you are taking data from any external sources (like Database or Excel), pass your expected value (like Bar or Foo) as a parameter to the xpath method like below:

Define a class called Element like as below:

public class Element {

    private WebElement element;
    private WebDriver driver;
    private String xpath;

//  Constructor will wrap web element into Object and will allow to use any of the method declared below
    public Element(String xpath) {
        this.driver = new ChromeDriver();
        this.xpath = xpath;
        this.element = this.driver.findElement(By.xpath(this.xpath));
    }

    public void click() {
        this.element.click();
    }
}

Create POM class and write a methods like below:

public class PageObjectClass {

        private Element elementToClick(String value) {
            return new Element("//*[@class='card']/div[.='" + value + "']/following-sibling::a");
        }

        public void clickOnViewItemsLink(String value) {
            this.elementToClick(value).click();
        }
    }

By this way, you can click on any of View Item link just by passing value as a parameter
0 голосов
/ 20 мая 2019

Попробуйте использовать EC и ниже xpath.

Вариант 1:

Проверьте, существует ли ссылка, и нажмите (вы можете добавить атрибуты для ссылки в xpath, если вы ищете какую-либо конкретную ссылку)

link =WebDriverWait(driver,10).until(EC.presence_of_element_located((By.XPATH,"//div[@class='card' and div[normalize-space(.)='Bar']]/a")))
if (link):
    link.click()

Опции 2:

Использование разных xpath и len

links =WebDriverWait(driver,10).until(EC.presence_of_all_elements_located((By.XPATH,"//div[@class='card']/div[normalize-space(.)='Bar']/following-sibling::a[normalize-space(.)='View Item']")))
if len(links)>0:
    links[0].click()

Вариант 3:

Если вы не уверены, что существуют какие-либо уровни между B и A, вы можете использовать приведенный ниже xpath.

links =WebDriverWait(driver,10).until(EC.presence_of_all_elements_located((By.XPATH,"//div[normalize-space(.)='Bar']/ancestor::div[@class='card']//a[normalize-space(.)='View Item']")))
if len(links)>0:
    links[0].click()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...