diff options
Diffstat (limited to 'vendor/gems/rspec-1.3.1/lib')
119 files changed, 8353 insertions, 0 deletions
diff --git a/vendor/gems/rspec-1.3.1/lib/autotest/discover.rb b/vendor/gems/rspec-1.3.1/lib/autotest/discover.rb new file mode 100644 index 000000000..3ac51c135 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/autotest/discover.rb @@ -0,0 +1,3 @@ +Autotest.add_discovery do + "rspec" if File.directory?('spec') && ENV['RSPEC'] +end diff --git a/vendor/gems/rspec-1.3.1/lib/autotest/rspec.rb b/vendor/gems/rspec-1.3.1/lib/autotest/rspec.rb new file mode 100644 index 000000000..73ffcb374 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/autotest/rspec.rb @@ -0,0 +1,54 @@ +require 'autotest' + +Autotest.add_hook :initialize do |at| + at.clear_mappings + # watch out for Ruby bug (1.8.6): %r(/) != /\// + at.add_mapping(%r%^spec/.*_spec\.rb$%) { |filename, _| + filename + } + at.add_mapping(%r%^lib/(.*)\.rb$%) { |_, m| + ["spec/#{m[1]}_spec.rb"] + } + at.add_mapping(%r%^spec/(spec_helper|shared/.*)\.rb$%) { + at.files_matching %r%^spec/.*_spec\.rb$% + } +end + +class RspecCommandError < StandardError; end + +class Autotest::Rspec < Autotest + + SPEC_PROGRAM = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'bin', 'spec')) + + def initialize + super + self.failed_results_re = /^\d+\)\n(?:\e\[\d*m)?(?:.*?in )?'([^\n]*)'(?: FAILED)?(?:\e\[\d*m)?\n\n?(.*?(\n\n\(.*?)?)\n\n/m + self.completed_re = /\n(?:\e\[\d*m)?\d* examples?/m + end + + def consolidate_failures(failed) + filters = new_hash_of_arrays + failed.each do |spec, trace| + if trace =~ /\n(\.\/)?(.*spec\.rb):[\d]+:/ + filters[$2] << spec + end + end + return filters + end + + def make_test_cmd(files_to_test) + files_to_test.empty? ? '' : + "#{ruby} #{SPEC_PROGRAM} --autospec #{normalize(files_to_test).keys.flatten.join(' ')} #{add_options_if_present}" + end + + def normalize(files_to_test) + files_to_test.keys.inject({}) do |result, filename| + result[File.expand_path(filename)] = [] + result + end + end + + def add_options_if_present # :nodoc: + File.exist?("spec/spec.opts") ? "-O #{File.join('spec','spec.opts')} " : "" + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec.rb b/vendor/gems/rspec-1.3.1/lib/spec.rb new file mode 100644 index 000000000..879c373e8 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec.rb @@ -0,0 +1,8 @@ +require 'spec/deprecation' +require 'spec/ruby' +require 'spec/matchers' +require 'spec/expectations' +require 'spec/example' +require 'spec/runner' +require 'spec/version' +require 'spec/dsl' diff --git a/vendor/gems/rspec-1.3.1/lib/spec/adapters/mock_frameworks/flexmock.rb b/vendor/gems/rspec-1.3.1/lib/spec/adapters/mock_frameworks/flexmock.rb new file mode 100644 index 000000000..18dd453dd --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/adapters/mock_frameworks/flexmock.rb @@ -0,0 +1,24 @@ +#!/usr/bin/env ruby +# +# Created by Jim Weirich on 2007-04-10. +# Copyright (c) 2007. All rights reserved. + +require 'rubygems' unless ENV['NO_RUBYGEMS'] +require 'flexmock/rspec' + +module Spec + module Adapters + module MockFramework + include FlexMock::MockContainer + def setup_mocks_for_rspec + # No setup required + end + def verify_mocks_for_rspec + flexmock_verify + end + def teardown_mocks_for_rspec + flexmock_close + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/adapters/mock_frameworks/mocha.rb b/vendor/gems/rspec-1.3.1/lib/spec/adapters/mock_frameworks/mocha.rb new file mode 100644 index 000000000..4c97c139a --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/adapters/mock_frameworks/mocha.rb @@ -0,0 +1,25 @@ +require 'rubygems' unless ENV['NO_RUBYGEMS'] +require 'mocha/standalone' +require 'mocha/object' + +module Spec + module Adapters + module MockFramework + # Mocha::Standalone was deprecated as of Mocha 0.9.7. + begin + include Mocha::API + rescue NameError + include Mocha::Standalone + end + def setup_mocks_for_rspec + mocha_setup + end + def verify_mocks_for_rspec + mocha_verify + end + def teardown_mocks_for_rspec + mocha_teardown + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/adapters/mock_frameworks/rr.rb b/vendor/gems/rspec-1.3.1/lib/spec/adapters/mock_frameworks/rr.rb new file mode 100644 index 000000000..758ddf611 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/adapters/mock_frameworks/rr.rb @@ -0,0 +1,22 @@ +require 'rubygems' unless ENV['NO_RUBYGEMS'] +require 'rr' + +patterns = ::Spec::Runner::QuietBacktraceTweaker::IGNORE_PATTERNS +patterns.push(RR::Errors::BACKTRACE_IDENTIFIER) + +module Spec + module Adapters + module MockFramework + include RR::Extensions::InstanceMethods + def setup_mocks_for_rspec + RR::Space.instance.reset + end + def verify_mocks_for_rspec + RR::Space.instance.verify_doubles + end + def teardown_mocks_for_rspec + RR::Space.instance.reset + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/adapters/mock_frameworks/rspec.rb b/vendor/gems/rspec-1.3.1/lib/spec/adapters/mock_frameworks/rspec.rb new file mode 100644 index 000000000..b159f8bfe --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/adapters/mock_frameworks/rspec.rb @@ -0,0 +1,21 @@ +require 'spec/mocks/framework' +require 'spec/mocks/extensions' + +module Spec + module Adapters + unless defined?(MockFramework) + module MockFramework + include Spec::Mocks::ExampleMethods + def setup_mocks_for_rspec + $rspec_mocks ||= Spec::Mocks::Space.new + end + def verify_mocks_for_rspec + $rspec_mocks.verify_all + end + def teardown_mocks_for_rspec + $rspec_mocks.reset_all + end + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/autorun.rb b/vendor/gems/rspec-1.3.1/lib/spec/autorun.rb new file mode 100644 index 000000000..f29b81966 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/autorun.rb @@ -0,0 +1,3 @@ +require 'spec' + +Spec::Runner.autorun diff --git a/vendor/gems/rspec-1.3.1/lib/spec/deprecation.rb b/vendor/gems/rspec-1.3.1/lib/spec/deprecation.rb new file mode 100644 index 000000000..3e3140d47 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/deprecation.rb @@ -0,0 +1,41 @@ +module Spec + class << self + def deprecate(method, alternate_method=nil) + return if Spec::Runner.configuration.suppress_deprecation_warnings? + message = <<-NOTICE + +***************************************************************** +DEPRECATION WARNING: you are using deprecated behaviour that will +be removed from a future version of RSpec. + +#{caller(0)[2]} + +* #{method} is deprecated. +NOTICE + if alternate_method + message << <<-ADDITIONAL +* please use #{alternate_method} instead. +ADDITIONAL + end + + message << "*****************************************************************" + warn(message) + end + + def warn(message) + Kernel.warn(message) + end + + end + + class HashWithDeprecationNotice < Hash + def initialize(method, alternate_method=nil, &block) + @method, @alternate_method = method, alternate_method + end + def []=(k,v) + Spec.deprecate(@method, @alternate_method) + super + end + end +end + diff --git a/vendor/gems/rspec-1.3.1/lib/spec/dsl.rb b/vendor/gems/rspec-1.3.1/lib/spec/dsl.rb new file mode 100644 index 000000000..d93e90d84 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/dsl.rb @@ -0,0 +1 @@ +require 'spec/dsl/main' diff --git a/vendor/gems/rspec-1.3.1/lib/spec/dsl/main.rb b/vendor/gems/rspec-1.3.1/lib/spec/dsl/main.rb new file mode 100644 index 000000000..d0c51f70f --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/dsl/main.rb @@ -0,0 +1,93 @@ +module Spec + module DSL + module Main + include Spec::Example::ArgsAndOptions + + # Creates and returns a class that includes the ExampleGroupMethods + # module. Which ExampleGroup type is created depends on the directory of the file + # calling this method. For example, Spec::Rails will use different + # classes for specs living in <tt>spec/models</tt>, + # <tt>spec/helpers</tt>, <tt>spec/views</tt> and + # <tt>spec/controllers</tt>. + # + # It is also possible to override autodiscovery of the example group + # type with an options Hash as the last argument: + # + # describe "name", :type => :something_special do ... + # + # The reason for using different example group classes is to have different + # matcher methods available from within the <tt>describe</tt> block. + # + # See Spec::Example::ExampleGroupFactory#register for details about how to + # register special implementations. + # + def describe(*args, &block) + raise Spec::Example::NoDescriptionError.new("example group", caller(0)[1]) if args.empty? + add_options(args, :scope => self) + set_location(args.options, caller(0)[1]) + Spec::Example::ExampleGroupFactory.create_example_group(*args, &block) + end + alias :context :describe unless defined?(IRB::Context) + + # Creates an example group that can be shared by other example groups + # + # == Examples + # + # share_examples_for "All Editions" do + # it "all editions behaviour" ... + # end + # + # describe SmallEdition do + # it_should_behave_like "All Editions" + # + # it "should do small edition stuff" do + # ... + # end + # end + def share_examples_for(*args, &block) + add_options(args) + set_location(args.options, caller(0)[1]) + Spec::Example::ExampleGroupFactory.create_shared_example_group(*args, &block) + end + alias :shared_examples_for :share_examples_for + + # Creates a Shared Example Group and assigns it to a constant + # + # share_as :AllEditions do + # it "should do all editions stuff" ... + # end + # + # describe SmallEdition do + # it_should_behave_like AllEditions + # + # it "should do small edition stuff" do + # ... + # end + # end + # + # And, for those of you who prefer to use something more like Ruby, you + # can just include the module directly + # + # describe SmallEdition do + # include AllEditions + # + # it "should do small edition stuff" do + # ... + # end + # end + def share_as(name, &block) + Spec.deprecate("share_as","shared_examples_for") + begin + args = [name] + add_options(args) + set_location(args.options, caller(0)[1]) + Object.const_set(name, Spec::Example::ExampleGroupFactory.create_shared_example_group(*args, &block)) + rescue NameError => e + raise NameError.new(e.message + "\nThe first argument to share_as must be a legal name for a constant\n") + end + end + end + end +end + +include Spec::DSL::Main diff --git a/vendor/gems/rspec-1.3.1/lib/spec/example.rb b/vendor/gems/rspec-1.3.1/lib/spec/example.rb new file mode 100644 index 000000000..afbf41286 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/example.rb @@ -0,0 +1,164 @@ +module Spec + # == Example Groups and Code Examples + # + # A Code Example is an executable example of how a bit of code is expected + # to behave. + # + # An Example Group is a group of code examples. + # + # RSpec exposes a DSL to describe groups of examples. + # + # describe Account do + # it "should have a balance of $0" do + # account = Account.new + # account.balance.should == Money.new(0, :dollars) + # end + # end + # + # == Before and After + # + # You can use the <tt>before()</tt> and <tt>after()</tt> methods to extract + # common code within an Example Group. Both methods take an optional scope + # argument so you can run the block before :each example or before :all + # examples + # + # describe "..." do + # before :all do + # ... + # end + # + # before :each do + # ... + # end + # + # it "should do something" do + # ... + # end + # + # it "should do something else" do + # ... + # end + # + # after :each do + # ... + # end + # + # after :all do + # ... + # end + # + # end + # + # The <tt>before :each</tt> block will run before each of the examples, once + # for each example. Likewise, the <tt>after :each</tt> block will run after + # each of the examples. + # + # It is also possible to specify a <tt>before :all</tt> and <tt>after + # :all</tt> block that will run only once for each example group, before the + # first <code>before :each</code> and after the last <code>after + # :each</code> respectively. The use of these is generally discouraged, + # because it introduces dependencies between the examples. Still, it might + # prove useful for very expensive operations if you know what you are doing. + # + # == Local helper methods + # + # You can include local helper methods by simply expressing them within an + # example group: + # + # describe "..." do + # + # it "..." do + # helper_method + # end + # + # def helper_method + # ... + # end + # + # end + # + # == Included helper methods + # + # You can include helper methods in multiple example groups by expressing + # them within a module, and then including that module in your example + # groups: + # + # module AccountExampleHelperMethods + # def helper_method + # ... + # end + # end + # + # describe "A new account" do + # include AccountExampleHelperMethods + # before do + # @account = Account.new + # end + # + # it "should have a balance of $0" do + # helper_method + # @account.balance.should eql(Money.new(0, :dollars)) + # end + # end + # + # == Shared Example Groups + # + # You can define a shared example group, that may be used on other groups + # + # share_examples_for "All Editions" do + # it "all editions behaviour" ... + # end + # + # describe SmallEdition do + # it_should_behave_like "All Editions" + # + # it "should do small edition stuff" do + # ... + # end + # end + # + # You can also assign the shared group to a module and include that + # + # share_as :AllEditions do + # it "should do all editions stuff" ... + # end + # + # describe SmallEdition do + # it_should_behave_like AllEditions + # + # it "should do small edition stuff" do + # ... + # end + # end + # + # And, for those of you who prefer to use something more like Ruby, you can + # just include the module directly + # + # describe SmallEdition do + # include AllEditions + # + # it "should do small edition stuff" do + # ... + # end + # end + module Example + end +end + +require 'timeout' +require 'spec/example/args_and_options' +require 'spec/example/predicate_matchers' +require 'spec/example/example_group_proxy' +require 'spec/example/example_proxy' +require 'spec/example/subject' +require 'spec/example/before_and_after_hooks' +require 'spec/example/pending' +require 'spec/example/module_reopening_fix' +require 'spec/example/example_group_hierarchy' +require 'spec/example/example_group_methods' +require 'spec/example/example_methods' +require 'spec/example/example_group' +require 'spec/example/shared_example_group' +require 'spec/example/example_group_factory' +require 'spec/example/errors' +require 'spec/example/example_matcher' diff --git a/vendor/gems/rspec-1.3.1/lib/spec/example/args_and_options.rb b/vendor/gems/rspec-1.3.1/lib/spec/example/args_and_options.rb new file mode 100644 index 000000000..b74fddd8e --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/example/args_and_options.rb @@ -0,0 +1,27 @@ +module Spec + module Example + module ArgsAndOptions + def args_and_options(*args) # :nodoc: + options = Hash === args.last ? args.pop : {} + return args, options + end + + def add_options(args, options={}) # :nodoc: + args << {} unless Hash === args.last + args.extend WithOptions + args.options.merge!(options) + args.options + end + + def set_location(options, location) # :nodoc: + options[:location] ||= location + end + + module WithOptions # :nodoc: + def options + last + end + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/example/before_and_after_hooks.rb b/vendor/gems/rspec-1.3.1/lib/spec/example/before_and_after_hooks.rb new file mode 100644 index 000000000..9f5039d1e --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/example/before_and_after_hooks.rb @@ -0,0 +1,93 @@ +module Spec + module Example + module BeforeAndAfterHooks + class << self + def before_suite_parts # :nodoc: + @before_suite_parts ||= [] + end + + def after_suite_parts # :nodoc: + @after_suite_parts ||= [] + end + end + + # Registers a block to be executed before examples. <tt>scope</tt> can be + # <tt>:each</tt> (default), <tt>:all</tt>, or <tt>:suite</tt>. When + # <tt>:each</tt>, the block is executed before each example. When + # <tt>:all</tt>, the block is executed only once before any examples are + # run. + def append_before(scope = :each, &block) + before_parts(scope) << block + end + alias_method :before, :append_before + + # Registers a block to be executed before each example. + # This method prepends +block+ to existing before blocks. + # + # See <tt>append_before</tt> for scoping semantics. + def prepend_before(scope = :each, &block) + before_parts(scope).unshift(block) + end + + # Registers a block to be executed after each example. + # This method prepends +block+ to existing after blocks. + # + # See <tt>append_before</tt> for scoping semantics. + def prepend_after(scope = :each, &block) + after_parts(scope).unshift(block) + end + alias_method :after, :prepend_after + + # Registers a block to be executed after each example. + # This method appends +block+ to existing after blocks. + # + # See <tt>append_before</tt> for scoping semantics. + def append_after(scope = :each, &block) + after_parts(scope) << block + end + + def before_each_parts # :nodoc: + @before_each_parts ||= [] + end + + def after_each_parts # :nodoc: + @after_each_parts ||= [] + end + + def before_all_parts # :nodoc: + @before_all_parts ||= [] + end + + def after_all_parts # :nodoc: + @after_all_parts ||= [] + end + + def before_suite_parts # :nodoc: + BeforeAndAfterHooks.before_suite_parts + end + + def after_suite_parts # :nodoc: + BeforeAndAfterHooks.after_suite_parts + end + + private + + def before_parts(scope) + case scope + when :each; before_each_parts + when :all; before_all_parts + when :suite; before_suite_parts + end + end + + def after_parts(scope) + case scope + when :each; after_each_parts + when :all; after_all_parts + when :suite; after_suite_parts + end + end + + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/example/errors.rb b/vendor/gems/rspec-1.3.1/lib/spec/example/errors.rb new file mode 100644 index 000000000..157b669b0 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/example/errors.rb @@ -0,0 +1,25 @@ +module Spec + module Example + class ExamplePendingError < StandardError; end + + class NotYetImplementedError < ExamplePendingError + MESSAGE = "Not Yet Implemented" + def initialize + super(MESSAGE) + end + end + + class PendingExampleFixedError < StandardError; end + + class NoDescriptionError < ArgumentError + class << self + def message(kind, location) + "No description supplied for #{kind} declared on #{location}" + end + end + def initialize(kind, location) + super(self.class.message(kind, location)) + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/example/example_group.rb b/vendor/gems/rspec-1.3.1/lib/spec/example/example_group.rb new file mode 100644 index 000000000..983be9a24 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/example/example_group.rb @@ -0,0 +1,10 @@ +module Spec + module Example + # Base class for customized example groups. Use this if you + # want to make a custom example group. + class ExampleGroup + extend Spec::Example::ExampleGroupMethods + include Spec::Example::ExampleMethods + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/example/example_group_factory.rb b/vendor/gems/rspec-1.3.1/lib/spec/example/example_group_factory.rb new file mode 100644 index 000000000..1d662782a --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/example/example_group_factory.rb @@ -0,0 +1,82 @@ +module Spec + module Example + + class ExampleGroupFactory + module ClassMethods + include Spec::Example::ArgsAndOptions + + def reset + @example_group_types = nil + default(ExampleGroup) + end + + def example_group_creation_listeners + @example_group_creation_listeners ||= [] + end + + def register_example_group(klass) + example_group_creation_listeners.each do |listener| + listener.register_example_group(klass) + end + end + + def create_shared_example_group(*args, &example_group_block) # :nodoc: + ::Spec::Example::SharedExampleGroup.register(*args, &example_group_block) + end + + def create_example_group(*args, &block) + raise ArgumentError if args.empty? || block.nil? + add_options(args) + superclass = determine_superclass(args.last) + superclass.describe(*args, &block) + end + + # Registers an example group class +klass+ with the symbol +type+. For + # example: + # + # Spec::Example::ExampleGroupFactory.register(:farm, FarmExampleGroup) + # + # With that you can append a hash with :type => :farm to the describe + # method and it will load an instance of FarmExampleGroup. + # + # describe Pig, :type => :farm do + # ... + # + # If you don't use the hash explicitly, <tt>describe</tt> will + # implicitly use an instance of FarmExampleGroup for any file loaded + # from the <tt>./spec/farm</tt> directory. + def register(key, example_group_class) + @example_group_types[key.to_sym] = example_group_class + end + + # Sets the default ExampleGroup class + def default(example_group_class) + Spec.__send__ :remove_const, :ExampleGroup if Spec.const_defined?(:ExampleGroup) + Spec.const_set(:ExampleGroup, example_group_class) + old = @example_group_types + @example_group_types = Hash.new(example_group_class) + @example_group_types.merge!(old) if old + end + + def [](key) + @example_group_types[key] + end + + protected + + def determine_superclass(opts) + if type = opts[:type] + self[type] + elsif opts[:location] =~ /spec(\\|\/)(#{@example_group_types.keys.sort_by{|k| k.to_s.length}.reverse.join('|')})/ + self[$2 == '' ? nil : $2.to_sym] + else + self[nil] + end + end + + end + extend ClassMethods + self.reset + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/example/example_group_hierarchy.rb b/vendor/gems/rspec-1.3.1/lib/spec/example/example_group_hierarchy.rb new file mode 100644 index 000000000..f2c9fb5cd --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/example/example_group_hierarchy.rb @@ -0,0 +1,53 @@ +module Spec + module Example + class ExampleGroupHierarchy < Array + def initialize(example_group_class) + push example_group_class + if example_group_class.respond_to?(:superclass) && example_group_class.superclass.respond_to?(:example_group_hierarchy) + unshift example_group_class.superclass.example_group_hierarchy + flatten! + end + end + + def run_before_all(example) + example.eval_each_fail_fast(before_all_parts) + end + + def run_before_each(example) + example.eval_each_fail_fast(before_each_parts) + end + + def run_after_each(example) + example.eval_each_fail_slow(after_each_parts) + end + + def run_after_all(example) + example.eval_each_fail_slow(after_all_parts) + end + + def before_all_parts + @before_all_parts ||= collect {|klass| klass.before_all_parts}.flatten + end + + def before_each_parts + @before_each_parts ||= collect {|klass| klass.before_each_parts}.flatten + end + + def after_each_parts + @after_each_parts ||= reverse.collect {|klass| klass.after_each_parts}.flatten + end + + def after_all_parts + @after_all_parts ||= reverse.collect {|klass| klass.after_all_parts}.flatten + end + + def nested_descriptions + @nested_descriptions ||= collect {|eg| nested_description_from(eg) == "" ? nil : nested_description_from(eg) }.compact + end + + def nested_description_from(example_group) + example_group.description_args.join + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/example/example_group_methods.rb b/vendor/gems/rspec-1.3.1/lib/spec/example/example_group_methods.rb new file mode 100644 index 000000000..93f459587 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/example/example_group_methods.rb @@ -0,0 +1,287 @@ +module Spec + module Example + + module ExampleGroupMethods + class << self + attr_accessor :matcher_class + + def build_description_from(*args) + text = args.inject("") do |description, arg| + description << " " unless (description == "" || arg.to_s =~ /^(\s|\.|#)/) + description << arg.to_s + end + text == "" ? nil : text + end + end + + include Spec::Example::BeforeAndAfterHooks + include Spec::Example::Subject::ExampleGroupMethods + include Spec::Example::PredicateMatchers + include Spec::Example::ArgsAndOptions + + attr_reader :location + + def options # :nodoc: + @options ||= {} + end + + def inherited(klass) # :nodoc: + super + ExampleGroupFactory.register_example_group(klass) + end + + # Makes the describe/it syntax available from a class. For example: + # + # class StackSpec < Spec::ExampleGroup + # describe Stack, "with no elements" + # + # before + # @stack = Stack.new + # end + # + # it "should raise on pop" do + # lambda{ @stack.pop }.should raise_error + # end + # end + # + def describe(*args, &example_group_block) + raise Spec::Example::NoDescriptionError.new("example group", caller(0)[1]) if args.empty? + if example_group_block + options = add_options(args) + set_location(options, caller(0)[1]) + if options[:shared] + ExampleGroupFactory.create_shared_example_group(*args, &example_group_block) + else + subclass(*args, &example_group_block) + end + else + set_description(*args) + end + end + alias :context :describe + + # Use this to pull in examples from shared example groups. + def it_should_behave_like(*shared_example_groups) + shared_example_groups.each do |group| + include_shared_example_group(group) + end + end + + # Creates an instance of the current example group class and adds it to + # a collection of examples of the current example group. + def example(description=nil, options={}, backtrace=nil, &implementation) + example_proxy = ExampleProxy.new(description, options, backtrace || caller(0)[1]) + example_proxies << example_proxy + example_implementations[example_proxy] = implementation || pending_implementation + example_proxy + end + + def pending_implementation + lambda {|*args| raise(Spec::Example::NotYetImplementedError) } + end + + alias_method :it, :example + alias_method :specify, :example + + # Use this to temporarily disable an example. + def xexample(description=nil, opts={}, &block) + Kernel.warn("Example disabled: #{description}") + end + + alias_method :xit, :xexample + alias_method :xspecify, :xexample + + def run(run_options) + examples = examples_to_run(run_options) + notify(run_options.reporter) unless examples.empty? + return true if examples.empty? + return dry_run(examples, run_options) if run_options.dry_run? + + define_methods_from_predicate_matchers + + success, before_all_instance_variables = run_before_all(run_options) + success, after_all_instance_variables = run_examples(success, before_all_instance_variables, examples, run_options) + success = run_after_all(success, after_all_instance_variables, run_options) + end + + def set_description(*args) + @description_args, @options = args_and_options(*args) + @backtrace = caller(1) + @location = File.expand_path(options[:location]) if options[:location] + self + end + + def notify(reporter) # :nodoc: + reporter.example_group_started(ExampleGroupProxy.new(self)) + end + + def description + @description ||= ExampleGroupMethods.build_description_from(*description_parts) || to_s + end + + def described_type + @described_type ||= description_parts.reverse.find {|part| part.is_a?(Module)} + end + + def described_class + @described_class ||= Class === described_type ? described_type : nil + end + + def description_args + @description_args ||= [] + end + + def description_parts #:nodoc: + @description_parts ||= example_group_hierarchy.inject([]) do |parts, example_group_class| + [parts << example_group_class.description_args].flatten + end + end + + def example_proxies # :nodoc: + @example_proxies ||= [] + end + + def example_implementations # :nodoc: + @example_implementations ||= {} + end + + def examples(run_options=nil) #:nodoc: + (run_options && run_options.reverse) ? example_proxies.reverse : example_proxies + end + + def number_of_examples #:nodoc: + example_proxies.length + end + + def example_group_hierarchy + @example_group_hierarchy ||= ExampleGroupHierarchy.new(self) + end + + def nested_descriptions + example_group_hierarchy.nested_descriptions + end + + def include_constants_in(mod) + include mod if (Spec::Ruby.version.to_f >= 1.9) & (Module === mod) & !(Class === mod) + end + + def let(name, &block) + define_method name do + @assignments ||= {} + @assignments[name] ||= instance_eval(&block) + end + end + + def let!(name, &block) + let(name, &block) + before { __send__(name) } + end + + private + + def subclass(*args, &example_group_block) + @class_count ||= 0 + @class_count += 1 + klass = const_set("Subclass_#{@class_count}", Class.new(self)) + klass.set_description(*args) + klass.include_constants_in(args.last[:scope]) + klass.module_eval(&example_group_block) + klass + end + + def dry_run(examples, run_options) + examples.each do |example| + run_options.reporter.example_started(example) + run_options.reporter.example_finished(example) + end + end + + def run_before_all(run_options) + return [true,{}] if example_group_hierarchy.before_all_parts.empty? + example_proxy = ExampleProxy.new("before(:all)") + before_all = new(example_proxy) + begin + example_group_hierarchy.run_before_all(before_all) + return [true, before_all.instance_variable_hash] + rescue Exception => e + run_options.reporter.example_failed(example_proxy, e) + return [false, before_all.instance_variable_hash] + end + end + + def run_examples(success, instance_variables, examples, run_options) + return [success, instance_variables] unless success + + after_all_instance_variables = instance_variables + + examples.each do |example| + example_group_instance = new(example, &example_implementations[example]) + success &= example_group_instance.execute(run_options, instance_variables) + after_all_instance_variables = example_group_instance.instance_variable_hash + end + + return [success, after_all_instance_variables] + end + + def run_after_all(success, instance_variables, run_options) + return success if example_group_hierarchy.after_all_parts.empty? + example_proxy = ExampleProxy.new("after(:all)") + after_all = new(example_proxy) + after_all.set_instance_variables_from_hash(instance_variables) + example_group_hierarchy.run_after_all(after_all) + success + rescue Exception => e + run_options.reporter.example_failed(example_proxy, e) + false + end + + def examples_to_run(run_options) + return example_proxies unless examples_were_specified?(run_options) + if run_options.line_number_requested? + if location =~ /:#{run_options.example_line}:?/ + example_proxies + else + example_proxies.select {|proxy| proxy.location =~ /:#{run_options.example_line}:?/} + end + else + example_proxies.reject do |proxy| + matcher = ExampleGroupMethods.matcher_class. + new(description.to_s, proxy.description) + !matcher.matches?(run_options.examples) + end + end + end + + def examples_were_specified?(run_options) + !run_options.examples.empty? + end + + def method_added(name) # :nodoc: + example(name.to_s, {}, caller(0)[1]) {__send__ name.to_s} if example_method?(name.to_s) + end + + def example_method?(method_name) + should_method?(method_name) + end + + def should_method?(method_name) + !(method_name =~ /^should(_not)?$/) && + method_name =~ /^should/ && + instance_method(method_name).arity < 1 + end + + def include_shared_example_group(shared_example_group) + case shared_example_group + when SharedExampleGroup + include shared_example_group + else + unless example_group = SharedExampleGroup.find(shared_example_group) + raise RuntimeError.new("Shared Example Group '#{shared_example_group}' can not be found") + end + include(example_group) + end + end + end + + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/example/example_group_proxy.rb b/vendor/gems/rspec-1.3.1/lib/spec/example/example_group_proxy.rb new file mode 100644 index 000000000..3c258d61f --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/example/example_group_proxy.rb @@ -0,0 +1,61 @@ +module Spec + module Example + # Lightweight proxy for an example group. This is the object that is passed + # to Spec::Runner::Formatter::BaseFormatter#example_group_started + class ExampleGroupProxy + + def initialize(example_group) # :nodoc: + @description = example_group.description + @nested_descriptions = example_group.nested_descriptions + @examples = example_group.example_proxies + @location = example_group.location + @backtrace = example_group.location # deprecated - see the backtrace method below + @options = example_group.options.dup + @options.delete(:location) + @options.delete(:scope) + end + + # Optional hash passed to the example group declaration. Note that RSpec uses + # this hash internally and reserves the keys :location and :scope for its own + # use (and removes them from this hash) + attr_reader :options + + # This is the description passed to the <tt>describe()</tt> method or any + # of its aliases + attr_reader :description + + # Used by Spec::Runner::Formatter::NestedTextFormatter to access the + # description of each example group in a nested group separately. + attr_reader :nested_descriptions + + # A collection of ExampleGroupProxy objects, one for each example + # declared in this group. + attr_reader :examples + + # The file and line number at which the proxied example group + # was declared. This is extracted from <tt>caller</tt>, and is therefore + # formatted as an individual line in a backtrace. + attr_reader :location + + # Deprecated - use location() instead + def backtrace + Spec::deprecate("ExampleGroupProxy#backtrace","ExampleGroupProxy#location") + @backtrace + end + + # Deprecated - just use gsub on the description instead. + def filtered_description(regexp) + Spec::deprecate("ExampleGroupProxy#filtered_description","gsub (or similar) to modify ExampleGroupProxy#description") + ExampleGroupMethods.build_description_from( + *nested_descriptions.collect do |description| + description =~ regexp ? description.gsub($1, "") : description + end + ) + end + + def ==(other) # :nodoc: + other.description == description + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/example/example_matcher.rb b/vendor/gems/rspec-1.3.1/lib/spec/example/example_matcher.rb new file mode 100644 index 000000000..3acd7e14a --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/example/example_matcher.rb @@ -0,0 +1,43 @@ +module Spec + module Example + class ExampleMatcher + def initialize(example_group_description, example_name) + @example_group_description = example_group_description + @example_name = example_name + end + + def matches?(specified_examples) + specified_examples.any? do |specified_example| + matches_literal_example?(specified_example) || matches_example_not_considering_modules?(specified_example) + end + end + + protected + def matches_literal_example?(specified_example) + specified_example =~ /(^#{example_group_regex} #{example_regexp}$|^#{example_group_regex}$|^#{example_group_with_before_all_regexp}$|^#{example_regexp}$)/ + end + + def matches_example_not_considering_modules?(specified_example) + specified_example =~ /(^#{example_group_regex_not_considering_modules} #{example_regexp}$|^#{example_group_regex_not_considering_modules}$|^#{example_regexp}$)/ + end + + def example_group_regex + Regexp.escape(@example_group_description) + end + + def example_group_with_before_all_regexp + Regexp.escape("#{@example_group_description} before(:all)") + end + + def example_group_regex_not_considering_modules + Regexp.escape(@example_group_description.split('::').last) + end + + def example_regexp + Regexp.escape(@example_name) if @example_name + end + end + + ExampleGroupMethods.matcher_class = ExampleMatcher + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/example/example_methods.rb b/vendor/gems/rspec-1.3.1/lib/spec/example/example_methods.rb new file mode 100644 index 000000000..10f45a722 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/example/example_methods.rb @@ -0,0 +1,152 @@ +module Spec + module Example + module ExampleMethods + + extend Spec::Example::ModuleReopeningFix + include Spec::Example::Subject::ExampleMethods + + def violated(message="") + raise Spec::Expectations::ExpectationNotMetError.new(message) + end + + # Declared description for this example: + # + # describe Account do + # it "should start with a balance of 0" do + # ... + # + # description + # => "should start with a balance of 0" + def description + if description = @_proxy.description || ::Spec::Matchers.generated_description + description + else + Spec.warn Spec::Example::NoDescriptionError.message("example", @_proxy.location) + end + end + + def options # :nodoc: + @_proxy.options + end + + def execute(run_options, instance_variables) # :nodoc: + run_options.reporter.example_started(@_proxy) + set_instance_variables_from_hash(instance_variables) + + execution_error = nil + Timeout.timeout(run_options.timeout) do + begin + before_each_example + instance_eval(&@_implementation) + rescue Interrupt + exit 1 + rescue Exception => e + execution_error ||= e + end + begin + after_each_example + rescue Interrupt + exit 1 + rescue Exception => e + execution_error ||= e + end + end + + run_options.reporter.example_finished(@_proxy.update(description), execution_error) + success = execution_error.nil? || ExamplePendingError === execution_error + end + + module BlockAliases + alias_method :to, :should + alias_method :to_not, :should_not + end + + # Extends the submitted block with aliases to and to_not + # for should and should_not. Allows expectations like this: + # + # expect { this_block }.to change{this.expression}.from(old_value).to(new_value) + # expect { this_block }.to raise_error + def expect(&block) + block.extend BlockAliases + end + + def eval_each_fail_fast(blocks) # :nodoc: + blocks.each {|block| instance_eval(&block)} + end + + def eval_each_fail_slow(blocks) # :nodoc: + first_exception = nil + blocks.each do |block| + begin + instance_eval(&block) + rescue Exception => e + first_exception ||= e + end + end + raise first_exception if first_exception + end + + def instance_variable_hash # :nodoc: + instance_variables.inject({}) do |variable_hash, variable_name| + variable_hash[variable_name] = instance_variable_get(variable_name) + variable_hash + end + end + + def set_instance_variables_from_hash(ivars) # :nodoc: + ivars.each do |variable_name, value| + # Ruby 1.9 requires variable.to_s on the next line + unless ['@_proxy', '@_implementation', '@method_name'].include?(variable_name.to_s) + instance_variable_set variable_name, value + end + end + end + + # Run all the before(:each) blocks for this example + def run_before_each + example_group_hierarchy.run_before_each(self) + end + + # Run all the after(:each) blocks for this example + def run_after_each + example_group_hierarchy.run_after_each(self) + end + + def initialize(example_proxy, &implementation) + @_proxy = example_proxy + @_implementation = implementation + @_backtrace = caller + end + + private + + include Matchers + include Pending + + def before_each_example + setup_mocks_for_rspec + run_before_each + end + + def after_each_example + run_after_each + verify_mocks_for_rspec + ensure + teardown_mocks_for_rspec + end + + def described_class + self.class.described_class + end + + def description_args + self.class.description_args + end + + def example_group_hierarchy + self.class.example_group_hierarchy + end + + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/example/example_proxy.rb b/vendor/gems/rspec-1.3.1/lib/spec/example/example_proxy.rb new file mode 100644 index 000000000..f726d0e70 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/example/example_proxy.rb @@ -0,0 +1,41 @@ +module Spec + module Example + # Lightweight proxy for an example. This is the object that is passed to + # example-related methods in Spec::Runner::Formatter::BaseFormatter + class ExampleProxy + + def initialize(description=nil, options={}, location=nil) # :nodoc: + @description, @options, @location = description, options, location + end + + # Optional hash passed to the example declaration + attr_reader :options + + # This is the docstring passed to the <tt>it()</tt> method or any + # of its aliases + attr_reader :description + + # The file and line number at which the represented example + # was declared. This is extracted from <tt>caller</tt>, and is therefore + # formatted as an individual line in a backtrace. + attr_reader :location + + # Deprecated - use location() + def backtrace + Spec.deprecate("ExampleProxy#backtrace","ExampleProxy#location") + location + end + + # Convenience method for example group - updates the value of + # <tt>description</tt> and returns self. + def update(description) # :nodoc: + @description = description + self + end + + def ==(other) # :nodoc: + (other.description == description) & (other.location == location) + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/example/module_reopening_fix.rb b/vendor/gems/rspec-1.3.1/lib/spec/example/module_reopening_fix.rb new file mode 100644 index 000000000..9ea088a2e --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/example/module_reopening_fix.rb @@ -0,0 +1,43 @@ +module Spec + module Example + # When you reopen a module that is included in another module that is included in a class, + # the new material you define does not make it to the class. This fixes that. + # + # == Example + # + # module M1; end + # + # module M2 + # def foo; "FOO"; end + # end + # + # class C + # include M1 + # end + # + # module M1 + # include M2 + # end + # + # c = C.new + # c.foo + # NoMethodError: undefined method `foo' for #<C:0x5e89a4> + # from (irb):12 + module ModuleReopeningFix + def child_modules + @child_modules ||= [] + end + + def included(mod) + child_modules << mod + end + + def include(mod) + super + child_modules.each do |child_module| + child_module.__send__(:include, mod) + end + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/example/pending.rb b/vendor/gems/rspec-1.3.1/lib/spec/example/pending.rb new file mode 100644 index 000000000..9aad1aab0 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/example/pending.rb @@ -0,0 +1,18 @@ +module Spec + module Example + module Pending + def pending(message = "TODO") + if block_given? + begin + yield + rescue Exception + raise Spec::Example::ExamplePendingError.new(message) + end + raise Spec::Example::PendingExampleFixedError.new("Expected pending '#{message}' to fail. No Error was raised.") + else + raise Spec::Example::ExamplePendingError.new(message) + end + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/example/predicate_matchers.rb b/vendor/gems/rspec-1.3.1/lib/spec/example/predicate_matchers.rb new file mode 100644 index 000000000..c3c319519 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/example/predicate_matchers.rb @@ -0,0 +1,46 @@ +module Spec + module Example + module PredicateMatchers + # :call-seq: + # predicate_matchers[matcher_name] = method_on_object + # predicate_matchers[matcher_name] = [method1_on_object, method2_on_object] + # + # Dynamically generates a custom matcher that will match + # a predicate on your class. RSpec provides a couple of these + # out of the box: + # + # exist (for state expectations) + # File.should exist("path/to/file") + # + # an_instance_of (for mock argument matchers) + # mock.should_receive(:message).with(an_instance_of(String)) + # + # == Examples + # + # class Fish + # def can_swim? + # true + # end + # end + # + # describe Fish do + # predicate_matchers[:swim] = :can_swim? + # it "should swim" do + # Fish.new.should swim + # end + # end + def predicate_matchers + @predicate_matchers ||= Spec::HashWithDeprecationNotice.new("predicate_matchers", "the new Matcher DSL") + end + + def define_methods_from_predicate_matchers # :nodoc: + predicate_matchers.each_pair do |matcher_method, method_on_object| + define_method matcher_method do |*args| + eval("be_#{method_on_object.to_s.gsub('?','')}(*args)") + end + end + end + + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/example/shared_example_group.rb b/vendor/gems/rspec-1.3.1/lib/spec/example/shared_example_group.rb new file mode 100644 index 000000000..336944914 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/example/shared_example_group.rb @@ -0,0 +1,59 @@ +module Spec + module Example + class SharedExampleGroup < Module + module ClassMethods + def register(*args, &block) + new_example_group = new(*args, &block) + shared_example_groups << new_example_group unless already_registered?(new_example_group) + new_example_group + end + + def find(example_group_description) + shared_example_groups.find {|b| b.description == example_group_description} + end + + def clear + shared_example_groups.clear + end + + def include?(group) + shared_example_groups.include?(group) + end + + def count + shared_example_groups.length + end + + private + + def shared_example_groups + @shared_example_groups ||= [] + end + + def already_registered?(new_example_group) + existing_example_group = find(new_example_group.description) + return false unless existing_example_group + return true if new_example_group.equal?(existing_example_group) + return true if expanded_path(new_example_group) == expanded_path(existing_example_group) + raise ArgumentError.new("Shared Example '#{existing_example_group.description}' already exists") + end + + def expanded_path(example_group) + File.expand_path(example_group.location) + end + end + + extend ClassMethods + include ExampleGroupMethods + + def initialize(*args, &example_group_block) + set_description(*args) + @example_group_block = example_group_block + end + + def included(mod) # :nodoc: + mod.module_eval(&@example_group_block) + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/example/subject.rb b/vendor/gems/rspec-1.3.1/lib/spec/example/subject.rb new file mode 100644 index 000000000..4f53f543a --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/example/subject.rb @@ -0,0 +1,114 @@ +module Spec + module Example + module Subject + module ExampleGroupMethods + # Defines an explicit subject for an example group which can then be the + # implicit receiver (through delegation) of calls to +should+. + # + # == Examples + # + # describe CheckingAccount, "with $50" do + # subject { CheckingAccount.new(:amount => 50, :currency => :USD) } + # it { should have_a_balance_of(50, :USD) } + # it { should_not be_overdrawn } + # its(:currency) { should == :USD } + # end + # + # See +ExampleMethods#should+ for more information about this approach. + def subject(&block) + block.nil? ? + explicit_subject || implicit_subject : @explicit_subject_block = block + end + + def its(attribute, &block) + describe(attribute) do + example do + self.class.class_eval do + define_method(:subject) do + super().send(attribute) + end + end + instance_eval(&block) + end + end + end + + attr_reader :explicit_subject_block # :nodoc: + + private + + def explicit_subject + group = self + while group.respond_to?(:explicit_subject_block) + return group.explicit_subject_block if group.explicit_subject_block + group = group.superclass + end + end + + def implicit_subject + (described_class ? proc {described_class.new} : proc {description_args.first}) + end + end + + module ExampleMethods + + alias_method :__should_for_example_group__, :should + alias_method :__should_not_for_example_group__, :should_not + + # Returns the subject defined in ExampleGroupMethods#subject. The + # subject block is only executed once per example, the result of which + # is cached and returned by any subsequent calls to +subject+. + # + # If a class is passed to +describe+ and no subject is explicitly + # declared in the example group, then +subject+ will return a new + # instance of that class. + # + # == Examples + # + # # explicit subject defined by the subject method + # describe Person do + # subject { Person.new(:birthdate => 19.years.ago) } + # it "should be eligible to vote" do + # subject.should be_eligible_to_vote + # end + # end + # + # # implicit subject => { Person.new } + # describe Person do + # it "should be eligible to vote" do + # subject.should be_eligible_to_vote + # end + # end + def subject + @subject ||= instance_eval(&self.class.subject) + end + + # When +should+ is called with no explicit receiver, the call is + # delegated to the object returned by +subject+. Combined with + # an implicit subject (see +subject+), this supports very concise + # expressions. + # + # == Examples + # + # describe Person do + # it { should be_eligible_to_vote } + # end + def should(matcher=nil, message=nil) + self == subject ? self.__should_for_example_group__(matcher) : subject.should(matcher,message) + end + + # Just like +should+, +should_not+ delegates to the subject (implicit or + # explicit) of the example group. + # + # == Examples + # + # describe Person do + # it { should_not be_eligible_to_vote } + # end + def should_not(matcher=nil, message=nil) + self == subject ? self.__should_not_for_example_group__(matcher) : subject.should_not(matcher,message) + end + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/expectations.rb b/vendor/gems/rspec-1.3.1/lib/spec/expectations.rb new file mode 100644 index 000000000..13cf59b26 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/expectations.rb @@ -0,0 +1,35 @@ +require 'spec/matchers' +require 'spec/expectations/fail_with' +require 'spec/expectations/errors' +require 'spec/expectations/extensions' +require 'spec/expectations/handler' + +module Spec + + # Spec::Expectations lets you set expectations on your objects. + # + # result.should == 37 + # team.should have(11).players_on_the_field + # + # == How Expectations work. + # + # Spec::Expectations adds two methods to Object: + # + # should(matcher=nil) + # should_not(matcher=nil) + # + # Both methods take an optional Expression Matcher (See Spec::Matchers). + # + # When +should+ receives an Expression Matcher, it calls <tt>matches?(self)</tt>. If + # it returns +true+, the spec passes and execution continues. If it returns + # +false+, then the spec fails with the message returned by <tt>matcher.failure_message</tt>. + # + # Similarly, when +should_not+ receives a matcher, it calls <tt>matches?(self)</tt>. If + # it returns +false+, the spec passes and execution continues. If it returns + # +true+, then the spec fails with the message returned by <tt>matcher.negative_failure_message</tt>. + # + # RSpec ships with a standard set of useful matchers, and writing your own + # matchers is quite simple. See Spec::Matchers for details. + module Expectations + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/expectations/errors.rb b/vendor/gems/rspec-1.3.1/lib/spec/expectations/errors.rb new file mode 100644 index 000000000..1fabd105d --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/expectations/errors.rb @@ -0,0 +1,12 @@ +module Spec + module Expectations + # If Test::Unit is loaed, we'll use its error as baseclass, so that Test::Unit + # will report unmet RSpec expectations as failures rather than errors. + superclass = ['Test::Unit::AssertionFailedError', '::StandardError'].map do |c| + eval(c) rescue nil + end.compact.first + + class ExpectationNotMetError < superclass + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/expectations/extensions.rb b/vendor/gems/rspec-1.3.1/lib/spec/expectations/extensions.rb new file mode 100644 index 000000000..d68212e42 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/expectations/extensions.rb @@ -0,0 +1 @@ +require 'spec/expectations/extensions/kernel' diff --git a/vendor/gems/rspec-1.3.1/lib/spec/expectations/extensions/kernel.rb b/vendor/gems/rspec-1.3.1/lib/spec/expectations/extensions/kernel.rb new file mode 100644 index 000000000..7d8849226 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/expectations/extensions/kernel.rb @@ -0,0 +1,52 @@ +module Kernel + # :call-seq: + # should(matcher) + # should == expected + # should === expected + # should =~ expected + # + # receiver.should(matcher) + # => Passes if matcher.matches?(receiver) + # + # receiver.should == expected #any value + # => Passes if (receiver == expected) + # + # receiver.should === expected #any value + # => Passes if (receiver === expected) + # + # receiver.should =~ regexp + # => Passes if (receiver =~ regexp) + # + # See Spec::Matchers for more information about matchers + # + # == Warning + # + # NOTE that this does NOT support receiver.should != expected. + # Instead, use receiver.should_not == expected + def should(matcher=nil, message=nil, &block) + Spec::Expectations::PositiveExpectationHandler.handle_matcher(self, matcher, message, &block) + end + + # :call-seq: + # should_not(matcher) + # should_not == expected + # should_not === expected + # should_not =~ expected + # + # receiver.should_not(matcher) + # => Passes unless matcher.matches?(receiver) + # + # receiver.should_not == expected + # => Passes unless (receiver == expected) + # + # receiver.should_not === expected + # => Passes unless (receiver === expected) + # + # receiver.should_not =~ regexp + # => Passes unless (receiver =~ regexp) + # + # See Spec::Matchers for more information about matchers + def should_not(matcher=nil, message=nil, &block) + Spec::Expectations::NegativeExpectationHandler.handle_matcher(self, matcher, message, &block) + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/expectations/fail_with.rb b/vendor/gems/rspec-1.3.1/lib/spec/expectations/fail_with.rb new file mode 100644 index 000000000..5e01f99df --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/expectations/fail_with.rb @@ -0,0 +1,45 @@ +module Spec + module Expectations + class << self + attr_accessor :differ + + # raises a Spec::Expectations::ExpectationNotMetError with message + # + # When a differ has been assigned and fail_with is passed + # <code>expected</code> and <code>target</code>, passes them + # to the differ to append a diff message to the failure message. + def fail_with(message, expected=nil, target=nil) # :nodoc: + if message.nil? + raise ArgumentError, "Failure message is nil. Does your matcher define the " + + "appropriate failure_message_for_* method to return a string?" + end + if (Array === message) & (message.length == 3) + ::Spec.warn(<<-NOTICE + +***************************************************************** +DEPRECATION WARNING: you are using deprecated behaviour that will +be removed from a future version of RSpec. + +* Support for matchers that return arrays from failure message +methods is deprecated. +* Instead, the matcher should return a string, and expose methods +for the expected() and actual() values. +***************************************************************** +NOTICE + ) + message, expected, target = message[0], message[1], message[2] + end + unless (differ.nil? || expected.nil? || target.nil?) + if expected.is_a?(String) + message << "\n\n Diff:" << self.differ.diff_as_string(target.to_s, expected) + elsif expected.is_a?(Hash) && target.is_a?(Hash) + message << "\n\n Diff:" << self.differ.diff_as_hash(target, expected) + elsif !target.is_a?(Proc) + message << "\n\n Diff:" << self.differ.diff_as_object(target, expected) + end + end + Kernel::raise(Spec::Expectations::ExpectationNotMetError.new(message)) + end + end + end +end
\ No newline at end of file diff --git a/vendor/gems/rspec-1.3.1/lib/spec/expectations/handler.rb b/vendor/gems/rspec-1.3.1/lib/spec/expectations/handler.rb new file mode 100644 index 000000000..c059637c7 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/expectations/handler.rb @@ -0,0 +1,50 @@ +module Spec + module Expectations + class InvalidMatcherError < ArgumentError; end + + class PositiveExpectationHandler + def self.handle_matcher(actual, matcher, message=nil, &block) + ::Spec::Matchers.last_should = :should + ::Spec::Matchers.last_matcher = matcher + return ::Spec::Matchers::PositiveOperatorMatcher.new(actual) if matcher.nil? + + match = matcher.matches?(actual, &block) + return match if match + + message ||= matcher.respond_to?(:failure_message_for_should) ? + matcher.failure_message_for_should : + matcher.failure_message + + if matcher.respond_to?(:diffable?) && matcher.diffable? + ::Spec::Expectations.fail_with message, matcher.expected.first, matcher.actual + else + ::Spec::Expectations.fail_with message + end + end + end + + class NegativeExpectationHandler + def self.handle_matcher(actual, matcher, message=nil, &block) + ::Spec::Matchers.last_should = :should_not + ::Spec::Matchers.last_matcher = matcher + return ::Spec::Matchers::NegativeOperatorMatcher.new(actual) if matcher.nil? + + match = matcher.respond_to?(:does_not_match?) ? + !matcher.does_not_match?(actual, &block) : + matcher.matches?(actual, &block) + return match unless match + + message ||= matcher.respond_to?(:failure_message_for_should_not) ? + matcher.failure_message_for_should_not : + matcher.negative_failure_message + + if matcher.respond_to?(:diffable?) && matcher.diffable? + ::Spec::Expectations.fail_with message, matcher.expected.first, matcher.actual + else + ::Spec::Expectations.fail_with message + end + end + end + end +end + diff --git a/vendor/gems/rspec-1.3.1/lib/spec/extensions/instance_exec.rb b/vendor/gems/rspec-1.3.1/lib/spec/extensions/instance_exec.rb new file mode 100644 index 000000000..ca7e14ead --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/extensions/instance_exec.rb @@ -0,0 +1,31 @@ +module Spec + module Matchers + module InstanceExec + unless respond_to?(:instance_exec) + # based on Bounded Spec InstanceExec (Mauricio Fernandez) + # http://eigenclass.org/hiki/bounded+space+instance_exec + # - uses singleton_class of matcher instead of global + # InstanceExecHelper module + # - this keeps it scoped to this class only, which is the + # only place we need it + # - only necessary for ruby 1.8.6 + def instance_exec(*args, &block) + singleton_class = (class << self; self; end) + begin + orig_critical, Thread.critical = Thread.critical, true + n = 0 + n += 1 while respond_to?(method_name="__instance_exec#{n}") + singleton_class.module_eval{ define_method(:__instance_exec, &block) } + ensure + Thread.critical = orig_critical + end + begin + return send(:__instance_exec, *args) + ensure + singleton_class.module_eval{ remove_method(:__instance_exec) } rescue nil + end + end + end + end + end +end
\ No newline at end of file diff --git a/vendor/gems/rspec-1.3.1/lib/spec/interop/test.rb b/vendor/gems/rspec-1.3.1/lib/spec/interop/test.rb new file mode 100644 index 000000000..156ab8f87 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/interop/test.rb @@ -0,0 +1,44 @@ +require 'spec' + +if Spec::Ruby.version.to_f >= 1.9 + gem 'test-unit','= 1.2.3' +end + +require 'test/unit' + +if Spec::Ruby.version.to_f >= 1.9 + require 'test/unit/version' + if Test::Unit::VERSION > '1.2.3' + raise <<-MESSAGE +#{'*' * 50} +Required: test-unit-1.2.3 +Loaded: test-unit-#{Test::Unit::VERSION} + +With ruby-1.9, rspec-#{Spec::VERSION::STRING} requires test-unit-1.2.3, and +tries to force it with "gem 'test-unit', '= 1.2.3'" in: + + #{__FILE__} + +Unfortunately, test-unit-#{Test::Unit::VERSION} was loaded anyway. While we are +aware of this bug we have not been able to track down its source. +Until we do, you have two alternatives: + +* uninstall test-unit-#{Test::Unit::VERSION} +* use 'script/spec' instead of 'rake spec' +#{'*' * 50} +MESSAGE + end +end + + +require 'test/unit/testresult' + +require 'spec/interop/test/unit/testcase' +require 'spec/interop/test/unit/testsuite_adapter' +require 'spec/interop/test/unit/autorunner' +require 'spec/interop/test/unit/testresult' +require 'spec/interop/test/unit/ui/console/testrunner' + +Spec::Example::ExampleGroupFactory.default(Test::Unit::TestCase) + +Test::Unit.run = true diff --git a/vendor/gems/rspec-1.3.1/lib/spec/interop/test/unit/autorunner.rb b/vendor/gems/rspec-1.3.1/lib/spec/interop/test/unit/autorunner.rb new file mode 100644 index 000000000..3944e6995 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/interop/test/unit/autorunner.rb @@ -0,0 +1,6 @@ +class Test::Unit::AutoRunner + remove_method :process_args + def process_args(argv) + true + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/interop/test/unit/testcase.rb b/vendor/gems/rspec-1.3.1/lib/spec/interop/test/unit/testcase.rb new file mode 100644 index 000000000..dc10a2a64 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/interop/test/unit/testcase.rb @@ -0,0 +1,56 @@ +require 'test/unit/testcase' + +module Test + module Unit + # This extension of the standard Test::Unit::TestCase makes RSpec + # available from within, so that you can do things like: + # + # require 'spec/test/unit' + # + # class MyTest < Test::Unit::TestCase + # it "should work with Test::Unit assertions" do + # assert_equal 4, 2+1 + # end + # + # def test_should_work_with_rspec_expectations + # (3+1).should == 5 + # end + # end + # + # See also Spec::Example::ExampleGroup + class TestCase + extend Spec::Example::ExampleGroupMethods + include Spec::Example::ExampleMethods + + def self.suite + Test::Unit::TestSuiteAdapter.new(self) + end + + def self.example_method?(method_name) + should_method?(method_name) || test_method?(method_name) + end + + def self.test_method?(method_name) + method_name =~ /^test./ && ( + instance_method(method_name).arity == 0 || + instance_method(method_name).arity == -1 + ) + end + + before(:each) {setup} + after(:each) {teardown} + + def initialize(description, &implementation) + super + # Some Test::Unit extensions depend on @method_name being present. + @method_name = description.description + @_result = ::Test::Unit::TestResult.new + end + + def run(ignore_this_argument=nil) + super() + end + + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/interop/test/unit/testresult.rb b/vendor/gems/rspec-1.3.1/lib/spec/interop/test/unit/testresult.rb new file mode 100644 index 000000000..dddcfe868 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/interop/test/unit/testresult.rb @@ -0,0 +1,6 @@ +class Test::Unit::TestResult + alias_method :tu_passed?, :passed? + def passed? + return tu_passed? & ::Spec::Runner.run + end +end
\ No newline at end of file diff --git a/vendor/gems/rspec-1.3.1/lib/spec/interop/test/unit/testsuite_adapter.rb b/vendor/gems/rspec-1.3.1/lib/spec/interop/test/unit/testsuite_adapter.rb new file mode 100644 index 000000000..76dcd14dc --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/interop/test/unit/testsuite_adapter.rb @@ -0,0 +1,36 @@ +require 'test/unit/testsuite' + +module Test + module Unit + class TestSuiteAdapter < TestSuite + attr_reader :example_group, :examples + alias_method :tests, :examples + def initialize(example_group) + @example_group = example_group + @examples = example_group.examples + end + + def name + example_group.description + end + + def run(*args) + return true unless args.empty? + example_group.run(Spec::Runner.options) + end + + def size + example_group.number_of_examples + end + + def delete(example) + examples.delete example + end + + def empty? + examples.empty? + end + end + end +end + diff --git a/vendor/gems/rspec-1.3.1/lib/spec/interop/test/unit/ui/console/testrunner.rb b/vendor/gems/rspec-1.3.1/lib/spec/interop/test/unit/ui/console/testrunner.rb new file mode 100644 index 000000000..8e9995e02 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/interop/test/unit/ui/console/testrunner.rb @@ -0,0 +1,61 @@ +require 'test/unit/ui/console/testrunner' + +module Test + module Unit + module UI + module Console + class TestRunner + + alias_method :started_without_rspec, :started + def started_with_rspec(result) + @result = result + @need_to_output_started = true + end + alias_method :started, :started_with_rspec + + alias_method :test_started_without_rspec, :test_started + def test_started_with_rspec(name) + if @need_to_output_started + if @rspec_io + @rspec_io.rewind + output(@rspec_io.read) + end + output("Started") + @need_to_output_started = false + end + test_started_without_rspec(name) + end + alias_method :test_started, :test_started_with_rspec + + alias_method :test_finished_without_rspec, :test_finished + def test_finished_with_rspec(name) + test_finished_without_rspec(name) + @ran_test = true + end + alias_method :test_finished, :test_finished_with_rspec + + alias_method :finished_without_rspec, :finished + def finished_with_rspec(elapsed_time) + @ran_test ||= false + if @ran_test + finished_without_rspec(elapsed_time) + end + end + alias_method :finished, :finished_with_rspec + + alias_method :setup_mediator_without_rspec, :setup_mediator + def setup_mediator_with_rspec + orig_io = @io + @io = StringIO.new + setup_mediator_without_rspec + ensure + @rspec_io = @io + @io = orig_io + end + alias_method :setup_mediator, :setup_mediator_with_rspec + + end + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/matchers.rb b/vendor/gems/rspec-1.3.1/lib/spec/matchers.rb new file mode 100644 index 000000000..a235df3ad --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/matchers.rb @@ -0,0 +1,214 @@ +require 'spec/extensions/instance_exec' +require 'spec/matchers/pretty' +require 'spec/matchers/matcher' +require 'spec/matchers/operator_matcher' +require 'spec/matchers/be' +require 'spec/matchers/be_close' +require 'spec/matchers/be_instance_of' +require 'spec/matchers/be_kind_of' +require 'spec/matchers/change' +require 'spec/matchers/eql' +require 'spec/matchers/equal' +require 'spec/matchers/errors' +require 'spec/matchers/exist' +require 'spec/matchers/generated_descriptions' +require 'spec/matchers/has' +require 'spec/matchers/have' +require 'spec/matchers/include' +require 'spec/matchers/match' +require 'spec/matchers/match_array' +require 'spec/matchers/method_missing' +require 'spec/matchers/raise_exception' +require 'spec/matchers/respond_to' +require 'spec/matchers/satisfy' +require 'spec/matchers/simple_matcher' +require 'spec/matchers/throw_symbol' +require 'spec/matchers/wrap_expectation' +require 'spec/matchers/compatibility' +require 'spec/matchers/dsl' + +module Spec + + # RSpec ships with a number of useful Expression Matchers. An Expression Matcher + # is any object that responds to the following methods: + # + # matches?(actual) + # failure_message_for_should + # + # These methods are also part of the matcher protocol, but are optional: + # + # does_not_match?(actual) + # failure_message_for_should_not + # description #optional + # + # These methods are from older versions of the protocol. They are still supported, + # but are not recommended: + # + # failure_message (use failure_message_for_should instead) + # negative_failure_message (use failure_message_for_should_not instead) + # + # See Spec::Expectations to learn how to use these as Expectation Matchers. + # + # == Predicates + # + # In addition to those Expression Matchers that are defined explicitly, RSpec will + # create custom Matchers on the fly for any arbitrary predicate, giving your specs + # a much more natural language feel. + # + # A Ruby predicate is a method that ends with a "?" and returns true or false. + # Common examples are +empty?+, +nil?+, and +instance_of?+. + # + # All you need to do is write +should be_+ followed by the predicate without + # the question mark, and RSpec will figure it out from there. For example: + # + # [].should be_empty => [].empty? #passes + # [].should_not be_empty => [].empty? #fails + # + # In addtion to prefixing the predicate matchers with "be_", you can also use "be_a_" + # and "be_an_", making your specs read much more naturally: + # + # "a string".should be_an_instance_of(String) =>"a string".instance_of?(String) #passes + # + # 3.should be_a_kind_of(Fixnum) => 3.kind_of?(Numeric) #passes + # 3.should be_a_kind_of(Numeric) => 3.kind_of?(Numeric) #passes + # 3.should be_an_instance_of(Fixnum) => 3.instance_of?(Fixnum) #passes + # 3.should_not be_instance_of(Numeric) => 3.instance_of?(Numeric) #fails + # + # RSpec will also create custom matchers for predicates like +has_key?+. To + # use this feature, just state that the object should have_key(:key) and RSpec will + # call has_key?(:key) on the target. For example: + # + # {:a => "A"}.should have_key(:a) => {:a => "A"}.has_key?(:a) #passes + # {:a => "A"}.should have_key(:b) => {:a => "A"}.has_key?(:b) #fails + # + # You can use this feature to invoke any predicate that begins with "has_", whether it is + # part of the Ruby libraries (like +Hash#has_key?+) or a method you wrote on your own class. + # + # == Custom Matchers + # + # When you find that none of the stock Expectation Matchers provide a natural + # feeling expectation, you can very easily write your own using RSpec's matcher + # DSL or writing one from scratch. + # + # === Matcher DSL + # + # Imagine that you are writing a game in which players can be in various + # zones on a virtual board. To specify that bob should be in zone 4, you + # could say: + # + # bob.current_zone.should eql(Zone.new("4")) + # + # But you might find it more expressive to say: + # + # bob.should be_in_zone("4") + # + # and/or + # + # bob.should_not be_in_zone("3") + # + # You can create such a matcher like so: + # + # Spec::Matchers.define :be_in_zone do |zone| + # match do |player| + # player.in_zone?(zone) + # end + # end + # + # This will generate a <tt>be_in_zone</tt> method that returns a matcher + # with logical default messages for failures. You can override the failure + # messages and the generated description as follows: + # + # Spec::Matchers.define :be_in_zone do |zone| + # match do |player| + # player.in_zone?(zone) + # end + # failure_message_for_should do |player| + # # generate and return the appropriate string. + # end + # failure_message_for_should_not do |player| + # # generate and return the appropriate string. + # end + # description do + # # generate and return the appropriate string. + # end + # end + # + # Each of the message-generation methods has access to the block arguments + # passed to the <tt>create</tt> method (in this case, <tt>zone</tt>). The + # failure message methods (<tt>failure_message_for_should</tt> and + # <tt>failure_message_for_should_not</tt>) are passed the actual value (the + # receiver of <tt>should</tt> or <tt>should_not</tt>). + # + # You can also create matchers that obey a fluent interface using the + # <tt>chain</tt> method: + # + # Spec::Matchers.define :tip do |expected_tip| + # chain :on do |bill| + # @bill = bill + # end + # + # match do |person| + # person.tip_for(bill) == expected_tip + # end + # end + # + # This matcher can be used as follows: + # + # describe Customer do + # it { should tip(10).on(50) } + # end + # + # === Custom Matcher from scratch + # + # You could also write a custom matcher from scratch, as follows: + # + # class BeInZone + # def initialize(expected) + # @expected = expected + # end + # def matches?(target) + # @target = target + # @target.current_zone.eql?(Zone.new(@expected)) + # end + # def failure_message_for_should + # "expected #{@target.inspect} to be in Zone #{@expected}" + # end + # def failure_message_for_should_not + # "expected #{@target.inspect} not to be in Zone #{@expected}" + # end + # end + # + # ... and a method like this: + # + # def be_in_zone(expected) + # BeInZone.new(expected) + # end + # + # And then expose the method to your specs. This is normally done + # by including the method and the class in a module, which is then + # included in your spec: + # + # module CustomGameMatchers + # class BeInZone + # ... + # end + # + # def be_in_zone(expected) + # ... + # end + # end + # + # describe "Player behaviour" do + # include CustomGameMatchers + # ... + # end + # + # or you can include in globally in a spec_helper.rb file <tt>require</tt>d + # from your spec file(s): + # + # Spec::Runner.configure do |config| + # config.include(CustomGameMatchers) + # end + # + module Matchers; end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/matchers/be.rb b/vendor/gems/rspec-1.3.1/lib/spec/matchers/be.rb new file mode 100644 index 000000000..1cbf90308 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/matchers/be.rb @@ -0,0 +1,249 @@ +require 'spec/matchers/dsl' + +Spec::Matchers.define :be_true do + match do |actual| + !!actual + end +end + +Spec::Matchers.define :be_false do + match do |actual| + !actual + end +end + +Spec::Matchers.define :be_nil do + match do |actual| + actual.nil? + end + + failure_message_for_should do |actual| + "expected nil, got #{actual.inspect}" + end + + failure_message_for_should_not do + "expected not nil, got nil" + end +end + +module Spec + module Matchers + + class Be #:nodoc: + include Spec::Matchers::Pretty + + def initialize(*args, &block) + @args = args + end + + def matches?(actual) + @actual = actual + !!@actual + end + + def failure_message_for_should + "expected #{@actual.inspect} to evaluate to true" + end + + def failure_message_for_should_not + "expected #{@actual.inspect} to evaluate to false" + end + + def description + "be" + end + + [:==, :<, :<=, :>=, :>, :===].each do |operator| + define_method operator do |operand| + BeComparedTo.new(operand, operator) + end + end + + private + + def args_to_s + @args.empty? ? "" : parenthesize(inspected_args.join(', ')) + end + + def parenthesize(string) + return "(#{string})" + end + + def inspected_args + @args.collect{|a| a.inspect} + end + + def expected_to_sentence + split_words(@expected) + end + + def args_to_sentence + to_sentence(@args) + end + + end + + class BeComparedTo < Be + + def initialize(operand, operator) + @expected, @operator = operand, operator + @args = [] + end + + def matches?(actual) + @actual = actual + @actual.__send__(@operator, @expected) + end + + def failure_message_for_should + "expected #{@operator} #{@expected}, got #{@actual.inspect}" + end + + def failure_message_for_should_not + message = <<-MESSAGE +'should_not be #{@operator} #{@expected}' not only FAILED, +it is a bit confusing. + MESSAGE + + raise message << ([:===,:==].include?(@operator) ? + "It might be more clearly expressed without the \"be\"?" : + "It might be more clearly expressed in the positive?") + end + + def description + "be #{@operator} #{expected_to_sentence}#{args_to_sentence}" + end + + end + + class BePredicate < Be + + def initialize(*args, &block) + @expected = parse_expected(args.shift) + @args = args + @block = block + end + + def matches?(actual) + @actual = actual + begin + return @result = actual.__send__(predicate, *@args, &@block) + rescue NameError => predicate_missing_error + "this needs to be here or rcov will not count this branch even though it's executed in a code example" + end + + begin + return @result = actual.__send__(present_tense_predicate, *@args, &@block) + rescue NameError + raise predicate_missing_error + end + end + + def failure_message_for_should + "expected #{predicate}#{args_to_s} to return true, got #{@result.inspect}" + end + + def failure_message_for_should_not + "expected #{predicate}#{args_to_s} to return false, got #{@result.inspect}" + end + + def description + "#{prefix_to_sentence}#{expected_to_sentence}#{args_to_sentence}" + end + + private + + def predicate + "#{@expected}?".to_sym + end + + def present_tense_predicate + "#{@expected}s?".to_sym + end + + def parse_expected(expected) + @prefix, expected = prefix_and_expected(expected) + expected + end + + def prefix_and_expected(symbol) + symbol.to_s =~ /^(be_(an?_)?)(.*)/ + return $1, $3 + end + + def prefix_to_sentence + split_words(@prefix) + end + + end + + class BeSameAs < Be + + def initialize(*args, &block) + @expected = args.shift + @args = args + end + + def matches?(actual) + @actual = actual + @actual.equal?(@expected) + end + + def failure_message_for_should + "expected #{@expected}, got #{@actual.inspect}" + end + + def failure_message_for_should_not + "expected not #{@expected}, got #{@actual.inspect}" + end + + def description + "be #{expected_to_sentence}#{args_to_sentence}" + end + + end + + # :call-seq: + # should be_true + # should be_false + # should be_nil + # should be_[arbitrary_predicate](*args) + # should_not be_nil + # should_not be_[arbitrary_predicate](*args) + # + # Given true, false, or nil, will pass if actual value is + # true, false or nil (respectively). Given no args means + # the caller should satisfy an if condition (to be or not to be). + # + # Predicates are any Ruby method that ends in a "?" and returns true or false. + # Given be_ followed by arbitrary_predicate (without the "?"), RSpec will match + # convert that into a query against the target object. + # + # The arbitrary_predicate feature will handle any predicate + # prefixed with "be_an_" (e.g. be_an_instance_of), "be_a_" (e.g. be_a_kind_of) + # or "be_" (e.g. be_empty), letting you choose the prefix that best suits the predicate. + # + # == Examples + # + # target.should be_true + # target.should be_false + # target.should be_nil + # target.should_not be_nil + # + # collection.should be_empty #passes if target.empty? + # target.should_not be_empty #passes unless target.empty? + # target.should_not be_old_enough(16) #passes unless target.old_enough?(16) + def be(*args) + args.empty? ? + Matchers::Be.new : + Matchers::BeSameAs.new(*args) + end + + # passes if target.kind_of?(klass) + def be_a(klass) + be_a_kind_of(klass) + end + + alias_method :be_an, :be_a + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/matchers/be_close.rb b/vendor/gems/rspec-1.3.1/lib/spec/matchers/be_close.rb new file mode 100644 index 000000000..28015f5fb --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/matchers/be_close.rb @@ -0,0 +1,32 @@ +module Spec + module Matchers + # :call-seq: + # should be_close(expected, delta) + # should_not be_close(expected, delta) + # + # Passes if actual == expected +/- delta + # + # == Example + # + # result.should be_close(3.0, 0.5) + def be_close(expected, delta) + Matcher.new :be_close, expected, delta do |_expected_, _delta_| + match do |actual| + (actual - _expected_).abs < _delta_ + end + + failure_message_for_should do |actual| + "expected #{_expected_} +/- (< #{_delta_}), got #{actual}" + end + + failure_message_for_should_not do |actual| + "expected #{_expected_} +/- (< #{_delta_}), got #{actual}" + end + + description do + "be close to #{_expected_} (within +- #{_delta_})" + end + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/matchers/be_instance_of.rb b/vendor/gems/rspec-1.3.1/lib/spec/matchers/be_instance_of.rb new file mode 100644 index 000000000..ffc238405 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/matchers/be_instance_of.rb @@ -0,0 +1,26 @@ +module Spec + module Matchers + # :call-seq: + # should be_instance_of(expected) + # should be_an_instance_of(expected) + # should_not be_instance_of(expected) + # should_not be_an_instance_of(expected) + # + # Passes if actual.instance_of?(expected) + # + # == Examples + # + # 5.should be_instance_of(Fixnum) + # 5.should_not be_instance_of(Numeric) + # 5.should_not be_instance_of(Float) + def be_an_instance_of(expected) + Matcher.new :be_an_instance_of, expected do |_expected_| + match do |actual| + actual.instance_of?(_expected_) + end + end + end + + alias_method :be_instance_of, :be_an_instance_of + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/matchers/be_kind_of.rb b/vendor/gems/rspec-1.3.1/lib/spec/matchers/be_kind_of.rb new file mode 100644 index 000000000..6a1fddc13 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/matchers/be_kind_of.rb @@ -0,0 +1,26 @@ +module Spec + module Matchers + # :call-seq: + # should be_kind_of(expected) + # should be_a_kind_of(expected) + # should_not be_kind_of(expected) + # should_not be_a_kind_of(expected) + # + # Passes if actual.kind_of?(expected) + # + # == Examples + # + # 5.should be_kind_of(Fixnum) + # 5.should be_kind_of(Numeric) + # 5.should_not be_kind_of(Float) + def be_a_kind_of(expected) + Matcher.new :be_a_kind_of, expected do |_expected_| + match do |actual| + actual.kind_of?(_expected_) + end + end + end + + alias_method :be_kind_of, :be_a_kind_of + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/matchers/change.rb b/vendor/gems/rspec-1.3.1/lib/spec/matchers/change.rb new file mode 100644 index 000000000..c8ab9e5cf --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/matchers/change.rb @@ -0,0 +1,151 @@ +module Spec + module Matchers + + #Based on patch from Wilson Bilkovich + class Change #:nodoc: + def initialize(receiver=nil, message=nil, &block) + @message = message || "result" + @value_proc = block || lambda {receiver.__send__(message)} + @to = @from = @minimum = @maximum = @amount = nil + end + + def matches?(event_proc) + raise_block_syntax_error if block_given? + + @before = evaluate_value_proc + event_proc.call + @after = evaluate_value_proc + + return (@to = false) if @from unless @from == @before + return false if @to unless @to == @after + return (@before + @amount == @after) if @amount + return ((@after - @before) >= @minimum) if @minimum + return ((@after - @before) <= @maximum) if @maximum + return @before != @after + end + + def raise_block_syntax_error + raise MatcherError.new(<<-MESSAGE +block passed to should or should_not change must use {} instead of do/end +MESSAGE + ) + end + + def evaluate_value_proc + @value_proc.call + end + + def failure_message_for_should + if @to + "#{@message} should have been changed to #{@to.inspect}, but is now #{@after.inspect}" + elsif @from + "#{@message} should have initially been #{@from.inspect}, but was #{@before.inspect}" + elsif @amount + "#{@message} should have been changed by #{@amount.inspect}, but was changed by #{actual_delta.inspect}" + elsif @minimum + "#{@message} should have been changed by at least #{@minimum.inspect}, but was changed by #{actual_delta.inspect}" + elsif @maximum + "#{@message} should have been changed by at most #{@maximum.inspect}, but was changed by #{actual_delta.inspect}" + else + "#{@message} should have changed, but is still #{@before.inspect}" + end + end + + def actual_delta + @after - @before + end + + def failure_message_for_should_not + "#{@message} should not have changed, but did change from #{@before.inspect} to #{@after.inspect}" + end + + def by(amount) + @amount = amount + self + end + + def by_at_least(minimum) + @minimum = minimum + self + end + + def by_at_most(maximum) + @maximum = maximum + self + end + + def to(to) + @to = to + self + end + + def from (from) + @from = from + self + end + + def description + "change ##{@message}" + end + end + + # :call-seq: + # should change(receiver, message, &block) + # should change(receiver, message, &block).by(value) + # should change(receiver, message, &block).from(old).to(new) + # should_not change(receiver, message, &block) + # + # Allows you to specify that a Proc will cause some value to change. + # + # == Examples + # + # lambda { + # team.add_player(player) + # }.should change(roster, :count) + # + # lambda { + # team.add_player(player) + # }.should change(roster, :count).by(1) + # + # lambda { + # team.add_player(player) + # }.should change(roster, :count).by_at_least(1) + # + # lambda { + # team.add_player(player) + # }.should change(roster, :count).by_at_most(1) + # + # string = "string" + # lambda { + # string.reverse! + # }.should change { string }.from("string").to("gnirts") + # + # lambda { + # person.happy_birthday + # }.should change(person, :birthday).from(32).to(33) + # + # lambda { + # employee.develop_great_new_social_networking_app + # }.should change(employee, :title).from("Mail Clerk").to("CEO") + # + # Evaluates <tt>receiver.message</tt> or <tt>block</tt> before and after + # it evaluates the c object (generated by the lambdas in the examples + # above). + # + # Then compares the values before and after the <tt>receiver.message</tt> + # and evaluates the difference compared to the expected difference. + # + # == WARNING + # <tt>should_not change</tt> only supports the form with no + # subsequent calls to <tt>by</tt>, <tt>by_at_least</tt>, + # <tt>by_at_most</tt>, <tt>to</tt> or <tt>from</tt>. + # + # blocks passed to <tt>should</tt> <tt>change</tt> and <tt>should_not</tt> + # <tt>change</tt> must use the <tt>{}</tt> form (<tt>do/end</tt> is not + # supported). + # + def change(receiver=nil, message=nil, &block) + Matchers::Change.new(receiver, message, &block) + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/matchers/compatibility.rb b/vendor/gems/rspec-1.3.1/lib/spec/matchers/compatibility.rb new file mode 100644 index 000000000..3b3ddb9b6 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/matchers/compatibility.rb @@ -0,0 +1,14 @@ +Spec::Matchers.constants.each do |c| + if Class === (klass = Spec::Matchers.const_get(c)) + if klass.public_instance_methods.any? {|m| ['failure_message_for_should',:failure_message_for_should].include?(m)} + klass.class_eval do + alias_method :failure_message, :failure_message_for_should + end + end + if klass.public_instance_methods.any? {|m| ['failure_message_for_should_not',:failure_message_for_should_not].include?(m)} + klass.class_eval do + alias_method :negative_failure_message, :failure_message_for_should_not + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/matchers/dsl.rb b/vendor/gems/rspec-1.3.1/lib/spec/matchers/dsl.rb new file mode 100644 index 000000000..73f363457 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/matchers/dsl.rb @@ -0,0 +1,20 @@ +module Spec + module Matchers + module DSL + # See Spec::Matchers + def define(name, &declarations) + define_method name do |*expected| + Spec::Matchers::Matcher.new name, *expected, &declarations + end + end + + # Deprecated - use define + def create(name, &declarations) + Spec.deprecate("Spec::Matchers.create","Spec::Matchers.define") + define(name, &declarations) + end + end + end +end + +Spec::Matchers.extend Spec::Matchers::DSL diff --git a/vendor/gems/rspec-1.3.1/lib/spec/matchers/eql.rb b/vendor/gems/rspec-1.3.1/lib/spec/matchers/eql.rb new file mode 100644 index 000000000..98ab198d9 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/matchers/eql.rb @@ -0,0 +1,42 @@ +module Spec + module Matchers + # :call-seq: + # should eql(expected) + # should_not eql(expected) + # + # Passes if actual and expected are of equal value, but not necessarily the same object. + # + # See http://www.ruby-doc.org/core/classes/Object.html#M001057 for more information about equality in Ruby. + # + # == Examples + # + # 5.should eql(5) + # 5.should_not eql(3) + def eql(expected) + Matcher.new :eql, expected do |_expected_| + match do |actual| + actual.eql?(_expected_) + end + + failure_message_for_should do |actual| + <<-MESSAGE + +expected #{_expected_.inspect} + got #{actual.inspect} + +(compared using eql?) +MESSAGE + end + + failure_message_for_should_not do |actual| + <<-MESSAGE + +expected #{actual.inspect} not to equal #{_expected_.inspect} + +(compared using eql?) +MESSAGE + end + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/matchers/equal.rb b/vendor/gems/rspec-1.3.1/lib/spec/matchers/equal.rb new file mode 100644 index 000000000..3580a95af --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/matchers/equal.rb @@ -0,0 +1,53 @@ +module Spec + module Matchers + + # :call-seq: + # should equal(expected) + # should_not equal(expected) + # + # Passes if actual and expected are the same object (object identity). + # + # See http://www.ruby-doc.org/core/classes/Object.html#M001057 for more information about equality in Ruby. + # + # == Examples + # + # 5.should equal(5) #Fixnums are equal + # "5".should_not equal("5") #Strings that look the same are not the same object + def equal(expected) + Matcher.new :equal, expected do |_expected_| + match do |actual| + actual.equal?(_expected_) + end + + def inspect_object(o) + "#<#{o.class}:#{o.object_id}> => #{o.inspect}" + end + + failure_message_for_should do |actual| + <<-MESSAGE + +expected #{inspect_object(_expected_)} + got #{inspect_object(actual)} + +Compared using equal?, which compares object identity, +but expected and actual are not the same object. Use +'actual.should == expected' if you don't care about +object identity in this example. + +MESSAGE + end + + failure_message_for_should_not do |actual| + <<-MESSAGE + +expected not #{inspect_object(actual)} + got #{inspect_object(_expected_)} + +Compared using equal?, which compares object identity. + +MESSAGE + end + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/matchers/errors.rb b/vendor/gems/rspec-1.3.1/lib/spec/matchers/errors.rb new file mode 100644 index 000000000..49c267797 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/matchers/errors.rb @@ -0,0 +1,5 @@ +module Spec + module Matchers + class MatcherError < StandardError; end + end +end
\ No newline at end of file diff --git a/vendor/gems/rspec-1.3.1/lib/spec/matchers/exist.rb b/vendor/gems/rspec-1.3.1/lib/spec/matchers/exist.rb new file mode 100644 index 000000000..dc69c683d --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/matchers/exist.rb @@ -0,0 +1,16 @@ +module Spec + module Matchers + # :call-seq: + # should exist + # should_not exist + # + # Passes if actual.exist? + def exist(arg=nil) + Matcher.new :exist do + match do |actual| + arg ? actual.exist?(arg) : actual.exist? + end + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/matchers/generated_descriptions.rb b/vendor/gems/rspec-1.3.1/lib/spec/matchers/generated_descriptions.rb new file mode 100644 index 000000000..2340f57d8 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/matchers/generated_descriptions.rb @@ -0,0 +1,36 @@ +module Spec + module Matchers + class << self + attr_accessor :last_matcher, :last_should # :nodoc: + end + + def self.clear_generated_description + self.last_matcher = nil + self.last_should = nil + end + + def self.generated_description + return nil if last_should.nil? + "#{last_should.to_s.gsub('_',' ')} #{last_description}" + end + + private + + def self.last_description + last_matcher.respond_to?(:description) ? last_matcher.description : <<-MESSAGE +When you call a matcher in an example without a String, like this: + +specify { object.should matcher } + +or this: + +it { should matcher } + +RSpec expects the matcher to have a #description method. You should either +add a String to the example this matcher is being used in, or give it a +description method. Then you won't have to suffer this lengthy warning again. +MESSAGE + end + end +end + diff --git a/vendor/gems/rspec-1.3.1/lib/spec/matchers/has.rb b/vendor/gems/rspec-1.3.1/lib/spec/matchers/has.rb new file mode 100644 index 000000000..283154fa6 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/matchers/has.rb @@ -0,0 +1,35 @@ +module Spec + module Matchers + + class Has + + def initialize(expected, *args, &block) + @expected, @args, @block = expected, args, block + end + + def matches?(actual) + actual.__send__(predicate(@expected), *@args, &@block) + end + + def failure_message_for_should + "expected ##{predicate(@expected)}(#{@args[0].inspect}) to return true, got false" + end + + def failure_message_for_should_not + "expected ##{predicate(@expected)}(#{@args[0].inspect}) to return false, got true" + end + + def description + "have key #{@args[0].inspect}" + end + + private + + def predicate(sym) + "#{sym.to_s.sub("have_","has_")}?".to_sym + end + + end + + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/matchers/have.rb b/vendor/gems/rspec-1.3.1/lib/spec/matchers/have.rb new file mode 100644 index 000000000..0c936d617 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/matchers/have.rb @@ -0,0 +1,152 @@ +module Spec + module Matchers + class Have #:nodoc: + def initialize(expected, relativity=:exactly) + @expected = (expected == :no ? 0 : expected) + @relativity = relativity + @actual = nil + @plural_collection_name = nil + end + + def relativities + @relativities ||= { + :exactly => "", + :at_least => "at least ", + :at_most => "at most " + } + end + + def matches?(collection_owner) + if collection_owner.respond_to?(@collection_name) + collection = collection_owner.__send__(@collection_name, *@args, &@block) + elsif (@plural_collection_name && collection_owner.respond_to?(@plural_collection_name)) + collection = collection_owner.__send__(@plural_collection_name, *@args, &@block) + elsif (collection_owner.respond_to?(:length) || collection_owner.respond_to?(:size)) + collection = collection_owner + else + collection_owner.__send__(@collection_name, *@args, &@block) + end + @actual = collection.size if collection.respond_to?(:size) + @actual = collection.length if collection.respond_to?(:length) + raise not_a_collection if @actual.nil? + return @actual >= @expected if @relativity == :at_least + return @actual <= @expected if @relativity == :at_most + return @actual == @expected + end + + def not_a_collection + "expected #{@collection_name} to be a collection but it does not respond to #length or #size" + end + + def failure_message_for_should + "expected #{relative_expectation} #{@collection_name}, got #{@actual}" + end + + def failure_message_for_should_not + if @relativity == :exactly + return "expected target not to have #{@expected} #{@collection_name}, got #{@actual}" + elsif @relativity == :at_most + return <<-EOF +Isn't life confusing enough? +Instead of having to figure out the meaning of this: + should_not have_at_most(#{@expected}).#{@collection_name} +We recommend that you use this instead: + should have_at_least(#{@expected + 1}).#{@collection_name} +EOF + elsif @relativity == :at_least + return <<-EOF +Isn't life confusing enough? +Instead of having to figure out the meaning of this: + should_not have_at_least(#{@expected}).#{@collection_name} +We recommend that you use this instead: + should have_at_most(#{@expected - 1}).#{@collection_name} +EOF + end + end + + def description + "have #{relative_expectation} #{@collection_name}" + end + + def respond_to?(sym) + @expected.respond_to?(sym) || super + end + + private + + def method_missing(sym, *args, &block) + @collection_name = sym + if inflector = (defined?(ActiveSupport::Inflector) ? ActiveSupport::Inflector : (defined?(Inflector) ? Inflector : nil)) + @plural_collection_name = inflector.pluralize(sym.to_s) + end + @args = args + @block = block + self + end + + def relative_expectation + "#{relativities[@relativity]}#{@expected}" + end + end + + # :call-seq: + # should have(number).named_collection__or__sugar + # should_not have(number).named_collection__or__sugar + # + # Passes if receiver is a collection with the submitted + # number of items OR if the receiver OWNS a collection + # with the submitted number of items. + # + # If the receiver OWNS the collection, you must use the name + # of the collection. So if a <tt>Team</tt> instance has a + # collection named <tt>#players</tt>, you must use that name + # to set the expectation. + # + # If the receiver IS the collection, you can use any name + # you like for <tt>named_collection</tt>. We'd recommend using + # either "elements", "members", or "items" as these are all + # standard ways of describing the things IN a collection. + # + # This also works for Strings, letting you set an expectation + # about its length + # + # == Examples + # + # # Passes if team.players.size == 11 + # team.should have(11).players + # + # # Passes if [1,2,3].length == 3 + # [1,2,3].should have(3).items #"items" is pure sugar + # + # # Passes if "this string".length == 11 + # "this string".should have(11).characters #"characters" is pure sugar + def have(n) + Matchers::Have.new(n) + end + alias :have_exactly :have + + # :call-seq: + # should have_at_least(number).items + # + # Exactly like have() with >=. + # + # == Warning + # + # +should_not+ +have_at_least+ is not supported + def have_at_least(n) + Matchers::Have.new(n, :at_least) + end + + # :call-seq: + # should have_at_most(number).items + # + # Exactly like have() with <=. + # + # == Warning + # + # +should_not+ +have_at_most+ is not supported + def have_at_most(n) + Matchers::Have.new(n, :at_most) + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/matchers/include.rb b/vendor/gems/rspec-1.3.1/lib/spec/matchers/include.rb new file mode 100644 index 000000000..a2a7fe3db --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/matchers/include.rb @@ -0,0 +1,44 @@ +module Spec + module Matchers + # :call-seq: + # should include(expected) + # should_not include(expected) + # + # Passes if actual includes expected. This works for + # collections and Strings. You can also pass in multiple args + # and it will only pass if all args are found in collection. + # + # == Examples + # + # [1,2,3].should include(3) + # [1,2,3].should include(2,3) #would pass + # [1,2,3].should include(2,3,4) #would fail + # [1,2,3].should_not include(4) + # "spread".should include("read") + # "spread".should_not include("red") + def include(*expected) + Matcher.new :include, *expected do |*_expected_| + match do |actual| + helper(actual, *_expected_) + end + + def helper(actual, *_expected_) + _expected_.each do |expected| + if actual.is_a?(Hash) + if expected.is_a?(Hash) + expected.each_pair do |k,v| + return false unless actual[k] == v + end + else + return false unless actual.has_key?(expected) + end + else + return false unless actual.include?(expected) + end + end + true + end + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/matchers/match.rb b/vendor/gems/rspec-1.3.1/lib/spec/matchers/match.rb new file mode 100644 index 000000000..b4b9ea864 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/matchers/match.rb @@ -0,0 +1,21 @@ +module Spec + module Matchers + # :call-seq: + # should match(pattern) + # should_not match(pattern) + # + # Given a Regexp or String, passes if actual.match(pattern) + # + # == Examples + # + # email.should match(/^([^\s]+)((?:[-a-z0-9]+\.)+[a-z]{2,})$/i) + # email.should match("@example.com") + def match(expected) + Matcher.new :match, expected do |_expected_| + match do |actual| + actual.match(_expected_) + end + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/matchers/match_array.rb b/vendor/gems/rspec-1.3.1/lib/spec/matchers/match_array.rb new file mode 100644 index 000000000..51b4f3929 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/matchers/match_array.rb @@ -0,0 +1,71 @@ +module Spec + module Matchers + + class MatchArray #:nodoc: + include Spec::Matchers::Pretty + + def initialize(expected) + @expected = expected + end + + def matches?(actual) + @actual = actual + @extra_items = difference_between_arrays(@actual, @expected) + @missing_items = difference_between_arrays(@expected, @actual) + @extra_items.empty? & @missing_items.empty? + end + + def failure_message_for_should + message = "expected collection contained: #{safe_sort(@expected).inspect}\n" + message += "actual collection contained: #{safe_sort(@actual).inspect}\n" + message += "the missing elements were: #{safe_sort(@missing_items).inspect}\n" unless @missing_items.empty? + message += "the extra elements were: #{safe_sort(@extra_items).inspect}\n" unless @extra_items.empty? + message + end + + def failure_message_for_should_not + "Matcher does not support should_not" + end + + def description + "contain exactly #{_pretty_print(@expected)}" + end + + private + + def safe_sort(array) + array.all?{|item| item.respond_to?(:<=>)} ? array.sort : array + end + + def difference_between_arrays(array_1, array_2) + difference = array_1.dup + array_2.each do |element| + if index = difference.index(element) + difference.delete_at(index) + end + end + difference + end + + + end + + # :call-seq: + # should =~ expected + # + # Passes if actual contains all of the expected regardless of order. + # This works for collections. Pass in multiple args and it will only + # pass if all args are found in collection. + # + # NOTE: there is no should_not version of array.should =~ other_array + # + # == Examples + # + # [1,2,3].should =~ [1,2,3] # => would pass + # [1,2,3].should =~ [2,3,1] # => would pass + # [1,2,3,4].should =~ [1,2,3] # => would fail + # [1,2,2,3].should =~ [1,2,3] # => would fail + # [1,2,3].should =~ [1,2,3,4] # => would fail + OperatorMatcher.register(Array, '=~', Spec::Matchers::MatchArray) + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/matchers/matcher.rb b/vendor/gems/rspec-1.3.1/lib/spec/matchers/matcher.rb new file mode 100644 index 000000000..4756e2fc3 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/matchers/matcher.rb @@ -0,0 +1,132 @@ +module Spec + module Matchers + class Matcher + include Spec::Matchers::InstanceExec + include Spec::Matchers::Pretty + include Spec::Matchers + + attr_reader :expected, :actual + + def initialize(name, *expected, &declarations) + @name = name + @expected = expected + @actual = nil + @diffable = false + @expected_exception = nil + @messages = { + :description => lambda {"#{name_to_sentence}#{expected_to_sentence}"}, + :failure_message_for_should => lambda {|actual| "expected #{actual.inspect} to #{name_to_sentence}#{expected_to_sentence}"}, + :failure_message_for_should_not => lambda {|actual| "expected #{actual.inspect} not to #{name_to_sentence}#{expected_to_sentence}"} + } + making_declared_methods_public do + instance_exec(*@expected, &declarations) + end + end + + #Used internally by objects returns by +should+ and +should_not+. + def matches?(actual) + @actual = actual + if @expected_exception + begin + instance_exec(actual, &@match_block) + true + rescue @expected_exception + false + end + else + begin + instance_exec(actual, &@match_block) + rescue Spec::Expectations::ExpectationNotMetError + false + end + end + end + + # See Spec::Matchers + def match(&block) + @match_block = block + end + + # See Spec::Matchers + def match_unless_raises(exception=Exception, &block) + @expected_exception = exception + match(&block) + end + + # See Spec::Matchers + def failure_message_for_should(&block) + cache_or_call_cached(:failure_message_for_should, &block) + end + + # See Spec::Matchers + def failure_message_for_should_not(&block) + cache_or_call_cached(:failure_message_for_should_not, &block) + end + + # See Spec::Matchers + def description(&block) + cache_or_call_cached(:description, &block) + end + + #Used internally by objects returns by +should+ and +should_not+. + def diffable? + @diffable + end + + # See Spec::Matchers + def diffable + @diffable = true + end + + # See Spec::Matchers + def chain(method, &block) + self.class.class_eval do + define_method method do |*args| + block.call(*args) + self + end + end + end + + private + + def making_declared_methods_public # :nodoc: + # Our home-grown instance_exec in ruby 1.8.6 results in any methods + # declared in the block eval'd by instance_exec in the block to which we + # are yielding here are scoped private. This is NOT the case for Ruby + # 1.8.7 or 1.9. + # + # Also, due some crazy scoping that I don't understand, these methods + # are actually available in the specs (something about the matcher being + # defined in the scope of Spec::Matchers or within an example), so not + # doing the following will not cause specs to fail, but they *will* + # cause features to fail and that will make users unhappy. So don't. + orig_private_methods = private_methods + yield + st = (class << self; self; end) + (private_methods - orig_private_methods).each {|m| st.__send__ :public, m} + end + + def cache_or_call_cached(key, &block) + block ? cache(key, &block) : call_cached(key) + end + + def cache(key, &block) + @messages[key] = block + end + + def call_cached(key) + @messages[key].arity == 1 ? @messages[key].call(@actual) : @messages[key].call + end + + def name_to_sentence + split_words(@name) + end + + def expected_to_sentence + to_sentence(@expected) + end + + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/matchers/method_missing.rb b/vendor/gems/rspec-1.3.1/lib/spec/matchers/method_missing.rb new file mode 100644 index 000000000..74aad8071 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/matchers/method_missing.rb @@ -0,0 +1,9 @@ +module Spec + module Matchers + def method_missing(sym, *args, &block) # :nodoc: + return Matchers::BePredicate.new(sym, *args, &block) if sym.to_s =~ /^be_/ + return Matchers::Has.new(sym, *args, &block) if sym.to_s =~ /^have_/ + super + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/matchers/operator_matcher.rb b/vendor/gems/rspec-1.3.1/lib/spec/matchers/operator_matcher.rb new file mode 100644 index 000000000..a0465ae75 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/matchers/operator_matcher.rb @@ -0,0 +1,83 @@ +module Spec + module Matchers + + class OperatorMatcher + class << self + def registry + @registry ||= {} + end + + def register(klass, operator, matcher) + registry[klass] ||= {} + registry[klass][operator] = matcher + end + + def get(klass, operator) + matcher = registry[klass] && registry[klass][operator] + unless matcher + parent_class = registry.keys.detect {|pc| klass <= pc } + matcher = registry[parent_class] && registry[parent_class][operator] + end + matcher + end + end + + def initialize(actual) + @actual = actual + end + + def self.use_custom_matcher_or_delegate(operator) + define_method(operator) do |expected| + if matcher = OperatorMatcher.get(@actual.class, operator) + @actual.send(::Spec::Matchers.last_should, matcher.new(expected)) + else + eval_match(@actual, operator, expected) + end + end + end + + ['==', '===', '=~', '>', '>=', '<', '<='].each do |operator| + use_custom_matcher_or_delegate operator + end + + def fail_with_message(message) + Spec::Expectations.fail_with(message, @expected, @actual) + end + + def description + "#{@operator} #{@expected.inspect}" + end + + private + + def eval_match(actual, operator, expected) + ::Spec::Matchers.last_matcher = self + @operator, @expected = operator, expected + __delegate_operator(actual, operator, expected) + end + + end + + class PositiveOperatorMatcher < OperatorMatcher #:nodoc: + def __delegate_operator(actual, operator, expected) + if actual.__send__(operator, expected) + true + elsif ['==','===', '=~'].include?(operator) + fail_with_message("expected: #{expected.inspect},\n got: #{actual.inspect} (using #{operator})") + else + fail_with_message("expected: #{operator} #{expected.inspect},\n got: #{operator.gsub(/./, ' ')} #{actual.inspect}") + end + end + + end + + class NegativeOperatorMatcher < OperatorMatcher #:nodoc: + def __delegate_operator(actual, operator, expected) + return false unless actual.__send__(operator, expected) + return fail_with_message("expected not: #{operator} #{expected.inspect},\n got: #{operator.gsub(/./, ' ')} #{actual.inspect}") + end + + end + + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/matchers/pretty.rb b/vendor/gems/rspec-1.3.1/lib/spec/matchers/pretty.rb new file mode 100644 index 000000000..6db1d051a --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/matchers/pretty.rb @@ -0,0 +1,37 @@ +module Spec + module Matchers + module Pretty + def split_words(sym) + sym.to_s.gsub(/_/,' ') + end + + def to_sentence(words=[]) + words = words.map{|w| w.inspect} + case words.length + when 0 + "" + when 1 + " #{words[0]}" + when 2 + " #{words[0]} and #{words[1]}" + else + " #{words[0...-1].join(', ')}, and #{words[-1]}" + end + end + + def _pretty_print(array) + result = "" + array.each_with_index do |item, index| + if index < (array.length - 2) + result << "#{item.inspect}, " + elsif index < (array.length - 1) + result << "#{item.inspect} and " + else + result << "#{item.inspect}" + end + end + result + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/matchers/raise_exception.rb b/vendor/gems/rspec-1.3.1/lib/spec/matchers/raise_exception.rb new file mode 100644 index 000000000..66741c64d --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/matchers/raise_exception.rb @@ -0,0 +1,131 @@ +module Spec + module Matchers + class RaiseException #:nodoc: + def initialize(expected_exception_or_message=Exception, expected_message=nil, &block) + @block = block + @actual_exception = nil + case expected_exception_or_message + when String, Regexp + @expected_exception, @expected_message = Exception, expected_exception_or_message + else + @expected_exception, @expected_message = expected_exception_or_message, expected_message + end + end + + def matches?(given_proc) + @raised_expected_exception = false + @with_expected_message = false + @eval_block = false + @eval_block_passed = false + begin + given_proc.call + rescue @expected_exception => @actual_exception + @raised_expected_exception = true + @with_expected_message = verify_message + rescue Exception => @actual_exception + # This clause should be empty, but rcov will not report it as covered + # unless something (anything) is executed within the clause + rcov_exception_report = "http://eigenclass.org/hiki.rb?rcov-0.8.0" + end + + unless negative_expectation? + eval_block if @raised_expected_exception && @with_expected_message && @block + end + + (@raised_expected_exception & @with_expected_message) ? (@eval_block ? @eval_block_passed : true) : false + end + + def eval_block + @eval_block = true + begin + @block[@actual_exception] + @eval_block_passed = true + rescue Exception => err + @actual_exception = err + end + end + + def verify_message + case @expected_message + when nil + true + when Regexp + @expected_message =~ @actual_exception.message + else + @expected_message == @actual_exception.message + end + end + + def failure_message_for_should + @eval_block ? @actual_exception.message : "expected #{expected_exception}#{given_exception}" + end + + def failure_message_for_should_not + "expected no #{expected_exception}#{given_exception}" + end + + def description + "raise #{expected_exception}" + end + + private + def expected_exception + case @expected_message + when nil + @expected_exception + when Regexp + "#{@expected_exception} with message matching #{@expected_message.inspect}" + else + "#{@expected_exception} with #{@expected_message.inspect}" + end + end + + def given_exception + @actual_exception.nil? ? " but nothing was raised" : ", got #{@actual_exception.inspect}" + end + + def negative_expectation? + # YES - I'm a bad person... help me find a better way - ryand + caller.first(3).find { |s| s =~ /should_not/ } + end + end + + # :call-seq: + # should raise_exception() + # should raise_exception(NamedError) + # should raise_exception(NamedError, String) + # should raise_exception(NamedError, Regexp) + # should raise_exception() { |exception| ... } + # should raise_exception(NamedError) { |exception| ... } + # should raise_exception(NamedError, String) { |exception| ... } + # should raise_exception(NamedError, Regexp) { |exception| ... } + # should_not raise_exception() + # should_not raise_exception(NamedError) + # should_not raise_exception(NamedError, String) + # should_not raise_exception(NamedError, Regexp) + # + # With no args, matches if any exception is raised. + # With a named exception, matches only if that specific exception is raised. + # With a named exception and messsage specified as a String, matches only if both match. + # With a named exception and messsage specified as a Regexp, matches only if both match. + # Pass an optional block to perform extra verifications on the exception matched + # + # == Examples + # + # lambda { do_something_risky }.should raise_exception + # lambda { do_something_risky }.should raise_exception(PoorRiskDecisionError) + # lambda { do_something_risky }.should raise_exception(PoorRiskDecisionError) { |exception| exception.data.should == 42 } + # lambda { do_something_risky }.should raise_exception(PoorRiskDecisionError, "that was too risky") + # lambda { do_something_risky }.should raise_exception(PoorRiskDecisionError, /oo ri/) + # + # lambda { do_something_risky }.should_not raise_exception + # lambda { do_something_risky }.should_not raise_exception(PoorRiskDecisionError) + # lambda { do_something_risky }.should_not raise_exception(PoorRiskDecisionError, "that was too risky") + # lambda { do_something_risky }.should_not raise_exception(PoorRiskDecisionError, /oo ri/) + def raise_exception(exception=Exception, message=nil, &block) + Matchers::RaiseException.new(exception, message, &block) + end + + alias_method :raise_error, :raise_exception + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/matchers/respond_to.rb b/vendor/gems/rspec-1.3.1/lib/spec/matchers/respond_to.rb new file mode 100644 index 000000000..9161cb94e --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/matchers/respond_to.rb @@ -0,0 +1,71 @@ +module Spec + module Matchers + + class RespondTo #:nodoc: + def initialize(*names) + @names = names + @expected_arity = nil + @names_not_responded_to = [] + end + + def matches?(actual) + @actual = actual + @names.each do |name| + @names_not_responded_to << name unless actual.respond_to?(name) && matches_arity?(actual, name) + end + return @names_not_responded_to.empty? + end + + def failure_message_for_should + "expected #{@actual.inspect} to respond to #{@names_not_responded_to.collect {|name| name.inspect }.join(', ')}#{with_arity}" + end + + def failure_message_for_should_not + "expected #{@actual.inspect} not to respond to #{@names.collect {|name| name.inspect }.join(', ')}" + end + + def description + "respond to #{pp_names}#{with_arity}" + end + + def with(n) + @expected_arity = n + self + end + + def argument + self + end + alias :arguments :argument + + private + + def matches_arity?(actual, name) + @expected_arity.nil?? true : @expected_arity == actual.method(name).arity + end + + def with_arity + @expected_arity.nil?? "" : + " with #{@expected_arity} argument#{@expected_arity == 1 ? '' : 's'}" + end + + def pp_names + # Ruby 1.9 returns the same thing for array.to_s as array.inspect, so just use array.inspect here + @names.length == 1 ? "##{@names.first}" : @names.inspect + end + end + + # :call-seq: + # should respond_to(*names) + # should_not respond_to(*names) + # + # Matches if the target object responds to all of the names + # provided. Names can be Strings or Symbols. + # + # == Examples + # + def respond_to(*names) + Matchers::RespondTo.new(*names) + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/matchers/satisfy.rb b/vendor/gems/rspec-1.3.1/lib/spec/matchers/satisfy.rb new file mode 100644 index 000000000..58e3f56aa --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/matchers/satisfy.rb @@ -0,0 +1,47 @@ +module Spec + module Matchers + + class Satisfy #:nodoc: + def initialize(&block) + @block = block + end + + def matches?(actual, &block) + @block = block if block + @actual = actual + @block.call(actual) + end + + def failure_message_for_should + "expected #{@actual} to satisfy block" + end + + def failure_message_for_should_not + "expected #{@actual} not to satisfy block" + end + end + + # :call-seq: + # should satisfy {} + # should_not satisfy {} + # + # Passes if the submitted block returns true. Yields target to the + # block. + # + # Generally speaking, this should be thought of as a last resort when + # you can't find any other way to specify the behaviour you wish to + # specify. + # + # If you do find yourself in such a situation, you could always write + # a custom matcher, which would likely make your specs more expressive. + # + # == Examples + # + # 5.should satisfy { |n| + # n > 3 + # } + def satisfy(&block) + Matchers::Satisfy.new(&block) + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/matchers/simple_matcher.rb b/vendor/gems/rspec-1.3.1/lib/spec/matchers/simple_matcher.rb new file mode 100644 index 000000000..9c77c0732 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/matchers/simple_matcher.rb @@ -0,0 +1,134 @@ +module Spec + module Matchers + class SimpleMatcher + attr_writer :failure_message, :negative_failure_message, :description + + def initialize(description, &match_block) + @description = description + @match_block = match_block + @failure_message = @negative_failure_message = nil + end + + def matches?(given) + @given = given + case @match_block.arity + when 2 + @match_block.call(@given, self) + else + @match_block.call(@given) + end + end + + def description + @description || explanation + end + + def failure_message_for_should + @failure_message || (@description.nil? ? explanation : %[expected #{@description.inspect} but got #{@given.inspect}]) + end + + def failure_message_for_should_not + @negative_failure_message || (@description.nil? ? explanation : %[expected not to get #{@description.inspect}, but got #{@given.inspect}]) + end + + def explanation + "No description provided. See RDoc for simple_matcher()" + end + end + + # simple_matcher makes it easy for you to create your own custom matchers + # in just a few lines of code when you don't need all the power of a + # completely custom matcher object. + # + # The <tt>description</tt> argument will appear as part of any failure + # message, and is also the source for auto-generated descriptions. + # + # The <tt>match_block</tt> can have an arity of 1 or 2. The first block + # argument will be the given value. The second, if the block accepts it + # will be the matcher itself, giving you access to set custom failure + # messages in favor of the defaults. + # + # The <tt>match_block</tt> should return a boolean: <tt>true</tt> + # indicates a match, which will pass if you use <tt>should</tt> and fail + # if you use <tt>should_not</tt>. false (or nil) indicates no match, + # which will do the reverse: fail if you use <tt>should</tt> and pass if + # you use <tt>should_not</tt>. + # + # An error in the <tt>match_block</tt> will bubble up, resulting in a + # failure. + # + # == Example with default messages + # + # def be_even + # simple_matcher("an even number") { |given| given % 2 == 0 } + # end + # + # describe 2 do + # it "should be even" do + # 2.should be_even + # end + # end + # + # Given an odd number, this example would produce an error message stating: + # expected "an even number", got 3. + # + # Unfortunately, if you're a fan of auto-generated descriptions, this will + # produce "should an even number." Not the most desirable result. You can + # control that using custom messages: + # + # == Example with custom messages + # + # def rhyme_with(expected) + # simple_matcher("rhyme with #{expected.inspect}") do |given, matcher| + # matcher.failure_message = "expected #{given.inspect} to rhyme with #{expected.inspect}" + # matcher.negative_failure_message = "expected #{given.inspect} not to rhyme with #{expected.inspect}" + # given.rhymes_with? expected + # end + # end + # + # # OR + # + # def rhyme_with(expected) + # simple_matcher do |given, matcher| + # matcher.description = "rhyme with #{expected.inspect}" + # matcher.failure_message = "expected #{given.inspect} to rhyme with #{expected.inspect}" + # matcher.negative_failure_message = "expected #{given.inspect} not to rhyme with #{expected.inspect}" + # given.rhymes_with? expected + # end + # end + # + # describe "pecan" do + # it "should rhyme with 'be gone'" do + # nut = "pecan" + # nut.extend Rhymer + # nut.should rhyme_with("be gone") + # end + # end + # + # The resulting messages would be: + # description: rhyme with "be gone" + # failure_message: expected "pecan" to rhyme with "be gone" + # negative failure_message: expected "pecan" not to rhyme with "be gone" + # + # == Wrapped Expectations + # + # Because errors will bubble up, it is possible to wrap other expectations + # in a SimpleMatcher. + # + # def be_even + # simple_matcher("an even number") { |given| (given % 2).should == 0 } + # end + # + # BE VERY CAREFUL when you do this. Only use wrapped expectations for + # matchers that will always be used in only the positive + # (<tt>should</tt>) or negative (<tt>should_not</tt>), but not both. + # The reason is that is you wrap a <tt>should</tt> and call the wrapper + # with <tt>should_not</tt>, the correct result (the <tt>should</tt> + # failing), will fail when you want it to pass. + # + def simple_matcher(description=nil, &match_block) + Spec.deprecate("simple_matcher", "Matcher DSL (http://rspec.rubyforge.org/rspec/1.3.0/classes/Spec/Matchers.html)") + SimpleMatcher.new(description, &match_block) + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/matchers/throw_symbol.rb b/vendor/gems/rspec-1.3.1/lib/spec/matchers/throw_symbol.rb new file mode 100644 index 000000000..2e5dd62f0 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/matchers/throw_symbol.rb @@ -0,0 +1,100 @@ +module Spec + module Matchers + + class ThrowSymbol #:nodoc: + def initialize(expected_symbol = nil, expected_arg=nil) + @expected_symbol = expected_symbol + @expected_arg = expected_arg + @caught_symbol = @caught_arg = nil + end + + def matches?(given_proc) + begin + if @expected_symbol.nil? + given_proc.call + else + @caught_arg = catch :proc_did_not_throw_anything do + catch @expected_symbol do + given_proc.call + throw :proc_did_not_throw_anything, :nothing_thrown + end + end + @caught_symbol = @expected_symbol unless @caught_arg == :nothing_thrown + end + + # Ruby 1.8 uses NameError with `symbol' + # Ruby 1.9 uses ArgumentError with :symbol + rescue NameError, ArgumentError => e + raise e unless e.message =~ /uncaught throw (`|\:)([a-zA-Z0-9_]*)(')?/ + @caught_symbol = $2.to_sym + end + if @expected_symbol.nil? + !@caught_symbol.nil? + elsif @expected_arg.nil? + @caught_symbol == @expected_symbol + else + (@caught_symbol == @expected_symbol) & (@caught_arg == @expected_arg) + end + end + + def failure_message_for_should + if @caught_symbol + "expected #{expected}, got #{@caught_symbol.inspect}" + else + "expected #{expected} but nothing was thrown" + end + end + + def failure_message_for_should_not + if @expected_symbol + "expected #{expected} not to be thrown" + else + "expected no Symbol, got :#{@caught_symbol}" + end + end + + def description + "throw #{expected}" + end + + private + + def expected + @expected_symbol.nil? ? "a Symbol" : "#{@expected_symbol.inspect}#{args}" + end + + def args + @expected_arg.nil? ? "" : " with #{@expected_arg.inspect}" + end + + end + + # :call-seq: + # should throw_symbol() + # should throw_symbol(:sym) + # should throw_symbol(:sym, arg) + # should_not throw_symbol() + # should_not throw_symbol(:sym) + # should_not throw_symbol(:sym, arg) + # + # Given no argument, matches if a proc throws any Symbol. + # + # Given a Symbol, matches if the given proc throws the specified Symbol. + # + # Given a Symbol and an arg, matches if the given proc throws the + # specified Symbol with the specified arg. + # + # == Examples + # + # lambda { do_something_risky }.should throw_symbol + # lambda { do_something_risky }.should throw_symbol(:that_was_risky) + # lambda { do_something_risky }.should throw_symbol(:that_was_risky, culprit) + # + # lambda { do_something_risky }.should_not throw_symbol + # lambda { do_something_risky }.should_not throw_symbol(:that_was_risky) + # lambda { do_something_risky }.should_not throw_symbol(:that_was_risky, culprit) + def throw_symbol(expected_symbol = nil, expected_arg=nil) + Matchers::ThrowSymbol.new(expected_symbol, expected_arg) + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/matchers/wrap_expectation.rb b/vendor/gems/rspec-1.3.1/lib/spec/matchers/wrap_expectation.rb new file mode 100644 index 000000000..95162cae1 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/matchers/wrap_expectation.rb @@ -0,0 +1,55 @@ +module Spec + module Matchers + # wraps an expectation in a block that will return true if the + # expectation passes and false if it fails (without bubbling up + # the failure). + # + # This is intended to be used in the context of a simple matcher, + # and is especially useful for wrapping multiple expectations or + # one or more assertions from test/unit extensions when running + # with test/unit. + # + # == Examples + # + # def eat_cheese(cheese) + # simple_matcher do |mouse, matcher| + # matcher.failure_message = "expected #{mouse} to eat cheese" + # wrap_expectation do |matcher| + # assert_eats_cheese(mouse) + # end + # end + # end + # + # describe Mouse do + # it "eats cheese" do + # Mouse.new.should eat_cheese + # end + # end + # + # You might be wondering "why would I do this if I could just say" + # assert_eats_cheese?", a fair question, indeed. You might prefer + # to replace the word assert with something more aligned with the + # rest of your code examples. You are using rspec, after all. + # + # The other benefit you get is that you can use the negative version + # of the matcher: + # + # describe Cat do + # it "does not eat cheese" do + # Cat.new.should_not eat_cheese + # end + # end + # + # So in the event there is no assert_does_not_eat_cheese available, + # you're all set! + def wrap_expectation(matcher, &block) + begin + block.call(matcher) + return true + rescue Exception => e + matcher.failure_message = e.message + return false + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/mocks.rb b/vendor/gems/rspec-1.3.1/lib/spec/mocks.rb new file mode 100644 index 000000000..339c0cc50 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/mocks.rb @@ -0,0 +1,200 @@ +require 'spec/mocks/framework' +require 'spec/mocks/extensions/object' + +module Spec + # == Mocks and Stubs + # + # RSpec will create Mock Objects and Stubs for you at runtime, or attach stub/mock behaviour + # to any of your real objects (Partial Mock/Stub). Because the underlying implementation + # for mocks and stubs is the same, you can intermingle mock and stub + # behaviour in either dynamically generated mocks or your pre-existing classes. + # There is a semantic difference in how they are created, however, + # which can help clarify the role it is playing within a given spec. + # + # == Mock Objects + # + # Mocks are objects that allow you to set and verify expectations that they will + # receive specific messages during run time. They are very useful for specifying how the subject of + # the spec interacts with its collaborators. This approach is widely known as "interaction + # testing". + # + # Mocks are also very powerful as a design tool. As you are + # driving the implementation of a given class, Mocks provide an anonymous + # collaborator that can change in behaviour as quickly as you can write an expectation in your + # spec. This flexibility allows you to design the interface of a collaborator that often + # does not yet exist. As the shape of the class being specified becomes more clear, so do the + # requirements for its collaborators - often leading to the discovery of new types that are + # needed in your system. + # + # Read Endo-Testing[http://www.mockobjects.com/files/endotesting.pdf] for a much + # more in depth description of this process. + # + # == Stubs + # + # Stubs are objects that allow you to set "stub" responses to + # messages. As Martin Fowler points out on his site, + # mocks_arent_stubs[http://www.martinfowler.com/articles/mocksArentStubs.html]. + # Paraphrasing Fowler's paraphrasing + # of Gerard Meszaros: Stubs provide canned responses to messages they might receive in a test, while + # mocks allow you to specify and, subsquently, verify that certain messages should be received during + # the execution of a test. + # + # == Partial Mocks/Stubs + # + # RSpec also supports partial mocking/stubbing, allowing you to add stub/mock behaviour + # to instances of your existing classes. This is generally + # something to be avoided, because changes to the class can have ripple effects on + # seemingly unrelated specs. When specs fail due to these ripple effects, the fact + # that some methods are being mocked can make it difficult to understand why a + # failure is occurring. + # + # That said, partials do allow you to expect and + # verify interactions with class methods such as +#find+ and +#create+ + # on Ruby on Rails model classes. + # + # == Further Reading + # + # There are many different viewpoints about the meaning of mocks and stubs. If you are interested + # in learning more, here is some recommended reading: + # + # * Mock Objects: http://www.mockobjects.com/ + # * Endo-Testing: http://www.mockobjects.com/files/endotesting.pdf + # * Mock Roles, Not Objects: http://www.mockobjects.com/files/mockrolesnotobjects.pdf + # * Test Double Patterns: http://xunitpatterns.com/Test%20Double%20Patterns.html + # * Mocks aren't stubs: http://www.martinfowler.com/articles/mocksArentStubs.html + # + # == Creating a Mock + # + # You can create a mock in any specification (or setup) using: + # + # mock(name, options={}) + # + # The optional +options+ argument is a +Hash+. Currently the only supported + # option is +:null_object+. Setting this to true instructs the mock to ignore + # any messages it hasn’t been told to expect – and quietly return itself. For example: + # + # mock("person", :null_object => true) + # + # == Creating a Stub + # + # You can create a stub in any specification (or setup) using: + # + # stub(name, stub_methods_and_values_hash) + # + # For example, if you wanted to create an object that always returns + # "More?!?!?!" to "please_sir_may_i_have_some_more" you would do this: + # + # stub("Mr Sykes", :please_sir_may_i_have_some_more => "More?!?!?!") + # + # == Creating a Partial Mock + # + # You don't really "create" a partial mock, you simply add method stubs and/or + # mock expectations to existing classes and objects: + # + # Factory.should_receive(:find).with(id).and_return(value) + # obj.stub!(:to_i).and_return(3) + # etc ... + # + # == Expecting Messages + # + # my_mock.should_receive(:sym) + # my_mock.should_not_receive(:sym) + # + # == Expecting Arguments + # + # my_mock.should_receive(:sym).with(*args) + # my_mock.should_not_receive(:sym).with(*args) + # + # == Argument Matchers + # + # Arguments that are passed to #with are compared with actual arguments received + # using == by default. In cases in which you want to specify things about the arguments + # rather than the arguments themselves, you can use any of RSpec's Expression Matchers. + # They don't all make syntactic sense (they were primarily designed for use with + # Spec::Expectations), but you are free to create your own custom Spec::Matchers. + # + # Spec::Mocks does provide one additional Matcher method named #ducktype. + # + # In addition, Spec::Mocks adds some keyword Symbols that you can use to + # specify certain kinds of arguments: + # + # my_mock.should_receive(:sym).with(no_args()) + # my_mock.should_receive(:sym).with(any_args()) + # my_mock.should_receive(:sym).with(1, kind_of(Numeric), "b") #2nd argument can any kind of Numeric + # my_mock.should_receive(:sym).with(1, boolean(), "b") #2nd argument can true or false + # my_mock.should_receive(:sym).with(1, /abc/, "b") #2nd argument can be any String matching the submitted Regexp + # my_mock.should_receive(:sym).with(1, anything(), "b") #2nd argument can be anything at all + # my_mock.should_receive(:sym).with(1, ducktype(:abs, :div), "b") + # #2nd argument can be object that responds to #abs and #div + # + # == Receive Counts + # + # my_mock.should_receive(:sym).once + # my_mock.should_receive(:sym).twice + # my_mock.should_receive(:sym).exactly(n).times + # my_mock.should_receive(:sym).at_least(:once) + # my_mock.should_receive(:sym).at_least(:twice) + # my_mock.should_receive(:sym).at_least(n).times + # my_mock.should_receive(:sym).at_most(:once) + # my_mock.should_receive(:sym).at_most(:twice) + # my_mock.should_receive(:sym).at_most(n).times + # my_mock.should_receive(:sym).any_number_of_times + # + # == Ordering + # + # my_mock.should_receive(:sym).ordered + # my_mock.should_receive(:other_sym).ordered + # #This will fail if the messages are received out of order + # + # == Setting Reponses + # + # Whether you are setting a mock expectation or a simple stub, you can tell the + # object precisely how to respond: + # + # my_mock.should_receive(:sym).and_return(value) + # my_mock.should_receive(:sym).exactly(3).times.and_return(value1, value2, value3) + # # returns value1 the first time, value2 the second, etc + # my_mock.should_receive(:sym).and_return { ... } #returns value returned by the block + # my_mock.should_receive(:sym).and_raise(error) + # #error can be an instantiated object or a class + # #if it is a class, it must be instantiable with no args + # my_mock.should_receive(:sym).and_throw(:sym) + # my_mock.should_receive(:sym).and_yield(values,to,yield) + # my_mock.should_receive(:sym).and_yield(values,to,yield).and_yield(some,other,values,this,time) + # # for methods that yield to a block multiple times + # + # Any of these responses can be applied to a stub as well, but stubs do + # not support any qualifiers about the message received (i.e. you can't specify arguments + # or receive counts): + # + # my_mock.stub!(:sym).and_return(value) + # my_mock.stub!(:sym).and_return(value1, value2, value3) + # my_mock.stub!(:sym).and_raise(error) + # my_mock.stub!(:sym).and_throw(:sym) + # my_mock.stub!(:sym).and_yield(values,to,yield) + # my_mock.stub!(:sym).and_yield(values,to,yield).and_yield(some,other,values,this,time) + # + # == Arbitrary Handling + # + # Once in a while you'll find that the available expectations don't solve the + # particular problem you are trying to solve. Imagine that you expect the message + # to come with an Array argument that has a specific length, but you don't care + # what is in it. You could do this: + # + # my_mock.should_receive(:sym) do |arg| + # arg.should be_an_istance_of(Array) + # arg.length.should == 7 + # end + # + # Note that this would fail if the number of arguments received was different from + # the number of block arguments (in this case 1). + # + # == Combining Expectation Details + # + # Combining the message name with specific arguments, receive counts and responses + # you can get quite a bit of detail in your expectations: + # + # my_mock.should_receive(:<<).with("illegal value").once.and_raise(ArgumentError) + module Mocks + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/mocks/argument_expectation.rb b/vendor/gems/rspec-1.3.1/lib/spec/mocks/argument_expectation.rb new file mode 100644 index 000000000..b51b7bae5 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/mocks/argument_expectation.rb @@ -0,0 +1,51 @@ +module Spec + module Mocks + + class ArgumentExpectation + attr_reader :args + + def initialize(args, &block) + @args = args + @matchers_block = block + @match_any_args = false + @matchers = nil + + if ArgumentMatchers::AnyArgsMatcher === args.first + @match_any_args = true + elsif ArgumentMatchers::NoArgsMatcher === args.first + @matchers = [] + else + @matchers = args.collect {|arg| matcher_for(arg)} + end + end + + def matcher_for(arg) + return ArgumentMatchers::MatcherMatcher.new(arg) if is_matcher?(arg) + return ArgumentMatchers::RegexpMatcher.new(arg) if arg.is_a?(Regexp) + return ArgumentMatchers::EqualityProxy.new(arg) + end + + def is_matcher?(obj) + return obj.respond_to?(:matches?) & obj.respond_to?(:description) + end + + def args_match?(given_args) + match_any_args? || matchers_block_matches?(given_args) || matchers_match?(given_args) + end + + def matchers_block_matches?(given_args) + @matchers_block ? @matchers_block.call(*given_args) : nil + end + + def matchers_match?(given_args) + @matchers == given_args + end + + def match_any_args? + @match_any_args + end + + end + + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/mocks/argument_matchers.rb b/vendor/gems/rspec-1.3.1/lib/spec/mocks/argument_matchers.rb new file mode 100644 index 000000000..f56551f21 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/mocks/argument_matchers.rb @@ -0,0 +1,237 @@ +module Spec + module Mocks + + # ArgumentMatchers are messages that you can include in message + # expectations to match arguments against a broader check than simple + # equality. + # + # With the exception of any_args() and no_args(), the matchers + # are all positional - they match against the arg in the given position. + module ArgumentMatchers + + class AnyArgsMatcher + def description + "any args" + end + end + + class NoArgsMatcher + def description + "no args" + end + end + + class AnyArgMatcher + def initialize(ignore) + end + + def ==(other) + true + end + + def description + "anything" + end + end + + class RegexpMatcher + def initialize(regexp) + @regexp = regexp + end + + def ==(value) + return value =~ @regexp unless value.is_a?(Regexp) + value == @regexp + end + end + + class BooleanMatcher + def initialize(ignore) + end + + def ==(value) + TrueClass === value || FalseClass === value + end + end + + class HashIncludingMatcher + def initialize(expected) + @expected = expected + end + + def ==(actual) + @expected.each do | key, value | + return false unless actual.has_key?(key) && value == actual[key] + end + true + rescue NoMethodError => ex + return false + end + + def description + "hash_including(#{@expected.inspect.sub(/^\{/,"").sub(/\}$/,"")})" + end + end + + class HashNotIncludingMatcher + def initialize(expected) + @expected = expected + end + + def ==(actual) + @expected.each do | key, value | + return false if actual.has_key?(key) && value == actual[key] + end + true + rescue NoMethodError => ex + return false + end + + def description + "hash_not_including(#{@expected.inspect.sub(/^\{/,"").sub(/\}$/,"")})" + end + end + + class DuckTypeMatcher + def initialize(*methods_to_respond_to) + @methods_to_respond_to = methods_to_respond_to + end + + def ==(value) + @methods_to_respond_to.all? { |sym| value.respond_to?(sym) } + end + end + + class MatcherMatcher + def initialize(matcher) + @matcher = matcher + end + + def ==(value) + @matcher.matches?(value) + end + end + + class EqualityProxy + def initialize(given) + @given = given + end + + def ==(expected) + @given == expected + end + end + + class InstanceOf + def initialize(klass) + @klass = klass + end + + def ==(actual) + actual.instance_of?(@klass) + end + end + + class KindOf + def initialize(klass) + @klass = klass + end + + def ==(actual) + actual.kind_of?(@klass) + end + end + + # :call-seq: + # object.should_receive(:message).with(no_args()) + # + # Passes if no arguments are passed along with the message + def no_args + NoArgsMatcher.new + end + + # :call-seq: + # object.should_receive(:message).with(any_args()) + # + # Passes if object receives :message with any args at all. This is + # really a more explicit variation of object.should_receive(:message) + def any_args + AnyArgsMatcher.new + end + + # :call-seq: + # object.should_receive(:message).with(anything()) + # + # Passes as long as there is an argument. + def anything + AnyArgMatcher.new(nil) + end + + # :call-seq: + # object.should_receive(:message).with(duck_type(:hello)) + # object.should_receive(:message).with(duck_type(:hello, :goodbye)) + # + # Passes if the argument responds to the specified messages. + # + # == Examples + # + # array = [] + # display = mock('display') + # display.should_receive(:present_names).with(duck_type(:length, :each)) + # => passes + def duck_type(*args) + DuckTypeMatcher.new(*args) + end + + # :call-seq: + # object.should_receive(:message).with(boolean()) + # + # Passes if the argument is boolean. + def boolean + BooleanMatcher.new(nil) + end + + # :call-seq: + # object.should_receive(:message).with(hash_including(:key => val)) + # object.should_receive(:message).with(hash_including(:key)) + # object.should_receive(:message).with(hash_including(:key, :key2 => val2)) + # Passes if the argument is a hash that includes the specified key(s) or key/value + # pairs. If the hash includes other keys, it will still pass. + def hash_including(*args) + HashIncludingMatcher.new(anythingize_lonely_keys(*args)) + end + + # :call-seq: + # object.should_receive(:message).with(hash_not_including(:key => val)) + # object.should_receive(:message).with(hash_not_including(:key)) + # object.should_receive(:message).with(hash_not_including(:key, :key2 => :val2)) + # + # Passes if the argument is a hash that doesn't include the specified key(s) or key/value + def hash_not_including(*args) + HashNotIncludingMatcher.new(anythingize_lonely_keys(*args)) + end + + # Passes if arg.instance_of?(klass) + def instance_of(klass) + InstanceOf.new(klass) + end + + alias_method :an_instance_of, :instance_of + + # Passes if arg.kind_of?(klass) + def kind_of(klass) + KindOf.new(klass) + end + + alias_method :a_kind_of, :kind_of + + private + + def anythingize_lonely_keys(*args) + hash = args.last.class == Hash ? args.delete_at(-1) : {} + args.each { | arg | hash[arg] = anything } + hash + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/mocks/error_generator.rb b/vendor/gems/rspec-1.3.1/lib/spec/mocks/error_generator.rb new file mode 100644 index 000000000..f63811fed --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/mocks/error_generator.rb @@ -0,0 +1,92 @@ +module Spec + module Mocks + class ErrorGenerator + attr_writer :opts + + def initialize(target, name, options={}) + @declared_as = options[:__declared_as] || 'Mock' + @target = target + @name = name + end + + def opts + @opts ||= {} + end + + def raise_unexpected_message_error(sym, *args) + __raise "#{intro} received unexpected message :#{sym}#{arg_message(*args)}" + end + + def raise_unexpected_message_args_error(expectation, *args) + expected_args = format_args(*expectation.expected_args) + actual_args = args.empty? ? "(no args)" : format_args(*args) + __raise "#{intro} received #{expectation.sym.inspect} with unexpected arguments\n expected: #{expected_args}\n got: #{actual_args}" + end + + def raise_expectation_error(sym, expected_received_count, actual_received_count, *args) + __raise "#{intro} expected :#{sym}#{arg_message(*args)} #{count_message(expected_received_count)}, but received it #{count_message(actual_received_count)}" + end + + def raise_out_of_order_error(sym) + __raise "#{intro} received :#{sym} out of order" + end + + def raise_block_failed_error(sym, detail) + __raise "#{intro} received :#{sym} but passed block failed with: #{detail}" + end + + def raise_missing_block_error(args_to_yield) + __raise "#{intro} asked to yield |#{arg_list(*args_to_yield)}| but no block was passed" + end + + def raise_wrong_arity_error(args_to_yield, arity) + __raise "#{intro} yielded |#{arg_list(*args_to_yield)}| to block with arity of #{arity}" + end + + private + + def intro + if @name + "#{@declared_as} #{@name.inspect}" + elsif Mock === @target + @declared_as + elsif Class === @target + "<#{@target.inspect} (class)>" + elsif @target + @target + else + "nil" + end + end + + def __raise(message) + message = opts[:message] unless opts[:message].nil? + Kernel::raise(Spec::Mocks::MockExpectationError, message) + end + + def arg_message(*args) + " with " + format_args(*args) + end + + def format_args(*args) + args.empty? ? "(no args)" : "(" + arg_list(*args) + ")" + end + + def arg_list(*args) + args.collect {|arg| arg.respond_to?(:description) ? arg.description : arg.inspect}.join(", ") + end + + def count_message(count) + return "at least #{pretty_print(count.abs)}" if count < 0 + return pretty_print(count) + end + + def pretty_print(count) + return "once" if count == 1 + return "twice" if count == 2 + return "#{count} times" + end + + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/mocks/errors.rb b/vendor/gems/rspec-1.3.1/lib/spec/mocks/errors.rb new file mode 100644 index 000000000..560b66a93 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/mocks/errors.rb @@ -0,0 +1,10 @@ +module Spec + module Mocks + class MockExpectationError < Exception + end + + class AmbiguousReturnError < StandardError + end + end +end + diff --git a/vendor/gems/rspec-1.3.1/lib/spec/mocks/example_methods.rb b/vendor/gems/rspec-1.3.1/lib/spec/mocks/example_methods.rb new file mode 100644 index 000000000..f6c68ab6a --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/mocks/example_methods.rb @@ -0,0 +1,69 @@ +module Spec + module Mocks + module ExampleMethods + include Spec::Mocks::ArgumentMatchers + + # Shortcut for creating an instance of Spec::Mocks::Mock. + # + # +name+ is used for failure reporting, so you should use the + # role that the double is playing in the example. + # + # +stubs_and_options+ lets you assign options and stub values + # at the same time. The only option available is :null_object. + # Anything else is treated as a stub value. + # + # == Examples + # + # thing = double("thing", :a => "A") + # thing.a == "A" => true + # + # person = double("thing", :name => "Joe", :email => "joe@domain.com") + # person.name => "Joe" + # person.email => "joe@domain.com" + def double(*args) + __declare_double('Double', *args) + end + + # Alias for double + def mock(*args) + __declare_double('Mock', *args) + end + + # Alias for double + def stub(*args) + __declare_double('Stub', *args) + end + + def __declare_double(declared_as, *args) # :nodoc: + args << {} unless Hash === args.last + args.last[:__declared_as] = declared_as + Spec::Mocks::Mock.new(*args) + end + + # DEPRECATED - use double('name').as_null_object instead + # + # Shortcut for creating a mock object that will return itself in response + # to any message it receives that it hasn't been explicitly instructed + # to respond to. + def stub_everything(name = 'stub') + Spec.warn(<<-WARNING) + +DEPRECATION: stub_everything('#{name}') is deprecated and will be removed +from a future version of rspec. Please use double('#{name}').as_null_object +(or stub('#{name}').as_null_object or mock('#{name}').as_null_object instead. + +WARNING + mock(name, :null_object => true) + end + + # Disables warning messages about expectations being set on nil. + # + # By default warning messages are issued when expectations are set on nil. This is to + # prevent false-positives and to catch potential bugs early on. + def allow_message_expectations_on_nil + Proxy.allow_message_expectations_on_nil + end + + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/mocks/extensions.rb b/vendor/gems/rspec-1.3.1/lib/spec/mocks/extensions.rb new file mode 100644 index 000000000..6fd51a272 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/mocks/extensions.rb @@ -0,0 +1 @@ +require 'spec/mocks/extensions/object' diff --git a/vendor/gems/rspec-1.3.1/lib/spec/mocks/extensions/object.rb b/vendor/gems/rspec-1.3.1/lib/spec/mocks/extensions/object.rb new file mode 100644 index 000000000..4b7531066 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/mocks/extensions/object.rb @@ -0,0 +1,3 @@ +class Object + include Spec::Mocks::Methods +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/mocks/framework.rb b/vendor/gems/rspec-1.3.1/lib/spec/mocks/framework.rb new file mode 100644 index 000000000..e25778655 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/mocks/framework.rb @@ -0,0 +1,15 @@ +# Require everything except the global extensions of class and object. This +# supports wrapping rspec's mocking functionality without invading every +# object in the system. + +require 'spec/mocks/methods' +require 'spec/mocks/argument_matchers' +require 'spec/mocks/example_methods' +require 'spec/mocks/proxy' +require 'spec/mocks/mock' +require 'spec/mocks/argument_expectation' +require 'spec/mocks/message_expectation' +require 'spec/mocks/order_group' +require 'spec/mocks/errors' +require 'spec/mocks/error_generator' +require 'spec/mocks/space' diff --git a/vendor/gems/rspec-1.3.1/lib/spec/mocks/message_expectation.rb b/vendor/gems/rspec-1.3.1/lib/spec/mocks/message_expectation.rb new file mode 100644 index 000000000..cd8dc0f97 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/mocks/message_expectation.rb @@ -0,0 +1,344 @@ +module Spec + module Mocks + + class BaseExpectation + attr_reader :sym + attr_writer :expected_received_count, :method_block, :expected_from + protected :expected_received_count=, :method_block=, :expected_from= + attr_accessor :error_generator + protected :error_generator, :error_generator= + + def initialize(error_generator, expectation_ordering, expected_from, sym, method_block, expected_received_count=1, opts={}, &implementation) + @error_generator = error_generator + @error_generator.opts = opts + @expected_from = expected_from + @sym = sym + @method_block = method_block + @actual_received_count = 0 + @expected_received_count = expected_received_count + @args_expectation = ArgumentExpectation.new([ArgumentMatchers::AnyArgsMatcher.new]) + @consecutive = false + @exception_to_raise = nil + @symbol_to_throw = nil + @order_group = expectation_ordering + @at_least = nil + @at_most = nil + @args_to_yield = [] + @failed_fast = nil + @args_to_yield_were_cloned = false + @return_block = implementation + @eval_context = nil + end + + def build_child(expected_from, method_block, expected_received_count, opts={}) + child = clone + child.expected_from = expected_from + child.method_block = method_block + child.expected_received_count = expected_received_count + child.clear_actual_received_count! + new_gen = error_generator.clone + new_gen.opts = opts + child.error_generator = new_gen + child.clone_args_to_yield @args_to_yield + child + end + + def expected_args + @args_expectation.args + end + + def and_return(*values, &return_block) + Kernel::raise AmbiguousReturnError unless @method_block.nil? + case values.size + when 0 then value = nil + when 1 then value = values[0] + else + value = values + @consecutive = true + @expected_received_count = values.size if !ignoring_args? && + @expected_received_count < values.size + end + @return_block = block_given? ? return_block : lambda { value } + end + + # :call-seq: + # and_raise() + # and_raise(Exception) #any exception class + # and_raise(exception) #any exception object + # + # == Warning + # + # When you pass an exception class, the MessageExpectation will + # raise an instance of it, creating it with +new+. If the exception + # class initializer requires any parameters, you must pass in an + # instance and not the class. + def and_raise(exception=Exception) + @exception_to_raise = exception + end + + def and_throw(symbol) + @symbol_to_throw = symbol + end + + def and_yield(*args, &block) + if @args_to_yield_were_cloned + @args_to_yield.clear + @args_to_yield_were_cloned = false + end + + if block + require 'spec/extensions/instance_exec' + @eval_context = Object.new + @eval_context.extend Spec::Matchers::InstanceExec + yield @eval_context + end + @args_to_yield << args + self + end + + def matches(sym, args) + @sym == sym and @args_expectation.args_match?(args) + end + + def invoke(*args, &block) + if @expected_received_count == 0 + @failed_fast = true + @actual_received_count += 1 + @error_generator.raise_expectation_error @sym, @expected_received_count, @actual_received_count, *args + end + + @order_group.handle_order_constraint self + + begin + Kernel::raise @exception_to_raise unless @exception_to_raise.nil? + Kernel::throw @symbol_to_throw unless @symbol_to_throw.nil? + + + if !@method_block.nil? + default_return_val = invoke_method_block(*args) + elsif @args_to_yield.size > 0 || @eval_context + default_return_val = invoke_with_yield(&block) + else + default_return_val = nil + end + + if @consecutive + return invoke_consecutive_return_block(*args, &block) + elsif @return_block + return invoke_return_block(*args, &block) + else + return default_return_val + end + ensure + @actual_received_count += 1 + end + end + + def called_max_times? + @expected_received_count != :any && @expected_received_count > 0 && + @actual_received_count >= @expected_received_count + end + + def invoke_return_block(*args, &block) + args << block unless block.nil? + # Ruby 1.9 - when we set @return_block to return values + # regardless of arguments, any arguments will result in + # a "wrong number of arguments" error + @return_block.arity == 0 ? @return_block.call : @return_block.call(*args) + end + + protected + + def invoke_method_block(*args) + begin + @method_block.call(*args) + rescue => detail + @error_generator.raise_block_failed_error @sym, detail.message + end + end + + def invoke_with_yield(&block) + if block.nil? + @error_generator.raise_missing_block_error @args_to_yield + end + value = nil + @args_to_yield.each do |args_to_yield_this_time| + if block.arity > -1 && args_to_yield_this_time.length != block.arity + @error_generator.raise_wrong_arity_error args_to_yield_this_time, block.arity + end + value = eval_block(*args_to_yield_this_time, &block) + end + value + end + + def eval_block(*args, &block) + if @eval_context + @eval_context.instance_exec(*args, &block) + else + block.call(*args) + end + end + + def invoke_consecutive_return_block(*args, &block) + value = invoke_return_block(*args, &block) + index = [@actual_received_count, value.size-1].min + value[index] + end + + def clone_args_to_yield(args) + @args_to_yield = args.clone + @args_to_yield_were_cloned = true + end + + def failed_fast? + @failed_fast + end + end + + class MessageExpectation < BaseExpectation + + def matches_name?(sym) + @sym == sym + end + + def matches_name_but_not_args(sym, args) + matches_name?(sym) and not @args_expectation.args_match?(args) + end + + def verify_messages_received + return if expected_messages_received? || failed_fast? + + generate_error + rescue Spec::Mocks::MockExpectationError => error + error.backtrace.insert(0, @expected_from) + Kernel::raise error + end + + def expected_messages_received? + ignoring_args? || matches_exact_count? || + matches_at_least_count? || matches_at_most_count? + end + + def ignoring_args? + @expected_received_count == :any + end + + def matches_at_least_count? + @at_least && @actual_received_count >= @expected_received_count + end + + def matches_at_most_count? + @at_most && @actual_received_count <= @expected_received_count + end + + def matches_exact_count? + @expected_received_count == @actual_received_count + end + + def similar_messages + @similar_messages ||= [] + end + + def advise(args, block) + similar_messages << args + end + + def generate_error + if similar_messages.empty? + @error_generator.raise_expectation_error(@sym, @expected_received_count, @actual_received_count, *@args_expectation.args) + else + @error_generator.raise_unexpected_message_args_error(self, *@similar_messages) + end + end + + def with(*args, &block) + @args_expectation = ArgumentExpectation.new(args, &block) + self + end + + def exactly(n) + set_expected_received_count :exactly, n + self + end + + def at_least(n) + set_expected_received_count :at_least, n + self + end + + def at_most(n) + set_expected_received_count :at_most, n + self + end + + def times(&block) + @method_block = block if block + self + end + + def any_number_of_times(&block) + @method_block = block if block + @expected_received_count = :any + self + end + + def never + @expected_received_count = 0 + self + end + + def once(&block) + @method_block = block if block + @expected_received_count = 1 + self + end + + def twice(&block) + @method_block = block if block + @expected_received_count = 2 + self + end + + def ordered(&block) + @method_block = block if block + @order_group.register(self) + @ordered = true + self + end + + def negative_expectation_for?(sym) + return false + end + + protected + def set_expected_received_count(relativity, n) + @at_least = (relativity == :at_least) + @at_most = (relativity == :at_most) + @expected_received_count = case n + when Numeric + n + when :once + 1 + when :twice + 2 + end + end + + def clear_actual_received_count! + @actual_received_count = 0 + end + + end + + class NegativeMessageExpectation < MessageExpectation + def initialize(message, expectation_ordering, expected_from, sym, method_block) + super(message, expectation_ordering, expected_from, sym, method_block, 0) + end + + def negative_expectation_for?(sym) + return @sym == sym + end + end + + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/mocks/methods.rb b/vendor/gems/rspec-1.3.1/lib/spec/mocks/methods.rb new file mode 100644 index 000000000..5d94cac37 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/mocks/methods.rb @@ -0,0 +1,94 @@ +module Spec + module Mocks + module Methods + def should_receive(sym, opts={}, &block) + __mock_proxy.add_message_expectation(opts[:expected_from] || caller(1)[0], sym.to_sym, opts, &block) + end + + def should_not_receive(sym, &block) + __mock_proxy.add_negative_message_expectation(caller(1)[0], sym.to_sym, &block) + end + + def stub!(sym_or_hash, opts={}, &block) + if Hash === sym_or_hash + sym_or_hash.each {|method, value| stub!(method).and_return value } + else + __mock_proxy.add_stub(caller(1)[0], sym_or_hash.to_sym, opts, &block) + end + end + + alias_method :stub, :stub! + + def unstub!(message) + __mock_proxy.remove_stub(message) + end + + alias_method :unstub, :unstub! + + # :call-seq: + # object.stub_chain(:first, :second, :third).and_return(:this) + # + # Supports stubbing a chain of methods. Each argument represents + # a method name to stub, and each one returns a proxy object that + # can accept more stubs, until the last, which returns whatever + # is passed to +and_return_. + # + # == Examples + # + # # with this in an example ... + # article = double('article') + # Article.stub_chain(:authored_by, :published, :recent).and_return([article]) + # # then this will return an Array with the article double in it: + # Article.authored_by(params[:author_id]).published.recent + def stub_chain(*methods) + if methods.length > 1 + if matching_stub = __mock_proxy.find_matching_method_stub(methods[0]) + methods.shift + matching_stub.invoke_return_block.stub_chain(*methods) + else + next_in_chain = Object.new + stub!(methods.shift) {next_in_chain} + next_in_chain.stub_chain(*methods) + end + else + stub!(methods.shift) + end + end + + # Record and otherwise ignore all messages that aren't specified, + # with +stub+, +stub!+, or +should_receive+. + # + # == Returns + # self + def as_null_object + __mock_proxy.as_null_object + end + + def null_object? + __mock_proxy.null_object? + end + + def received_message?(sym, *args, &block) #:nodoc: + __mock_proxy.received_message?(sym.to_sym, *args, &block) + end + + def rspec_verify #:nodoc: + __mock_proxy.verify + end + + def rspec_reset #:nodoc: + __mock_proxy.reset + end + + private + + def __mock_proxy + if Mock === self + @mock_proxy ||= Proxy.new(self, @name, @options) + else + @mock_proxy ||= Proxy.new(self) + end + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/mocks/mock.rb b/vendor/gems/rspec-1.3.1/lib/spec/mocks/mock.rb new file mode 100644 index 000000000..35a6c798e --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/mocks/mock.rb @@ -0,0 +1,71 @@ +module Spec + module Mocks + class Mock + include Methods + + # Creates a new mock with a +name+ (that will be used in error messages + # only) == Options: + # * <tt>:null_object</tt> - if true, the mock object acts as a forgiving + # null object allowing any message to be sent to it. + def initialize(name=nil, stubs_and_options={}) + if name.is_a?(Hash) && stubs_and_options.empty? + stubs_and_options = name + @name = nil + else + @name = name + end + @options = extract_options(stubs_and_options) + assign_stubs(stubs_and_options) + end + + # This allows for comparing the mock to other objects that proxy such as + # ActiveRecords belongs_to proxy objects. By making the other object run + # the comparison, we're sure the call gets delegated to the proxy + # target. + def ==(other) + other == __mock_proxy + end + + def inspect + "#<#{self.class}:#{sprintf '0x%x', self.object_id} @name=#{@name.inspect}>" + end + + def to_s + inspect.gsub('<','[').gsub('>',']') + end + + private + + def method_missing(sym, *args, &block) + __mock_proxy.record_message_received(sym, args, block) + begin + return self if __mock_proxy.null_object? + super(sym, *args, &block) + rescue NameError + __mock_proxy.raise_unexpected_message_error sym, *args + end + end + + def extract_options(stubs_and_options) + options = {} + extract_option(stubs_and_options, options, :null_object) + extract_option(stubs_and_options, options, :__declared_as, 'Mock') + options + end + + def extract_option(source, target, key, default=nil) + if source[key] + target[key] = source.delete(key) + elsif default + target[key] = default + end + end + + def assign_stubs(stubs) + stubs.each_pair do |message, response| + stub!(message).and_return(response) + end + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/mocks/order_group.rb b/vendor/gems/rspec-1.3.1/lib/spec/mocks/order_group.rb new file mode 100644 index 000000000..9983207eb --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/mocks/order_group.rb @@ -0,0 +1,29 @@ +module Spec + module Mocks + class OrderGroup + def initialize error_generator + @error_generator = error_generator + @ordering = Array.new + end + + def register(expectation) + @ordering << expectation + end + + def ready_for?(expectation) + return @ordering.first == expectation + end + + def consume + @ordering.shift + end + + def handle_order_constraint expectation + return unless @ordering.include? expectation + return consume if ready_for?(expectation) + @error_generator.raise_out_of_order_error expectation.sym + end + + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/mocks/proxy.rb b/vendor/gems/rspec-1.3.1/lib/spec/mocks/proxy.rb new file mode 100644 index 000000000..6c29a9cdd --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/mocks/proxy.rb @@ -0,0 +1,268 @@ +module Spec + module Mocks + class Proxy + DEFAULT_OPTIONS = { + :null_object => false, + } + + @@warn_about_expectations_on_nil = true + + def self.allow_message_expectations_on_nil + @@warn_about_expectations_on_nil = false + + # ensure nil.rspec_verify is called even if an expectation is not set in the example + # otherwise the allowance would effect subsequent examples + $rspec_mocks.add(nil) unless $rspec_mocks.nil? + end + + def initialize(target, name=nil, options={}) + @target = target + @name = name + @error_generator = ErrorGenerator.new target, name, options + @expectation_ordering = OrderGroup.new @error_generator + @expectations = [] + @messages_received = [] + @stubs = [] + @proxied_methods = [] + @options = options ? DEFAULT_OPTIONS.dup.merge(options) : DEFAULT_OPTIONS + @already_proxied_respond_to = false + end + + def null_object? + @options[:null_object] + end + + def as_null_object + @options[:null_object] = true + @target + end + + def add_message_expectation(expected_from, sym, opts={}, &block) + __add sym + warn_if_nil_class sym + @expectations << build_expectation(expected_from, sym, opts, &block) + @expectations.last + end + + def build_expectation(expected_from, sym, opts, &block) + if stub = find_matching_method_stub(sym) + stub.build_child(expected_from, block_given?? block : nil, 1, opts) + else + MessageExpectation.new(@error_generator, @expectation_ordering, expected_from, sym, block_given? ? block : nil, 1, opts) + end + end + + def add_negative_message_expectation(expected_from, sym, &block) + __add sym + warn_if_nil_class sym + @expectations << NegativeMessageExpectation.new(@error_generator, @expectation_ordering, expected_from, sym, block_given? ? block : nil) + @expectations.last + end + + def add_stub(expected_from, sym, opts={}, &implementation) + __add sym + @stubs.unshift MessageExpectation.new(@error_generator, @expectation_ordering, expected_from, sym, nil, :any, opts, &implementation) + @stubs.first + end + + def remove_stub(message) + message = message.to_sym + if stub_to_remove = @stubs.detect { |s| s.matches_name?(message) } + reset_proxied_method(message) + @stubs.delete(stub_to_remove) + else + raise MockExpectationError, "The method `#{message}` was not stubbed or was already unstubbed" + end + end + + def verify #:nodoc: + verify_expectations + ensure + reset + end + + def reset + clear_expectations + clear_stubs + reset_proxied_methods + clear_proxied_methods + reset_nil_expectations_warning + end + + def received_message?(sym, *args, &block) + @messages_received.any? {|array| array == [sym, args, block]} + end + + def has_negative_expectation?(sym) + @expectations.any? {|expectation| expectation.negative_expectation_for?(sym)} + end + + def record_message_received(sym, args, block) + @messages_received << [sym, args, block] + end + + def message_received(sym, *args, &block) + expectation = find_matching_expectation(sym, *args) + stub = find_matching_method_stub(sym, *args) + + if ok_to_invoke_stub?(stub, expectation) + record_stub(stub, sym, args, &block) + elsif expectation + invoke_expectation(expectation, *args, &block) + elsif expectation = find_almost_matching_expectation(sym, *args) + record_almost_matching_expectation(expectation, sym, *args, &block) + elsif @target.is_a?(Class) + @target.superclass.send(sym, *args, &block) + else + @target.__send__ :method_missing, sym, *args, &block + end + end + + def record_stub(stub, sym, args, &block) + almost_matching_expectation(sym, *args) do |e| + e.advise(args, block) + end + stub.invoke(*args, &block) + end + + def invoke_expectation(expectation, *args, &block) + expectation.invoke(*args, &block) + end + + def record_almost_matching_expectation(expectation, sym, *args, &block) + expectation.advise(args, block) + unless (null_object? or has_negative_expectation?(sym)) + raise_unexpected_message_args_error(expectation, *args) + end + end + + def ok_to_invoke_stub?(stub, expectation) + stub && (!expectation || expectation.called_max_times?) + end + + def raise_unexpected_message_args_error(expectation, *args) + @error_generator.raise_unexpected_message_args_error expectation, *args + end + + def raise_unexpected_message_error(sym, *args) + @error_generator.raise_unexpected_message_error sym, *args + end + + def find_matching_method_stub(sym, *args) + @stubs.find {|stub| stub.matches(sym, args)} + end + + private + + def __add(sym) + $rspec_mocks.add(@target) unless $rspec_mocks.nil? + define_expected_method(sym) + end + + def warn_if_nil_class(sym) + if proxy_for_nil_class? & @@warn_about_expectations_on_nil + Kernel.warn("An expectation of :#{sym} was set on nil. Called from #{caller[2]}. Use allow_message_expectations_on_nil to disable warnings.") + end + end + + def define_expected_method(sym) + unless @proxied_methods.include?(sym) + visibility_string = "#{visibility(sym)} :#{sym}" + if target_responds_to?(sym) + munged_sym = munge(sym) + target_metaclass.instance_eval do + alias_method munged_sym, sym if method_defined?(sym) + end + @proxied_methods << sym + end + target_metaclass.class_eval(<<-EOF, __FILE__, __LINE__) + def #{sym}(*args, &block) + __mock_proxy.message_received :#{sym}, *args, &block + end + #{visibility_string} + EOF + end + end + + def target_responds_to?(sym) + return @target.__send__(munge(:respond_to?),sym) if @already_proxied_respond_to + return @already_proxied_respond_to = true if sym == :respond_to? + return @target.respond_to?(sym, true) + end + + def visibility(sym) + if Mock === @target + 'public' + elsif target_metaclass.private_method_defined?(sym) + 'private' + elsif target_metaclass.protected_method_defined?(sym) + 'protected' + else + 'public' + end + end + + def munge(sym) + "proxied_by_rspec__#{sym}" + end + + def clear_expectations + @expectations.clear + end + + def clear_stubs + @stubs.clear + end + + def clear_proxied_methods + @proxied_methods.clear + end + + def target_metaclass + class << @target; self; end + end + + def verify_expectations + @expectations.map {|e| e.verify_messages_received} + end + + def reset_proxied_methods + @proxied_methods.map {|sym| reset_proxied_method(sym)} + end + + def reset_proxied_method(sym) + munged_sym = munge(sym) + target_metaclass.instance_eval do + remove_method sym + if method_defined?(munged_sym) + alias_method sym, munged_sym + remove_method munged_sym + end + end + end + + def proxy_for_nil_class? + @target.nil? + end + + def reset_nil_expectations_warning + @@warn_about_expectations_on_nil = true if proxy_for_nil_class? + end + + def find_matching_expectation(sym, *args) + @expectations.find {|expectation| expectation.matches(sym, args) && !expectation.called_max_times?} || + @expectations.find {|expectation| expectation.matches(sym, args)} + end + + def almost_matching_expectation(sym, *args, &block) + if e = find_almost_matching_expectation(sym, *args) + yield e + end + end + + def find_almost_matching_expectation(sym, *args) + @expectations.find {|expectation| expectation.matches_name_but_not_args(sym, args)} + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/mocks/space.rb b/vendor/gems/rspec-1.3.1/lib/spec/mocks/space.rb new file mode 100644 index 000000000..3e13224c7 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/mocks/space.rb @@ -0,0 +1,28 @@ +module Spec + module Mocks + class Space + def add(obj) + mocks << obj unless mocks.detect {|m| m.equal? obj} + end + + def verify_all + mocks.each do |mock| + mock.rspec_verify + end + end + + def reset_all + mocks.each do |mock| + mock.rspec_reset + end + mocks.clear + end + + private + + def mocks + @mocks ||= [] + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/rake/spectask.rb b/vendor/gems/rspec-1.3.1/lib/spec/rake/spectask.rb new file mode 100644 index 000000000..9049fd08e --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/rake/spectask.rb @@ -0,0 +1,230 @@ +#!/usr/bin/env ruby + +# Define a task library for running RSpec contexts. + +require 'rake' +require 'rake/tasklib' + +module Spec + module Rake + + # A Rake task that runs a set of specs. + # + # Example: + # + # Spec::Rake::SpecTask.new do |t| + # t.warning = true + # t.rcov = true + # end + # + # This will create a task that can be run with: + # + # rake spec + # + # If rake is invoked with a "SPEC=filename" command line option, + # then the list of spec files will be overridden to include only the + # filename specified on the command line. This provides an easy way + # to run just one spec. + # + # If rake is invoked with a "SPEC_OPTS=options" command line option, + # then the given options will override the value of the +spec_opts+ + # attribute. + # + # If rake is invoked with a "RCOV_OPTS=options" command line option, + # then the given options will override the value of the +rcov_opts+ + # attribute. + # + # Examples: + # + # rake spec # run specs normally + # rake spec SPEC=just_one_file.rb # run just one spec file. + # rake spec SPEC_OPTS="--diff" # enable diffing + # rake spec RCOV_OPTS="--aggregate myfile.txt" # see rcov --help for details + # + # Each attribute of this task may be a proc. This allows for lazy evaluation, + # which is sometimes handy if you want to defer the evaluation of an attribute value + # until the task is run (as opposed to when it is defined). + # + # This task can also be used to run existing Test::Unit tests and get RSpec + # output, for example like this: + # + # require 'spec/rake/spectask' + # Spec::Rake::SpecTask.new do |t| + # t.ruby_opts = ['-rtest/unit'] + # t.spec_files = FileList['test/**/*_test.rb'] + # end + # + class SpecTask < ::Rake::TaskLib + def self.attr_accessor(*names) + super(*names) + names.each do |name| + module_eval "def #{name}() evaluate(@#{name}) end" # Allows use of procs + end + end + + # Name of spec task. (default is :spec) + attr_accessor :name + + # Array of directories to be added to $LOAD_PATH before running the + # specs. Defaults to ['<the absolute path to RSpec's lib directory>'] + attr_accessor :libs + + # If true, requests that the specs be run with the warning flag set. + # E.g. warning=true implies "ruby -w" used to run the specs. Defaults to false. + attr_accessor :warning + + # Glob pattern to match spec files. (default is 'spec/**/*_spec.rb') + # Setting the SPEC environment variable overrides this. + attr_accessor :pattern + + # Array of commandline options to pass to RSpec. Defaults to []. + # Setting the SPEC_OPTS environment variable overrides this. + attr_accessor :spec_opts + + # Whether or not to use RCov (default is false) + # See http://eigenclass.org/hiki.rb?rcov + attr_accessor :rcov + + # Array of commandline options to pass to RCov. Defaults to ['--exclude', 'lib\/spec,bin\/spec']. + # Ignored if rcov=false + # Setting the RCOV_OPTS environment variable overrides this. + attr_accessor :rcov_opts + + # Directory where the RCov report is written. Defaults to "coverage" + # Ignored if rcov=false + attr_accessor :rcov_dir + + # Array of commandline options to pass to ruby. Defaults to []. + attr_accessor :ruby_opts + + # Whether or not to fail Rake when an error occurs (typically when specs fail). + # Defaults to true. + attr_accessor :fail_on_error + + # A message to print to stderr when there are failures. + attr_accessor :failure_message + + # Where RSpec's output is written. Defaults to $stdout. + # DEPRECATED. Use --format FORMAT:WHERE in spec_opts. + attr_accessor :out + + # Explicitly define the list of spec files to be included in a + # spec. +spec_files+ is expected to be an array of file names (a + # FileList is acceptable). If both +pattern+ and +spec_files+ are + # used, then the list of spec files is the union of the two. + # Setting the SPEC environment variable overrides this. + attr_accessor :spec_files + + # Use verbose output. If this is set to true, the task will print + # the executed spec command to stdout. Defaults to false. + attr_accessor :verbose + + # Explicitly define the path to the ruby binary, or its proxy (e.g. multiruby) + attr_accessor :ruby_cmd + + # Defines a new task, using the name +name+. + def initialize(name=:spec) + @name = name + @libs = ['lib'] + @pattern = nil + @spec_files = nil + @spec_opts = [] + @warning = false + @ruby_opts = [] + @fail_on_error = true + @rcov = false + @rcov_opts = ['--exclude', 'lib\/spec,bin\/spec,config\/boot.rb'] + @rcov_dir = "coverage" + + yield self if block_given? + @pattern = 'spec/**/*_spec.rb' if pattern.nil? && spec_files.nil? + define + end + + def define # :nodoc: + spec_script = File.expand_path(File.join(File.dirname(__FILE__),"..","..","..","bin","spec")) + + lib_path = libs.join(File::PATH_SEPARATOR) + actual_name = Hash === name ? name.keys.first : name + unless ::Rake.application.last_comment + desc "Run specs" + (rcov ? " using RCov" : "") + end + task name do + RakeFileUtils.verbose(verbose) do + unless spec_file_list.empty? + # ruby [ruby_opts] -Ilib -S rcov [rcov_opts] bin/spec -- examples [spec_opts] + # or + # ruby [ruby_opts] -Ilib bin/spec examples [spec_opts] + cmd_parts = [ruby_cmd || RUBY] + cmd_parts += ruby_opts + cmd_parts << %[-I"#{lib_path}"] + cmd_parts << "-S rcov" if rcov + cmd_parts << "-w" if warning + cmd_parts << rcov_option_list + cmd_parts << %[-o "#{rcov_dir}"] if rcov + cmd_parts << %["#{spec_script}"] + cmd_parts << "--" if rcov + cmd_parts += spec_file_list.collect { |fn| %["#{fn}"] } + cmd_parts << spec_option_list + if out + cmd_parts << %[> "#{out}"] + STDERR.puts "The Spec::Rake::SpecTask#out attribute is DEPRECATED and will be removed in a future version. Use --format FORMAT:WHERE instead." + end + cmd = cmd_parts.join(" ") + puts cmd if verbose + unless system(cmd) + STDERR.puts failure_message if failure_message + raise("Command #{cmd} failed") if fail_on_error + end + end + end + end + + if rcov + desc "Remove rcov products for #{actual_name}" + task paste("clobber_", actual_name) do + rm_r rcov_dir rescue nil + end + + clobber_task = paste("clobber_", actual_name) + task :clobber => [clobber_task] + + task actual_name => clobber_task + end + self + end + + def rcov_option_list # :nodoc: + if rcov + ENV['RCOV_OPTS'] || rcov_opts.join(" ") || "" + else + "" + end + end + + def spec_option_list # :nodoc: + STDERR.puts "RSPECOPTS is DEPRECATED and will be removed in a future version. Use SPEC_OPTS instead." if ENV['RSPECOPTS'] + ENV['SPEC_OPTS'] || ENV['RSPECOPTS'] || spec_opts.join(" ") || "" + end + + def evaluate(o) # :nodoc: + case o + when Proc then o.call + else o + end + end + + def spec_file_list # :nodoc: + if ENV['SPEC'] + FileList[ ENV['SPEC'] ] + else + result = [] + result += spec_files.to_a if spec_files + result += FileList[ pattern ].to_a if pattern + FileList[result] + end + end + + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/rake/verify_rcov.rb b/vendor/gems/rspec-1.3.1/lib/spec/rake/verify_rcov.rb new file mode 100644 index 000000000..199bd8546 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/rake/verify_rcov.rb @@ -0,0 +1,52 @@ +module RCov + # A task that can verify that the RCov coverage doesn't + # drop below a certain threshold. It should be run after + # running Spec::Rake::SpecTask. + class VerifyTask < Rake::TaskLib + # Name of the task. Defaults to :verify_rcov + attr_accessor :name + + # Path to the index.html file generated by RCov, which + # is the file containing the total coverage. + # Defaults to 'coverage/index.html' + attr_accessor :index_html + + # Whether or not to output details. Defaults to true. + attr_accessor :verbose + + # The threshold value (in percent) for coverage. If the + # actual coverage is not equal to this value, the task will raise an + # exception. + attr_accessor :threshold + + # Require the threshold value be met exactly. This is the default. + attr_accessor :require_exact_threshold + + def initialize(name=:verify_rcov) + @name = name + @index_html = 'coverage/index.html' + @verbose = true + @require_exact_threshold = true + yield self if block_given? + raise "Threshold must be set" if @threshold.nil? + define + end + + def define + desc "Verify that rcov coverage is at least #{threshold}%" + task @name do + total_coverage = 0 + + File.open(index_html).each_line do |line| + if line =~ /<tt class='coverage_total'>\s*(\d+\.\d+)%\s*<\/tt>/ + total_coverage = $1.to_f + break + end + end + puts "Coverage: #{total_coverage}% (threshold: #{threshold}%)" if verbose + raise "Coverage must be at least #{threshold}% but was #{total_coverage}%" if total_coverage < threshold + raise "Coverage has increased above the threshold of #{threshold}% to #{total_coverage}%. You should update your threshold value." if (total_coverage > threshold) and require_exact_threshold + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/ruby.rb b/vendor/gems/rspec-1.3.1/lib/spec/ruby.rb new file mode 100644 index 000000000..863877c7f --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/ruby.rb @@ -0,0 +1,9 @@ +module Spec + module Ruby + class << self + def version + RUBY_VERSION + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/runner.rb b/vendor/gems/rspec-1.3.1/lib/spec/runner.rb new file mode 100644 index 000000000..519b536e2 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/runner.rb @@ -0,0 +1,66 @@ +require 'spec/runner/configuration' +require 'spec/runner/options' +require 'spec/runner/option_parser' +require 'spec/runner/example_group_runner' +require 'spec/runner/command_line' +require 'spec/runner/drb_command_line' +require 'spec/runner/backtrace_tweaker' +require 'spec/runner/reporter' +require 'spec/runner/line_number_query' +require 'spec/runner/class_and_arguments_parser' +require 'spec/runner/extensions/kernel' + +module Spec + module Runner + + class ExampleGroupCreationListener + def register_example_group(klass) + Spec::Runner.options.add_example_group klass + end + end + + Spec::Example::ExampleGroupFactory.example_group_creation_listeners << ExampleGroupCreationListener.new + + class << self + def configuration # :nodoc: + @configuration ||= Spec::Runner::Configuration.new + end + + # Use this to configure various configurable aspects of + # RSpec: + # + # Spec::Runner.configure do |configuration| + # # Configure RSpec here + # end + # + # The yielded <tt>configuration</tt> object is a + # Spec::Runner::Configuration instance. See its RDoc + # for details about what you can do with it. + # + def configure + yield configuration + end + + def autorun # :nodoc: + at_exit {exit run unless $!} + end + + def options # :nodoc: + @options ||= begin + parser = ::Spec::Runner::OptionParser.new($stderr, $stdout) + parser.order!(ARGV) + parser.options + end + end + + def use options + @options = options + end + + def run + options.examples_run? || options.run_examples + end + + end + end +end
\ No newline at end of file diff --git a/vendor/gems/rspec-1.3.1/lib/spec/runner/backtrace_tweaker.rb b/vendor/gems/rspec-1.3.1/lib/spec/runner/backtrace_tweaker.rb new file mode 100644 index 000000000..5f19171bf --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/runner/backtrace_tweaker.rb @@ -0,0 +1,78 @@ +module Spec + module Runner + class BacktraceTweaker + def initialize(*patterns) + @ignore_patterns = [] + end + + def clean_up_double_slashes(line) + line.gsub!('//','/') + end + + def ignore_patterns(*patterns) + # do nothing. Only QuietBacktraceTweaker ignores patterns. + end + + def ignored_patterns + [] + end + + def tweak_backtrace(error) + return if error.backtrace.nil? + tweaked = error.backtrace.collect do |message| + clean_up_double_slashes(message) + kept_lines = message.split("\n").select do |line| + ignored_patterns.each do |ignore| + break if line =~ ignore + end + end + kept_lines.empty?? nil : kept_lines.join("\n") + end + error.set_backtrace(tweaked.select {|line| line}) + end + end + + class NoisyBacktraceTweaker < BacktraceTweaker + end + + # Tweaks raised Exceptions to mask noisy (unneeded) parts of the backtrace + class QuietBacktraceTweaker < BacktraceTweaker + unless defined?(IGNORE_PATTERNS) + root_dir = File.expand_path(File.join(__FILE__, '..', '..', '..', '..')) + spec_files = Dir["#{root_dir}/lib/*"].map do |path| + subpath = path[root_dir.length..-1] + /#{subpath}/ + end + IGNORE_PATTERNS = spec_files + [ + /\/rspec-[^\/]*\/lib\/spec\//, + /\/spork-[^\/]*\/lib\/spork\//, + /\/lib\/ruby\//, + /bin\/spec:/, + /bin\/spork:/, + /bin\/rcov:/, + /lib\/rspec-rails/, + /vendor\/rails/, + # TextMate's Ruby and RSpec plugins + /Ruby\.tmbundle\/Support\/tmruby.rb:/, + /RSpec\.tmbundle\/Support\/lib/, + /temp_textmate\./, + /mock_frameworks\/rspec/, + /spec_server/ + ] + end + + def initialize(*patterns) + super + ignore_patterns(*patterns) + end + + def ignore_patterns(*patterns) + @ignore_patterns += patterns.flatten.map { |pattern| Regexp.new(pattern) } + end + + def ignored_patterns + IGNORE_PATTERNS + @ignore_patterns + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/runner/class_and_arguments_parser.rb b/vendor/gems/rspec-1.3.1/lib/spec/runner/class_and_arguments_parser.rb new file mode 100644 index 000000000..a49ade26e --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/runner/class_and_arguments_parser.rb @@ -0,0 +1,14 @@ +module Spec + module Runner + class ClassAndArgumentsParser + def self.parse(s) + if s =~ /([a-zA-Z_]+(?:::[a-zA-Z_]+)*):?(.*)/ + arg = $2 == "" ? nil : $2 + [$1, arg] + else + raise "Couldn't parse #{s.inspect}" + end + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/runner/command_line.rb b/vendor/gems/rspec-1.3.1/lib/spec/runner/command_line.rb new file mode 100644 index 000000000..35a7e3159 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/runner/command_line.rb @@ -0,0 +1,15 @@ +require 'spec/runner/option_parser' + +module Spec + module Runner + class CommandLine + def self.run(tmp_options=Spec::Runner.options) + orig_options = Spec::Runner.options + Spec::Runner.use tmp_options + tmp_options.run_examples + ensure + Spec::Runner.use orig_options + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/runner/configuration.rb b/vendor/gems/rspec-1.3.1/lib/spec/runner/configuration.rb new file mode 100644 index 000000000..19db52435 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/runner/configuration.rb @@ -0,0 +1,202 @@ +module Spec + module Runner + class Configuration + include Spec::Example::ArgsAndOptions + + # Chooses what mock framework to use. Example: + # + # Spec::Runner.configure do |config| + # config.mock_with :rspec, :mocha, :flexmock, or :rr + # end + # + # To use any other mock framework, you'll have to provide your own + # adapter. This is simply a module that responds to the following + # methods: + # + # setup_mocks_for_rspec + # verify_mocks_for_rspec + # teardown_mocks_for_rspec. + # + # These are your hooks into the lifecycle of a given example. RSpec will + # call setup_mocks_for_rspec before running anything else in each + # Example. After executing the #after methods, RSpec will then call + # verify_mocks_for_rspec and teardown_mocks_for_rspec (this is + # guaranteed to run even if there are failures in + # verify_mocks_for_rspec). + # + # Once you've defined this module, you can pass that to mock_with: + # + # Spec::Runner.configure do |config| + # config.mock_with MyMockFrameworkAdapter + # end + # + def mock_with(mock_framework) + @mock_framework = case mock_framework + when Symbol + mock_framework_path(mock_framework.to_s) + else + mock_framework + end + end + + def mock_framework # :nodoc: + @mock_framework ||= mock_framework_path("rspec") + end + + # :call-seq: + # include(Some::Helpers) + # include(Some::Helpers, More::Helpers) + # include(My::Helpers, :type => :key) + # + # Declares modules to be included in multiple example groups + # (<tt>describe</tt> blocks). With no <tt>:type</tt>, the modules listed + # will be included in all example groups. + # + # Use <tt>:type</tt> to restrict + # the inclusion to a subset of example groups. The value assigned to + # <tt>:type</tt> should be a key that maps to a class that is either a + # subclass of Spec::Example::ExampleGroup or extends + # Spec::Example::ExampleGroupMethods and includes + # Spec::Example::ExampleMethods. + # + # For example, the rspec-rails gem/plugin extends Test::Unit::TestCase + # with Spec::Example::ExampleGroupMethods and includes + # Spec::Example::ExampleMethods in it. So if you have a module of helper + # methods for controller examples, you could do this: + # + # config.include(ControllerExampleHelpers, :type => :controller) + # + # Only example groups that have that type will get the modules included: + # + # describe Account, :type => :model do + # # Will *not* include ControllerExampleHelpers + # end + # + # describe AccountsController, :type => :controller do + # # *Will* include ControllerExampleHelpers + # end + # + def include(*modules_and_options) + include_or_extend(:include, *modules_and_options) + end + + # :call-seq: + # extend(Some::Helpers) + # extend(Some::Helpers, More::Helpers) + # extend(My::Helpers, :type => :key) + # + # Works just like #include, but extends the example groups + # with the modules rather than including them. + def extend(*modules_and_options) + include_or_extend(:extend, *modules_and_options) + end + + # Appends a global <tt>before</tt> block to all example groups. + # <tt>scope</tt> can be any of <tt>:each</tt> (default), <tt>:all</tt>, or + # <tt>:suite</tt>. When <tt>:each</tt>, the block is executed before each + # example. When <tt>:all</tt>, the block is executed once per example + # group, before any of its examples are run. When <tt>:suite</tt> the + # block is run once before the entire suite is run. + def append_before(scope = :each, options={}, &proc) + add_callback(:append_before, scope, options, &proc) + end + alias_method :before, :append_before + + # Prepends a global <tt>before</tt> block to all example groups. + # + # See <tt>append_before</tt> for scoping semantics. + def prepend_before(scope = :each, options={}, &proc) + add_callback(:prepend_before, scope, options, &proc) + end + + # Prepends a global <tt>after</tt> block to all example groups. + # + # See <tt>append_before</tt> for scoping semantics. + def prepend_after(scope = :each, options={}, &proc) + add_callback(:prepend_after, scope, options, &proc) + end + alias_method :after, :prepend_after + + # Appends a global <tt>after</tt> block to all example groups. + # + # See <tt>append_before</tt> for scoping semantics. + def append_after(scope = :each, options={}, &proc) + add_callback(:append_after, scope, options, &proc) + end + + # DEPRECATED - use Spec::Matchers::DSL instead + # + # Defines global predicate matchers. Example: + # + # config.predicate_matchers[:swim] = :can_swim? + # + # This makes it possible to say: + # + # person.should swim # passes if person.can_swim? returns true + # + def predicate_matchers + @predicate_matchers ||= Spec::HashWithDeprecationNotice.new("predicate_matchers", "the new Matcher DSL") + end + + # Adds patterns to the list of patterns ignored in the backtrace when a + # failure is output by rspec. Example: + # + # config.ignore_backtrace_patterns /spork/, /shoulda/, "/some/weird/path/" + # + # When quiet backtraces are turned on (default), this will exclude any + # lines that match any of the Regexps and Strings passed. + # + def ignore_backtrace_patterns(*patterns) + @ignored_backtrace_patterns ||= [] + @ignored_backtrace_patterns += patterns + end + + def ignored_backtrace_patterns # :nodoc: + @ignored_backtrace_patterns ||= [] + end + + def suppress_deprecation_warnings! + @suppress_deprecation_warnings = true + end + + def suppress_deprecation_warnings? + @suppress_deprecation_warnings ||= false + end + + private + + def include_or_extend(action, *args) + modules, options = args_and_options(*args) + [get_type_from_options(options)].flatten.each do |required_example_group| + required_example_group = required_example_group.to_sym if required_example_group + modules.each do |mod| + Spec::Example::ExampleGroupFactory[required_example_group].__send__(action, mod) + end + end + end + + def add_callback(sym, *args, &proc) + scope, options = scope_and_options(*args) + example_group = Spec::Example::ExampleGroupFactory[get_type_from_options(options)] + example_group.__send__(sym, scope, &proc) + end + + def get_type_from_options(options) + options[:type] || options[:behaviour_type] + end + + def mock_framework_path(framework_name) + "spec/adapters/mock_frameworks/#{framework_name}" + end + + def scope_and_options(*args) # :nodoc: + args, options = args_and_options(*args) + return scope_from(*args), options + end + + def scope_from(*args) # :nodoc: + args[0] || :each + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/runner/differs/default.rb b/vendor/gems/rspec-1.3.1/lib/spec/runner/differs/default.rb new file mode 100644 index 000000000..3a05da9d1 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/runner/differs/default.rb @@ -0,0 +1,93 @@ +require 'spec/runner/differs/load-diff-lcs' +require 'pp' + +module Spec + module Expectations + module Differs + unless defined?(Spec::Expectations::Differs::Default) + class Default + def initialize(options) + @options = options + end + + # This is snagged from diff/lcs/ldiff.rb (which is a commandline tool) + def diff_as_string(data_new, data_old) + data_old = data_old.split(/\n/).map! { |e| e.chomp } + data_new = data_new.split(/\n/).map! { |e| e.chomp } + output = "" + diffs = Diff::LCS.diff(data_old, data_new) + return output if diffs.empty? + oldhunk = hunk = nil + file_length_difference = 0 + diffs.each do |piece| + begin + hunk = Diff::LCS::Hunk.new(data_old, data_new, piece, context_lines, + file_length_difference) + file_length_difference = hunk.file_length_difference + next unless oldhunk + # Hunks may overlap, which is why we need to be careful when our + # diff includes lines of context. Otherwise, we might print + # redundant lines. + if (context_lines > 0) and hunk.overlaps?(oldhunk) + hunk.unshift(oldhunk) + else + output << oldhunk.diff(format) + end + ensure + oldhunk = hunk + output << "\n" + end + end + #Handle the last remaining hunk + output << oldhunk.diff(format) << "\n" + end + + def diff_as_object(target,expected) + diff_as_string(PP.pp(target,""), PP.pp(expected,"")) + end + + def diff_as_hash(target, expected) + contains_hash = false + contains_array = false + + extra_expected_keys = expected.keys - target.keys + extra_target_keys = target.keys - expected.keys + + o = "\n" + + o << "Expected hash contains keys that target hash does not: " << extra_expected_keys.inspect << "\n" if !extra_expected_keys.empty? + o << "Target hash contains keys that expected hash does not: " << extra_target_keys.inspect << "\n" if !extra_target_keys.empty? + + expected.delete_if do |key, value| + contains_hash = true if value.is_a?(Hash) + contains_array = true if value.is_a?(Array) + target[key] == value + end + + expected.keys.sort { |a,b| a.to_s <=> b.to_s }.each do |key| + o << "Expected the key #{key.inspect} to be #{expected[key].inspect}, but was #{target[key].inspect}\n" + end + + o << "\n" + + if contains_hash || contains_array + o << diff_as_object(target, expected) + else + o + end + end + + protected + def format + @options.diff_format + end + + def context_lines + @options.context_lines + end + end + + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/runner/differs/load-diff-lcs.rb b/vendor/gems/rspec-1.3.1/lib/spec/runner/differs/load-diff-lcs.rb new file mode 100644 index 000000000..f708bc9b4 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/runner/differs/load-diff-lcs.rb @@ -0,0 +1,12 @@ +begin + require 'diff/lcs' +rescue LoadError + begin + require 'rubygems' unless ENV['NO_RUBYGEMS'] + require 'diff/lcs' + rescue LoadError + raise "You must gem install diff-lcs to use diffing" + end +end + +require 'diff/lcs/hunk' diff --git a/vendor/gems/rspec-1.3.1/lib/spec/runner/drb_command_line.rb b/vendor/gems/rspec-1.3.1/lib/spec/runner/drb_command_line.rb new file mode 100644 index 000000000..cbc0f2d9a --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/runner/drb_command_line.rb @@ -0,0 +1,32 @@ +require "drb/drb" + +module Spec + module Runner + # Facade to run specs by connecting to a DRB server + class DrbCommandLine + + def self.port(options) + (options.drb_port || ENV["RSPEC_DRB"] || 8989).to_i + end + + # Runs specs on a DRB server. Note that this API is similar to that of + # CommandLine - making it possible for clients to use both interchangeably. + def self.run(options) + begin + begin; \ + DRb.start_service("druby://localhost:0"); \ + rescue SocketError, Errno::EADDRNOTAVAIL; \ + DRb.start_service("druby://:0"); \ + end + spec_server = DRbObject.new_with_uri("druby://127.0.0.1:#{port(options)}") + spec_server.run(options.argv, options.error_stream, options.output_stream) + true + rescue DRb::DRbConnError + options.error_stream.puts "No server is running" + false + end + end + + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/runner/example_group_runner.rb b/vendor/gems/rspec-1.3.1/lib/spec/runner/example_group_runner.rb new file mode 100644 index 000000000..4de043f08 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/runner/example_group_runner.rb @@ -0,0 +1,58 @@ +module Spec + module Runner + class ExampleGroupRunner + def initialize(options) + @options = options + end + + def load_files(files) + $KCODE = 'u' if RUBY_VERSION.to_f < 1.9 + # It's important that loading files (or choosing not to) stays the + # responsibility of the ExampleGroupRunner. Some implementations (like) + # the one using DRb may choose *not* to load files, but instead tell + # someone else to do it over the wire. + files.each do |file| + load file + end + end + + def run + prepare + success = true + example_groups.each do |example_group| + success = success & example_group.run(@options) + end + finish + success + end + + protected + + def prepare + reporter.start(number_of_examples) + example_groups.reverse! if reverse + end + + def finish + reporter.end + reporter.dump + end + + def reporter + @options.reporter + end + + def reverse + @options.reverse + end + + def example_groups + @options.example_groups + end + + def number_of_examples + @options.number_of_examples + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/runner/extensions/kernel.rb b/vendor/gems/rspec-1.3.1/lib/spec/runner/extensions/kernel.rb new file mode 100644 index 000000000..4e23cdf22 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/runner/extensions/kernel.rb @@ -0,0 +1,9 @@ +module Kernel + unless respond_to?(:debugger) + # Start a debugging session if ruby-debug is loaded with the -u/--debugger option + def debugger(steps=1) + # If not then just comment and proceed + $stderr.puts "debugger statement ignored, use -u or --debugger option on rspec to enable debugging" + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/base_formatter.rb b/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/base_formatter.rb new file mode 100644 index 000000000..0fbc12ce4 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/base_formatter.rb @@ -0,0 +1,139 @@ +module Spec + module Runner + module Formatter + # Formatter base-class, which implements all required methods as no-ops, with the exception + class BaseFormatter + # Formatters are initialized with <tt>options</tt> and <tt>output</tt> + # arguments. RSpec's built-in formatters already expect this, and any + # custom formatters should as well. + # + # ==== Parameters + # options:: + # A struct containing boolean values for colour, autospec, + # and dry_run + # output:: + # Used by RSpec's built-in formatters to determine where to + # write the output. Default is <tt>STDOUT</tt>, otherwise a + # filename is expected. + # + # === Example + # If you invoke the <tt>spec</tt> command with: + # + # --format progress:progress_report.txt + # + # ... the value of <tt>output</tt> will be progress_report.txt. If you + # don't identify an output destination, the default is STDOUT. + def initialize(options, output) + end + + # This method is invoked before any examples are run, right after + # they have all been collected. This can be useful for special + # formatters that need to provide progress on feedback (graphical ones) + # + # This method will only be invoked once, and the next one to be invoked + # is #example_group_started + # + # ==== Parameters + # example_count:: the total number of examples to be run + def start(example_count) + end + + # This method is invoked at the beginning of the execution of each + # example_group. The next method to be invoked after this is + # #example_started + # + # ==== Parameters + # example_group_proxy:: instance of Spec::Example::ExampleGroupProxy + def example_group_started(example_group_proxy) + end + + # Deprecated - use example_group_started instead + def add_example_group(example_group_proxy) + Spec.deprecate("BaseFormatter#add_example_group", "BaseFormatter#example_group_started") + example_group_started(example_group_proxy) + end + + # This method is invoked when an +example+ starts. The next method to be + # invoked after this is #example_passed, #example_failed, or + # #example_pending + # + # ==== Parameters + # example_proxy:: instance of Spec::Example::ExampleProxy + def example_started(example_proxy) + end + + # This method is invoked when an +example+ passes. + # +example_proxy+ is the same instance of Spec::Example::ExampleProxy + # that was passed to example_started + # + # ==== Parameters + # example_proxy:: instance of Spec::Example::ExampleProxy + def example_passed(example_proxy) + end + + # This method is invoked when an +example+ fails, i.e. an exception occurred + # inside it (such as a failed should or other exception). + # + # ==== Parameters + # example_proxy:: + # The same instance of Spec::Example::ExampleProxy that was passed + # to <tt>example_started</tt> + # + # counter:: the sequential number of this failure + # + # failure:: instance of Spec::Runner::Reporter::Failure + def example_failed(example_proxy, counter, failure) + end + + # This method is invoked when an example is not yet implemented (i.e. has not + # been provided a block), or when an ExamplePendingError is raised. + # +message+ is the message from the ExamplePendingError, if it exists, or the + # default value of "Not Yet Implemented". +deprecated_pending_location+ is + # deprecated - use example_proxy.location instead + # + # ==== Parameters + # example_proxy:: instance of Spec::Example::ExampleProxy + # message:: + # the message passed to the pending message, or an internal + # default + # + def example_pending(example_proxy, message, deprecated_pending_location=nil) + end + + # This method is invoked after all of the examples have executed. The next method + # to be invoked after this one is #dump_failure (once for each failed example) + def start_dump + end + + # Dumps detailed information about an example failure. + # This method is invoked for each failed example after all examples have run. +counter+ is the sequence number + # of the associated example. +failure+ is a Failure object, which contains detailed + # information about the failure. + # + # ==== Parameters + # counter:: the sequential number of this failure + # failure:: instance of Spec::Runner::Reporter::Failure + def dump_failure(counter, failure) + end + + # This method is invoked after the dumping of examples and failures. + # + # ==== Parameters + # duration:: the total time for the entire run + # example_count:: the number of examples run + # failure_count:: the number of examples that failed + # pending_count:: the number of examples that are pending + def dump_summary(duration, example_count, failure_count, pending_count) + end + + # This gets invoked after the summary + def dump_pending + end + + # This method is invoked at the very end. Allows the formatter to clean up, like closing open streams. + def close + end + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/base_text_formatter.rb b/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/base_text_formatter.rb new file mode 100644 index 000000000..ee8db75a4 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/base_text_formatter.rb @@ -0,0 +1,142 @@ +require 'spec/runner/formatter/base_formatter' +require 'fileutils' + +module Spec + module Runner + module Formatter + # Baseclass for text-based formatters. Can in fact be used for + # non-text based ones too - just ignore the +output+ constructor + # argument. + class BaseTextFormatter < BaseFormatter + attr_reader :output, :example_group + # Creates a new instance that will write to +output+. If +output+ is a + # String, output will be written to the File with that name, otherwise + # +output+ is exected to be an IO (or an object that responds to #puts + # and #write). + def initialize(options, output) + @options = options + if String === output + FileUtils.mkdir_p(File.dirname(output)) + @output = File.open(output, 'w') + else + @output = output + end + @pending_examples = [] + end + + def example_group_started(example_group_proxy) + @example_group = example_group_proxy + end + + def example_pending(example, message, deprecated_pending_location=nil) + @pending_examples << ["#{@example_group.description} #{example.description}", message, example.location] + end + + def dump_failure(counter, failure) + @output.puts + @output.puts "#{counter.to_s})" + @output.puts colorize_failure("#{failure.header}\n#{failure.exception.message}", failure) + @output.puts format_backtrace(failure.exception.backtrace) + @output.flush + end + + def colorize_failure(message, failure) + failure.pending_fixed? ? blue(message) : red(message) + end + + def colourise(message, failure) + Spec::deprecate("BaseTextFormatter#colourise", "colorize_failure") + colorize_failure(message, failure) + end + + def dump_summary(duration, example_count, failure_count, pending_count) + return if dry_run? + @output.puts + @output.puts "Finished in #{duration} seconds" + @output.puts + + summary = "#{example_count} example#{'s' unless example_count == 1}, #{failure_count} failure#{'s' unless failure_count == 1}" + summary << ", #{pending_count} pending" if pending_count > 0 + + if failure_count == 0 + if pending_count > 0 + @output.puts yellow(summary) + else + @output.puts green(summary) + end + else + @output.puts red(summary) + end + @output.flush + end + + def dump_pending + unless @pending_examples.empty? + @output.puts + @output.puts "Pending:" + @pending_examples.each do |pending_example| + @output.puts "\n#{pending_example[0]} (#{pending_example[1]})" + @output.puts "#{pending_example[2]}\n" + end + end + @output.flush + end + + def close + @output.close if (IO === @output) & (@output != $stdout) + end + + def format_backtrace(backtrace) + return "" if backtrace.nil? + backtrace.map { |line| backtrace_line(line) }.join("\n") + end + + protected + + def colour? + !!@options.colour + end + + def dry_run? + !!@options.dry_run + end + + def autospec? + !!@options.autospec || ENV.has_key?("AUTOTEST") + end + + def backtrace_line(line) + line.sub(/\A([^:]+:\d+)$/, '\\1:') + end + + def colour(text, colour_code) + return text if output_to_file? + return text unless ENV['RSPEC_COLOR'] || (colour? & (autospec? || output_to_tty?)) + "#{colour_code}#{text}\e[0m" + end + + def output_to_file? + File === @output + end + + def output_to_tty? + begin + @output.tty? + rescue NoMethodError + false + end + end + + def green(text); colour(text, "\e[32m"); end + def red(text); colour(text, "\e[31m"); end + def yellow(text); colour(text, "\e[33m"); end + def blue(text); colour(text, "\e[34m"); end + + def magenta(text) + Spec::deprecate("BaseTextFormatter#magenta") + red(text) + end + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/failing_example_groups_formatter.rb b/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/failing_example_groups_formatter.rb new file mode 100644 index 000000000..31729438b --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/failing_example_groups_formatter.rb @@ -0,0 +1,25 @@ +require 'spec/runner/formatter/base_text_formatter' + +module Spec + module Runner + module Formatter + class FailingExampleGroupsFormatter < BaseTextFormatter + def example_failed(example, counter, failure) + if @example_group + @output.puts @example_group.description.gsub(/ \(druby.*\)/,"") + + @output.flush + @example_group = nil + end + end + + def dump_failure(counter, failure) + end + + def dump_summary(duration, example_count, failure_count, pending_count) + end + + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/failing_examples_formatter.rb b/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/failing_examples_formatter.rb new file mode 100644 index 000000000..e3a271c8b --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/failing_examples_formatter.rb @@ -0,0 +1,20 @@ +require 'spec/runner/formatter/base_text_formatter' + +module Spec + module Runner + module Formatter + class FailingExamplesFormatter < BaseTextFormatter + def example_failed(example, counter, failure) + @output.puts "#{example_group.description} #{example.description}" + @output.flush + end + + def dump_failure(counter, failure) + end + + def dump_summary(duration, example_count, failure_count, pending_count) + end + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/html_formatter.rb b/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/html_formatter.rb new file mode 100644 index 000000000..2d0c65d1b --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/html_formatter.rb @@ -0,0 +1,338 @@ +require 'erb' +require 'spec/runner/formatter/base_text_formatter' +require 'spec/runner/formatter/no_op_method_missing' + +module Spec + module Runner + module Formatter + class HtmlFormatter < BaseTextFormatter + include ERB::Util # for the #h method + include NOOPMethodMissing + + def initialize(options, output) + super + @example_group_number = 0 + @example_number = 0 + @header_red = nil + end + + # The number of the currently running example_group + def example_group_number + @example_group_number + end + + # The number of the currently running example (a global counter) + def example_number + @example_number + end + + def start(example_count) + @example_count = example_count + + @output.puts html_header + @output.puts report_header + @output.flush + end + + def example_group_started(example_group) + super + @example_group_red = false + @example_group_number += 1 + unless example_group_number == 1 + @output.puts " </dl>" + @output.puts "</div>" + end + @output.puts "<div class=\"example_group\">" + @output.puts " <dl>" + @output.puts " <dt id=\"example_group_#{example_group_number}\">#{h(example_group.description)}</dt>" + @output.flush + end + + def start_dump + @output.puts " </dl>" + @output.puts "</div>" + @output.flush + end + + def example_started(example) + @example_number += 1 + end + + def example_passed(example) + move_progress + @output.puts " <dd class=\"spec passed\"><span class=\"passed_spec_name\">#{h(example.description)}</span></dd>" + @output.flush + end + + def example_failed(example, counter, failure) + extra = extra_failure_content(failure) + failure_style = failure.pending_fixed? ? 'pending_fixed' : 'failed' + @output.puts " <script type=\"text/javascript\">makeRed('rspec-header');</script>" unless @header_red + @header_red = true + @output.puts " <script type=\"text/javascript\">makeRed('example_group_#{example_group_number}');</script>" unless @example_group_red + @example_group_red = true + move_progress + @output.puts " <dd class=\"spec #{failure_style}\">" + @output.puts " <span class=\"failed_spec_name\">#{h(example.description)}</span>" + @output.puts " <div class=\"failure\" id=\"failure_#{counter}\">" + @output.puts " <div class=\"message\"><pre>#{h(failure.exception.message)}</pre></div>" unless failure.exception.nil? + @output.puts " <div class=\"backtrace\"><pre>#{format_backtrace(failure.exception.backtrace)}</pre></div>" unless failure.exception.nil? + @output.puts extra unless extra == "" + @output.puts " </div>" + @output.puts " </dd>" + @output.flush + end + + def example_pending(example, message, deprecated_pending_location=nil) + @output.puts " <script type=\"text/javascript\">makeYellow('rspec-header');</script>" unless @header_red + @output.puts " <script type=\"text/javascript\">makeYellow('example_group_#{example_group_number}');</script>" unless @example_group_red + move_progress + @output.puts " <dd class=\"spec not_implemented\"><span class=\"not_implemented_spec_name\">#{h(example.description)} (PENDING: #{h(message)})</span></dd>" + @output.flush + end + + # Override this method if you wish to output extra HTML for a failed spec. For example, you + # could output links to images or other files produced during the specs. + # + def extra_failure_content(failure) + require 'spec/runner/formatter/snippet_extractor' + @snippet_extractor ||= SnippetExtractor.new + " <pre class=\"ruby\"><code>#{@snippet_extractor.snippet(failure.exception)}</code></pre>" + end + + def move_progress + @output.puts " <script type=\"text/javascript\">moveProgressBar('#{percent_done}');</script>" + @output.flush + end + + def percent_done + result = 100.0 + if @example_count != 0 + result = ((example_number).to_f / @example_count.to_f * 1000).to_i / 10.0 + end + result + end + + def dump_failure(counter, failure) + end + + def dump_summary(duration, example_count, failure_count, pending_count) + if dry_run? + totals = "This was a dry-run" + else + totals = "#{example_count} example#{'s' unless example_count == 1}, #{failure_count} failure#{'s' unless failure_count == 1}" + totals << ", #{pending_count} pending" if pending_count > 0 + end + @output.puts "<script type=\"text/javascript\">document.getElementById('duration').innerHTML = \"Finished in <strong>#{duration} seconds</strong>\";</script>" + @output.puts "<script type=\"text/javascript\">document.getElementById('totals').innerHTML = \"#{totals}\";</script>" + @output.puts "</div>" + @output.puts "</div>" + @output.puts "</body>" + @output.puts "</html>" + @output.flush + end + + def html_header + <<-EOF +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html + PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head> + <title>RSpec results</title> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <meta http-equiv="Expires" content="-1" /> + <meta http-equiv="Pragma" content="no-cache" /> + <style type="text/css"> + body { + margin: 0; + padding: 0; + background: #fff; + font-size: 80%; + } + </style> + <script type="text/javascript"> + // <![CDATA[ +#{global_scripts} + // ]]> + </script> + <style type="text/css"> +#{global_styles} + </style> +</head> +<body> +EOF + end + + def report_header + <<-EOF +<div class="rspec-report"> + +<div id="rspec-header"> + <div id="label"> + <h1>RSpec Code Examples</h1> + </div> + + <div id="summary"> + <p id="totals"> </p> + <p id="duration"> </p> + </div> +</div> + +<div class="results"> +EOF + end + + def global_scripts + <<-EOF +function moveProgressBar(percentDone) { + document.getElementById("rspec-header").style.width = percentDone +"%"; +} +function makeRed(element_id) { + document.getElementById(element_id).style.background = '#C40D0D'; + document.getElementById(element_id).style.color = '#FFFFFF'; +} + +function makeYellow(element_id) { + if (element_id == "rspec-header" && document.getElementById(element_id).style.background != '#C40D0D') + { + document.getElementById(element_id).style.background = '#FAF834'; + document.getElementById(element_id).style.color = '#000000'; + } + else + { + document.getElementById(element_id).style.background = '#FAF834'; + document.getElementById(element_id).style.color = '#000000'; + } +} +EOF + end + + def global_styles + <<-EOF +#rspec-header { + background: #65C400; color: #fff; height: 4em; +} + +.rspec-report h1 { + margin: 0px 10px 0px 10px; + padding: 10px; + font-family: "Lucida Grande", Helvetica, sans-serif; + font-size: 1.8em; + position: absolute; +} + +#summary { + margin: 0; padding: 5px 10px; + font-family: "Lucida Grande", Helvetica, sans-serif; + text-align: right; + top: 0px; + right: 0px; + float:right; +} + +#summary p { + margin: 0 0 0 2px; +} + +#summary #totals { + font-size: 1.2em; +} + +.example_group { + margin: 0 10px 5px; + background: #fff; +} + +dl { + margin: 0; padding: 0 0 5px; + font: normal 11px "Lucida Grande", Helvetica, sans-serif; +} + +dt { + padding: 3px; + background: #65C400; + color: #fff; + font-weight: bold; +} + +dd { + margin: 5px 0 5px 5px; + padding: 3px 3px 3px 18px; +} + +dd.spec.passed { + border-left: 5px solid #65C400; + border-bottom: 1px solid #65C400; + background: #DBFFB4; color: #3D7700; +} + +dd.spec.failed { + border-left: 5px solid #C20000; + border-bottom: 1px solid #C20000; + color: #C20000; background: #FFFBD3; +} + +dd.spec.not_implemented { + border-left: 5px solid #FAF834; + border-bottom: 1px solid #FAF834; + background: #FCFB98; color: #131313; +} + +dd.spec.pending_fixed { + border-left: 5px solid #0000C2; + border-bottom: 1px solid #0000C2; + color: #0000C2; background: #D3FBFF; +} + +.backtrace { + color: #000; + font-size: 12px; +} + +a { + color: #BE5C00; +} + +/* Ruby code, style similar to vibrant ink */ +.ruby { + font-size: 12px; + font-family: monospace; + color: white; + background-color: black; + padding: 0.1em 0 0.2em 0; +} + +.ruby .keyword { color: #FF6600; } +.ruby .constant { color: #339999; } +.ruby .attribute { color: white; } +.ruby .global { color: white; } +.ruby .module { color: white; } +.ruby .class { color: white; } +.ruby .string { color: #66FF00; } +.ruby .ident { color: white; } +.ruby .method { color: #FFCC00; } +.ruby .number { color: white; } +.ruby .char { color: white; } +.ruby .comment { color: #9933CC; } +.ruby .symbol { color: white; } +.ruby .regex { color: #44B4CC; } +.ruby .punct { color: white; } +.ruby .escape { color: white; } +.ruby .interp { color: white; } +.ruby .expr { color: white; } + +.ruby .offending { background-color: gray; } +.ruby .linenum { + width: 75px; + padding: 0.1em 1em 0.2em 0; + color: #000000; + background-color: #FFFBD3; +} +EOF + end + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/nested_text_formatter.rb b/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/nested_text_formatter.rb new file mode 100644 index 000000000..df5274591 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/nested_text_formatter.rb @@ -0,0 +1,50 @@ +require 'spec/runner/formatter/base_text_formatter' + +module Spec + module Runner + module Formatter + class NestedTextFormatter < BaseTextFormatter + + INDENT = ' ' + + def initialize(options, where) + super + @last_nested_descriptions = [] + end + + def example_group_started(example_group) + super + + example_group.nested_descriptions.each_with_index do |nested_description, i| + unless example_group.nested_descriptions[0..i] == @last_nested_descriptions[0..i] + output.puts "#{INDENT*i}#{nested_description}" + end + end + + @last_nested_descriptions = example_group.nested_descriptions + end + + def example_failed(example, counter, failure) + output.puts(red("#{current_indentation}#{example.description} (FAILED - #{counter})")) + output.flush + end + + def example_passed(example) + message = "#{current_indentation}#{example.description}" + output.puts green(message) + output.flush + end + + def example_pending(example, message, deprecated_pending_location=nil) + super + output.puts yellow("#{current_indentation}#{example.description} (PENDING: #{message})") + output.flush + end + + def current_indentation + INDENT*@last_nested_descriptions.length + end + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/no_op_method_missing.rb b/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/no_op_method_missing.rb new file mode 100644 index 000000000..350e29f73 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/no_op_method_missing.rb @@ -0,0 +1,21 @@ +module Spec + module Runner + module Formatter + module NOOPMethodMissing + def respond_to?(message, include_private = false) + if include_private + true + else + !private_methods.any? {|m| [message.to_s, message.to_sym].include?(m)} + end + end + + private + + def method_missing(sym, *args) + # a no-op + end + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/profile_formatter.rb b/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/profile_formatter.rb new file mode 100644 index 000000000..3784f3ac7 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/profile_formatter.rb @@ -0,0 +1,47 @@ +require 'spec/runner/formatter/progress_bar_formatter' + +module Spec + module Runner + module Formatter + class ProfileFormatter < ProgressBarFormatter + + def initialize(options, where) + super + @example_times = [] + end + + def start(count) + @output.puts "Profiling enabled." + end + + def example_started(example) + @time = Time.now + end + + def example_passed(example) + super + @example_times << [ + example_group.description, + example.description, + Time.now - @time + ] + end + + def start_dump + super + @output.puts "\n\nTop 10 slowest examples:\n" + + @example_times = @example_times.sort_by do |description, example, time| + time + end.reverse + + @example_times[0..9].each do |description, example, time| + @output.print red(sprintf("%.7f", time)) + @output.puts " #{description} #{example}" + end + @output.flush + end + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/progress_bar_formatter.rb b/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/progress_bar_formatter.rb new file mode 100644 index 000000000..862f87a44 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/progress_bar_formatter.rb @@ -0,0 +1,33 @@ +require 'spec/runner/formatter/base_text_formatter' +require 'spec/runner/formatter/no_op_method_missing' + +module Spec + module Runner + module Formatter + class ProgressBarFormatter < BaseTextFormatter + include NOOPMethodMissing + + def example_failed(example, counter, failure) + @output.print colorize_failure('F', failure) + @output.flush + end + + def example_passed(example) + @output.print green('.') + @output.flush + end + + def example_pending(example, message, deprecated_pending_location=nil) + super + @output.print yellow('*') + @output.flush + end + + def start_dump + @output.puts + @output.flush + end + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/silent_formatter.rb b/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/silent_formatter.rb new file mode 100644 index 000000000..43cce33bb --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/silent_formatter.rb @@ -0,0 +1,10 @@ +require 'spec/runner/formatter/base_formatter' + +module Spec + module Runner + module Formatter + class SilentFormatter < BaseFormatter + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/snippet_extractor.rb b/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/snippet_extractor.rb new file mode 100644 index 000000000..4f34e5fee --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/snippet_extractor.rb @@ -0,0 +1,52 @@ +module Spec + module Runner + module Formatter + # This class extracts code snippets by looking at the backtrace of the passed error + class SnippetExtractor #:nodoc: + class NullConverter; def convert(code, pre); code; end; end #:nodoc: + begin; require 'syntax/convertors/html'; @@converter = Syntax::Convertors::HTML.for_syntax "ruby"; rescue LoadError => e; @@converter = NullConverter.new; end + + def snippet(error) + raw_code, line = snippet_for(error.backtrace[0]) + highlighted = @@converter.convert(raw_code, false) + highlighted << "\n<span class=\"comment\"># gem install syntax to get syntax highlighting</span>" if @@converter.is_a?(NullConverter) + post_process(highlighted, line) + end + + def snippet_for(error_line) + if error_line =~ /(.*):(\d+)/ + file = $1 + line = $2.to_i + [lines_around(file, line), line] + else + ["# Couldn't get snippet for #{error_line}", 1] + end + end + + def lines_around(file, line) + if File.file?(file) + lines = File.open(file).read.split("\n") + min = [0, line-3].max + max = [line+1, lines.length-1].min + selected_lines = [] + selected_lines.join("\n") + lines[min..max].join("\n") + else + "# Couldn't get snippet for #{file}" + end + end + + def post_process(highlighted, offending_line) + new_lines = [] + highlighted.split("\n").each_with_index do |line, i| + new_line = "<span class=\"linenum\">#{offending_line+i-2}</span>#{line}" + new_line = "<span class=\"offending\">#{new_line}</span>" if i == 2 + new_lines << new_line + end + new_lines.join("\n") + end + + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/specdoc_formatter.rb b/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/specdoc_formatter.rb new file mode 100644 index 000000000..7204f2147 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/specdoc_formatter.rb @@ -0,0 +1,33 @@ +require 'spec/runner/formatter/base_text_formatter' + +module Spec + module Runner + module Formatter + class SpecdocFormatter < BaseTextFormatter + def example_group_started(example_group) + super + output.puts + output.puts example_group.description + output.flush + end + + def example_failed(example, counter, failure) + output.puts(red("- #{example.description} (FAILED - #{counter})")) + output.flush + end + + def example_passed(example) + message = "- #{example.description}" + output.puts green(message) + output.flush + end + + def example_pending(example, message, deprecated_pending_location=nil) + super + output.puts yellow("- #{example.description} (PENDING: #{message})") + output.flush + end + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/text_mate_formatter.rb b/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/text_mate_formatter.rb new file mode 100644 index 000000000..4c0a9c7de --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/runner/formatter/text_mate_formatter.rb @@ -0,0 +1,16 @@ +require 'spec/runner/formatter/html_formatter' + +module Spec + module Runner + module Formatter + # Formats backtraces so they're clickable by TextMate + class TextMateFormatter < HtmlFormatter + def backtrace_line(line) + line.gsub(/([^:]*\.rb):(\d*)/) do + "<a href=\"txmt://open?url=file://#{File.expand_path($1)}&line=#{$2}\">#{$1}:#{$2}</a> " + end + end + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/runner/heckle_runner.rb b/vendor/gems/rspec-1.3.1/lib/spec/runner/heckle_runner.rb new file mode 100644 index 000000000..5c81ea846 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/runner/heckle_runner.rb @@ -0,0 +1,72 @@ +if Spec::Ruby.version.to_f < 1.9 + begin + require 'rubygems' unless ENV['NO_RUBYGEMS'] + require 'heckle' + rescue LoadError ; raise "You must gem install heckle to use --heckle" ; end + + module Spec + module Runner + # Creates a new Heckler configured to heckle all methods in the classes + # whose name matches +filter+ + class HeckleRunner + def initialize(filter, heckle_class=Heckler) + @filter = filter + @heckle_class = heckle_class + end + + # Runs all the example groups held by +rspec_options+ once for each of the + # methods in the matched classes. + def heckle_with + if @filter =~ /(.*)[#\.](.*)/ + heckle_method($1, $2) + else + heckle_class_or_module(@filter) + end + end + + def heckle_method(class_name, method_name) + verify_constant(class_name) + heckle = @heckle_class.new(class_name, method_name, Spec::Runner.options) + heckle.validate + end + + def heckle_class_or_module(class_or_module_name) + verify_constant(class_or_module_name) + pattern = /^#{class_or_module_name}/ + classes = [] + ObjectSpace.each_object(Class) do |klass| + classes << klass if klass.name =~ pattern + end + + classes.each do |klass| + klass.instance_methods(false).each do |method_name| + heckle = @heckle_class.new(klass.name, method_name, Spec::Runner.options) + heckle.validate + end + end + end + + def verify_constant(name) + begin + # This is defined in Heckle + name.to_class + rescue + raise "Heckling failed - \"#{name}\" is not a known class or module" + end + end + end + + class Heckler < Heckle + def initialize(klass_name, method_name, rspec_options) + super(klass_name, method_name) + @rspec_options = rspec_options + end + + def tests_pass? + @rspec_options.run_examples + end + + end + end + end +end
\ No newline at end of file diff --git a/vendor/gems/rspec-1.3.1/lib/spec/runner/heckle_runner_unsupported.rb b/vendor/gems/rspec-1.3.1/lib/spec/runner/heckle_runner_unsupported.rb new file mode 100644 index 000000000..35ff86e10 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/runner/heckle_runner_unsupported.rb @@ -0,0 +1,10 @@ +module Spec + module Runner + # Dummy implementation for Windows that just fails (Heckle is not supported on Windows) + class HeckleRunner + def initialize(filter) + raise "Heckle is not supported on Windows or Ruby 1.9" + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/runner/line_number_query.rb b/vendor/gems/rspec-1.3.1/lib/spec/runner/line_number_query.rb new file mode 100644 index 000000000..0a907d3fe --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/runner/line_number_query.rb @@ -0,0 +1,78 @@ +module Spec + module Runner + # Parses a spec file and finds the nearest example for a given line number. + class LineNumberQuery + attr_reader :best_match + + def initialize(run_options) + @best_match = {} + @run_options = run_options + end + + def spec_name_for(file, line_number) + best_match.clear + file = File.expand_path(file) + determine_best_match(file, line_number) + if best_match[:example_group] + if best_match[:example] + "#{best_match[:example_group].description} #{best_match[:example].description}" + else + best_match[:example_group].description + end + else + nil + end + end + + def example_line_for(file, line_number) + determine_best_match(file, line_number) + best_match[:line] + end + + protected + + def determine_best_match(file, line_number) + best_match.clear + file = File.expand_path(file) + @run_options.example_groups.each do |example_group| + next unless example_group.location + consider_example_group_for_best_match(example_group, file, line_number) + + example_group.examples.each do |example| + consider_example_for_best_match(example, example_group, file, line_number) + end + end + end + + def consider_example_group_for_best_match(example_group, file, line_number) + example_group_file, example_group_line = parse_location(example_group.location) + if is_best_match?(file, line_number, example_group_file, example_group_line) + best_match.clear + best_match[:example_group] = example_group + best_match[:line] = example_group_line + end + end + + def consider_example_for_best_match(example, example_group, file, line_number) + example_file, example_line = parse_location(example.location) + if is_best_match?(file, line_number, example_file, example_line) + best_match.clear + best_match[:example_group] = example_group + best_match[:example] = example + best_match[:line] = example_line + end + end + + def is_best_match?(file, line_number, example_file, example_line) + file == File.expand_path(example_file) && + example_line <= line_number && + example_line > best_match[:line].to_i + end + + def parse_location(location) + location =~ /(.*)\:(\d*)(\:|$)/ + return $1, Integer($2) + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/runner/option_parser.rb b/vendor/gems/rspec-1.3.1/lib/spec/runner/option_parser.rb new file mode 100644 index 000000000..87c9522c2 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/runner/option_parser.rb @@ -0,0 +1,225 @@ +require 'optparse' +require 'stringio' + +module Spec + module Runner + class OptionParser < ::OptionParser + class << self + def parse(args, err, out) + parser = new(err, out) + parser.parse(args) + parser.options + end + + def spec_command? + $0.split('/').last == 'spec' + end + end + + attr_reader :options + + OPTIONS = { + :pattern => ["-p", "--pattern [PATTERN]","Limit files loaded to those matching this pattern. Defaults to '**/*_spec.rb'", + "Separate multiple patterns with commas.", + "Applies only to directories named on the command line (files", + "named explicitly on the command line will be loaded regardless)."], + :diff => ["-D", "--diff [FORMAT]","Show diff of objects that are expected to be equal when they are not", + "Builtin formats: unified|u|context|c", + "You can also specify a custom differ class", + "(in which case you should also specify --require)"], + :colour => ["-c", "--colour", "--color", "Show coloured (red/green) output"], + :example => ["-e", "--example [NAME|FILE_NAME]", "Execute example(s) with matching name(s). If the argument is", + "the path to an existing file (typically generated by a previous", + "run using --format failing_examples:file.txt), then the examples", + "on each line of that file will be executed. If the file is empty,", + "all examples will be run (as if --example was not specified).", + " ", + "If the argument is not an existing file, then it is treated as", + "an example name directly, causing RSpec to run just the example", + "matching that name"], + :specification => ["-s", "--specification [NAME]", "DEPRECATED - use -e instead", "(This will be removed when autotest works with -e)"], + :line => ["-l", "--line LINE_NUMBER", Integer, "Execute example group or example at given line.", + "(does not work for dynamically generated examples)"], + :format => ["-f", "--format FORMAT[:WHERE]","Specifies what format to use for output. Specify WHERE to tell", + "the formatter where to write the output. All built-in formats", + "expect WHERE to be a file name, and will write to $stdout if it's", + "not specified. The --format option may be specified several times", + "if you want several outputs", + " ", + "Builtin formats:", + "silent|l : No output", "progress|p : Text-based progress bar", + "profile|o : Text-based progress bar with profiling of 10 slowest examples", + "specdoc|s : Code example doc strings", + "nested|n : Code example doc strings with nested groups indented", + "html|h : A nice HTML report", + "failing_examples|e : Write all failing examples - input for --example", + "failing_example_groups|g : Write all failing example groups - input for --example", + " ", + "FORMAT can also be the name of a custom formatter class", + "(in which case you should also specify --require to load it)"], + :require => ["-r", "--require FILE", "Require FILE before running specs", + "Useful for loading custom formatters or other extensions.", + "If this option is used it must come before the others"], + :backtrace => ["-b", "--backtrace", "Output full backtrace"], + :loadby => ["-L", "--loadby STRATEGY", "Specify the strategy by which spec files should be loaded.", + "STRATEGY can currently only be 'mtime' (File modification time)", + "By default, spec files are loaded in alphabetical order if --loadby", + "is not specified."], + :reverse => ["-R", "--reverse", "Run examples in reverse order"], + :timeout => ["-t", "--timeout FLOAT", "Interrupt and fail each example that doesn't complete in the", + "specified time"], + :heckle => ["-H", "--heckle CODE", "If all examples pass, this will mutate the classes and methods", + "identified by CODE little by little and run all the examples again", + "for each mutation. The intent is that for each mutation, at least", + "one example *should* fail, and RSpec will tell you if this is not the", + "case. CODE should be either Some::Module, Some::Class or", + "Some::Fabulous#method}"], + :dry_run => ["-d", "--dry-run", "Invokes formatters without executing the examples."], + :options_file => ["-O", "--options PATH", "Read options from a file"], + :generate_options => ["-G", "--generate-options PATH", "Generate an options file for --options"], + :runner => ["-U", "--runner RUNNER", "Use a custom Runner."], + :debug => ["-u", "--debugger", "Enable ruby-debugging."], + :drb => ["-X", "--drb", "Run examples via DRb. (For example against script/spec_server)"], + :drb_port => ["--port PORT", "Port for DRb server. (Ignored without --drb)"], + :version => ["-v", "--version", "Show version"], + :help => ["-h", "--help", "You're looking at it"] + } + + def initialize(err, out) + super() + @error_stream = err + @out_stream = out + @options = Options.new(@error_stream, @out_stream) + + @file_factory = File + + self.banner = "Usage: spec (FILE(:LINE)?|DIRECTORY|GLOB)+ [options]" + self.separator "" + on(*OPTIONS[:pattern]) {|pattern| @options.filename_pattern = pattern} + on(*OPTIONS[:diff]) {|diff| @options.parse_diff(diff)} + on(*OPTIONS[:colour]) {@options.colour = true} + on(*OPTIONS[:example]) {|example| @options.parse_example(example)} + on(*OPTIONS[:specification]) {|example| @options.parse_example(example)} + on(*OPTIONS[:line]) {|line_number| @options.line_number = line_number.to_i} + on(*OPTIONS[:format]) {|format| @options.parse_format(format)} + on(*OPTIONS[:require]) {|requires| invoke_requires(requires)} + on(*OPTIONS[:backtrace]) {@options.backtrace_tweaker = NoisyBacktraceTweaker.new} + on(*OPTIONS[:loadby]) {|loadby| @options.loadby = loadby} + on(*OPTIONS[:reverse]) {@options.reverse = true} + on(*OPTIONS[:timeout]) {|timeout| @options.timeout = timeout.to_f} + on(*OPTIONS[:heckle]) {|heckle| @options.load_heckle_runner(heckle)} + on(*OPTIONS[:dry_run]) {@options.dry_run = true} + on(*OPTIONS[:options_file]) {|options_file|} + on(*OPTIONS[:generate_options]) {|options_file|} + on(*OPTIONS[:runner]) {|runner| @options.user_input_for_runner = runner} + on(*OPTIONS[:debug]) {@options.debug = true} + on(*OPTIONS[:drb]) {} + on(*OPTIONS[:drb_port]) {|port| @options.drb_port = port} + on(*OPTIONS[:version]) {parse_version} + on("--autospec") {@options.autospec = true} + on_tail(*OPTIONS[:help]) {parse_help} + end + + def order!(argv, &blk) + @argv = argv.dup + @argv = (@argv.empty? & self.class.spec_command?) ? ['--help'] : @argv + + # Parse options file first + parse_file_options(:options_file, :parse_options_file) + + @options.argv = @argv.dup + return if parse_file_options(:generate_options, :write_options_file) + return if parse_drb + + super(@argv) do |file| + if file =~ /^(.+):(\d+)$/ + file = $1 + @options.line_number = $2.to_i + end + + @options.files << file + blk.call(file) if blk + end + + @options + end + + protected + + def invoke_requires(requires) + requires.split(",").each do |file| + require file + end + end + + def parse_file_options(option_name, action) + # Remove the file option and the argument before handling the file + options_file = nil + options_list = OPTIONS[option_name][0..1] + options_list[1].gsub!(" PATH", "") + options_list.each do |option| + if index = @argv.index(option) + @argv.delete_at(index) + options_file = @argv.delete_at(index) + end + end + + if options_file.nil? && + File.exist?('spec/spec.opts') && + !@argv.any?{|a| a =~ /^\-/ } + options_file = 'spec/spec.opts' + end + + if options_file + send(action, options_file) + return true + else + return false + end + end + + def parse_options_file(options_file) + option_file_args = File.readlines(options_file).map {|l| l.chomp.split " "}.flatten + @argv.push(*option_file_args) + end + + def write_options_file(options_file) + File.open(options_file, 'w') do |io| + io.puts @argv.join("\n") + end + @out_stream.puts "\nOptions written to #{options_file}. You can now use these options with:" + @out_stream.puts "spec --options #{options_file}" + @options.examples_should_not_be_run + end + + def parse_drb + argv = @options.argv + is_drb = false + is_drb ||= argv.delete(OPTIONS[:drb][0]) + is_drb ||= argv.delete(OPTIONS[:drb][1]) + return false unless is_drb + if DrbCommandLine.run(self.class.parse(argv, @error_stream, @out_stream)) + @options.examples_should_not_be_run + true + else + @error_stream.puts "Running specs locally:" + false + end + end + + def parse_version + @out_stream.puts ::Spec::VERSION::SUMMARY + exit if stdout? + end + + def parse_help + @out_stream.puts self + exit if stdout? + end + + def stdout? + @out_stream == $stdout + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/runner/options.rb b/vendor/gems/rspec-1.3.1/lib/spec/runner/options.rb new file mode 100644 index 000000000..6e23da7da --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/runner/options.rb @@ -0,0 +1,406 @@ +require 'ostruct' +require 'rbconfig' + +module Spec + module Runner + class Options + FILE_SORTERS = { + 'mtime' => lambda {|file_a, file_b| File.mtime(file_b) <=> File.mtime(file_a)} + } + + EXAMPLE_FORMATTERS = { # Load these lazily for better speed + 'silent' => ['spec/runner/formatter/silent_formatter', 'Formatter::SilentFormatter'], + 'l' => ['spec/runner/formatter/silent_formatter', 'Formatter::SilentFormatter'], + 'specdoc' => ['spec/runner/formatter/specdoc_formatter', 'Formatter::SpecdocFormatter'], + 's' => ['spec/runner/formatter/specdoc_formatter', 'Formatter::SpecdocFormatter'], + 'nested' => ['spec/runner/formatter/nested_text_formatter', 'Formatter::NestedTextFormatter'], + 'n' => ['spec/runner/formatter/nested_text_formatter', 'Formatter::NestedTextFormatter'], + 'html' => ['spec/runner/formatter/html_formatter', 'Formatter::HtmlFormatter'], + 'h' => ['spec/runner/formatter/html_formatter', 'Formatter::HtmlFormatter'], + 'progress' => ['spec/runner/formatter/progress_bar_formatter', 'Formatter::ProgressBarFormatter'], + 'p' => ['spec/runner/formatter/progress_bar_formatter', 'Formatter::ProgressBarFormatter'], + 'failing_examples' => ['spec/runner/formatter/failing_examples_formatter', 'Formatter::FailingExamplesFormatter'], + 'e' => ['spec/runner/formatter/failing_examples_formatter', 'Formatter::FailingExamplesFormatter'], +'failing_example_groups' => ['spec/runner/formatter/failing_example_groups_formatter', 'Formatter::FailingExampleGroupsFormatter'], + 'g' => ['spec/runner/formatter/failing_example_groups_formatter', 'Formatter::FailingExampleGroupsFormatter'], + 'profile' => ['spec/runner/formatter/profile_formatter', 'Formatter::ProfileFormatter'], + 'o' => ['spec/runner/formatter/profile_formatter', 'Formatter::ProfileFormatter'], + 'textmate' => ['spec/runner/formatter/text_mate_formatter', 'Formatter::TextMateFormatter'] + } + + attr_accessor( + :autospec, # hack to tell + :filename_pattern, + :backtrace_tweaker, + :context_lines, + :diff_format, + :dry_run, + :profile, + :heckle_runner, + :debug, + :line_number, + :loadby, + :reporter, + :reverse, + :timeout, + :verbose, + :user_input_for_runner, + :error_stream, + :output_stream, + # TODO: BT - Figure out a better name + :argv + ) + attr_reader :colour, :differ_class, :files, :examples, :example_groups + attr_writer :drb_port + + def initialize(error_stream, output_stream) + @error_stream = error_stream + @output_stream = output_stream + @filename_pattern = "**/*_spec.rb" + @backtrace_tweaker = QuietBacktraceTweaker.new + @examples = [] + @colour = false + @profile = false + @dry_run = false + @debug = false + @reporter = Reporter.new(self) + @context_lines = 3 + @diff_format = :unified + @files = [] + @example_groups = [] + @result = nil + @examples_run = false + @examples_should_be_run = nil + @user_input_for_runner = nil + @after_suite_parts = [] + @files_loaded = false + @out_used = nil + end + + def add_example_group(example_group) + @example_groups << example_group + end + + def line_number_requested? + !!line_number + end + + def example_line + Spec::Runner::LineNumberQuery.new(self).example_line_for(files.first, line_number) + end + + def remove_example_group(example_group) + @example_groups.delete(example_group) + end + + def require_ruby_debug + require 'rubygems' unless ENV['NO_RUBYGEMS'] + require 'ruby-debug' + end + + def project_root # :nodoc: + require 'pathname' + @project_root ||= determine_project_root + end + + def determine_project_root # :nodoc: + # This is borrowed (slightly modified) from Scott Taylors + # project_path project: + # http://github.com/smtlaissezfaire/project_path + Pathname(File.expand_path('.')).ascend do |path| + if File.exists?(File.join(path, "spec")) + return path + end + end + end + + def add_dir_from_project_root_to_load_path(dir, load_path=$LOAD_PATH) # :nodoc: + return if project_root.nil? + full_dir = File.join(project_root, dir) + load_path.unshift full_dir unless load_path.include?(full_dir) + end + + def run_examples + require_ruby_debug if debug + return true unless examples_should_be_run? + success = true + begin + runner = custom_runner || ExampleGroupRunner.new(self) + + unless @files_loaded + ['spec','lib'].each do |dir| + add_dir_from_project_root_to_load_path(dir) + end + runner.load_files(files_to_load) + @files_loaded = true + end + + define_predicate_matchers + plugin_mock_framework + ignore_backtrace_patterns + + # TODO - this has to happen after the files get loaded, + # otherwise the before_suite_parts are not populated + # from the configuration. There is no spec for this + # directly, but features/before_and_after_blocks/before_and_after_blocks.story + # will fail if this happens before the files are loaded. + before_suite_parts.each { |part| part.call } + + if example_groups.empty? + true + else + set_spec_from_line_number if line_number + success = runner.run + @examples_run = true + heckle if heckle_runner + success + end + ensure + after_suite_parts.each do |part| + part.arity < 1 ? part.call : part.call(success) + end + end + end + + def before_suite_parts + Spec::Example::BeforeAndAfterHooks.before_suite_parts + end + + def after_suite_parts + Spec::Example::BeforeAndAfterHooks.after_suite_parts + end + + def examples_run? + @examples_run + end + + def examples_should_not_be_run + @examples_should_be_run = false + end + + def mock_framework + # TODO - don't like this dependency - perhaps store this in here instead? + Spec::Runner.configuration.mock_framework + end + + def colour=(colour) + @colour = colour + if @colour && Config::CONFIG['host_os'] =~ /mswin|mingw/ ;\ + begin ;\ + replace_output = @output_stream.equal?($stdout) ;\ + require 'rubygems' unless ENV['NO_RUBYGEMS'] ;\ + require 'Win32/Console/ANSI' ;\ + @output_stream = $stdout if replace_output ;\ + rescue LoadError ;\ + warn "You must 'gem install win32console' to use colour on Windows" ;\ + @colour = false ;\ + end + end + end + + def parse_diff(format) + case format + when :context, 'context', 'c' + @diff_format = :context + default_differ + when :unified, 'unified', 'u', '', nil + @diff_format = :unified + default_differ + else + @diff_format = :custom + self.differ_class = load_class(format, 'differ', '--diff') + end + end + + def parse_example(example) + if(File.file?(example)) + @examples = [File.open(example).read.split("\n")].flatten + else + @examples = [example] + end + end + + def parse_format(format_arg) + format, where = ClassAndArgumentsParser.parse(format_arg) + unless where + raise "When using several --format options only one of them can be without a file" if @out_used + where = @output_stream + @out_used = true + end + @format_options ||= [] + @format_options << [format, where] + end + + def formatters + @format_options ||= [['progress', @output_stream]] + @formatters ||= load_formatters(@format_options, EXAMPLE_FORMATTERS) + end + + def load_formatters(format_options, formatters) + format_options.map do |format, where| + formatter_type = if formatters[format] + require formatters[format][0] + eval(formatters[format][1], binding, __FILE__, __LINE__) + else + load_class(format, 'formatter', '--format') + end + formatter_type.new(formatter_options, where) + end + end + + def formatter_options + @formatter_options ||= OpenStruct.new( + :colour => colour, + :autospec => autospec, + :dry_run => dry_run + ) + end + + def which_heckle_runner + ([/mswin/, /java/].detect{|p| p =~ RUBY_PLATFORM} || Spec::Ruby.version.to_f == 1.9) ? "spec/runner/heckle_runner_unsupported" : "spec/runner/heckle_runner" + end + + def load_heckle_runner(heckle) + @format_options ||= [['silent', @output_stream]] + require which_heckle_runner + @heckle_runner = ::Spec::Runner::HeckleRunner.new(heckle) + end + + def number_of_examples + return examples.size unless examples.empty? + @example_groups.inject(0) {|sum, group| sum + group.number_of_examples} + end + + def files_to_load + result = [] + sorted_files.each do |file| + if File.directory?(file) + filename_pattern.split(",").each do |pattern| + result += Dir[File.expand_path("#{file}/#{pattern.strip}")] + end + elsif File.file?(file) + result << file + else + raise "File or directory not found: #{file}" + end + end + result + end + + def dry_run? + @dry_run == true + end + + def drb_port + @drb_port.to_i if defined?(@drb_port) + end + + protected + + def define_predicate_matchers + Spec::Runner.configuration.predicate_matchers.each_pair do |matcher_method, method_on_object| + Spec::Example::ExampleMethods::__send__ :define_method, matcher_method do |*args| + eval("be_#{method_on_object.to_s.gsub('?','')}(*args)") + end + end + end + + def plugin_mock_framework + case mock_framework + when Module + Spec::Example::ExampleMethods.__send__ :include, mock_framework + else + require mock_framework + Spec::Example::ExampleMethods.__send__ :include, Spec::Adapters::MockFramework + end + end + + def ignore_backtrace_patterns + @backtrace_tweaker.ignore_patterns Spec::Runner.configuration.ignored_backtrace_patterns + end + + def examples_should_be_run? + return @examples_should_be_run unless @examples_should_be_run.nil? + @examples_should_be_run = true + end + + def differ_class=(klass) + return unless klass + @differ_class = klass + Spec::Expectations.differ = self.differ_class.new(self) + end + + def load_class(name, kind, option) + if name =~ /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ + arg = $2 == "" ? nil : $2 + [$1, arg] + else + m = "#{name.inspect} is not a valid class name" + @error_stream.puts m + raise m + end + begin + eval(name, binding, __FILE__, __LINE__) + rescue NameError => e + @error_stream.puts "Couldn't find #{kind} class #{name}" + @error_stream.puts "Make sure the --require option is specified *before* #{option}" + if $_spec_spec ; raise e ; else exit(1) ; end + end + end + + def custom_runner + return nil unless custom_runner? + klass_name, arg = ClassAndArgumentsParser.parse(user_input_for_runner) + runner_type = load_class(klass_name, 'example group runner', '--runner') + return runner_type.new(self, arg) + end + + def custom_runner? + return user_input_for_runner ? true : false + end + + def heckle + heckle_runner = self.heckle_runner + self.heckle_runner = nil + heckle_runner.heckle_with + end + + def sorted_files + return sorter ? files.sort(&sorter) : files + end + + def sorter + FILE_SORTERS[loadby] + end + + def default_differ + require 'spec/runner/differs/default' + self.differ_class = ::Spec::Expectations::Differs::Default + end + + def set_spec_from_line_number + if examples.empty? + if files.length == 1 + if File.directory?(files[0]) + error_stream.puts "You must specify one file, not a directory when providing a line number" + exit(1) if stderr? + else + example = LineNumberQuery.new(self).spec_name_for(files[0], line_number) + @examples = [example] + end + else + error_stream.puts "Only one file can be specified when providing a line number: #{files.inspect}" + exit(3) if stderr? + end + else + error_stream.puts "You cannot use --example and specify a line number" + exit(4) if stderr? + end + end + + def stderr? + @error_stream == $stderr + end + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/runner/reporter.rb b/vendor/gems/rspec-1.3.1/lib/spec/runner/reporter.rb new file mode 100644 index 000000000..0fae7d137 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/runner/reporter.rb @@ -0,0 +1,171 @@ +module Spec + module Runner + class Reporter + attr_reader :options + + def initialize(options) + @options = options + @options.reporter = self + @failures = [] + @pending_count = 0 + @example_count = 0 + @start_time = nil + @end_time = nil + end + + def example_group_started(example_group) + @example_group = example_group + formatters.each do |f| + f.example_group_started(example_group) + end + end + + def example_started(example) + formatters.each{|f| f.example_started(example)} + end + + def example_finished(example, error=nil) + @example_count += 1 + + if error.nil? + example_passed(example) + elsif Spec::Example::ExamplePendingError === error + example_pending(example, example.location, error.message) + else + example_failed(example, error) + end + end + + def example_failed(example, error) + backtrace_tweaker.tweak_backtrace(error) + failure = Failure.new(@example_group.description, example.description, error) + @failures << failure + formatters.each do |f| + f.example_failed(example, @failures.length, failure) + end + end + + def start(number_of_examples) + @start_time = Time.new + formatters.each{|f| f.start(number_of_examples)} + end + + def end + @end_time = Time.new + end + + # Dumps the summary and returns the total number of failures + def dump + formatters.each{|f| f.start_dump} + dump_pending + dump_failures + formatters.each do |f| + f.dump_summary(duration, @example_count, @failures.length, @pending_count) + f.close + end + @failures.length + end + + class Failure + def initialize(group_description, example_description, exception) # :nodoc: + @example_name = "#{group_description} #{example_description}" + @exception = exception + end + + # The Exception object raised + attr_reader :exception + + # Header messsage for reporting this failure, including the name of the + # example and an indicator of the type of failure. FAILED indicates a + # failed expectation. FIXED indicates a pending example that passes, and + # no longer needs to be pending. RuntimeError indicates that a + # RuntimeError occured. + # + # == Examples + # + # 'A new account should have a zero balance' FAILED + # 'A new account should have a zero balance' FIXED + # RuntimeError in 'A new account should have a zero balance' + def header + if expectation_not_met? + "'#{@example_name}' FAILED" + elsif pending_fixed? + "'#{@example_name}' FIXED" + else + "#{@exception.class.name} in '#{@example_name}'" + end + end + + def pending_fixed? # :nodoc: + @exception.is_a?(Spec::Example::PendingExampleFixedError) + end + + def expectation_not_met? # :nodoc: + @exception.is_a?(Spec::Expectations::ExpectationNotMetError) + end + end + + private + + def formatters + @options.formatters + end + + def backtrace_tweaker + @options.backtrace_tweaker + end + + def dump_failures + return if @failures.empty? + @failures.inject(1) do |index, failure| + formatters.each{|f| f.dump_failure(index, failure)} + index + 1 + end + end + + def dump_pending + formatters.each{|f| f.dump_pending} + end + + def duration + return @end_time - @start_time unless (@end_time.nil? or @start_time.nil?) + return "0.0" + end + + def example_passed(example) + formatters.each{|f| f.example_passed(example)} + end + + EXAMPLE_PENDING_DEPRECATION_WARNING = <<-WARNING + +********************************************************************* +DEPRECATION WARNING: RSpec's formatters have changed example_pending +to accept two arguments instead of three. Please see the rdoc +for Spec::Runner::Formatter::BaseFormatter#example_pending +for more information. + +Please update any custom formatters to accept only two arguments +to example_pending. Support for example_pending with two arguments +and this warning message will be removed after the RSpec 2.0 release. +********************************************************************* +WARNING + + def example_pending(example, ignore, message="Not Yet Implemented") + @pending_count += 1 + formatters.each do |formatter| + if formatter_uses_deprecated_example_pending_method?(formatter) + Spec.warn EXAMPLE_PENDING_DEPRECATION_WARNING + formatter.example_pending(example, message, example.location) + else + formatter.example_pending(example, message) + end + end + end + + def formatter_uses_deprecated_example_pending_method?(formatter) + formatter.method(:example_pending).arity == 3 + end + + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/stubs/cucumber.rb b/vendor/gems/rspec-1.3.1/lib/spec/stubs/cucumber.rb new file mode 100644 index 000000000..ed294ed66 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/stubs/cucumber.rb @@ -0,0 +1,5 @@ +# This plugs RSpec's mocking/stubbing framework into cucumber +require 'spec/mocks' +Before {$rspec_mocks ||= Spec::Mocks::Space.new} +After {$rspec_mocks.reset_all} +World(Spec::Mocks::ExampleMethods) diff --git a/vendor/gems/rspec-1.3.1/lib/spec/test/unit.rb b/vendor/gems/rspec-1.3.1/lib/spec/test/unit.rb new file mode 100644 index 000000000..fb4eb4932 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/test/unit.rb @@ -0,0 +1,10 @@ +require 'spec/interop/test' + +# Hack to stop active_support/dependencies from complaining about +# 'spec/test/unit' not defining Spec::Test::Unit +module Spec + module Test + module Unit + end + end +end diff --git a/vendor/gems/rspec-1.3.1/lib/spec/version.rb b/vendor/gems/rspec-1.3.1/lib/spec/version.rb new file mode 100644 index 000000000..122c45101 --- /dev/null +++ b/vendor/gems/rspec-1.3.1/lib/spec/version.rb @@ -0,0 +1,14 @@ +module Spec # :nodoc: + module VERSION # :nodoc: + unless defined? MAJOR + MAJOR = 1 + MINOR = 3 + TINY = 1 + PRE = nil + + STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.') + + SUMMARY = "rspec #{STRING}" + end + end +end |