Acceptance Testing
   with Webrat
         Luismi Cavallé

       http://twitter.com/cavalle
          http://lmcavalle.com
    http://spainrb.org/luismi-cavalle
Demo
Internals
Webrat

#get   #post      #head       #delete    ...

#put   #request           #follow_redirect!



   ActionController::                            Nokogiri
     Integration::
        Session
Rails Integration Test
test "Hotel creation" do
  get "/hotels"

 assert_select "body", :text => /Ritz/, :count => 0

 get "/hotels/new"

 post_via_redirect "/hotels",
                   :hotel => { :name => "Ritz" }

  assert_response :success
  assert_select "body", /Hotel was successfully created/
  assert_select "body", /Ritz/
end
Webrat

#get   #post      #head       #delete    ...

#put   #request           #follow_redirect!



                                               Hpricot + REXML
         Rack::Test
click_link


def click_link(text_or_title_or_id, options = {})
  find_link(text_or_title_or_id).click(options)
end
click_link


def find_link(text_or_title_or_id) #:nodoc:
  LinkLocator.new(@session, dom, text_or_title_or_id).locate!
end
click_link


def locate
  Link.load(@session, link_element)
end
click_link


def link_element
  matching_links.min { |a, b|
Webrat::XML.all_inner_text(a).length <=>
Webrat::XML.all_inner_text(b).length }
end
click_link


def matching_links
  @matching_links ||= link_elements.select do |link_element|
    matches_text?(link_element) ||
    matches_id?(link_element)
  end
end
click_link


def link_elements
  Webrat::XML.xpath_search(@dom, *Link.xpath_search)
end
click_link


def self.xpath_search
  ".//a[@href]"
end
click_link

def self.xpath_search(element, *searches)
  searches.flatten.map do |search|
    if Webrat.configuration.parse_with_nokogiri?
      element.xpath(search)
    else
      REXML::XPath.match(element, search)
    end
  end.flatten.compact
end
click_link


def matching_links
  @matching_links ||= link_elements.select do |link_element|
    matches_text?(link_element) ||
    matches_id?(link_element)
  end
end
click_link

def matches_text?(link)
  if @value.is_a?(Regexp)
    matcher = @value
  else
    matcher = /#{Regexp.escape(@value.to_s)}/i
  end

  replace_nbsp(Webrat::XML.all_inner_text(link)) =~ matcher ||
  replace_nbsp_ref(Webrat::XML.inner_html(link)) =~ matcher ||
  Webrat::XML.attribute(link, "title")=~ matcher
end
click_link


def matches_id?(link)
  if @value.is_a?(Regexp)
    (Webrat::XML.attribute(link, "id") =~ @value) ? true : false
  else
    (Webrat::XML.attribute(link, "id") == @value) ? true : false
  end
end
click_link


def link_element
  matching_links.min { |a, b|
Webrat::XML.all_inner_text(a).length <=>
Webrat::XML.all_inner_text(b).length }
end
click_link


def locate
  Link.load(@session, link_element)
end
click_link


def click_link(text_or_title_or_id, options = {})
  find_link(text_or_title_or_id).click(options)
end
click_link

def click(options = {})
  method = options[:method] || http_method
  return if href =~ /^#/ && method == :get

 options[:javascript] = true if options[:javascript].nil?

  if options[:javascript]
    @session.request_page(absolute_href, method, data)
  else
    @session.request_page(absolute_href, :get, {})
  end
end
API
Navigation

visit "/hotels/new"

visit hotels_path
Navigation


click_link "Create a new hotel"
Navigation


click_area 'Madrid'
Forms


select "Canada", :from => "Country"

select "Canada"
Forms
Forms
select_date "April 26, 1982", :from => "Birthday"
select_date Date.today


select_datetime 2.days.ago
select_datetime "April 26, 1982 7:00PM", :from => "Event"


select_time "22:30"
select_time "1:30AM", :from => "Arrival time"
Forms
select_date "April 26, 1982", :from => "Birthday"
select_date Date.today


