From cdafd2ec0ff481d5676e808e46a1f1108fafeea1 Mon Sep 17 00:00:00 2001 From: Gwyn Morfey Date: Wed, 16 Apr 2008 10:54:37 +0100 Subject: [PATCH 01/29] 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/29] 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/29] 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/29] 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/29] 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/29] 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/29] 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/29] 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/29] 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/29] 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/29] 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/29] 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/29] 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/29] 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/29] 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/29] 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/29] 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/29] 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 300880db2f0d50a3e2d7b171eb9745cb50e1c534 Mon Sep 17 00:00:00 2001 From: Jeremy Burks Date: Sun, 5 Oct 2008 22:05:01 -0500 Subject: [PATCH 19/29] 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 264b147b6fb7e5ed118c1d0e0161fd0e69b4a1b8 Mon Sep 17 00:00:00 2001 From: Rob Kaufman Date: Sat, 11 Oct 2008 17:09:15 -0700 Subject: [PATCH 20/29] 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 b8e76a1af28a41ede3288443777714b1f4dad42f Mon Sep 17 00:00:00 2001 From: Rob Kaufman Date: Fri, 17 Oct 2008 19:41:24 -0700 Subject: [PATCH 21/29] 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 22/29] 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 06997fabb8e8e4bb8c9d43bf4d3f627d2ec9c3a6 Mon Sep 17 00:00:00 2001 From: Krzysztof Zylawy Date: Tue, 21 Oct 2008 13:05:35 +0100 Subject: [PATCH 23/29] 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 24/29] 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 25/29] 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 26/29] 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 27/29] 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 28/29] 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 29/29] 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