2012-04-20 5 views
9

Ich versuche, einen Datumsauswahl mit Capybara mit den Standard-Rails-Datum, Uhrzeit und Datetime-Felder zu erstellen. Ich verwende die within Methode, um die Auswahlfelder für das Feld zu finden, aber wenn ich xPath verwende, um das richtige Feld zu finden, verlässt es den Bereich within und findet das erste Vorkommen auf der Seite des Elements.capybara - Find mit xPath verlässt den Geltungsbereich

Hier ist der Code, den ich verwende. Die Seite, auf der ich teste, hat 2 Datetime-Felder, aber ich kann nur bekommen, dass ich die erste wegen dieses Fehlers ändere. Im Moment habe ich einen div-Container mit ID, der das datetime-Feld umschließt, aber ich habe vor, den Code zu wechseln, um nach dem Label zu suchen.

module Marketron 
    module DateTime 

    def select_date(field, options = {}) 
     date_parse = Date.parse(options[:with]) 

     year = date_parse.year.to_s 
     month = date_parse.strftime('%B') 
     day = date_parse.day.to_s 

     within("div##{field}") do 
     find(:xpath, "//select[contains(@id, \"_#{FIELDS[:year]}\")]").select(year) 
     find(:xpath, "//select[contains(@id, \"_#{FIELDS[:month]}\")]").select(month) 
     find(:xpath, "//select[contains(@id, \"_#{FIELDS[:day]}\")]").select(day) 
     end 

    end 

    def select_time(field, options = {}) 
     require "time" 
     time_parse = Time.parse(options[:with]) 

     hour = time_parse.hour.to_s.rjust(2, '0') 
     minute = time_parse.min.to_s.rjust(2, '0') 

     within("div##{field}") do 
     find(:xpath, "//select[contains(@id, \"_#{FIELDS[:hour]}\")]").find(:xpath, "option[contains(@value, '#{hour}')]").select_option 
     find(:xpath, "//select[contains(@id, \"_#{FIELDS[:minute]}\")]").find(:xpath, "option[contains(@value, '#{minute}')]").select_option 

     end 

    end 

    def select_datetime(field, options = {}) 
     select_date(field, options) 
     select_time(field, options) 
    end 

    private 

     FIELDS = {year: "1i", month: "2i", day: "3i", hour: "4i", minute: "5i"} 

    end 
end 

World(Marketron::DateTime) 

Antwort

25

Sie im XPath angeben soll, die Sie mit dem aktuellen Knoten gestartet werden sollen, indem ein . zum Start Hinzufügen:

find(:xpath, ".//select[contains(@id, \"_#{FIELDS[:year]}\")]") 

Beispiel:

ich eine HTML-Seite getestet davon (hoffentlich nicht über die Vereinfachung Ihrer Seite):

<html> 
    <div id='div1'> 
     <span class='container'>  
      <span id='field_01'>field 1</span> 
     </span> 
    </div> 
    <div id='div2'> 
     <span class='container'> 
      <span id='field_02'>field 2</span> 
     </span> 
    </div> 
</html> 

Verwendung der innerhalb von Methoden, können Sie Ihr Problem sehen können, wenn Sie dies tun:

within("div#div1"){ puts find(:xpath, "//span[contains(@id, \"field\")]").text } 
#=> field 1 
within("div#div2"){ puts find(:xpath, "//span[contains(@id, \"field\")]").text } 
#=> field 1 

Aber Sie können, dass aber die Angabe des XPath sehen in den aktuellen Knoten zu suchen (dh . verwenden), erhalten Sie die Ergebnisse, die Sie wollen:

within("div#div1"){ puts find(:xpath, ".//span[contains(@id, \"field\")]").text } 
#=> field 1 
within("div#div2"){ puts find(:xpath, ".//span[contains(@id, \"field\")]").text } 
#=> field 2