From cdafd2ec0ff481d5676e808e46a1f1108fafeea1 Mon Sep 17 00:00:00 2001 From: Gwyn Morfey Date: Wed, 16 Apr 2008 10:54:37 +0100 Subject: [PATCH 01/70] Added Merb support. --- Manifest.txt | 28 +--- lib/boot_merb.rb | 84 ++++++++++++ lib/boot_rails.rb | 39 ++++++ lib/merb_support/indifferent_access.rb | 138 ++++++++++++++++++++ lib/merb_support/param_parser.rb | 17 +++ lib/merb_support/url_encoded_pair_parser.rb | 93 +++++++++++++ lib/webrat.rb | 42 +----- lib/webrat/field.rb | 10 +- lib/webrat/logging.rb | 4 +- test/fills_in_test.rb | 12 ++ 10 files changed, 401 insertions(+), 66 deletions(-) create mode 100644 lib/boot_merb.rb create mode 100644 lib/boot_rails.rb create mode 100644 lib/merb_support/indifferent_access.rb create mode 100644 lib/merb_support/param_parser.rb create mode 100644 lib/merb_support/url_encoded_pair_parser.rb diff --git a/Manifest.txt b/Manifest.txt index 55ecc1f..abdb8ef 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -1,26 +1,3 @@ -.git/HEAD -.git/config -.git/description -.git/hooks/applypatch-msg -.git/hooks/commit-msg -.git/hooks/post-commit -.git/hooks/post-receive -.git/hooks/post-update -.git/hooks/pre-applypatch -.git/hooks/pre-commit -.git/hooks/pre-rebase -.git/hooks/update -.git/index -.git/info/exclude -.git/logs/HEAD -.git/logs/refs/heads/master -.git/logs/refs/remotes/origin/master -.git/objects/pack/pack-3243faf8e8f6f0e226adf39a2c2e8c19c18da6c4.idx -.git/objects/pack/pack-3243faf8e8f6f0e226adf39a2c2e8c19c18da6c4.pack -.git/refs/heads/master -.git/refs/remotes/origin/HEAD -.git/refs/remotes/origin/master -.gitignore History.txt MIT-LICENSE.txt Manifest.txt @@ -38,6 +15,11 @@ lib/webrat/logging.rb lib/webrat/page.rb lib/webrat/redirect_actions.rb lib/webrat/select_option.rb +lib/boot_merb.rb +lib/boot_rails.rb +lib/merb_support/indifferent_access.rb +lib/merb_support/param_parser.rb +lib/merb_support/url_encoded_pair_parser.rb test/checks_test.rb test/chooses_test.rb test/clicks_button_test.rb diff --git a/lib/boot_merb.rb b/lib/boot_merb.rb new file mode 100644 index 0000000..21c4a9b --- /dev/null +++ b/lib/boot_merb.rb @@ -0,0 +1,84 @@ +#In Merb, we have an RspecStory instead of an integration Session. +class Merb::Test::RspecStory + + #Our own redirect actions defined below, to deal with the fact that we need to store + #a controller reference. + + def current_page + @current_page ||= Webrat::Page.new(self) + end + + def current_page=(new_page) + @current_page = new_page + end + + # Issues a GET request for a page, follows any redirects, and verifies the final page + # load was successful. + # + # Example: + # visits "/" + def visits(*args) + @current_page = Webrat::Page.new(self, *args) + end + + def save_and_open_page + current_page.save_and_open + end + + [:reloads, :fills_in, :clicks_button, :selects, :chooses, :checks, :unchecks, :clicks_link, :clicks_link_within, :clicks_put_link, :clicks_get_link, :clicks_post_link, :clicks_delete_link].each do |method_name| + define_method(method_name) do |*args| + current_page.send(method_name, *args) + end + end + + #Session defines the following (used by webrat), but RspecStory doesn't. Merb's get/put/delete return a controller, + #which is where we get our status and response from. + def get_via_redirect(path, parameters = {}, headers = {}) + @controller=get path, parameters, headers + follow_redirect! while redirect? + status + end + def put_via_redirect(path, parameters = {}, headers = {}) + @controller=put path, parameters, headers + follow_redirect! while redirect? + status + end + def delete_via_redirect(path, parameters = {}, headers = {}) + @controller=delete path, parameters, headers + follow_redirect! while redirect? + status + end + + def follow_redirect! + @controller=get @controller.headers["Location"] + end + + def redirect? + [307, *(300..305)].include?(status) + end + + def status + @controller.status + end + + def response + @controller #things like @controller.body will work. + end + + def assert_response(resp) + if resp == :success + response.should be_successful + else + raise "assert_response #{resp.inspect} is not supported" + end + end +end + +#Other utilities used by Webrat that are present in Rails but not Merb. We can require heavy dependencies +#here because we're only loaded in Test mode. +require 'strscan' +require 'cgi' +require File.join(File.dirname(__FILE__), "merb_support", "param_parser.rb") +require File.join(File.dirname(__FILE__), "merb_support", "url_encoded_pair_parser.rb") +require File.join(File.dirname(__FILE__), "merb_support", "indifferent_access.rb") + diff --git a/lib/boot_rails.rb b/lib/boot_rails.rb new file mode 100644 index 0000000..1954ca7 --- /dev/null +++ b/lib/boot_rails.rb @@ -0,0 +1,39 @@ +module ActionController + module Integration + class Session + + unless instance_methods.include?("put_via_redirect") + include Webrat::RedirectActions + end + + def current_page + @current_page ||= Webrat::Page.new(self) + end + + def current_page=(new_page) + @current_page = new_page + end + + # Issues a GET request for a page, follows any redirects, and verifies the final page + # load was successful. + # + # Example: + # visits "/" + def visits(*args) + @current_page = Webrat::Page.new(self, *args) + end + + def save_and_open_page + current_page.save_and_open + end + + [:reloads, :fills_in, :clicks_button, :selects, :chooses, :checks, :unchecks, :clicks_link, :clicks_link_within, :clicks_put_link, :clicks_get_link, :clicks_post_link, :clicks_delete_link].each do |method_name| + define_method(method_name) do |*args| + current_page.send(method_name, *args) + end + end + + end + end +end + diff --git a/lib/merb_support/indifferent_access.rb b/lib/merb_support/indifferent_access.rb new file mode 100644 index 0000000..2213b09 --- /dev/null +++ b/lib/merb_support/indifferent_access.rb @@ -0,0 +1,138 @@ +# This class has dubious semantics and we only have it so that +# people can write params[:key] instead of params['key'] +# and they get the same value for both keys. + +class HashWithIndifferentAccess < Hash + def initialize(constructor = {}) + if constructor.is_a?(Hash) + super() + update(constructor) + else + super(constructor) + end + end + + def default(key = nil) + if key.is_a?(Symbol) && include?(key = key.to_s) + self[key] + else + super + end + end + + alias_method :regular_writer, :[]= unless method_defined?(:regular_writer) + alias_method :regular_update, :update unless method_defined?(:regular_update) + + # + # Assigns a new value to the hash. + # + # Example: + # + # hash = HashWithIndifferentAccess.new + # hash[:key] = "value" + # + def []=(key, value) + regular_writer(convert_key(key), convert_value(value)) + end + + # + # Updates the instantized hash with values from the second. + # + # Example: + # + # >> hash_1 = HashWithIndifferentAccess.new + # => {} + # + # >> hash_1[:key] = "value" + # => "value" + # + # >> hash_2 = HashWithIndifferentAccess.new + # => {} + # + # >> hash_2[:key] = "New Value!" + # => "New Value!" + # + # >> hash_1.update(hash_2) + # => {"key"=>"New Value!"} + # + def update(other_hash) + other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) } + self + end + + alias_method :merge!, :update + + # Checks the hash for a key matching the argument passed in + def key?(key) + super(convert_key(key)) + end + + alias_method :include?, :key? + alias_method :has_key?, :key? + alias_method :member?, :key? + + # Fetches the value for the specified key, same as doing hash[key] + def fetch(key, *extras) + super(convert_key(key), *extras) + end + + # Returns an array of the values at the specified indicies. + def values_at(*indices) + indices.collect {|key| self[convert_key(key)]} + end + + # Returns an exact copy of the hash. + def dup + HashWithIndifferentAccess.new(self) + end + + # Merges the instantized and the specified hashes together, giving precedence to the values from the second hash + # Does not overwrite the existing hash. + def merge(hash) + self.dup.update(hash) + end + + # Removes a specified key from the hash. + def delete(key) + super(convert_key(key)) + end + + def stringify_keys!; self end + def symbolize_keys!; self end + def to_options!; self end + + # Convert to a Hash with String keys. + def to_hash + Hash.new(default).merge(self) + end + + protected + def convert_key(key) + key.kind_of?(Symbol) ? key.to_s : key + end + + def convert_value(value) + case value + when Hash + value.with_indifferent_access + when Array + value.collect { |e| e.is_a?(Hash) ? e.with_indifferent_access : e } + else + value + end + end +end + +module ActiveSupport #:nodoc: + module CoreExtensions #:nodoc: + module Hash #:nodoc: + module IndifferentAccess #:nodoc: + def with_indifferent_access + hash = HashWithIndifferentAccess.new(self) + hash.default = self.default + hash + end + end + end + end +end diff --git a/lib/merb_support/param_parser.rb b/lib/merb_support/param_parser.rb new file mode 100644 index 0000000..534e1ff --- /dev/null +++ b/lib/merb_support/param_parser.rb @@ -0,0 +1,17 @@ +module Webrat + class ParamParser + def self.parse_query_parameters(query_string) + return {} if query_string.blank? + + pairs = query_string.split('&').collect do |chunk| + next if chunk.empty? + key, value = chunk.split('=', 2) + next if key.empty? + value = value.nil? ? nil : CGI.unescape(value) + [ CGI.unescape(key), value ] + end.compact + + UrlEncodedPairParser.new(pairs).result + end + end +end \ No newline at end of file diff --git a/lib/merb_support/url_encoded_pair_parser.rb b/lib/merb_support/url_encoded_pair_parser.rb new file mode 100644 index 0000000..8e668c7 --- /dev/null +++ b/lib/merb_support/url_encoded_pair_parser.rb @@ -0,0 +1,93 @@ +class UrlEncodedPairParser < StringScanner #:nodoc: + attr_reader :top, :parent, :result + + def initialize(pairs = []) + super('') + @result = {} + pairs.each { |key, value| parse(key, value) } + end + + KEY_REGEXP = %r{([^\[\]=&]+)} + BRACKETED_KEY_REGEXP = %r{\[([^\[\]=&]+)\]} + + # Parse the query string + def parse(key, value) + self.string = key + @top, @parent = result, nil + + # First scan the bare key + key = scan(KEY_REGEXP) or return + key = post_key_check(key) + + # Then scan as many nestings as present + until eos? + r = scan(BRACKETED_KEY_REGEXP) or return + key = self[1] + key = post_key_check(key) + end + + bind(key, value) + end + + private + # After we see a key, we must look ahead to determine our next action. Cases: + # + # [] follows the key. Then the value must be an array. + # = follows the key. (A value comes next) + # & or the end of string follows the key. Then the key is a flag. + # otherwise, a hash follows the key. + def post_key_check(key) + if scan(/\[\]/) # a[b][] indicates that b is an array + container(key, Array) + nil + elsif check(/\[[^\]]/) # a[b] indicates that a is a hash + container(key, Hash) + nil + else # End of key? We do nothing. + key + end + end + + # Add a container to the stack. + def container(key, klass) + type_conflict! klass, top[key] if top.is_a?(Hash) && top.key?(key) && ! top[key].is_a?(klass) + value = bind(key, klass.new) + type_conflict! klass, value unless value.is_a?(klass) + push(value) + end + + # Push a value onto the 'stack', which is actually only the top 2 items. + def push(value) + @parent, @top = @top, value + end + + # Bind a key (which may be nil for items in an array) to the provided value. + def bind(key, value) + if top.is_a? Array + if key + if top[-1].is_a?(Hash) && ! top[-1].key?(key) + top[-1][key] = value + else + top << {key => value}.with_indifferent_access + push top.last + value = top[key] + end + else + top << value + end + elsif top.is_a? Hash + key = CGI.unescape(key) + parent << (@top = {}) if top.key?(key) && parent.is_a?(Array) + top[key] ||= value + return top[key] + else + raise ArgumentError, "Don't know what to do: top is #{top.inspect}" + end + + return value + end + + def type_conflict!(klass, value) + raise TypeError, "Conflicting types for parameter containers. Expected an instance of #{klass} but found an instance of #{value.class}. This can be caused by colliding Array and Hash parameters like qs[]=value&qs[key]=value. (The parameters received were #{value.inspect}.)" + end +end \ No newline at end of file diff --git a/lib/webrat.rb b/lib/webrat.rb index 4401f1a..744fe10 100644 --- a/lib/webrat.rb +++ b/lib/webrat.rb @@ -6,42 +6,8 @@ module Webrat VERSION = '0.2.1' end -module ActionController - module Integration - class Session - - unless instance_methods.include?("put_via_redirect") - include Webrat::RedirectActions - end - - def current_page - @current_page ||= Webrat::Page.new(self) - end - - def current_page=(new_page) - @current_page = new_page - end - - # Issues a GET request for a page, follows any redirects, and verifies the final page - # load was successful. - # - # Example: - # visits "/" - def visits(*args) - @current_page = Webrat::Page.new(self, *args) - end - - def save_and_open_page - current_page.save_and_open - end - - [:reloads, :fills_in, :clicks_button, :selects, :chooses, :checks, :unchecks, :clicks_link, :clicks_link_within, :clicks_put_link, :clicks_get_link, :clicks_post_link, :clicks_delete_link].each do |method_name| - define_method(method_name) do |*args| - current_page.send(method_name, *args) - end - end - - end - end +if defined?(Merb) + require File.join(File.dirname(__FILE__), "boot_merb.rb") +else + require File.join(File.dirname(__FILE__), "boot_rails.rb") end - diff --git a/lib/webrat/field.rb b/lib/webrat/field.rb index 34b70bd..7c28798 100644 --- a/lib/webrat/field.rb +++ b/lib/webrat/field.rb @@ -6,15 +6,15 @@ module Webrat if %w[submit image].include?(element["type"]) field_class = "button" else - field_class = element["type"] + field_class = element["type"] || "text" #default type; 'type' attribute is not mandatory end else field_class = element.name end Webrat.const_get("#{field_class.capitalize}Field") - rescue NameError - raise "Invalid field element: #{element.inspect}" + #rescue NameError + # raise "Invalid field element: #{element.inspect}" end def initialize(form, element) @@ -92,8 +92,10 @@ module Webrat def param_parser if defined?(CGIMethods) CGIMethods - else + elsif defined?(ActionController::AbstractRequest) ActionController::AbstractRequest + else + Webrat::ParamParser #used for Merb end end diff --git a/lib/webrat/logging.rb b/lib/webrat/logging.rb index 08e9870..a77b6fa 100644 --- a/lib/webrat/logging.rb +++ b/lib/webrat/logging.rb @@ -3,12 +3,14 @@ module Webrat def debug_log(message) # :nodoc: return unless logger - logger.debug + logger.debug message end def logger # :nodoc: if defined? RAILS_DEFAULT_LOGGER RAILS_DEFAULT_LOGGER + elsif defined? Merb + Merb.logger else nil end diff --git a/test/fills_in_test.rb b/test/fills_in_test.rb index 0ebb567..19daf3f 100644 --- a/test/fills_in_test.rb +++ b/test/fills_in_test.rb @@ -137,6 +137,18 @@ class FillsInTest < Test::Unit::TestCase @session.fills_in "user[email]", :with => "foo@example.com" @session.clicks_button end + + def test_should_work_without_input_type + @response.stubs(:body).returns(<<-EOS) +
+ + +
+ EOS + @session.expects(:post_via_redirect).with("/login", "user" => {"email" => "foo@example.com"}) + @session.fills_in "user[email]", :with => "foo@example.com" + @session.clicks_button + end def test_should_work_with_symbols @response.stubs(:body).returns(<<-EOS) From 44745f689164ca1b53b1af6277cb361395e42bd9 Mon Sep 17 00:00:00 2001 From: Gwyn Morfey Date: Wed, 16 Apr 2008 15:35:10 +0100 Subject: [PATCH 02/70] Fixed Webrat not finding

