2013-09-04 30 views
6

Szukałem i nie mogę znaleźć sposobu, aby to zrobić.Wyświetlenie elementów potomnych dla elementu Capybara/Poltergeist

Prowadzimy testy Capybara ze sterownikiem Poltergeist w funkcjach ogórka w aplikacji EmberJS/Rails. Nie mogę używać strony page.driver.debug, ponieważ korzystam z instancji bez nagłówka Vagrant, więc rozwiązywanie problemów nie jest dla mnie dostępne, ale zrzuty ekranu działają, a narzędzia sprawdzające Chrome na danej stronie pokazują właściwe elementy.

Mam scenariusz z ogórkiem, który zawodzi, a dzieje się tak dlatego, że znalezisko nie działa. Mój test wygląda następująco:

When(/^I delete description "(.*?)"$/) do |description| 
    within :css, '#myform' do 
    first('label', :text => /#{description}/).find(:xpath, '..').find(:css, 'button.delete') 
    end 
end 

Nie można znaleźć danego elementu. Oto odnośny fragment DOM:

<form id="myform"> 
    <div class="row-fluid question"> 
     <div class="span12"> 
     <div class="padding"> 
      <div id="ember576" class="ember-view is-viewing-edit-controls"> 
      <button class="delete" data-ember-action="31"></button> 
      <button class="edit" data-ember-action="32"></button> 
      <button class="insert_above" data-ember-action="33"></button> 
      <button class="insert_below" data-ember-action="34"></button> 
      <button class="move_up" data-ember-action="35"></button> 
      <button class="move_down" data-ember-action="36"></button> 
      <label class="question" data-ember-action="37">Enter your first name</label> 
      <input id="ember577" class="ember-view ember-text-field"> 
      <span class="error"></span> 
      </div> 
     </div> 
    </div> 
    </div> 
</form> 

Jeśli dodać w binding.pry, to:

first('label', :text => /#{description}/).find(:xpath, '..') 
                           │ 

daje mi tej odpowiedzi:

=> #<Capybara::Element tag="div"> 

a to:

first('label', :text => /#{description}/).find(:xpath, '..') 
                           │ 

daje mi tę odpowiedź:

=> "Enter your first name" 

ale pełny znalezisko:

first('label', :text => /#{description}/).find(:xpath, '..').find(:css, 'button.delete') 

daje mi tej odpowiedzi:

Capybara::ElementNotFound: Unable to find css "button.delete" 

Mam wrażenie, że jest to kwestia rodzice/rodzeństwo, ale nie mogę rozwiązać to. Tak myślę, że mam kilka pytań:

  1. Do debugowania, czy istnieje mimo to sterownik poltergeist do listy wszystkich elementów podrzędnych?
  2. Czy jest coś nie tak z moim selektorem xpath? Fakt, że .. powraca Capybara::Element tag="div" powoduje, że myślę, że mam właściwy element nadrzędny (i jak powiedziałem, działa na innych stronach w innych podobnych testach), ale nie mam możliwości zweryfikowania, który to element. Nie mogę znaleźć, jak uzyskać xpath lub cokolwiek innego, co pomaga mi zidentyfikować element.

Odpowiedz

2

Wymyśliłem to. Test sprawdzał się dobrze, ale brakowało mi kroku akcji w moim scenariuszu.

Jednak pomyślałem, że może ci się przydać wiedzieć, w jaki sposób otrzymałem zawartość: wykonanie jQuery na stronie. Dodałem binding.pry do mojego testu, a następnie w konsoli binding.pry Zalogowałem wynik jQuery, np:

# this gave me the expected contents and verified that button.delete was a child 
page.execute_script("console.log($('#myform label.question').parent().html())"); 

# and this gave me the classes to demonstrate that it was the correct div 
page.execute_script("console.log($('#myform label.question').parent().attr('class'))"); 

Wziąłem skrót z selektorów, bo wiedziałam, że etykieta szukałem był pierwszy, ale selektor nie ma znaczenia, to była idea konsoli. log() - jQuery w binding.pry, która była przydatna.

0

Coś do wypróbowania dla innych, którzy wciąż szukają: Spróbuj użyć first(:xpath, './/..') zamiast find(:xpath, '..').

Również jest to dobry pomysł, aby ograniczyć zakres find kiedy można, zakładając atrybut id postaci jest statyczna, dla lepszej wydajności i zapobiegając niejednoznacznej dopasowywania:

within('#myform') do 
    find('label', text: "#{description}", match: :first). 
    first(:xpath, './/..'). 
    find('button.delete'). 
    click 
end