2012-03-27 9 views
9

Używam rspec 2.6.0 i Capybara 1.1.1 do testów akceptacyjnych.
Mając tak:Kapibara i Rspec: poprawny sposób użycia w ramach() i have_selector() razem?

<tr > 
    <td>Team 3 Name</td> 
    <td>true</td> 
    <td><a href="/teams/3">Show</a></td> 
    <td><a href="/teams/3/edit">Edit</a></td> 
    <td><a href="/teams/3">Deactivate</a></td> 
</tr> 
<tr > 
    <td>Team 4 Name</td> 
    <td>true</td> 
    <td><a href="/teams/4">Show</a></td> 
    <td><a href="/teams/4/edit">Edit</a></td> 
    <td><a href="/teams/4">Deactivate</a></td> 
</tr> 

Chcę napisać test akceptacji, która stwierdza: „Zespół 3 nie ma linku«dezaktywować»” Spodziewam się, że poniższe zawiodą:

within('tr', :text => 'Team 3 Name') do |ref| 
    page.should_not have_selector('a', :text => 'Deactivate') 
end 

Ale mija. Aby dokładniej przetestować, co się dzieje, napisałem absurd:

lock = false 
within('tr', :text => 'Team 3 Name') do |ref| 
    page.should have_selector('a', :text => 'Deactivate') 
    page.should_not have_selector('a', :text => 'Deactivate') 
    lock = true 
end 
lock.should be_true 

Który również przechodzi.

Zakładam z tego, że zasięg wywołania have_selector() nie jest ograniczony przez blok within(), ale nie jestem pewien, dlaczego tak się dzieje. Dokumentacja kapibara wykorzystuje ten wzorzec i nie wspomina o żadnych gotchach. Jaki jest prawidłowy sposób użycia w celu ograniczenia zakresu mojego wyboru? Dziękuję. /Salernost

+0

Czy można sprawdzić, aby zobaczyć, czy 'page' jest zerowa przez jakiś dziwny zbieg okoliczności, lub umieścić w debuggera linia na górze testu, abyś mógł dostać się do konsoli i wypisać wartość 'strony' lub dodać krok' I pokaż mi stronę', aby przeglądarka pokazała ci kopię strony w stanie, w którym się znajduje tuż przed uruchomieniem tego testu? Jeśli tak, jakie ramy testowe faktycznie widzą? – jefflunt

+0

Dziękuję za odpowiedź. Mogę zweryfikować, że strona nie jest pusta przez wyjście debugowania, a ponadto, gdy wywołuję: "puts ref.text" wewnątrz bloku within(), otrzymuję poprawne: "Team 3 Name true Show Edit Deactivate". Zauważ, że mam poprawkę małpią wewnątrz(), aby uzyskać kontekst, abym mógł nazywać tekst na tym. Poprawiłem wewnątrz() PO Zidentyfikowaniu tego dziwnego zachowania, a więc nie jest przyczyną. :) – salernost

+0

[Ten wątek] (https://groups.google.com/forum/?fromgroups#!topic/ruby-capybara/1sdsA7nubyE) może być interesujący. –

Odpowiedz

10

Wciąż uczę się Kapibary, ale czy wypróbowałeś have_link zamiast have_selector? Również nie sądzę, że potrzebujesz |ref|. Na przykład:

lock = false 
within('tr', :text => 'Team 3 Name') do # omit |ref| 
    page.should have_link('Deactivate') 
    page.should_not have_link('Deactivate') 
    lock = true 
end 
lock.should be_true 


Aktualizacja 13 października 2012

Doszedłszy trochę dalej z Kapibara, widzę kilka potencjalnych problemów tutaj:

  • within może dyskretnie ignorować text pole. Zauważysz, że przykłady pokazują tylko wyszukiwarki CSS lub XPath bez dodatkowych argumentów.
  • Jeśli within nie używa text, może nie działać tutaj, ponieważ pytasz go, aby spojrzeć na <tr>, ale tekst jest w <td>.
  • Jest całkiem możliwe, że obiekt page nadal będzie kierował całą stronę, nawet jeśli znajdujesz się w bloku within. Przykłady z przykładów within dotyczą głównie używania fill_in lub click. Wyjątkiem jest przykład pod numerem Beware the XPath // trap.

chodzi o tworzenie within blok, można dać wierszy tabeli unikalne identyfikatory i szukać dla nich za pomocą CSS, lub może być w stanie napisać konkretnego XPath kierowania pierwszy pasujący wiersz.

Problem z tym ostatnim jest, że chcesz użyć within na <tr>, ale tekst używasz do kierowania jest wewnątrz <td> podelementu. Na przykład ta ścieżka XPath powinna znaleźć komórkę tabeli zawierającą tekst Team 3 Name, ale wtedy pracujesz tylko jako pierwsza komórka, a nie cały wiersz.

within(:xpath, "//tr/td[normalize-space(text())='Team 3 Name'") do 

Istnieją sposoby, aby „z powrotem” do elementu nadrzędnego za pomocą XPath, ale nie wiem, jak to zrobić i czytałem, że to nie jest dobra praktyka.Myślę, że najlepszym tutaj może być po prostu generować identyfikatory więc twoje wiersze zacząć tak:

<tr id="team_3"> 

następnie kierować je z prostym

within("tr#team_3") 
+1

Dziękuję Mark. Niestety have_link nie zmienia błędnego zachowania. Dodatkowo masz rację, nie _need_ "ref", i zauważyłem problem bez niego również. Powyższy kod został skopiowany w połowie śledzenia błędów.(W rzeczywistości musiałem załatać kapibarę, aby pozwolić mi zrezygnować z bloku, tak czy inaczej ...) Dalsze badania zdają się wskazywać, że błąd dotyczy wywołania within(). Kiedy używam wewnątrz ("tr # some_id"), zachowanie nie udaje się z powodu prawa tożsamości. Uważam, że jest to błąd w przypadku Capybara, ponieważ dokumentacja wyraźnie stwierdza, że ​​wywołanie intra() będzie pasować do jednego/pierwszego na stronie – salernost

4

have_selector zdaje się ignorować :text i :content opcje. Musiałem użyć coś takiego zamiast:

within 'a' do 
    page.should have_content 'Deactivate' 
end 
2

Chciałbym również polecić Mark Berry „s końcowego podejścia wspominał dodawania identyfikatorów dla każdego z elementów tabeli.

<tr id="team_3"> 

następnie kierowana

within("tr#team_3") 

Kapibara dał mi problemy przy wyborze przez XPath w to, że nie wydają się działać konsekwentnie, zwłaszcza z usług CI.

Chcę również zwrócić uwagę na tę samą odpowiedź tę sekcję:

Jest całkiem możliwe, że osoba, której strona nadal kieruje całą stronę, nawet jeśli znajdują się w obrębie bloku. W obrębie przykładów najczęściej chodzi o użycie fill_in lub kliknięcie. Wyjątkiem jest przykład w przypadku pułapki XPath // uwaga.

Może to miało miejsce w starszej wersji, ale w obecnej wersji Kapibara, nazywając page wewnątrz within bloku kontroluje tylko część strony docelowej. Tak więc, stosując powyższy przykład Marka:

within("tr#team_3") do 
    expect(page).to have_content 'Team 3 Name' 
    # => true 
    expect(page).to have_content 'Team 4 Name' 
    # => false 
end 
1

Rozwiązaniem jest, aby nie używać within metody:

expect(page).to have_css('tr#team_3') do 
    without_tag('a', text: 'Deactivate') 
end 
Powiązane problemy