+ + + EOS + @session.expects(:post_via_redirect) + @session.clicks_button + end + def test_should_not_explode_on_file_fields @response.stubs(:body).returns(<<-EOS)
From 04261e66d88f9e5272d00e828e49896dbcf0d6f3 Mon Sep 17 00:00:00 2001 From: Gwyn Morfey Date: Wed, 16 Apr 2008 15:37:47 +0100 Subject: [PATCH 03/70] Added missing post_via_redirect --- lib/boot_merb.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/boot_merb.rb b/lib/boot_merb.rb index 21c4a9b..d5c85f0 100644 --- a/lib/boot_merb.rb +++ b/lib/boot_merb.rb @@ -43,6 +43,11 @@ class Merb::Test::RspecStory follow_redirect! while redirect? status end + def post_via_redirect(path, parameters = {}, headers = {}) + @controller=post path, parameters, headers + follow_redirect! while redirect? + status + end def delete_via_redirect(path, parameters = {}, headers = {}) @controller=delete path, parameters, headers follow_redirect! while redirect? From f74037e4dac06f7c4a6f2f43a38296abbd749886 Mon Sep 17 00:00:00 2001 From: Gwyn Morfey Date: Wed, 16 Apr 2008 17:12:31 +0100 Subject: [PATCH 04/70] Preserve cookies, so that we don't lose the session between requests. Make sure you are using the memory session store. --- lib/boot_merb.rb | 42 +++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/lib/boot_merb.rb b/lib/boot_merb.rb index d5c85f0..11120cb 100644 --- a/lib/boot_merb.rb +++ b/lib/boot_merb.rb @@ -33,29 +33,38 @@ class Merb::Test::RspecStory #Session defines the following (used by webrat), but RspecStory doesn't. Merb's get/put/delete return a controller, #which is where we get our status and response from. + # + #We have to preserve cookies like this, or the session is lost. + def request_via_redirect(method,path,parameters={},headers={}) + mycookies = @controller.cookies rescue nil #will be nil if no requests yet + @controller=self.send(method, path, parameters, headers) do |new_controller| + new_controller.cookies = mycookies + end + follow_redirect! while redirect? + status + end + def get_via_redirect(path, parameters = {}, headers = {}) - @controller=get path, parameters, headers - follow_redirect! while redirect? - status + request_via_redirect(:get,path,parameters,headers) end + def put_via_redirect(path, parameters = {}, headers = {}) - @controller=put path, parameters, headers - follow_redirect! while redirect? - status + request_via_redirect(:put,path,parameters,headers) end + def post_via_redirect(path, parameters = {}, headers = {}) - @controller=post path, parameters, headers - follow_redirect! while redirect? - status + request_via_redirect(:post,path,parameters,headers) end + def delete_via_redirect(path, parameters = {}, headers = {}) - @controller=delete path, parameters, headers - follow_redirect! while redirect? - status + request_via_redirect(:delete,path,parameters,headers) end def follow_redirect! - @controller=get @controller.headers["Location"] + mycookies = @controller.cookies rescue nil + @controller=get @controller.headers["Location"] do |new_controller| + new_controller.cookies=mycookies + end end def redirect? @@ -79,6 +88,13 @@ class Merb::Test::RspecStory end end +class Application < Merb::Controller + def cookies=(newcookies) + @_cookies = newcookies + end +end + + #Other utilities used by Webrat that are present in Rails but not Merb. We can require heavy dependencies #here because we're only loaded in Test mode. require 'strscan' From ede0073db409a379573bd5573f56e9794161ca0f Mon Sep 17 00:00:00 2001 From: Gwyn Morfey Date: Wed, 16 Apr 2008 17:14:23 +0100 Subject: [PATCH 05/70] Added note to readme file: use session_store = memory or lose your sessions. --- README.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.txt b/README.txt index ffbdf08..467385c 100644 --- a/README.txt +++ b/README.txt @@ -63,7 +63,7 @@ A test written with Webrat can handle these changes smoothly. == REQUIREMENTS: -* Rails >= 1.2.6 +* Rails >= 1.2.6 or Merb edge * Hpricot >= 0.6 * Rails integration tests in Test::Unit _or_ * RSpec stories (using an RSpec version >= revision 2997) @@ -76,6 +76,12 @@ In your stories/helper.rb: You could also unpack the gem into vendor/plugins. +To avoid losing sessions, you need this in environments/test.rb: + +Merb::Config.use do |c| + c[:session_store] = 'memory' +end + == HISTORY: See CHANGELOG in this directory. From 2e03051735e5fecb9270437a677ecf76c609a6de Mon Sep 17 00:00:00 2001 From: Gwyn Morfey Date: Thu, 17 Apr 2008 11:52:42 +0100 Subject: [PATCH 06/70] Wrap RAILS_ROOT to support Merb also --- lib/webrat.rb | 3 +++ lib/webrat/page.rb | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/webrat.rb b/lib/webrat.rb index 744fe10..2419dba 100644 --- a/lib/webrat.rb +++ b/lib/webrat.rb @@ -4,6 +4,9 @@ end module Webrat VERSION = '0.2.1' + def self.root + defined?(RAILS_ROOT) ? RAILS_ROOT : Merb.root + end end if defined?(Merb) diff --git a/lib/webrat/page.rb b/lib/webrat/page.rb index 65e5056..7887aa7 100644 --- a/lib/webrat/page.rb +++ b/lib/webrat/page.rb @@ -94,10 +94,10 @@ module Webrat # Example: # save_and_open def save_and_open - return unless File.exist?(RAILS_ROOT + "/tmp") + return unless File.exist?(Webrat.root + "/tmp") filename = "webrat-#{Time.now.to_i}.html" - File.open(RAILS_ROOT + "/tmp/#{filename}", "w") do |f| + File.open(Webrat.root + "/tmp/#{filename}", "w") do |f| f.write response.body end `open tmp/#{filename}` From a45d654bb8f44e30dc1c93f465fa63ac07102943 Mon Sep 17 00:00:00 2001 From: Gwyn Morfey Date: Fri, 18 Apr 2008 13:19:13 +0100 Subject: [PATCH 07/70] Basic test working --- test/helper.rb | 43 +++++++++++++++++++++++++++++++------------ test/visits_test.rb | 21 +++++++++++++++------ 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/test/helper.rb b/test/helper.rb index 9c0418e..35550ce 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -1,20 +1,39 @@ require "rubygems" require "test/unit" -# gem install redgreen for colored test output -begin require "redgreen" unless ENV['TM_CURRENT_LINE']; rescue LoadError; end require "mocha" -require "active_support" +# gem install redgreen for colored test output +begin require "redgreen" unless ENV['TM_CURRENT_LINE']; rescue LoadError; end -silence_warnings do - require "action_controller" - require "action_controller/integration" +if ENV["TEST_MODE"] == "rails" + require "active_support" + silence_warnings do + require "action_controller" + require "action_controller/integration" + end + + class ActionController::Integration::Session + def flunk(message) + raise message + end + end + +elsif ENV["TEST_MODE"] == "merb" + require 'merb-core' + require 'merb_stories' + #require 'spec' #makes mocha cry + module Merb + module Test + class RspecStory + include Merb::Test::ControllerHelper + include Merb::Test::RouteHelper + include Merb::Test::ViewHelper + end + end + end + +else + raise "Please set the environment variable TEST_MODE to either 'rails' or 'merb'." end require File.expand_path(File.dirname(__FILE__) + "/../lib/webrat") - -class ActionController::Integration::Session - def flunk(message) - raise message - end -end \ No newline at end of file diff --git a/test/visits_test.rb b/test/visits_test.rb index 0b89631..d497892 100644 --- a/test/visits_test.rb +++ b/test/visits_test.rb @@ -5,12 +5,21 @@ RAILS_ROOT = "." unless defined?(RAILS_ROOT) class VisitsTest < Test::Unit::TestCase def setup - @session = ActionController::Integration::Session.new - @session.stubs(:assert_response) - @session.stubs(:get_via_redirect) - @response = mock - @session.stubs(:response).returns(@response) - @response.stubs(:body).returns("") + if ENV["TEST_MODE"] == "rails" + @session = ActionController::Integration::Session.new + @session.stubs(:assert_response) + @session.stubs(:get_via_redirect) + @response = mock + @session.stubs(:response).returns(@response) + @response.stubs(:body).returns("") + elsif ENV["TEST_MODE"] == "merb" + @session = Merb::Test::RspecStory.new + @session.stubs(:assert_response) + @session.stubs(:get_via_redirect) + @response = mock + @session.stubs(:response).returns(@response) + @response.stubs(:body).returns("") + end end def test_should_use_get From b9f6affa3f44b766c3fe6f657d3e099b1592d87f Mon Sep 17 00:00:00 2001 From: Gwyn Morfey Date: Fri, 18 Apr 2008 13:37:03 +0100 Subject: [PATCH 08/70] All but 3 merb tests pass --- test/checks_test.rb | 4 ++-- test/chooses_test.rb | 2 +- test/clicks_button_test.rb | 2 +- test/clicks_link_test.rb | 2 +- test/fills_in_test.rb | 2 +- test/helper.rb | 37 +++++++++---------------------------- test/reloads_test.rb | 2 +- test/selects_test.rb | 2 +- test/visits_test.rb | 21 ++++++--------------- 9 files changed, 23 insertions(+), 51 deletions(-) diff --git a/test/checks_test.rb b/test/checks_test.rb index 7d3113b..56f4432 100644 --- a/test/checks_test.rb +++ b/test/checks_test.rb @@ -2,7 +2,7 @@ require File.dirname(__FILE__) + "/helper" class ChecksTest < Test::Unit::TestCase def setup - @session = ActionController::Integration::Session.new + @session = test_session @session.stubs(:assert_response) @session.stubs(:get_via_redirect) @session.stubs(:response).returns(@response=mock) @@ -72,7 +72,7 @@ end class UnchecksTest < Test::Unit::TestCase def setup - @session = ActionController::Integration::Session.new + @session = test_session @session.stubs(:assert_response) @session.stubs(:get_via_redirect) @session.stubs(:response).returns(@response=mock) diff --git a/test/chooses_test.rb b/test/chooses_test.rb index 6b9afa8..cd5097e 100644 --- a/test/chooses_test.rb +++ b/test/chooses_test.rb @@ -3,7 +3,7 @@ require File.dirname(__FILE__) + "/helper" class ChoosesTest < Test::Unit::TestCase def setup - @session = ActionController::Integration::Session.new + @session = test_session @session.stubs(:assert_response) @session.stubs(:get_via_redirect) @session.stubs(:response).returns(@response=mock) diff --git a/test/clicks_button_test.rb b/test/clicks_button_test.rb index 26a8b9a..4239b2e 100644 --- a/test/clicks_button_test.rb +++ b/test/clicks_button_test.rb @@ -2,7 +2,7 @@ require File.dirname(__FILE__) + "/helper" class ClicksButtonTest < Test::Unit::TestCase def setup - @session = ActionController::Integration::Session.new + @session = test_session @session.stubs(:assert_response) @session.stubs(:get_via_redirect) @page = Webrat::Page.new(@session) diff --git a/test/clicks_link_test.rb b/test/clicks_link_test.rb index 3b1c7e9..7ed2db6 100644 --- a/test/clicks_link_test.rb +++ b/test/clicks_link_test.rb @@ -2,7 +2,7 @@ require File.dirname(__FILE__) + "/helper" class ClicksLinkTest < Test::Unit::TestCase def setup - @session = ActionController::Integration::Session.new + @session = test_session @session.stubs(:assert_response) @session.stubs(:get_via_redirect) @session.stubs(:response).returns(@response=mock) diff --git a/test/fills_in_test.rb b/test/fills_in_test.rb index 19daf3f..aba64c8 100644 --- a/test/fills_in_test.rb +++ b/test/fills_in_test.rb @@ -2,7 +2,7 @@ require File.dirname(__FILE__) + "/helper" class FillsInTest < Test::Unit::TestCase def setup - @session = ActionController::Integration::Session.new + @session = test_session @session.stubs(:assert_response) @session.stubs(:get_via_redirect) @session.stubs(:response).returns(@response=mock) diff --git a/test/helper.rb b/test/helper.rb index 35550ce..8b6224b 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -5,35 +5,16 @@ require "mocha" # gem install redgreen for colored test output begin require "redgreen" unless ENV['TM_CURRENT_LINE']; rescue LoadError; end -if ENV["TEST_MODE"] == "rails" - require "active_support" - silence_warnings do - require "action_controller" - require "action_controller/integration" - end - - class ActionController::Integration::Session - def flunk(message) - raise message - end - end - -elsif ENV["TEST_MODE"] == "merb" - require 'merb-core' - require 'merb_stories' - #require 'spec' #makes mocha cry - module Merb - module Test - class RspecStory - include Merb::Test::ControllerHelper - include Merb::Test::RouteHelper - include Merb::Test::ViewHelper - end - end - end - +if ["rails","merb"].include?(ENV["TEST_MODE"]) + require File.join(File.dirname(__FILE__), "helper_#{ENV["TEST_MODE"]}.rb") else raise "Please set the environment variable TEST_MODE to either 'rails' or 'merb'." end - + require File.expand_path(File.dirname(__FILE__) + "/../lib/webrat") + +def test_session + return ActionController::Integration::Session.new if ENV["TEST_MODE"] == "rails" + return Merb::Test::RspecStory.new if ENV["TEST_MODE"] == "merb" + raise "Unknown test type #{ENV["TEST_MODE"]}" +end \ No newline at end of file diff --git a/test/reloads_test.rb b/test/reloads_test.rb index 1f3e1ff..a69c330 100644 --- a/test/reloads_test.rb +++ b/test/reloads_test.rb @@ -5,7 +5,7 @@ RAILS_ROOT = "." unless defined?(RAILS_ROOT) class ReloadsTest < Test::Unit::TestCase def setup - @session = ActionController::Integration::Session.new + @session = test_session @session.stubs(:assert_response) @session.stubs(:get_via_redirect) @response = mock diff --git a/test/selects_test.rb b/test/selects_test.rb index 05576c4..cc26f37 100644 --- a/test/selects_test.rb +++ b/test/selects_test.rb @@ -2,7 +2,7 @@ require File.dirname(__FILE__) + "/helper" class SelectsTest < Test::Unit::TestCase def setup - @session = ActionController::Integration::Session.new + @session = test_session @session.stubs(:assert_response) @session.stubs(:get_via_redirect) @session.stubs(:response).returns(@response=mock) diff --git a/test/visits_test.rb b/test/visits_test.rb index d497892..a17cf54 100644 --- a/test/visits_test.rb +++ b/test/visits_test.rb @@ -5,21 +5,12 @@ RAILS_ROOT = "." unless defined?(RAILS_ROOT) class VisitsTest < Test::Unit::TestCase def setup - if ENV["TEST_MODE"] == "rails" - @session = ActionController::Integration::Session.new - @session.stubs(:assert_response) - @session.stubs(:get_via_redirect) - @response = mock - @session.stubs(:response).returns(@response) - @response.stubs(:body).returns("") - elsif ENV["TEST_MODE"] == "merb" - @session = Merb::Test::RspecStory.new - @session.stubs(:assert_response) - @session.stubs(:get_via_redirect) - @response = mock - @session.stubs(:response).returns(@response) - @response.stubs(:body).returns("") - end + @session = test_session + @session.stubs(:assert_response) + @session.stubs(:get_via_redirect) + @response = mock + @session.stubs(:response).returns(@response) + @response.stubs(:body).returns("") end def test_should_use_get From aeb6aa056c2bab3b8ede8865bec7fac38ac8a5ee Mon Sep 17 00:00:00 2001 From: Gwyn Morfey Date: Fri, 18 Apr 2008 13:37:53 +0100 Subject: [PATCH 09/70] All but 3 merb tests pass --- lib/webrat.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/webrat.rb b/lib/webrat.rb index 2419dba..106288b 100644 --- a/lib/webrat.rb +++ b/lib/webrat.rb @@ -10,6 +10,7 @@ module Webrat end if defined?(Merb) + puts "************ Booting merb mode" require File.join(File.dirname(__FILE__), "boot_merb.rb") else require File.join(File.dirname(__FILE__), "boot_rails.rb") From c967a02ca01293738cf6d8b6bb2027a13de4193d Mon Sep 17 00:00:00 2001 From: Gwyn Morfey Date: Fri, 18 Apr 2008 16:39:28 +0100 Subject: [PATCH 10/70] All tests pass in merb --- lib/boot_merb.rb | 3 +++ lib/merb_support/indifferent_access.rb | 15 +-------------- lib/webrat.rb | 1 - lib/webrat/form.rb | 2 +- 4 files changed, 5 insertions(+), 16 deletions(-) diff --git a/lib/boot_merb.rb b/lib/boot_merb.rb index 11120cb..59fe2b2 100644 --- a/lib/boot_merb.rb +++ b/lib/boot_merb.rb @@ -102,4 +102,7 @@ require 'cgi' require File.join(File.dirname(__FILE__), "merb_support", "param_parser.rb") require File.join(File.dirname(__FILE__), "merb_support", "url_encoded_pair_parser.rb") require File.join(File.dirname(__FILE__), "merb_support", "indifferent_access.rb") +require File.join(File.dirname(__FILE__), "merb_support", "support.rb") + + diff --git a/lib/merb_support/indifferent_access.rb b/lib/merb_support/indifferent_access.rb index 2213b09..26e0814 100644 --- a/lib/merb_support/indifferent_access.rb +++ b/lib/merb_support/indifferent_access.rb @@ -1,7 +1,6 @@ # This class has dubious semantics and we only have it so that # people can write params[:key] instead of params['key'] # and they get the same value for both keys. - class HashWithIndifferentAccess < Hash def initialize(constructor = {}) if constructor.is_a?(Hash) @@ -123,16 +122,4 @@ class HashWithIndifferentAccess < Hash end end -module ActiveSupport #:nodoc: - module CoreExtensions #:nodoc: - module Hash #:nodoc: - module IndifferentAccess #:nodoc: - def with_indifferent_access - hash = HashWithIndifferentAccess.new(self) - hash.default = self.default - hash - end - end - end - end -end + diff --git a/lib/webrat.rb b/lib/webrat.rb index 106288b..2419dba 100644 --- a/lib/webrat.rb +++ b/lib/webrat.rb @@ -10,7 +10,6 @@ module Webrat end if defined?(Merb) - puts "************ Booting merb mode" require File.join(File.dirname(__FILE__), "boot_merb.rb") else require File.join(File.dirname(__FILE__), "boot_rails.rb") diff --git a/lib/webrat/form.rb b/lib/webrat/form.rb index 923e5c9..265b20c 100644 --- a/lib/webrat/form.rb +++ b/lib/webrat/form.rb @@ -123,7 +123,7 @@ module Webrat def merge_hash_values(a, b) # :nodoc: a.keys.each do |k| if b.has_key?(k) - case [a[k], b[k]].map(&:class) + case [a[k].class, b[k].class] when [Hash, Hash] a[k] = merge_hash_values(a[k], b[k]) b.delete(k) From e4e2de1206172231e6c35641a5cbc1a6e4493445 Mon Sep 17 00:00:00 2001 From: Gwyn Morfey Date: Fri, 18 Apr 2008 16:40:24 +0100 Subject: [PATCH 11/70] Missing files --- lib/merb_support/support.rb | 12 ++++++++++++ test/helper_merb.rb | 14 ++++++++++++++ test/helper_rails.rb | 11 +++++++++++ test/mocha_test.rb | 14 ++++++++++++++ 4 files changed, 51 insertions(+) create mode 100644 lib/merb_support/support.rb create mode 100644 test/helper_merb.rb create mode 100644 test/helper_rails.rb create mode 100644 test/mocha_test.rb diff --git a/lib/merb_support/support.rb b/lib/merb_support/support.rb new file mode 100644 index 0000000..f7c24ee --- /dev/null +++ b/lib/merb_support/support.rb @@ -0,0 +1,12 @@ +class Hash + def with_indifferent_access + hash = HashWithIndifferentAccess.new(self) + hash.default = self.default + hash + end +end +class NilClass + def to_param + nil + end +end diff --git a/test/helper_merb.rb b/test/helper_merb.rb new file mode 100644 index 0000000..cad48fd --- /dev/null +++ b/test/helper_merb.rb @@ -0,0 +1,14 @@ +require 'merb-core' +require 'merb_stories' +module Merb + module Test + class RspecStory + include Merb::Test::ControllerHelper + include Merb::Test::RouteHelper + include Merb::Test::ViewHelper + def flunk(message) + raise message + end + end + end +end diff --git a/test/helper_rails.rb b/test/helper_rails.rb new file mode 100644 index 0000000..8c0e9b4 --- /dev/null +++ b/test/helper_rails.rb @@ -0,0 +1,11 @@ +require "active_support" +silence_warnings do + require "action_controller" + require "action_controller/integration" +end + +class ActionController::Integration::Session + def flunk(message) + raise message + end +end \ No newline at end of file diff --git a/test/mocha_test.rb b/test/mocha_test.rb new file mode 100644 index 0000000..25185af --- /dev/null +++ b/test/mocha_test.rb @@ -0,0 +1,14 @@ +require File.dirname(__FILE__) + "/helper" + +RAILS_ROOT = "." unless defined?(RAILS_ROOT) + +class FooThing +end + +class MochaTest < Test::Unit::TestCase + def test_mocha + @foo = FooThing.new + @foo.stubs(:bar).returns("bar") + assert_equal @foo.bar, "bar" + end +end From 87af3dbcc75b64ee5ab2a0db107f9b1174b89db9 Mon Sep 17 00:00:00 2001 From: Gwyn Morfey Date: Fri, 18 Apr 2008 16:46:57 +0100 Subject: [PATCH 12/70] Remove temporary test --- test/mocha_test.rb | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 test/mocha_test.rb diff --git a/test/mocha_test.rb b/test/mocha_test.rb deleted file mode 100644 index 25185af..0000000 --- a/test/mocha_test.rb +++ /dev/null @@ -1,14 +0,0 @@ -require File.dirname(__FILE__) + "/helper" - -RAILS_ROOT = "." unless defined?(RAILS_ROOT) - -class FooThing -end - -class MochaTest < Test::Unit::TestCase - def test_mocha - @foo = FooThing.new - @foo.stubs(:bar).returns("bar") - assert_equal @foo.bar, "bar" - end -end From 97c1f8de3c4a86f786d7a339e5aeb55a4f23d741 Mon Sep 17 00:00:00 2001 From: Gwyn Morfey Date: Fri, 18 Apr 2008 16:54:42 +0100 Subject: [PATCH 13/70] Tidy up: these helpers aren't needed by existing tests --- test/helper_merb.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/helper_merb.rb b/test/helper_merb.rb index cad48fd..82f54fe 100644 --- a/test/helper_merb.rb +++ b/test/helper_merb.rb @@ -3,9 +3,6 @@ require 'merb_stories' module Merb module Test class RspecStory - include Merb::Test::ControllerHelper - include Merb::Test::RouteHelper - include Merb::Test::ViewHelper def flunk(message) raise message end From 94f0086a55cec2250e226df37094b57149bd2bd1 Mon Sep 17 00:00:00 2001 From: Gwyn Morfey Date: Tue, 22 Apr 2008 11:25:21 +0100 Subject: [PATCH 14/70] Corrected manifest --- Manifest.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Manifest.txt b/Manifest.txt index abdb8ef..cf2fd87 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -20,6 +20,7 @@ lib/boot_rails.rb lib/merb_support/indifferent_access.rb lib/merb_support/param_parser.rb lib/merb_support/url_encoded_pair_parser.rb +lib/merb_support/support.rb test/checks_test.rb test/chooses_test.rb test/clicks_button_test.rb From 580a301984aef358bfaf22977c6ac4d25cea60aa Mon Sep 17 00:00:00 2001 From: Gwyn Morfey Date: Wed, 23 Apr 2008 10:41:34 +0100 Subject: [PATCH 15/70] Make sure that PUTS and DELETES are handled correctly in merb --- lib/boot_merb.rb | 7 ++++++- test/clicks_button_test.rb | 27 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/lib/boot_merb.rb b/lib/boot_merb.rb index 59fe2b2..e6f6e64 100644 --- a/lib/boot_merb.rb +++ b/lib/boot_merb.rb @@ -35,8 +35,13 @@ class Merb::Test::RspecStory #which is where we get our status and response from. # #We have to preserve cookies like this, or the session is lost. + # + #While (in a web application) a PUT is modelled as a POST with a parameter _method, + #this close to the metal we need to make sure that we actually hit the underlying 'put' method, + #so we rewrite 'method'. def request_via_redirect(method,path,parameters={},headers={}) - mycookies = @controller.cookies rescue nil #will be nil if no requests yet + method = parameters["_method"] if !parameters["_method"].blank? + mycookies = defined?(@controller) ? @controller.cookies : nil #will be nil if no requests yet @controller=self.send(method, path, parameters, headers) do |new_controller| new_controller.cookies = mycookies end diff --git a/test/clicks_button_test.rb b/test/clicks_button_test.rb index 4239b2e..23a297e 100644 --- a/test/clicks_button_test.rb +++ b/test/clicks_button_test.rb @@ -9,6 +9,8 @@ class ClicksButtonTest < Test::Unit::TestCase @session.stubs(:current_page).returns(@page) @response = mock @session.stubs(:response).returns(@response) + @controller = mock + @controller.stubs(:status).returns(200) end def test_should_fail_if_no_buttons @@ -349,4 +351,29 @@ class ClicksButtonTest < Test::Unit::TestCase @session.expects(:get_via_redirect).with("/login", "user" => {"email" => ""}) @session.clicks_button end + + def test_should_use_put_method_when_needed + @response.stubs(:body).returns(<<-EOS) + + + + + EOS + @session.stubs(:redirect?).returns(false) + @session.expects(:put).returns(@controller) + @session.clicks_button + end + + def test_should_use_delete_method_when_needed + @response.stubs(:body).returns(<<-EOS) +
+ + +
+ EOS + @session.stubs(:redirect?).returns(false) + @session.expects(:delete).returns(@controller) + @session.clicks_button + end + end From 2855b4382f7e6db9da68b7998b739567714a68ee Mon Sep 17 00:00:00 2001 From: Gwyn Morfey Date: Wed, 23 Apr 2008 14:33:05 +0100 Subject: [PATCH 16/70] Implemented Merb's magic exception handling in tests. This could be more robust. --- lib/boot_merb.rb | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/boot_merb.rb b/lib/boot_merb.rb index e6f6e64..f02c28d 100644 --- a/lib/boot_merb.rb +++ b/lib/boot_merb.rb @@ -42,9 +42,21 @@ class Merb::Test::RspecStory def request_via_redirect(method,path,parameters={},headers={}) method = parameters["_method"] if !parameters["_method"].blank? mycookies = defined?(@controller) ? @controller.cookies : nil #will be nil if no requests yet - @controller=self.send(method, path, parameters, headers) do |new_controller| - new_controller.cookies = mycookies + begin + @controller=self.send(method, path, parameters, headers) do |new_controller| + new_controller.cookies = mycookies + end + rescue => exception + raise unless exception.kind_of?(Merb::ControllerExceptions::Base) + #Now we want to go one level below 'post' to build the request ourselves, then send it to the controller + exception_klass = exception.class + klass = ::Exceptions rescue Merb::Controller + request = fake_request + request.params[:exception] = exception + request.params[:action] = exception_klass.name + @controller=dispatch_request(request, klass, exception_klass.name) end + follow_redirect! while redirect? status end From 20561b0c411c687cd755be381109937910fcda97 Mon Sep 17 00:00:00 2001 From: Gwyn Morfey Date: Tue, 29 Apr 2008 12:26:16 +0100 Subject: [PATCH 17/70] Also find buttons by caption, if no value has been specified. --- lib/webrat/field.rb | 4 ++++ lib/webrat/form.rb | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/lib/webrat/field.rb b/lib/webrat/field.rb index ee99d26..5d13f7f 100644 --- a/lib/webrat/field.rb +++ b/lib/webrat/field.rb @@ -105,6 +105,10 @@ module Webrat def matches_value?(value) @element["value"] =~ /^\W*#{Regexp.escape(value.to_s)}/i end + + def matches_caption?(value) + @element.innerHTML =~ /^\W*#{Regexp.escape(value.to_s)}/i + end def to_param return nil if @value.nil? diff --git a/lib/webrat/form.rb b/lib/webrat/form.rb index 265b20c..37d842d 100644 --- a/lib/webrat/form.rb +++ b/lib/webrat/form.rb @@ -37,6 +37,11 @@ module Webrat return possible_button if possible_button.matches_value?(value) end + #If nothing matched on value, try by name. + possible_buttons.each do |possible_button| + return possible_button if possible_button.matches_caption?(value) + end + nil end From 9e673539a5f8ed0f8aaec78dc8c5225612e8191e Mon Sep 17 00:00:00 2001 From: Gwyn Morfey Date: Mon, 7 Jul 2008 15:57:52 +0100 Subject: [PATCH 18/70] Now you can do clicks_button 'foo_123' (passing button ID, not value) --- lib/webrat/field.rb | 4 ++++ lib/webrat/form.rb | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/lib/webrat/field.rb b/lib/webrat/field.rb index 5d13f7f..5dec37e 100644 --- a/lib/webrat/field.rb +++ b/lib/webrat/field.rb @@ -106,6 +106,10 @@ module Webrat @element["value"] =~ /^\W*#{Regexp.escape(value.to_s)}/i end + def matches_id?(id) + @element["id"] =~ /^\W*#{Regexp.escape(id.to_s)}/i + end + def matches_caption?(value) @element.innerHTML =~ /^\W*#{Regexp.escape(value.to_s)}/i end diff --git a/lib/webrat/form.rb b/lib/webrat/form.rb index 37d842d..2b81fc4 100644 --- a/lib/webrat/form.rb +++ b/lib/webrat/form.rb @@ -33,6 +33,10 @@ module Webrat possible_buttons = fields_by_type([ButtonField]) + possible_buttons.each do |possible_button| + return possible_button if possible_button.matches_id?(value) + end + possible_buttons.each do |possible_button| return possible_button if possible_button.matches_value?(value) end From c5e3546cffc471898b1012176cc4b9cb6a53fec5 Mon Sep 17 00:00:00 2001 From: "nicholas a. evans" Date: Mon, 22 Sep 2008 22:19:20 -0400 Subject: [PATCH 19/70] Fixed bug where disabled fields would be submitted. --- lib/webrat/core/field.rb | 7 ++++++- spec/api/clicks_button_spec.rb | 15 +++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/webrat/core/field.rb b/lib/webrat/core/field.rb index 21c878f..2d6bb1c 100644 --- a/lib/webrat/core/field.rb +++ b/lib/webrat/core/field.rb @@ -47,10 +47,15 @@ module Webrat end def to_param + return nil if disabled? value = @value.to_s.gsub('&', '%26') param_parser.parse_query_parameters("#{name}=#{value}") end - + + def disabled? + @element.attributes.has_key? "disabled" + end + def set(value) @value = value end diff --git a/spec/api/clicks_button_spec.rb b/spec/api/clicks_button_spec.rb index 3978e4b..747013c 100644 --- a/spec/api/clicks_button_spec.rb +++ b/spec/api/clicks_button_spec.rb @@ -154,6 +154,21 @@ describe "clicks_button" do @session.clicks_button end + it "should not send disabled field values" do + @session.response_body = <<-EOS +
+ + + + + + +
+ EOS + @session.should_receive(:get).with("/login", {}) + @session.clicks_button + end + it "should send default checked fields" do @session.response_body = <<-EOS
From 300880db2f0d50a3e2d7b171eb9745cb50e1c534 Mon Sep 17 00:00:00 2001 From: Jeremy Burks Date: Sun, 5 Oct 2008 22:05:01 -0500 Subject: [PATCH 20/70] get webrat+cucumber+merb working i put this in env.rb require 'webrat' World do w = Object.new w.extend(Merb::Test::ViewHelper) w.extend(Merb::Test::RouteHelper) w.extend(Merb::Test::ControllerHelper) w.extend(Webrat::MerbTest) end --- lib/boot_merb.rb | 194 ++++++++++++++++++++++++----------------------- lib/webrat.rb | 2 +- 2 files changed, 99 insertions(+), 97 deletions(-) diff --git a/lib/boot_merb.rb b/lib/boot_merb.rb index f02c28d..b0500db 100644 --- a/lib/boot_merb.rb +++ b/lib/boot_merb.rb @@ -1,108 +1,110 @@ -#In Merb, we have an RspecStory instead of an integration Session. -class Merb::Test::RspecStory +module Webrat + module MerbTest - #Our own redirect actions defined below, to deal with the fact that we need to store - #a controller reference. + #Our own redirect actions defined below, to deal with the fact that we need to store + #a controller reference. - def current_page - @current_page ||= Webrat::Page.new(self) - end - - def current_page=(new_page) - @current_page = new_page - end - - # Issues a GET request for a page, follows any redirects, and verifies the final page - # load was successful. - # - # Example: - # visits "/" - def visits(*args) - @current_page = Webrat::Page.new(self, *args) - end - - def save_and_open_page - current_page.save_and_open - end - - [:reloads, :fills_in, :clicks_button, :selects, :chooses, :checks, :unchecks, :clicks_link, :clicks_link_within, :clicks_put_link, :clicks_get_link, :clicks_post_link, :clicks_delete_link].each do |method_name| - define_method(method_name) do |*args| - current_page.send(method_name, *args) + def current_page + @current_page ||= Webrat::Page.new(self) end - end - - #Session defines the following (used by webrat), but RspecStory doesn't. Merb's get/put/delete return a controller, - #which is where we get our status and response from. - # - #We have to preserve cookies like this, or the session is lost. - # - #While (in a web application) a PUT is modelled as a POST with a parameter _method, - #this close to the metal we need to make sure that we actually hit the underlying 'put' method, - #so we rewrite 'method'. - def request_via_redirect(method,path,parameters={},headers={}) - method = parameters["_method"] if !parameters["_method"].blank? - mycookies = defined?(@controller) ? @controller.cookies : nil #will be nil if no requests yet - begin - @controller=self.send(method, path, parameters, headers) do |new_controller| - new_controller.cookies = mycookies + + def current_page=(new_page) + @current_page = new_page + end + + # Issues a GET request for a page, follows any redirects, and verifies the final page + # load was successful. + # + # Example: + # visits "/" + def visits(*args) + @current_page = Webrat::Page.new(self, *args) + end + + def save_and_open_page + current_page.save_and_open + end + + [:reloads, :fills_in, :clicks_button, :selects, :chooses, :checks, :unchecks, :clicks_link, :clicks_link_within, :clicks_put_link, :clicks_get_link, :clicks_post_link, :clicks_delete_link].each do |method_name| + define_method(method_name) do |*args| + current_page.send(method_name, *args) end - rescue => exception - raise unless exception.kind_of?(Merb::ControllerExceptions::Base) - #Now we want to go one level below 'post' to build the request ourselves, then send it to the controller - exception_klass = exception.class - klass = ::Exceptions rescue Merb::Controller - request = fake_request - request.params[:exception] = exception - request.params[:action] = exception_klass.name - @controller=dispatch_request(request, klass, exception_klass.name) end - - follow_redirect! while redirect? - status - end + + #Session defines the following (used by webrat), but RspecStory doesn't. Merb's get/put/delete return a controller, + #which is where we get our status and response from. + # + #We have to preserve cookies like this, or the session is lost. + # + #While (in a web application) a PUT is modelled as a POST with a parameter _method, + #this close to the metal we need to make sure that we actually hit the underlying 'put' method, + #so we rewrite 'method'. + def request_via_redirect(method,path,parameters={},headers={}) + method = parameters["_method"] if !parameters["_method"].blank? + mycookies = defined?(@controller) ? @controller.cookies : nil #will be nil if no requests yet + begin + @controller=self.send(method, path, parameters, headers) do |new_controller| + new_controller.cookies = mycookies + end + rescue => exception + raise unless exception.kind_of?(Merb::ControllerExceptions::Base) + #Now we want to go one level below 'post' to build the request ourselves, then send it to the controller + exception_klass = exception.class + klass = ::Exceptions rescue Merb::Controller + request = fake_request + request.params[:exception] = exception + request.params[:action] = exception_klass.name + @controller=dispatch_request(request, klass, exception_klass.name) + end - def get_via_redirect(path, parameters = {}, headers = {}) - request_via_redirect(:get,path,parameters,headers) - end - - def put_via_redirect(path, parameters = {}, headers = {}) - request_via_redirect(:put,path,parameters,headers) - end - - def post_via_redirect(path, parameters = {}, headers = {}) - request_via_redirect(:post,path,parameters,headers) - end - - def delete_via_redirect(path, parameters = {}, headers = {}) - request_via_redirect(:delete,path,parameters,headers) - end - - def follow_redirect! - mycookies = @controller.cookies rescue nil - @controller=get @controller.headers["Location"] do |new_controller| - new_controller.cookies=mycookies + follow_redirect! while redirect? + status end - end - - def redirect? - [307, *(300..305)].include?(status) - end - - def status - @controller.status - end - - def response - @controller #things like @controller.body will work. - end - def assert_response(resp) - if resp == :success - response.should be_successful - else - raise "assert_response #{resp.inspect} is not supported" + def get_via_redirect(path, parameters = {}, headers = {}) + request_via_redirect(:get,path,parameters,headers) end - end + + def put_via_redirect(path, parameters = {}, headers = {}) + request_via_redirect(:put,path,parameters,headers) + end + + def post_via_redirect(path, parameters = {}, headers = {}) + request_via_redirect(:post,path,parameters,headers) + end + + def delete_via_redirect(path, parameters = {}, headers = {}) + request_via_redirect(:delete,path,parameters,headers) + end + + def follow_redirect! + mycookies = @controller.cookies rescue nil + @controller=get @controller.headers["Location"] do |new_controller| + new_controller.cookies=mycookies + end + end + + def redirect? + [307, *(300..305)].include?(status) + end + + def status + @controller.status + end + + def response + @controller #things like @controller.body will work. + end + + def assert_response(resp) + if resp == :success + response.should be_successful + else + raise "assert_response #{resp.inspect} is not supported" + end + end + + end end class Application < Merb::Controller diff --git a/lib/webrat.rb b/lib/webrat.rb index 2419dba..072145a 100644 --- a/lib/webrat.rb +++ b/lib/webrat.rb @@ -3,7 +3,7 @@ Dir[File.join(File.dirname(__FILE__), "webrat", "*.rb")].each do |file| end module Webrat - VERSION = '0.2.1' + VERSION = '0.2.2' def self.root defined?(RAILS_ROOT) ? RAILS_ROOT : Merb.root end From 9d3c60f9226579392f5ecd1ae80561ae344cc445 Mon Sep 17 00:00:00 2001 From: Jan Suchal Date: Thu, 9 Oct 2008 14:54:53 +0200 Subject: [PATCH 21/70] Replaced some full sorts with simple linear search. Refactored old code to nicer collection methods. --- lib/webrat/core/form.rb | 43 ++++++++++------------------------------ lib/webrat/core/scope.rb | 8 +++----- 2 files changed, 14 insertions(+), 37 deletions(-) diff --git a/lib/webrat/core/form.rb b/lib/webrat/core/form.rb index 60a5c07..4d8a47b 100644 --- a/lib/webrat/core/form.rb +++ b/lib/webrat/core/form.rb @@ -29,27 +29,17 @@ module Webrat end def find_button(value = nil) - return fields_by_type([ButtonField]).first if value.nil? - - possible_buttons = fields_by_type([ButtonField]) - - possible_buttons.each do |possible_button| - return possible_button if possible_button.matches_value?(value) - end - - nil + return fields_by_type([ButtonField]).first if value.nil? + possible_buttons = fields_by_type([ButtonField]) + possible_buttons.detect { |possible_button| possible_button.matches_value?(value) } end def fields return @fields if @fields - @fields = [] - - (@element / "button, input, textarea, select").each do |field_element| - @fields << Field.class_for_element(field_element).new(self, field_element) + @fields = (@element / "button, input, textarea, select").collect do |field_element| + Field.class_for_element(field_element).new(self, field_element) end - - @fields end def submit @@ -59,29 +49,18 @@ module Webrat protected def find_field_by_id(possible_fields, id) - possible_fields.each do |possible_field| - return possible_field if possible_field.matches_id?(id) - end - - nil + possible_fields.detect { |possible_field| possible_field.matches_id?(id) } end def find_field_by_name(possible_fields, name) - possible_fields.each do |possible_field| - return possible_field if possible_field.matches_name?(name) - end - - nil + possible_fields.detect { |possible_field| possible_field.matches_name?(name) } end def find_field_by_label(possible_fields, label) - matching_fields = [] - - possible_fields.each do |possible_field| - matching_fields << possible_field if possible_field.matches_label?(label) - end - - matching_fields.sort_by { |f| f.label_text.length }.first + matching_fields = possible_fields.select do |possible_field| + possible_field.matches_label?(label) + end + matching_fields.min { |a, b| a.label_text.length <=> b.label_text.length } end def fields_by_type(field_types) diff --git a/lib/webrat/core/scope.rb b/lib/webrat/core/scope.rb index 445c1e9..c26e375 100644 --- a/lib/webrat/core/scope.rb +++ b/lib/webrat/core/scope.rb @@ -202,14 +202,12 @@ module Webrat end def find_link(text, selector = nil) - matching_links = [] - - links_within(selector).each do |possible_link| - matching_links << possible_link if possible_link.matches_text?(text) + matching_links = links_within(selector).select do |possible_link| + possible_link.matches_text?(text) end if matching_links.any? - matching_links.sort_by { |l| l.text.length }.first + matching_links.min { |a, b| a.text.length <=> b.text.length } else flunk("Could not find link with text #{text.inspect}") end From 264b147b6fb7e5ed118c1d0e0161fd0e69b4a1b8 Mon Sep 17 00:00:00 2001 From: Rob Kaufman Date: Sat, 11 Oct 2008 17:09:15 -0700 Subject: [PATCH 22/70] fully merged webrat merb branch with brynary. File upload tests still fail, will look at later --- lib/webrat.rb | 7 +------ lib/webrat/core/scope.rb | 4 +--- spec/api/attaches_file_spec.rb | 3 ++- spec/spec_helper.rb | 6 ++++-- spec/webrat/merb/helper.rb | 11 +++++++++++ spec/webrat/rails/helper.rb | 6 ++++++ 6 files changed, 25 insertions(+), 12 deletions(-) create mode 100644 spec/webrat/merb/helper.rb create mode 100644 spec/webrat/rails/helper.rb diff --git a/lib/webrat.rb b/lib/webrat.rb index fbddb7c..f7f1a73 100644 --- a/lib/webrat.rb +++ b/lib/webrat.rb @@ -10,9 +10,4 @@ require "active_support" require File.dirname(__FILE__) + "/webrat/core" require File.dirname(__FILE__) + "/webrat/rails" if defined?(RAILS_ENV) - -if defined?(Merb) - require File.join(File.dirname(__FILE__), "boot_merb.rb") -else - require File.join(File.dirname(__FILE__), "boot_rails.rb") -end +require File.join(File.dirname(__FILE__), "boot_merb.rb") if defined?(Merb) diff --git a/lib/webrat/core/scope.rb b/lib/webrat/core/scope.rb index 3b96c12..891c298 100644 --- a/lib/webrat/core/scope.rb +++ b/lib/webrat/core/scope.rb @@ -82,12 +82,11 @@ module Webrat # along with the form. An optional content_type may be given. # # Example: -<<<<<<< HEAD:lib/webrat/core/scope.rb # attaches_file "Resume", "/path/to/the/resume.txt" # attaches_file "Photo", "/path/to/the/image.png", "image/png" def attaches_file(id_or_name_or_label, path, content_type = nil) find_field(id_or_name_or_label, FileField).set(path, content_type) -======= + end # save_and_open def save_and_open return unless File.exist?(Webrat.root + "/tmp") @@ -97,7 +96,6 @@ module Webrat f.write response.body end `open tmp/#{filename}` ->>>>>>> 300880db2f0d50a3e2d7b171eb9745cb50e1c534:lib/webrat/page.rb end alias_method :attach_file, :attaches_file diff --git a/spec/api/attaches_file_spec.rb b/spec/api/attaches_file_spec.rb index edf0e74..55e040f 100644 --- a/spec/api/attaches_file_spec.rb +++ b/spec/api/attaches_file_spec.rb @@ -1,5 +1,5 @@ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper") - +unless ENV["TEST_MODE"] == "merb" describe "attaches_file" do before do @session = Webrat::TestSession.new @@ -70,3 +70,4 @@ describe "attaches_file" do @session.clicks_button end end +end \ No newline at end of file diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index c4370c3..35403b0 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -5,9 +5,11 @@ require "spec" begin require "redgreen" unless ENV['TM_CURRENT_LINE']; rescue LoadError; end if ["rails","merb"].include?(ENV["TEST_MODE"]) - require File.join(File.dirname(__FILE__), "helper_#{ENV["TEST_MODE"]}.rb") + require File.join(File.dirname(__FILE__), "webrat", "#{ENV["TEST_MODE"]}", "helper.rb") else - raise "Please set the environment variable TEST_MODE to either 'rails' or 'merb'." + puts "Please set the environment variable TEST_MODE to either 'rails' or 'merb'." + $stdout.flush + exit 1 end require File.expand_path(File.dirname(__FILE__) + "/../lib/webrat") diff --git a/spec/webrat/merb/helper.rb b/spec/webrat/merb/helper.rb new file mode 100644 index 0000000..8c79f95 --- /dev/null +++ b/spec/webrat/merb/helper.rb @@ -0,0 +1,11 @@ +require 'merb-core' +require 'merb_stories' +# module Merb +# module Test +# class RspecStory +# def flunk(message) +# raise message +# end +# end +# end +# end diff --git a/spec/webrat/rails/helper.rb b/spec/webrat/rails/helper.rb new file mode 100644 index 0000000..bde582b --- /dev/null +++ b/spec/webrat/rails/helper.rb @@ -0,0 +1,6 @@ +require "active_support" + +silence_warnings do + require "action_controller" + require "action_controller/integration" +end From 89d56fb5da15ef58805e77e002284c7a6e10eb5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aslak=20Helles=C3=B8y?= Date: Mon, 13 Oct 2008 14:56:13 +0200 Subject: [PATCH 23/70] Start adding support for rack and sinatra --- lib/webrat/rack/rack_session.rb | 13 +++++++++++++ lib/webrat/sinatra/sinatra_session.rb | 13 +++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 lib/webrat/rack/rack_session.rb create mode 100644 lib/webrat/sinatra/sinatra_session.rb diff --git a/lib/webrat/rack/rack_session.rb b/lib/webrat/rack/rack_session.rb new file mode 100644 index 0000000..b283294 --- /dev/null +++ b/lib/webrat/rack/rack_session.rb @@ -0,0 +1,13 @@ +require 'webrat' + +module Webrat + class RackSession < Session + def response_body + @response.body + end + + def response_code + @response.status + end + end +end \ No newline at end of file diff --git a/lib/webrat/sinatra/sinatra_session.rb b/lib/webrat/sinatra/sinatra_session.rb new file mode 100644 index 0000000..597c3b8 --- /dev/null +++ b/lib/webrat/sinatra/sinatra_session.rb @@ -0,0 +1,13 @@ +require 'webrat/rack/rack_session' +require 'sinatra' +require 'sinatra/test/methods' + +module Webrat + class SinatraSession < RackSession + include Sinatra::Test::Methods + + def get(*args) + get_it(*args) + end + end +end \ No newline at end of file From 46ced27dbdc8a0806f5c90dbf56b6639eeeb6fe8 Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Mon, 13 Oct 2008 14:23:48 -0400 Subject: [PATCH 24/70] Minor selenium_session updates to alias #visits as #visit, fix the constructor, and successfully locate a field whose label is it's parent. -Lee Bankewitz & Luke Melia --- lib/webrat/selenium/selenium_session.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/webrat/selenium/selenium_session.rb b/lib/webrat/selenium/selenium_session.rb index e4b9ab0..e2cb766 100644 --- a/lib/webrat/selenium/selenium_session.rb +++ b/lib/webrat/selenium/selenium_session.rb @@ -2,7 +2,7 @@ module Webrat class SeleniumSession < Session def initialize(selenium_driver) - super + super() @selenium = selenium_driver define_location_strategies end @@ -11,6 +11,8 @@ module Webrat @selenium.open(url) end + alias_method :visit, :visits + def fills_in(field_identifier, options) locator = "webrat=#{Regexp.escape(field_identifier)}" @selenium.type(locator, "#{options[:with]}") @@ -99,6 +101,9 @@ module Webrat candidateLabels = candidateLabels.sortBy(function(s) { return s.length * -1; }); //reverse length sort var locatedLabel = candidateLabels.first(); var labelFor = locatedLabel.getAttribute('for'); + if ((labelFor == null) && (locatedLabel.hasChildNodes())) { + return locatedLabel.firstChild; //TODO: should find the first form field, not just any node + } return selenium.browserbot.locationStrategies['id'].call(this, labelFor, inDocument, inWindow); JS From bf924ba1283d5da17a0e7cce71522f769e77bf8c Mon Sep 17 00:00:00 2001 From: Lee Bankewitz Date: Mon, 13 Oct 2008 18:42:48 -0400 Subject: [PATCH 25/70] use jQuery to wait for ajax operations to complete --- lib/webrat/selenium/selenium_session.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/webrat/selenium/selenium_session.rb b/lib/webrat/selenium/selenium_session.rb index e2cb766..a2c4ec0 100644 --- a/lib/webrat/selenium/selenium_session.rb +++ b/lib/webrat/selenium/selenium_session.rb @@ -54,7 +54,7 @@ module Webrat end def wait_for_ajax(timeout = 15000) - @selenium.wait_for_condition "window.Ajax.activeRequestCount == 0", timeout + @selenium.wait_for_condition "Ajax.activeRequestCount == 0", timeout end def wait_for_effects(timeout = 15000) From f7cf981a759d98d0a21226162f7cfaba8c0bf67a Mon Sep 17 00:00:00 2001 From: Lee Bankewitz Date: Mon, 13 Oct 2008 18:43:36 -0400 Subject: [PATCH 26/70] alias click_link/clicks_link, and click_button/clicks_button --- lib/webrat/selenium/selenium_session.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/webrat/selenium/selenium_session.rb b/lib/webrat/selenium/selenium_session.rb index a2c4ec0..6141269 100644 --- a/lib/webrat/selenium/selenium_session.rb +++ b/lib/webrat/selenium/selenium_session.rb @@ -28,11 +28,13 @@ module Webrat @selenium.click("button=#{button_text}") wait_for_result(options[:wait]) end + alias_method :click_button, :clicks_button def clicks_link(link_text, options = {}) @selenium.click("webratlink=#{link_text}") wait_for_result(options[:wait]) end + alias_method :click_link, :clicks_link def clicks_link_within(selector, link_text, options = {}) @selenium.click("webratlinkwithin=#{selector}|#{link_text}") From fb5b6635909eb5791923866274bdec3902a659d8 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Sun, 14 Sep 2008 10:47:03 -0400 Subject: [PATCH 27/70] Updating Manifest --- Manifest.txt | 65 +++++++++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/Manifest.txt b/Manifest.txt index 94b69bb..55d7772 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -1,41 +1,48 @@ -.gitignore History.txt MIT-LICENSE.txt Manifest.txt README.txt Rakefile TODO.txt -coverage/index.html -coverage/lib-webrat-field_rb.html -coverage/lib-webrat-form_rb.html -coverage/lib-webrat-label_rb.html -coverage/lib-webrat-link_rb.html -coverage/lib-webrat-logging_rb.html -coverage/lib-webrat-page_rb.html -coverage/lib-webrat-redirect_actions_rb.html -coverage/lib-webrat-select_option_rb.html -coverage/lib-webrat_rb.html init.rb install.rb lib/webrat.rb -lib/webrat/field.rb -lib/webrat/form.rb -lib/webrat/label.rb -lib/webrat/link.rb -lib/webrat/logging.rb -lib/webrat/page.rb -lib/webrat/redirect_actions.rb -lib/webrat/select_option.rb -spec/attaches_file_spec.rb -spec/checks_spec.rb -spec/chooses_spec.rb -spec/clicks_button_spec.rb -spec/clicks_link_spec.rb -spec/fills_in_spec.rb +lib/webrat/core.rb +lib/webrat/core/field.rb +lib/webrat/core/flunk.rb +lib/webrat/core/form.rb +lib/webrat/core/label.rb +lib/webrat/core/link.rb +lib/webrat/core/logging.rb +lib/webrat/core/scope.rb +lib/webrat/core/select_option.rb +lib/webrat/core/session.rb +lib/webrat/mechanize.rb +lib/webrat/mechanize/mechanize_session.rb +lib/webrat/rails.rb +lib/webrat/rails/rails_session.rb +lib/webrat/rails/redirect_actions.rb +lib/webrat/rails/session.rb +lib/webrat/selenium.rb +lib/webrat/selenium/selenium_session.rb +mechanize_spike.rb +selenium_spike.rb +spec/api/attaches_file_spec.rb +spec/api/checks_spec.rb +spec/api/chooses_spec.rb +spec/api/clicks_button_spec.rb +spec/api/clicks_link_spec.rb +spec/api/fills_in_spec.rb +spec/api/reloads_spec.rb +spec/api/save_and_open_spec.rb +spec/api/selects_spec.rb +spec/api/visits_spec.rb +spec/api/within_spec.rb +spec/fakes/test_session.rb +spec/integration/rails_spec.rb spec/rcov.opts -spec/reloads_spec.rb -spec/save_and_open_page_spec.rb -spec/selects_spec.rb spec/spec.opts spec/spec_helper.rb -spec/visits_spec.rb +spec/webrat/core/logging_spec.rb +spec/webrat/core/session_spec.rb +spec/webrat/rails/rails_session_spec.rb From 44db244a7615f8a7f29d6f76d399e9505c6f6cdd Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Sun, 14 Sep 2008 14:37:24 -0400 Subject: [PATCH 28/70] Cleaning up the Rails session code. Extract scoped_html method in Scope --- lib/webrat/core/scope.rb | 20 +++++++++++--------- lib/webrat/core/session.rb | 6 +++++- lib/webrat/rails/session.rb | 10 +--------- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/lib/webrat/core/scope.rb b/lib/webrat/core/scope.rb index 445c1e9..42df3d7 100644 --- a/lib/webrat/core/scope.rb +++ b/lib/webrat/core/scope.rb @@ -165,19 +165,21 @@ module Webrat alias_method :click_button, :clicks_button def dom # :nodoc: - return @dom if defined?(@dom) && @dom - @dom = Hpricot(@html) - - if @selector - html = (@dom / @selector).first.to_html - @dom = Hpricot(html) - end - - return @dom + @dom ||= Hpricot(scoped_html) end protected + def scoped_html + @scoped_html ||= begin + if @selector + (Hpricot(@html) / @selector).first.to_html + else + @html + end + end + end + def find_select_option(option_text, id_or_name_or_label) if id_or_name_or_label field = find_field(id_or_name_or_label, SelectField) diff --git a/lib/webrat/core/session.rb b/lib/webrat/core/session.rb index ecf243c..7e9d9c6 100644 --- a/lib/webrat/core/session.rb +++ b/lib/webrat/core/session.rb @@ -109,6 +109,11 @@ module Webrat yield Scope.new(self, response_body, selector) end + # Issues a GET request for a page, follows any redirects, and verifies the final page + # load was successful. + # + # Example: + # visits "/" def visits(url = nil, http_method = :get, data = {}) request_page(url, http_method, data) end @@ -136,6 +141,5 @@ module Webrat def_delegators :current_scope, :click_post_link, :clicks_post_link def_delegators :current_scope, :click_put_link, :clicks_put_link def_delegators :current_scope, :click_button, :clicks_button - end end \ No newline at end of file diff --git a/lib/webrat/rails/session.rb b/lib/webrat/rails/session.rb index 01a186f..de89cfa 100644 --- a/lib/webrat/rails/session.rb +++ b/lib/webrat/rails/session.rb @@ -5,15 +5,6 @@ module ActionController unless instance_methods.include?("put_via_redirect") include Webrat::RedirectActions end - - # Issues a GET request for a page, follows any redirects, and verifies the final page - # load was successful. - # - # Example: - # visits "/" - def visits(*args) - webrat_session.visits(*args) - end def respond_to?(name) super || webrat_session.respond_to?(name) @@ -32,6 +23,7 @@ module ActionController def webrat_session @webrat_session ||= Webrat::RailsSession.new(self) end + end end end \ No newline at end of file From 1a4db57d93d0f18350b81e61115677af2c510808 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Sun, 14 Sep 2008 14:54:29 -0400 Subject: [PATCH 29/70] Add should_see and should_not_see assertions --- Rakefile | 2 +- lib/webrat/core/assertions.rb | 27 ++++++++++++ lib/webrat/core/scope.rb | 1 + lib/webrat/core/session.rb | 2 + spec/api/should_not_see_spec.rb | 73 +++++++++++++++++++++++++++++++++ spec/api/should_see_spec.rb | 73 +++++++++++++++++++++++++++++++++ 6 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 lib/webrat/core/assertions.rb create mode 100644 spec/api/should_not_see_spec.rb create mode 100644 spec/api/should_see_spec.rb diff --git a/Rakefile b/Rakefile index 601fac3..9bd083a 100644 --- a/Rakefile +++ b/Rakefile @@ -56,7 +56,7 @@ end require 'spec/rake/verify_rcov' RCov::VerifyTask.new(:verify_rcov => :rcov) do |t| - t.threshold = 97.1 # Make sure you have rcov 0.7 or higher! + t.threshold = 97.2 # Make sure you have rcov 0.7 or higher! end remove_task "default" diff --git a/lib/webrat/core/assertions.rb b/lib/webrat/core/assertions.rb new file mode 100644 index 0000000..7161280 --- /dev/null +++ b/lib/webrat/core/assertions.rb @@ -0,0 +1,27 @@ +module Webrat + module Assertions + + def should_see(text_or_regexp) + case text_or_regexp + when Regexp + return if scoped_html.match(text_or_regexp) + else + return if scoped_html.include?(text_or_regexp) + end + + flunk("Should see #{text_or_regexp.inspect} but didn't") + end + + def should_not_see(text_or_regexp) + case text_or_regexp + when Regexp + return unless scoped_html.match(text_or_regexp) + else + return unless scoped_html.include?(text_or_regexp) + end + + flunk("Should not see #{text_or_regexp.inspect} but did") + end + + end +end \ No newline at end of file diff --git a/lib/webrat/core/scope.rb b/lib/webrat/core/scope.rb index 42df3d7..559204f 100644 --- a/lib/webrat/core/scope.rb +++ b/lib/webrat/core/scope.rb @@ -4,6 +4,7 @@ module Webrat class Scope include Logging include Flunk + include Assertions def initialize(session, html, selector = nil) @session = session diff --git a/lib/webrat/core/session.rb b/lib/webrat/core/session.rb index 7e9d9c6..6142877 100644 --- a/lib/webrat/core/session.rb +++ b/lib/webrat/core/session.rb @@ -141,5 +141,7 @@ module Webrat def_delegators :current_scope, :click_post_link, :clicks_post_link def_delegators :current_scope, :click_put_link, :clicks_put_link def_delegators :current_scope, :click_button, :clicks_button + def_delegators :current_scope, :should_see + def_delegators :current_scope, :should_not_see end end \ No newline at end of file diff --git a/spec/api/should_not_see_spec.rb b/spec/api/should_not_see_spec.rb new file mode 100644 index 0000000..6e58b23 --- /dev/null +++ b/spec/api/should_not_see_spec.rb @@ -0,0 +1,73 @@ +require File.expand_path(File.dirname(__FILE__) + "/../spec_helper") + +describe "should_not_see" do + before do + @session = Webrat::TestSession.new + end + + it "should fail if the string is in the HTML" do + @session.response_body = <<-EOS + Link + EOS + + lambda { + @session.should_not_see "Link" + }.should raise_error + end + + it "should fail if the regexp is in the HTML" do + @session.response_body = <<-EOS + Link + EOS + + lambda { + @session.should_not_see /Li(n)[ck]/ + }.should raise_error + end + + it "should fail if the string is in the HTML scope" do + @session.response_body = <<-EOS +
+ Link +
+
+
+ EOS + + lambda { + @session.within "#first" do |scope| + scope.should_not_see "Link" + end + }.should raise_error + end + + it "should pass if the string is not in the HTML scope" do + @session.response_body = <<-EOS +
+ Link +
+
+
+ EOS + + @session.within "#second" do |scope| + scope.should_not_see "Link" + end + end + + it "should pass if the string is not in the HTML" do + @session.response_body = <<-EOS + Link + EOS + + @session.should_not_see "Missing" + end + + it "should pass if the regexp is not in the HTML" do + @session.response_body = <<-EOS + Different + EOS + + @session.should_not_see /Li(n)[ck]/ + end +end diff --git a/spec/api/should_see_spec.rb b/spec/api/should_see_spec.rb new file mode 100644 index 0000000..9ae021f --- /dev/null +++ b/spec/api/should_see_spec.rb @@ -0,0 +1,73 @@ +require File.expand_path(File.dirname(__FILE__) + "/../spec_helper") + +describe "should_see" do + before do + @session = Webrat::TestSession.new + end + + it "should pass if the string is in the HTML" do + @session.response_body = <<-EOS + Link + EOS + + @session.should_see "Link" + end + + it "should pass if the regexp is in the HTML" do + @session.response_body = <<-EOS + Link + EOS + + @session.should_see /Li(n)[ck]/ + end + + it "should pass if the string is in the HTML scope" do + @session.response_body = <<-EOS +
+ Link +
+
+
+ EOS + + @session.within "#first" do |scope| + scope.should_see "Link" + end + end + + it "should fail if the string is not in the HTML scope" do + @session.response_body = <<-EOS +
+ Link +
+
+
+ EOS + + lambda { + @session.within "#second" do |scope| + scope.should_see "Link" + end + }.should raise_error + end + + it "should fail if the string is not in the HTML" do + @session.response_body = <<-EOS + Link + EOS + + lambda { + @session.should_see "Missing" + }.should raise_error + end + + it "should fail if the regexp is not in the HTML" do + @session.response_body = <<-EOS + Different + EOS + + lambda { + @session.should_see /Li(n)[ck]/ + }.should raise_error + end +end From 07784229890c40cceea9b2db16916e9bee65c0f6 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Sun, 14 Sep 2008 14:55:11 -0400 Subject: [PATCH 30/70] Changelog --- History.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/History.txt b/History.txt index 2e82518..6566b74 100644 --- a/History.txt +++ b/History.txt @@ -3,6 +3,7 @@ * Major enhancements * Added #within for manipulating the current page within a selector scope + * Add should_see and should_not_see for verifying HTML response bodys * Add support for simulating SSL requests (Luke Melia) * Add support for file fields via #attaches_file method (Patch from Kyle Hargraves) * Support relative links, including href="?foo=bar" (Patch from Kyle Hargraves) From a73cc5bc3fe94332e323dec2c547852846e5c80a Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Mon, 13 Oct 2008 20:32:10 -0400 Subject: [PATCH 31/70] Update manifest --- Manifest.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Manifest.txt b/Manifest.txt index 55d7772..f031991 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -8,6 +8,7 @@ init.rb install.rb lib/webrat.rb lib/webrat/core.rb +lib/webrat/core/assertions.rb lib/webrat/core/field.rb lib/webrat/core/flunk.rb lib/webrat/core/form.rb @@ -36,6 +37,8 @@ spec/api/fills_in_spec.rb spec/api/reloads_spec.rb spec/api/save_and_open_spec.rb spec/api/selects_spec.rb +spec/api/should_not_see_spec.rb +spec/api/should_see_spec.rb spec/api/visits_spec.rb spec/api/within_spec.rb spec/fakes/test_session.rb From cf55dbad94da0d63429fc0362f9756dc6ac3071e Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Mon, 13 Oct 2008 20:50:03 -0400 Subject: [PATCH 32/70] Add support to click_button for IDs (Patch form Gwyn Morfey) --- History.txt | 1 + lib/webrat/core/field.rb | 4 ++++ lib/webrat/core/form.rb | 3 ++- spec/api/clicks_button_spec.rb | 10 ++++++++++ 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/History.txt b/History.txt index 6566b74..db42057 100644 --- a/History.txt +++ b/History.txt @@ -26,6 +26,7 @@ * Support clicking links by title (Patch from Dan Barry) * Added missing spec for clicking image buttons (Patch from Tim Harper) * Switched tests to specs, and from Mocha to RSpec's mocking library + * Add support to click_button for IDs (Patch form Gwyn Morfey) * Bug fixes diff --git a/lib/webrat/core/field.rb b/lib/webrat/core/field.rb index c9ea46b..4238afb 100644 --- a/lib/webrat/core/field.rb +++ b/lib/webrat/core/field.rb @@ -138,6 +138,10 @@ module Webrat @element.innerHTML =~ /#{Regexp.escape(text.to_s)}/i end + # def matches_id?(id) + # @element["id"] =~ /^\W*#{Regexp.escape(id.to_s)}/i + # end + def matches_value?(value) @element["value"] =~ /^\W*#{Regexp.escape(value.to_s)}/i || matches_text?(value) || matches_alt?(value) end diff --git a/lib/webrat/core/form.rb b/lib/webrat/core/form.rb index 4d8a47b..3d739ab 100644 --- a/lib/webrat/core/form.rb +++ b/lib/webrat/core/form.rb @@ -30,7 +30,8 @@ module Webrat def find_button(value = nil) return fields_by_type([ButtonField]).first if value.nil? - possible_buttons = fields_by_type([ButtonField]) + possible_buttons = fields_by_type([ButtonField]) + possible_buttons.detect { |possible_button| possible_button.matches_id?(value) } || possible_buttons.detect { |possible_button| possible_button.matches_value?(value) } end diff --git a/spec/api/clicks_button_spec.rb b/spec/api/clicks_button_spec.rb index c732526..48b51d2 100644 --- a/spec/api/clicks_button_spec.rb +++ b/spec/api/clicks_button_spec.rb @@ -344,6 +344,16 @@ describe "clicks_button" do @session.clicks_button end + it "should find buttons by their IDs" do + @session.response_body = <<-EOS + + + + EOS + @session.should_receive(:get) + @session.clicks_button "my_button" + end + it "should find image buttons by their alt text" do @session.response_body = <<-EOS
From 8c5216e3ae8e965dbdcdb0621073786c38dd1d8d Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Mon, 13 Oct 2008 20:56:54 -0400 Subject: [PATCH 33/70] Combing definitions of #disabled? --- lib/webrat/core/field.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/webrat/core/field.rb b/lib/webrat/core/field.rb index 5f64cc2..107bd66 100644 --- a/lib/webrat/core/field.rb +++ b/lib/webrat/core/field.rb @@ -47,7 +47,7 @@ module Webrat end def disabled? - !@element["disabled"].nil? && @element["disabled"] != 'false' + @element.attributes.has_key?("disabled") && @element["disabled"] != 'false' end def raise_error_if_disabled @@ -60,10 +60,6 @@ module Webrat param_parser.parse_query_parameters("#{name}=#{value}") end - def disabled? - @element.attributes.has_key? "disabled" - end - def set(value) @value = value end From be44933556693266974318865d0bca2663223d38 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Mon, 13 Oct 2008 20:58:05 -0400 Subject: [PATCH 34/70] History --- History.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/History.txt b/History.txt index db42057..7b51a47 100644 --- a/History.txt +++ b/History.txt @@ -10,6 +10,7 @@ * Separated Rails-specific code from the Webrat core to make it easier to use Webrat with other environments * Alias visits as visit, clicks_link as click_link, etc. for better readability * Raise error when trying to interact with a disabled form element (Luke Melia) + * Don't send disabled form elements to the server (Patch from Nicholas A. Evans) * Minor enhancements From ab91b0cee822cf5b5e8752c9019ac7bff8fe4b95 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Mon, 13 Oct 2008 21:01:16 -0400 Subject: [PATCH 35/70] History --- History.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/History.txt b/History.txt index 7b51a47..73451cf 100644 --- a/History.txt +++ b/History.txt @@ -27,7 +27,8 @@ * Support clicking links by title (Patch from Dan Barry) * Added missing spec for clicking image buttons (Patch from Tim Harper) * Switched tests to specs, and from Mocha to RSpec's mocking library - * Add support to click_button for IDs (Patch form Gwyn Morfey) + * Add support to click_button for IDs (Patch from Gwyn Morfey) + * Miscellaneous core refactorings (Patch from Jan Suchal) * Bug fixes @@ -37,6 +38,7 @@ * Fix bug with empty select list option (Patch from Kyle Hargraves) * Fix regression of not sending default values in password fields * Don't explode if encountering inputs with no type attribute (assume text) + * Fix bug where choosing a radio button in a series with a default submitted the incorrect field value (Luke Melia) == 0.2.0 / 2008-04-04 From 7ff69b02e4d2429ce365e4d41f0961f9d1764ff8 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Mon, 13 Oct 2008 21:06:38 -0400 Subject: [PATCH 36/70] Add gemspec --- Manifest.txt | 1 + webrat.gemspec | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 webrat.gemspec diff --git a/Manifest.txt b/Manifest.txt index f031991..4e749b6 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -49,3 +49,4 @@ spec/spec_helper.rb spec/webrat/core/logging_spec.rb spec/webrat/core/session_spec.rb spec/webrat/rails/rails_session_spec.rb +webrat.gemspec diff --git a/webrat.gemspec b/webrat.gemspec new file mode 100644 index 0000000..b246f57 --- /dev/null +++ b/webrat.gemspec @@ -0,0 +1,35 @@ +Gem::Specification.new do |s| + s.name = %q{webrat} + s.version = "0.2.1" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Bryan Helmkamp", "Seth Fitzsimmons"] + s.date = %q{2008-10-13} + s.description = %q{When comparing Webrat with an in-browser testing solution like Watir or Selenium, the primary consideration should be how much JavaScript the application uses. In-browser testing is currently the only way to test JS, and that may make it a requirement for your project. If JavaScript is not central to your application, Webrat is a simpler, effective solution that will let you run your tests much faster and more frequently. Initial development was sponsored by [EastMedia](http://www.eastmedia.com). Synopsis --------} + s.email = ["bryan@brynary.com", "seth@mojodna.net"] + s.extra_rdoc_files = ["History.txt", "MIT-LICENSE.txt", "Manifest.txt", "README.txt", "TODO.txt"] + s.files = ["History.txt", "MIT-LICENSE.txt", "Manifest.txt", "README.txt", "Rakefile", "TODO.txt", "init.rb", "install.rb", "lib/webrat.rb", "lib/webrat/core.rb", "lib/webrat/core/assertions.rb", "lib/webrat/core/field.rb", "lib/webrat/core/flunk.rb", "lib/webrat/core/form.rb", "lib/webrat/core/label.rb", "lib/webrat/core/link.rb", "lib/webrat/core/logging.rb", "lib/webrat/core/scope.rb", "lib/webrat/core/select_option.rb", "lib/webrat/core/session.rb", "lib/webrat/mechanize.rb", "lib/webrat/mechanize/mechanize_session.rb", "lib/webrat/rails.rb", "lib/webrat/rails/rails_session.rb", "lib/webrat/rails/redirect_actions.rb", "lib/webrat/rails/session.rb", "lib/webrat/selenium.rb", "lib/webrat/selenium/selenium_session.rb", "mechanize_spike.rb", "selenium_spike.rb", "spec/api/attaches_file_spec.rb", "spec/api/checks_spec.rb", "spec/api/chooses_spec.rb", "spec/api/clicks_button_spec.rb", "spec/api/clicks_link_spec.rb", "spec/api/fills_in_spec.rb", "spec/api/reloads_spec.rb", "spec/api/save_and_open_spec.rb", "spec/api/selects_spec.rb", "spec/api/should_not_see_spec.rb", "spec/api/should_see_spec.rb", "spec/api/visits_spec.rb", "spec/api/within_spec.rb", "spec/fakes/test_session.rb", "spec/integration/rails_spec.rb", "spec/rcov.opts", "spec/spec.opts", "spec/spec_helper.rb", "spec/webrat/core/logging_spec.rb", "spec/webrat/core/session_spec.rb", "spec/webrat/rails/rails_session_spec.rb", "webrat.gemspec"] + s.has_rdoc = true + s.homepage = %q{- [Code on GitHub](http://github.com/brynary/webrat)} + s.rdoc_options = ["--main", "README.txt"] + s.require_paths = ["lib"] + s.rubyforge_project = %q{webrat} + s.rubygems_version = %q{1.2.0} + s.summary = %q{Ruby Acceptance Testing for Web applications} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if current_version >= 3 then + s.add_runtime_dependency(%q, [">= 0.6"]) + s.add_development_dependency(%q, [">= 1.7.0"]) + else + s.add_dependency(%q, [">= 0.6"]) + s.add_dependency(%q, [">= 1.7.0"]) + end + else + s.add_dependency(%q, [">= 0.6"]) + s.add_dependency(%q, [">= 1.7.0"]) + end +end From c536b422dfa0bce50c4bf5709d2a2863ea84d78d Mon Sep 17 00:00:00 2001 From: David Chelimsky Date: Mon, 6 Oct 2008 06:52:36 -0500 Subject: [PATCH 37/70] require 'spec/interop/test' so you can run specs w/ the ruby command --- spec/spec.opts | 0 spec/spec_helper.rb | 1 + 2 files changed, 1 insertion(+) delete mode 100644 spec/spec.opts diff --git a/spec/spec.opts b/spec/spec.opts deleted file mode 100644 index e69de29..0000000 diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index eff88ee..297d4ed 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,5 +1,6 @@ require "rubygems" require "spec" +require "spec/interop/test" # gem install redgreen for colored test output begin require "redgreen" unless ENV['TM_CURRENT_LINE']; rescue LoadError; end From b5ace471aa08c732a49b700e865c2dbc34b70c0c Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Mon, 13 Oct 2008 21:12:40 -0400 Subject: [PATCH 38/70] Restoring spec.opts --- spec/spec.opts | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 spec/spec.opts diff --git a/spec/spec.opts b/spec/spec.opts new file mode 100644 index 0000000..e69de29 From 1777b59b57333d7bfc1626351939f7cce9f84243 Mon Sep 17 00:00:00 2001 From: David Chelimsky Date: Mon, 6 Oct 2008 06:58:55 -0500 Subject: [PATCH 39/70] format README and update Manifest.txt to enable building a gem --- README.txt | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/README.txt b/README.txt index df8ec0e..8467c0c 100644 --- a/README.txt +++ b/README.txt @@ -1,11 +1,9 @@ -Webrat -====== +=== Webrat - [Code on GitHub](http://github.com/brynary/webrat) - [Tickets on Lighthouse](http://webrat.lighthouseapp.com/) -Description ------------ +=== Description Webrat (_Ruby Acceptance Testing for Web applications_) lets you quickly write robust and thorough acceptance tests for a Ruby @@ -23,8 +21,7 @@ run your tests much faster and more frequently. Initial development was sponsored by [EastMedia](http://www.eastmedia.com). -Synopsis --------- +=== Synopsis def test_sign_up visits "/" @@ -62,8 +59,7 @@ tests to break unnecessarily as your application evolves: A test written with Webrat can handle these changes to these without any modifications. -Install -------- +=== Install To install the latest release: @@ -75,23 +71,20 @@ In your stories/helper.rb: You could also unpack the gem into vendor/plugins. -Requirements ------------- +=== Requirements - Rails >= 1.2.6 - Hpricot >= 0.6 - Rails integration tests in Test::Unit _or_ - RSpec stories (using an RSpec version >= revision 2997) -Authors -------- +=== Authors - Maintained by [Bryan Helmkamp](mailto:bryan@brynary.com) - Original code written by [Seth Fitzsimmons](mailto:seth@mojodna.net) - Many other contributors. See attributions in History.txt -License -------- +=== License Copyright (c) 2007 Bryan Helmkamp, Seth Fitzsimmons. See MIT-LICENSE.txt in this directory. From 1af45a7a27a1dbcab80a0a626ba761173ffaf063 Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Tue, 14 Oct 2008 00:11:19 -0400 Subject: [PATCH 40/70] Extracted Selenium location strategies to their own .js files for easier readability and editing. --- .../location_strategy_javascript/button.js | 12 +++ .../location_strategy_javascript/label.js | 16 ++++ .../location_strategy_javascript/webrat.js | 5 + .../webratlink.js | 9 ++ .../webratlinkwithin.js | 15 +++ .../webratselectwithoption.js | 5 + lib/webrat/selenium/selenium_session.rb | 91 ++----------------- 7 files changed, 70 insertions(+), 83 deletions(-) create mode 100644 lib/webrat/selenium/location_strategy_javascript/button.js create mode 100644 lib/webrat/selenium/location_strategy_javascript/label.js create mode 100644 lib/webrat/selenium/location_strategy_javascript/webrat.js create mode 100644 lib/webrat/selenium/location_strategy_javascript/webratlink.js create mode 100644 lib/webrat/selenium/location_strategy_javascript/webratlinkwithin.js create mode 100644 lib/webrat/selenium/location_strategy_javascript/webratselectwithoption.js diff --git a/lib/webrat/selenium/location_strategy_javascript/button.js b/lib/webrat/selenium/location_strategy_javascript/button.js new file mode 100644 index 0000000..42449c7 --- /dev/null +++ b/lib/webrat/selenium/location_strategy_javascript/button.js @@ -0,0 +1,12 @@ +if (locator == '*') { + return selenium.browserbot.locationStrategies['xpath'].call(this, "//input[@type='submit']", inDocument, inWindow) +} +var inputs = inDocument.getElementsByTagName('input'); +return $A(inputs).find(function(candidate){ + inputType = candidate.getAttribute('type'); + if (inputType == 'submit' || inputType == 'image') { + var buttonText = $F(candidate); + return (PatternMatcher.matches(locator + '*', buttonText)); + } + return false; +}); diff --git a/lib/webrat/selenium/location_strategy_javascript/label.js b/lib/webrat/selenium/location_strategy_javascript/label.js new file mode 100644 index 0000000..b5acd10 --- /dev/null +++ b/lib/webrat/selenium/location_strategy_javascript/label.js @@ -0,0 +1,16 @@ +var allLabels = inDocument.getElementsByTagName("label"); +var candidateLabels = $A(allLabels).select(function(candidateLabel){ + var regExp = new RegExp('^' + locator + '\\b', 'i'); + var labelText = getText(candidateLabel).strip(); + return (labelText.search(regExp) >= 0); +}); +if (candidateLabels.length == 0) { + return null; +} +candidateLabels = candidateLabels.sortBy(function(s) { return s.length * -1; }); //reverse length sort +var locatedLabel = candidateLabels.first(); +var labelFor = locatedLabel.getAttribute('for'); +if ((labelFor == null) && (locatedLabel.hasChildNodes())) { + return locatedLabel.firstChild; //TODO: should find the first form field, not just any node +} +return selenium.browserbot.locationStrategies['id'].call(this, labelFor, inDocument, inWindow); diff --git a/lib/webrat/selenium/location_strategy_javascript/webrat.js b/lib/webrat/selenium/location_strategy_javascript/webrat.js new file mode 100644 index 0000000..c513309 --- /dev/null +++ b/lib/webrat/selenium/location_strategy_javascript/webrat.js @@ -0,0 +1,5 @@ +var locationStrategies = selenium.browserbot.locationStrategies; +return locationStrategies['id'].call(this, locator, inDocument, inWindow) + || locationStrategies['name'].call(this, locator, inDocument, inWindow) + || locationStrategies['label'].call(this, locator, inDocument, inWindow) + || null; diff --git a/lib/webrat/selenium/location_strategy_javascript/webratlink.js b/lib/webrat/selenium/location_strategy_javascript/webratlink.js new file mode 100644 index 0000000..ad71957 --- /dev/null +++ b/lib/webrat/selenium/location_strategy_javascript/webratlink.js @@ -0,0 +1,9 @@ +var links = inDocument.getElementsByTagName('a'); +var candidateLinks = $A(links).select(function(candidateLink) { + return PatternMatcher.matches(locator, getText(candidateLink)); +}); +if (candidateLinks.length == 0) { + return null; +} +candidateLinks = candidateLinks.sortBy(function(s) { return s.length * -1; }); //reverse length sort +return candidateLinks.first(); diff --git a/lib/webrat/selenium/location_strategy_javascript/webratlinkwithin.js b/lib/webrat/selenium/location_strategy_javascript/webratlinkwithin.js new file mode 100644 index 0000000..3cf00f6 --- /dev/null +++ b/lib/webrat/selenium/location_strategy_javascript/webratlinkwithin.js @@ -0,0 +1,15 @@ +var locatorParts = locator.split('|'); +var cssAncestor = locatorParts[0]; +var linkText = locatorParts[1]; +var matchingElements = cssQuery(cssAncestor, inDocument); +var candidateLinks = matchingElements.collect(function(ancestor){ + var links = ancestor.getElementsByTagName('a'); + return $A(links).select(function(candidateLink) { + return PatternMatcher.matches(linkText, getText(candidateLink)); + }); +}).flatten().compact(); +if (candidateLinks.length == 0) { + return null; +} +candidateLinks = candidateLinks.sortBy(function(s) { return s.length * -1; }); //reverse length sort +return candidateLinks.first(); diff --git a/lib/webrat/selenium/location_strategy_javascript/webratselectwithoption.js b/lib/webrat/selenium/location_strategy_javascript/webratselectwithoption.js new file mode 100644 index 0000000..2a8b403 --- /dev/null +++ b/lib/webrat/selenium/location_strategy_javascript/webratselectwithoption.js @@ -0,0 +1,5 @@ +var optionElements = inDocument.getElementsByTagName('option'); +var locatedOption = $A(optionElements).find(function(candidate){ + return (PatternMatcher.matches(locator, getText(candidate))); +}); +return locatedOption ? locatedOption.parentNode : null; diff --git a/lib/webrat/selenium/selenium_session.rb b/lib/webrat/selenium/selenium_session.rb index 6141269..32ffbd5 100644 --- a/lib/webrat/selenium/selenium_session.rb +++ b/lib/webrat/selenium/selenium_session.rb @@ -87,89 +87,14 @@ module Webrat @selenium.check("webrat=#{label_text}") end - protected - - def define_location_strategies - @selenium.add_location_strategy('label', <<-JS) - var allLabels = inDocument.getElementsByTagName("label"); - var candidateLabels = $A(allLabels).select(function(candidateLabel){ - var regExp = new RegExp('^' + locator + '\\\\b', 'i'); - var labelText = getText(candidateLabel).strip(); - return (labelText.search(regExp) >= 0); - }); - if (candidateLabels.length == 0) { - return null; - } - candidateLabels = candidateLabels.sortBy(function(s) { return s.length * -1; }); //reverse length sort - var locatedLabel = candidateLabels.first(); - var labelFor = locatedLabel.getAttribute('for'); - if ((labelFor == null) && (locatedLabel.hasChildNodes())) { - return locatedLabel.firstChild; //TODO: should find the first form field, not just any node - } - return selenium.browserbot.locationStrategies['id'].call(this, labelFor, inDocument, inWindow); - JS - - @selenium.add_location_strategy('webrat', <<-JS) - var locationStrategies = selenium.browserbot.locationStrategies; - return locationStrategies['id'].call(this, locator, inDocument, inWindow) - || locationStrategies['name'].call(this, locator, inDocument, inWindow) - || locationStrategies['label'].call(this, locator, inDocument, inWindow) - || null; - JS - - @selenium.add_location_strategy('button', <<-JS) - if (locator == '*') { - return selenium.browserbot.locationStrategies['xpath'].call(this, "//input[@type='submit']", inDocument, inWindow) - } - var inputs = inDocument.getElementsByTagName('input'); - return $A(inputs).find(function(candidate){ - inputType = candidate.getAttribute('type'); - if (inputType == 'submit' || inputType == 'image') { - var buttonText = $F(candidate); - return (PatternMatcher.matches(locator + '*', buttonText)); - } - return false; - }); - JS - - @selenium.add_location_strategy('webratlink', <<-JS) - var links = inDocument.getElementsByTagName('a'); - var candidateLinks = $A(links).select(function(candidateLink) { - return PatternMatcher.matches(locator, getText(candidateLink)); - }); - if (candidateLinks.length == 0) { - return null; - } - candidateLinks = candidateLinks.sortBy(function(s) { return s.length * -1; }); //reverse length sort - return candidateLinks.first(); - JS - - @selenium.add_location_strategy('webratlinkwithin', <<-JS) - var locatorParts = locator.split('|'); - var cssAncestor = locatorParts[0]; - var linkText = locatorParts[1]; - var matchingElements = cssQuery(cssAncestor, inDocument); - var candidateLinks = matchingElements.collect(function(ancestor){ - var links = ancestor.getElementsByTagName('a'); - return $A(links).select(function(candidateLink) { - return PatternMatcher.matches(linkText, getText(candidateLink)); - }); - }).flatten().compact(); - if (candidateLinks.length == 0) { - return null; - } - candidateLinks = candidateLinks.sortBy(function(s) { return s.length * -1; }); //reverse length sort - return candidateLinks.first(); - JS - - @selenium.add_location_strategy('webratselectwithoption', <<-JS) - var optionElements = inDocument.getElementsByTagName('option'); - var locatedOption = $A(optionElements).find(function(candidate){ - return (PatternMatcher.matches(locator, getText(candidate))); - }); - return locatedOption ? locatedOption.parentNode : null; - JS - end + protected + def define_location_strategies + Dir[File.join(File.dirname(__FILE__), "location_strategy_javascript", "*.js")].sort.each do |file| + strategy_js = File.read(file) + strategy_name = File.basename(file, '.js') + @selenium.add_location_strategy(strategy_name, strategy_js) + end + end end end \ No newline at end of file From 50a4c1bc79dec1449a8106218f05d3db5a438bc0 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Tue, 14 Oct 2008 12:17:25 -0400 Subject: [PATCH 41/70] Also load webrat when RAILS_ENV == "selenium" --- init.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/init.rb b/init.rb index 0e19c46..e19fb6a 100644 --- a/init.rb +++ b/init.rb @@ -1,3 +1,3 @@ -if RAILS_ENV == "test" +if RAILS_ENV == "test" || RAILS_ENV == "selenium" require File.join(File.dirname(__FILE__), "lib", "webrat") end From 1db6f70f5b0c4218a3a0900eafbda3e944421dbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aslak=20Helles=C3=B8y?= Date: Mon, 13 Oct 2008 14:56:13 +0200 Subject: [PATCH 42/70] Start adding support for rack and sinatra --- lib/webrat/rack/rack_session.rb | 13 +++++++++++++ lib/webrat/sinatra/sinatra_session.rb | 13 +++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 lib/webrat/rack/rack_session.rb create mode 100644 lib/webrat/sinatra/sinatra_session.rb diff --git a/lib/webrat/rack/rack_session.rb b/lib/webrat/rack/rack_session.rb new file mode 100644 index 0000000..b283294 --- /dev/null +++ b/lib/webrat/rack/rack_session.rb @@ -0,0 +1,13 @@ +require 'webrat' + +module Webrat + class RackSession < Session + def response_body + @response.body + end + + def response_code + @response.status + end + end +end \ No newline at end of file diff --git a/lib/webrat/sinatra/sinatra_session.rb b/lib/webrat/sinatra/sinatra_session.rb new file mode 100644 index 0000000..597c3b8 --- /dev/null +++ b/lib/webrat/sinatra/sinatra_session.rb @@ -0,0 +1,13 @@ +require 'webrat/rack/rack_session' +require 'sinatra' +require 'sinatra/test/methods' + +module Webrat + class SinatraSession < RackSession + include Sinatra::Test::Methods + + def get(*args) + get_it(*args) + end + end +end \ No newline at end of file From 682f4d19f92eb906c891b1f0764f8954f1174155 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aslak=20Helles=C3=B8y?= Date: Thu, 16 Oct 2008 15:50:11 +0200 Subject: [PATCH 43/70] Decouple from Rails so we can use Webrat with Sinatra --- lib/webrat.rb | 1 - lib/webrat/core/form.rb | 4 +++- lib/webrat/rack/rack_session.rb | 11 +++++++++++ lib/webrat/sinatra/sinatra_session.rb | 8 ++++++-- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/lib/webrat.rb b/lib/webrat.rb index dffddac..8f11582 100644 --- a/lib/webrat.rb +++ b/lib/webrat.rb @@ -3,7 +3,6 @@ module Webrat end require "rubygems" -require "active_support" require File.dirname(__FILE__) + "/webrat/core" require File.dirname(__FILE__) + "/webrat/rails" if defined?(RAILS_ENV) diff --git a/lib/webrat/core/form.rb b/lib/webrat/core/form.rb index 60a5c07..9e55a95 100644 --- a/lib/webrat/core/form.rb +++ b/lib/webrat/core/form.rb @@ -106,11 +106,13 @@ module Webrat def form_action @element["action"].blank? ? @session.current_url : @element["action"] end + + HASH = [Hash, HashWithIndifferentAccess] rescue [Hash] def merge(all_params, new_param) new_param.each do |key, value| case all_params[key] - when Hash, HashWithIndifferentAccess + when *HASH merge_hash_values(all_params[key], value) when Array all_params[key] += value diff --git a/lib/webrat/rack/rack_session.rb b/lib/webrat/rack/rack_session.rb index b283294..e3c2e24 100644 --- a/lib/webrat/rack/rack_session.rb +++ b/lib/webrat/rack/rack_session.rb @@ -1,5 +1,16 @@ require 'webrat' +class CGIMethods + def self.parse_query_parameters(params) + hash = {} + params.split('&').each do |p| + pair = p.split('=') + hash[pair[0]] = pair[1] + end + hash + end +end + module Webrat class RackSession < Session def response_body diff --git a/lib/webrat/sinatra/sinatra_session.rb b/lib/webrat/sinatra/sinatra_session.rb index 597c3b8..f770554 100644 --- a/lib/webrat/sinatra/sinatra_session.rb +++ b/lib/webrat/sinatra/sinatra_session.rb @@ -6,8 +6,12 @@ module Webrat class SinatraSession < RackSession include Sinatra::Test::Methods - def get(*args) - get_it(*args) + def get(url, data, headers = nil) + get_it(url, data) + end + + def post(url, data, headers = nil) + post_it(url, data) end end end \ No newline at end of file From a885a80a7b2c3622990c1f4c649c222460b3f541 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aslak=20Helles=C3=B8y?= Date: Fri, 17 Oct 2008 12:38:59 +0200 Subject: [PATCH 44/70] More complete Sinatra support --- lib/webrat/sinatra/sinatra_session.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/webrat/sinatra/sinatra_session.rb b/lib/webrat/sinatra/sinatra_session.rb index f770554..2647f6c 100644 --- a/lib/webrat/sinatra/sinatra_session.rb +++ b/lib/webrat/sinatra/sinatra_session.rb @@ -6,12 +6,12 @@ module Webrat class SinatraSession < RackSession include Sinatra::Test::Methods - def get(url, data, headers = nil) - get_it(url, data) - end - - def post(url, data, headers = nil) - post_it(url, data) + %w(get head post put delete).each do |verb| + define_method(verb) do |*args| + url, data, headers = *args + self.__send__("#{verb}_it", url, data) + follow! while @response.redirect? + end end end end \ No newline at end of file From e2c70b8e919d860857061aab698a64a7fb9c6c1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aslak=20Helles=C3=B8y?= Date: Fri, 17 Oct 2008 13:39:34 +0200 Subject: [PATCH 45/70] Update History with note about Sinatra and Rack --- History.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/History.txt b/History.txt index 2e82518..3a41df6 100644 --- a/History.txt +++ b/History.txt @@ -2,6 +2,7 @@ * Major enhancements + * Added support for Sinatra and Rack (Aslak Hellesøy) * Added #within for manipulating the current page within a selector scope * Add support for simulating SSL requests (Luke Melia) * Add support for file fields via #attaches_file method (Patch from Kyle Hargraves) From 17cf56eb5e9f3872b842a43a3181caca4f005a28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aslak=20Helles=C3=B8y?= Date: Fri, 17 Oct 2008 17:43:14 +0200 Subject: [PATCH 46/70] Add support for Basic Auth --- History.txt | 1 + lib/webrat/core/session.rb | 26 +++++++++++++++++++------- lib/webrat/sinatra/sinatra_session.rb | 7 ++++--- spec/api/basic_auth_spec.rb | 23 +++++++++++++++++++++++ 4 files changed, 47 insertions(+), 10 deletions(-) create mode 100644 spec/api/basic_auth_spec.rb diff --git a/History.txt b/History.txt index 3a41df6..d9e65c0 100644 --- a/History.txt +++ b/History.txt @@ -2,6 +2,7 @@ * Major enhancements + * Added #basic_auth(user, pass) to support HTTP Basic Auth (Aslak Hellesøy) * Added support for Sinatra and Rack (Aslak Hellesøy) * Added #within for manipulating the current page within a selector scope * Add support for simulating SSL requests (Luke Melia) diff --git a/lib/webrat/core/session.rb b/lib/webrat/core/session.rb index ecf243c..65396df 100644 --- a/lib/webrat/core/session.rb +++ b/lib/webrat/core/session.rb @@ -10,8 +10,9 @@ module Webrat attr_reader :current_url def initialize - @http_method = :get - @data = {} + @http_method = :get + @data = {} + @default_headers = {} end # Saves the page out to RAILS_ROOT/tmp/ and opens it in the default @@ -52,14 +53,25 @@ module Webrat File.expand_path(".") end + def basic_auth(user, pass) + @default_headers['HTTP_AUTHORIZATION'] = "Basic " + ["#{user}:#{pass}"].pack("m*") + end + + def headers + @default_headers.dup + end + def request_page(url, http_method, data) - debug_log "REQUESTING PAGE: #{http_method.to_s.upcase} #{url} with #{data.inspect}" - if @current_url - send "#{http_method}", url, data || {}, {"HTTP_REFERER" => @current_url} - else + h = headers + h['HTTP_REFERER'] = @current_url if @current_url + + debug_log "REQUESTING PAGE: #{http_method.to_s.upcase} #{url} with #{data.inspect} and HTTP headers #{h.inspect}" + if h.empty? send "#{http_method}", url, data || {} + else + send "#{http_method}", url, data || {}, h end - + save_and_open_page if exception_caught? flunk("Page load was not successful (Code: #{response_code.inspect})") unless success_code? diff --git a/lib/webrat/sinatra/sinatra_session.rb b/lib/webrat/sinatra/sinatra_session.rb index 2647f6c..3152c6c 100644 --- a/lib/webrat/sinatra/sinatra_session.rb +++ b/lib/webrat/sinatra/sinatra_session.rb @@ -7,9 +7,10 @@ module Webrat include Sinatra::Test::Methods %w(get head post put delete).each do |verb| - define_method(verb) do |*args| - url, data, headers = *args - self.__send__("#{verb}_it", url, data) + define_method(verb) do |*args| # (path, data, headers = nil) + path, data, headers = *args + params = data.merge({:env => headers || {}}) + self.__send__("#{verb}_it", path, params) follow! while @response.redirect? end end diff --git a/spec/api/basic_auth_spec.rb b/spec/api/basic_auth_spec.rb new file mode 100644 index 0000000..07b9cb1 --- /dev/null +++ b/spec/api/basic_auth_spec.rb @@ -0,0 +1,23 @@ +require File.expand_path(File.dirname(__FILE__) + "/../spec_helper") + +describe "Basic Auth HTTP headers" do + before do + @session = Webrat::TestSession.new + @session.basic_auth('user', 'secret') + end + + it "should be present in visits" do + @session.should_receive(:get).with("/", {}, {'HTTP_AUTHORIZATION' => "Basic dXNlcjpzZWNyZXQ=\n"}) + @session.visits("/") + end + + it "should be present in form submits" do + @session.response_body = <<-EOS + + + + EOS + @session.should_receive(:post).with("/form1", {}, {'HTTP_AUTHORIZATION' => "Basic dXNlcjpzZWNyZXQ=\n"}) + @session.clicks_button + end +end From b8e76a1af28a41ede3288443777714b1f4dad42f Mon Sep 17 00:00:00 2001 From: Rob Kaufman Date: Fri, 17 Oct 2008 19:41:24 -0700 Subject: [PATCH 47/70] Moved merb files to be more in line with current webrat layout --- lib/boot_rails.rb | 39 ------------------- lib/webrat.rb | 2 +- lib/{boot_merb.rb => webrat/merb.rb} | 8 ++-- .../merb}/indifferent_access.rb | 0 .../merb}/param_parser.rb | 0 lib/{merb_support => webrat/merb}/support.rb | 0 .../merb}/url_encoded_pair_parser.rb | 0 spec/api/attaches_file_spec.rb | 2 +- spec/webrat/merb/helper.rb | 1 - test/helper_merb.rb | 11 ------ test/helper_rails.rb | 11 ------ 11 files changed, 6 insertions(+), 68 deletions(-) delete mode 100644 lib/boot_rails.rb rename lib/{boot_merb.rb => webrat/merb.rb} (92%) rename lib/{merb_support => webrat/merb}/indifferent_access.rb (100%) rename lib/{merb_support => webrat/merb}/param_parser.rb (100%) rename lib/{merb_support => webrat/merb}/support.rb (100%) rename lib/{merb_support => webrat/merb}/url_encoded_pair_parser.rb (100%) delete mode 100644 test/helper_merb.rb delete mode 100644 test/helper_rails.rb diff --git a/lib/boot_rails.rb b/lib/boot_rails.rb deleted file mode 100644 index 1954ca7..0000000 --- a/lib/boot_rails.rb +++ /dev/null @@ -1,39 +0,0 @@ -module ActionController - module Integration - class Session - - unless instance_methods.include?("put_via_redirect") - include Webrat::RedirectActions - end - - def current_page - @current_page ||= Webrat::Page.new(self) - end - - def current_page=(new_page) - @current_page = new_page - end - - # Issues a GET request for a page, follows any redirects, and verifies the final page - # load was successful. - # - # Example: - # visits "/" - def visits(*args) - @current_page = Webrat::Page.new(self, *args) - end - - def save_and_open_page - current_page.save_and_open - end - - [:reloads, :fills_in, :clicks_button, :selects, :chooses, :checks, :unchecks, :clicks_link, :clicks_link_within, :clicks_put_link, :clicks_get_link, :clicks_post_link, :clicks_delete_link].each do |method_name| - define_method(method_name) do |*args| - current_page.send(method_name, *args) - end - end - - end - end -end - diff --git a/lib/webrat.rb b/lib/webrat.rb index f7f1a73..57df591 100644 --- a/lib/webrat.rb +++ b/lib/webrat.rb @@ -10,4 +10,4 @@ require "active_support" require File.dirname(__FILE__) + "/webrat/core" require File.dirname(__FILE__) + "/webrat/rails" if defined?(RAILS_ENV) -require File.join(File.dirname(__FILE__), "boot_merb.rb") if defined?(Merb) +require File.dirname(__FILE__) + "/webrat/merb" if defined?(Merb) diff --git a/lib/boot_merb.rb b/lib/webrat/merb.rb similarity index 92% rename from lib/boot_merb.rb rename to lib/webrat/merb.rb index b0500db..343f7e1 100644 --- a/lib/boot_merb.rb +++ b/lib/webrat/merb.rb @@ -118,10 +118,10 @@ end #here because we're only loaded in Test mode. require 'strscan' require 'cgi' -require File.join(File.dirname(__FILE__), "merb_support", "param_parser.rb") -require File.join(File.dirname(__FILE__), "merb_support", "url_encoded_pair_parser.rb") -require File.join(File.dirname(__FILE__), "merb_support", "indifferent_access.rb") -require File.join(File.dirname(__FILE__), "merb_support", "support.rb") +require File.join(File.dirname(__FILE__), "merb", "param_parser.rb") +require File.join(File.dirname(__FILE__), "merb", "url_encoded_pair_parser.rb") +require File.join(File.dirname(__FILE__), "merb", "indifferent_access.rb") +require File.join(File.dirname(__FILE__), "merb", "support.rb") diff --git a/lib/merb_support/indifferent_access.rb b/lib/webrat/merb/indifferent_access.rb similarity index 100% rename from lib/merb_support/indifferent_access.rb rename to lib/webrat/merb/indifferent_access.rb diff --git a/lib/merb_support/param_parser.rb b/lib/webrat/merb/param_parser.rb similarity index 100% rename from lib/merb_support/param_parser.rb rename to lib/webrat/merb/param_parser.rb diff --git a/lib/merb_support/support.rb b/lib/webrat/merb/support.rb similarity index 100% rename from lib/merb_support/support.rb rename to lib/webrat/merb/support.rb diff --git a/lib/merb_support/url_encoded_pair_parser.rb b/lib/webrat/merb/url_encoded_pair_parser.rb similarity index 100% rename from lib/merb_support/url_encoded_pair_parser.rb rename to lib/webrat/merb/url_encoded_pair_parser.rb diff --git a/spec/api/attaches_file_spec.rb b/spec/api/attaches_file_spec.rb index 55e040f..6adecba 100644 --- a/spec/api/attaches_file_spec.rb +++ b/spec/api/attaches_file_spec.rb @@ -1,5 +1,5 @@ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper") -unless ENV["TEST_MODE"] == "merb" +unless ENV["TEST_MODE"] == "merb" #TODO - Rob describe "attaches_file" do before do @session = Webrat::TestSession.new diff --git a/spec/webrat/merb/helper.rb b/spec/webrat/merb/helper.rb index 8c79f95..2994b62 100644 --- a/spec/webrat/merb/helper.rb +++ b/spec/webrat/merb/helper.rb @@ -1,5 +1,4 @@ require 'merb-core' -require 'merb_stories' # module Merb # module Test # class RspecStory diff --git a/test/helper_merb.rb b/test/helper_merb.rb deleted file mode 100644 index 82f54fe..0000000 --- a/test/helper_merb.rb +++ /dev/null @@ -1,11 +0,0 @@ -require 'merb-core' -require 'merb_stories' -module Merb - module Test - class RspecStory - def flunk(message) - raise message - end - end - end -end diff --git a/test/helper_rails.rb b/test/helper_rails.rb deleted file mode 100644 index 8c0e9b4..0000000 --- a/test/helper_rails.rb +++ /dev/null @@ -1,11 +0,0 @@ -require "active_support" -silence_warnings do - require "action_controller" - require "action_controller/integration" -end - -class ActionController::Integration::Session - def flunk(message) - raise message - end -end \ No newline at end of file From 9ed5c9013c4e3225a90b1cdc3df762c49726eb58 Mon Sep 17 00:00:00 2001 From: Rob Kaufman Date: Sat, 18 Oct 2008 00:38:25 -0700 Subject: [PATCH 48/70] Working on moving merb code to be functional with merbs request testing --- Manifest.txt | 72 +++++++++++-------- lib/webrat/core/field.rb | 2 +- lib/webrat/merb.rb | 152 +++++++++++---------------------------- 3 files changed, 86 insertions(+), 140 deletions(-) diff --git a/Manifest.txt b/Manifest.txt index 94b69bb..7fe0341 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -1,41 +1,55 @@ -.gitignore History.txt MIT-LICENSE.txt Manifest.txt README.txt Rakefile TODO.txt -coverage/index.html -coverage/lib-webrat-field_rb.html -coverage/lib-webrat-form_rb.html -coverage/lib-webrat-label_rb.html -coverage/lib-webrat-link_rb.html -coverage/lib-webrat-logging_rb.html -coverage/lib-webrat-page_rb.html -coverage/lib-webrat-redirect_actions_rb.html -coverage/lib-webrat-select_option_rb.html -coverage/lib-webrat_rb.html init.rb install.rb lib/webrat.rb -lib/webrat/field.rb -lib/webrat/form.rb -lib/webrat/label.rb -lib/webrat/link.rb -lib/webrat/logging.rb -lib/webrat/page.rb -lib/webrat/redirect_actions.rb -lib/webrat/select_option.rb -spec/attaches_file_spec.rb -spec/checks_spec.rb -spec/chooses_spec.rb -spec/clicks_button_spec.rb -spec/clicks_link_spec.rb -spec/fills_in_spec.rb +lib/webrat/core.rb +lib/webrat/core/field.rb +lib/webrat/core/flunk.rb +lib/webrat/core/form.rb +lib/webrat/core/label.rb +lib/webrat/core/link.rb +lib/webrat/core/logging.rb +lib/webrat/core/scope.rb +lib/webrat/core/select_option.rb +lib/webrat/core/session.rb +lib/webrat/mechanize.rb +lib/webrat/mechanize/mechanize_session.rb +lib/webrat/merb.rb +lib/webrat/merb/indifferent_access.rb +lib/webrat/merb/param_parser.rb +lib/webrat/merb/support.rb +lib/webrat/merb/url_encoded_pair_parser.rb +lib/webrat/rails.rb +lib/webrat/rails/rails_session.rb +lib/webrat/rails/redirect_actions.rb +lib/webrat/rails/session.rb +lib/webrat/selenium.rb +lib/webrat/selenium/selenium_session.rb +mechanize_spike.rb +selenium_spike.rb +spec/api/attaches_file_spec.rb +spec/api/checks_spec.rb +spec/api/chooses_spec.rb +spec/api/clicks_button_spec.rb +spec/api/clicks_link_spec.rb +spec/api/fills_in_spec.rb +spec/api/reloads_spec.rb +spec/api/save_and_open_spec.rb +spec/api/selects_spec.rb +spec/api/visits_spec.rb +spec/api/within_spec.rb +spec/fakes/test_session.rb +spec/integration/rails_spec.rb spec/rcov.opts -spec/reloads_spec.rb -spec/save_and_open_page_spec.rb -spec/selects_spec.rb spec/spec.opts spec/spec_helper.rb -spec/visits_spec.rb +spec/webrat/core/logging_spec.rb +spec/webrat/core/session_spec.rb +spec/webrat/merb/helper.rb +spec/webrat/rails/helper.rb +spec/webrat/rails/rails_session_spec.rb \ No newline at end of file diff --git a/lib/webrat/core/field.rb b/lib/webrat/core/field.rb index 2621c9e..1400a0c 100644 --- a/lib/webrat/core/field.rb +++ b/lib/webrat/core/field.rb @@ -174,7 +174,7 @@ module Webrat else checkbox_with_same_name = @form.find_field(name, CheckboxField) - if checkbox_with_same_name.to_param.nil? + if checkbox_with_same_name.to_param.blank? super else nil diff --git a/lib/webrat/merb.rb b/lib/webrat/merb.rb index 343f7e1..bc7f662 100644 --- a/lib/webrat/merb.rb +++ b/lib/webrat/merb.rb @@ -1,127 +1,59 @@ module Webrat - module MerbTest - - #Our own redirect actions defined below, to deal with the fact that we need to store - #a controller reference. - - def current_page - @current_page ||= Webrat::Page.new(self) + class Session + include Merb::Test::RequestHelper + + attr_reader :response + + def get(url, data, headers = nil) + @response = request(url, :params => data, :headers => headers, :method => "GET") end - - def current_page=(new_page) - @current_page = new_page - end - - # Issues a GET request for a page, follows any redirects, and verifies the final page - # load was successful. - # - # Example: - # visits "/" - def visits(*args) - @current_page = Webrat::Page.new(self, *args) - end - - def save_and_open_page - current_page.save_and_open - end - - [:reloads, :fills_in, :clicks_button, :selects, :chooses, :checks, :unchecks, :clicks_link, :clicks_link_within, :clicks_put_link, :clicks_get_link, :clicks_post_link, :clicks_delete_link].each do |method_name| - define_method(method_name) do |*args| - current_page.send(method_name, *args) - end - end - - #Session defines the following (used by webrat), but RspecStory doesn't. Merb's get/put/delete return a controller, - #which is where we get our status and response from. - # - #We have to preserve cookies like this, or the session is lost. - # - #While (in a web application) a PUT is modelled as a POST with a parameter _method, - #this close to the metal we need to make sure that we actually hit the underlying 'put' method, - #so we rewrite 'method'. - def request_via_redirect(method,path,parameters={},headers={}) - method = parameters["_method"] if !parameters["_method"].blank? - mycookies = defined?(@controller) ? @controller.cookies : nil #will be nil if no requests yet - begin - @controller=self.send(method, path, parameters, headers) do |new_controller| - new_controller.cookies = mycookies - end - rescue => exception - raise unless exception.kind_of?(Merb::ControllerExceptions::Base) - #Now we want to go one level below 'post' to build the request ourselves, then send it to the controller - exception_klass = exception.class - klass = ::Exceptions rescue Merb::Controller - request = fake_request - request.params[:exception] = exception - request.params[:action] = exception_klass.name - @controller=dispatch_request(request, klass, exception_klass.name) - end - follow_redirect! while redirect? - status + def post(url, data, headers = nil) + @response = request(url, :params => data, :headers => headers, :method => "POST") end - - def get_via_redirect(path, parameters = {}, headers = {}) - request_via_redirect(:get,path,parameters,headers) + + def put(url, data, headers = nil) + @response = request(url, :params => data, :headers => headers, :method => "PUT") end - - def put_via_redirect(path, parameters = {}, headers = {}) - request_via_redirect(:put,path,parameters,headers) + + def delete(url, data, headers = nil) + @response = request(url, :params => data, :headers => headers, :method => "DELETE") end - - def post_via_redirect(path, parameters = {}, headers = {}) - request_via_redirect(:post,path,parameters,headers) - end - - def delete_via_redirect(path, parameters = {}, headers = {}) - request_via_redirect(:delete,path,parameters,headers) - end - - def follow_redirect! - mycookies = @controller.cookies rescue nil - @controller=get @controller.headers["Location"] do |new_controller| - new_controller.cookies=mycookies - end + + def response_body + @response.body end - - def redirect? - [307, *(300..305)].include?(status) + + def response_code + @response.status end - - def status - @controller.status - end - - def response - @controller #things like @controller.body will work. - end - - def assert_response(resp) - if resp == :success - response.should be_successful - else - raise "assert_response #{resp.inspect} is not supported" - end - end - + end end -class Application < Merb::Controller - def cookies=(newcookies) - @_cookies = newcookies +class Merb::Test::RspecStory + def browser + @browser ||= Webrat::Session.new end end -#Other utilities used by Webrat that are present in Rails but not Merb. We can require heavy dependencies -#here because we're only loaded in Test mode. -require 'strscan' -require 'cgi' +# +# class Application < Merb::Controller +# def cookies=(newcookies) +# @_cookies = newcookies +# end +# end +# +# +# #Other utilities used by Webrat that are present in Rails but not Merb. We can require heavy dependencies +# #here because we're only loaded in Test mode. +# require 'strscan' +# require 'cgi' require File.join(File.dirname(__FILE__), "merb", "param_parser.rb") require File.join(File.dirname(__FILE__), "merb", "url_encoded_pair_parser.rb") -require File.join(File.dirname(__FILE__), "merb", "indifferent_access.rb") -require File.join(File.dirname(__FILE__), "merb", "support.rb") - - - +# require File.join(File.dirname(__FILE__), "merb", "indifferent_access.rb") +# require File.join(File.dirname(__FILE__), "merb", "support.rb") +# +# +# From 2fd734f9ffc76cf107aca3d150acd079b9645073 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Sun, 19 Oct 2008 15:36:53 -0400 Subject: [PATCH 49/70] Coverage --- Rakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rakefile b/Rakefile index 9bd083a..75c8c69 100644 --- a/Rakefile +++ b/Rakefile @@ -56,7 +56,7 @@ end require 'spec/rake/verify_rcov' RCov::VerifyTask.new(:verify_rcov => :rcov) do |t| - t.threshold = 97.2 # Make sure you have rcov 0.7 or higher! + t.threshold = 97.3 # Make sure you have rcov 0.7 or higher! end remove_task "default" From 86879c13c05ad0448456575f148495bf700e1d4c Mon Sep 17 00:00:00 2001 From: Rob Kaufman Date: Mon, 20 Oct 2008 22:06:49 -0700 Subject: [PATCH 50/70] Added webrat, thanks to jrun and gwynm for they're initial work on this --- README.txt | 7 ++ Rakefile | 15 ++- lib/webrat.rb | 1 + lib/webrat/core/logging.rb | 2 + lib/webrat/merb.rb | 45 ++++++++ lib/webrat/merb/indifferent_access.rb | 125 +++++++++++++++++++++ lib/webrat/merb/param_parser.rb | 17 +++ lib/webrat/merb/support.rb | 12 ++ lib/webrat/merb/url_encoded_pair_parser.rb | 93 +++++++++++++++ spec/api/attaches_file_spec.rb | 3 +- spec/spec_helper.rb | 16 +-- spec/webrat/merb/helper.rb | 2 + spec/webrat/rails/helper.rb | 7 ++ 13 files changed, 335 insertions(+), 10 deletions(-) create mode 100644 lib/webrat/merb.rb create mode 100644 lib/webrat/merb/indifferent_access.rb create mode 100644 lib/webrat/merb/param_parser.rb create mode 100644 lib/webrat/merb/support.rb create mode 100644 lib/webrat/merb/url_encoded_pair_parser.rb create mode 100644 spec/webrat/merb/helper.rb create mode 100644 spec/webrat/rails/helper.rb diff --git a/README.txt b/README.txt index 8467c0c..e050010 100644 --- a/README.txt +++ b/README.txt @@ -59,6 +59,13 @@ tests to break unnecessarily as your application evolves: A test written with Webrat can handle these changes to these without any modifications. +=== Merb +To avoid losing sessions, you need this in environments/test.rb: + +Merb::Config.use do |c| + c[:session_store] = 'memory' +end + === Install To install the latest release: diff --git a/Rakefile b/Rakefile index 75c8c69..5992b94 100644 --- a/Rakefile +++ b/Rakefile @@ -35,25 +35,36 @@ def remove_task(task_name) Rake.application.remove_task(task_name) end +def set_file_list + if ENV['TEST_MODE'] == "merb" + list = FileList['spec/**/*_spec.rb'] + list = list.find_all do |file| !file.match("rails") end + return list + else + return FileList['spec/**/*_spec.rb'] + end +end + remove_task "test" remove_task "test_deps" desc "Run all specs in spec directory" Spec::Rake::SpecTask.new do |t| t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""] - t.spec_files = FileList['spec/**/*_spec.rb'] + t.spec_files = set_file_list end desc "Run all specs in spec directory with RCov" Spec::Rake::SpecTask.new(:rcov) do |t| t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""] - t.spec_files = FileList['spec/**/*_spec.rb'] + t.spec_files = set_file_list t.rcov = true t.rcov_opts = lambda do IO.readlines(File.dirname(__FILE__) + "/spec/rcov.opts").map {|l| l.chomp.split " "}.flatten end end + require 'spec/rake/verify_rcov' RCov::VerifyTask.new(:verify_rcov => :rcov) do |t| t.threshold = 97.3 # Make sure you have rcov 0.7 or higher! diff --git a/lib/webrat.rb b/lib/webrat.rb index 8f11582..76acd40 100644 --- a/lib/webrat.rb +++ b/lib/webrat.rb @@ -6,3 +6,4 @@ require "rubygems" require File.dirname(__FILE__) + "/webrat/core" require File.dirname(__FILE__) + "/webrat/rails" if defined?(RAILS_ENV) +require File.dirname(__FILE__) + "/webrat/merb" if defined?(Merb) diff --git a/lib/webrat/core/logging.rb b/lib/webrat/core/logging.rb index e2be0c4..0d1a5fd 100644 --- a/lib/webrat/core/logging.rb +++ b/lib/webrat/core/logging.rb @@ -9,6 +9,8 @@ module Webrat def logger # :nodoc: if defined? RAILS_DEFAULT_LOGGER RAILS_DEFAULT_LOGGER + elsif defined? Merb + Merb.logger else nil end diff --git a/lib/webrat/merb.rb b/lib/webrat/merb.rb new file mode 100644 index 0000000..992c0ba --- /dev/null +++ b/lib/webrat/merb.rb @@ -0,0 +1,45 @@ +module Webrat + class Session + include Merb::Test::RequestHelper + + attr_reader :response + + def get(url, data, headers = nil) + do_request(url, data, headers, "GET") + end + + def post(url, data, headers = nil) + do_request(url, data, headers, "POST") + end + + def put(url, data, headers = nil) + do_request(url, data, headers, "PUT") + end + + def delete(url, data, headers = nil) + do_request(url, data, headers, "DELETE") + end + + def response_body + @response.body.to_s + end + + def response_code + @response.status + end + + protected + def do_request(url, data, headers, method) + @response = request(url, :params => data, :headers => headers, :method => method) + self.get(@response.headers['Location'], nil, @response.headers) if @response.status == 302 + end + + end +end + +class Merb::Test::RspecStory + def browser + @browser ||= Webrat::Session.new + end +end + diff --git a/lib/webrat/merb/indifferent_access.rb b/lib/webrat/merb/indifferent_access.rb new file mode 100644 index 0000000..26e0814 --- /dev/null +++ b/lib/webrat/merb/indifferent_access.rb @@ -0,0 +1,125 @@ +# This class has dubious semantics and we only have it so that +# people can write params[:key] instead of params['key'] +# and they get the same value for both keys. +class HashWithIndifferentAccess < Hash + def initialize(constructor = {}) + if constructor.is_a?(Hash) + super() + update(constructor) + else + super(constructor) + end + end + + def default(key = nil) + if key.is_a?(Symbol) && include?(key = key.to_s) + self[key] + else + super + end + end + + alias_method :regular_writer, :[]= unless method_defined?(:regular_writer) + alias_method :regular_update, :update unless method_defined?(:regular_update) + + # + # Assigns a new value to the hash. + # + # Example: + # + # hash = HashWithIndifferentAccess.new + # hash[:key] = "value" + # + def []=(key, value) + regular_writer(convert_key(key), convert_value(value)) + end + + # + # Updates the instantized hash with values from the second. + # + # Example: + # + # >> hash_1 = HashWithIndifferentAccess.new + # => {} + # + # >> hash_1[:key] = "value" + # => "value" + # + # >> hash_2 = HashWithIndifferentAccess.new + # => {} + # + # >> hash_2[:key] = "New Value!" + # => "New Value!" + # + # >> hash_1.update(hash_2) + # => {"key"=>"New Value!"} + # + def update(other_hash) + other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) } + self + end + + alias_method :merge!, :update + + # Checks the hash for a key matching the argument passed in + def key?(key) + super(convert_key(key)) + end + + alias_method :include?, :key? + alias_method :has_key?, :key? + alias_method :member?, :key? + + # Fetches the value for the specified key, same as doing hash[key] + def fetch(key, *extras) + super(convert_key(key), *extras) + end + + # Returns an array of the values at the specified indicies. + def values_at(*indices) + indices.collect {|key| self[convert_key(key)]} + end + + # Returns an exact copy of the hash. + def dup + HashWithIndifferentAccess.new(self) + end + + # Merges the instantized and the specified hashes together, giving precedence to the values from the second hash + # Does not overwrite the existing hash. + def merge(hash) + self.dup.update(hash) + end + + # Removes a specified key from the hash. + def delete(key) + super(convert_key(key)) + end + + def stringify_keys!; self end + def symbolize_keys!; self end + def to_options!; self end + + # Convert to a Hash with String keys. + def to_hash + Hash.new(default).merge(self) + end + + protected + def convert_key(key) + key.kind_of?(Symbol) ? key.to_s : key + end + + def convert_value(value) + case value + when Hash + value.with_indifferent_access + when Array + value.collect { |e| e.is_a?(Hash) ? e.with_indifferent_access : e } + else + value + end + end +end + + diff --git a/lib/webrat/merb/param_parser.rb b/lib/webrat/merb/param_parser.rb new file mode 100644 index 0000000..534e1ff --- /dev/null +++ b/lib/webrat/merb/param_parser.rb @@ -0,0 +1,17 @@ +module Webrat + class ParamParser + def self.parse_query_parameters(query_string) + return {} if query_string.blank? + + pairs = query_string.split('&').collect do |chunk| + next if chunk.empty? + key, value = chunk.split('=', 2) + next if key.empty? + value = value.nil? ? nil : CGI.unescape(value) + [ CGI.unescape(key), value ] + end.compact + + UrlEncodedPairParser.new(pairs).result + end + end +end \ No newline at end of file diff --git a/lib/webrat/merb/support.rb b/lib/webrat/merb/support.rb new file mode 100644 index 0000000..f7c24ee --- /dev/null +++ b/lib/webrat/merb/support.rb @@ -0,0 +1,12 @@ +class Hash + def with_indifferent_access + hash = HashWithIndifferentAccess.new(self) + hash.default = self.default + hash + end +end +class NilClass + def to_param + nil + end +end diff --git a/lib/webrat/merb/url_encoded_pair_parser.rb b/lib/webrat/merb/url_encoded_pair_parser.rb new file mode 100644 index 0000000..8e668c7 --- /dev/null +++ b/lib/webrat/merb/url_encoded_pair_parser.rb @@ -0,0 +1,93 @@ +class UrlEncodedPairParser < StringScanner #:nodoc: + attr_reader :top, :parent, :result + + def initialize(pairs = []) + super('') + @result = {} + pairs.each { |key, value| parse(key, value) } + end + + KEY_REGEXP = %r{([^\[\]=&]+)} + BRACKETED_KEY_REGEXP = %r{\[([^\[\]=&]+)\]} + + # Parse the query string + def parse(key, value) + self.string = key + @top, @parent = result, nil + + # First scan the bare key + key = scan(KEY_REGEXP) or return + key = post_key_check(key) + + # Then scan as many nestings as present + until eos? + r = scan(BRACKETED_KEY_REGEXP) or return + key = self[1] + key = post_key_check(key) + end + + bind(key, value) + end + + private + # After we see a key, we must look ahead to determine our next action. Cases: + # + # [] follows the key. Then the value must be an array. + # = follows the key. (A value comes next) + # & or the end of string follows the key. Then the key is a flag. + # otherwise, a hash follows the key. + def post_key_check(key) + if scan(/\[\]/) # a[b][] indicates that b is an array + container(key, Array) + nil + elsif check(/\[[^\]]/) # a[b] indicates that a is a hash + container(key, Hash) + nil + else # End of key? We do nothing. + key + end + end + + # Add a container to the stack. + def container(key, klass) + type_conflict! klass, top[key] if top.is_a?(Hash) && top.key?(key) && ! top[key].is_a?(klass) + value = bind(key, klass.new) + type_conflict! klass, value unless value.is_a?(klass) + push(value) + end + + # Push a value onto the 'stack', which is actually only the top 2 items. + def push(value) + @parent, @top = @top, value + end + + # Bind a key (which may be nil for items in an array) to the provided value. + def bind(key, value) + if top.is_a? Array + if key + if top[-1].is_a?(Hash) && ! top[-1].key?(key) + top[-1][key] = value + else + top << {key => value}.with_indifferent_access + push top.last + value = top[key] + end + else + top << value + end + elsif top.is_a? Hash + key = CGI.unescape(key) + parent << (@top = {}) if top.key?(key) && parent.is_a?(Array) + top[key] ||= value + return top[key] + else + raise ArgumentError, "Don't know what to do: top is #{top.inspect}" + end + + return value + end + + def type_conflict!(klass, value) + raise TypeError, "Conflicting types for parameter containers. Expected an instance of #{klass} but found an instance of #{value.class}. This can be caused by colliding Array and Hash parameters like qs[]=value&qs[key]=value. (The parameters received were #{value.inspect}.)" + end +end \ No newline at end of file diff --git a/spec/api/attaches_file_spec.rb b/spec/api/attaches_file_spec.rb index edf0e74..6adecba 100644 --- a/spec/api/attaches_file_spec.rb +++ b/spec/api/attaches_file_spec.rb @@ -1,5 +1,5 @@ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper") - +unless ENV["TEST_MODE"] == "merb" #TODO - Rob describe "attaches_file" do before do @session = Webrat::TestSession.new @@ -70,3 +70,4 @@ describe "attaches_file" do @session.clicks_button end end +end \ No newline at end of file diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 297d4ed..feb04ac 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -5,16 +5,18 @@ require "spec/interop/test" # gem install redgreen for colored test output begin require "redgreen" unless ENV['TM_CURRENT_LINE']; rescue LoadError; end -require "active_support" +require File.expand_path(File.dirname(__FILE__) + "/../lib/webrat") +require File.dirname(__FILE__) + "/fakes/test_session" -silence_warnings do - require "action_controller" - require "action_controller/integration" +if ["rails","merb"].include?(ENV["TEST_MODE"]) + require File.join(File.dirname(__FILE__), "webrat", "#{ENV["TEST_MODE"]}", "helper.rb") +else + puts "Assuming test mode is Rails... for Merb set TEST_MODE=merb and rerun." + ENV["TEST_MODE"] = 'rails' + require File.join(File.dirname(__FILE__), "webrat", "#{ENV["TEST_MODE"]}", "helper.rb") end -require File.expand_path(File.dirname(__FILE__) + "/../lib/webrat") -require File.expand_path(File.dirname(__FILE__) + "/../lib/webrat/rails") -require File.dirname(__FILE__) + "/fakes/test_session" + Spec::Runner.configure do |config| # Nothing to configure yet diff --git a/spec/webrat/merb/helper.rb b/spec/webrat/merb/helper.rb new file mode 100644 index 0000000..ca55fd2 --- /dev/null +++ b/spec/webrat/merb/helper.rb @@ -0,0 +1,2 @@ +require 'merb-core' +require File.expand_path(File.dirname(__FILE__) + "/../../../lib/webrat/merb") \ No newline at end of file diff --git a/spec/webrat/rails/helper.rb b/spec/webrat/rails/helper.rb new file mode 100644 index 0000000..05d8068 --- /dev/null +++ b/spec/webrat/rails/helper.rb @@ -0,0 +1,7 @@ +require "active_support" + +silence_warnings do + require "action_controller" + require "action_controller/integration" +end +require File.expand_path(File.dirname(__FILE__) + "/../../../lib/webrat/rails") From 06997fabb8e8e4bb8c9d43bf4d3f627d2ec9c3a6 Mon Sep 17 00:00:00 2001 From: Krzysztof Zylawy Date: Tue, 21 Oct 2008 13:05:35 +0100 Subject: [PATCH 51/70] merged changes from notch8 repo --- History.txt | 2 ++ README.txt | 7 ++++++ Rakefile | 17 +++++++++++--- lib/webrat.rb | 1 - lib/webrat/core/form.rb | 4 +++- lib/webrat/core/logging.rb | 2 +- lib/webrat/core/session.rb | 26 ++++++++++++++++------ lib/webrat/merb.rb | 32 +++++++++++++++++++++++++++ lib/webrat/rack/rack_session.rb | 11 +++++++++ lib/webrat/sinatra/sinatra_session.rb | 10 +++++++-- spec/api/basic_auth_spec.rb | 23 +++++++++++++++++++ spec/spec_helper.rb | 13 +++++------ spec/webrat/merb/helper.rb | 10 +-------- spec/webrat/rails/helper.rb | 1 + 14 files changed, 128 insertions(+), 31 deletions(-) create mode 100644 spec/api/basic_auth_spec.rb diff --git a/History.txt b/History.txt index 73451cf..d9ac11e 100644 --- a/History.txt +++ b/History.txt @@ -2,6 +2,8 @@ * Major enhancements + * Added #basic_auth(user, pass) to support HTTP Basic Auth (Aslak Hellesøy) + * Added support for Sinatra and Rack (Aslak Hellesøy) * Added #within for manipulating the current page within a selector scope * Add should_see and should_not_see for verifying HTML response bodys * Add support for simulating SSL requests (Luke Melia) diff --git a/README.txt b/README.txt index dc9d997..e83f474 100644 --- a/README.txt +++ b/README.txt @@ -59,6 +59,13 @@ tests to break unnecessarily as your application evolves: A test written with Webrat can handle these changes to these without any modifications. +=== Merb +To avoid losing sessions, you need this in environments/test.rb: + +Merb::Config.use do |c| + c[:session_store] = 'memory' +end + === Install To install the latest release: diff --git a/Rakefile b/Rakefile index 9bd083a..5992b94 100644 --- a/Rakefile +++ b/Rakefile @@ -35,28 +35,39 @@ def remove_task(task_name) Rake.application.remove_task(task_name) end +def set_file_list + if ENV['TEST_MODE'] == "merb" + list = FileList['spec/**/*_spec.rb'] + list = list.find_all do |file| !file.match("rails") end + return list + else + return FileList['spec/**/*_spec.rb'] + end +end + remove_task "test" remove_task "test_deps" desc "Run all specs in spec directory" Spec::Rake::SpecTask.new do |t| t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""] - t.spec_files = FileList['spec/**/*_spec.rb'] + t.spec_files = set_file_list end desc "Run all specs in spec directory with RCov" Spec::Rake::SpecTask.new(:rcov) do |t| t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""] - t.spec_files = FileList['spec/**/*_spec.rb'] + t.spec_files = set_file_list t.rcov = true t.rcov_opts = lambda do IO.readlines(File.dirname(__FILE__) + "/spec/rcov.opts").map {|l| l.chomp.split " "}.flatten end end + require 'spec/rake/verify_rcov' RCov::VerifyTask.new(:verify_rcov => :rcov) do |t| - t.threshold = 97.2 # Make sure you have rcov 0.7 or higher! + t.threshold = 97.3 # Make sure you have rcov 0.7 or higher! end remove_task "default" diff --git a/lib/webrat.rb b/lib/webrat.rb index 57df591..af0c4dc 100644 --- a/lib/webrat.rb +++ b/lib/webrat.rb @@ -6,7 +6,6 @@ module Webrat end require "rubygems" -require "active_support" require File.dirname(__FILE__) + "/webrat/core" require File.dirname(__FILE__) + "/webrat/rails" if defined?(RAILS_ENV) diff --git a/lib/webrat/core/form.rb b/lib/webrat/core/form.rb index 3d739ab..847b159 100644 --- a/lib/webrat/core/form.rb +++ b/lib/webrat/core/form.rb @@ -86,11 +86,13 @@ module Webrat def form_action @element["action"].blank? ? @session.current_url : @element["action"] end + + HASH = [Hash, HashWithIndifferentAccess] rescue [Hash] def merge(all_params, new_param) new_param.each do |key, value| case all_params[key] - when Hash, HashWithIndifferentAccess + when *HASH merge_hash_values(all_params[key], value) when Array all_params[key] += value diff --git a/lib/webrat/core/logging.rb b/lib/webrat/core/logging.rb index a77b6fa..6634e96 100644 --- a/lib/webrat/core/logging.rb +++ b/lib/webrat/core/logging.rb @@ -10,7 +10,7 @@ module Webrat if defined? RAILS_DEFAULT_LOGGER RAILS_DEFAULT_LOGGER elsif defined? Merb - Merb.logger + Merb.logger else nil end diff --git a/lib/webrat/core/session.rb b/lib/webrat/core/session.rb index 6142877..1577b1a 100644 --- a/lib/webrat/core/session.rb +++ b/lib/webrat/core/session.rb @@ -10,8 +10,9 @@ module Webrat attr_reader :current_url def initialize - @http_method = :get - @data = {} + @http_method = :get + @data = {} + @default_headers = {} end # Saves the page out to RAILS_ROOT/tmp/ and opens it in the default @@ -52,14 +53,25 @@ module Webrat File.expand_path(".") end + def basic_auth(user, pass) + @default_headers['HTTP_AUTHORIZATION'] = "Basic " + ["#{user}:#{pass}"].pack("m*") + end + + def headers + @default_headers.dup + end + def request_page(url, http_method, data) - debug_log "REQUESTING PAGE: #{http_method.to_s.upcase} #{url} with #{data.inspect}" - if @current_url - send "#{http_method}", url, data || {}, {"HTTP_REFERER" => @current_url} - else + h = headers + h['HTTP_REFERER'] = @current_url if @current_url + + debug_log "REQUESTING PAGE: #{http_method.to_s.upcase} #{url} with #{data.inspect} and HTTP headers #{h.inspect}" + if h.empty? send "#{http_method}", url, data || {} + else + send "#{http_method}", url, data || {}, h end - + save_and_open_page if exception_caught? flunk("Page load was not successful (Code: #{response_code.inspect})") unless success_code? diff --git a/lib/webrat/merb.rb b/lib/webrat/merb.rb index bc7f662..eab0e1c 100644 --- a/lib/webrat/merb.rb +++ b/lib/webrat/merb.rb @@ -5,6 +5,7 @@ module Webrat attr_reader :response def get(url, data, headers = nil) +<<<<<<< HEAD:lib/webrat/merb.rb @response = request(url, :params => data, :headers => headers, :method => "GET") end @@ -22,12 +23,40 @@ module Webrat def response_body @response.body +======= + do_request(url, data, headers, "GET") + end + + def post(url, data, headers = nil) + do_request(url, data, headers, "POST") + end + + def put(url, data, headers = nil) + do_request(url, data, headers, "PUT") + end + + def delete(url, data, headers = nil) + do_request(url, data, headers, "DELETE") + end + + def response_body + @response.body.to_s +>>>>>>> 86879c13c05ad0448456575f148495bf700e1d4c:lib/webrat/merb.rb end def response_code @response.status end +<<<<<<< HEAD:lib/webrat/merb.rb +======= + protected + def do_request(url, data, headers, method) + @response = request(url, :params => data, :headers => headers, :method => method) + self.get(@response.headers['Location'], nil, @response.headers) if @response.status == 302 + end + +>>>>>>> 86879c13c05ad0448456575f148495bf700e1d4c:lib/webrat/merb.rb end end @@ -37,6 +66,7 @@ class Merb::Test::RspecStory end end +<<<<<<< HEAD:lib/webrat/merb.rb # # class Application < Merb::Controller @@ -57,3 +87,5 @@ require File.join(File.dirname(__FILE__), "merb", "url_encoded_pair_parser.rb") # # # +======= +>>>>>>> 86879c13c05ad0448456575f148495bf700e1d4c:lib/webrat/merb.rb diff --git a/lib/webrat/rack/rack_session.rb b/lib/webrat/rack/rack_session.rb index b283294..e3c2e24 100644 --- a/lib/webrat/rack/rack_session.rb +++ b/lib/webrat/rack/rack_session.rb @@ -1,5 +1,16 @@ require 'webrat' +class CGIMethods + def self.parse_query_parameters(params) + hash = {} + params.split('&').each do |p| + pair = p.split('=') + hash[pair[0]] = pair[1] + end + hash + end +end + module Webrat class RackSession < Session def response_body diff --git a/lib/webrat/sinatra/sinatra_session.rb b/lib/webrat/sinatra/sinatra_session.rb index 597c3b8..1083eb6 100644 --- a/lib/webrat/sinatra/sinatra_session.rb +++ b/lib/webrat/sinatra/sinatra_session.rb @@ -6,8 +6,14 @@ module Webrat class SinatraSession < RackSession include Sinatra::Test::Methods - def get(*args) - get_it(*args) + %w(get head post put delete).each do |verb| + define_method(verb) do |*args| # (path, data, headers = nil) + path, data, headers = *args + params = data.merge({:env => headers || {}}) + self.__send__("#{verb}_it", path, params) + follow! while @response.redirect? + end end + end end \ No newline at end of file diff --git a/spec/api/basic_auth_spec.rb b/spec/api/basic_auth_spec.rb new file mode 100644 index 0000000..07b9cb1 --- /dev/null +++ b/spec/api/basic_auth_spec.rb @@ -0,0 +1,23 @@ +require File.expand_path(File.dirname(__FILE__) + "/../spec_helper") + +describe "Basic Auth HTTP headers" do + before do + @session = Webrat::TestSession.new + @session.basic_auth('user', 'secret') + end + + it "should be present in visits" do + @session.should_receive(:get).with("/", {}, {'HTTP_AUTHORIZATION' => "Basic dXNlcjpzZWNyZXQ=\n"}) + @session.visits("/") + end + + it "should be present in form submits" do + @session.response_body = <<-EOS +
+ +
+ EOS + @session.should_receive(:post).with("/form1", {}, {'HTTP_AUTHORIZATION' => "Basic dXNlcjpzZWNyZXQ=\n"}) + @session.clicks_button + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 3fbe7cd..015d1e8 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -5,17 +5,16 @@ require "spec/interop/test" # gem install redgreen for colored test output begin require "redgreen" unless ENV['TM_CURRENT_LINE']; rescue LoadError; end +require File.expand_path(File.dirname(__FILE__) + "/../lib/webrat") +require File.dirname(__FILE__) + "/fakes/test_session" + if ["rails","merb"].include?(ENV["TEST_MODE"]) require File.join(File.dirname(__FILE__), "webrat", "#{ENV["TEST_MODE"]}", "helper.rb") else - puts "Please set the environment variable TEST_MODE to either 'rails' or 'merb'." - $stdout.flush - exit 1 + puts "Assuming test mode is Rails... for Merb set TEST_MODE=merb and rerun." + ENV["TEST_MODE"] = 'rails' + require File.join(File.dirname(__FILE__), "webrat", "#{ENV["TEST_MODE"]}", "helper.rb") end - -require File.expand_path(File.dirname(__FILE__) + "/../lib/webrat") -require File.expand_path(File.dirname(__FILE__) + "/../lib/webrat/rails") -require File.dirname(__FILE__) + "/fakes/test_session" Spec::Runner.configure do |config| # Nothing to configure yet diff --git a/spec/webrat/merb/helper.rb b/spec/webrat/merb/helper.rb index 2994b62..ca55fd2 100644 --- a/spec/webrat/merb/helper.rb +++ b/spec/webrat/merb/helper.rb @@ -1,10 +1,2 @@ require 'merb-core' -# module Merb -# module Test -# class RspecStory -# def flunk(message) -# raise message -# end -# end -# end -# end +require File.expand_path(File.dirname(__FILE__) + "/../../../lib/webrat/merb") \ No newline at end of file diff --git a/spec/webrat/rails/helper.rb b/spec/webrat/rails/helper.rb index bde582b..05d8068 100644 --- a/spec/webrat/rails/helper.rb +++ b/spec/webrat/rails/helper.rb @@ -4,3 +4,4 @@ silence_warnings do require "action_controller" require "action_controller/integration" end +require File.expand_path(File.dirname(__FILE__) + "/../../../lib/webrat/rails") From 0e66ec82afa9acb476ce6bfa2261e95008e81958 Mon Sep 17 00:00:00 2001 From: Krzysztof Zylawy Date: Tue, 21 Oct 2008 13:19:50 +0100 Subject: [PATCH 52/70] removed conflict accidentally checked in --- lib/webrat/merb.rb | 55 ++-------------------------------------------- 1 file changed, 2 insertions(+), 53 deletions(-) diff --git a/lib/webrat/merb.rb b/lib/webrat/merb.rb index eab0e1c..ac65ee9 100644 --- a/lib/webrat/merb.rb +++ b/lib/webrat/merb.rb @@ -5,25 +5,6 @@ module Webrat attr_reader :response def get(url, data, headers = nil) -<<<<<<< HEAD:lib/webrat/merb.rb - @response = request(url, :params => data, :headers => headers, :method => "GET") - end - - def post(url, data, headers = nil) - @response = request(url, :params => data, :headers => headers, :method => "POST") - end - - def put(url, data, headers = nil) - @response = request(url, :params => data, :headers => headers, :method => "PUT") - end - - def delete(url, data, headers = nil) - @response = request(url, :params => data, :headers => headers, :method => "DELETE") - end - - def response_body - @response.body -======= do_request(url, data, headers, "GET") end @@ -41,22 +22,14 @@ module Webrat def response_body @response.body.to_s ->>>>>>> 86879c13c05ad0448456575f148495bf700e1d4c:lib/webrat/merb.rb end - - def response_code - @response.status - end - -<<<<<<< HEAD:lib/webrat/merb.rb -======= + protected def do_request(url, data, headers, method) @response = request(url, :params => data, :headers => headers, :method => method) self.get(@response.headers['Location'], nil, @response.headers) if @response.status == 302 end - ->>>>>>> 86879c13c05ad0448456575f148495bf700e1d4c:lib/webrat/merb.rb + end end @@ -65,27 +38,3 @@ class Merb::Test::RspecStory @browser ||= Webrat::Session.new end end - -<<<<<<< HEAD:lib/webrat/merb.rb - -# -# class Application < Merb::Controller -# def cookies=(newcookies) -# @_cookies = newcookies -# end -# end -# -# -# #Other utilities used by Webrat that are present in Rails but not Merb. We can require heavy dependencies -# #here because we're only loaded in Test mode. -# require 'strscan' -# require 'cgi' -require File.join(File.dirname(__FILE__), "merb", "param_parser.rb") -require File.join(File.dirname(__FILE__), "merb", "url_encoded_pair_parser.rb") -# require File.join(File.dirname(__FILE__), "merb", "indifferent_access.rb") -# require File.join(File.dirname(__FILE__), "merb", "support.rb") -# -# -# -======= ->>>>>>> 86879c13c05ad0448456575f148495bf700e1d4c:lib/webrat/merb.rb From a940e3232b2c828a6c7b0ef192e99de4e77303ea Mon Sep 17 00:00:00 2001 From: Krzysztof Zylawy Date: Tue, 21 Oct 2008 13:24:35 +0100 Subject: [PATCH 53/70] more fixing to broken file --- lib/webrat/merb.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/webrat/merb.rb b/lib/webrat/merb.rb index ac65ee9..1684545 100644 --- a/lib/webrat/merb.rb +++ b/lib/webrat/merb.rb @@ -23,7 +23,11 @@ module Webrat def response_body @response.body.to_s end - + + def response_code + @response.status + end + protected def do_request(url, data, headers, method) @response = request(url, :params => data, :headers => headers, :method => method) @@ -38,3 +42,4 @@ class Merb::Test::RspecStory @browser ||= Webrat::Session.new end end + From 4ed917da618294d7760d45f330725a6f8e364bb7 Mon Sep 17 00:00:00 2001 From: Krzysztof Zylawy Date: Tue, 21 Oct 2008 16:27:35 +0100 Subject: [PATCH 54/70] few fixes and added whitebox tetss to increase coverage --- spec/webrat/merb/indifferent_access_spec.rb | 48 +++++++++++++++++++++ spec/webrat/merb/session_spec.rb | 43 ++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 spec/webrat/merb/indifferent_access_spec.rb create mode 100644 spec/webrat/merb/session_spec.rb diff --git a/spec/webrat/merb/indifferent_access_spec.rb b/spec/webrat/merb/indifferent_access_spec.rb new file mode 100644 index 0000000..9a92c6d --- /dev/null +++ b/spec/webrat/merb/indifferent_access_spec.rb @@ -0,0 +1,48 @@ +require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper") +require File.expand_path(File.dirname(__FILE__) + "/helper") + +describe HashWithIndifferentAccess do + it "should not update constructor when not a hash" do + HashWithIndifferentAccess.should_receive(:update).never + HashWithIndifferentAccess.new('test') + end + + it "should get the default for key" do + h = HashWithIndifferentAccess.new(:test => 'me') + h.should_receive(:super).never + + h.default(:test).should == 'me' + end + + context "a hash with a test value applied" do + + setup do + @h = HashWithIndifferentAccess.new + @h[:test] = 'me' + end + + it "should assign a new value" do + @h[:test].should == 'me' + end + + it "should return true if asked for existing key" do + @h.key?(:test).should be_true + end + + it "should return array of values for keys" do + @h.values_at(:test).should == ['me'] + end + + it "should merge with another hash" do + another = HashWithIndifferentAccess.new(:value => 'test') + @h.merge(another).values_at(:test, :value).should == ['me','test'] + end + + it "should delete the key" do + @h.delete(:test) + @h.any?.should be_false + @h[:test].should be_nil + end + + end +end \ No newline at end of file diff --git a/spec/webrat/merb/session_spec.rb b/spec/webrat/merb/session_spec.rb new file mode 100644 index 0000000..00f6021 --- /dev/null +++ b/spec/webrat/merb/session_spec.rb @@ -0,0 +1,43 @@ +require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper") +require File.expand_path(File.dirname(__FILE__) + "/helper") + +describe Webrat::Session do + + it "should not pass empty params if data is and empty hash" do + session = Webrat::Session.new + response = OpenStruct.new + response.status = 200 + session.should_receive(:request).with('url', {:params=>{}, :method=>"GET", :headers=>nil}).and_return(response) + session.get('url', {}, nil) + end + + %w{post put delete}.each do |request_method| + it "should call do request with method #{request_method.upcase} for a #{request_method} call" do + session = Webrat::Session.new + response = OpenStruct.new + response.status = 200 + + session.should_receive(:request).with('url', {:params=>{}, :method=>request_method.upcase, :headers=>nil}).and_return(response) + session.send(request_method, 'url', {}, nil) + end + end + + context "a session with a response" do + + setup do + @session = Webrat::Session.new + @response = OpenStruct.new + @response.status = 200 + @response.body = 'test response' + @session.instance_variable_set(:@response, @response) + end + + it "should return body of a request as a response_body" do + @session.response_body.should == @response.body + end + + it "should return status of a request as a response_code" do + @session.response_code.should == @response.status + end + end +end \ No newline at end of file From ddd0dd70c3c9eea282a0b748baa68d3ac97d85cf Mon Sep 17 00:00:00 2001 From: Krzysztof Zylawy Date: Tue, 21 Oct 2008 16:29:06 +0100 Subject: [PATCH 55/70] added few small fixes to webrat --- lib/webrat/core/form.rb | 2 +- lib/webrat/merb.rb | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/webrat/core/form.rb b/lib/webrat/core/form.rb index 847b159..4522710 100644 --- a/lib/webrat/core/form.rb +++ b/lib/webrat/core/form.rb @@ -105,7 +105,7 @@ module Webrat def merge_hash_values(a, b) # :nodoc: a.keys.each do |k| if b.has_key?(k) - case [a[k], b[k]].map(&:class) + case [a[k], b[k]].map{|value| value.class} when [Hash, Hash] a[k] = merge_hash_values(a[k], b[k]) b.delete(k) diff --git a/lib/webrat/merb.rb b/lib/webrat/merb.rb index 1684545..a55cf94 100644 --- a/lib/webrat/merb.rb +++ b/lib/webrat/merb.rb @@ -1,3 +1,7 @@ +Dir[File.join(File.dirname(__FILE__), "merb", "*.rb")].sort.each do |file| + require File.expand_path(file) +end + module Webrat class Session include Merb::Test::RequestHelper From ff36b51adbe8b0d044b61e26e6b0dfb44ef37cba Mon Sep 17 00:00:00 2001 From: Krzysztof Zylawy Date: Tue, 21 Oct 2008 16:47:15 +0100 Subject: [PATCH 56/70] not passing empty params --- lib/webrat/merb.rb | 2 +- spec/webrat/merb/session_spec.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/webrat/merb.rb b/lib/webrat/merb.rb index a55cf94..9d1dc8d 100644 --- a/lib/webrat/merb.rb +++ b/lib/webrat/merb.rb @@ -34,7 +34,7 @@ module Webrat protected def do_request(url, data, headers, method) - @response = request(url, :params => data, :headers => headers, :method => method) + @response = request(url, :params => (data && data.any?) ? data : nil, :headers => headers, :method => method) self.get(@response.headers['Location'], nil, @response.headers) if @response.status == 302 end diff --git a/spec/webrat/merb/session_spec.rb b/spec/webrat/merb/session_spec.rb index 00f6021..237413d 100644 --- a/spec/webrat/merb/session_spec.rb +++ b/spec/webrat/merb/session_spec.rb @@ -7,7 +7,7 @@ describe Webrat::Session do session = Webrat::Session.new response = OpenStruct.new response.status = 200 - session.should_receive(:request).with('url', {:params=>{}, :method=>"GET", :headers=>nil}).and_return(response) + session.should_receive(:request).with('url', {:params=> nil, :method=>"GET", :headers=>nil}).and_return(response) session.get('url', {}, nil) end @@ -17,7 +17,7 @@ describe Webrat::Session do response = OpenStruct.new response.status = 200 - session.should_receive(:request).with('url', {:params=>{}, :method=>request_method.upcase, :headers=>nil}).and_return(response) + session.should_receive(:request).with('url', {:params=>nil, :method=>request_method.upcase, :headers=>nil}).and_return(response) session.send(request_method, 'url', {}, nil) end end From 12f415d33015576c6f09fd83ea646d0bee9314a4 Mon Sep 17 00:00:00 2001 From: Krzysztof Zylawy Date: Tue, 21 Oct 2008 16:52:47 +0100 Subject: [PATCH 57/70] fixed manifest that prevnts from properly installing in merb app --- Manifest.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Manifest.txt b/Manifest.txt index a4fed52..53eaa24 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -38,7 +38,8 @@ lib/webrat/selenium/location_strategy_javascript/webratlink.js lib/webrat/selenium/location_strategy_javascript/webratlinkwithin.js lib/webrat/selenium/location_strategy_javascript/webratselectwithoption.js lib/webrat/selenium/selenium_session.rb -lib/webrat/sinatra/sinatra_session.rbmechanize_spike.rb +lib/webrat/sinatra/sinatra_session.rb +mechanize_spike.rb selenium_spike.rb spec/api/attaches_file_spec.rb spec/api/checks_spec.rb From e30e88594fb1348b7e83ea4eb0c73616ab780217 Mon Sep 17 00:00:00 2001 From: Miha Filej Date: Tue, 21 Oct 2008 18:13:42 +0200 Subject: [PATCH 58/70] Added field value escaping --- lib/webrat/core/field.rb | 7 +++++-- spec/api/fills_in_spec.rb | 13 +++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/webrat/core/field.rb b/lib/webrat/core/field.rb index 107bd66..e5a366c 100644 --- a/lib/webrat/core/field.rb +++ b/lib/webrat/core/field.rb @@ -56,10 +56,9 @@ module Webrat def to_param return nil if disabled? - value = @value.to_s.gsub('&', '%26') param_parser.parse_query_parameters("#{name}=#{value}") end - + def set(value) @value = value end @@ -78,6 +77,10 @@ module Webrat @element["name"] end + def value + CGI.escape(@value.to_s) + end + def labels @labels ||= label_elements.map { |element| Label.new(self, element) } end diff --git a/spec/api/fills_in_spec.rb b/spec/api/fills_in_spec.rb index b13b2cf..99682f6 100644 --- a/spec/api/fills_in_spec.rb +++ b/spec/api/fills_in_spec.rb @@ -157,4 +157,17 @@ describe "fills_in" do @session.fills_in :email, :with => "foo@example.com" @session.clicks_button end + + it "should escape field values" do + @session.response_body = <<-EOS +
+ + + +
+ EOS + @session.should_receive(:post).with("/users", "user" => {"phone" => "+1 22 33"}) + @session.fills_in 'Phone', :with => "+1 22 33" + @session.clicks_button + end end From 2d166ae2b83d9482af3d54bac855b69233ad00f8 Mon Sep 17 00:00:00 2001 From: Derek Kastner Date: Tue, 21 Oct 2008 21:33:49 -0400 Subject: [PATCH 59/70] fixed Webrat::MechanizeSession - calling visit on a newly created session was failing. Default headers were not set and Webrat::Session#request_page would fail when Webrat::Session#headers was called - dup was being called on the nil headers --- lib/webrat/mechanize/mechanize_session.rb | 1 + spec/webrat/mechanize/mechanize_session_spec.rb | 13 +++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 spec/webrat/mechanize/mechanize_session_spec.rb diff --git a/lib/webrat/mechanize/mechanize_session.rb b/lib/webrat/mechanize/mechanize_session.rb index 2f48c17..7a817c4 100644 --- a/lib/webrat/mechanize/mechanize_session.rb +++ b/lib/webrat/mechanize/mechanize_session.rb @@ -2,6 +2,7 @@ module Webrat class MechanizeSession < Session def initialize(mechanize = WWW::Mechanize.new) + super() @mechanize = mechanize end diff --git a/spec/webrat/mechanize/mechanize_session_spec.rb b/spec/webrat/mechanize/mechanize_session_spec.rb new file mode 100644 index 0000000..f69dad2 --- /dev/null +++ b/spec/webrat/mechanize/mechanize_session_spec.rb @@ -0,0 +1,13 @@ +require File.expand_path(File.dirname(__FILE__) + "/../../../lib/webrat/mechanize") + +describe Webrat::MechanizeSession do + before(:each) do + @mech = Webrat::MechanizeSession.new + end + + describe "headers method" do + it "should return empty headers for a newly initialized session" do + @mech.headers.should == {} + end + end +end \ No newline at end of file From 85330c9b1b0c0a5480dfde64a90c029373db8239 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Tue, 21 Oct 2008 22:02:24 -0400 Subject: [PATCH 60/70] Changelog --- History.txt | 63 +++++++++++++++++++++++++++-------------------------- Rakefile | 2 +- 2 files changed, 33 insertions(+), 32 deletions(-) diff --git a/History.txt b/History.txt index d9ac11e..fb34b97 100644 --- a/History.txt +++ b/History.txt @@ -7,40 +7,41 @@ * Added #within for manipulating the current page within a selector scope * Add should_see and should_not_see for verifying HTML response bodys * Add support for simulating SSL requests (Luke Melia) - * Add support for file fields via #attaches_file method (Patch from Kyle Hargraves) - * Support relative links, including href="?foo=bar" (Patch from Kyle Hargraves) + * Add support for file fields via #attaches_file method (Kyle Hargraves) + * Support relative links, including href="?foo=bar" (Kyle Hargraves) * Separated Rails-specific code from the Webrat core to make it easier to use Webrat with other environments * Alias visits as visit, clicks_link as click_link, etc. for better readability * Raise error when trying to interact with a disabled form element (Luke Melia) - * Don't send disabled form elements to the server (Patch from Nicholas A. Evans) + * Don't send disabled form elements to the server (Nicholas A. Evans) * Minor enhancements - * Add support for redirect_to :back by sending HTTP_REFERER headers (Patch from Hendrik Volkmer) + * Add support for redirect_to :back by sending HTTP_REFERER headers (Hendrik Volkmer) * Expose current DOM (as an Hpricot object) as #current_dom * Add support for disabling JavaScript when clicking a link to enable testing of both JS and non-JS implementations (Luke Melia and Bryan Helmkamp) - * Support  's as spaces in matching link text (Patch from Luke Melia) - * Support button elements (Patch from Nick Sieger) - * Support matching select options by regexp (Patch from Kyle Hargraves) + * Support  's as spaces in matching link text (Luke Melia) + * Support button elements (Nick Sieger) + * Support matching select options by regexp (Kyle Hargraves) * save_and_open_page rewrites css and image references to provide a friendlier debugging experience (Luke Melia) - * Added support for matching alt attributes in fields (primarly for clicks_button) (Patch from Aaron Quint) - * Support '&' in submitted values (Patch from Kyle Hargraves) - * Support clicking links by title (Patch from Dan Barry) - * Added missing spec for clicking image buttons (Patch from Tim Harper) + * Added support for matching alt attributes in fields (primarly for clicks_button) (Aaron Quint) + * Support '&' in submitted values (Kyle Hargraves) + * Support clicking links by title (Dan Barry) + * Added missing spec for clicking image buttons (Tim Harper) * Switched tests to specs, and from Mocha to RSpec's mocking library - * Add support to click_button for IDs (Patch from Gwyn Morfey) - * Miscellaneous core refactorings (Patch from Jan Suchal) + * Add support to click_button for IDs (Gwyn Morfey) + * Miscellaneous core refactorings (Jan Suchal) * Bug fixes - * Don't open blank pages in the browser (Patch from Kyle Hargraves) - * Support radio buttons with multiple labels (Patch from Dan Barry) - * Fix load order bug on some platforms (Patch from Ismael Celis) - * Fix bug with empty select list option (Patch from Kyle Hargraves) + * Don't open blank pages in the browser (Kyle Hargraves) + * Support radio buttons with multiple labels (Dan Barry) + * Fix load order bug on some platforms (Ismael Celis) + * Fix bug with empty select list option (Kyle Hargraves) * Fix regression of not sending default values in password fields * Don't explode if encountering inputs with no type attribute (assume text) * Fix bug where choosing a radio button in a series with a default submitted the incorrect field value (Luke Melia) + * Fix initialization of WWW::Mechanize (Derek Kastner) == 0.2.0 / 2008-04-04 @@ -50,29 +51,29 @@ * Add radio button support via #chooses method * Add basic support for Rails-generated JavaScript link tags * Add support for checkboxes (Patches from Kyle Hargraves and Jarkko Laine) - * Add support for textarea fields (Patch from Sacha Schlegel) + * Add support for textarea fields (Sacha Schlegel) * 8 Minor enhancements - * Added reloads method to reload the page (Patch from Kamal Fariz Mahyuddi) - * Prevent making a request if clicking on local anchor link (Patch from Kamal Fariz Mahyuddi) + * Added reloads method to reload the page (Kamal Fariz Mahyuddi) + * Prevent making a request if clicking on local anchor link (Kamal Fariz Mahyuddi) * Added clicks_link_within(selector, link_text), allowing restricting link search - to within a given css selector (Patch from Luke Melia) - * Allow specifying the input name/label when doing a select (Patch from David Chelimsky) - * Raise a specific exception if the developer tries to manipulate form elements before loading a page (Patch from James Deville) - * Add support for alternate POST, PUT and DELETE link clicking (Patch from Kyle Hargraves) - * Change clicks_link to find the shortest matching link (Patch from Luke Melia) + to within a given css selector (Luke Melia) + * Allow specifying the input name/label when doing a select (David Chelimsky) + * Raise a specific exception if the developer tries to manipulate form elements before loading a page (James Deville) + * Add support for alternate POST, PUT and DELETE link clicking (Kyle Hargraves) + * Change clicks_link to find the shortest matching link (Luke Melia) * Improve matching for labels in potentially ambiguous cases * 7 Bug fixes - * Fix incorrect serializing of collection inputs, i.e. name contains [] (Patch from Kamal Fariz Mahyuddi) - * Serialize empty text field values just like browsers (Patch from Kamal Fariz Mahyuddi) - * Quick fix to avoid @dom not initialized warnings (Patch from Kamal Fariz Mahyuddi) - * Docfix: bad reference to #select method in README (Patch from Luke Melia) + * Fix incorrect serializing of collection inputs, i.e. name contains [] (Kamal Fariz Mahyuddi) + * Serialize empty text field values just like browsers (Kamal Fariz Mahyuddi) + * Quick fix to avoid @dom not initialized warnings (Kamal Fariz Mahyuddi) + * Docfix: bad reference to #select method in README (Luke Melia) * Ensure Rails-style checkboxes work properly (checkboxes followed by a hidden input with the same name) - * Fix Edge Rails (a.k.a. 2.0 RC) compatibility (Patch from David Chelimsky) - * Support param hashes nested more than one level (Patch from David Chelimsky) + * Fix Edge Rails (a.k.a. 2.0 RC) compatibility (David Chelimsky) + * Support param hashes nested more than one level (David Chelimsky) == 0.1.0 / 2007-11-28 diff --git a/Rakefile b/Rakefile index 75c8c69..cc6e097 100644 --- a/Rakefile +++ b/Rakefile @@ -56,7 +56,7 @@ end require 'spec/rake/verify_rcov' RCov::VerifyTask.new(:verify_rcov => :rcov) do |t| - t.threshold = 97.3 # Make sure you have rcov 0.7 or higher! + t.threshold = 96.4 # Make sure you have rcov 0.7 or higher! end remove_task "default" From 8c73680e64d22ce1306971cab92b4a182a783446 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Tue, 21 Oct 2008 22:05:21 -0400 Subject: [PATCH 61/70] Rename Field#value to Field#escaped_value --- lib/webrat/core/field.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/webrat/core/field.rb b/lib/webrat/core/field.rb index e5a366c..dde96ca 100644 --- a/lib/webrat/core/field.rb +++ b/lib/webrat/core/field.rb @@ -56,7 +56,7 @@ module Webrat def to_param return nil if disabled? - param_parser.parse_query_parameters("#{name}=#{value}") + param_parser.parse_query_parameters("#{name}=#{escaped_value}") end def set(value) @@ -77,7 +77,7 @@ module Webrat @element["name"] end - def value + def escaped_value CGI.escape(@value.to_s) end From 854d09a13e400c8b7ed5be2319ad82faaa32db4c Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Tue, 21 Oct 2008 22:06:18 -0400 Subject: [PATCH 62/70] History --- History.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/History.txt b/History.txt index fb34b97..fe876e2 100644 --- a/History.txt +++ b/History.txt @@ -16,6 +16,7 @@ * Minor enhancements + * CGI escape form field values (Miha Filej) * Add support for redirect_to :back by sending HTTP_REFERER headers (Hendrik Volkmer) * Expose current DOM (as an Hpricot object) as #current_dom * Add support for disabling JavaScript when clicking a link to enable testing of both JS @@ -34,6 +35,7 @@ * Bug fixes + * Fix initialization of WWW::Mechanize (Derek Kastner) * Don't open blank pages in the browser (Kyle Hargraves) * Support radio buttons with multiple labels (Dan Barry) * Fix load order bug on some platforms (Ismael Celis) @@ -41,7 +43,6 @@ * Fix regression of not sending default values in password fields * Don't explode if encountering inputs with no type attribute (assume text) * Fix bug where choosing a radio button in a series with a default submitted the incorrect field value (Luke Melia) - * Fix initialization of WWW::Mechanize (Derek Kastner) == 0.2.0 / 2008-04-04 From bbc826d8c59e2102a33e41f8d6561b9be43f0157 Mon Sep 17 00:00:00 2001 From: David Leal Date: Sun, 19 Oct 2008 10:45:08 +0100 Subject: [PATCH 63/70] Show error page. --- lib/webrat/core/session.rb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/webrat/core/session.rb b/lib/webrat/core/session.rb index 1577b1a..ffe7eeb 100644 --- a/lib/webrat/core/session.rb +++ b/lib/webrat/core/session.rb @@ -73,7 +73,7 @@ module Webrat end save_and_open_page if exception_caught? - flunk("Page load was not successful (Code: #{response_code.inspect})") unless success_code? + flunk("Page load was not successful (Code: #{response_code.inspect}):\n#{formatted_error}") unless success_code? @scope = nil @current_url = url @@ -141,6 +141,11 @@ module Webrat response_html.gsub(/"\/(stylesheets|images)/, doc_root + '/\1') end + # Subclasses can override this to show error messages without html + def formatted_error + response_body + end + def_delegators :current_scope, :fill_in, :fills_in def_delegators :current_scope, :check, :checks def_delegators :current_scope, :uncheck, :unchecks @@ -156,4 +161,4 @@ module Webrat def_delegators :current_scope, :should_see def_delegators :current_scope, :should_not_see end -end \ No newline at end of file +end From 8e32ae80caa3158f235692f4638d409aeaf92a0f Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Tue, 21 Oct 2008 22:13:43 -0400 Subject: [PATCH 64/70] History --- History.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/History.txt b/History.txt index fe876e2..887bf96 100644 --- a/History.txt +++ b/History.txt @@ -16,6 +16,7 @@ * Minor enhancements + * Display response body when the page load is not successful (David Leal) * CGI escape form field values (Miha Filej) * Add support for redirect_to :back by sending HTTP_REFERER headers (Hendrik Volkmer) * Expose current DOM (as an Hpricot object) as #current_dom From a59e6f873a35436585ebec12bcbca9164f5ffd1c Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Tue, 21 Oct 2008 22:20:02 -0400 Subject: [PATCH 65/70] Coverage --- Rakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rakefile b/Rakefile index cc6e097..4838cb7 100644 --- a/Rakefile +++ b/Rakefile @@ -56,7 +56,7 @@ end require 'spec/rake/verify_rcov' RCov::VerifyTask.new(:verify_rcov => :rcov) do |t| - t.threshold = 96.4 # Make sure you have rcov 0.7 or higher! + t.threshold = 96.2 # Make sure you have rcov 0.7 or higher! end remove_task "default" From 7adeb86f2c5d4f9c0f92c00280ba8d55a9d4d2bb Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Tue, 21 Oct 2008 22:35:12 -0400 Subject: [PATCH 66/70] Add support for clicking areas of an image map (Alex Lang) --- History.txt | 9 ++-- lib/webrat/core/area.rb | 44 ++++++++++++++++++++ lib/webrat/core/scope.rb | 17 +++++++- lib/webrat/core/session.rb | 1 + spec/api/clicks_area_spec.rb | 81 ++++++++++++++++++++++++++++++++++++ 5 files changed, 147 insertions(+), 5 deletions(-) create mode 100644 lib/webrat/core/area.rb create mode 100644 spec/api/clicks_area_spec.rb diff --git a/History.txt b/History.txt index 887bf96..378f661 100644 --- a/History.txt +++ b/History.txt @@ -5,17 +5,18 @@ * Added #basic_auth(user, pass) to support HTTP Basic Auth (Aslak Hellesøy) * Added support for Sinatra and Rack (Aslak Hellesøy) * Added #within for manipulating the current page within a selector scope - * Add should_see and should_not_see for verifying HTML response bodys * Add support for simulating SSL requests (Luke Melia) * Add support for file fields via #attaches_file method (Kyle Hargraves) + +* Minor enhancements + + * Add support for clicking areas of an image map (Alex Lang) + * Add should_see and should_not_see for verifying HTML response bodys * Support relative links, including href="?foo=bar" (Kyle Hargraves) * Separated Rails-specific code from the Webrat core to make it easier to use Webrat with other environments * Alias visits as visit, clicks_link as click_link, etc. for better readability * Raise error when trying to interact with a disabled form element (Luke Melia) * Don't send disabled form elements to the server (Nicholas A. Evans) - -* Minor enhancements - * Display response body when the page load is not successful (David Leal) * CGI escape form field values (Miha Filej) * Add support for redirect_to :back by sending HTTP_REFERER headers (Hendrik Volkmer) diff --git a/lib/webrat/core/area.rb b/lib/webrat/core/area.rb new file mode 100644 index 0000000..3812654 --- /dev/null +++ b/lib/webrat/core/area.rb @@ -0,0 +1,44 @@ +module Webrat + class Area + + def initialize(session, element) + @session = session + @element = element + end + + def click(method = nil, options = {}) + @session.request_page(absolute_href, :get, {}) + end + + def matches_text?(id_or_title) + matcher = /#{Regexp.escape(id_or_title.to_s)}/i + title =~ matcher || id =~ matcher + end + + protected + + def href + @element["href"] + end + + def title + @element["title"] + end + + def id + @element["id"] + end + + + def absolute_href + if href =~ /^\?/ + "#{@session.current_url}#{href}" + elsif href !~ %r{^https?://[\w|.]+(/.*)} && (href !~ /^\//) + "#{@session.current_url}/#{href}" + else + href + end + end + + end +end \ No newline at end of file diff --git a/lib/webrat/core/scope.rb b/lib/webrat/core/scope.rb index f74727d..99b95c6 100644 --- a/lib/webrat/core/scope.rb +++ b/lib/webrat/core/scope.rb @@ -91,6 +91,12 @@ module Webrat alias_method :attach_file, :attaches_file + def clicks_area(area_name) + find_area(area_name).click + end + + alias_method :click_area, :clicks_area + # Issues a request for the URL pointed to by a link on the current page, # follows any redirects, and verifies the final page load was successful. # @@ -200,10 +206,19 @@ module Webrat button = form.find_button(value) return button if button end - flunk("Could not find button #{value.inspect}") end + def find_area(area_name) + areas.select{|area| area.matches_text?(area_name)}.first || flunk("Could not find area with name #{area_name}") + end + + def areas + (dom / "area").map do |element| + Area.new(@session, element) + end + end + def find_link(text, selector = nil) matching_links = links_within(selector).select do |possible_link| possible_link.matches_text?(text) diff --git a/lib/webrat/core/session.rb b/lib/webrat/core/session.rb index ffe7eeb..04e25af 100644 --- a/lib/webrat/core/session.rb +++ b/lib/webrat/core/session.rb @@ -152,6 +152,7 @@ module Webrat def_delegators :current_scope, :choose, :chooses def_delegators :current_scope, :select, :selects def_delegators :current_scope, :attach_file, :attaches_file + def_delegators :current_scope, :click_area, :clicks_area def_delegators :current_scope, :click_link, :clicks_link def_delegators :current_scope, :click_get_link, :clicks_get_link def_delegators :current_scope, :click_delete_link, :clicks_delete_link diff --git a/spec/api/clicks_area_spec.rb b/spec/api/clicks_area_spec.rb new file mode 100644 index 0000000..c7fbc29 --- /dev/null +++ b/spec/api/clicks_area_spec.rb @@ -0,0 +1,81 @@ +require File.expand_path(File.dirname(__FILE__) + "/../spec_helper") + +describe "clicks_area" do + before do + @session = Webrat::TestSession.new + end + + it "should use get by default" do + @session.response_body = <<-EOS + + Berlin + + EOS + @session.should_receive(:get).with("/page", {}) + @session.clicks_area "Berlin" + end + + it "should assert valid response" do + @session.response_body = <<-EOS + + Berlin + + EOS + @session.response_code = 404 + lambda { @session.clicks_area "Berlin" }.should raise_error + end + + it "should fail if the area doesn't exist" do + @session.response_body = <<-EOS + + Berlin + + EOS + + lambda { + @session.clicks_area "Missing area" + }.should raise_error + end + + it "should not be case sensitive" do + @session.response_body = <<-EOS + + Berlin + + EOS + @session.should_receive(:get).with("/page", {}) + @session.clicks_area "berlin" + end + + + it "should follow relative links" do + @session.stub!(:current_url).and_return("/page") + @session.response_body = <<-EOS + + Berlin + + EOS + @session.should_receive(:get).with("/page/sub", {}) + @session.clicks_area "Berlin" + end + + it "should follow fully qualified local links" do + @session.response_body = <<-EOS + + Berlin + + EOS + @session.should_receive(:get).with("http://www.example.com/page", {}) + @session.clicks_area "Berlin" + end + + it "should follow query parameters" do + @session.response_body = <<-EOS + + Berlin + + EOS + @session.should_receive(:get).with("/page?foo=bar", {}) + @session.clicks_area "Berlin" + end +end From 1b51de8f0fda13778fe8e0ba5e86adf0982cbed6 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Tue, 21 Oct 2008 22:41:02 -0400 Subject: [PATCH 67/70] Support selecting options by their values (Alex Lang) --- History.txt | 3 ++- lib/webrat/core/field.rb | 14 +++++++++++--- lib/webrat/core/select_option.rb | 4 ++++ spec/api/selects_spec.rb | 12 ++++++++++++ 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/History.txt b/History.txt index 378f661..303cb50 100644 --- a/History.txt +++ b/History.txt @@ -10,7 +10,8 @@ * Minor enhancements - * Add support for clicking areas of an image map (Alex Lang) + * Support selecting options by their values (Alex Lang) + * Support for clicking areas of an image map (Alex Lang) * Add should_see and should_not_see for verifying HTML response bodys * Support relative links, including href="?foo=bar" (Kyle Hargraves) * Separated Rails-specific code from the Webrat core to make it easier to use Webrat with other environments diff --git a/lib/webrat/core/field.rb b/lib/webrat/core/field.rb index dde96ca..05cec00 100644 --- a/lib/webrat/core/field.rb +++ b/lib/webrat/core/field.rb @@ -30,11 +30,11 @@ module Webrat end def matches_id?(id) - @element["id"] == id.to_s + matches?(self.id, id) end def matches_name?(name) - @element["name"] == name.to_s + matches?(self.name, name) end def matches_label?(label_text) @@ -69,6 +69,14 @@ module Webrat protected + def matches?(string, string_or_regex) + if string_or_regex.is_a?(Regexp) + string_or_regex.match string + else + string == string_or_regex + end + end + def id @element["id"] end @@ -303,7 +311,7 @@ module Webrat class SelectField < Field def find_option(text) - options.detect { |o| o.matches_text?(text) } + options.detect { |o| o.matches_text?(text) || o.matches_value?(text)} end protected diff --git a/lib/webrat/core/select_option.rb b/lib/webrat/core/select_option.rb index c46224f..8df63dd 100644 --- a/lib/webrat/core/select_option.rb +++ b/lib/webrat/core/select_option.rb @@ -14,6 +14,10 @@ module Webrat end end + def matches_value?(value) + @element.attributes['value'] == value.to_s + end + def choose @select.raise_error_if_disabled @select.set(value) diff --git a/spec/api/selects_spec.rb b/spec/api/selects_spec.rb index d33afce..75e44d9 100644 --- a/spec/api/selects_spec.rb +++ b/spec/api/selects_spec.rb @@ -108,6 +108,18 @@ describe "selects" do @session.clicks_button end + it "should send value from option in list specified by value" do + @session.response_body = <<-EOS +
+ + +
+ EOS + @session.should_receive(:post).with("/login", "start_month" => "s1") + @session.selects "s1", :from => "start_month" + @session.clicks_button + end + it "should send value from option in list specified by label" do @session.response_body = <<-EOS
From 9671c4256cfaa232690bec0ebe547e2d1370ed0a Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Tue, 21 Oct 2008 22:44:39 -0400 Subject: [PATCH 68/70] Add #select_date for quickly filling out Rails-style date fields (Alex Lang) --- History.txt | 1 + lib/webrat/core/form.rb | 6 +- lib/webrat/core/scope.rb | 16 +++++ lib/webrat/core/session.rb | 1 + spec/api/selects_date_spec.rb | 111 ++++++++++++++++++++++++++++++++++ 5 files changed, 131 insertions(+), 4 deletions(-) create mode 100644 spec/api/selects_date_spec.rb diff --git a/History.txt b/History.txt index 303cb50..26eb924 100644 --- a/History.txt +++ b/History.txt @@ -10,6 +10,7 @@ * Minor enhancements + * Add #select_date for quickly filling out Rails-style date fields (Alex Lang) * Support selecting options by their values (Alex Lang) * Support for clicking areas of an image map (Alex Lang) * Add should_see and should_not_see for verifying HTML response bodys diff --git a/lib/webrat/core/form.rb b/lib/webrat/core/form.rb index 847b159..0dbf3db 100644 --- a/lib/webrat/core/form.rb +++ b/lib/webrat/core/form.rb @@ -17,14 +17,12 @@ module Webrat nil end - def find_select_option(option_text) + def find_select_option(option_text, field_name_pattern = nil) select_fields = fields_by_type([SelectField]) - - select_fields.each do |select_field| + select_fields.select{|field| field_name_pattern.nil? || field.matches_name?(field_name_pattern) || field.matches_id?(field_name_pattern)}.each do |select_field| result = select_field.find_option(option_text) return result if result end - nil end diff --git a/lib/webrat/core/scope.rb b/lib/webrat/core/scope.rb index 99b95c6..600a7b0 100644 --- a/lib/webrat/core/scope.rb +++ b/lib/webrat/core/scope.rb @@ -12,6 +12,22 @@ module Webrat @selector = selector end + def selects_date(date_string, options = {}) + id_or_name = options[:from] + date = Date.parse date_string + + year_option = find_select_option(date.year.to_s, /#{id_or_name.to_s}.*1i/) + month_option = find_select_option(date.month.to_s, /#{id_or_name.to_s}.*2i/) + day_option = find_select_option(date.day.to_s, /#{id_or_name.to_s}.*3i/) + + flunk("Could not find date picker for #{date_string}") if year_option.nil? || month_option.nil? || day_option.nil? + year_option.choose + month_option.choose + day_option.choose + end + + alias_method :select_date, :selects_date + # Verifies an input field or textarea exists on the current page, and stores a value for # it which will be sent when the form is submitted. # diff --git a/lib/webrat/core/session.rb b/lib/webrat/core/session.rb index 04e25af..ab89e50 100644 --- a/lib/webrat/core/session.rb +++ b/lib/webrat/core/session.rb @@ -151,6 +151,7 @@ module Webrat def_delegators :current_scope, :uncheck, :unchecks def_delegators :current_scope, :choose, :chooses def_delegators :current_scope, :select, :selects + def_delegators :current_scope, :select_date, :selects_date def_delegators :current_scope, :attach_file, :attaches_file def_delegators :current_scope, :click_area, :clicks_area def_delegators :current_scope, :click_link, :clicks_link diff --git a/spec/api/selects_date_spec.rb b/spec/api/selects_date_spec.rb new file mode 100644 index 0000000..cad52ff --- /dev/null +++ b/spec/api/selects_date_spec.rb @@ -0,0 +1,111 @@ +require File.expand_path(File.dirname(__FILE__) + "/../spec_helper") + +describe "date_selects" do + before do + @session = Webrat::TestSession.new + @example_date_select = <<-EOS + +
+ + + + + + EOS + end + + + it "should fail if option not found" do + @session.response_body = @example_date_select + lambda { @session.selects_date "2008-07-13"}.should raise_error + end + + it "should fail if option not found in list specified by element name" do + @session.response_body = @example_date_select + lambda { @session.selects_date "2008-07-13", :from => "created_at" }.should raise_error + end + + it "should fail if specified list not found" do + @session.response_body = <<-EOS +
+ +
+ EOS + + lambda { @session.selects_date "2003-12-01", :from => "created_at" }.should raise_error + end + + it "should send value from option" do + @session.response_body = <<-EOS +
+
+ + + +
+ + + + +
+ EOS + @session.should_receive(:post).with("/login", "created_at(1i)" => "2003", 'created_at(2i)' => '12', 'created_at(3i)' => '1', "updated_at(1i)" => "", 'updated_at(2i)' => '', 'updated_at(3i)' => '') + @session.selects_date '2003-12-01', :from => "created_at" + @session.clicks_button + end + + it "should work without specifying the field name or label" do + @session.response_body = @example_date_select + @session.should_receive(:post).with("/login", "created_at(1i)" => "2003", 'created_at(2i)' => '12', 'created_at(3i)' => '1') + @session.selects_date '2003-12-01' + @session.clicks_button + end + + it "should correctly set day and month when there are the same options available" do + @session.response_body = <<-EOS +
+
+ + + + +
+ EOS + @session.should_receive(:post).with("/login", "created_at(1i)" => "2003", 'created_at(2i)' => '12', 'created_at(3i)' => '1') + @session.selects_date '2003-12-01' + @session.clicks_button + end + +end From 58a9fc3ac37c2c27331809ab140f4373f7a6f08e Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Tue, 21 Oct 2008 23:01:08 -0400 Subject: [PATCH 69/70] Manifest --- Manifest.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Manifest.txt b/Manifest.txt index 4e749b6..08b0319 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -8,6 +8,7 @@ init.rb install.rb lib/webrat.rb lib/webrat/core.rb +lib/webrat/core/area.rb lib/webrat/core/assertions.rb lib/webrat/core/field.rb lib/webrat/core/flunk.rb @@ -20,22 +21,38 @@ lib/webrat/core/select_option.rb lib/webrat/core/session.rb lib/webrat/mechanize.rb lib/webrat/mechanize/mechanize_session.rb +lib/webrat/merb.rb +lib/webrat/merb/indifferent_access.rb +lib/webrat/merb/param_parser.rb +lib/webrat/merb/support.rb +lib/webrat/merb/url_encoded_pair_parser.rb +lib/webrat/rack/rack_session.rb lib/webrat/rails.rb lib/webrat/rails/rails_session.rb lib/webrat/rails/redirect_actions.rb lib/webrat/rails/session.rb lib/webrat/selenium.rb +lib/webrat/selenium/location_strategy_javascript/button.js +lib/webrat/selenium/location_strategy_javascript/label.js +lib/webrat/selenium/location_strategy_javascript/webrat.js +lib/webrat/selenium/location_strategy_javascript/webratlink.js +lib/webrat/selenium/location_strategy_javascript/webratlinkwithin.js +lib/webrat/selenium/location_strategy_javascript/webratselectwithoption.js lib/webrat/selenium/selenium_session.rb +lib/webrat/sinatra/sinatra_session.rb mechanize_spike.rb selenium_spike.rb spec/api/attaches_file_spec.rb +spec/api/basic_auth_spec.rb spec/api/checks_spec.rb spec/api/chooses_spec.rb +spec/api/clicks_area_spec.rb spec/api/clicks_button_spec.rb spec/api/clicks_link_spec.rb spec/api/fills_in_spec.rb spec/api/reloads_spec.rb spec/api/save_and_open_spec.rb +spec/api/selects_date_spec.rb spec/api/selects_spec.rb spec/api/should_not_see_spec.rb spec/api/should_see_spec.rb @@ -48,5 +65,8 @@ spec/spec.opts spec/spec_helper.rb spec/webrat/core/logging_spec.rb spec/webrat/core/session_spec.rb +spec/webrat/mechanize/mechanize_session_spec.rb +spec/webrat/merb/helper.rb +spec/webrat/rails/helper.rb spec/webrat/rails/rails_session_spec.rb webrat.gemspec From 2f656c85c725c292d17f997a3b8dc2aef1a99392 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Tue, 21 Oct 2008 23:02:45 -0400 Subject: [PATCH 70/70] History --- History.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/History.txt b/History.txt index 26eb924..70f95ac 100644 --- a/History.txt +++ b/History.txt @@ -2,6 +2,7 @@ * Major enhancements + * Added Merb support (Gwyn Morfey, Jeremy Burks, Rob Kaufman) * Added #basic_auth(user, pass) to support HTTP Basic Auth (Aslak Hellesøy) * Added support for Sinatra and Rack (Aslak Hellesøy) * Added #within for manipulating the current page within a selector scope