Home > Элегантные решения, XPath > Клик по не самому последнему элементу (оси в xpath)

Клик по не самому последнему элементу (оси в 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
  1. 8 June 2011 at 21:54

    хм)) оригинальненько, но зачем так заморачиваться? не легче было бы использовать что-то типа:
    //*[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. Olya
    8 August 2011 at 16:30

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

    • 8 August 2011 at 16:52

      Конечно.

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

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

      • Olya
        10 August 2011 at 15:54

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

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

      • Olya
        10 August 2011 at 17:53

        Вопрос снимаю, все получилось, спасибо 🙂

    • 12 August 2011 at 18:11

      Вот более “подробный ответ

  3. Mary
    7 March 2012 at 16:20

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

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

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

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

    click
    id=passedModeration

    click
    link=Зберегти

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

    • 7 March 2012 at 17:08

      Код, к сожалению, не виден.

      В гуглодок какой-нибудь его положите для надежности.

  4. Евгений
    29 August 2012 at 11:44

    Есть цикл пробега по 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. Александр
    29 March 2013 at 13:09

    Добрый день. Подскажите пожалуйста как при помощи 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. Oleksii
    11 November 2014 at 16:31

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

    • 11 November 2014 at 21:56

      Совершенно не представляю, в чем может быть проблема.

  7. Ксюша
    14 January 2015 at 10:07

    Добрый день.
    Помогите, пжл, решить проблему.
    Существует табличка с 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. Ксюша
    14 January 2015 at 13:50

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

    • 14 January 2015 at 13:59

      Без детального изучения приложения можно только гадать.

  9. Ксюша
    14 January 2015 at 14:24

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

  1. No trackbacks yet.

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 )

Google photo

You are commenting using your Google 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

%d bloggers like this: