module Remarkable module ActionController module Matchers class RespondWithMatcher < Remarkable::ActionController::Base #:nodoc: arguments :block => true optional :with, :body, :content_type before_assert do @response = @subject.respond_to?(:response) ? @subject.response : @subject @controller = @spec.instance_variable_get('@controller') end before_assert :evaluate_content_type, :evaluate_body assertions :status_matches?, :body_matches?, :content_type_matches? protected def status_matches? return true unless @options[:with] # only continue if not nil case @options[:with] when :success, :missing, :redirect, :error @response.send("#{@options[:with]}?") when Fixnum @response.response_code == @options[:with] when Symbol, String @response.response_code == ::ActionController::StatusCodes::SYMBOL_TO_STATUS_CODE[@options[:with].to_sym] when Range @options[:with].include?(@response.response_code) else raise ArgumentError, "I don't know how to interpret status #{@options[:with].inspect}, " << "please give me a Fixnum, Symbol, String or Range." end end def body_matches? return true unless @options.key?(:body) assert_contains(@response.body, @options[:body]) end def content_type_matches? return true unless @options.key?(:content_type) assert_contains(@response.content_type, @options[:content_type]) end def evaluate_content_type return unless @options.key?(:content_type) @options[:content_type] = case @options[:content_type] when Symbol Mime::Type.lookup_by_extension(@options[:content_type].to_s).to_s when Regexp @options[:content_type] else @options[:content_type].to_s end end def evaluate_body if @options.key?(:body) || @block value = @options.key?(:body) ? @options[:body] : @block value = @spec.instance_eval(&value) if value.is_a?(Proc) @options[:body] = value end end def interpolation_options if @response { :actual_body => @response.body.inspect, :actual_status => @response.response_code.inspect, :actual_content_type => @response.content_type.inspect } else { } end end end # Passes if the response has the given status. Status can be a Symbol lik # :success, :missing, :redirect and :error. Can be also a Fixnum, Range o # any other symbol which matches to any of Rails status codes. # # == Options # # * :body - The body of the response. It accepts strings and or # regular expressions. Altought you might be running your tests without # integrating your views, this is useful when rendering :xml or :text. # # * :content_type - The content type of the response. # It accepts strings ('application/rss+xml'), mime constants (Mime::RSS), # symbols (:rss) and regular expressions /rss/. # # == Examples # # should_respond_with :success # should_respond_with :error, :body => /System error/ # should_respond_with 301, :content_type => Mime::XML # should_respond_with 300..399, :content_type => Mime::XML # # it { should respond_with(:success) } # it { should respond_with(:error).body(/System error/) } # it { should respond_with(301).content_type(Mime::XML) } # it { should respond_with(300..399).content_type(Mime::XML) } # def respond_with(*args, &block) options = args.extract_options! options.merge!(:with => args.first) RespondWithMatcher.new(options, &block).spec(self) end # This is just a shortcut for respond_with :body => body. Check respond_with # for more information. # def respond_with_body(*args, &block) options = args.extract_options! # Since body can be also given as block, only merge if any arguments was # actually sent. options.merge!(:body => args.first) unless args.empty? RespondWithMatcher.new(options, &block).spec(self) end # This is just a shortcut for respond_with :content_type => content_type. # It's also used for Shoulda compatibility. Check respond_with for more # information. # def respond_with_content_type(*args, &block) options = args.extract_options! options.merge!(:content_type => args.first) RespondWithMatcher.new(options, &block).spec(self) end end end end