diff options
Diffstat (limited to 'vendor/plugins/rspec/lib')
104 files changed, 2277 insertions, 4139 deletions
diff --git a/vendor/plugins/rspec/lib/autotest/discover.rb b/vendor/plugins/rspec/lib/autotest/discover.rb index 81914c3b7..3ac51c135 100644 --- a/vendor/plugins/rspec/lib/autotest/discover.rb +++ b/vendor/plugins/rspec/lib/autotest/discover.rb @@ -1,3 +1,3 @@ Autotest.add_discovery do - "rspec" if File.exist?('spec') + "rspec" if File.directory?('spec') && ENV['RSPEC'] end diff --git a/vendor/plugins/rspec/lib/autotest/rspec.rb b/vendor/plugins/rspec/lib/autotest/rspec.rb index 164f298f5..625e340b5 100644 --- a/vendor/plugins/rspec/lib/autotest/rspec.rb +++ b/vendor/plugins/rspec/lib/autotest/rspec.rb @@ -4,13 +4,13 @@ Autotest.add_hook :initialize do |at| at.clear_mappings # watch out: Ruby bug (1.8.6): # %r(/) != /\// - at.add_mapping(%r%^spec/.*\.rb$%) { |filename, _| - filename + at.add_mapping(%r%^spec/.*_spec.rb$%) { |filename, _| + filename } - at.add_mapping(%r%^lib/(.*)\.rb$%) { |_, m| + at.add_mapping(%r%^lib/(.*)\.rb$%) { |_, m| ["spec/#{m[1]}_spec.rb"] } - at.add_mapping(%r%^spec/(spec_helper|shared/.*)\.rb$%) { + at.add_mapping(%r%^spec/(spec_helper|shared/.*)\.rb$%) { at.files_matching %r%^spec/.*_spec\.rb$% } end @@ -21,14 +21,14 @@ class Autotest::Rspec < Autotest def initialize super - self.failed_results_re = /^\d+\)\n(?:\e\[\d*m)?(?:.*?Error in )?'([^\n]*)'(?: FAILED)?(?:\e\[\d*m)?\n(.*?)\n\n/m + 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(\.\/)?(.*\.rb):[\d]+:\Z?/ + if trace =~ /\n(\.\/)?(.*spec\.rb):[\d]+:/ filters[$2] << spec end end @@ -36,37 +36,12 @@ class Autotest::Rspec < Autotest end def make_test_cmd(files_to_test) - return "#{ruby} -S #{spec_command} #{add_options_if_present} #{files_to_test.keys.flatten.join(' ')}" + return '' if files_to_test.empty? + spec_program = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'bin', 'spec')) + return "#{ruby} #{spec_program} --autospec #{files_to_test.keys.flatten.join(' ')} #{add_options_if_present}" end - + def add_options_if_present # :nodoc: File.exist?("spec/spec.opts") ? "-O spec/spec.opts " : "" end - - # Finds the proper spec command to use. Precendence is set in the - # lazily-evaluated method spec_commands. Alias + Override that in - # ~/.autotest to provide a different spec command then the default - # paths provided. - def spec_command(separator=File::ALT_SEPARATOR) - unless defined? @spec_command then - @spec_command = spec_commands.find { |cmd| File.exists? cmd } - - raise RspecCommandError, "No spec command could be found!" unless @spec_command - - @spec_command.gsub! File::SEPARATOR, separator if separator - end - @spec_command - end - - # Autotest will look for spec commands in the following - # locations, in this order: - # - # * bin/spec - # * default spec bin/loader installed in Rubygems - def spec_commands - [ - File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'bin', 'spec')), - File.join(Config::CONFIG['bindir'], 'spec') - ] - end end diff --git a/vendor/plugins/rspec/lib/spec.rb b/vendor/plugins/rspec/lib/spec.rb index c143aa885..879c373e8 100644 --- a/vendor/plugins/rspec/lib/spec.rb +++ b/vendor/plugins/rspec/lib/spec.rb @@ -1,30 +1,8 @@ -require 'spec/version' +require 'spec/deprecation' +require 'spec/ruby' require 'spec/matchers' require 'spec/expectations' require 'spec/example' -require 'spec/extensions' require 'spec/runner' - -if Object.const_defined?(:Test); \ - require 'spec/interop/test'; \ -end - -module Spec - class << self - def run? - @run || rspec_options.examples_run? - end - - def run; \ - return true if run?; \ - result = rspec_options.run_examples; \ - @run = true; \ - result; \ - end - attr_writer :run - - def exit?; \ - !Object.const_defined?(:Test) || Test::Unit.run?; \ - end - end -end
\ No newline at end of file +require 'spec/version' +require 'spec/dsl' diff --git a/vendor/plugins/rspec/lib/spec/example.rb b/vendor/plugins/rspec/lib/spec/example.rb index 16ce12261..afbf41286 100644 --- a/vendor/plugins/rspec/lib/spec/example.rb +++ b/vendor/plugins/rspec/lib/spec/example.rb @@ -1,12 +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/module_inclusion_warnings' +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/configuration' require 'spec/example/example_matcher' diff --git a/vendor/plugins/rspec/lib/spec/example/configuration.rb b/vendor/plugins/rspec/lib/spec/example/configuration.rb deleted file mode 100644 index cd3f46909..000000000 --- a/vendor/plugins/rspec/lib/spec/example/configuration.rb +++ /dev/null @@ -1,158 +0,0 @@ -module Spec - module Example - class Configuration - # 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 :type, the modules listed will be - # included in all example groups. Use :type to restrict the inclusion to - # a subset of example groups. The value assigned to :type 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 - # - # config.include(My::Pony, My::Horse, :type => :farm) - # - # Only example groups that have that type will get the modules included: - # - # describe "Downtown", :type => :city do - # # Will *not* get My::Pony and My::Horse included - # end - # - # describe "Old Mac Donald", :type => :farm do - # # *Will* get My::Pony and My::Horse included - # end - # - def include(*args) - args << {} unless Hash === args.last - modules, options = args_and_options(*args) - required_example_group = get_type_from_options(options) - required_example_group = required_example_group.to_sym if required_example_group - modules.each do |mod| - ExampleGroupFactory.get(required_example_group).send(:include, mod) - end - end - - # 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 ||= {} - end - - # Prepends a global <tt>before</tt> block to all example groups. - # See #append_before for filtering semantics. - def prepend_before(*args, &proc) - scope, options = scope_and_options(*args) - example_group = ExampleGroupFactory.get( - get_type_from_options(options) - ) - example_group.prepend_before(scope, &proc) - end - - # Appends a global <tt>before</tt> block to all example groups. - # - # If you want to restrict the block to a subset of all the example - # groups then specify this in a Hash as the last argument: - # - # config.prepend_before(:all, :type => :farm) - # - # or - # - # config.prepend_before(:type => :farm) - # - def append_before(*args, &proc) - scope, options = scope_and_options(*args) - example_group = ExampleGroupFactory.get( - get_type_from_options(options) - ) - example_group.append_before(scope, &proc) - end - alias_method :before, :append_before - - # Prepends a global <tt>after</tt> block to all example groups. - # See #append_before for filtering semantics. - def prepend_after(*args, &proc) - scope, options = scope_and_options(*args) - example_group = ExampleGroupFactory.get( - get_type_from_options(options) - ) - example_group.prepend_after(scope, &proc) - end - alias_method :after, :prepend_after - - # Appends a global <tt>after</tt> block to all example groups. - # See #append_before for filtering semantics. - def append_after(*args, &proc) - scope, options = scope_and_options(*args) - example_group = ExampleGroupFactory.get( - get_type_from_options(options) - ) - example_group.append_after(scope, &proc) - end - - private - - def scope_and_options(*args) - args, options = args_and_options(*args) - scope = (args[0] || :each), options - end - - def get_type_from_options(options) - options[:type] || options[:behaviour_type] - end - - def mock_framework_path(framework_name) - File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "plugins", "mock_frameworks", framework_name)) - end - end - end -end diff --git a/vendor/plugins/rspec/lib/spec/example/errors.rb b/vendor/plugins/rspec/lib/spec/example/errors.rb index c6cb22453..157b669b0 100644 --- a/vendor/plugins/rspec/lib/spec/example/errors.rb +++ b/vendor/plugins/rspec/lib/spec/example/errors.rb @@ -1,9 +1,25 @@ module Spec module Example - class ExamplePendingError < StandardError + class ExamplePendingError < StandardError; end + + class NotYetImplementedError < ExamplePendingError + MESSAGE = "Not Yet Implemented" + def initialize + super(MESSAGE) + end end - class PendingExampleFixedError < StandardError + 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/plugins/rspec/lib/spec/example/example_group.rb b/vendor/plugins/rspec/lib/spec/example/example_group.rb index 35997f0c4..983be9a24 100644 --- a/vendor/plugins/rspec/lib/spec/example/example_group.rb +++ b/vendor/plugins/rspec/lib/spec/example/example_group.rb @@ -5,13 +5,6 @@ module Spec class ExampleGroup extend Spec::Example::ExampleGroupMethods include Spec::Example::ExampleMethods - - def initialize(defined_description, &implementation) - @_defined_description = defined_description - @_implementation = implementation - end end end end - -Spec::ExampleGroup = Spec::Example::ExampleGroup diff --git a/vendor/plugins/rspec/lib/spec/example/example_group_factory.rb b/vendor/plugins/rspec/lib/spec/example/example_group_factory.rb index c5caf4c9c..1d662782a 100644 --- a/vendor/plugins/rspec/lib/spec/example/example_group_factory.rb +++ b/vendor/plugins/rspec/lib/spec/example/example_group_factory.rb @@ -1,12 +1,36 @@ module Spec module Example + class ExampleGroupFactory - class << self + 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: # @@ -22,42 +46,36 @@ module Spec # 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] = 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 get(key=nil) - if @example_group_types.values.include?(key) - key - else - @example_group_types[key] - end - end - - def create_example_group(*args, &block) - opts = Hash === args.last ? args.last : {} - superclass = determine_superclass(opts) - superclass.describe(*args, &block) + def [](key) + @example_group_types[key] end - protected + protected def determine_superclass(opts) - key = if opts[:type] - opts[:type] - elsif opts[:spec_path] =~ /spec(\\|\/)(#{@example_group_types.keys.join('|')})/ - $2 == '' ? nil : $2.to_sym + 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 - get(key) end end + extend ClassMethods self.reset end end diff --git a/vendor/plugins/rspec/lib/spec/example/example_group_methods.rb b/vendor/plugins/rspec/lib/spec/example/example_group_methods.rb index 64e90cdb2..3862fdef6 100644 --- a/vendor/plugins/rspec/lib/spec/example/example_group_methods.rb +++ b/vendor/plugins/rspec/lib/spec/example/example_group_methods.rb @@ -3,22 +3,33 @@ module Spec module ExampleGroupMethods class << self - def description_text(*args) - args.inject("") do |result, arg| - result << " " unless (result == "" || arg.to_s =~ /^(\s|\.|#)/) - result << arg.to_s + 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 - attr_reader :description_text, :description_args, :description_options, :spec_path, :registration_binding_block + 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) + def inherited(klass) # :nodoc: super - klass.register {} - Spec::Runner.register_at_exit_hook + ExampleGroupFactory.register_example_group(klass) end - + # Makes the describe/it syntax available from a class. For example: # # class StackSpec < Spec::ExampleGroup @@ -34,390 +45,214 @@ module Spec # end # def describe(*args, &example_group_block) - args << {} unless Hash === args.last + raise Spec::Example::NoDescriptionError.new("example group", caller(0)[1]) if args.empty? if example_group_block - params = args.last - params[:spec_path] = eval("caller(0)[1]", example_group_block) unless params[:spec_path] - if params[:shared] - SharedExampleGroup.new(*args, &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 - self.subclass("Subclass") do - describe(*args) - module_eval(&example_group_block) - end + subclass(*args, &example_group_block) end else set_description(*args) - before_eval - self end end alias :context :describe # Use this to pull in examples from shared example groups. - # See Spec::Runner for information about shared example groups. - def it_should_behave_like(shared_example_group) - case shared_example_group - when SharedExampleGroup - include shared_example_group - else - example_group = SharedExampleGroup.find_shared_example_group(shared_example_group) - unless example_group - raise RuntimeError.new("Shared Example Group '#{shared_example_group}' can not be found") - end - include(example_group) + def it_should_behave_like(*shared_example_groups) + shared_example_groups.each do |group| + include_shared_example_group(group) end end - # :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 (or state expectations) - # File.should exist("path/to/file") - # - # an_instance_of (for mock argument constraints) - # 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 ||= {:an_instance_of => :is_a?} + # 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 - # Creates an instance of Spec::Example::Example and adds - # it to a collection of examples of the current example group. - def it(description=nil, &implementation) - e = new(description, &implementation) - example_objects << e - e + def pending_implementation + lambda { raise(Spec::Example::NotYetImplementedError) } end - alias_method :specify, :it + alias_method :it, :example + alias_method :specify, :example # Use this to temporarily disable an example. - def xit(description=nil, opts={}, &block) + def xexample(description=nil, opts={}, &block) Kernel.warn("Example disabled: #{description}") end - alias_method :xspecify, :xit - def run - examples = examples_to_run - reporter.add_example_group(self) + 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) if dry_run? + return dry_run(examples, run_options) if run_options.dry_run? - plugin_mock_framework define_methods_from_predicate_matchers - success, before_all_instance_variables = run_before_all - success, after_all_instance_variables = execute_examples(success, before_all_instance_variables, examples) - success = run_after_all(success, after_all_instance_variables) - end - - def description - result = ExampleGroupMethods.description_text(*description_parts) - if result.nil? || result == "" - return to_s - else - result - end - end - - def described_type - description_parts.find {|part| part.is_a?(Module)} - end - - def description_parts #:nodoc: - parts = [] - execute_in_class_hierarchy do |example_group| - parts << example_group.description_args - end - parts.flatten.compact + 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) - args, options = args_and_options(*args) - @description_args = args - @description_options = options - @description_text = ExampleGroupMethods.description_text(*args) - @spec_path = File.expand_path(options[:spec_path]) if options[:spec_path] - if described_type.class == Module - @described_module = described_type - end + @description_args, @options = args_and_options(*args) + @backtrace = caller(1) + @location = File.expand_path(options[:location]) if options[:location] self end - - attr_reader :described_module - - def examples #:nodoc: - examples = example_objects.dup - add_method_examples(examples) - rspec_options.reverse ? examples.reverse : examples - end - - def number_of_examples #:nodoc: - examples.length - end - - # Registers a block to be executed before each example. - # This method prepends +block+ to existing before blocks. - def prepend_before(*args, &block) - scope, options = scope_and_options(*args) - parts = before_parts_from_scope(scope) - parts.unshift(block) - end - # Registers a block to be executed before each example. - # This method appends +block+ to existing before blocks. - def append_before(*args, &block) - scope, options = scope_and_options(*args) - parts = before_parts_from_scope(scope) - parts << block + def notify(reporter) # :nodoc: + reporter.example_group_started(ExampleGroupProxy.new(self)) end - alias_method :before, :append_before - # Registers a block to be executed after each example. - # This method prepends +block+ to existing after blocks. - def prepend_after(*args, &block) - scope, options = scope_and_options(*args) - parts = after_parts_from_scope(scope) - parts.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. - def append_after(*args, &block) - scope, options = scope_and_options(*args) - parts = after_parts_from_scope(scope) - parts << block + def description + @description ||= ExampleGroupMethods.build_description_from(*description_parts) || to_s end - def remove_after(scope, &block) - after_each_parts.delete(block) + def described_type + @described_type ||= description_parts.reverse.find {|part| part.is_a?(Module)} end - # Deprecated. Use before(:each) - def setup(&block) - before(:each, &block) + def described_class + @described_class ||= Class === described_type ? described_type : nil end - # Deprecated. Use after(:each) - def teardown(&block) - after(:each, &block) + def description_args + @description_args ||= [] end - def before_all_parts # :nodoc: - @before_all_parts ||= [] + 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 after_all_parts # :nodoc: - @after_all_parts ||= [] + def example_proxies # :nodoc: + @example_proxies ||= [] end - def before_each_parts # :nodoc: - @before_each_parts ||= [] + def example_implementations # :nodoc: + @example_implementations ||= {} end - def after_each_parts # :nodoc: - @after_each_parts ||= [] + def examples(run_options=nil) #:nodoc: + (run_options && run_options.reverse) ? example_proxies.reverse : example_proxies end - # Only used from RSpec's own examples - def reset # :nodoc: - @before_all_parts = nil - @after_all_parts = nil - @before_each_parts = nil - @after_each_parts = nil + def number_of_examples #:nodoc: + example_proxies.length end - def register(®istration_binding_block) - @registration_binding_block = registration_binding_block - rspec_options.add_example_group self + def example_group_hierarchy + @example_group_hierarchy ||= ExampleGroupHierarchy.new(self) end - def unregister #:nodoc: - rspec_options.remove_example_group self + def nested_descriptions + example_group_hierarchy.nested_descriptions end - def registration_backtrace - eval("caller", registration_binding_block.binding) + def include_constants_in(mod) + include mod if (Spec::Ruby.version.to_f >= 1.9) & (Module === mod) & !(Class === mod) end - def run_before_each(example) - execute_in_class_hierarchy do |example_group| - example.eval_each_fail_fast(example_group.before_each_parts) + def let(name, &block) + define_method name do + @assignments ||= {} + @assignments[name] ||= instance_eval(&block) end end - def run_after_each(example) - execute_in_class_hierarchy(:superclass_first) do |example_group| - example.eval_each_fail_slow(example_group.after_each_parts) - 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 - private - def dry_run(examples) + def dry_run(examples, run_options) examples.each do |example| - rspec_options.reporter.example_started(example) - rspec_options.reporter.example_finished(example) + run_options.reporter.example_started(example) + run_options.reporter.example_finished(example) end - return true end - def run_before_all - before_all = new("before(:all)") + 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 - execute_in_class_hierarchy do |example_group| - before_all.eval_each_fail_fast(example_group.before_all_parts) - end + example_group_hierarchy.run_before_all(before_all) return [true, before_all.instance_variable_hash] rescue Exception => e - reporter.failure(before_all, e) + run_options.reporter.example_failed(example_proxy, e) return [false, before_all.instance_variable_hash] end end - def execute_examples(success, instance_variables, examples) + 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_group_instance| - success &= example_group_instance.execute(rspec_options, 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) - after_all = new("after(:all)") + 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) - execute_in_class_hierarchy(:superclass_first) do |example_group| - after_all.eval_each_fail_slow(example_group.after_all_parts) - end - return success + example_group_hierarchy.run_after_all(after_all) + success rescue Exception => e - reporter.failure(after_all, e) - return false - end - - def examples_to_run - all_examples = examples - return all_examples unless specified_examples? - all_examples.reject do |example| - matcher = ExampleMatcher.new(description.to_s, example.description) - !matcher.matches?(specified_examples) - end - end - - def specified_examples? - specified_examples && !specified_examples.empty? - end - - def specified_examples - rspec_options.examples - end - - def reporter - rspec_options.reporter - end - - def dry_run? - rspec_options.dry_run - end - - def example_objects - @example_objects ||= [] - end - - def execute_in_class_hierarchy(superclass_last=false) - classes = [] - current_class = self - while is_example_group?(current_class) - superclass_last ? classes << current_class : classes.unshift(current_class) - current_class = current_class.superclass - end - superclass_last ? classes << ExampleMethods : classes.unshift(ExampleMethods) - - classes.each do |example_group| - yield example_group - end - end - - def is_example_group?(klass) - Module === klass && klass.kind_of?(ExampleGroupMethods) + run_options.reporter.example_failed(example_proxy, e) + false end - def plugin_mock_framework - case mock_framework = Spec::Runner.configuration.mock_framework - when Module - include mock_framework + 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 - require Spec::Runner.configuration.mock_framework - include Spec::Plugins::MockFramework - end - end - - def define_methods_from_predicate_matchers # :nodoc: - all_predicate_matchers = predicate_matchers.merge( - Spec::Runner.configuration.predicate_matchers - ) - all_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)") + example_proxies.reject do |proxy| + matcher = ExampleGroupMethods.matcher_class. + new(description.to_s, proxy.description) + !matcher.matches?(run_options.examples) end end end - def scope_and_options(*args) - args, options = args_and_options(*args) - scope = (args[0] || :each), options - end - - def before_parts_from_scope(scope) - case scope - when :each; before_each_parts - when :all; before_all_parts - when :suite; rspec_options.before_suite_parts - end - end - - def after_parts_from_scope(scope) - case scope - when :each; after_each_parts - when :all; after_all_parts - when :suite; rspec_options.after_suite_parts - end - end - - def before_eval + def examples_were_specified?(run_options) + !run_options.examples.empty? end - def add_method_examples(examples) - instance_methods.sort.each do |method_name| - if example_method?(method_name) - examples << new(method_name) do - __send__(method_name) - end - end - 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) @@ -426,10 +261,20 @@ module Spec def should_method?(method_name) !(method_name =~ /^should(_not)?$/) && - method_name =~ /^should/ && ( - instance_method(method_name).arity == 0 || - instance_method(method_name).arity == -1 - ) + 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 diff --git a/vendor/plugins/rspec/lib/spec/example/example_matcher.rb b/vendor/plugins/rspec/lib/spec/example/example_matcher.rb index 435eabf52..3acd7e14a 100644 --- a/vendor/plugins/rspec/lib/spec/example/example_matcher.rb +++ b/vendor/plugins/rspec/lib/spec/example/example_matcher.rb @@ -5,14 +5,13 @@ module Spec @example_group_description = example_group_description @example_name = example_name end - + def matches?(specified_examples) - specified_examples.each do |specified_example| - return true if matches_literal_example?(specified_example) || matches_example_not_considering_modules?(specified_example) + specified_examples.any? do |specified_example| + matches_literal_example?(specified_example) || matches_example_not_considering_modules?(specified_example) end - false 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}$)/ @@ -35,8 +34,10 @@ module Spec end def example_regexp - Regexp.escape(@example_name) + Regexp.escape(@example_name) if @example_name end end + + ExampleGroupMethods.matcher_class = ExampleMatcher end end diff --git a/vendor/plugins/rspec/lib/spec/example/example_methods.rb b/vendor/plugins/rspec/lib/spec/example/example_methods.rb index d4d716c2d..ca81a9379 100644 --- a/vendor/plugins/rspec/lib/spec/example/example_methods.rb +++ b/vendor/plugins/rspec/lib/spec/example/example_methods.rb @@ -1,60 +1,80 @@ module Spec module Example module ExampleMethods - extend ExampleGroupMethods - extend ModuleReopeningFix - include ModuleInclusionWarnings - - PENDING_EXAMPLE_BLOCK = lambda { - raise Spec::Example::ExamplePendingError.new("Not Yet Implemented") - } + 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(options, instance_variables) - options.reporter.example_started(self) + 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(options.timeout) do + Timeout.timeout(run_options.timeout) do begin - before_example - run_with_description_capturing + before_each_example + instance_eval(&@_implementation) rescue Exception => e execution_error ||= e end begin - after_example + after_each_example rescue Exception => e execution_error ||= e end end - options.reporter.example_finished(self, execution_error) + run_options.reporter.example_finished(@_proxy.update(description), execution_error) success = execution_error.nil? || ExamplePendingError === execution_error end - def instance_variable_hash - instance_variables.inject({}) do |variable_hash, variable_name| - variable_hash[variable_name] = instance_variable_get(variable_name) - variable_hash - end + module BlockAliases + alias_method :to, :should + alias_method :to_not, :should_not end - def violated(message="") - raise Spec::Expectations::ExpectationNotMetError.new(message) + # 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(procs) #:nodoc: - procs.each do |proc| - instance_eval(&proc) - end + def eval_each_fail_fast(blocks) # :nodoc: + blocks.each {|block| instance_eval(&block)} end - def eval_each_fail_slow(procs) #:nodoc: + def eval_each_fail_slow(blocks) # :nodoc: first_exception = nil - procs.each do |proc| + blocks.each do |block| begin - instance_eval(&proc) + instance_eval(&block) rescue Exception => e first_exception ||= e end @@ -62,51 +82,67 @@ module Spec raise first_exception if first_exception end - def description - @_defined_description || @_matcher_description || "NO NAME" + 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 __full_description - "#{self.class.description} #{self.description}" - end - - def set_instance_variables_from_hash(ivars) + 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 ['@_implementation', '@_defined_description', '@_matcher_description', '@method_name'].include?(variable_name.to_s) + unless ['@_proxy', '@_implementation', '@method_name'].include?(variable_name.to_s) instance_variable_set variable_name, value end end end - def run_with_description_capturing - begin - return instance_eval(&(@_implementation || PENDING_EXAMPLE_BLOCK)) - ensure - @_matcher_description = Spec::Matchers.generated_description - Spec::Matchers.clear_generated_description - end + # Run all the before(:each) blocks for this example + def run_before_each + example_group_hierarchy.run_before_each(self) end - def implementation_backtrace - eval("caller", @_implementation) + # 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 - protected + private + include Matchers include Pending - - def before_example + + def before_each_example setup_mocks_for_rspec - self.class.run_before_each(self) + run_before_each end - def after_example - self.class.run_after_each(self) + 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
\ No newline at end of file +end diff --git a/vendor/plugins/rspec/lib/spec/example/module_inclusion_warnings.rb b/vendor/plugins/rspec/lib/spec/example/module_inclusion_warnings.rb deleted file mode 100644 index c65faf2dd..000000000 --- a/vendor/plugins/rspec/lib/spec/example/module_inclusion_warnings.rb +++ /dev/null @@ -1,37 +0,0 @@ -module Spec - module Example - # In the future, modules will no longer be automatically included - # in the Example Group (based on the description name); when that - # time comes, this code should be removed. - module ModuleInclusionWarnings - # Thanks, Francis Hwang. - class MethodDispatcher - def initialize(mod, target=nil) - @mod = mod - @target = target - end - - def respond_to?(sym) - @mod && @mod.instance_methods.include?(sym.to_s) - end - - def call(sym, *args, &blk) - Kernel.warn("Modules will no longer be automatically included in RSpec version 1.1.4. Called from #{caller[2]}") - @target.extend @mod - @target.send(sym, *args, &blk) - end - end - - def respond_to?(sym) - MethodDispatcher.new(self.class.described_module).respond_to?(sym) ? true : super - end - - private - - def method_missing(sym, *args, &blk) - md = MethodDispatcher.new(self.class.described_module, self) - self.respond_to?(sym) ? md.call(sym, *args, &blk) : super - end - end - end -end diff --git a/vendor/plugins/rspec/lib/spec/example/module_reopening_fix.rb b/vendor/plugins/rspec/lib/spec/example/module_reopening_fix.rb index dc01dd666..9ea088a2e 100644 --- a/vendor/plugins/rspec/lib/spec/example/module_reopening_fix.rb +++ b/vendor/plugins/rspec/lib/spec/example/module_reopening_fix.rb @@ -1,6 +1,28 @@ module Spec module Example - # This is a fix for ...Something in Ruby 1.8.6??... (Someone fill in here please - Aslak) + # 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 ||= [] @@ -18,4 +40,4 @@ module Spec end end end -end
\ No newline at end of file +end diff --git a/vendor/plugins/rspec/lib/spec/example/pending.rb b/vendor/plugins/rspec/lib/spec/example/pending.rb index b1f27c866..9aad1aab0 100644 --- a/vendor/plugins/rspec/lib/spec/example/pending.rb +++ b/vendor/plugins/rspec/lib/spec/example/pending.rb @@ -1,11 +1,11 @@ module Spec - module Example + module Example module Pending def pending(message = "TODO") if block_given? begin yield - rescue Exception => e + rescue Exception raise Spec::Example::ExamplePendingError.new(message) end raise Spec::Example::PendingExampleFixedError.new("Expected pending '#{message}' to fail. No Error was raised.") diff --git a/vendor/plugins/rspec/lib/spec/example/shared_example_group.rb b/vendor/plugins/rspec/lib/spec/example/shared_example_group.rb index a6fd6211c..336944914 100644 --- a/vendor/plugins/rspec/lib/spec/example/shared_example_group.rb +++ b/vendor/plugins/rspec/lib/spec/example/shared_example_group.rb @@ -1,58 +1,59 @@ module Spec module Example class SharedExampleGroup < Module - class << self - def add_shared_example_group(new_example_group) - guard_against_redefining_existing_example_group(new_example_group) - shared_example_groups << new_example_group + 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_shared_example_group(example_group_description) - shared_example_groups.find do |b| - b.description == example_group_description - 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 - # TODO - this needs to be global, or at least accessible from - # from subclasses of Example in a centralized place. I'm not loving - # this as a solution, but it works for now. - $shared_example_groups ||= [] - end - - private - def guard_against_redefining_existing_example_group(new_example_group) - existing_example_group = find_shared_example_group(new_example_group.description) - return unless existing_example_group - return if new_example_group.equal?(existing_example_group) - return if spec_path(new_example_group) == spec_path(existing_example_group) + @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 spec_path(example_group) - File.expand_path(example_group.spec_path) + def expanded_path(example_group) + File.expand_path(example_group.location) end end + + extend ClassMethods include ExampleGroupMethods - public :include def initialize(*args, &example_group_block) - describe(*args) + set_description(*args) @example_group_block = example_group_block - self.class.add_shared_example_group(self) end def included(mod) # :nodoc: mod.module_eval(&@example_group_block) end - - def execute_in_class_hierarchy(superclass_last=false) - classes = [self] - superclass_last ? classes << ExampleMethods : classes.unshift(ExampleMethods) - classes.each do |example_group| - yield example_group - end - end end end end diff --git a/vendor/plugins/rspec/lib/spec/expectations.rb b/vendor/plugins/rspec/lib/spec/expectations.rb index 65ea47425..13cf59b26 100644 --- a/vendor/plugins/rspec/lib/spec/expectations.rb +++ b/vendor/plugins/rspec/lib/spec/expectations.rb @@ -1,4 +1,5 @@ require 'spec/matchers' +require 'spec/expectations/fail_with' require 'spec/expectations/errors' require 'spec/expectations/extensions' require 'spec/expectations/handler' @@ -30,27 +31,5 @@ module Spec # RSpec ships with a standard set of useful matchers, and writing your own # matchers is quite simple. See Spec::Matchers for details. 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 Array === message && message.length == 3 - message, expected, target = message[0], message[1], message[2] - end - unless (differ.nil? || expected.nil? || target.nil?) - if expected.is_a?(String) - message << "\nDiff:" << self.differ.diff_as_string(target.to_s, expected) - elsif !target.is_a?(Proc) - message << "\nDiff:" << self.differ.diff_as_object(target, expected) - end - end - Kernel::raise(Spec::Expectations::ExpectationNotMetError.new(message)) - end - end end end diff --git a/vendor/plugins/rspec/lib/spec/expectations/differs/default.rb b/vendor/plugins/rspec/lib/spec/expectations/differs/default.rb deleted file mode 100644 index 74b59bbe3..000000000 --- a/vendor/plugins/rspec/lib/spec/expectations/differs/default.rb +++ /dev/null @@ -1,66 +0,0 @@ -begin - require 'rubygems' - require 'diff/lcs' #necessary due to loading bug on some machines - not sure why - DaC - require 'diff/lcs/hunk' -rescue LoadError ; raise "You must gem install diff-lcs to use diffing" ; end - -require 'pp' - -module Spec - module Expectations - module Differs - - # TODO add some rdoc - 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 - - protected - def format - @options.diff_format - end - - def context_lines - @options.context_lines - end - end - end - end -end diff --git a/vendor/plugins/rspec/lib/spec/expectations/extensions.rb b/vendor/plugins/rspec/lib/spec/expectations/extensions.rb index 60c9b9e7d..d68212e42 100644 --- a/vendor/plugins/rspec/lib/spec/expectations/extensions.rb +++ b/vendor/plugins/rspec/lib/spec/expectations/extensions.rb @@ -1,2 +1 @@ -require 'spec/expectations/extensions/object' -require 'spec/expectations/extensions/string_and_symbol' +require 'spec/expectations/extensions/kernel' diff --git a/vendor/plugins/rspec/lib/spec/expectations/extensions/object.rb b/vendor/plugins/rspec/lib/spec/expectations/extensions/object.rb deleted file mode 100644 index 2091c2947..000000000 --- a/vendor/plugins/rspec/lib/spec/expectations/extensions/object.rb +++ /dev/null @@ -1,63 +0,0 @@ -module Spec - module Expectations - # rspec adds #should and #should_not to every Object (and, - # implicitly, every Class). - module ObjectExpectations - # :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=:use_operator_matcher, &block) - ExpectationMatcherHandler.handle_matcher(self, matcher, &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=:use_operator_matcher, &block) - NegativeExpectationMatcherHandler.handle_matcher(self, matcher, &block) - end - - end - end -end - -class Object - include Spec::Expectations::ObjectExpectations -end diff --git a/vendor/plugins/rspec/lib/spec/expectations/extensions/string_and_symbol.rb b/vendor/plugins/rspec/lib/spec/expectations/extensions/string_and_symbol.rb deleted file mode 100644 index 29cfbddfa..000000000 --- a/vendor/plugins/rspec/lib/spec/expectations/extensions/string_and_symbol.rb +++ /dev/null @@ -1,17 +0,0 @@ -module Spec - module Expectations - module StringHelpers - def starts_with?(prefix) - to_s[0..(prefix.to_s.length - 1)] == prefix.to_s - end - end - end -end - -class String - include Spec::Expectations::StringHelpers -end - -class Symbol - include Spec::Expectations::StringHelpers -end diff --git a/vendor/plugins/rspec/lib/spec/expectations/handler.rb b/vendor/plugins/rspec/lib/spec/expectations/handler.rb index 2e5f2a621..c059637c7 100644 --- a/vendor/plugins/rspec/lib/spec/expectations/handler.rb +++ b/vendor/plugins/rspec/lib/spec/expectations/handler.rb @@ -2,59 +2,49 @@ module Spec module Expectations class InvalidMatcherError < ArgumentError; end - module MatcherHandlerHelper - def describe_matcher(matcher) - matcher.respond_to?(:description) ? matcher.description : "[#{matcher.class.name} does not provide a description]" - end - end - - class ExpectationMatcherHandler - class << self - include MatcherHandlerHelper - def handle_matcher(actual, matcher, &block) - if :use_operator_matcher == matcher - return Spec::Matchers::PositiveOperatorMatcher.new(actual) - 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? - unless matcher.respond_to?(:matches?) - raise InvalidMatcherError, "Expected a matcher, got #{matcher.inspect}." - end - - match = matcher.matches?(actual, &block) - ::Spec::Matchers.generated_description = "should #{describe_matcher(matcher)}" - Spec::Expectations.fail_with(matcher.failure_message) unless match + 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 NegativeExpectationMatcherHandler - class << self - include MatcherHandlerHelper - def handle_matcher(actual, matcher, &block) - if :use_operator_matcher == matcher - return Spec::Matchers::NegativeOperatorMatcher.new(actual) - end - - unless matcher.respond_to?(:matches?) - raise InvalidMatcherError, "Expected a matcher, got #{matcher.inspect}." - 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 - unless matcher.respond_to?(:negative_failure_message) - Spec::Expectations.fail_with( -<<-EOF -Matcher does not support should_not. -See Spec::Matchers for more information -about matchers. -EOF -) - end - match = matcher.matches?(actual, &block) - ::Spec::Matchers.generated_description = "should not #{describe_matcher(matcher)}" - Spec::Expectations.fail_with(matcher.negative_failure_message) if match + 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/plugins/rspec/lib/spec/extensions.rb b/vendor/plugins/rspec/lib/spec/extensions.rb deleted file mode 100755 index 715bb49f2..000000000 --- a/vendor/plugins/rspec/lib/spec/extensions.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'spec/extensions/object' -require 'spec/extensions/class' -require 'spec/extensions/main' -require 'spec/extensions/metaclass' diff --git a/vendor/plugins/rspec/lib/spec/extensions/class.rb b/vendor/plugins/rspec/lib/spec/extensions/class.rb deleted file mode 100644 index 30730f87e..000000000 --- a/vendor/plugins/rspec/lib/spec/extensions/class.rb +++ /dev/null @@ -1,24 +0,0 @@ -class Class - # Creates a new subclass of self, with a name "under" our own name. - # Example: - # - # x = Foo::Bar.subclass('Zap'){} - # x.name # => Foo::Bar::Zap_1 - # x.superclass.name # => Foo::Bar - def subclass(base_name, &body) - klass = Class.new(self) - class_name = "#{base_name}_#{class_count!}" - instance_eval do - const_set(class_name, klass) - end - klass.instance_eval(&body) - klass - end - - private - def class_count! - @class_count ||= 0 - @class_count += 1 - @class_count - end -end
\ No newline at end of file diff --git a/vendor/plugins/rspec/lib/spec/extensions/main.rb b/vendor/plugins/rspec/lib/spec/extensions/main.rb deleted file mode 100644 index 281cbf879..000000000 --- a/vendor/plugins/rspec/lib/spec/extensions/main.rb +++ /dev/null @@ -1,102 +0,0 @@ -module Spec - module Extensions - module Main - # 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 behaviour classes is to have different - # matcher methods available from within the <tt>describe</tt> block. - # - # See Spec::Example::ExampleFactory#register for details about how to - # register special implementations. - # - def describe(*args, &block) - raise ArgumentError if args.empty? - raise ArgumentError unless block - args << {} unless Hash === args.last - args.last[:spec_path] = caller(0)[1] - Spec::Example::ExampleGroupFactory.create_example_group(*args, &block) - end - alias :context :describe - - # 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(name, &block) - describe(name, :shared => true, &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) - begin - Object.const_set(name, share_examples_for(name, &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 - - private - - def rspec_options - $rspec_options ||= begin; \ - parser = ::Spec::Runner::OptionParser.new(STDERR, STDOUT); \ - parser.order!(ARGV); \ - $rspec_options = parser.options; \ - end - $rspec_options - end - - def init_rspec_options(options) - $rspec_options = options if $rspec_options.nil? - end - end - end -end - -include Spec::Extensions::Main
\ No newline at end of file diff --git a/vendor/plugins/rspec/lib/spec/extensions/metaclass.rb b/vendor/plugins/rspec/lib/spec/extensions/metaclass.rb deleted file mode 100644 index acf9febea..000000000 --- a/vendor/plugins/rspec/lib/spec/extensions/metaclass.rb +++ /dev/null @@ -1,7 +0,0 @@ -module Spec - module MetaClass - def metaclass - class << self; self; end - end - end -end
\ No newline at end of file diff --git a/vendor/plugins/rspec/lib/spec/extensions/object.rb b/vendor/plugins/rspec/lib/spec/extensions/object.rb deleted file mode 100755 index 0b8c26fa2..000000000 --- a/vendor/plugins/rspec/lib/spec/extensions/object.rb +++ /dev/null @@ -1,6 +0,0 @@ -class Object - def args_and_options(*args) - options = Hash === args.last ? args.pop : {} - return args, options - end -end diff --git a/vendor/plugins/rspec/lib/spec/interop/test.rb b/vendor/plugins/rspec/lib/spec/interop/test.rb index afa16137b..284eb32ce 100644 --- a/vendor/plugins/rspec/lib/spec/interop/test.rb +++ b/vendor/plugins/rspec/lib/spec/interop/test.rb @@ -1,4 +1,36 @@ +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-2.0.3 +* use 'script/spec' instead of 'rake spec' +#{'*' * 50} +MESSAGE + end +end + + require 'test/unit/testresult' require 'spec/interop/test/unit/testcase' diff --git a/vendor/plugins/rspec/lib/spec/interop/test/unit/testcase.rb b/vendor/plugins/rspec/lib/spec/interop/test/unit/testcase.rb index b32a820c1..dc10a2a64 100644 --- a/vendor/plugins/rspec/lib/spec/interop/test/unit/testcase.rb +++ b/vendor/plugins/rspec/lib/spec/interop/test/unit/testcase.rb @@ -5,8 +5,7 @@ module Test # This extension of the standard Test::Unit::TestCase makes RSpec # available from within, so that you can do things like: # - # require 'test/unit' - # require 'spec' + # require 'spec/test/unit' # # class MyTest < Test::Unit::TestCase # it "should work with Test::Unit assertions" do @@ -23,39 +22,35 @@ module Test extend Spec::Example::ExampleGroupMethods include Spec::Example::ExampleMethods - before(:each) {setup} - after(:each) {teardown} + def self.suite + Test::Unit::TestSuiteAdapter.new(self) + end - class << self - def suite - Test::Unit::TestSuiteAdapter.new(self) - end - - def example_method?(method_name) - should_method?(method_name) || test_method?(method_name) - end - - def test_method?(method_name) - method_name =~ /^test[_A-Z]./ && ( - instance_method(method_name).arity == 0 || - instance_method(method_name).arity == -1 - ) - end + def self.example_method?(method_name) + should_method?(method_name) || test_method?(method_name) end - def initialize(defined_description, &implementation) - @_defined_description = defined_description - @_implementation = implementation + def self.test_method?(method_name) + method_name =~ /^test./ && ( + instance_method(method_name).arity == 0 || + instance_method(method_name).arity == -1 + ) + end - @_result = ::Test::Unit::TestResult.new - # @method_name is important to set here because it "complies" with Test::Unit's interface. + before(:each) {setup} + after(:each) {teardown} + + def initialize(description, &implementation) + super # Some Test::Unit extensions depend on @method_name being present. - @method_name = @_defined_description + @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/plugins/rspec/lib/spec/interop/test/unit/testresult.rb b/vendor/plugins/rspec/lib/spec/interop/test/unit/testresult.rb index 1386dc728..dddcfe868 100644 --- a/vendor/plugins/rspec/lib/spec/interop/test/unit/testresult.rb +++ b/vendor/plugins/rspec/lib/spec/interop/test/unit/testresult.rb @@ -1,6 +1,6 @@ class Test::Unit::TestResult alias_method :tu_passed?, :passed? def passed? - return tu_passed? & ::Spec.run + return tu_passed? & ::Spec::Runner.run end end
\ No newline at end of file diff --git a/vendor/plugins/rspec/lib/spec/interop/test/unit/testsuite_adapter.rb b/vendor/plugins/rspec/lib/spec/interop/test/unit/testsuite_adapter.rb index 7c0ed092d..912762f18 100644 --- a/vendor/plugins/rspec/lib/spec/interop/test/unit/testsuite_adapter.rb +++ b/vendor/plugins/rspec/lib/spec/interop/test/unit/testsuite_adapter.rb @@ -14,7 +14,7 @@ module Test def run(*args) return true unless args.empty? - example_group.run + example_group.run(Spec::Runner.options) end def size diff --git a/vendor/plugins/rspec/lib/spec/matchers.rb b/vendor/plugins/rspec/lib/spec/matchers.rb index afae5ae5f..4ef832936 100644 --- a/vendor/plugins/rspec/lib/spec/matchers.rb +++ b/vendor/plugins/rspec/lib/spec/matchers.rb @@ -1,19 +1,31 @@ -require 'spec/matchers/simple_matcher' +require 'spec/matchers/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_error' require 'spec/matchers/respond_to' require 'spec/matchers/satisfy' +require 'spec/matchers/simple_matcher' require 'spec/matchers/throw_symbol' -require 'spec/matchers/operator_matcher' +require 'spec/matchers/wrap_expectation' +require 'spec/matchers/compatibility' +require 'spec/matchers/dsl' module Spec @@ -21,12 +33,21 @@ module Spec # is any object that responds to the following methods: # # matches?(actual) - # failure_message - # negative_failure_message #optional + # 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. - # See Spec::Mocks to learn how to use them as Mock Argument Constraints. # # == Predicates # @@ -63,14 +84,17 @@ module Spec # 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 Expectation Matchers + # == Custom Matchers # # When you find that none of the stock Expectation Matchers provide a natural - # feeling expectation, you can very easily write your own. + # feeling expectation, you can very easily write your own using RSpec's matcher + # DSL or writing one from scratch. + # + # === Matcher DSL # - # For example, 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: + # 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")) # @@ -82,7 +106,42 @@ module Spec # # bob.should_not be_in_zone("3") # - # To do this, you would need to write a class like this: + # 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>). + # + # === Custom Matcher from scratch + # + # You could also write a custom matcher from scratch, as follows: # # class BeInZone # def initialize(expected) @@ -92,10 +151,10 @@ module Spec # @target = target # @target.current_zone.eql?(Zone.new(@expected)) # end - # def failure_message + # def failure_message_for_should # "expected #{@target.inspect} to be in Zone #{@expected}" # end - # def negative_failure_message + # def failure_message_for_should_not # "expected #{@target.inspect} not to be in Zone #{@expected}" # end # end @@ -132,25 +191,5 @@ module Spec # config.include(CustomGameMatchers) # end # - module Matchers - module ModuleMethods - attr_accessor :generated_description - - def clear_generated_description - self.generated_description = nil - end - end - - extend ModuleMethods - - def method_missing(sym, *args, &block) # :nodoc: - return Matchers::Be.new(sym, *args) if sym.starts_with?("be_") - return Matchers::Has.new(sym, *args) if sym.starts_with?("have_") - super - end - - class MatcherError < StandardError - end - - end + module Matchers; end end diff --git a/vendor/plugins/rspec/lib/spec/matchers/be.rb b/vendor/plugins/rspec/lib/spec/matchers/be.rb index 2b25b11f4..242f7c5c9 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/be.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/be.rb @@ -2,142 +2,130 @@ module Spec module Matchers class Be #:nodoc: + include Spec::Matchers::Pretty + def initialize(*args) - if args.empty? - @expected = :satisfy_if - else - @expected = parse_expected(args.shift) - end + @expected = args.empty? ? true : set_expected(args.shift) @args = args - @comparison = "" + @comparison_method = nil end def matches?(actual) @actual = actual - if handling_predicate? - begin - return @result = actual.__send__(predicate, *@args) - rescue => predicate_error - # This clause should be empty, but rcov will not report it as covered - # unless something (anything) is executed within the clause - rcov_error_report = "http://eigenclass.org/hiki.rb?rcov-0.8.0" - end - - # This supports should_exist > target.exists? in the old world. - # We should consider deprecating that ability as in the new world - # you can't write "should exist" unless you have your own custom matcher. - begin - return @result = actual.__send__(present_tense_predicate, *@args) - rescue - raise predicate_error - end - else - return match_or_compare - end - end - - def failure_message - return "expected #{@comparison}#{expected}, got #{@actual.inspect}" unless handling_predicate? - return "expected #{predicate}#{args_to_s} to return true, got #{@result.inspect}" + handling_predicate? ? run_predicate_on(actual) : match_or_compare(actual) end - def negative_failure_message - return "expected not #{expected}, got #{@actual.inspect}" unless handling_predicate? - return "expected #{predicate}#{args_to_s} to return false, got #{@result.inspect}" + def run_predicate_on(actual) + begin + return @result = actual.__send__(predicate, *@args) + 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) + rescue NameError + raise predicate_missing_error + end end - def expected - return "if to be satisfied" if @expected == :satisfy_if - return true if @expected == :true - return false if @expected == :false - return "nil" if @expected == :nil - return @expected.inspect + def failure_message_for_should + if handling_predicate? + if predicate == :nil? + "expected nil, got #{@actual.inspect}" + else + "expected #{predicate}#{args_to_s} to return true, got #{@result.inspect}" + end + else + "expected #{@comparison_method} #{expected}, got #{@actual.inspect}".gsub(' ',' ') + end end - def match_or_compare - return @actual ? true : false if @expected == :satisfy_if - return @actual == true if @expected == :true - return @actual == false if @expected == :false - return @actual.nil? if @expected == :nil - return @actual < @expected if @less_than - return @actual <= @expected if @less_than_or_equal - return @actual >= @expected if @greater_than_or_equal - return @actual > @expected if @greater_than - return @actual == @expected if @double_equal - return @actual === @expected if @triple_equal - return @actual.equal?(@expected) + def failure_message_for_should_not + if handling_predicate? + if predicate == :nil? + "expected not nil, got nil" + else + "expected #{predicate}#{args_to_s} to return false, got #{@result.inspect}" + end + else + message = <<-MESSAGE +'should_not be #{@comparison_method} #{expected}' not only FAILED, +it is a bit confusing. + MESSAGE + + raise message << ([:===,:==].include?(@comparison_method) ? + "It might be more clearly expressed without the \"be\"?" : + "It might be more clearly expressed in the positive?") + end end - def ==(expected) - @prefix = "be " - @double_equal = true - @comparison = "== " - @expected = expected - self - end - - def ===(expected) - @prefix = "be " - @triple_equal = true - @comparison = "=== " - @expected = expected - self - end - - def <(expected) - @prefix = "be " - @less_than = true - @comparison = "< " - @expected = expected - self - end - - def <=(expected) - @prefix = "be " - @less_than_or_equal = true - @comparison = "<= " - @expected = expected - self + def description + "#{prefix_to_sentence}#{comparison} #{expected_to_sentence}#{args_to_sentence}".gsub(/\s+/,' ') end - def >=(expected) - @prefix = "be " - @greater_than_or_equal = true - @comparison = ">= " - @expected = expected - self + [:==, :<, :<=, :>=, :>, :===].each do |method| + define_method method do |expected| + compare_to(expected, :using => method) + self + end end - def >(expected) - @prefix = "be " - @greater_than = true - @comparison = "> " - @expected = expected - self - end + private + def match_or_compare(actual) + TrueClass === @expected ? @actual : @actual.__send__(comparison_method, @expected) + end - def description - "#{prefix_to_sentence}#{comparison}#{expected_to_sentence}#{args_to_sentence}" - end + def comparison_method + @comparison_method || :equal? + end + + def expected + @expected + end - private + def compare_to(expected, opts) + @expected, @comparison_method = expected, opts[:using] + end + + def set_expected(expected) + Symbol === expected ? parse_expected(expected) : expected + end + def parse_expected(expected) - if Symbol === expected - @handling_predicate = true - ["be_an_","be_a_","be_"].each do |prefix| - if expected.starts_with?(prefix) - @prefix = prefix - return "#{expected.to_s.sub(@prefix,"")}".to_sym + ["be_an_","be_a_","be_"].each do |prefix| + handling_predicate! + if expected.to_s =~ /^#{prefix}/ + set_prefix(prefix) + expected = expected.to_s.sub(prefix,"") + [true, false, nil].each do |val| + return val if val.to_s == expected end + return expected.to_sym end end - @prefix = "" - return expected + end + + def set_prefix(prefix) + @prefix = prefix + end + + def prefix + # FIXME - this is a bit goofy - but we get failures + # if just defining @prefix = nil in initialize + @prefix = nil unless defined?(@prefix) + @prefix + end + + def handling_predicate! + @handling_predicate = true end def handling_predicate? - return false if [:true, :false, :nil].include?(@expected) - return @handling_predicate + return false if [true, false, nil].include?(expected) + # FIXME - this is a bit goofy - but we get failures + # if just defining @handling_predicate = nil or false in initialize + return defined?(@handling_predicate) ? @handling_predicate : nil end def predicate @@ -149,50 +137,44 @@ module Spec end def args_to_s - return "" if @args.empty? - inspected_args = @args.collect{|a| a.inspect} - return "(#{inspected_args.join(', ')})" + @args.empty? ? "" : parenthesize(inspected_args.join(', ')) + end + + def parenthesize(string) + return "(#{string})" + end + + def inspected_args + @args.collect{|a| a.inspect} end def comparison - @comparison + @comparison_method.nil? ? " " : "be #{@comparison_method.to_s} " end def expected_to_sentence - split_words(@expected) + split_words(expected) end def prefix_to_sentence - split_words(@prefix) - end - - def split_words(sym) - sym.to_s.gsub(/_/,' ') + split_words(prefix) end def args_to_sentence - case @args.length - when 0 - "" - when 1 - " #{@args[0]}" - else - " #{@args[0...-1].join(', ')} and #{@args[-1]}" - end + to_sentence(@args) end end # :call-seq: - # should be # should be_true # should be_false # should be_nil - # should be_arbitrary_predicate(*args) + # should be_[arbitrary_predicate](*args) # should_not be_nil - # should_not be_arbitrary_predicate(*args) + # should_not be_[arbitrary_predicate](*args) # - # Given true, false, or nil, will pass if actual is + # 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). # @@ -206,19 +188,23 @@ module Spec # # == Examples # - # target.should be # 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? - # "this string".should be_an_intance_of(String) - # # 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) Matchers::Be.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/plugins/rspec/lib/spec/matchers/be_close.rb b/vendor/plugins/rspec/lib/spec/matchers/be_close.rb index 7763eb97e..28015f5fb 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/be_close.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/be_close.rb @@ -1,26 +1,5 @@ module Spec module Matchers - - class BeClose #:nodoc: - def initialize(expected, delta) - @expected = expected - @delta = delta - end - - def matches?(actual) - @actual = actual - (@actual - @expected).abs < @delta - end - - def failure_message - "expected #{@expected} +/- (< #{@delta}), got #{@actual}" - end - - def description - "be close to #{@expected} (within +- #{@delta})" - end - end - # :call-seq: # should be_close(expected, delta) # should_not be_close(expected, delta) @@ -31,7 +10,23 @@ module Spec # # result.should be_close(3.0, 0.5) def be_close(expected, delta) - Matchers::BeClose.new(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/plugins/rspec/lib/spec/matchers/change.rb b/vendor/plugins/rspec/lib/spec/matchers/change.rb index 8f4ecc187..c8ab9e5cf 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/change.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/change.rb @@ -4,60 +4,59 @@ module Spec #Based on patch from Wilson Bilkovich class Change #:nodoc: def initialize(receiver=nil, message=nil, &block) - @receiver = receiver - @message = message - @block = block + @message = message || "result" + @value_proc = block || lambda {receiver.__send__(message)} + @to = @from = @minimum = @maximum = @amount = nil end - def matches?(target, &block) - if block - raise MatcherError.new(<<-EOF -block passed to should or should_not change must use {} instead of do/end -EOF -) - end - @target = target - execute_change - return false if @from && (@from != @before) - return false if @to && (@to != @after) + 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 execute_change - @before = @block.nil? ? @receiver.send(@message) : @block.call - @target.call - @after = @block.nil? ? @receiver.send(@message) : @block.call + 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 + def failure_message_for_should if @to - "#{result} should have been changed to #{@to.inspect}, but is now #{@after.inspect}" + "#{@message} should have been changed to #{@to.inspect}, but is now #{@after.inspect}" elsif @from - "#{result} should have initially been #{@from.inspect}, but was #{@before.inspect}" + "#{@message} should have initially been #{@from.inspect}, but was #{@before.inspect}" elsif @amount - "#{result} should have been changed by #{@amount.inspect}, but was changed by #{actual_delta.inspect}" + "#{@message} should have been changed by #{@amount.inspect}, but was changed by #{actual_delta.inspect}" elsif @minimum - "#{result} should have been changed by at least #{@minimum.inspect}, but was changed by #{actual_delta.inspect}" + "#{@message} should have been changed by at least #{@minimum.inspect}, but was changed by #{actual_delta.inspect}" elsif @maximum - "#{result} should have been changed by at most #{@maximum.inspect}, but was changed by #{actual_delta.inspect}" + "#{@message} should have been changed by at most #{@maximum.inspect}, but was changed by #{actual_delta.inspect}" else - "#{result} should have changed, but is still #{@before.inspect}" + "#{@message} should have changed, but is still #{@before.inspect}" end end - def result - @message || "result" - end - def actual_delta @after - @before end - def negative_failure_message - "#{result} should not have changed, but did change from #{@before.inspect} to #{@after.inspect}" + def failure_message_for_should_not + "#{@message} should not have changed, but did change from #{@before.inspect} to #{@after.inspect}" end def by(amount) @@ -84,6 +83,10 @@ EOF @from = from self end + + def description + "change ##{@message}" + end end # :call-seq: @@ -125,20 +128,24 @@ EOF # employee.develop_great_new_social_networking_app # }.should change(employee, :title).from("Mail Clerk").to("CEO") # - # Evaluates +receiver.message+ or +block+ before and - # after it evaluates the c object (generated by the lambdas in the examples above). + # 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. # - # Then compares the values before and after the +receiver.message+ 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>. # - # == Warning - # +should_not+ +change+ only supports the form with no subsequent calls to - # +by+, +by_at_least+, +by_at_most+, +to+ or +from+. + # 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). # - # blocks passed to +should+ +change+ and +should_not+ +change+ - # must use the <tt>{}</tt> form (<tt>do/end</tt> is not supported) - def change(target=nil, message=nil, &block) - Matchers::Change.new(target, message, &block) + def change(receiver=nil, message=nil, &block) + Matchers::Change.new(receiver, message, &block) end end end diff --git a/vendor/plugins/rspec/lib/spec/matchers/eql.rb b/vendor/plugins/rspec/lib/spec/matchers/eql.rb index 280ca5454..98ab198d9 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/eql.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/eql.rb @@ -1,29 +1,5 @@ module Spec module Matchers - - class Eql #:nodoc: - def initialize(expected) - @expected = expected - end - - def matches?(actual) - @actual = actual - @actual.eql?(@expected) - end - - def failure_message - return "expected #{@expected.inspect}, got #{@actual.inspect} (using .eql?)", @expected, @actual - end - - def negative_failure_message - return "expected #{@actual.inspect} not to equal #{@expected.inspect} (using .eql?)", @expected, @actual - end - - def description - "eql #{@expected.inspect}" - end - end - # :call-seq: # should eql(expected) # should_not eql(expected) @@ -37,7 +13,30 @@ module Spec # 5.should eql(5) # 5.should_not eql(3) def eql(expected) - Matchers::Eql.new(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/plugins/rspec/lib/spec/matchers/equal.rb b/vendor/plugins/rspec/lib/spec/matchers/equal.rb index 4bfc74951..3580a95af 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/equal.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/equal.rb @@ -1,29 +1,6 @@ module Spec module Matchers - - class Equal #:nodoc: - def initialize(expected) - @expected = expected - end - - def matches?(actual) - @actual = actual - @actual.equal?(@expected) - end - - def failure_message - return "expected #{@expected.inspect}, got #{@actual.inspect} (using .equal?)", @expected, @actual - end - def negative_failure_message - return "expected #{@actual.inspect} not to equal #{@expected.inspect} (using .equal?)", @expected, @actual - end - - def description - "equal #{@expected.inspect}" - end - end - # :call-seq: # should equal(expected) # should_not equal(expected) @@ -37,7 +14,40 @@ module Spec # 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) - Matchers::Equal.new(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/plugins/rspec/lib/spec/matchers/exist.rb b/vendor/plugins/rspec/lib/spec/matchers/exist.rb index a5a911132..dc69c683d 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/exist.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/exist.rb @@ -1,17 +1,16 @@ module Spec module Matchers - class Exist - def matches? actual - @actual = actual - @actual.exist? - end - def failure_message - "expected #{@actual.inspect} to exist, but it doesn't." - end - def negative_failure_message - "expected #{@actual.inspect} to not exist, but it does." + # :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 - def exist; Exist.new; end end end diff --git a/vendor/plugins/rspec/lib/spec/matchers/has.rb b/vendor/plugins/rspec/lib/spec/matchers/has.rb index 60199f54d..7073e0a86 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/has.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/has.rb @@ -1,34 +1,35 @@ module Spec module Matchers - class Has #:nodoc: - def initialize(sym, *args) - @sym = sym - @args = args + class Has + + def initialize(expected, *args) + @expected, @args = expected, args end - def matches?(target) - target.send(predicate, *@args) + def matches?(actual) + actual.__send__(predicate(@expected), *@args) end - def failure_message - "expected ##{predicate}(#{@args[0].inspect}) to return true, got false" + def failure_message_for_should + "expected ##{predicate(@expected)}(#{@args[0].inspect}) to return true, got false" end - def negative_failure_message - "expected ##{predicate}(#{@args[0].inspect}) to return false, got true" + 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 - private - def predicate - "#{@sym.to_s.sub("have_","has_")}?".to_sym - end - end - + end end diff --git a/vendor/plugins/rspec/lib/spec/matchers/have.rb b/vendor/plugins/rspec/lib/spec/matchers/have.rb index 47454e3be..2975ee129 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/have.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/have.rb @@ -1,10 +1,10 @@ module Spec module Matchers - class Have #:nodoc: def initialize(expected, relativity=:exactly) @expected = (expected == :no ? 0 : expected) @relativity = relativity + @actual = nil end def relativities @@ -15,23 +15,15 @@ module Spec } end - def method_missing(sym, *args, &block) - @collection_name = sym - @plural_collection_name = Inflector.pluralize(sym.to_s) if Object.const_defined?(:Inflector) - @args = args - @block = block - self - end - def matches?(collection_owner) if collection_owner.respond_to?(@collection_name) - collection = collection_owner.send(@collection_name, *@args, &@block) + 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) + 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) + collection_owner.__send__(@collection_name, *@args, &@block) end @actual = collection.size if collection.respond_to?(:size) @actual = collection.length if collection.respond_to?(:length) @@ -45,11 +37,11 @@ module Spec "expected #{@collection_name} to be a collection but it does not respond to #length or #size" end - def failure_message + def failure_message_for_should "expected #{relative_expectation} #{@collection_name}, got #{@actual}" end - def negative_failure_message + def failure_message_for_should_not if @relativity == :exactly return "expected target not to have #{@expected} #{@collection_name}, got #{@actual}" elsif @relativity == :at_most @@ -75,8 +67,22 @@ EOF "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 diff --git a/vendor/plugins/rspec/lib/spec/matchers/include.rb b/vendor/plugins/rspec/lib/spec/matchers/include.rb index 5476f97d8..a2a7fe3db 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/include.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/include.rb @@ -1,52 +1,5 @@ module Spec module Matchers - - class Include #:nodoc: - - def initialize(*expecteds) - @expecteds = expecteds - end - - def matches?(actual) - @actual = actual - @expecteds.each do |expected| - return false unless actual.include?(expected) - end - true - end - - def failure_message - _message - end - - def negative_failure_message - _message("not ") - end - - def description - "include #{_pretty_print(@expecteds)}" - end - - private - def _message(maybe_not="") - "expected #{@actual.inspect} #{maybe_not}to include #{_pretty_print(@expecteds)}" - 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 - # :call-seq: # should include(expected) # should_not include(expected) @@ -64,7 +17,28 @@ module Spec # "spread".should include("read") # "spread".should_not include("red") def include(*expected) - Matchers::Include.new(*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/plugins/rspec/lib/spec/matchers/match.rb b/vendor/plugins/rspec/lib/spec/matchers/match.rb index 61ab52429..b4b9ea864 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/match.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/match.rb @@ -1,41 +1,21 @@ module Spec module Matchers - - class Match #:nodoc: - def initialize(expected) - @expected = expected - end - - def matches?(actual) - @actual = actual - return true if actual =~ @expected - return false - end - - def failure_message - return "expected #{@actual.inspect} to match #{@expected.inspect}", @expected, @actual - end - - def negative_failure_message - return "expected #{@actual.inspect} not to match #{@expected.inspect}", @expected, @actual - end - - def description - "match #{@expected.inspect}" - end - end - # :call-seq: - # should match(regexp) - # should_not match(regexp) + # should match(pattern) + # should_not match(pattern) # - # Given a Regexp, passes if actual =~ regexp + # Given a Regexp or String, passes if actual.match(pattern) # # == Examples # - # email.should match(/^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i) - def match(regexp) - Matchers::Match.new(regexp) + # 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/plugins/rspec/lib/spec/matchers/operator_matcher.rb b/vendor/plugins/rspec/lib/spec/matchers/operator_matcher.rb index dd23a0994..30295be01 100755..100644 --- a/vendor/plugins/rspec/lib/spec/matchers/operator_matcher.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/operator_matcher.rb @@ -1,70 +1,75 @@ module Spec module Matchers - class BaseOperatorMatcher - attr_reader :generated_description - - def initialize(target) - @target = target - end - def ==(expected) - @expected = expected - __delegate_method_missing_to_target("==", expected) - end + class OperatorMatcher + class << self + def registry + @registry ||= {} + end - def ===(expected) - @expected = expected - __delegate_method_missing_to_target("===", expected) - end + def register(klass, operator, matcher) + registry[klass] ||= {} + registry[klass][operator] = matcher + end - def =~(expected) - @expected = expected - __delegate_method_missing_to_target("=~", expected) + def get(klass, operator) + registry[klass] && registry[klass][operator] + end end - def >(expected) - @expected = expected - __delegate_method_missing_to_target(">", expected) + def initialize(actual) + @actual = actual end - def >=(expected) - @expected = expected - __delegate_method_missing_to_target(">=", expected) + 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 - def <(expected) - @expected = expected - __delegate_method_missing_to_target("<", expected) + ['==', '===', '=~', '>', '>=', '<', '<='].each do |operator| + use_custom_matcher_or_delegate operator end - def <=(expected) - @expected = expected - __delegate_method_missing_to_target("<=", expected) + def fail_with_message(message) + Spec::Expectations.fail_with(message, @expected, @actual) end - def fail_with_message(message) - Spec::Expectations.fail_with(message, @expected, @target) + 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 < BaseOperatorMatcher #:nodoc: - - def __delegate_method_missing_to_target(operator, expected) - ::Spec::Matchers.generated_description = "should #{operator} #{expected.inspect}" - return if @target.send(operator, expected) - return fail_with_message("expected: #{expected.inspect},\n got: #{@target.inspect} (using #{operator})") if ['==','===', '=~'].include?(operator) - return fail_with_message("expected: #{operator} #{expected.inspect},\n got: #{operator.gsub(/./, ' ')} #{@target.inspect}") + 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 < BaseOperatorMatcher #:nodoc: - - def __delegate_method_missing_to_target(operator, expected) - ::Spec::Matchers.generated_description = "should not #{operator} #{expected.inspect}" - return unless @target.send(operator, expected) - return fail_with_message("expected not: #{operator} #{expected.inspect},\n got: #{operator.gsub(/./, ' ')} #{@target.inspect}") + 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 diff --git a/vendor/plugins/rspec/lib/spec/matchers/raise_error.rb b/vendor/plugins/rspec/lib/spec/matchers/raise_error.rb index c003849b6..65bdf2370 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/raise_error.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/raise_error.rb @@ -1,23 +1,24 @@ module Spec module Matchers class RaiseError #:nodoc: - def initialize(error_or_message=Exception, message=nil, &block) + def initialize(expected_error_or_message=Exception, expected_message=nil, &block) @block = block - case error_or_message + @actual_error = nil + case expected_error_or_message when String, Regexp - @expected_error, @expected_message = Exception, error_or_message + @expected_error, @expected_message = Exception, expected_error_or_message else - @expected_error, @expected_message = error_or_message, message + @expected_error, @expected_message = expected_error_or_message, expected_message end end - def matches?(proc) + def matches?(given_proc) @raised_expected_error = false @with_expected_message = false @eval_block = false @eval_block_passed = false begin - proc.call + given_proc.call rescue @expected_error => @actual_error @raised_expected_error = true @with_expected_message = verify_message @@ -31,7 +32,7 @@ module Spec eval_block if @raised_expected_error && @with_expected_message && @block end ensure - return (@raised_expected_error && @with_expected_message) ? (@eval_block ? @eval_block_passed : true) : false + return (@raised_expected_error & @with_expected_message) ? (@eval_block ? @eval_block_passed : true) : false end def eval_block @@ -47,24 +48,20 @@ module Spec def verify_message case @expected_message when nil - return true + true when Regexp - return @expected_message =~ @actual_error.message + @expected_message =~ @actual_error.message else - return @expected_message == @actual_error.message + @expected_message == @actual_error.message end end - def failure_message - if @eval_block - return @actual_error.message - else - return "expected #{expected_error}#{actual_error}" - end + def failure_message_for_should + @eval_block ? @actual_error.message : "expected #{expected_error}#{given_error}" end - def negative_failure_message - "expected no #{expected_error}#{actual_error}" + def failure_message_for_should_not + "expected no #{expected_error}#{given_error}" end def description @@ -83,7 +80,7 @@ module Spec end end - def actual_error + def given_error @actual_error.nil? ? " but nothing was raised" : ", got #{@actual_error.inspect}" end diff --git a/vendor/plugins/rspec/lib/spec/matchers/respond_to.rb b/vendor/plugins/rspec/lib/spec/matchers/respond_to.rb index 3d23422aa..9161cb94e 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/respond_to.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/respond_to.rb @@ -4,28 +4,54 @@ module Spec class RespondTo #:nodoc: def initialize(*names) @names = names + @expected_arity = nil @names_not_responded_to = [] end - def matches?(target) + def matches?(actual) + @actual = actual @names.each do |name| - unless target.respond_to?(name) - @names_not_responded_to << name - end + @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 - "expected target to respond to #{@names_not_responded_to.collect {|name| name.inspect }.join(', ')}" + def failure_message_for_should + "expected #{@actual.inspect} to respond to #{@names_not_responded_to.collect {|name| name.inspect }.join(', ')}#{with_arity}" end - def negative_failure_message - "expected target not to respond to #{@names.collect {|name| name.inspect }.join(', ')}" + def failure_message_for_should_not + "expected #{@actual.inspect} not to respond to #{@names.collect {|name| name.inspect }.join(', ')}" end def description - "respond to ##{@names.to_s}" + "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 diff --git a/vendor/plugins/rspec/lib/spec/matchers/satisfy.rb b/vendor/plugins/rspec/lib/spec/matchers/satisfy.rb index 6c0ca95bc..58e3f56aa 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/satisfy.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/satisfy.rb @@ -12,11 +12,11 @@ module Spec @block.call(actual) end - def failure_message + def failure_message_for_should "expected #{@actual} to satisfy block" end - def negative_failure_message + def failure_message_for_should_not "expected #{@actual} not to satisfy block" end end diff --git a/vendor/plugins/rspec/lib/spec/matchers/simple_matcher.rb b/vendor/plugins/rspec/lib/spec/matchers/simple_matcher.rb index ac547d06a..5ab7f3068 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/simple_matcher.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/simple_matcher.rb @@ -1,29 +1,133 @@ module Spec module Matchers class SimpleMatcher - attr_reader :description + 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?(actual) - @actual = actual - return @match_block.call(@actual) + 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() - return %[expected #{@description.inspect} but got #{@actual.inspect}] + def failure_message_for_should + @failure_message || (@description.nil? ? explanation : %[expected #{@description.inspect} but got #{@given.inspect}]) end - - def negative_failure_message() - return %[expected not to get #{@description.inspect}, but got #{@actual.inspect}] + + 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 - - def simple_matcher(message, &match_block) - SimpleMatcher.new(message, &match_block) + + # 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) + SimpleMatcher.new(description, &match_block) end end end
\ No newline at end of file diff --git a/vendor/plugins/rspec/lib/spec/matchers/throw_symbol.rb b/vendor/plugins/rspec/lib/spec/matchers/throw_symbol.rb index c74d84436..da16bb654 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/throw_symbol.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/throw_symbol.rb @@ -2,39 +2,58 @@ module Spec module Matchers class ThrowSymbol #:nodoc: - def initialize(expected=nil) - @expected = expected - @actual = nil + def initialize(expected_symbol = nil, expected_arg=nil) + @expected_symbol = expected_symbol + @expected_arg = expected_arg + @caught_symbol = @caught_arg = nil end - def matches?(proc) + def matches?(given_proc) begin - proc.call - rescue NameError => e - raise e unless e.message =~ /uncaught throw/ - @actual = e.name.to_sym + 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 + ensure - if @expected.nil? - return @actual.nil? ? false : true + if @expected_symbol.nil? + return !@caught_symbol.nil? else - return @actual == @expected + if @expected_arg.nil? + return @caught_symbol == @expected_symbol + else + return (@caught_symbol == @expected_symbol) & (@caught_arg == @expected_arg) + end end end end - def failure_message - if @actual - "expected #{expected}, got #{@actual.inspect}" + def failure_message_for_should + if @caught_symbol + "expected #{expected}, got #{@caught_symbol.inspect}" else "expected #{expected} but nothing was thrown" end end - def negative_failure_message - if @expected + def failure_message_for_should_not + if @expected_symbol "expected #{expected} not to be thrown" else - "expected no Symbol, got :#{@actual}" + "expected no Symbol, got :#{@caught_symbol}" end end @@ -45,7 +64,11 @@ module Spec private def expected - @expected.nil? ? "a Symbol" : @expected.inspect + @expected_symbol.nil? ? "a Symbol" : "#{@expected_symbol.inspect}#{args}" + end + + def args + @expected_arg.nil? ? "" : " with #{@expected_arg.inspect}" end end @@ -53,20 +76,27 @@ module Spec # :call-seq: # should throw_symbol() # should throw_symbol(:sym) + # should throw_symbol(:sym, arg) # should_not throw_symbol() # should_not throw_symbol(:sym) - # - # Given a Symbol argument, matches if a proc throws the specified Symbol. + # 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(sym=nil) Matchers::ThrowSymbol.new(sym) end diff --git a/vendor/plugins/rspec/lib/spec/mocks.rb b/vendor/plugins/rspec/lib/spec/mocks.rb index 678dd6aae..339c0cc50 100644 --- a/vendor/plugins/rspec/lib/spec/mocks.rb +++ b/vendor/plugins/rspec/lib/spec/mocks.rb @@ -1,16 +1,5 @@ require 'spec/mocks/framework' -require 'spec/mocks/methods' -require 'spec/mocks/argument_constraint_matchers' -require 'spec/mocks/spec_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/extensions/object' -require 'spec/mocks/space' module Spec # == Mocks and Stubs @@ -116,11 +105,11 @@ module Spec # my_mock.should_receive(:sym).with(*args) # my_mock.should_not_receive(:sym).with(*args) # - # == Argument Constraints using Expression Matchers + # == 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 the Expression Matchers. + # 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. # @@ -131,7 +120,7 @@ module Spec # # my_mock.should_receive(:sym).with(no_args()) # my_mock.should_receive(:sym).with(any_args()) - # my_mock.should_receive(:sym).with(1, an_instance_of(Numeric), "b") #2nd argument can any type of Numeric + # 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 diff --git a/vendor/plugins/rspec/lib/spec/mocks/argument_constraint_matchers.rb b/vendor/plugins/rspec/lib/spec/mocks/argument_constraint_matchers.rb deleted file mode 100644 index 96ccf0f4a..000000000 --- a/vendor/plugins/rspec/lib/spec/mocks/argument_constraint_matchers.rb +++ /dev/null @@ -1,31 +0,0 @@ -module Spec - module Mocks - module ArgumentConstraintMatchers - - # Shortcut for creating an instance of Spec::Mocks::DuckTypeArgConstraint - def duck_type(*args) - DuckTypeArgConstraint.new(*args) - end - - def any_args - AnyArgsConstraint.new - end - - def anything - AnyArgConstraint.new(nil) - end - - def boolean - BooleanArgConstraint.new(nil) - end - - def hash_including(expected={}) - HashIncludingConstraint.new(expected) - end - - def no_args - NoArgsConstraint.new - end - end - end -end diff --git a/vendor/plugins/rspec/lib/spec/mocks/argument_expectation.rb b/vendor/plugins/rspec/lib/spec/mocks/argument_expectation.rb index b3fdcc80d..b51b7bae5 100644 --- a/vendor/plugins/rspec/lib/spec/mocks/argument_expectation.rb +++ b/vendor/plugins/rspec/lib/spec/mocks/argument_expectation.rb @@ -1,208 +1,50 @@ module Spec module Mocks - - class MatcherConstraint - def initialize(matcher) - @matcher = matcher - end - - def matches?(value) - @matcher.matches?(value) - end - end - - class LiteralArgConstraint - def initialize(literal) - @literal_value = literal - end - - def matches?(value) - @literal_value == value - end - end - - class RegexpArgConstraint - def initialize(regexp) - @regexp = regexp - end - - def matches?(value) - return value =~ @regexp unless value.is_a?(Regexp) - value == @regexp - end - end - - class AnyArgConstraint - def initialize(ignore) - end - - def ==(other) - true - end - - # TODO - need this? - def matches?(value) - true - end - end - - class AnyArgsConstraint - def description - "any args" - end - end - - class NoArgsConstraint - def description - "no args" - end - - def ==(args) - args == [] - end - end - - class NumericArgConstraint - def initialize(ignore) - end - - def matches?(value) - value.is_a?(Numeric) - end - end - class BooleanArgConstraint - def initialize(ignore) - end - - def ==(value) - matches?(value) - end - - def matches?(value) - return true if value.is_a?(TrueClass) - return true if value.is_a?(FalseClass) - false - end - end - - class StringArgConstraint - def initialize(ignore) - end - - def matches?(value) - value.is_a?(String) - end - end - - class DuckTypeArgConstraint - def initialize(*methods_to_respond_to) - @methods_to_respond_to = methods_to_respond_to - end - - def matches?(value) - @methods_to_respond_to.all? { |sym| value.respond_to?(sym) } - end - - def description - "duck_type" - end - end - - class HashIncludingConstraint - def initialize(expected) - @expected = expected - end - - def ==(actual) - @expected.each do | key, value | - # check key for case that value evaluates to nil - return false unless actual.has_key?(key) && actual[key] == value - end - true - rescue NoMethodError => ex - return false - end - - def matches?(value) - self == value - end - - def description - "hash_including(#{@expected.inspect.sub(/^\{/,"").sub(/\}$/,"")})" - end - - end - - class ArgumentExpectation attr_reader :args - @@constraint_classes = Hash.new { |hash, key| LiteralArgConstraint} - @@constraint_classes[:anything] = AnyArgConstraint - @@constraint_classes[:numeric] = NumericArgConstraint - @@constraint_classes[:boolean] = BooleanArgConstraint - @@constraint_classes[:string] = StringArgConstraint - def initialize(args) + def initialize(args, &block) @args = args - if [:any_args] == args - @expected_params = nil - warn_deprecated(:any_args.inspect, "any_args()") - elsif args.length == 1 && args[0].is_a?(AnyArgsConstraint) then @expected_params = nil - elsif [:no_args] == args - @expected_params = [] - warn_deprecated(:no_args.inspect, "no_args()") - elsif args.length == 1 && args[0].is_a?(NoArgsConstraint) then @expected_params = [] - else @expected_params = process_arg_constraints(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 process_arg_constraints(constraints) - constraints.collect do |constraint| - convert_constraint(constraint) - 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 warn_deprecated(deprecated_method, instead) - Kernel.warn "The #{deprecated_method} constraint is deprecated. Use #{instead} instead." + def is_matcher?(obj) + return obj.respond_to?(:matches?) & obj.respond_to?(:description) end - def convert_constraint(constraint) - if [:anything, :numeric, :boolean, :string].include?(constraint) - case constraint - when :anything - instead = "anything()" - when :boolean - instead = "boolean()" - when :numeric - instead = "an_instance_of(Numeric)" - when :string - instead = "an_instance_of(String)" - end - warn_deprecated(constraint.inspect, instead) - return @@constraint_classes[constraint].new(constraint) - end - return MatcherConstraint.new(constraint) if is_matcher?(constraint) - return RegexpArgConstraint.new(constraint) if constraint.is_a?(Regexp) - return LiteralArgConstraint.new(constraint) + def args_match?(given_args) + match_any_args? || matchers_block_matches?(given_args) || matchers_match?(given_args) end - def is_matcher?(obj) - return obj.respond_to?(:matches?) && obj.respond_to?(:description) + def matchers_block_matches?(given_args) + @matchers_block ? @matchers_block.call(*given_args) : nil end - def check_args(args) - return true if @expected_params.nil? - return true if @expected_params == args - return constraints_match?(args) + def matchers_match?(given_args) + @matchers == given_args end - def constraints_match?(args) - return false if args.length != @expected_params.length - @expected_params.each_index { |i| return false unless @expected_params[i].matches?(args[i]) } - return true + def match_any_args? + @match_any_args end - + end end diff --git a/vendor/plugins/rspec/lib/spec/mocks/error_generator.rb b/vendor/plugins/rspec/lib/spec/mocks/error_generator.rb index 01d8f720d..f63811fed 100644 --- a/vendor/plugins/rspec/lib/spec/mocks/error_generator.rb +++ b/vendor/plugins/rspec/lib/spec/mocks/error_generator.rb @@ -3,7 +3,8 @@ module Spec class ErrorGenerator attr_writer :opts - def initialize(target, name) + def initialize(target, name, options={}) + @declared_as = options[:__declared_as] || 'Mock' @target = target @name = name end @@ -19,7 +20,7 @@ module Spec 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} expected #{expectation.sym.inspect} with #{expected_args} but received it with #{actual_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) @@ -42,9 +43,20 @@ module Spec __raise "#{intro} yielded |#{arg_list(*args_to_yield)}| to block with arity of #{arity}" end - private + private + def intro - @name ? "Mock '#{@name}'" : @target.inspect + 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) @@ -57,15 +69,11 @@ module Spec end def format_args(*args) - return "(no args)" if args.empty? || args == [:no_args] - return "(any args)" if args == [:any_args] - "(" + arg_list(*args) + ")" + args.empty? ? "(no args)" : "(" + arg_list(*args) + ")" end def arg_list(*args) - args.collect do |arg| - arg.respond_to?(:description) ? arg.description : arg.inspect - end.join(", ") + args.collect {|arg| arg.respond_to?(:description) ? arg.description : arg.inspect}.join(", ") end def count_message(count) diff --git a/vendor/plugins/rspec/lib/spec/mocks/errors.rb b/vendor/plugins/rspec/lib/spec/mocks/errors.rb index 68fdfe006..560b66a93 100644 --- a/vendor/plugins/rspec/lib/spec/mocks/errors.rb +++ b/vendor/plugins/rspec/lib/spec/mocks/errors.rb @@ -1,6 +1,6 @@ module Spec module Mocks - class MockExpectationError < StandardError + class MockExpectationError < Exception end class AmbiguousReturnError < StandardError diff --git a/vendor/plugins/rspec/lib/spec/mocks/framework.rb b/vendor/plugins/rspec/lib/spec/mocks/framework.rb index 92089673a..e25778655 100644 --- a/vendor/plugins/rspec/lib/spec/mocks/framework.rb +++ b/vendor/plugins/rspec/lib/spec/mocks/framework.rb @@ -3,8 +3,8 @@ # object in the system. require 'spec/mocks/methods' -require 'spec/mocks/argument_constraint_matchers' -require 'spec/mocks/spec_methods' +require 'spec/mocks/argument_matchers' +require 'spec/mocks/example_methods' require 'spec/mocks/proxy' require 'spec/mocks/mock' require 'spec/mocks/argument_expectation' diff --git a/vendor/plugins/rspec/lib/spec/mocks/message_expectation.rb b/vendor/plugins/rspec/lib/spec/mocks/message_expectation.rb index 0b10290b3..8a8133f69 100644 --- a/vendor/plugins/rspec/lib/spec/mocks/message_expectation.rb +++ b/vendor/plugins/rspec/lib/spec/mocks/message_expectation.rb @@ -3,17 +3,20 @@ module Spec 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={}) + 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 - @return_block = nil @actual_received_count = 0 @expected_received_count = expected_received_count - @args_expectation = ArgumentExpectation.new([AnyArgsConstraint.new]) + @args_expectation = ArgumentExpectation.new([ArgumentMatchers::AnyArgsMatcher.new]) @consecutive = false @exception_to_raise = nil @symbol_to_throw = nil @@ -21,6 +24,22 @@ module Spec @at_least = nil @at_most = nil @args_to_yield = [] + @failed_fast = nil + @args_to_yield_were_cloned = false + @return_block = implementation + 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 @@ -39,8 +58,6 @@ module Spec @expected_received_count < values.size end @return_block = block_given? ? return_block : lambda { value } - # Ruby 1.9 - see where this is used below - @ignore_args = !block_given? end # :call-seq: @@ -63,16 +80,22 @@ module Spec end def and_yield(*args) + if @args_to_yield_were_cloned + @args_to_yield.clear + @args_to_yield_were_cloned = false + end + @args_to_yield << args self end - + def matches(sym, args) - @sym == sym and @args_expectation.check_args(args) + @sym == sym and @args_expectation.args_match?(args) end - def invoke(args, block) + 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 @@ -85,17 +108,17 @@ module Spec if !@method_block.nil? - default_return_val = invoke_method_block(args) + default_return_val = invoke_method_block(*args) elsif @args_to_yield.size > 0 - default_return_val = invoke_with_yield(block) + default_return_val = invoke_with_yield(&block) else default_return_val = nil end if @consecutive - return invoke_consecutive_return_block(args, block) + return invoke_consecutive_return_block(*args, &block) elsif @return_block - return invoke_return_block(args, block) + return invoke_return_block(*args, &block) else return default_return_val end @@ -103,10 +126,23 @@ module Spec @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) + def invoke_method_block(*args) begin @method_block.call(*args) rescue => detail @@ -114,7 +150,7 @@ module Spec end end - def invoke_with_yield(block) + def invoke_with_yield(&block) if block.nil? @error_generator.raise_missing_block_error @args_to_yield end @@ -128,35 +164,34 @@ module Spec value end - def invoke_consecutive_return_block(args, block) - args << block unless block.nil? - value = @return_block.call(*args) - + 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 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 - if @ignore_args - @return_block.call() - else - @return_block.call(*args) - 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) - @sym == sym and not @args_expectation.check_args(args) + matches_name?(sym) and not @args_expectation.args_match?(args) end - def verify_messages_received - return if expected_messages_received? + def verify_messages_received + return if expected_messages_received? || failed_fast? generate_error rescue Spec::Mocks::MockExpectationError => error @@ -197,13 +232,12 @@ module Spec 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.first) + @error_generator.raise_unexpected_message_args_error(self, *@similar_messages) end end def with(*args, &block) - @method_block = block if block - @args_expectation = ArgumentExpectation.new(args) + @args_expectation = ArgumentExpectation.new(args, &block) self end @@ -274,6 +308,10 @@ module Spec 2 end end + + def clear_actual_received_count! + @actual_received_count = 0 + end end diff --git a/vendor/plugins/rspec/lib/spec/mocks/methods.rb b/vendor/plugins/rspec/lib/spec/mocks/methods.rb index d9fa324d3..16dd6e842 100644 --- a/vendor/plugins/rspec/lib/spec/mocks/methods.rb +++ b/vendor/plugins/rspec/lib/spec/mocks/methods.rb @@ -9,8 +9,50 @@ module Spec __mock_proxy.add_negative_message_expectation(caller(1)[0], sym.to_sym, &block) end - def stub!(sym, opts={}) - __mock_proxy.add_stub(caller(1)[0], sym.to_sym, opts) + 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 def received_message?(sym, *args, &block) #:nodoc: @@ -24,6 +66,14 @@ module Spec def rspec_reset #:nodoc: __mock_proxy.reset end + + def as_null_object + __mock_proxy.as_null_object + end + + def null_object? + __mock_proxy.null_object? + end private @@ -31,7 +81,7 @@ module Spec if Mock === self @mock_proxy ||= Proxy.new(self, @name, @options) else - @mock_proxy ||= Proxy.new(self, self.class.name) + @mock_proxy ||= Proxy.new(self) end end end diff --git a/vendor/plugins/rspec/lib/spec/mocks/mock.rb b/vendor/plugins/rspec/lib/spec/mocks/mock.rb index d0b5f204d..35a6c798e 100644 --- a/vendor/plugins/rspec/lib/spec/mocks/mock.rb +++ b/vendor/plugins/rspec/lib/spec/mocks/mock.rb @@ -7,23 +7,37 @@ module Spec # 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, stubs_and_options={}) - @name = name - @options = parse_options(stubs_and_options) + 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 - # This is an unfortunate side effect from ActiveRecord, but this should - # be safe unless the RHS redefines == in a nonsensical manner + # 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.instance_eval {@messages_received << [sym, args, block]} + __mock_proxy.record_message_received(sym, args, block) begin return self if __mock_proxy.null_object? super(sym, *args, &block) @@ -31,22 +45,27 @@ module Spec __mock_proxy.raise_unexpected_message_error sym, *args end end - - def inspect - "#<#{self.class}:#{sprintf '0x%x', self.object_id} @name=#{@name.inspect}>" + + 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 - private - - def parse_options(options) - options.has_key?(:null_object) ? {:null_object => options.delete(:null_object)} : {} + def extract_option(source, target, key, default=nil) + if source[key] + target[key] = source.delete(key) + elsif default + target[key] = default end - - def assign_stubs(stubs) - stubs.each_pair do |message, response| - stub!(message).and_return(response) - 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/plugins/rspec/lib/spec/mocks/proxy.rb b/vendor/plugins/rspec/lib/spec/mocks/proxy.rb index 45b96a30b..acf72e0f3 100644 --- a/vendor/plugins/rspec/lib/spec/mocks/proxy.rb +++ b/vendor/plugins/rspec/lib/spec/mocks/proxy.rb @@ -4,41 +4,75 @@ module Spec 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, options={}) + def initialize(target, name=nil, options={}) @target = target @name = name - @error_generator = ErrorGenerator.new target, 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) + def add_message_expectation(expected_from, sym, opts={}, &block) __add sym - @expectations << MessageExpectation.new(@error_generator, @expectation_ordering, expected_from, sym, block_given? ? block : nil, 1, opts) + warn_if_nil_class sym + if existing_stub = @stubs.detect {|s| s.sym == sym } + expectation = existing_stub.build_child(expected_from, block_given?? block : nil, 1, opts) + else + expectation = MessageExpectation.new(@error_generator, @expectation_ordering, expected_from, sym, block_given? ? block : nil, 1, opts) + end + @expectations << expectation @expectations.last 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={}) + def add_stub(expected_from, sym, opts={}, &implementation) __add sym - @stubs.unshift MessageExpectation.new(@error_generator, @expectation_ordering, expected_from, sym, nil, :any, opts) + @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 @@ -50,6 +84,7 @@ module Spec clear_stubs reset_proxied_methods clear_proxied_methods + reset_nil_expectations_warning end def received_message?(sym, *args, &block) @@ -59,20 +94,27 @@ module Spec def has_negative_expectation?(sym) @expectations.detect {|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) - if expectation = find_matching_expectation(sym, *args) - expectation.invoke(args, block) - elsif (stub = find_matching_method_stub(sym, *args)) + expectation = find_matching_expectation(sym, *args) + stub = find_matching_method_stub(sym, *args) + + if (stub && expectation && expectation.called_max_times?) || (stub && !expectation) if expectation = find_almost_matching_expectation(sym, *args) expectation.advise(args, block) unless expectation.expected_messages_received? end - stub.invoke([], block) + stub.invoke(*args, &block) + elsif expectation + expectation.invoke(*args, &block) elsif expectation = find_almost_matching_expectation(sym, *args) expectation.advise(args, block) if null_object? unless expectation.expected_messages_received? raise_unexpected_message_args_error(expectation, *args) unless (has_negative_expectation?(sym) or null_object?) else - @target.send :method_missing, sym, *args, &block + @target.__send__ :method_missing, sym, *args, &block end end @@ -84,6 +126,10 @@ module Spec @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) @@ -91,28 +137,35 @@ module Spec 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) - visibility_string = "#{visibility(sym)} :#{sym}" - if target_responds_to?(sym) && !target_metaclass.method_defined?(munge(sym)) - munged_sym = munge(sym) - target_metaclass.instance_eval do - alias_method munged_sym, sym if method_defined?(sym.to_s) + 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 - @proxied_methods << sym + target_metaclass.class_eval(<<-EOF, __FILE__, __LINE__) + def #{sym}(*args, &block) + __mock_proxy.message_received :#{sym}, *args, &block + end + #{visibility_string} + EOF end - - target_metaclass.class_eval(<<-EOF, __FILE__, __LINE__) - def #{sym}(*args, &block) - __mock_proxy.message_received :#{sym}, *args, &block - end - #{visibility_string} - EOF end def target_responds_to?(sym) - return @target.send(munge(:respond_to?),sym) if @already_proxied_respond_to + 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) + return @target.respond_to?(sym, true) end def visibility(sym) @@ -128,7 +181,7 @@ module Spec end def munge(sym) - "proxied_by_rspec__#{sym.to_s}".to_sym + "proxied_by_rspec__#{sym}" end def clear_expectations @@ -155,19 +208,31 @@ module Spec def reset_proxied_methods @proxied_methods.each do |sym| - munged_sym = munge(sym) - target_metaclass.instance_eval do - if method_defined?(munged_sym.to_s) - alias_method sym, munged_sym - undef_method munged_sym - else - undef_method sym - end + reset_proxied_method(sym) + end + 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 @@ -175,10 +240,6 @@ module Spec @expectations.find {|expectation| expectation.matches_name_but_not_args(sym, args)} end - def find_matching_method_stub(sym, *args) - @stubs.find {|stub| stub.matches(sym, args)} - end - end end end diff --git a/vendor/plugins/rspec/lib/spec/mocks/spec_methods.rb b/vendor/plugins/rspec/lib/spec/mocks/spec_methods.rb deleted file mode 100644 index d92a4cedd..000000000 --- a/vendor/plugins/rspec/lib/spec/mocks/spec_methods.rb +++ /dev/null @@ -1,38 +0,0 @@ -module Spec - module Mocks - module ExampleMethods - include Spec::Mocks::ArgumentConstraintMatchers - - # Shortcut for creating an instance of Spec::Mocks::Mock. - # - # +name+ is used for failure reporting, so you should use the - # role that the mock 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 - # - # stub_thing = mock("thing", :a => "A") - # stub_thing.a == "A" => true - # - # stub_person = stub("thing", :name => "Joe", :email => "joe@domain.com") - # stub_person.name => "Joe" - # stub_person.email => "joe@domain.com" - def mock(name, stubs_and_options={}) - Spec::Mocks::Mock.new(name, stubs_and_options) - end - - alias :stub :mock - - # 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') - mock(name, :null_object => true) - end - - end - end -end diff --git a/vendor/plugins/rspec/lib/spec/rake/spectask.rb b/vendor/plugins/rspec/lib/spec/rake/spectask.rb index ecf39506d..9049fd08e 100644 --- a/vendor/plugins/rspec/lib/spec/rake/spectask.rb +++ b/vendor/plugins/rspec/lib/spec/rake/spectask.rb @@ -48,7 +48,6 @@ module Spec # This task can also be used to run existing Test::Unit tests and get RSpec # output, for example like this: # - # require 'rubygems' # require 'spec/rake/spectask' # Spec::Rake::SpecTask.new do |t| # t.ruby_opts = ['-rtest/unit'] @@ -56,12 +55,10 @@ module Spec # end # class SpecTask < ::Rake::TaskLib - class << self - def attr_accessor(*names) - super(*names) - names.each do |name| - module_eval "def #{name}() evaluate(@#{name}) end" # Allows use of procs - end + def self.attr_accessor(*names) + super(*names) + names.each do |name| + module_eval "def #{name}() evaluate(@#{name}) end" # Allows use of procs end end @@ -107,7 +104,7 @@ module Spec # A message to print to stderr when there are failures. attr_accessor :failure_message - # Where RSpec's output is written. Defaults to STDOUT. + # Where RSpec's output is written. Defaults to $stdout. # DEPRECATED. Use --format FORMAT:WHERE in spec_opts. attr_accessor :out @@ -122,10 +119,13 @@ module Spec # 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 = [File.expand_path(File.dirname(__FILE__) + '/../../../lib')] + @libs = ['lib'] @pattern = nil @spec_files = nil @spec_opts = [] @@ -142,7 +142,7 @@ module Spec end def define # :nodoc: - spec_script = File.expand_path(File.dirname(__FILE__) + '/../../../bin/spec') + 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 @@ -155,30 +155,23 @@ module Spec # ruby [ruby_opts] -Ilib -S rcov [rcov_opts] bin/spec -- examples [spec_opts] # or # ruby [ruby_opts] -Ilib bin/spec examples [spec_opts] - cmd = "#{File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name'])} " - - rb_opts = ruby_opts.clone - rb_opts << "-I\"#{lib_path}\"" - rb_opts << "-S rcov" if rcov - rb_opts << "-w" if warning - cmd << rb_opts.join(" ") - cmd << " " - cmd << rcov_option_list - cmd << %[ -o "#{rcov_dir}" ] if rcov - cmd << %Q|"#{spec_script}"| - cmd << " " - cmd << "-- " if rcov - cmd << spec_file_list.collect { |fn| %["#{fn}"] }.join(' ') - cmd << " " - cmd << spec_option_list + 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 << " " - cmd << %Q| > "#{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 - if verbose - puts cmd - 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 @@ -202,8 +195,11 @@ module Spec end def rcov_option_list # :nodoc: - return "" unless rcov - ENV['RCOV_OPTS'] || rcov_opts.join(" ") || "" + if rcov + ENV['RCOV_OPTS'] || rcov_opts.join(" ") || "" + else + "" + end end def spec_option_list # :nodoc: @@ -232,4 +228,3 @@ module Spec end end end - diff --git a/vendor/plugins/rspec/lib/spec/rake/verify_rcov.rb b/vendor/plugins/rspec/lib/spec/rake/verify_rcov.rb index 3328f9e9a..199bd8546 100644 --- a/vendor/plugins/rspec/lib/spec/rake/verify_rcov.rb +++ b/vendor/plugins/rspec/lib/spec/rake/verify_rcov.rb @@ -35,11 +35,11 @@ module RCov def define desc "Verify that rcov coverage is at least #{threshold}%" task @name do - total_coverage = nil + total_coverage = 0 File.open(index_html).each_line do |line| - if line =~ /<tt class='coverage_total'>(\d+\.\d+)%<\/tt>/ - total_coverage = eval($1) + if line =~ /<tt class='coverage_total'>\s*(\d+\.\d+)%\s*<\/tt>/ + total_coverage = $1.to_f break end end diff --git a/vendor/plugins/rspec/lib/spec/runner.rb b/vendor/plugins/rspec/lib/spec/runner.rb index 97ef95bd2..519b536e2 100644 --- a/vendor/plugins/rspec/lib/spec/runner.rb +++ b/vendor/plugins/rspec/lib/spec/runner.rb @@ -1,3 +1,4 @@ +require 'spec/runner/configuration' require 'spec/runner/options' require 'spec/runner/option_parser' require 'spec/runner/example_group_runner' @@ -5,170 +6,26 @@ require 'spec/runner/command_line' require 'spec/runner/drb_command_line' require 'spec/runner/backtrace_tweaker' require 'spec/runner/reporter' -require 'spec/runner/spec_parser' +require 'spec/runner/line_number_query' require 'spec/runner/class_and_arguments_parser' +require 'spec/runner/extensions/kernel' module Spec - # == ExampleGroups and Examples - # - # Rather than expressing examples in classes, RSpec uses a custom DSLL (DSL light) to - # describe groups of examples. - # - # A ExampleGroup is the equivalent of a fixture in xUnit-speak. It is a metaphor for the context - # in which you will run your executable example - a set of known objects in a known starting state. - # We begin be describing - # - # describe Account do - # - # before do - # @account = Account.new - # end - # - # it "should have a balance of $0" do - # @account.balance.should == Money.new(0, :dollars) - # end - # - # end - # - # We use the before block to set up the Example (given), and then the #it method to - # hold the example code that expresses the event (when) and the expected outcome (then). - # - # == Helper Methods - # - # A primary goal of RSpec is to keep the examples clear. We therefore prefer - # less indirection than you might see in xUnit examples and in well factored, DRY production code. We feel - # that duplication is OK if removing it makes it harder to understand an example without - # having to look elsewhere to understand its context. - # - # That said, RSpec does support some level of encapsulating common code in helper - # methods that can exist within a context or within an included module. - # - # == Setup and Teardown - # - # You can use before and after within a Example. 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 behaviour, respectively before the first <code>before :each</code> - # and after the last <code>after :each</code>. 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 a context: - # - # describe "..." do - # - # it "..." do - # helper_method - # end - # - # def helper_method - # ... - # end - # - # end - # - # == Included helper methods - # - # You can include helper methods in multiple contexts by expressing them within - # a module, and then including that module in your context: - # - # 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 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::Example::Configuration.new + @configuration ||= Spec::Runner::Configuration.new end - + # Use this to configure various configurable aspects of # RSpec: # @@ -177,26 +34,33 @@ module Spec # end # # The yielded <tt>configuration</tt> object is a - # Spec::Example::Configuration instance. See its RDoc + # Spec::Runner::Configuration instance. See its RDoc # for details about what you can do with it. # def configure yield configuration end - def register_at_exit_hook # :nodoc: - $spec_runner_at_exit_hook_registered ||= nil - unless $spec_runner_at_exit_hook_registered - at_exit do - unless $! || Spec.run?; \ - success = Spec.run; \ - exit success if Spec.exit?; \ - end - end - $spec_runner_at_exit_hook_registered = true + 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 +end
\ No newline at end of file diff --git a/vendor/plugins/rspec/lib/spec/runner/backtrace_tweaker.rb b/vendor/plugins/rspec/lib/spec/runner/backtrace_tweaker.rb index 587e57d90..a3cb7d9bd 100644 --- a/vendor/plugins/rspec/lib/spec/runner/backtrace_tweaker.rb +++ b/vendor/plugins/rspec/lib/spec/runner/backtrace_tweaker.rb @@ -1,31 +1,53 @@ module Spec module Runner class BacktraceTweaker + def initialize(*patterns) + @ignore_patterns = [] + end + def clean_up_double_slashes(line) line.gsub!('//','/') end - end - class NoisyBacktraceTweaker < BacktraceTweaker + def ignore_patterns(*patterns) + # do nothing. Only QuietBacktraceTweaker ignores patterns. + end + + def ignored_patterns + [] + end + def tweak_backtrace(error) return if error.backtrace.nil? - error.backtrace.each do |line| - clean_up_double_slashes(line) + 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] + spec_files = Dir["lib/*"].map do |path| + subpath = path[1..-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/, @@ -37,20 +59,18 @@ module Spec /spec_server/ ] end - - def tweak_backtrace(error) - return if error.backtrace.nil? - error.backtrace.collect! do |line| - clean_up_double_slashes(line) - IGNORE_PATTERNS.each do |ignore| - if line =~ ignore - line = nil - break - end - end - line - end - error.backtrace.compact! + + 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 diff --git a/vendor/plugins/rspec/lib/spec/runner/class_and_arguments_parser.rb b/vendor/plugins/rspec/lib/spec/runner/class_and_arguments_parser.rb index 65dc4519c..a49ade26e 100644 --- a/vendor/plugins/rspec/lib/spec/runner/class_and_arguments_parser.rb +++ b/vendor/plugins/rspec/lib/spec/runner/class_and_arguments_parser.rb @@ -1,16 +1,14 @@ module Spec module Runner class ClassAndArgumentsParser - class << self - def parse(s) - if s =~ /([a-zA-Z_]+(?:::[a-zA-Z_]+)*):?(.*)/ - arg = $2 == "" ? nil : $2 - [$1, arg] - else - raise "Couldn't parse #{s.inspect}" - end + 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
\ No newline at end of file +end diff --git a/vendor/plugins/rspec/lib/spec/runner/command_line.rb b/vendor/plugins/rspec/lib/spec/runner/command_line.rb index 9849c4853..35a7e3159 100644 --- a/vendor/plugins/rspec/lib/spec/runner/command_line.rb +++ b/vendor/plugins/rspec/lib/spec/runner/command_line.rb @@ -2,26 +2,13 @@ require 'spec/runner/option_parser' module Spec module Runner - # Facade to run specs without having to fork a new ruby process (using `spec ...`) class CommandLine - class << self - # Runs specs. +argv+ is the commandline args as per the spec commandline API, +err+ - # and +out+ are the streams output will be written to. - def run(instance_rspec_options) - # NOTE - this call to init_rspec_options is not spec'd, but neither is any of this - # swapping of $rspec_options. That is all here to enable rspec to run against itself - # and maintain coverage in a single process. Therefore, DO NOT mess with this stuff - # unless you know what you are doing! - init_rspec_options(instance_rspec_options) - orig_rspec_options = rspec_options - begin - $rspec_options = instance_rspec_options - return $rspec_options.run_examples - ensure - ::Spec.run = true - $rspec_options = orig_rspec_options - end - end + 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 diff --git a/vendor/plugins/rspec/lib/spec/runner/drb_command_line.rb b/vendor/plugins/rspec/lib/spec/runner/drb_command_line.rb index 6c340cfea..058a8e1df 100644 --- a/vendor/plugins/rspec/lib/spec/runner/drb_command_line.rb +++ b/vendor/plugins/rspec/lib/spec/runner/drb_command_line.rb @@ -8,11 +8,17 @@ module Spec # CommandLine - making it possible for clients to use both interchangeably. def self.run(options) begin - DRb.start_service - spec_server = DRbObject.new_with_uri("druby://localhost:8989") + begin; \ + DRb.start_service("druby://localhost:0"); \ + rescue SocketError; \ + DRb.start_service("druby://:0"); \ + end + spec_server = DRbObject.new_with_uri("druby://127.0.0.1:8989") spec_server.run(options.argv, options.error_stream, options.output_stream) - rescue DRb::DRbConnError => e + true + rescue DRb::DRbConnError options.error_stream.puts "No server is running" + false end end end diff --git a/vendor/plugins/rspec/lib/spec/runner/example_group_runner.rb b/vendor/plugins/rspec/lib/spec/runner/example_group_runner.rb index 7275c6a88..67dc99509 100644 --- a/vendor/plugins/rspec/lib/spec/runner/example_group_runner.rb +++ b/vendor/plugins/rspec/lib/spec/runner/example_group_runner.rb @@ -6,6 +6,7 @@ module Spec 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 @@ -19,14 +20,15 @@ module Spec prepare success = true example_groups.each do |example_group| - success = success & example_group.run + success = success & example_group.run(@options) end return success ensure finish end - protected + protected + def prepare reporter.start(number_of_examples) example_groups.reverse! if reverse @@ -53,7 +55,5 @@ module Spec @options.number_of_examples end end - # TODO: BT - Deprecate BehaviourRunner? - BehaviourRunner = ExampleGroupRunner end -end
\ No newline at end of file +end diff --git a/vendor/plugins/rspec/lib/spec/runner/formatter/base_formatter.rb b/vendor/plugins/rspec/lib/spec/runner/formatter/base_formatter.rb index a1269b513..0fbc12ce4 100644 --- a/vendor/plugins/rspec/lib/spec/runner/formatter/base_formatter.rb +++ b/vendor/plugins/rspec/lib/spec/runner/formatter/base_formatter.rb @@ -1,12 +1,29 @@ module Spec module Runner module Formatter - # Baseclass for formatters that implements all required methods as no-ops. + # Formatter base-class, which implements all required methods as no-ops, with the exception class BaseFormatter - attr_accessor :example_group, :options, :where - def initialize(options, where) - @options = options - @where = where + # 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 @@ -14,42 +31,77 @@ module Spec # 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 #add_example_group + # 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. - # +example_group+ is the example_group. + # 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 # - # The next method to be invoked after this is #example_failed or #example_finished - def add_example_group(example_group) - @example_group = example_group + # ==== 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. - def example_started(example) + # 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. - def example_passed(example) + # +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). +counter+ is the - # sequence number of the failure (starting at 1) and +failure+ is the associated - # Failure object. - def example_failed(example, counter, failure) + # 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" - def example_pending(example, message) + # 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), + # to be invoked after this one is #dump_failure (once for each failed example) def start_dump end @@ -57,14 +109,24 @@ module Spec # 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 if option is set to do so. + # This gets invoked after the summary def dump_pending end diff --git a/vendor/plugins/rspec/lib/spec/runner/formatter/base_text_formatter.rb b/vendor/plugins/rspec/lib/spec/runner/formatter/base_text_formatter.rb index bad023db7..ee8db75a4 100644 --- a/vendor/plugins/rspec/lib/spec/runner/formatter/base_text_formatter.rb +++ b/vendor/plugins/rspec/lib/spec/runner/formatter/base_text_formatter.rb @@ -1,4 +1,5 @@ require 'spec/runner/formatter/base_formatter' +require 'fileutils' module Spec module Runner @@ -7,47 +8,47 @@ module Spec # non-text based ones too - just ignore the +output+ constructor # argument. class BaseTextFormatter < BaseFormatter - attr_reader :output, :pending_examples - # Creates a new instance that will write to +where+. If +where+ is a + 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 - # +where+ is exected to be an IO (or an object that responds to #puts and #write). - def initialize(options, where) - super - if where.is_a?(String) - @output = File.open(where, 'w') - elsif where == STDOUT - @output = Kernel - def @output.flush - STDOUT.flush - end + # +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 = where + @output = output end @pending_examples = [] end + + def example_group_started(example_group_proxy) + @example_group = example_group_proxy + end - def example_pending(example, message) - @pending_examples << [example.__full_description, message] + 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 colourise("#{failure.header}\n#{failure.exception.message}", failure) + @output.puts colorize_failure("#{failure.header}\n#{failure.exception.message}", failure) @output.puts format_backtrace(failure.exception.backtrace) @output.flush end - def colourise(s, failure) - if(failure.expectation_not_met?) - red(s) - elsif(failure.pending_fixed?) - blue(s) - else - magenta(s) - 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 @@ -74,16 +75,15 @@ module Spec @output.puts @output.puts "Pending:" @pending_examples.each do |pending_example| - @output.puts "#{pending_example[0]} (#{pending_example[1]})" + @output.puts "\n#{pending_example[0]} (#{pending_example[1]})" + @output.puts "#{pending_example[2]}\n" end end @output.flush end def close - if IO === @output - @output.close - end + @output.close if (IO === @output) & (@output != $stdout) end def format_backtrace(backtrace) @@ -94,11 +94,15 @@ module Spec protected def colour? - @options.colour ? true : false + !!@options.colour end def dry_run? - @options.dry_run ? true : false + !!@options.dry_run + end + + def autospec? + !!@options.autospec || ENV.has_key?("AUTOTEST") end def backtrace_line(line) @@ -106,13 +110,18 @@ module Spec end def colour(text, colour_code) - return text unless colour? && output_to_tty? + 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 == Kernel || @output.tty? + @output.tty? rescue NoMethodError false end @@ -120,10 +129,13 @@ module Spec def green(text); colour(text, "\e[32m"); end def red(text); colour(text, "\e[31m"); end - def magenta(text); colour(text, "\e[35m"); 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 diff --git a/vendor/plugins/rspec/lib/spec/runner/formatter/failing_example_groups_formatter.rb b/vendor/plugins/rspec/lib/spec/runner/formatter/failing_example_groups_formatter.rb index 8d39bc572..31729438b 100644 --- a/vendor/plugins/rspec/lib/spec/runner/formatter/failing_example_groups_formatter.rb +++ b/vendor/plugins/rspec/lib/spec/runner/formatter/failing_example_groups_formatter.rb @@ -6,21 +6,19 @@ module Spec class FailingExampleGroupsFormatter < BaseTextFormatter def example_failed(example, counter, failure) if @example_group - description_parts = @example_group.description_parts.collect do |description| - description =~ /(.*) \(druby.*\)$/ ? $1 : description - end - @output.puts ::Spec::Example::ExampleGroupMethods.description_text(*description_parts) + @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 diff --git a/vendor/plugins/rspec/lib/spec/runner/formatter/html_formatter.rb b/vendor/plugins/rspec/lib/spec/runner/formatter/html_formatter.rb index e5368f2cb..2d0c65d1b 100644 --- a/vendor/plugins/rspec/lib/spec/runner/formatter/html_formatter.rb +++ b/vendor/plugins/rspec/lib/spec/runner/formatter/html_formatter.rb @@ -1,22 +1,21 @@ 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 - def method_missing(sym, *args) - # no-op - end - # The number of the currently running example_group def example_group_number @example_group_number @@ -35,10 +34,9 @@ module Spec @output.flush end - def add_example_group(example_group) + def example_group_started(example_group) super @example_group_red = false - @example_group_red = false @example_group_number += 1 unless example_group_number == 1 @output.puts " </dl>" @@ -85,7 +83,7 @@ module Spec @output.flush end - def example_pending(example, message) + 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 @@ -154,14 +152,6 @@ module Spec font-size: 80%; } </style> -</head> -<body> -EOF - end - - def report_header - <<-EOF -<div class="rspec-report"> <script type="text/javascript"> // <![CDATA[ #{global_scripts} @@ -170,9 +160,19 @@ EOF <style type="text/css"> #{global_styles} </style> +</head> +<body> +EOF + end + + def report_header + <<-EOF +<div class="rspec-report"> <div id="rspec-header"> - <h1>RSpec Results</h1> + <div id="label"> + <h1>RSpec Code Examples</h1> + </div> <div id="summary"> <p id="totals"> </p> @@ -212,7 +212,7 @@ EOF def global_styles <<-EOF #rspec-header { - background: #65C400; color: #fff; + background: #65C400; color: #fff; height: 4em; } .rspec-report h1 { @@ -220,15 +220,16 @@ EOF 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; - position: absolute; top: 0px; right: 0px; + float:right; } #summary p { diff --git a/vendor/plugins/rspec/lib/spec/runner/formatter/nested_text_formatter.rb b/vendor/plugins/rspec/lib/spec/runner/formatter/nested_text_formatter.rb index f9aa5f67c..5caec5a4d 100644 --- a/vendor/plugins/rspec/lib/spec/runner/formatter/nested_text_formatter.rb +++ b/vendor/plugins/rspec/lib/spec/runner/formatter/nested_text_formatter.rb @@ -4,33 +4,25 @@ module Spec module Runner module Formatter class NestedTextFormatter < BaseTextFormatter - attr_reader :previous_nested_example_groups def initialize(options, where) super - @previous_nested_example_groups = [] + @last_nested_descriptions = [] end - def add_example_group(example_group) + def example_group_started(example_group) super - current_nested_example_groups = described_example_group_chain - current_nested_example_groups.each_with_index do |nested_example_group, i| - unless nested_example_group == previous_nested_example_groups[i] - output.puts "#{' ' * i}#{nested_example_group.description_args}" + example_group.nested_descriptions.each_with_index do |nested_description, i| + unless nested_description == @last_nested_descriptions[i] + output.puts "#{' ' * i}#{nested_description}" end end - @previous_nested_example_groups = described_example_group_chain + @last_nested_descriptions = example_group.nested_descriptions end def example_failed(example, counter, failure) - message = if failure.expectation_not_met? - "#{current_indentation}#{example.description} (FAILED - #{counter})" - else - "#{current_indentation}#{example.description} (ERROR - #{counter})" - end - - output.puts(failure.expectation_not_met? ? red(message) : magenta(message)) + output.puts(red("#{current_indentation}#{example.description} (FAILED - #{counter})")) output.flush end @@ -40,24 +32,14 @@ module Spec output.flush end - def example_pending(example, message) + 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 - ' ' * previous_nested_example_groups.length - end - - def described_example_group_chain - example_group_chain = [] - example_group.send(:execute_in_class_hierarchy) do |parent_example_group| - if parent_example_group.description_args && !parent_example_group.description_args.empty? - example_group_chain << parent_example_group - end - end - example_group_chain + ' ' * @last_nested_descriptions.length end end end diff --git a/vendor/plugins/rspec/lib/spec/runner/formatter/profile_formatter.rb b/vendor/plugins/rspec/lib/spec/runner/formatter/profile_formatter.rb index 8671d721e..3784f3ac7 100644 --- a/vendor/plugins/rspec/lib/spec/runner/formatter/profile_formatter.rb +++ b/vendor/plugins/rspec/lib/spec/runner/formatter/profile_formatter.rb @@ -41,10 +41,6 @@ module Spec end @output.flush end - - def method_missing(sym, *args) - # ignore - end end end end diff --git a/vendor/plugins/rspec/lib/spec/runner/formatter/progress_bar_formatter.rb b/vendor/plugins/rspec/lib/spec/runner/formatter/progress_bar_formatter.rb index 032a2872d..862f87a44 100644 --- a/vendor/plugins/rspec/lib/spec/runner/formatter/progress_bar_formatter.rb +++ b/vendor/plugins/rspec/lib/spec/runner/formatter/progress_bar_formatter.rb @@ -1,11 +1,14 @@ 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 colourise('F', failure) + @output.print colorize_failure('F', failure) @output.flush end @@ -14,9 +17,9 @@ module Spec @output.flush end - def example_pending(example, message) + def example_pending(example, message, deprecated_pending_location=nil) super - @output.print yellow('P') + @output.print yellow('*') @output.flush end @@ -24,10 +27,6 @@ module Spec @output.puts @output.flush end - - def method_missing(sym, *args) - # ignore - end end end end diff --git a/vendor/plugins/rspec/lib/spec/runner/formatter/snippet_extractor.rb b/vendor/plugins/rspec/lib/spec/runner/formatter/snippet_extractor.rb index 41119fe46..4f34e5fee 100644 --- a/vendor/plugins/rspec/lib/spec/runner/formatter/snippet_extractor.rb +++ b/vendor/plugins/rspec/lib/spec/runner/formatter/snippet_extractor.rb @@ -4,7 +4,7 @@ module Spec # 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 'rubygems'; require 'syntax/convertors/html'; @@converter = Syntax::Convertors::HTML.for_syntax "ruby"; rescue LoadError => e; @@converter = NullConverter.new; end + 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]) diff --git a/vendor/plugins/rspec/lib/spec/runner/formatter/specdoc_formatter.rb b/vendor/plugins/rspec/lib/spec/runner/formatter/specdoc_formatter.rb index facf1a65a..7204f2147 100644 --- a/vendor/plugins/rspec/lib/spec/runner/formatter/specdoc_formatter.rb +++ b/vendor/plugins/rspec/lib/spec/runner/formatter/specdoc_formatter.rb @@ -4,7 +4,7 @@ module Spec module Runner module Formatter class SpecdocFormatter < BaseTextFormatter - def add_example_group(example_group) + def example_group_started(example_group) super output.puts output.puts example_group.description @@ -12,13 +12,7 @@ module Spec end def example_failed(example, counter, failure) - message = if failure.expectation_not_met? - "- #{example.description} (FAILED - #{counter})" - else - "- #{example.description} (ERROR - #{counter})" - end - - output.puts(failure.expectation_not_met? ? red(message) : magenta(message)) + output.puts(red("- #{example.description} (FAILED - #{counter})")) output.flush end @@ -28,7 +22,7 @@ module Spec output.flush end - def example_pending(example, message) + def example_pending(example, message, deprecated_pending_location=nil) super output.puts yellow("- #{example.description} (PENDING: #{message})") output.flush diff --git a/vendor/plugins/rspec/lib/spec/runner/formatter/story/html_formatter.rb b/vendor/plugins/rspec/lib/spec/runner/formatter/story/html_formatter.rb deleted file mode 100644 index 5a8134683..000000000 --- a/vendor/plugins/rspec/lib/spec/runner/formatter/story/html_formatter.rb +++ /dev/null @@ -1,128 +0,0 @@ -require 'erb' -require 'spec/runner/formatter/base_text_formatter' - -module Spec - module Runner - module Formatter - module Story - class HtmlFormatter < BaseTextFormatter - include ERB::Util - - def run_started(count) - @output.puts <<-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>Stories</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" /> - <script src="javascripts/prototype.js" type="text/javascript"></script> - <script src="javascripts/scriptaculous.js" type="text/javascript"></script> - <script src="javascripts/rspec.js" type="text/javascript"></script> - <link href="stylesheets/rspec.css" rel="stylesheet" type="text/css" /> - </head> - <body> - <div id="container"> -EOF - end - - def collected_steps(steps) - unless steps.empty? - @output.puts " <ul id=\"stock_steps\" style=\"display: none;\">" - steps.each do |step| - @output.puts " <li>#{step}</li>" - end - @output.puts " </ul>" - end - end - - def run_ended - @output.puts <<-EOF - </div> - </body> -</head> -EOF - end - - def story_started(title, narrative) - @output.puts <<-EOF - <dl class="story passed"> - <dt>Story: #{h title}</dt> - <dd> - <p> - #{h(narrative).split("\n").join("<br />")} - </p> -EOF - end - - def story_ended(title, narrative) - @output.puts <<-EOF - </dd> - </dl> -EOF - end - - def scenario_started(story_title, scenario_name) - @output.puts <<-EOF - <dl class="passed"> - <dt>Scenario: #{h scenario_name}</dt> - <dd> - <ul class="steps"> -EOF - end - - def scenario_ended - @output.puts <<-EOF - </ul> - </dd> - </dl> -EOF - end - - def found_scenario(type, description) - end - - def scenario_succeeded(story_title, scenario_name) - scenario_ended - end - - def scenario_pending(story_title, scenario_name, reason) - scenario_ended - end - - def scenario_failed(story_title, scenario_name, err) - scenario_ended - end - - def step_upcoming(type, description, *args) - end - - def step_succeeded(type, description, *args) - print_step('passed', type, description, *args) # TODO: uses succeeded CSS class - end - - def step_pending(type, description, *args) - print_step('pending', type, description, *args) - end - - def step_failed(type, description, *args) - print_step('failed', type, description, *args) - end - - def print_step(klass, type, description, *args) - spans = args.map { |arg| "<span class=\"param\">#{arg}</span>" } - desc_string = description.step_name - arg_regexp = description.arg_regexp - i = -1 - inner = type.to_s.capitalize + ' ' + desc_string.gsub(arg_regexp) { |param| spans[i+=1] } - @output.puts " <li class=\"#{klass}\">#{inner}</li>" - end - end - end - end - end -end
\ No newline at end of file diff --git a/vendor/plugins/rspec/lib/spec/runner/formatter/story/plain_text_formatter.rb b/vendor/plugins/rspec/lib/spec/runner/formatter/story/plain_text_formatter.rb deleted file mode 100644 index 31cd614cb..000000000 --- a/vendor/plugins/rspec/lib/spec/runner/formatter/story/plain_text_formatter.rb +++ /dev/null @@ -1,142 +0,0 @@ -require 'spec/runner/formatter/base_text_formatter' - -module Spec - module Runner - module Formatter - module Story - class PlainTextFormatter < BaseTextFormatter - def initialize(options, where) - super - @successful_scenario_count = 0 - @pending_scenario_count = 0 - @failed_scenarios = [] - @pending_steps = [] - @previous_type = nil - end - - def run_started(count) - @count = count - @output.puts "Running #@count scenarios\n\n" - end - - def story_started(title, narrative) - @current_story_title = title - @output.puts "Story: #{title}\n\n" - narrative.each_line do |line| - @output.print " " - @output.print line - end - end - - def story_ended(title, narrative) - @output.puts - @output.puts - end - - def scenario_started(story_title, scenario_name) - @current_scenario_name = scenario_name - @scenario_already_failed = false - @output.print "\n\n Scenario: #{scenario_name}" - @scenario_ok = true - @scenario_pending = false - end - - def scenario_succeeded(story_title, scenario_name) - @successful_scenario_count += 1 - end - - def scenario_failed(story_title, scenario_name, err) - @options.backtrace_tweaker.tweak_backtrace(err) - @failed_scenarios << [story_title, scenario_name, err] unless @scenario_already_failed - @scenario_already_failed = true - end - - def scenario_pending(story_title, scenario_name, msg) - @pending_scenario_count += 1 unless @scenario_already_failed - @scenario_pending = true - @scenario_already_failed = true - end - - def run_ended - @output.puts "#@count scenarios: #@successful_scenario_count succeeded, #{@failed_scenarios.size} failed, #@pending_scenario_count pending" - unless @pending_steps.empty? - @output.puts "\nPending Steps:" - @pending_steps.each_with_index do |pending, i| - story_name, scenario_name, msg = pending - @output.puts "#{i+1}) #{story_name} (#{scenario_name}): #{msg}" - end - end - unless @failed_scenarios.empty? - @output.print "\nFAILURES:" - @failed_scenarios.each_with_index do |failure, i| - title, scenario_name, err = failure - @output.print %[ - #{i+1}) #{title} (#{scenario_name}) FAILED - #{err.class}: #{err.message} - #{err.backtrace.join("\n")} -] - end - end - end - - def step_upcoming(type, description, *args) - end - - def step_succeeded(type, description, *args) - found_step(type, description, false, false, *args) - end - - def step_pending(type, description, *args) - found_step(type, description, false, true, *args) - @pending_steps << [@current_story_title, @current_scenario_name, description] - @output.print yellow(" (PENDING)") - @scenario_pending = true - @scenario_ok = false - end - - def step_failed(type, description, *args) - found_step(type, description, true, @scenario_pending, *args) - if @scenario_pending - @output.print yellow(" (SKIPPED)") - else - @output.print red(@scenario_ok ? " (FAILED)" : " (SKIPPED)") - end - @scenario_ok = false - end - - def collected_steps(steps) - end - - def method_missing(sym, *args, &block) #:nodoc: - # noop - ignore unknown messages - end - - private - - def found_step(type, description, failed, pending, *args) - desc_string = description.step_name - arg_regexp = description.arg_regexp - text = if(type == @previous_type) - "\n And " - else - "\n\n #{type.to_s.capitalize} " - end - i = -1 - text << desc_string.gsub(arg_regexp) { |param| args[i+=1] } - if pending - @output.print yellow(text) - else - @output.print(failed ? red(text) : green(text)) - end - - if type == :'given scenario' - @previous_type = :given - else - @previous_type = type - end - end - end - end - end - end -end diff --git a/vendor/plugins/rspec/lib/spec/runner/heckle_runner.rb b/vendor/plugins/rspec/lib/spec/runner/heckle_runner.rb index 7695fe794..5c81ea846 100644 --- a/vendor/plugins/rspec/lib/spec/runner/heckle_runner.rb +++ b/vendor/plugins/rspec/lib/spec/runner/heckle_runner.rb @@ -1,72 +1,72 @@ -begin - require 'rubygems' - require 'heckle' -rescue LoadError ; raise "You must gem install heckle to use --heckle" ; end +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) + 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 - end - def heckle_method(class_name, method_name) - verify_constant(class_name) - heckle = @heckle_class.new(class_name, method_name, rspec_options) - heckle.validate - 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_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 + 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, rspec_options) - heckle.validate + 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 - 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" + 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 - end - #Supports Heckle 1.2 and prior (earlier versions used Heckle::Base) - class Heckler < (Heckle.const_defined?(:Base) ? Heckle::Base : Heckle) - def initialize(klass_name, method_name, rspec_options) - super(klass_name, method_name) - @rspec_options = rspec_options - 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? - success = @rspec_options.run_examples - success - end + def tests_pass? + @rspec_options.run_examples + end + end end end -end +end
\ No newline at end of file diff --git a/vendor/plugins/rspec/lib/spec/runner/heckle_runner_unsupported.rb b/vendor/plugins/rspec/lib/spec/runner/heckle_runner_unsupported.rb index 02aa37953..35ff86e10 100644 --- a/vendor/plugins/rspec/lib/spec/runner/heckle_runner_unsupported.rb +++ b/vendor/plugins/rspec/lib/spec/runner/heckle_runner_unsupported.rb @@ -3,7 +3,7 @@ module Spec # Dummy implementation for Windows that just fails (Heckle is not supported on Windows) class HeckleRunner def initialize(filter) - raise "Heckle not supported on Windows" + raise "Heckle is not supported on Windows or Ruby 1.9" end end end diff --git a/vendor/plugins/rspec/lib/spec/runner/option_parser.rb b/vendor/plugins/rspec/lib/spec/runner/option_parser.rb index 91525e089..fbbf444a9 100644 --- a/vendor/plugins/rspec/lib/spec/runner/option_parser.rb +++ b/vendor/plugins/rspec/lib/spec/runner/option_parser.rb @@ -10,6 +10,10 @@ module Spec parser.parse(args) parser.options end + + def spec_command? + $0.split('/').last == 'spec' + end end attr_reader :options @@ -27,34 +31,30 @@ module Spec :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 thatfile will be executed. If the file is empty,", + "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 behaviout or specification at given line.", - "(does not work for dynamically generated specs)"], + :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", + "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 for examples: ", - "progress|p : Text progress", - "profile|o : Text progress with profiling of 10 slowest examples", - "specdoc|s : Example doc as text", - "indented|i : Example doc as indented text", + "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", " ", - "Builtin formats for stories: ", - "plain|p : Plain Text", - "html|h : A nice HTML report", - " ", "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", @@ -78,6 +78,7 @@ module Spec :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)"], :version => ["-v", "--version", "Show version"], :help => ["-h", "--help", "You're looking at it"] @@ -91,37 +92,49 @@ module Spec @file_factory = File - self.banner = "Usage: spec (FILE|DIRECTORY|GLOB)+ [options]" + 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| parse_options_file(options_file)} + 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[:drb]) {} - on(*OPTIONS[:version]) {parse_version} - on_tail(*OPTIONS[:help]) {parse_help} + on(*OPTIONS[:runner]) {|runner| @options.user_input_for_runner = runner} + on(*OPTIONS[:debug]) {@options.debug = true} + on(*OPTIONS[:drb]) {} + on(*OPTIONS[:version]) {parse_version} + on("--autospec") {@options.autospec = true} + on_tail(*OPTIONS[:help]) {parse_help} end def order!(argv, &blk) - @argv = argv + @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_generate_options + 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 @@ -129,41 +142,46 @@ module Spec @options end - protected + protected + def invoke_requires(requires) requires.split(",").each do |file| require file end end - - def parse_options_file(options_file) - option_file_args = IO.readlines(options_file).map {|l| l.chomp.split " "}.flatten - @argv.push(*option_file_args) - # TODO - this is a brute force solution to http://rspec.lighthouseapp.com/projects/5645/tickets/293. - # Let's look for a cleaner way. Might not be one. But let's look. If not, perhaps - # this can be moved to a different method to indicate the special handling for drb? - parse_drb(@argv) - end - def parse_generate_options - # Remove the --generate-options option and the argument before writing to file + def parse_file_options(option_name, action) + # Remove the file option and the argument before handling the file options_file = nil - ['-G', '--generate-options'].each do |option| + 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 - write_generated_options(options_file) + send(action, options_file) return true else return false end end - - def write_generated_options(options_file) + + 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 @@ -172,28 +190,30 @@ module Spec @options.examples_should_not_be_run end - def parse_drb(argv = nil) - argv ||= @options.argv # TODO - see note about about http://rspec.lighthouseapp.com/projects/5645/tickets/293 + 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 - @options.examples_should_not_be_run - DrbCommandLine.run( - self.class.parse(argv, @error_stream, @out_stream) - ) - true + 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::DESCRIPTION + @out_stream.puts ::Spec::VERSION::SUMMARY exit if stdout? end def parse_help @out_stream.puts self exit if stdout? - end + end def stdout? @out_stream == $stdout diff --git a/vendor/plugins/rspec/lib/spec/runner/options.rb b/vendor/plugins/rspec/lib/spec/runner/options.rb index 6716464af..e0179e80e 100644 --- a/vendor/plugins/rspec/lib/spec/runner/options.rb +++ b/vendor/plugins/rspec/lib/spec/runner/options.rb @@ -1,3 +1,5 @@ +require 'ostruct' + module Spec module Runner class Options @@ -6,9 +8,11 @@ module Spec } 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'], + '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'], @@ -23,22 +27,16 @@ module Spec 'textmate' => ['spec/runner/formatter/text_mate_formatter', 'Formatter::TextMateFormatter'] } - STORY_FORMATTERS = { - 'plain' => ['spec/runner/formatter/story/plain_text_formatter', 'Formatter::Story::PlainTextFormatter'], - 'p' => ['spec/runner/formatter/story/plain_text_formatter', 'Formatter::Story::PlainTextFormatter'], - 'html' => ['spec/runner/formatter/story/html_formatter', 'Formatter::Story::HtmlFormatter'], - 'h' => ['spec/runner/formatter/story/html_formatter', 'Formatter::Story::HtmlFormatter'] - } - attr_accessor( + :autospec, # hack to tell :filename_pattern, :backtrace_tweaker, :context_lines, :diff_format, :dry_run, :profile, - :examples, :heckle_runner, + :debug, :line_number, :loadby, :reporter, @@ -48,12 +46,10 @@ module Spec :user_input_for_runner, :error_stream, :output_stream, - :before_suite_parts, - :after_suite_parts, # TODO: BT - Figure out a better name :argv ) - attr_reader :colour, :differ_class, :files, :example_groups + attr_reader :colour, :differ_class, :files, :examples, :example_groups def initialize(error_stream, output_stream) @error_stream = error_stream @@ -64,6 +60,7 @@ module Spec @colour = false @profile = false @dry_run = false + @debug = false @reporter = Reporter.new(self) @context_lines = 3 @diff_format = :unified @@ -73,32 +70,80 @@ module Spec @examples_run = false @examples_should_be_run = nil @user_input_for_runner = nil - @before_suite_parts = [] @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 - before_suite_parts.each do |part| - part.call - end 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 @@ -110,25 +155,40 @@ module Spec end ensure after_suite_parts.each do |part| - part.call(success) + 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 + 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 && RUBY_PLATFORM =~ /win32/ ;\ + if @colour && RUBY_PLATFORM =~ /mswin|mingw/ ;\ begin ;\ - require 'rubygems' ;\ + 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 ;\ @@ -152,7 +212,7 @@ module Spec def parse_example(example) if(File.file?(example)) - @examples = File.open(example).read.split("\n") + @examples = [File.open(example).read.split("\n")].flatten else @examples = [example] end @@ -168,17 +228,12 @@ module Spec @format_options ||= [] @format_options << [format, where] end - + def formatters @format_options ||= [['progress', @output_stream]] @formatters ||= load_formatters(@format_options, EXAMPLE_FORMATTERS) end - def story_formatters - @format_options ||= [['plain', @output_stream]] - @formatters ||= load_formatters(@format_options, STORY_FORMATTERS) - end - def load_formatters(format_options, formatters) format_options.map do |format, where| formatter_type = if formatters[format] @@ -187,22 +242,31 @@ module Spec else load_class(format, 'formatter', '--format') end - formatter_type.new(self, where) + 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) - suffix = [/mswin/, /java/].detect{|p| p =~ RUBY_PLATFORM} ? '_unsupported' : '' - require "spec/runner/heckle_runner#{suffix}" - @heckle_runner = HeckleRunner.new(heckle) + @format_options ||= [['silent', @output_stream]] + require which_heckle_runner + @heckle_runner = ::Spec::Runner::HeckleRunner.new(heckle) end def number_of_examples - total = 0 - @example_groups.each do |example_group| - total += example_group.number_of_examples - end - total + return examples.size unless examples.empty? + @example_groups.inject(0) {|sum, group| sum + group.number_of_examples} end def files_to_load @@ -220,13 +284,40 @@ module Spec end result end - - protected + + def dry_run? + @dry_run == true + 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 @@ -250,24 +341,24 @@ module Spec 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, 'behaviour runner', '--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 @@ -277,26 +368,26 @@ module Spec end def default_differ - require 'spec/expectations/differs/default' - self.differ_class = Spec::Expectations::Differs::Default + 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 using the --line option" + error_stream.puts "You must specify one file, not a directory when providing a line number" exit(1) if stderr? else - example = SpecParser.new.spec_name_for(files[0], line_number) + 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 using the --line option: #{files.inspect}" + 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 both --line and --example" + error_stream.puts "You cannot use --example and specify a line number" exit(4) if stderr? end end diff --git a/vendor/plugins/rspec/lib/spec/runner/reporter.rb b/vendor/plugins/rspec/lib/spec/runner/reporter.rb index 66db38406..0fae7d137 100644 --- a/vendor/plugins/rspec/lib/spec/runner/reporter.rb +++ b/vendor/plugins/rspec/lib/spec/runner/reporter.rb @@ -1,19 +1,23 @@ module Spec module Runner class Reporter - attr_reader :options, :example_groups + attr_reader :options def initialize(options) @options = options @options.reporter = self - clear + @failures = [] + @pending_count = 0 + @example_count = 0 + @start_time = nil + @end_time = nil end - def add_example_group(example_group) + def example_group_started(example_group) + @example_group = example_group formatters.each do |f| - f.add_example_group(example_group) + f.example_group_started(example_group) end - example_groups << example_group end def example_started(example) @@ -21,29 +25,27 @@ module Spec end def example_finished(example, error=nil) - @examples << example + @example_count += 1 if error.nil? example_passed(example) elsif Spec::Example::ExamplePendingError === error - example_pending(example, error.message) + example_pending(example, example.location, error.message) else example_failed(example, error) end end - def failure(example, error) + def example_failed(example, error) backtrace_tweaker.tweak_backtrace(error) - failure = Failure.new(example, 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 - alias_method :example_failed, :failure def start(number_of_examples) - clear @start_time = Time.new formatters.each{|f| f.start(number_of_examples)} end @@ -58,12 +60,51 @@ module Spec dump_pending dump_failures formatters.each do |f| - f.dump_summary(duration, @examples.length, @failures.length, @pending_count) + 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 @@ -74,15 +115,6 @@ module Spec @options.backtrace_tweaker end - def clear - @example_groups = [] - @failures = [] - @pending_count = 0 - @examples = [] - @start_time = nil - @end_time = nil - end - def dump_failures return if @failures.empty? @failures.inject(1) do |index, failure| @@ -103,45 +135,37 @@ module Spec 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, message="Not Yet Implemented") + def example_pending(example, ignore, message="Not Yet Implemented") @pending_count += 1 - formatters.each do |f| - f.example_pending(example, message) - end - end - - class Failure - attr_reader :example, :exception - - def initialize(example, exception) - @example = example - @exception = exception - end - - def header - if expectation_not_met? - "'#{example_name}' FAILED" - elsif pending_fixed? - "'#{example_name}' FIXED" + 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 - "#{@exception.class.name} in '#{example_name}'" + formatter.example_pending(example, message) end end - - def pending_fixed? - @exception.is_a?(Spec::Example::PendingExampleFixedError) - end - - def expectation_not_met? - @exception.is_a?(Spec::Expectations::ExpectationNotMetError) - end - - protected - def example_name - @example.__full_description - end end + + def formatter_uses_deprecated_example_pending_method?(formatter) + formatter.method(:example_pending).arity == 3 + end + end end end diff --git a/vendor/plugins/rspec/lib/spec/runner/spec_parser.rb b/vendor/plugins/rspec/lib/spec/runner/spec_parser.rb deleted file mode 100644 index 8beb384e9..000000000 --- a/vendor/plugins/rspec/lib/spec/runner/spec_parser.rb +++ /dev/null @@ -1,71 +0,0 @@ -module Spec - module Runner - # Parses a spec file and finds the nearest example for a given line number. - class SpecParser - attr_reader :best_match - - def initialize - @best_match = {} - end - - def spec_name_for(file, line_number) - best_match.clear - file = File.expand_path(file) - rspec_options.example_groups.each do |example_group| - consider_example_groups_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 - 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 - - protected - - def consider_example_groups_for_best_match(example_group, file, line_number) - parsed_backtrace = parse_backtrace(example_group.registration_backtrace) - parsed_backtrace.each do |example_file, example_line| - if is_best_match?(file, line_number, example_file, example_line) - best_match.clear - best_match[:example_group] = example_group - best_match[:line] = example_line - end - end - end - - def consider_example_for_best_match(example, example_group, file, line_number) - parsed_backtrace = parse_backtrace(example.implementation_backtrace) - parsed_backtrace.each do |example_file, example_line| - 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 - 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_backtrace(backtrace) - backtrace.collect do |trace_line| - split_line = trace_line.split(':') - [split_line[0], Integer(split_line[1])] - end - end - end - end -end diff --git a/vendor/plugins/rspec/lib/spec/story.rb b/vendor/plugins/rspec/lib/spec/story.rb deleted file mode 100644 index bc6960a28..000000000 --- a/vendor/plugins/rspec/lib/spec/story.rb +++ /dev/null @@ -1,10 +0,0 @@ -require 'spec' -require 'spec/story/extensions' -require 'spec/story/given_scenario' -require 'spec/story/runner' -require 'spec/story/scenario' -require 'spec/story/step' -require 'spec/story/step_group' -require 'spec/story/step_mother' -require 'spec/story/story' -require 'spec/story/world' diff --git a/vendor/plugins/rspec/lib/spec/story/extensions.rb b/vendor/plugins/rspec/lib/spec/story/extensions.rb deleted file mode 100644 index dc7dd1140..000000000 --- a/vendor/plugins/rspec/lib/spec/story/extensions.rb +++ /dev/null @@ -1,3 +0,0 @@ -require 'spec/story/extensions/main' -require 'spec/story/extensions/string' -require 'spec/story/extensions/regexp' diff --git a/vendor/plugins/rspec/lib/spec/story/extensions/main.rb b/vendor/plugins/rspec/lib/spec/story/extensions/main.rb deleted file mode 100644 index 6336b630c..000000000 --- a/vendor/plugins/rspec/lib/spec/story/extensions/main.rb +++ /dev/null @@ -1,86 +0,0 @@ -module Spec - module Story - module Extensions - module Main - def Story(title, narrative, params = {}, &body) - ::Spec::Story::Runner.story_runner.Story(title, narrative, params, &body) - end - - # Calling this deprecated is silly, since it hasn't been released yet. But, for - # those who are reading this - this will be deleted before the 1.1 release. - def run_story(*args, &block) - runner = Spec::Story::Runner::PlainTextStoryRunner.new(*args) - runner.instance_eval(&block) if block - runner.run - end - - # Creates (or appends to an existing) a namespaced group of steps for use in Stories - # - # == Examples - # - # # Creating a new group - # steps_for :forms do - # When("user enters $value in the $field field") do ... end - # When("user submits the $form form") do ... end - # end - def steps_for(tag, &block) - steps = rspec_story_steps[tag] - steps.instance_eval(&block) if block - steps - end - - # Creates a context for running a Plain Text Story with specific groups of Steps. - # Also supports adding arbitrary steps that will only be accessible to - # the Story being run. - # - # == Examples - # - # # Run a Story with one group of steps - # with_steps_for :checking_accounts do - # run File.dirname(__FILE__) + "/withdraw_cash" - # end - # - # # Run a Story, adding steps that are only available for this Story - # with_steps_for :accounts do - # Given "user is logged in as account administrator" - # run File.dirname(__FILE__) + "/reconcile_accounts" - # end - # - # # Run a Story with steps from two groups - # with_steps_for :checking_accounts, :savings_accounts do - # run File.dirname(__FILE__) + "/transfer_money" - # end - # - # # Run a Story with a specific Story extension - # with_steps_for :login, :navigation do - # run File.dirname(__FILE__) + "/user_changes_password", :type => RailsStory - # end - def with_steps_for(*tags, &block) - steps = Spec::Story::StepGroup.new do - extend StoryRunnerStepGroupAdapter - end - tags.each {|tag| steps << rspec_story_steps[tag]} - steps.instance_eval(&block) if block - steps - end - - private - - module StoryRunnerStepGroupAdapter - def run(path, options={}) - runner = Spec::Story::Runner::PlainTextStoryRunner.new(path, options) - runner.steps << self - runner.run - end - end - - def rspec_story_steps # :nodoc: - $rspec_story_steps ||= Spec::Story::StepGroupHash.new - end - - end - end - end -end - -include Spec::Story::Extensions::Main
\ No newline at end of file diff --git a/vendor/plugins/rspec/lib/spec/story/extensions/regexp.rb b/vendor/plugins/rspec/lib/spec/story/extensions/regexp.rb deleted file mode 100644 index 8ee338605..000000000 --- a/vendor/plugins/rspec/lib/spec/story/extensions/regexp.rb +++ /dev/null @@ -1,9 +0,0 @@ -class Regexp - def step_name - self.source.gsub '\\$', '$$' - end - - def arg_regexp - ::Spec::Story::Step::PARAM_OR_GROUP_PATTERN - end -end diff --git a/vendor/plugins/rspec/lib/spec/story/extensions/string.rb b/vendor/plugins/rspec/lib/spec/story/extensions/string.rb deleted file mode 100644 index 0e4ec1d68..000000000 --- a/vendor/plugins/rspec/lib/spec/story/extensions/string.rb +++ /dev/null @@ -1,9 +0,0 @@ -class String - def step_name - self - end - - def arg_regexp - ::Spec::Story::Step::PARAM_OR_GROUP_PATTERN - end -end diff --git a/vendor/plugins/rspec/lib/spec/story/given_scenario.rb b/vendor/plugins/rspec/lib/spec/story/given_scenario.rb deleted file mode 100644 index 88c51f981..000000000 --- a/vendor/plugins/rspec/lib/spec/story/given_scenario.rb +++ /dev/null @@ -1,14 +0,0 @@ -module Spec - module Story - class GivenScenario - def initialize(name) - @name = name - end - - def perform(instance, ignore_name) - scenario = Runner::StoryRunner.scenario_from_current_story(@name) - Runner::ScenarioRunner.new.run(scenario, instance) - end - end - end -end diff --git a/vendor/plugins/rspec/lib/spec/story/runner.rb b/vendor/plugins/rspec/lib/spec/story/runner.rb deleted file mode 100644 index 3d7ed59b5..000000000 --- a/vendor/plugins/rspec/lib/spec/story/runner.rb +++ /dev/null @@ -1,60 +0,0 @@ -require 'spec/story/runner/scenario_collector.rb' -require 'spec/story/runner/scenario_runner.rb' -require 'spec/story/runner/story_runner.rb' -require 'spec/story/runner/story_parser.rb' -require 'spec/story/runner/story_mediator.rb' -require 'spec/story/runner/plain_text_story_runner.rb' - -module Spec - module Story - module Runner - class << self - def run_options # :nodoc: - rspec_options - # @run_options ||= ::Spec::Runner::OptionParser.parse(ARGV, $stderr, $stdout) - end - - def story_runner # :nodoc: - unless @story_runner - @story_runner = create_story_runner - run_options.story_formatters.each do |formatter| - register_listener(formatter) - end - self.register_exit_hook - end - @story_runner - end - - def scenario_runner # :nodoc: - @scenario_runner ||= ScenarioRunner.new - end - - def world_creator # :nodoc: - @world_creator ||= World - end - - def create_story_runner - StoryRunner.new(scenario_runner, world_creator) - end - - # Use this to register a customer output formatter. - def register_listener(listener) - story_runner.add_listener(listener) # run_started, story_started, story_ended, #run_ended - world_creator.add_listener(listener) # found_scenario, step_succeeded, step_failed, step_failed - scenario_runner.add_listener(listener) # scenario_started, scenario_succeeded, scenario_pending, scenario_failed - end - - def register_exit_hook # :nodoc: - at_exit do - exit Runner.story_runner.run_stories unless $! - end - end - - def dry_run - run_options.dry_run - end - - end - end - end -end diff --git a/vendor/plugins/rspec/lib/spec/story/runner/plain_text_story_runner.rb b/vendor/plugins/rspec/lib/spec/story/runner/plain_text_story_runner.rb deleted file mode 100644 index a1bfbda4f..000000000 --- a/vendor/plugins/rspec/lib/spec/story/runner/plain_text_story_runner.rb +++ /dev/null @@ -1,48 +0,0 @@ -module Spec - module Story - module Runner - class PlainTextStoryRunner - # You can initialize a PlainTextStoryRunner with the path to the - # story file or a block, in which you can define the path using load. - # - # == Examples - # - # PlainTextStoryRunner.new('path/to/file') - # - # PlainTextStoryRunner.new do |runner| - # runner.load 'path/to/file' - # end - def initialize(*args) - @options = Hash === args.last ? args.pop : {} - @story_file = args.empty? ? nil : args.shift - yield self if block_given? - end - - def []=(key, value) - @options[key] = value - end - - def load(path) - @story_file = path - end - - def run(story_runner=Spec::Story::Runner.story_runner) - raise "You must set a path to the file with the story. See the RDoc." if @story_file.nil? - mediator = Spec::Story::Runner::StoryMediator.new(steps, story_runner, @options) - parser = Spec::Story::Runner::StoryParser.new(mediator) - - story_text = File.read(@story_file) - parser.parse(story_text.split("\n")) - - mediator.run_stories - end - - def steps - @step_group ||= Spec::Story::StepGroup.new - yield @step_group if block_given? - @step_group - end - end - end - end -end diff --git a/vendor/plugins/rspec/lib/spec/story/runner/scenario_collector.rb b/vendor/plugins/rspec/lib/spec/story/runner/scenario_collector.rb deleted file mode 100644 index 78339fd22..000000000 --- a/vendor/plugins/rspec/lib/spec/story/runner/scenario_collector.rb +++ /dev/null @@ -1,18 +0,0 @@ -module Spec - module Story - module Runner - class ScenarioCollector - attr_accessor :scenarios - - def initialize(story) - @story = story - @scenarios = [] - end - - def Scenario(name, &body) - @scenarios << Scenario.new(@story, name, &body) - end - end - end - end -end diff --git a/vendor/plugins/rspec/lib/spec/story/runner/scenario_runner.rb b/vendor/plugins/rspec/lib/spec/story/runner/scenario_runner.rb deleted file mode 100644 index 2d7c58d03..000000000 --- a/vendor/plugins/rspec/lib/spec/story/runner/scenario_runner.rb +++ /dev/null @@ -1,54 +0,0 @@ -module Spec - module Story - module Runner - class ScenarioRunner - def initialize - @listeners = [] - end - - def run(scenario, world) - @listeners.each { |l| l.scenario_started(scenario.story.title, scenario.name) } - run_story_ignoring_scenarios(scenario.story, world) - - world.start_collecting_errors - - unless scenario.body - @listeners.each { |l| l.scenario_pending(scenario.story.title, scenario.name, '') } - return true - end - - world.instance_eval(&scenario.body) - if world.errors.empty? - @listeners.each { |l| l.scenario_succeeded(scenario.story.title, scenario.name) } - else - if Spec::Example::ExamplePendingError === (e = world.errors.first) - @listeners.each { |l| l.scenario_pending(scenario.story.title, scenario.name, e.message) } - else - @listeners.each { |l| l.scenario_failed(scenario.story.title, scenario.name, e) } - return false - end - end - true - end - - def add_listener(listener) - @listeners << listener - end - - private - - def run_story_ignoring_scenarios(story, world) - class << world - def Scenario(name, &block) - # do nothing - end - end - story.run_in(world) - class << world - remove_method(:Scenario) - end - end - end - end - end -end diff --git a/vendor/plugins/rspec/lib/spec/story/runner/story_mediator.rb b/vendor/plugins/rspec/lib/spec/story/runner/story_mediator.rb deleted file mode 100644 index 826f322ee..000000000 --- a/vendor/plugins/rspec/lib/spec/story/runner/story_mediator.rb +++ /dev/null @@ -1,123 +0,0 @@ - module Spec - module Story - module Runner - - class StoryMediator - def initialize(step_group, runner, options={}) - @step_group = step_group - @stories = [] - @runner = runner - @options = options - end - - def stories - @stories.collect { |p| p.to_proc } - end - - def create_story(title, narrative) - @stories << Story.new(title, narrative, @step_group, @options) - end - - def create_scenario(title) - current_story.add_scenario Scenario.new(title) - end - - def create_given(name) - current_scenario.add_step Step.new('Given', name) - end - - def create_given_scenario(name) - current_scenario.add_step Step.new('GivenScenario', name) - end - - def create_when(name) - current_scenario.add_step Step.new('When', name) - end - - def create_then(name) - current_scenario.add_step Step.new('Then', name) - end - - def run_stories - stories.each { |story| @runner.instance_eval(&story) } - end - - private - def current_story - @stories.last - end - - def current_scenario - current_story.current_scenario - end - - class Story - def initialize(title, narrative, step_group, options) - @title = title - @narrative = narrative - @scenarios = [] - @step_group = step_group - @options = options - end - - def to_proc - title = @title - narrative = @narrative - scenarios = @scenarios.collect { |scenario| scenario.to_proc } - options = @options.merge(:steps_for => @step_group) - lambda do - Story title, narrative, options do - scenarios.each { |scenario| instance_eval(&scenario) } - end - end - end - - def add_scenario(scenario) - @scenarios << scenario - end - - def current_scenario - @scenarios.last - end - end - - class Scenario - def initialize(name) - @name = name - @steps = [] - end - - def to_proc - name = @name - steps = @steps.collect { |step| step.to_proc } - lambda do - Scenario name do - steps.each { |step| instance_eval(&step) } - end - end - end - - def add_step(step) - @steps << step - end - end - - class Step - def initialize(type, name) - @type = type - @name = name - end - - def to_proc - type = @type - name = @name - lambda do - send(type, name) - end - end - end - end - - end - end -end diff --git a/vendor/plugins/rspec/lib/spec/story/runner/story_parser.rb b/vendor/plugins/rspec/lib/spec/story/runner/story_parser.rb deleted file mode 100644 index d454df8cb..000000000 --- a/vendor/plugins/rspec/lib/spec/story/runner/story_parser.rb +++ /dev/null @@ -1,227 +0,0 @@ -module Spec - module Story - module Runner - - class IllegalStepError < StandardError - def initialize(state, event) - super("Illegal attempt to create a #{event} after a #{state}") - end - end - - class StoryParser - def initialize(story_mediator) - @story_mediator = story_mediator - @current_story_lines = [] - transition_to(:starting_state) - end - - def parse(lines) - lines.reject! {|line| line == ""} - until lines.empty? - process_line(lines.shift) - end - @state.eof - end - - def process_line(line) - line.strip! - case line - when /^Story: / then @state.story(line) - when /^Scenario: / then @state.scenario(line) - when /^Given:? / then @state.given(line) - when /^GivenScenario:? / then @state.given_scenario(line) - when /^When:? / then @state.event(line) - when /^Then:? / then @state.outcome(line) - when /^And:? / then @state.one_more_of_the_same(line) - else @state.other(line) - end - end - - def init_story(title) - @current_story_lines.clear - add_story_line(title) - end - - def add_story_line(line) - @current_story_lines << line - end - - def create_story() - unless @current_story_lines.empty? - @story_mediator.create_story(@current_story_lines[0].gsub("Story: ",""), @current_story_lines[1..-1].join("\n")) - @current_story_lines.clear - end - end - - def create_scenario(title) - @story_mediator.create_scenario(title.gsub("Scenario: ","")) - end - - def create_given(name) - @story_mediator.create_given(name) - end - - def create_given_scenario(name) - @story_mediator.create_given_scenario(name) - end - - def create_when(name) - @story_mediator.create_when(name) - end - - def create_then(name) - @story_mediator.create_then(name) - end - - def transition_to(key) - @state = states[key] - end - - def states - @states ||= { - :starting_state => StartingState.new(self), - :story_state => StoryState.new(self), - :scenario_state => ScenarioState.new(self), - :given_state => GivenState.new(self), - :when_state => WhenState.new(self), - :then_state => ThenState.new(self) - } - end - - class State - def initialize(parser) - @parser = parser - end - - def story(line) - @parser.init_story(line) - @parser.transition_to(:story_state) - end - - def scenario(line) - @parser.create_scenario(line) - @parser.transition_to(:scenario_state) - end - - def given(line) - @parser.create_given(remove_tag_from(:given, line)) - @parser.transition_to(:given_state) - end - - def given_scenario(line) - @parser.create_given_scenario(remove_tag_from(:givenscenario, line)) - @parser.transition_to(:given_state) - end - - def event(line) - @parser.create_when(remove_tag_from(:when, line)) - @parser.transition_to(:when_state) - end - - def outcome(line) - @parser.create_then(remove_tag_from(:then, line)) - @parser.transition_to(:then_state) - end - - def remove_tag_from(tag, line) - tokens = line.split - # validation of tag can go here - tokens[0].downcase.match(/#{tag.to_s}:?/) ? - (tokens[1..-1].join(' ')) : line - end - - def eof - end - - def other(line) - # no-op - supports header text before the first story in a file - end - end - - class StartingState < State - def initialize(parser) - @parser = parser - end - end - - class StoryState < State - def one_more_of_the_same(line) - other(line) - end - - def story(line) - @parser.create_story - @parser.add_story_line(line) - end - - def scenario(line) - @parser.create_story - @parser.create_scenario(line) - @parser.transition_to(:scenario_state) - end - - def given(line) - other(line) - end - - def event(line) - other(line) - end - - def outcome(line) - other(line) - end - - def other(line) - @parser.add_story_line(line) - end - - def eof - @parser.create_story - end - end - - class ScenarioState < State - def one_more_of_the_same(line) - raise IllegalStepError.new("Scenario", "And") - end - - def scenario(line) - @parser.create_scenario(line) - end - end - - class GivenState < State - def one_more_of_the_same(line) - @parser.create_given(remove_tag_from(:and, line)) - end - - def given(line) - @parser.create_given(remove_tag_from(:given, line)) - end - end - - class WhenState < State - def one_more_of_the_same(line) - @parser.create_when(remove_tag_from(:and ,line)) - end - - def event(line) - @parser.create_when(remove_tag_from(:when ,line)) - end - end - - class ThenState < State - def one_more_of_the_same(line) - @parser.create_then(remove_tag_from(:and ,line)) - end - - def outcome(line) - @parser.create_then(remove_tag_from(:then ,line)) - end - end - - end - end - end -end diff --git a/vendor/plugins/rspec/lib/spec/story/runner/story_runner.rb b/vendor/plugins/rspec/lib/spec/story/runner/story_runner.rb deleted file mode 100644 index a63479783..000000000 --- a/vendor/plugins/rspec/lib/spec/story/runner/story_runner.rb +++ /dev/null @@ -1,70 +0,0 @@ -module Spec - module Story - module Runner - class StoryRunner - class << self - attr_accessor :current_story_runner - - def scenario_from_current_story(scenario_name) - current_story_runner.scenario_from_current_story(scenario_name) - end - end - - attr_accessor :stories, :scenarios, :current_story - - def initialize(scenario_runner, world_creator = World) - StoryRunner.current_story_runner = self - @scenario_runner = scenario_runner - @world_creator = world_creator - @stories = [] - @scenarios_by_story = {} - @scenarios = [] - @listeners = [] - end - - def Story(title, narrative, params = {}, &body) - story = Story.new(title, narrative, params, &body) - @stories << story - - # collect scenarios - collector = ScenarioCollector.new(story) - story.run_in(collector) - @scenarios += collector.scenarios - @scenarios_by_story[story.title] = collector.scenarios - end - - def run_stories - return if @stories.empty? - @listeners.each { |l| l.run_started(scenarios.size) } - success = true - @stories.each do |story| - story.assign_steps_to(World) - @current_story = story - @listeners.each { |l| l.story_started(story.title, story.narrative) } - scenarios = @scenarios_by_story[story.title] - scenarios.each do |scenario| - type = story[:type] || Object - args = story[:args] || [] - world = @world_creator.create(type, *args) - success = success & @scenario_runner.run(scenario, world) - end - @listeners.each { |l| l.story_ended(story.title, story.narrative) } - World.step_mother.clear - end - unique_steps = (World.step_names.collect {|n| Regexp === n ? n.source : n.to_s}).uniq.sort - @listeners.each { |l| l.collected_steps(unique_steps) } - @listeners.each { |l| l.run_ended } - return success - end - - def add_listener(listener) - @listeners << listener - end - - def scenario_from_current_story(scenario_name) - @scenarios_by_story[@current_story.title].find {|s| s.name == scenario_name } - end - end - end - end -end diff --git a/vendor/plugins/rspec/lib/spec/story/scenario.rb b/vendor/plugins/rspec/lib/spec/story/scenario.rb deleted file mode 100644 index d83b3eeb8..000000000 --- a/vendor/plugins/rspec/lib/spec/story/scenario.rb +++ /dev/null @@ -1,14 +0,0 @@ - -module Spec - module Story - class Scenario - attr_accessor :name, :body, :story - - def initialize(story, name, &body) - @story = story - @name = name - @body = body - end - end - end -end diff --git a/vendor/plugins/rspec/lib/spec/story/step.rb b/vendor/plugins/rspec/lib/spec/story/step.rb deleted file mode 100644 index 5cd8765d6..000000000 --- a/vendor/plugins/rspec/lib/spec/story/step.rb +++ /dev/null @@ -1,58 +0,0 @@ -module Spec - module Story - class Step - PARAM_PATTERN = /([^\\]|^)(\$(?!\$)\w*)/ - PARAM_OR_GROUP_PATTERN = /(\$(?!\$)\w*)|\(.*?\)/ - - attr_reader :name - def initialize(name, &block) - @name = name - assign_expression(name) - init_module(name, &block) - end - - def perform(instance, *args) - instance.extend(@mod) - instance.__send__(sanitize(@name), *args) - end - - def init_module(name, &block) - sanitized_name = sanitize(name) - @mod = Module.new do - define_method(sanitized_name, &block) - end - end - - def sanitize(a_string_or_regexp) - return a_string_or_regexp.source if Regexp == a_string_or_regexp - a_string_or_regexp.to_s - end - - - def matches?(name) - !(matches = name.match(@expression)).nil? - end - - def parse_args(name) - name.match(@expression)[1..-1] - end - - private - - def assign_expression(string_or_regexp) - if String === string_or_regexp - expression = string_or_regexp.dup - expression.gsub! '(', '\(' - expression.gsub! ')', '\)' - elsif Regexp === string_or_regexp - expression = string_or_regexp.source - end - while expression =~ PARAM_PATTERN - expression.gsub!($2, "(.*?)") - end - @expression = Regexp.new("^#{expression}$") - end - - end - end -end diff --git a/vendor/plugins/rspec/lib/spec/story/step_group.rb b/vendor/plugins/rspec/lib/spec/story/step_group.rb deleted file mode 100644 index cae558c40..000000000 --- a/vendor/plugins/rspec/lib/spec/story/step_group.rb +++ /dev/null @@ -1,89 +0,0 @@ -module Spec - module Story - - class StepGroupHash < Hash - def initialize - super do |h,k| - h[k] = Spec::Story::StepGroup.new - end - end - end - - class StepGroup - def self.steps(&block) - @step_group ||= StepGroup.new(false) - @step_group.instance_eval(&block) if block - @step_group - end - - def initialize(init_defaults=true, &block) - @hash_of_lists_of_steps = Hash.new {|h, k| h[k] = []} - if init_defaults - self.class.steps.add_to(self) - end - instance_eval(&block) if block - end - - def find(type, name) - @hash_of_lists_of_steps[type].each do |step| - return step if step.matches?(name) - end - return nil - end - - def GivenScenario(name, &block) - create_matcher(:given_scenario, name, &block) - end - - def Given(name, &block) - create_matcher(:given, name, &block) - end - - def When(name, &block) - create_matcher(:when, name, &block) - end - - def Then(name, &block) - create_matcher(:then, name, &block) - end - - alias :given_scenario :GivenScenario - alias :given :Given - alias :when :When - alias :then :Then - - def add(type, steps) - (@hash_of_lists_of_steps[type] << steps).flatten! - end - - def clear - @hash_of_lists_of_steps.clear - end - - def empty? - [:given_scenario, :given, :when, :then].each do |type| - return false unless @hash_of_lists_of_steps[type].empty? - end - return true - end - - def add_to(other_step_matchers) - [:given_scenario, :given, :when, :then].each do |type| - other_step_matchers.add(type, @hash_of_lists_of_steps[type]) - end - end - - def <<(other_step_matchers) - other_step_matchers.add_to(self) if other_step_matchers.respond_to?(:add_to) - end - - # TODO - make me private - def create_matcher(type, name, &block) - matcher = Step.new(name, &block) - @hash_of_lists_of_steps[type] << matcher - matcher - end - - end - end -end diff --git a/vendor/plugins/rspec/lib/spec/story/step_mother.rb b/vendor/plugins/rspec/lib/spec/story/step_mother.rb deleted file mode 100644 index a2e84e310..000000000 --- a/vendor/plugins/rspec/lib/spec/story/step_mother.rb +++ /dev/null @@ -1,37 +0,0 @@ -module Spec - module Story - class StepMother - def initialize - @steps = StepGroup.new - end - - def use(new_step_group) - @steps << new_step_group - end - - def store(type, step) - @steps.add(type, step) - end - - def find(type, name) - if @steps.find(type, name).nil? - @steps.add(type, - Step.new(name) do - raise Spec::Example::ExamplePendingError.new("Unimplemented step: #{name}") - end - ) - end - @steps.find(type, name) - end - - def clear - @steps.clear - end - - def empty? - @steps.empty? - end - - end - end -end diff --git a/vendor/plugins/rspec/lib/spec/story/story.rb b/vendor/plugins/rspec/lib/spec/story/story.rb deleted file mode 100644 index 9cd1a0fec..000000000 --- a/vendor/plugins/rspec/lib/spec/story/story.rb +++ /dev/null @@ -1,39 +0,0 @@ -module Spec - module Story - class Story - attr_reader :title, :narrative - - def initialize(title, narrative, params = {}, &body) - @body = body - @title = title - @narrative = narrative - @params = params - end - - def [](key) - @params[key] - end - - def run_in(obj) - obj.instance_eval(&@body) - end - - def assign_steps_to(assignee) - if steps=@params[:steps_for] - steps = [steps] unless steps.is_a?(Array) - steps.each do |step| - if step.is_a?(StepGroup) - assignee.use(step) - else - assignee.use(steps_for(step)) - end - end - end - end - - def steps_for(key) - $rspec_story_steps[key] - end - end - end -end diff --git a/vendor/plugins/rspec/lib/spec/story/world.rb b/vendor/plugins/rspec/lib/spec/story/world.rb deleted file mode 100644 index a27d3dda9..000000000 --- a/vendor/plugins/rspec/lib/spec/story/world.rb +++ /dev/null @@ -1,124 +0,0 @@ -require 'spec/expectations' -require 'spec/matchers' -require 'spec/example/pending' - -module Spec - module Story -=begin - A World represents the actual instance a scenario will run in. - - The runner ensures any instance variables and methods defined anywhere - in a story block are available to all the scenarios. This includes - variables that are created or referenced inside Given, When and Then - blocks. -=end - module World - include ::Spec::Example::Pending - include ::Spec::Matchers - # store steps and listeners in the singleton metaclass. - # This serves both to keep them out of the way of runtime Worlds - # and to make them available to all instances. - class << self - def create(cls = Object, *args) - cls.new(*args).extend(World) - end - - def listeners - @listeners ||= [] - end - - def add_listener(listener) - listeners() << listener - end - - def step_mother - @step_mother ||= StepMother.new - end - - def use(steps) - step_mother.use(steps) - end - - def step_names - @step_names ||= [] - end - - def run_given_scenario_with_suspended_listeners(world, type, name, scenario) - current_listeners = Array.new(listeners) - begin - listeners.each { |l| l.found_scenario(type, name) } - @listeners.clear - scenario.perform(world, name) unless ::Spec::Story::Runner.dry_run - ensure - @listeners.replace(current_listeners) - end - end - - def store_and_call(world, type, name, *args, &block) - if block_given? - step_mother.store(type, Step.new(name, &block)) - end - step = step_mother.find(type, name) - - step_name = step.name - step_names << step_name - - # It's important to have access to the parsed args here, so - # we can give them to the listeners. The HTML reporter needs - # the args so it can style them. See the generated output in - # story_server/prototype/rspec_stories.html (generated by rake stories) - args = step.parse_args(name) if args.empty? - begin - listeners.each { |l| l.step_upcoming(type, step_name, *args) } - step.perform(world, *args) unless ::Spec::Story::Runner.dry_run - listeners.each { |l| l.step_succeeded(type, step_name, *args) } - rescue Exception => e - case e - when Spec::Example::ExamplePendingError - @listeners.each { |l| l.step_pending(type, step_name, *args) } - else - @listeners.each { |l| l.step_failed(type, step_name, *args) } - end - errors << e - end - end - - def errors - @errors ||= [] - end - end # end of class << self - - def start_collecting_errors - errors.clear - end - - def errors - World.errors - end - - def GivenScenario(name) - World.run_given_scenario_with_suspended_listeners(self, :'given scenario', name, GivenScenario.new(name)) - @__previous_step = :given - end - - def Given(name, *args, &block) - World.store_and_call self, :given, name, *args, &block - @__previous_step = :given - end - - def When(name, *args, &block) - World.store_and_call self, :when, name, *args, &block - @__previous_step = :when - end - - def Then(name, *args, &block) - World.store_and_call self, :then, name, *args, &block - @__previous_step = :then - end - - def And(name, *args, &block) - World.store_and_call self, @__previous_step, name, *args, &block - end - end - end -end diff --git a/vendor/plugins/rspec/lib/spec/translator.rb b/vendor/plugins/rspec/lib/spec/translator.rb deleted file mode 100644 index c1e07eda4..000000000 --- a/vendor/plugins/rspec/lib/spec/translator.rb +++ /dev/null @@ -1,114 +0,0 @@ -require 'fileutils' - -module Spec - class Translator - def translate(from, to) - from = File.expand_path(from) - to = File.expand_path(to) - if File.directory?(from) - translate_dir(from, to) - elsif(from =~ /\.rb$/) - translate_file(from, to) - end - end - - def translate_dir(from, to) - FileUtils.mkdir_p(to) unless File.directory?(to) - Dir["#{from}/*"].each do |sub_from| - path = sub_from[from.length+1..-1] - sub_to = File.join(to, path) - translate(sub_from, sub_to) - end - end - - def translate_file(from, to) - translation = "" - File.open(from) do |io| - io.each_line do |line| - translation << translate_line(line) - end - end - File.open(to, "w") do |io| - io.write(translation) - end - end - - def translate_line(line) - # Translate deprecated mock constraints - line.gsub!(/:any_args/, 'any_args') - line.gsub!(/:anything/, 'anything') - line.gsub!(/:boolean/, 'boolean') - line.gsub!(/:no_args/, 'no_args') - line.gsub!(/:numeric/, 'an_instance_of(Numeric)') - line.gsub!(/:string/, 'an_instance_of(String)') - - return line if line =~ /(should_not|should)_receive/ - - line.gsub!(/(^\s*)context([\s*|\(]['|"|A-Z])/, '\1describe\2') - line.gsub!(/(^\s*)specify([\s*|\(]['|"|A-Z])/, '\1it\2') - line.gsub!(/(^\s*)context_setup(\s*[do|\{])/, '\1before(:all)\2') - line.gsub!(/(^\s*)context_teardown(\s*[do|\{])/, '\1after(:all)\2') - line.gsub!(/(^\s*)setup(\s*[do|\{])/, '\1before(:each)\2') - line.gsub!(/(^\s*)teardown(\s*[do|\{])/, '\1after(:each)\2') - - if line =~ /(.*\.)(should_not|should)(?:_be)(?!_)(.*)/m - pre = $1 - should = $2 - post = $3 - be_or_equal = post =~ /(<|>)/ ? "be" : "equal" - - return "#{pre}#{should} #{be_or_equal}#{post}" - end - - if line =~ /(.*\.)(should_not|should)_(?!not)\s*(.*)/m - pre = $1 - should = $2 - post = $3 - - post.gsub!(/^raise/, 'raise_error') - post.gsub!(/^throw/, 'throw_symbol') - - unless standard_matcher?(post) - post = "be_#{post}" - end - - # Add parenthesis - post.gsub!(/^(\w+)\s+([\w|\.|\,|\(.*\)|\'|\"|\:|@| ]+)(\})/, '\1(\2)\3') # inside a block - post.gsub!(/^(redirect_to)\s+(.*)/, '\1(\2)') # redirect_to, which often has http: - post.gsub!(/^(\w+)\s+([\w|\.|\,|\(.*\)|\{.*\}|\'|\"|\:|@| ]+)/, '\1(\2)') - post.gsub!(/(\s+\))/, ')') - post.gsub!(/\)\}/, ') }') - post.gsub!(/^(\w+)\s+(\/.*\/)/, '\1(\2)') #regexps - line = "#{pre}#{should} #{post}" - end - - line - end - - def standard_matcher?(matcher) - patterns = [ - /^be/, - /^be_close/, - /^eql/, - /^equal/, - /^has/, - /^have/, - /^change/, - /^include/, - /^match/, - /^raise_error/, - /^respond_to/, - /^redirect_to/, - /^satisfy/, - /^throw_symbol/, - # Extra ones that we use in spec_helper - /^pass/, - /^fail/, - /^fail_with/, - ] - matched = patterns.detect{ |p| matcher =~ p } - !matched.nil? - end - - end -end diff --git a/vendor/plugins/rspec/lib/spec/version.rb b/vendor/plugins/rspec/lib/spec/version.rb index 959bf5189..b1088cd69 100644 --- a/vendor/plugins/rspec/lib/spec/version.rb +++ b/vendor/plugins/rspec/lib/spec/version.rb @@ -1,22 +1,14 @@ -module Spec
- module VERSION
- unless defined? MAJOR
- MAJOR = 1
- MINOR = 1
- TINY = 4
- RELEASE_CANDIDATE = nil
-
- BUILD_TIME_UTC = 20080526202855
-
- STRING = [MAJOR, MINOR, TINY].join('.')
- TAG = "REL_#{[MAJOR, MINOR, TINY, RELEASE_CANDIDATE].compact.join('_')}".upcase.gsub(/\.|-/, '_')
- FULL_VERSION = "#{[MAJOR, MINOR, TINY, RELEASE_CANDIDATE].compact.join('.')} (build #{BUILD_TIME_UTC})"
-
- NAME = "RSpec"
- URL = "http://rspec.rubyforge.org/"
-
- DESCRIPTION = "#{NAME}-#{FULL_VERSION} - BDD for Ruby\n#{URL}"
- end
- end
-end
-
+module Spec # :nodoc: + module VERSION # :nodoc: + unless defined? MAJOR + MAJOR = 1 + MINOR = 2 + TINY = 9 + PRE = nil + + STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.') + + SUMMARY = "rspec #{STRING}" + end + end +end |