select_datetime 2.days.ago
select_datetime "April 26, 1982 7:00PM", :from => "Event"


select_time "22:30"
select_time "1:30AM", :from => "Arrival time"
Forms
select_date "April 26, 1982", :from => "Birthday"
select_date Date.today


select_datetime 2.days.ago
select_datetime "April 26, 1982 7:00PM", :from => "Event"


select_time "22:30"
select_time "1:30AM", :from => "Arrival time"
Forms
select_date "April 26, 1982", :from => "Birthday"
select_date Date.today


select_datetime 2.days.ago
select_datetime "April 26, 1982 7:00PM", :from => "Event"


select_time "22:30"
select_time "1:30AM", :from => "Arrival time"
Forms
select_date "April 26, 1982", :from => "Birthday"
select_date Date.today


select_datetime 2.days.ago
select_datetime "April 26, 1982 7:00PM", :from => "Event"


select_time "22:30"
select_time "1:30AM", :from => "Arrival time"
Forms
select_date "April 26, 1982", :from => "Birthday"
select_date Date.today


select_datetime 2.days.ago
select_datetime "April 26, 1982 7:00PM", :from => "Event"


select_time "22:30"
select_time "1:30AM", :from => "Arrival time"
Forms
select_date "April 26, 1982", :from => "Birthday"
select_date Date.today


select_datetime 2.days.ago
select_datetime "April 26, 1982 7:00PM", :from => "Event"


select_time "22:30"
select_time "1:30AM", :from => "Arrival time"
Forms
select_date "April 26, 1982", :from => "Birthday"
select_date Date.today


select_datetime 2.days.ago
select_datetime "April 26, 1982 7:00PM", :from => "Event"


select_time "22:30"
select_time "1:30AM", :from => "Arrival time"
Forms


attach_file "Brochure", "/path/nh_cornella.pdf"

attach_file "Photo", "/path/front.jpg", "image/jpg"
Forms


check 'Remember me'

uncheck 'You can send me spam'
Forms


fill_in "Email", :with => "user@example.com"

fill_in "user[email]", :with => "user@example.com"
Forms


click_button "Login"

click_button
And more...


basic_auth "admin", "password"

save_and_open_page
And more...


within "#project_1" do
  click_link "Destroy"
end
Matchers

assert_contain "Hotel was successfully created"



assert_not_contain(/You have booked for d+ nights/)
Matchers

assert_have_selector "div#hotel_1",
                     :content => "Sol Meliá Berlín"

assert_have_selector ".bookings", :count => 5

assert_have_no_selector "a:enabled",
                        :href => "http://google.com"
Matchers

assert_have_xpath "//div[@id = 'hotel_1']",
                  :content => "Sol Meliá Berlín"

assert_have_xpath "//*[@class = 'bookings']",
                  :count => 5

assert_have_no_xpath "//a[enabled(.)]",
                     :href => "http://google.com"
Matchers

response.should contain(/You have booked for d+ nights/)



response.should_not have_selector(".bookings", :count => 5)
Matchers

response.should have_selector(".hotels") do |hotels|
  hotels.should have_selector("h2", :content => "Hotels")
  hotels.should have_xpath("//div[@id = 'hotel_1']",
                           :content => "Ritz")
end
Configuration
Webrat.configure do |config|
  config.parse_with_nokogiri = true
  config.infinite_redirect_limit = 10
  config.open_error_files = true
end
Webrat.configure do |config|
  config.mode = :rails | :merb | :sinatra |
                :rack_test |
                :mechanize | :selenium
end
TDD Benefits
★ Driving the design and
  development


★ Building a suite of automated
  regression tests
http://www.flickr.com/photos/icopythat/4375608/
Gracias!
     http://wiki.github.com/brynary/webrat
http://gitrdoc.com/brynary/webrat/tree/master/


          http://twitter.com/cavalle
             http://lmcavalle.com
       http://spainrb.org/luismi-cavalle

Acceptance Testing with Webrat