2011-02-01 5 views
70

Я работаю со многими плагинами jQuery, которые часто создают элементы DOM без идентификатора или других идентификационных свойств, и единственный способ получить их в Capybara (например, для клика) - это получить своего соседа (другого ребенка его предка) первый. Но я не нашел нигде, например, Capybara поддерживает такие вещи:Как получить родительский узел в Capybara?

find('#some_button').parent.fill_in "Name:", :with => name 

?

+0

Кроме того, это будет очень полезно для меня, если вы сообщите, что Capybara генерирует щелчок по элементам с помощью {display: hidden}, и есть ли способ найти элементы в некоторой области, где display! = Hidden? – sandrew

+0

Это отдельный вопрос, но это зависит от того, какой драйвер вы используете. webrat найдет спрятанные вещи счастливо, но селен не так счастлив нажимать на предметы, которые вы не видите. – jamuraa

ответ

99

Я действительно нашел ответ jamuraa полезно, но будет для полной XPath дал мне кошмар струны в моем случае, поэтому я с радостью воспользовался способностью конкатенации find в Capybara, позволяя мне смешивать выбор css и xpath. Ваш пример будет выглядеть следующим образом:

find('#some_button').find(:xpath,".//..").fill_in "Name:", :with => name 

водосвинку 2.0 обновление: будет, скорее всего, результат в Ambiguous match ошибки. В этом случае используйте вместо этого first(:xpath,".//..").

+0

Спасибо за эту идею - Я никогда бы не подумал об этом! Я делал el.parent для элемента td, который я нашел с помощью find (: css), но по какой-то причине я не понимаю, el.parent возвращал # . el.find (: xpath, ".// .."), с другой стороны, возвращает # , что мне и нужно. –

+0

Другой способ рекурсивно найти определенный родительский узел - это селектор предков или ящиков xpath. Проверьте это http://stackoverflow.com/questions/1362466/xpath-recursive-ancestor-search – vrish88

+0

+1 Спасибо за обновление вашего ответа! –

37

Невозможно сделать это с помощью capybara и CSS. Я использовал XPath в прошлом для достижения этой цели, хотя, что действительно есть способ получить родительский элемент и поддерживается Капибара:

find(:xpath, '//*[@id="some_button"]/..').fill_in "Name:", :with => name 
+2

Когда я делаю аналогичную xpath find, я получаю ошибку Nokogiri, говоря, что это выражение неверно. Я добавил звездочку в открытую квадратную скобку в выражении, чтобы исправить выражение: 'find (: xpath, '// * [@ id =" some_button "]/..')' –

3

Я использую другой подход найти родительский элемент первого использования текста внутри этого родительского элемента:

find("<parent element>", text: "text within your #some_button").fill_in "Name:", with: name 

Может быть, это полезно в ситуации похожа.

+1

Это отличный вариант. Обнаружить действия ui на части страницы, содержащей какой-то конкретный текст, является для меня обычным случаем. – clemensp

21

Это не работает для меня, с ошибкой:

Ambiguous match, found 2 elements matching xpath ".//.." 

я обнаружил следующее, что делает работу:

find(:xpath, '..') 

Капибара был обновлен для поддержки.

https://github.com/jnicklas/capybara/pull/505

+0

Мне кажется, вы отвечаете/завершаете предыдущий ответ здесь («Это», что «не работает»?). Было бы лучше, если бы это был полный и независимый ответ. Поэтому я рекомендую вам его отредактировать. ;-) – helenov

+0

Может подтвердить. С последним Capybara 2.14.4 это правильный способ получить родительский узел. – fny

-5

Здесь

http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Base:parent

Существует метод родительского присутствует;)

+5

Это возвращает только документ верхнего уровня для меня. Не уверен, что это проблема с драйвером или что. – Nerdmaster

+0

Чтение документов, похоже, это может означать родительский элемент «frame», а не родитель элемента? – Nick

6

Если вы наткнулись на это, пытаясь выяснить, как найти любого родителя (как в ancestor) узел (как указано в комментарии @ vrish88 на ответ @Pascal Lindelauf):

2

Мне нужно было найти предка с классом css, хотя он был неопределенным, если у предка-предка был один или несколько классов css, поэтому я не видел способа сделать детерминированный запрос xpath. Я работал в этом вверх, а:

def find_ancestor_with_class(field, cssClass) 
    ancestor = field 
    loop do 
    ancestor = ancestor.find(:xpath, '..') 
    break if ancestor.nil? 

    break if ancestor.has_css? cssClass 
    end 

    ancestor 
end 

Предупреждение: используйте это экономно, это может стоить вам много времени в тестах поэтому убедитесь, что предок находится всего в нескольких хмель прочь.

+0

Ускорение: замените свой второй разрыв на 'break if ancestor [: class] .split (" ") .include? (Css_class)'. – hakunin

+0

@hakunin Мне любопытно, сколько ускорений вы видите? Значительное? – kross

+0

Не могу проверить сейчас, но has_css, казалось, занял второе место, в то время как совпадение с классом казалось немедленным. – hakunin

4

Этот ответ относится к тому, как манипулировать родственный элемент, который является то, что я считаю, что оригинальный вопрос намекая

Вашего вопрос гипотезы работает с незначительной подстройкой. Если динамически генерируемое поле выглядит, как это и не имеет ID:

<div> 
    <input></input> 
    <button>Test</button> 
</div> 

Ваш запрос будет таким:

find('button', text: 'Test').find(:xpath, "..").find('input').set('whatever') 

Если динамически вход приходит с прилагаемым элементом ид (будьте осторожны с ними, хотя, как и в угловых, они имеют обыкновение меняться в зависимости от добавления и удаления элементов), было бы что-то вроде этого:

find('button', text: 'Test').find(:xpath, "..").fill_in('#input_1', with: 'whatever') 

Надежда, что помогает.

Смежные вопросы