Клик по не самому последнему элементу (оси в xpath)

На странице таблица с несколькими колонками. В таблице представлен список категорий сайта.

Первая колонка – чекбоксы.

Вторая – линки на страницы настроек каждой категории.

Другие колонки – сейчас не важны.

Внизу есть кнопка действия над выбранными категориями.

Что-то вроде этого:

Задача: средствами Selenium выбрать чекбокс напротив категории, которую нужно обработать. И нажать на кнопку, что уже мелочь.
Код одной из строк, которая находится в первых двух колонках:

<tr>
……..<td class=”w e s”>
……………. <input type=”checkbox” name=”CategoryID”>
…….. <td class=”table_detail e s”>
……………. <a href=”http://abcd/category”>Product Price</a></td>
</tr>

Абослютно все чекбоксы в исследуемой таблице идентифицируются одинаково: все они расположены в td с классом “w e s”, все представлены как <input type=”checkbox” name=”CategoryID”>.

Уникальности начинаются только в ячейках с линками на страницы категорий.

Вопрос: можно ли посредством Selenium выбрать чекбокс, который находится рядом с нужной мне категорией, которая находится хз где во всей этой таблице?

Думаем.

Идентифицировать элементы “td” по порядковому номеру – можно, но тупо, ведь содержимое таблицы легко модифицируется, и указание “td[18]” завтра уже будет указывать на чужую категорию.

Идентифицировать следует в зависимости от следующей ячейки, в которой находится линк на страницу категории – единственное уникальное значение.

Нужный xpath пишется очень просто:

//input[@type=’checkbox’ and @name=’CategoryID’]/../../td/a[contains(text(), ‘Product Price’)]

Но!

Таким образом Selenium ищет и находит только последний элемент во всей этой цепочке xpath. И соответственно, может обработать только указанный линк, тогда как мне нужен клик по чекбоксу, который находится ПЕРЕД линком.

Неочевидное Решение #1:

//a[contains(text(), ‘Product Price’)]/parent::td/preceding-sibling::td/input[@name=’CategoryID’]

Читается все это так:

  1. найти линк, который содержит текст ‘Product Price’,
  2. у этого линка есть родительский элемент – td. Просим обратить на него внимание.
  3. от этого родительского элемента ищем все то, что в нем находится, и именно этот элемент мы и будет обрабатывать.

Неочевидное Решение #2 (попроще):

//*[contains(text(), ‘ProductPrice’)]/../..//input[@name=’CategoryID’ and @type=’checkbox’]

Оно попроще, но таит в себе проблему.

Вот конструкция, в которой постоянно меняются циферки страниц. Я же хочу делать всегда клик по самой последней странице перед Next (в данном случае – №6)

(Previous)   1  2  3  4  5  6  (Next)

Если указанным образом обратиться к линку, который предшествует линку Next, то в действительности фокус переместится на самый первый элемент в списке – на линк Previous.

Решение – кликаем по предпоследнему элементу в цепочке этих линков, если считать линк ‘Next’ последним:

//a[contains(text(), ‘Next’)]/..//a[last()-1]

Дополнительно

  1. на тему осей в xpath – theorynpracticetesting.wordpress.com
  2. на тему ориентирования по последним элементам в списке идентичных – automationtricks.blogspot.com

19 thoughts on “Клик по не самому последнему элементу (оси в xpath)

  1. хм)) оригинальненько, но зачем так заморачиваться? не легче было бы использовать что-то типа:
    //*[contains(text(), ‘ProductPrice’)]/../..//input
    если input-ов больше(или страница в скором времени может измениться):
    1. ну, допустим, hidden в том же теге td, тогда юзаем [@type=’checkbox’ and @name=’CategoryID’] или [not(@type=’hidden’)], или уж совсем на крайний случай, [last()] или [1] в зависимости от положения нужного инпута
    2. если инпут находится в таге tr, тогда юзаем уже:
    //*[contains(text(), ‘ProductPrice’)]/../../td/input
    имхо так все намного проще, а вот preceding-sibling и following-sibling я использовал бы в других целях )
    пс: я, так сказать, просто чайник, так что не ругайте сильно )
    ппс: алексей, у тебя ни первый, ни второй xpaеh не будет работать. Product Price – нет нигде ) хотя даже если убрать пробел, то все равно в таблице найдутся 2 результата. по теме: fucking-great-advice.ru/advice/158/

  2. Добрый день! А если таблица настолько большая, что находится на нескольких страницах и навигация по ней примерно такая:
    | << first | | last >> |
    …и то, что мне нужно, “находится хз где во всей этой таблице”, можно ли как-то осуществить поиск того, что мне нужно?

    1. Конечно.

      Пишем условие, что “если нужный текст есть, то переходим к нему”, а если “текста на странице нет, то кликнуть один раз по линку ‘last >>’, и снова начинаем искать текст”.

      Я такое сделал буквально неделю назад.

      1. Я хочу это сделать в Selenium IDE с помощью команды runScript. Поиск сделала, работает, а по ссылке не получается перейти. Подскажите пожалуйста, что делаю не так.

        Так работает: click | document.getElementById(‘yui-pg0-0-next-link’)
        Так НЕ работает: runScript | document.getElementById(‘yui-pg0-0-next-link’).click()

  3. Не получается с помощью Selenium IDE поставить чекбокс. Нужно на странице блога в админке поставить чекбокс, что блог прошел модерацию. Чекбокс ставиться, но после того как сохранить страницу и опять зайти на этот блог, то его уже нету.

    Вот кусочек кода:

    Пройшов модерацію:

    Вот как это написала я и как не работает:

    click
    id=passedModeration

    click
    link=Зберегти

    Спасибо за внимание.

  4. Есть цикл пробега по radiobutton,на странице их 63,но число каждую неделю меняется.Возможно ли сделать так что бы цикл проходил все radio и сам определял их количество.

    store
    1
    i

    store
    63
    stopradio

    while
    storedVars[‘i’]<=storedVars[‘stopradio’]

    click
    xpath=(//input[@type=’radio’])[${i}]

    storeEval
    ${i}+1
    i

  5. Добрый день. Подскажите пожалуйста как при помощи Selenium IDE отловить последний созданный элемент:

    type
    name=name
    Новый Отдел

    clickAndWait
    css=#form-add > input.btn.btn-primary

    assertValue
    //input[@name=’roles[362][name]’]
    Новый Отдел

    При добавлении нового элемента локатор для него создается по принципу +1
    т.е меняется только числовое значение.
    Для xpath это выглядит следующим образом: //input[@name=’roles[362][name]’] следующий созданный элемент будет иметь xpath //input[@name=’roles[363][name]’]
    Собственно вопрос: как отловить последний созданный элемент, он же элемент с максимальным чиловым значением?
    Буду очень признателен если поможете с этим разобраться.

  6. Добрый день!
    У меня к Вам вопрос,если можно:
    Я столкнулся с одним интересным моментом – не могу ченуть чекбокс. Команда чекает по чекбоксам на других страницах так-как скрипт универсален, но в некоторых случаях не хочет работать, именно на определенных чекбоксах. при это они доступны и можно их выбрать “ручками”, но не в IDE. Команда проходит, горит зеленым, но галочки не появляется, хотя я уверен что локатор чекбокса верный! Попробывал очень много всего, в интернете пишут что есть такие случаи когда это обусловлена задействованием чекбокса в каких-то еще функциях/процедурах. Подскажите, как же по нему кликнуть.?

  7. Добрый день.
    Помогите, пжл, решить проблему.
    Существует табличка с 20 элементами на стр. Все это линки такого вида:
    Уникальный номер
    Это абсолютный Xpath: html/body/div[1]/div[4]/div[3]/div/table/tbody/tr[5]/td[1]/a
    Не получается кликнуть по линку через указание его position.
    Такой путь //tr/td/a[position()=10] не дает результатов. Что не так, подскажите.

  8. Не знаю, к сожалению, там номер, состоящий из 6 цифр. Он уникален. У линка есть атрибут href, содержащий также уникальный номер из 4 цифр. Как я понимаю, цепляться можно только за кого-то из них.

  9. Линк выглядит так:
    556139
    Можно ли строить локатор таким образом:
    //a[starts-with(@href, ‘/общее/общее/общее/Общее:’)][position()=5]? Без второй части [position()=5] все линки определяются, а с ней – ничего.
    Хочется просто понять, правильно ли я пишу локатор в принципе.

  10. Не знаю прочтете ли вы, но вы спасли мою жопу в 2021) Спасибо Вам)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s