2012-03-27 3 views
9

Ich verwende rspec 2.6.0 und Capybara 1.1.1 für Akzeptanztests.
Mit Blick wie folgt aus:Capybara und Rspec: richtiger Weg, um innerhalb() und have_selector() zusammen zu verwenden?

<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> 

ich eine Abnahmeprüfung schreiben wollen, die besagt: „Team 3 auf den Link‚Deaktivieren‘nicht über“ Ich erwarte folgendes:

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

Aber es geht. Um weiter zu testen, was vor sich geht, habe ich das Absurde geschrieben:

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 

Das geht auch.

Ich gehe davon aus, dass der Bereich, den der Aufruf have_selector() verwendet, nicht durch den Block iner() beschränkt ist, aber ich bin mir nicht sicher, warum das ist. Die Capybara-Dokumentation verwendet dieses Muster und scheint keine Probleme zu erwähnen. Was ist der richtige Weg, um den Umfang meiner Auswahl zu begrenzen? Danke. /Salernost

+0

Haben Sie überprüft, ob 'page' Null durch einen seltsamen Zufall ist, oder in einem Debugger setzen Zeile an der Spitze des Tests, so dass Sie zu einer Konsole gelangen und den Wert von 'Seite' ausgeben können, oder den Schritt' Und zeigen Sie mir die Seite' hinzugefügt, so dass Ihr Browser Ihnen eine Kopie der Seite in dem Zustand zeigt, in dem sie sich befindet kurz bevor es diesen Test durchführt? Wenn ja, was sieht der Testrahmen eigentlich? – jefflunt

+0

Danke für Ihre Antwort. Ich kann überprüfen, dass Seite nicht Null über Debug-Ausgabe ist, und noch mehr, wenn ich rufe: "puts ref.text" innerhalb der innerhalb() Block bekomme ich die richtige: "Team 3 Name wahr Show Edit deaktivieren". Beachten Sie, dass ich innerhalb von() monkey-patched habe, um den Kontext zu erhalten, damit ich Text darauf aufrufen kann. Ich habe gepatcht(), NACHDEM ich dieses seltsame Verhalten erkannt habe und deshalb nicht die Ursache ist. :) – salernost

+0

[Dieses Thema] (https://groups.google.com/forum/?fromgroups#!topic/ruby-capybara/1sdsA7nubyE) könnte von Interesse sein. –

Antwort

10

Immer noch Capybara lernen, aber haben Sie versucht have_link anstelle von have_selector? Ich glaube auch nicht, dass Sie |ref| brauchen. Zum Beispiel:

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 


-Update 13. Oktober 2012

ein wenig weiter mit Capybara gekommen, sehe ich mehrere mögliche Probleme hier:

  • within leise die text ignorieren Feld. Sie werden feststellen, dass die Beispiele nur CSS- oder XPath-Finder ohne zusätzliche Argumente anzeigen.
  • Wenn withintext verwendet, funktioniert es hier möglicherweise nicht, weil Sie es bitten, die <tr> zu betrachten, aber der Text ist in der <td>.
  • Es ist durchaus möglich, dass der Betreff page immer noch die gesamte Seite anvisiert, selbst wenn Sie sich in einem within Block befinden. Die within Beispiele sind hauptsächlich über die Verwendung fill_in oder click. Die Ausnahme ist das Beispiel unter Beware the XPath // trap.

Wie für einen within Block erstellen, können Sie entweder Ihre Tabellenzeilen eindeutige IDs geben und für sie suchen CSS verwenden, oder Sie können die erste passende Zeile Targeting einen bestimmten XPath schreiben können.

Das Problem mit letzterem ist, dass Sie die within auf der <tr> verwenden möchten, aber der Text, den Sie für Ihr Targeting verwenden, befindet sich in einem <td> Subelement. So sollte zum Beispiel dieser XPath die Tabellenzelle finden, die den Text enthält, aber dann arbeiten Sie nur within diese erste Zelle, nicht die ganze Zeile.

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

Es gibt Möglichkeiten, um „back up“ zu einem übergeordneten Element XPath verwenden, aber ich weiß nicht, wie es zu tun, und ich habe gelesen, dass es keine gute Praxis ist.Ich denke, Ihre beste Wette hier sein könnte, um nur Ids zu erzeugen so Ihre Zeilen wie folgt beginnen:

<tr id="team_3"> 

sie dann gezielt mit einem einfachen

within("tr#team_3") 
+1

Danke Mark. Leider hat have_link das fehlerhafte Verhalten nicht verändert. Außerdem sind Sie richtig, ich brauche nicht 'ref', und ich beobachtete das Problem auch ohne es. Der obige Code wurde als Mid-Bug-Tracking kopiert.(Tatsächlich musste ich Capybara patchern, um mir den Block zu geben, irgendwie ...) Weitere Untersuchung scheint anzuzeigen, dass der Fehler mit dem Aufruf von innerhalb() zu tun hat. Wenn ich innerhalb ('tr # some_id') verwende, ist das Verhalten aufgrund des Gesetzes der Identität fehlgeschlagen. Ich denke, dass dies ein Fehler von Capybara ist, da in der Dokumentation eindeutig angegeben ist, dass ein Aufruf von innerhalb() mit einem/ersten auf einer Seite übereinstimmt – salernost

4

have_selector scheint :text und :content Optionen zu ignorieren. Ich hatte so etwas wie dies stattdessen zu verwenden:

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

ich auch Mark Berry ‚s Endanflug würde empfehlen, er die Zugabe von ids zu jedem Ihres Tabellenelement erwähnt.

<tr id="team_3"> 

dann gezielt mit

within("tr#team_3") 

Capybara mir gegeben hat, ausgeben, wenn durch XPath bei der Auswahl, dass es scheint nicht konsequent zu arbeiten, vor allem mit CI-Dienstleistungen.

Ich möchte auch diesen Abschnitt auf der gleichen Antwort auf beachten Sie:

Es ist durchaus möglich, dass die Seite Thema nach wie vor die gesamte Seite richtet sich, auch wenn Sie in ein innerhalb des Blocks sind. In den Beispielen geht es hauptsächlich um fill_in oder click. Die Ausnahme ist das Beispiel unter Achtung der XPath // Trap. page innerhalb eines within Block Aufruf prüft nur den Teil gezielt auf der Seite

der Fall in einer älteren Version, aber in der aktuellen Version von Capybara gewesen, diese haben. Also, mit Markus obigem Beispiel:

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

Die Lösung ist nicht within Methode zu verwenden:

expect(page).to have_css('tr#team_3') do 
    without_tag('a', text: 'Deactivate') 
end 
Verwandte Themen