rr-3.1.0/0000755000004100000410000000000014265140426012172 5ustar www-datawww-datarr-3.1.0/rr.gemspec0000644000004100000410000000177014265140426014167 0ustar www-datawww-data# encoding: utf-8 require File.expand_path('../lib/rr/version', __FILE__) Gem::Specification.new do |gem| gem.name = 'rr' gem.version = RR.version gem.authors = ['Kouhei Sutou', 'Brian Takita', 'Elliot Winkler'] gem.email = ['kou@cozmixng.org'] gem.description = 'RR is a test double framework that features a rich selection of double techniques and a terse syntax.' gem.summary = 'RR is a test double framework that features a rich selection of double techniques and a terse syntax.' gem.homepage = 'https://rr.github.io/rr' gem.license = 'MIT' gem.files = Dir[ 'Appraisals', 'CHANGES.md', 'CREDITS.md', 'Gemfile', 'LICENSE', 'README.md', 'Rakefile', 'doc/*.md', 'gemfiles/**/*', 'lib/**/*.rb', 'rr.gemspec', 'spec/**/*' ].to_a gem.require_paths = ['lib'] gem.add_development_dependency("bundler") gem.add_development_dependency("rake") gem.add_development_dependency("test-unit") gem.add_development_dependency("test-unit-rr") end rr-3.1.0/README.md0000644000004100000410000001313414265140426013453 0ustar www-datawww-data# RR [![Gem Version](https://badge.fury.io/rb/rr.svg)](https://badge.fury.io/rb/rr) [![Build Status](https://travis-ci.org/rr/rr.svg?branch=master)](https://travis-ci.org/rr/rr) [![Code Climate GPA](https://codeclimate.com/github/rr/rr.svg)](https://codeclimate.com/github/rr/rr) RR is a test double framework for Ruby that features a rich selection of double techniques and a terse syntax. --- ## Learning more 1. [A whirlwind tour of RR](#a-whirlwind-tour-of-rr) 2. [What is a test double?](doc/01_test_double.md) 3. [Syntax between RR and other double/mock frameworks](doc/02_syntax_comparison.md) 4. [API overview - Full listing of DSL methods](doc/03_api_overview.md) ## A whirlwind tour of RR ### Stubs ~~~ ruby # Stub a method to return nothing stub(object).foo stub(MyClass).foo # Stub a method to always return a value stub(object).foo { 'bar' } stub(MyClass).foo { 'bar' } # Stub a method to return a value when called with certain arguments stub(object).foo(1, 2) { 'bar' } stub(MyClass).foo(1, 2) { 'bar' } ~~~ ### Mocks ~~~ ruby # Create an expectation on a method mock(object).foo mock(MyClass).foo # Create an expectation on a method and stub it to always return a value mock(object).foo { 'bar' } mock(MyClass).foo { 'bar' } # Create an expectation on a method with certain arguments and stub it to return # a value when called that way mock(object).foo(1, 2) { 'bar' } mock(MyClass).foo(1, 2) { 'bar' } ~~~ ### Spies ~~~ ruby # RSpec stub(object).foo expect(object).to have_received.foo # Test::Unit stub(object).foo assert_received(object) {|o| o.foo } ~~~ ### Proxies ~~~ ruby # Intercept a existing method without completely overriding it, and create a # new return value from the existing one stub.proxy(object).foo {|str| str.upcase } stub.proxy(MyClass).foo {|str| str.upcase } # Do the same thing except also create an expectation mock.proxy(object).foo {|str| str.upcase } mock.proxy(MyClass).foo {|str| str.upcase } # Intercept a class's new method and define a double on the return value stub.proxy(MyClass).new {|obj| stub(obj).foo; obj } # Do the same thing except also create an expectation on .new mock.proxy(MyClass).new {|obj| stub(obj).foo; obj } ~~~ ### Class instances ~~~ ruby # Stub a method on an instance of MyClass when it is created any_instance_of(MyClass) do |klass| stub(klass).foo { 'bar' } end # Another way to do this which gives you access to the instance itself stub.proxy(MyClass).new do |obj| stub(obj).foo { 'bar' } end ~~~ ## Installing RR into your project NOTE: If you want to use RR with [test-unit](https://test-unit.github.io/), use [test-unit-rr](https://test-unit.github.io/#test-unit-rr). You don't need to read the following subsections. For minimal setup, RR looks for an existing test framework and then hooks itself into it. Hence, RR works best when loaded *after* the test framework that you are using is loaded. If you are using Bundler, you can achieve this by specifying the dependency on RR with `require: false`; then, require RR directly following your test framework. Here's what this looks like for different kinds of projects: ### Ruby project (without Bundler) ~~~ ruby require 'your/test/framework' require 'rr' ~~~ ### Ruby project (with Bundler) ~~~ ruby # Gemfile gem 'rr', require: false # test helper require 'your/test/framework' require 'rr' ~~~ ### Rails project ~~~ ruby # Gemfile group :test do gem 'rr', require: false end # test helper require File.expand_path('../../config/environment', __FILE__) require 'your/test/framework' # if you are using something other than MiniTest / Test::Unit require 'rr' ~~~ ## Compatibility RR is designed and tested to work against the following Ruby versions: * 2.4 * 2.5 * 2.6 * 2.7 * 3.0 * JRuby 1.7.4 as well as the following test frameworks: * Test::Unit via [test-unit-rr](https://test-unit.github.io/#test-unit-rr) * RSpec 2 * MiniTest 4 * Minitest 5 ## Help! If you have a question or are having trouble, simply [post it as an issue](https://github.com/rr/rr/issues) and I'll respond as soon as I can. ## Contributing Want to contribute a bug fix or new feature to RR? Great! Follow these steps: 1. Make sure you have a recent Ruby (check the compatibility table above). 2. Clone the repo (you probably knew that already). 3. Make a new branch off of `master` with a descriptive name. 4. Work on your patch. 5. Run `bundle install`. 6. Ensure all of the tests pass by running `bundle exec rake`. 7. If you want to go the extra mile, install the other Ruby versions listed above in the compatibility table, and repeat steps 5-6. See the "Running test suites" section below for more information. 8. When you're done, push your branch and create a pull request from it. I'll respond as soon as I can. ### Running tests As indicated by the compatibility list above, in order to test support for multiple Ruby versions and environments, there are multiple test suites, and Rake tasks to run these suites. The list of available Rake tasks depends on which version of Ruby you are under, but you can get the full list with: bundle exec rake -D spec: To run all the suites, simply say: bundle exec rake (Incidentally, this is also the command which Travis runs.) ## Author/Contact RR was originally written by Brian Takita. And it was maintained by Elliot Winkler (). It is currently maintained by Kouhei Sutou (). ## Credits With any development effort, there are countless people who have contributed to making it possible; RR is no exception! [You can read the full list of credits here](CREDITS.md). ## License RR is available under the [MIT license](LICENSE). rr-3.1.0/gemfiles/0000755000004100000410000000000014265140426013765 5ustar www-datawww-datarr-3.1.0/gemfiles/ruby_19_rspec_2_rails_4.gemfile0000644000004100000410000000050714265140426021645 0ustar www-datawww-data# This file was generated by Appraisal source "https://rubygems.org" gem "rake", "~> 10.0" gem "aws-sdk", "~> 1.0" gem "minitar", "~> 0.5" gem "dotenv", "~> 0.7" gem "simplecov", "~> 0.7" gem "appraisal", "~> 0.5" gem "posix-spawn", :platforms=>:mri gem "open4", :platforms=>:mri gem "rspec", "~> 2.14" gem "rails", "4.0.0" rr-3.1.0/gemfiles/ruby_19_rspec_2_rails_4.gemfile.lock0000644000004100000410000000516614265140426022602 0ustar www-datawww-dataGEM remote: https://rubygems.org/ specs: actionmailer (4.0.0) actionpack (= 4.0.0) mail (~> 2.5.3) actionpack (4.0.0) activesupport (= 4.0.0) builder (~> 3.1.0) erubis (~> 2.7.0) rack (~> 1.5.2) rack-test (~> 0.6.2) activemodel (4.0.0) activesupport (= 4.0.0) builder (~> 3.1.0) activerecord (4.0.0) activemodel (= 4.0.0) activerecord-deprecated_finders (~> 1.0.2) activesupport (= 4.0.0) arel (~> 4.0.0) activerecord-deprecated_finders (1.0.3) activesupport (4.0.0) i18n (~> 0.6, >= 0.6.4) minitest (~> 4.2) multi_json (~> 1.3) thread_safe (~> 0.1) tzinfo (~> 0.3.37) appraisal (0.5.2) bundler rake arel (4.0.0) atomic (1.1.13) aws-sdk (1.9.5) json (~> 1.4) nokogiri (>= 1.4.4) uuidtools (~> 2.1) builder (3.1.4) diff-lcs (1.2.4) dotenv (0.7.0) erubis (2.7.0) hike (1.2.3) i18n (0.6.5) json (1.8.0) json (1.8.0-java) mail (2.5.4) mime-types (~> 1.16) treetop (~> 1.4.8) mime-types (1.24) minitar (0.5.4) minitest (4.7.5) multi_json (1.7.9) nokogiri (1.5.9) nokogiri (1.5.9-java) open4 (1.3.0) polyglot (0.3.3) posix-spawn (0.3.6) rack (1.5.2) rack-test (0.6.2) rack (>= 1.0) rails (4.0.0) actionmailer (= 4.0.0) actionpack (= 4.0.0) activerecord (= 4.0.0) activesupport (= 4.0.0) bundler (>= 1.3.0, < 2.0) railties (= 4.0.0) sprockets-rails (~> 2.0.0) railties (4.0.0) actionpack (= 4.0.0) activesupport (= 4.0.0) rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) rake (10.1.0) rspec (2.14.1) rspec-core (~> 2.14.0) rspec-expectations (~> 2.14.0) rspec-mocks (~> 2.14.0) rspec-core (2.14.5) rspec-expectations (2.14.2) diff-lcs (>= 1.1.3, < 2.0) rspec-mocks (2.14.3) simplecov (0.7.1) multi_json (~> 1.0) simplecov-html (~> 0.7.1) simplecov-html (0.7.1) sprockets (2.10.0) hike (~> 1.2) multi_json (~> 1.0) rack (~> 1.0) tilt (~> 1.1, != 1.3.0) sprockets-rails (2.0.0) actionpack (>= 3.0) activesupport (>= 3.0) sprockets (~> 2.8) thor (0.18.1) thread_safe (0.1.2) atomic tilt (1.4.1) treetop (1.4.14) polyglot polyglot (>= 0.3.1) tzinfo (0.3.37) uuidtools (2.1.4) PLATFORMS java ruby DEPENDENCIES appraisal (~> 0.5) aws-sdk (~> 1.0) dotenv (~> 0.7) minitar (~> 0.5) open4 posix-spawn rails (= 4.0.0) rake (~> 10.0) rspec (~> 2.14) simplecov (~> 0.7) rr-3.1.0/gemfiles/ruby_19_rspec_2.gemfile.lock0000644000004100000410000000170414265140426021157 0ustar www-datawww-dataGEM remote: https://rubygems.org/ specs: appraisal (0.5.2) bundler rake aws-sdk (1.9.5) json (~> 1.4) nokogiri (>= 1.4.4) uuidtools (~> 2.1) diff-lcs (1.2.4) dotenv (0.7.0) json (1.8.0) json (1.8.0-java) minitar (0.5.4) multi_json (1.7.7) nokogiri (1.5.9) nokogiri (1.5.9-java) open4 (1.3.0) posix-spawn (0.3.6) rake (10.0.4) rspec (2.14.1) rspec-core (~> 2.14.0) rspec-expectations (~> 2.14.0) rspec-mocks (~> 2.14.0) rspec-core (2.14.5) rspec-expectations (2.14.2) diff-lcs (>= 1.1.3, < 2.0) rspec-mocks (2.14.3) simplecov (0.7.1) multi_json (~> 1.0) simplecov-html (~> 0.7.1) simplecov-html (0.7.1) uuidtools (2.1.4) PLATFORMS java ruby DEPENDENCIES appraisal (~> 0.5) aws-sdk (~> 1.0) dotenv (~> 0.7) minitar (~> 0.5) open4 posix-spawn rake (~> 10.0) rspec (~> 2.14) simplecov (~> 0.7) rr-3.1.0/gemfiles/ruby_19_rspec_2.gemfile0000644000004100000410000000046214265140426020230 0ustar www-datawww-data# This file was generated by Appraisal source "https://rubygems.org" gem "rake", "~> 10.0" gem "aws-sdk", "~> 1.0" gem "minitar", "~> 0.5" gem "dotenv", "~> 0.7" gem "simplecov", "~> 0.7" gem "appraisal", "~> 0.5" gem "posix-spawn", :platforms=>:mri gem "open4", :platforms=>:mri gem "rspec", "~> 2.14" rr-3.1.0/spec/0000755000004100000410000000000014265140426013124 5ustar www-datawww-datarr-3.1.0/spec/custom_formatter_for_rspec_2.rb0000644000004100000410000000175514265140426021341 0ustar www-datawww-datarequire 'rspec/core/formatters/base_text_formatter' class CustomFormatterForRSpec2 < RSpec::Core::Formatters::BaseTextFormatter def example_passed(example) super(example) output.puts passed_output(example) output.flush end def example_pending(example) super(example) output.puts pending_output(example, example.execution_result[:pending_message]) output.flush end def example_failed(example) super(example) output.puts failure_output(example, example.execution_result[:exception]) output.flush end private def passed_output(example) success_color("#{example.full_description.strip}") end def pending_output(example, message) pending_color("#{example.full_description.strip} (PENDING: #{message})") end def failure_output(example, exception) failure_color("#{example.full_description.strip} (FAILED - #{next_failure_index})") end def next_failure_index @next_failure_index ||= 0 @next_failure_index += 1 end end rr-3.1.0/spec/fixtures/0000755000004100000410000000000014265140426014775 5ustar www-datawww-datarr-3.1.0/spec/fixtures/rubygems_patch_for_187.rb0000644000004100000410000003721614265140426021614 0ustar www-datawww-datarequire 'rails/gem_dependency' module Gem ## Copied from RubyGems 1.3.7 (Ruby 1.9.2) class SourceIndex include Enumerable attr_reader :gems # :nodoc: ## # Directories to use to refresh this SourceIndex when calling refresh! attr_accessor :spec_dirs class << self ## # Factory method to construct a source index instance for a given # path. # # deprecated:: # If supplied, from_installed_gems will act just like # +from_gems_in+. This argument is deprecated and is provided # just for backwards compatibility, and should not generally # be used. # # return:: # SourceIndex instance def from_installed_gems(*deprecated) if deprecated.empty? from_gems_in(*installed_spec_directories) else from_gems_in(*deprecated) # HACK warn end end ## # Returns a list of directories from Gem.path that contain specifications. def installed_spec_directories Gem.path.collect { |dir| File.join(dir, "specifications") } end ## # Creates a new SourceIndex from the ruby format gem specifications in # +spec_dirs+. def from_gems_in(*spec_dirs) source_index = new source_index.spec_dirs = spec_dirs source_index.refresh! end ## # Loads a ruby-format specification from +file_name+ and returns the # loaded spec. def load_specification(file_name) return nil unless file_name and File.exist? file_name spec_code = if defined? Encoding then File.read file_name, :encoding => 'UTF-8' else File.read file_name end.untaint begin gemspec = eval spec_code, binding, file_name if gemspec.is_a?(Gem::Specification) gemspec.loaded_from = file_name return gemspec end alert_warning "File '#{file_name}' does not evaluate to a gem specification" rescue SignalException, SystemExit raise rescue SyntaxError => e alert_warning e alert_warning spec_code rescue Exception => e alert_warning "#{e.inspect}\n#{spec_code}" alert_warning "Invalid .gemspec format in '#{file_name}'" end return nil end end ## # Constructs a source index instance from the provided specifications, which # is a Hash of gem full names and Gem::Specifications. #-- # TODO merge @gems and @prerelease_gems and provide a separate method # #prerelease_gems def initialize(specifications={}) @gems = {} specifications.each{ |full_name, spec| add_spec spec } @spec_dirs = nil end # TODO: remove method def all_gems @gems end def prerelease_gems @gems.reject{ |name, gem| !gem.version.prerelease? } end def released_gems @gems.reject{ |name, gem| gem.version.prerelease? } end ## # Reconstruct the source index from the specifications in +spec_dirs+. def load_gems_in(*spec_dirs) @gems.clear spec_dirs.reverse_each do |spec_dir| spec_files = Dir.glob File.join(spec_dir, '*.gemspec') spec_files.each do |spec_file| gemspec = self.class.load_specification spec_file.untaint add_spec gemspec if gemspec end end self end ## # Returns an Array specifications for the latest released versions # of each gem in this index. def latest_specs result = Hash.new { |h,k| h[k] = [] } latest = {} sort.each do |_, spec| name = spec.name curr_ver = spec.version prev_ver = latest.key?(name) ? latest[name].version : nil next if curr_ver.prerelease? next unless prev_ver.nil? or curr_ver >= prev_ver or latest[name].platform != Gem::Platform::RUBY if prev_ver.nil? or (curr_ver > prev_ver and spec.platform == Gem::Platform::RUBY) then result[name].clear latest[name] = spec end if spec.platform != Gem::Platform::RUBY then result[name].delete_if do |result_spec| result_spec.platform == spec.platform end end result[name] << spec end # TODO: why is this a hash while @gems is an array? Seems like # structural similarity would be good. result.values.flatten end ## # An array including only the prerelease gemspecs def prerelease_specs prerelease_gems.values end ## # An array including only the released gemspecs def released_specs released_gems.values end ## # Add a gem specification to the source index. def add_spec(gem_spec, name = gem_spec.full_name) # No idea why, but the Indexer wants to insert them using original_name # instead of full_name. So we make it an optional arg. @gems[name] = gem_spec end ## # Add gem specifications to the source index. def add_specs(*gem_specs) gem_specs.each do |spec| add_spec spec end end ## # Remove a gem specification named +full_name+. def remove_spec(full_name) @gems.delete full_name end ## # Iterate over the specifications in the source index. def each(&block) # :yields: gem.full_name, gem @gems.each(&block) end ## # The gem specification given a full gem spec name. def specification(full_name) @gems[full_name] end ## # The signature for the source index. Changes in the signature indicate a # change in the index. def index_signature require 'digest' Digest::SHA256.new.hexdigest(@gems.keys.sort.join(',')).to_s end ## # The signature for the given gem specification. def gem_signature(gem_full_name) require 'digest' Digest::SHA256.new.hexdigest(@gems[gem_full_name].to_yaml).to_s end def size @gems.size end alias length size ## # Find a gem by an exact match on the short name. def find_name(gem_name, version_requirement = Gem::Requirement.default) dep = Gem::Dependency.new gem_name, version_requirement search dep end ## # Search for a gem by Gem::Dependency +gem_pattern+. If +only_platform+ # is true, only gems matching Gem::Platform.local will be returned. An # Array of matching Gem::Specification objects is returned. # # For backwards compatibility, a String or Regexp pattern may be passed as # +gem_pattern+, and a Gem::Requirement for +platform_only+. This # behavior is deprecated and will be removed. def search(gem_pattern, platform_only = false) version_requirement = nil only_platform = false # TODO - Remove support and warning for legacy arguments after 2008/11 unless Gem::Dependency === gem_pattern warn "#{Gem.location_of_caller.join ':'}:Warning: Gem::SourceIndex#search support for #{gem_pattern.class} patterns is deprecated, use #find_name" end case gem_pattern when Regexp then version_requirement = platform_only || Gem::Requirement.default when Gem::Dependency then only_platform = platform_only version_requirement = gem_pattern.requirement gem_pattern = if Regexp === gem_pattern.name then gem_pattern.name elsif gem_pattern.name.empty? then // else /^#{Regexp.escape gem_pattern.name}$/ end else version_requirement = platform_only || Gem::Requirement.default gem_pattern = /#{gem_pattern}/i end unless Gem::Requirement === version_requirement then version_requirement = Gem::Requirement.create version_requirement end specs = all_gems.values.select do |spec| spec.name =~ gem_pattern and version_requirement.satisfied_by? spec.version end if only_platform then specs = specs.select do |spec| Gem::Platform.match spec.platform end end specs.sort_by { |s| s.sort_obj } end ## # Replaces the gems in the source index from specifications in the # directories this source index was created from. Raises an exception if # this source index wasn't created from a directory (via from_gems_in or # from_installed_gems, or having spec_dirs set). def refresh! raise 'source index not created from disk' if @spec_dirs.nil? load_gems_in(*@spec_dirs) end ## # Returns an Array of Gem::Specifications that are not up to date. def outdated outdateds = [] latest_specs.each do |local| dependency = Gem::Dependency.new local.name, ">= #{local.version}" begin fetcher = Gem::SpecFetcher.fetcher remotes = fetcher.find_matching dependency remotes = remotes.map { |(name, version,_),_| version } rescue Gem::RemoteFetcher::FetchError => e raise unless fetcher.warn_legacy e do require 'rubygems/source_info_cache' specs = Gem::SourceInfoCache.search_with_source dependency, true remotes = specs.map { |spec,| spec.version } end end latest = remotes.sort.last outdateds << local.name if latest and local.version < latest end outdateds end ## # Updates this SourceIndex from +source_uri+. If +all+ is false, only the # latest gems are fetched. def update(source_uri, all) source_uri = URI.parse source_uri unless URI::Generic === source_uri source_uri.path += '/' unless source_uri.path =~ /\/$/ use_incremental = false begin gem_names = fetch_quick_index source_uri, all remove_extra gem_names missing_gems = find_missing gem_names return false if missing_gems.size.zero? say "Missing metadata for #{missing_gems.size} gems" if missing_gems.size > 0 and Gem.configuration.really_verbose use_incremental = missing_gems.size <= Gem.configuration.bulk_threshold rescue Gem::OperationNotSupportedError => ex alert_error "Falling back to bulk fetch: #{ex.message}" if Gem.configuration.really_verbose use_incremental = false end if use_incremental then update_with_missing(source_uri, missing_gems) else new_index = fetch_bulk_index(source_uri) @gems.replace(new_index.gems) end true end def ==(other) # :nodoc: self.class === other and @gems == other.gems end def dump Marshal.dump(self) end private def fetcher require 'rubygems/remote_fetcher' Gem::RemoteFetcher.fetcher end def fetch_index_from(source_uri) @fetch_error = nil indexes = %W[ Marshal.#{Gem.marshal_version}.Z Marshal.#{Gem.marshal_version} yaml.Z yaml ] indexes.each do |name| spec_data = nil index = source_uri + name begin spec_data = fetcher.fetch_path index spec_data = unzip(spec_data) if name =~ /\.Z$/ if name =~ /Marshal/ then return Marshal.load(spec_data) else return YAML.load(spec_data) end rescue => e if Gem.configuration.really_verbose then alert_error "Unable to fetch #{name}: #{e.message}" end @fetch_error = e end end nil end def fetch_bulk_index(source_uri) say "Bulk updating Gem source index for: #{source_uri}" if Gem.configuration.verbose index = fetch_index_from(source_uri) if index.nil? then raise Gem::RemoteSourceException, "Error fetching remote gem cache: #{@fetch_error}" end @fetch_error = nil index end ## # Get the quick index needed for incremental updates. def fetch_quick_index(source_uri, all) index = all ? 'index' : 'latest_index' zipped_index = fetcher.fetch_path source_uri + "quick/#{index}.rz" unzip(zipped_index).split("\n") rescue ::Exception => e unless all then say "Latest index not found, using quick index" if Gem.configuration.really_verbose fetch_quick_index source_uri, true else raise Gem::OperationNotSupportedError, "No quick index found: #{e.message}" end end ## # Make a list of full names for all the missing gemspecs. def find_missing(spec_names) unless defined? @originals then @originals = {} each do |full_name, spec| @originals[spec.original_name] = spec end end spec_names.find_all { |full_name| @originals[full_name].nil? } end def remove_extra(spec_names) dictionary = spec_names.inject({}) { |h, k| h[k] = true; h } each do |name, spec| remove_spec name unless dictionary.include? spec.original_name end end ## # Unzip the given string. def unzip(string) require 'zlib' Gem.inflate string end ## # Tries to fetch Marshal representation first, then YAML def fetch_single_spec(source_uri, spec_name) @fetch_error = nil begin marshal_uri = source_uri + "quick/Marshal.#{Gem.marshal_version}/#{spec_name}.gemspec.rz" zipped = fetcher.fetch_path marshal_uri return Marshal.load(unzip(zipped)) rescue => ex @fetch_error = ex if Gem.configuration.really_verbose then say "unable to fetch marshal gemspec #{marshal_uri}: #{ex.class} - #{ex}" end end begin yaml_uri = source_uri + "quick/#{spec_name}.gemspec.rz" zipped = fetcher.fetch_path yaml_uri return YAML.load(unzip(zipped)) rescue => ex @fetch_error = ex if Gem.configuration.really_verbose then say "unable to fetch YAML gemspec #{yaml_uri}: #{ex.class} - #{ex}" end end nil end ## # Update the cached source index with the missing names. def update_with_missing(source_uri, missing_names) progress = ui.progress_reporter(missing_names.size, "Updating metadata for #{missing_names.size} gems from #{source_uri}") missing_names.each do |spec_name| gemspec = fetch_single_spec(source_uri, spec_name) if gemspec.nil? then ui.say "Failed to download spec #{spec_name} from #{source_uri}:\n" \ "\t#{@fetch_error.message}" else add_spec gemspec progress.updated spec_name end @fetch_error = nil end progress.done progress.count end end class FakeSourceIndex include Enumerable def initialize(specs_by_filename = {}) @specs_by_filename = specs_by_filename end def search(dep) Specification.find_all_by_name(dep.name, dep.requirement) end def each Specification.each do |spec| yield spec.name, spec end end end class Specification alias_method :installation_path, :base_dir end class << self attr_accessor :source_index alias_method :cache, :source_index ## Copied from RubyGems 1.3.7 (Ruby 1.9.2) def available?(gem, *requirements) requirements = Gem::Requirement.default if requirements.empty? unless gem.respond_to?(:name) and gem.respond_to?(:requirement) then gem = Gem::Dependency.new gem, requirements end !Gem.source_index.search(gem).empty? end end self.source_index = FakeSourceIndex.new end rr-3.1.0/spec/spec.opts0000644000004100000410000000012514265140426014763 0ustar www-datawww-data--require ./spec/custom_formatter_for_rspec --format CustomFormatterForRSpec --color rr-3.1.0/spec/global_helper.rb0000644000004100000410000000210114265140426016242 0ustar www-datawww-datarequire 'pp' require 'rubygems' require 'bundler' if ENV['COVERAGE'] require 'simplecov' SimpleCov.start end module RR module Test def self.setup_test_suite(adapter_name) puts "Setting up test suite for #{adapter_name}" if ENV['RR_DEBUG'] unset_bundler_vars adapter = Adapter.new(adapter_name) ENV['ADAPTER'] = adapter.name.to_s puts "Using appraisal: #{adapter.appraisal.name}" if ENV['RR_DEBUG'] ENV['BUNDLE_GEMFILE'] = adapter.appraisal.gemfile_path puts "Using gemfile: #{adapter.appraisal.gemfile_path}" if ENV['RR_DEBUG'] Bundler.setup(:default) $:.unshift File.expand_path('../../lib', __FILE__) end def self.unset_bundler_vars # Copied from appraisal %w(RUBYOPT BUNDLE_PATH BUNDLE_BIN_PATH BUNDLE_GEMFILE).each do |name| ENV[name] = nil end end end end lib_path = File.expand_path("../../lib", __FILE__) $LOAD_PATH.unshift(lib_path) unless $LOAD_PATH.include?(lib_path) Dir[ File.expand_path('../support/**/*.rb', __FILE__) ].each { |fn| require fn } $stdout.sync = true rr-3.1.0/spec/spec_suite_configuration.rb0000644000004100000410000000571014265140426020546 0ustar www-datawww-datarequire File.expand_path('../spec_suite_runner', __FILE__) require 'yaml' require 'erb' require 'forwardable' require 'ostruct' class SpecSuiteConfiguration SUITES_CONFIG_FILE = File.expand_path('../suites.yml', __FILE__) TRAVIS_CONFIG_FILE = File.expand_path('../../.travis.yml', __FILE__) class Suite < Struct.new(:name, :desc, :rvm_version, :ruby_id, :env, :travis) attr_reader :runner def initialize(name, desc, rvm_version, ruby_id, env, travis) super @runner = SpecSuiteRunner.new(self) end def appraisal_name "ruby_#{ruby_id}_#{name}" end def run runner.call end def current_ruby_id '19' end def matching_current_ruby_version? ruby_id == current_ruby_id end end attr_reader :ruby_groups, :runners def self.build new(parse) end def self.parse suites = [] yaml = ERB.new(File.read(SUITES_CONFIG_FILE)).result(binding) ruby_groups = YAML.load(yaml) ruby_groups.each do |ruby_id, ruby_group| base_env = ruby_group.fetch('env', {}) ruby_group['suites'].each do |suite| ruby_group['rvm_versions'].each do |rvm_version| suite = suite.dup suite['ruby_id'] = ruby_id.to_s suite['rvm_version'] = rvm_version['name'] suite['env'] = base_env.merge(rvm_version.fetch('env', {})) suite['travis'] = ruby_group.fetch('travis', {}) suite['travis']['env'] = base_env.merge(suite['travis'].fetch('env', {})) suites << suite end end end suites end def self.root_dir File.expand_path('../..', __FILE__) end attr_reader :suites def initialize(suites) @suites = suites.map do |suite| Suite.new( suite['name'], suite['desc'], suite['rvm_version'], suite['ruby_id'], suite['env'], suite['travis'] ) end end def each_matching_suite(&block) suites. select { |suite| suite.matching_current_ruby_version? }. each(&block) end def to_travis_config inclusions = [] allowed_failures = [] sorted_suites = suites.sort_by { |suite| [suite.rvm_version, suite.name] } sorted_suites.each do |suite| env = suite.travis['env'].merge('SUITE' => suite.name) row = { 'rvm' => suite.rvm_version, 'env' => env.map { |key, val| "#{key}=#{val.inspect}" } } inclusions << row if suite.rvm_version == 'jruby-19mode' allowed_failures << row end end { 'language' => 'ruby', 'script' => 'rake spec:${SUITE}', 'rvm' => '1.9.3', 'matrix' => { # exclude default row 'exclude' => [ {'rvm' => '1.9.3'}, ], 'include' => inclusions, 'allow_failures' => allowed_failures } } end def generate_travis_config config = to_travis_config File.open(TRAVIS_CONFIG_FILE, 'w') {|f| YAML.dump(config, f) } puts "Updated .travis.yml." end end rr-3.1.0/spec/custom_formatter_for_rspec.rb0000644000004100000410000000053414265140426021112 0ustar www-datawww-datarequire 'spec/runner/formatter/specdoc_formatter' class CustomFormatterForRSpec < Spec::Runner::Formatter::SpecdocFormatter def example_passed(example) super output.flush end def example_pending(example, message) super output.flush end def example_failed(example, counter, failure) super output.flush end end rr-3.1.0/spec/suites.yml0000644000004100000410000000037414265140426015167 0ustar www-datawww-data19: rvm_versions: - name: 1.9.3 - name: 2.0.0 - name: jruby-19mode suites: - name: rspec_2 desc: 'RSpec 2' env: SPEC_OPTS: '--require $PWD/spec/custom_formatter_for_rspec_2 --format CustomFormatterForRSpec2 --backtrace' rr-3.1.0/spec/suites/0000755000004100000410000000000014265140426014440 5ustar www-datawww-datarr-3.1.0/spec/suites/rspec_2/0000755000004100000410000000000014265140426015775 5ustar www-datawww-datarr-3.1.0/spec/suites/rspec_2/helper.rb0000644000004100000410000000114614265140426017603 0ustar www-datawww-datarequire 'rspec/core' require 'rspec/expectations' require 'rspec/autorun' require 'rr' module ExampleMethods def eigen(object) class << object; self; end end end module ExampleGroupMethods def macro(name, &implementation) (class << self; self; end).class_eval do define_method(name, &implementation) end end end RSpec.configure do |c| c.include ExampleMethods c.extend ExampleGroupMethods c.order = :random end Dir[ File.expand_path('../shared/*.rb', __FILE__) ].sort.each {|fn| require fn } Dir[ File.expand_path('../support/**/*.rb', __FILE__) ].sort.each {|fn| require fn } rr-3.1.0/spec/suites/rspec_2/unit/0000755000004100000410000000000014265140426016754 5ustar www-datawww-datarr-3.1.0/spec/suites/rspec_2/unit/wildcard_matchers/0000755000004100000410000000000014265140426022433 5ustar www-datawww-datarr-3.1.0/spec/suites/rspec_2/unit/wildcard_matchers/anything_spec.rb0000644000004100000410000000153114265140426025613 0ustar www-datawww-datarequire File.expand_path('../../../spec_helper', __FILE__) module RR module WildcardMatchers describe Anything do include WildcardMatcherMatchers describe '#wildcard_match?' do it "always returns true when given any object" do should wildcard_match(Object.new) should wildcard_match(:symbol) should wildcard_match([1, 2, 3]) end end describe '#==' do it "returns true when given an Anything object" do should equal_match(described_class.new) end it "returns false when not given an Anything object whatsoever" do should_not equal_match(:whatever) end end describe "#inspect" do it "returns the correct string" do expect(subject.inspect).to eq "anything" end end end end end rr-3.1.0/spec/suites/rspec_2/unit/wildcard_matchers/boolean_spec.rb0000644000004100000410000000226414265140426025415 0ustar www-datawww-datarequire File.expand_path('../../../spec_helper', __FILE__) module RR module WildcardMatchers describe Boolean do include WildcardMatcherMatchers describe '#wildcard_match?' do it "returns true when given a Boolean" do should wildcard_match(described_class.new) end it "returns true when given a boolean" do should wildcard_match(true) should wildcard_match(false) end it "returns false when not given a boolean" do should_not wildcard_match(:something_else) end end describe "#==" do it "returns true when given a Boolean" do should equal_match(described_class.new) end it "returns false even when given a boolean that wildcard matches this Boolean" do should_not equal_match(true) should_not equal_match(false) end it "returns false when not given a Boolean whatsoever" do should_not equal_match(:something_else) end end describe "#inspect" do it "returns the correct string" do expect(subject.inspect).to eq "boolean" end end end end end rr-3.1.0/spec/suites/rspec_2/unit/wildcard_matchers/is_a_spec.rb0000644000004100000410000000307214265140426024707 0ustar www-datawww-datarequire File.expand_path('../../../spec_helper', __FILE__) module RR module WildcardMatchers describe IsA do include WildcardMatcherMatchers describe '#wildcard_match?' do subject { described_class.new(Symbol) } it "returns true when given IsA is a copy of this IsA" do matcher2 = described_class.new(Symbol) should wildcard_match(matcher2) end it "returns true when given an object that is is_a?(klass)" do should wildcard_match(:a_symbol) end it "returns false if not given an object that is is_a?(klass)" do should_not wildcard_match('a string') end end describe '#==' do subject { described_class.new(Symbol) } it "returns true when given IsA is a copy of this IsA" do matcher2 = described_class.new(Symbol) should equal_match(matcher2) end it "returns false when given IsA is not a copy of this IsA" do matcher2 = described_class.new(String) should_not equal_match(matcher2) end it "returns false even when given an object that wildcard matches this IsA" do should_not equal_match(:something_else) end it "returns false when not given an IsA whatsoever" do should_not equal_match([1, 2, 3]) end end describe "#inspect" do it "returns the correct string" do matcher = described_class.new(Symbol) expect(matcher.inspect).to eq "is_a(Symbol)" end end end end end rr-3.1.0/spec/suites/rspec_2/unit/wildcard_matchers/satisfy_spec.rb0000644000004100000410000000330214265140426025452 0ustar www-datawww-datarequire File.expand_path('../../../spec_helper', __FILE__) module RR module WildcardMatchers describe Satisfy do include WildcardMatcherMatchers describe '#wildcard_match?' do let(:expectation_proc) { lambda {|v| v == 'x' } } subject { described_class.new(expectation_proc) } it "returns true if given Satisfy is a copy of this Satisfy" do matcher2 = described_class.new(expectation_proc) should wildcard_match(matcher2) end it "returns true if the given object matches the block" do should wildcard_match('x') end it "returns false otherwise" do should_not wildcard_match('y') end end describe '#==' do let(:expectation_proc) { lambda {|v| v == 'x' } } subject { described_class.new(expectation_proc) } it "returns true if given Satisfy is a copy of this Satisfy" do matcher2 = described_class.new(expectation_proc) should equal_match(matcher2) end it "returns false if given Satisfy is not a copy of this Satisfy" do matcher2 = described_class.new(lambda {|v| }) should_not equal_match(matcher2) end it "returns false even when given an object that wildcard matches this Satisfy" do should_not equal_match('x') end it "returns false when given object isn't even a Satisfy" do should_not equal_match(:something_else) end end describe '#inspect' do it "returns the correct string" do matcher = Satisfy.new(lambda {}) expect(matcher.inspect).to eq "satisfy { ... }" end end end end end rr-3.1.0/spec/suites/rspec_2/unit/wildcard_matchers/numeric_spec.rb0000644000004100000410000000235414265140426025440 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper") module RR module WildcardMatchers describe Numeric do include WildcardMatcherMatchers describe '#wildcard_match?' do it "returns true when given Numeric is a copy of this Numeric" do matcher2 = described_class.new should wildcard_match(matcher2) end it "returns true when given a Numeric" do should wildcard_match(99) end it "returns false otherwise" do should_not wildcard_match(:not_a_numeric) end end describe '#==' do it "returns true when given Numeric is a copy of this Numeric" do matcher2 = described_class.new should equal_match(matcher2) end it "returns false even when given an object that wildcard matches this Numeric" do should_not equal_match(99) end it "returns false when not a Numeric whatsoever" do should_not equal_match(:something_else) end end describe "#inspect" do it "returns the correct string" do matcher = described_class.new expect(matcher.inspect).to eq "numeric" end end end end end rr-3.1.0/spec/suites/rspec_2/unit/wildcard_matchers/hash_including_spec.rb0000644000004100000410000000407614265140426026760 0ustar www-datawww-datarequire File.expand_path('../../../spec_helper', __FILE__) module RR module WildcardMatchers describe HashIncluding do include WildcardMatcherMatchers describe '#wildcard_match?' do subject { described_class.new({:foo => 'x'}) } it "returns true when given object is a copy of this HashIncluding" do matcher2 = described_class.new({:foo => 'x'}) should wildcard_match(matcher2) end it "returns true when given hash is contained within expected hash" do should wildcard_match({:foo => 'x', :bar => 'y'}) end it "returns false when given object is not a Hash" do should_not wildcard_match('whatever') should_not wildcard_match(:whatever) should_not wildcard_match([1, 2, 3]) end it "returns false when given object is a hash but is not contained within expected hash" do should_not wildcard_match({:fiz => 'buz'}) end end describe '#==' do subject { described_class.new({:foo => 'x'}) } it "returns true when given object is a copy of this HashIncluding" do matcher2 = described_class.new({:foo => 'x'}) should equal_match(matcher2) end it "returns false when it is a HashIncluding but not with the same hash" do matcher2 = described_class.new({:x => 'y'}) should_not equal_match(matcher2) end it "returns false even when given a hash that wildcard matches this HashIncluding" do should_not equal_match({:foo => 'x'}) end it "returns false when not given a HashIncluding whatsoever" do should_not equal_match(:something_else) end end describe "#inspect" do it "returns the correct string" do matcher = described_class.new({:foo => 'x', :bar => 'y'}) str = matcher.inspect expect(str).to include("hash_including(") expect(str).to include(':foo=>"x"') expect(str).to include(':bar=>"y"') end end end end end rr-3.1.0/spec/suites/rspec_2/unit/wildcard_matchers/duck_type_spec.rb0000644000004100000410000000401714265140426025763 0ustar www-datawww-datarequire File.expand_path('../../../spec_helper', __FILE__) require 'ostruct' module RR module WildcardMatchers describe DuckType do include WildcardMatcherMatchers describe '#wildcard_match?' do subject { described_class.new(:quack, :waddle) } it "returns true when given DuckType is a copy of this DuckType" do matcher2 = described_class.new(:quack, :waddle) should wildcard_match(matcher2) end it "returns true when given object responds to all methods" do object = OpenStruct.new(:quack => 'x', :waddle => 'x') should wildcard_match(object) end it "returns false when given object responds to only some methods" do object = OpenStruct.new(:quack => 'x') should_not wildcard_match(object) end it "returns false when given object responds to no methods" do object = Object.new should_not wildcard_match(object) end end describe '#==' do subject { described_class.new(:quack, :waddle) } it "returns true when given DuckType is a copy of this DuckType" do matcher2 = described_class.new(:quack, :waddle) should equal_match(matcher2) end it "returns false when given DuckType is not a copy of this DuckType" do matcher2 = described_class.new(:something_else) should_not equal_match(matcher2) end it "returns false even when given a DuckType that wildcard matches this DuckType" do object = OpenStruct.new(:quack => 'x', :waddle => 'x') should_not equal_match(object) end it "returns false when not given a DuckType object whatsoever" do should_not equal_match(:something_else) end end describe "#inspect" do it "returns the correct string" do matcher = described_class.new(:quack, :waddle) expect(matcher.inspect).to eq "duck_type(:quack, :waddle)" end end end end end rr-3.1.0/spec/suites/rspec_2/unit/core_ext/0000755000004100000410000000000014265140426020564 5ustar www-datawww-datarr-3.1.0/spec/suites/rspec_2/unit/core_ext/enumerable_spec.rb0000644000004100000410000000305714265140426024247 0ustar www-datawww-datarequire File.expand_path('../../../spec_helper', __FILE__) describe Enumerable do include WildcardMatcherMatchers let(:klass) { Class.new do include Enumerable def initialize(*items) @arr = items end def each(&block) @arr.each(&block) end end } describe '#wildcard_match?' do context 'when this Enumerable has items that respond to #wildcard_match?' do subject { klass.new(hash_including({:foo => 'bar'})) } it "returns true if all items in the given Enumerable wildcard-match corresponding items in this Enumerable" do should wildcard_match([{:foo => 'bar', :baz => 'quux'}]) end it "returns true if any items in the given Enumerable do not wildcard-match corresponding items in this Enumerable" do should_not wildcard_match([{:foo => 'bat', :baz => 'quux'}]) end end context 'when this Enumerable has items that do not respond to #wildcard_match?' do subject { klass.new(:a_symbol) } it "returns true if all items in the given Enumerable equal-match corresponding items in this Enumerable" do should wildcard_match([:a_symbol]) end it "returns true if any items in the given Enumerable do not equal-match corresponding items in this Enumerable" do should_not wildcard_match([:another_symbol]) end end context 'when not given an Enumerable' do subject { klass.new({:foo => 'bar'}) } it "returns false" do should_not wildcard_match(:something_else) end end end end rr-3.1.0/spec/suites/rspec_2/unit/core_ext/range_spec.rb0000644000004100000410000000203314265140426023215 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper") describe Range do include WildcardMatcherMatchers describe '#wildcard_match?' do subject { 1..5 } it "returns true when given Range is exactly equal to this Range" do should wildcard_match(1..5) end it "returns true when given number falls within the range" do should wildcard_match(3) end it "returns false when given number falls outside the range" do should_not wildcard_match(8) end end describe '#==' do subject { 1..5 } it "returns true when given Range is exactly equal to this Range" do should equal_match(1..5) end it "returns false when given Range is not exactly equal to this Range" do should_not equal_match(3..5) end it "returns false even when given an object that wildcard matches this Range" do should_not equal_match(3) end it "returns false when given object isn't even a Range" do should_not equal_match(:something_else) end end end rr-3.1.0/spec/suites/rspec_2/unit/core_ext/array_spec.rb0000644000004100000410000000243014265140426023240 0ustar www-datawww-datarequire File.expand_path('../../../spec_helper', __FILE__) describe Array do include WildcardMatcherMatchers describe '#wildcard_match?' do context 'when this Array has items that respond to #wildcard_match?' do subject { [hash_including({:foo => 'bar'})] } it "returns true if all items in the given Array wildcard-match corresponding items in this Array" do should wildcard_match([{:foo => 'bar', :baz => 'quux'}]) end it "returns true if any items in the given Array do not wildcard-match corresponding items in this Array" do should_not wildcard_match([{:foo => 'bat', :baz => 'quux'}]) end end context 'when this Array has items that do not respond to #wildcard_match?' do subject { [:a_symbol] } it "returns true if all items in the given Array equal-match corresponding items in this Array" do should wildcard_match([:a_symbol]) end it "returns true if any items in the given Array do not equal-match corresponding items in this Array" do should_not wildcard_match([:another_symbol]) end end context 'when not given an Array' do subject { [{:foo => 'bar'}] } it "returns false" do should_not wildcard_match(:something_else) end end end end rr-3.1.0/spec/suites/rspec_2/unit/core_ext/hash_spec.rb0000644000004100000410000000350714265140426023053 0ustar www-datawww-datarequire File.expand_path('../../../spec_helper', __FILE__) describe Hash do include WildcardMatcherMatchers describe '#wildcard_match?' do context 'when this Hash has keys that respond to #wildcard_match?' do subject { {is_a(Symbol) => 'x'} } it "returns true if all keys in the given Hash wildcard-match the corresponding keys in this Hash" do should wildcard_match({:foo => 'x'}) end it "returns true if any keys in the given Hash do not wildcard-match the corresponding keys in this Hash" do should_not wildcard_match({'foo' => 'x'}) end end context 'when this Hash has values that respond to #wildcard_match?' do subject { {'x' => is_a(Symbol)} } it "returns true if all values in the given Hash wildcard-match the corresponding values in this Hash" do should wildcard_match({'x' => :foo}) end it "returns false if any values in the given Hash do not wildcard-match the corresponding values in this Hash" do should_not wildcard_match({'x' => 'foo'}) end end context 'when this Hash does not have keys or values that respond to #wildcard_match?' do subject { {:x => :y} } it "returns true if all pairs in the given Hash wildcard-match the corresponding values in this Hash" do should wildcard_match({:x => :y}) end it "returns false if any keys do not equal-match corresponding items in the subject" do should_not wildcard_match({:z => :y}) end it "returns false if any values do not equal-match corresponding items in the subject" do should_not wildcard_match({:x => :z}) end end context 'when not given a Hash' do subject { {:foo => 'bar'} } it "returns false" do should_not wildcard_match(:something_else) end end end end rr-3.1.0/spec/suites/rspec_2/unit/core_ext/regexp_spec.rb0000644000004100000410000000205014265140426023412 0ustar www-datawww-datarequire File.expand_path('../../../spec_helper', __FILE__) describe Regexp do include WildcardMatcherMatchers describe '#wildcard_match?' do subject { /foo/ } it "returns true when given Regexp is exactly equal to this Regexp" do should wildcard_match(/foo/) end it "returns true if given string matches the regexp" do should wildcard_match('foobarbaz') end it "returns false if given string does not match the regexp" do should_not wildcard_match('aslkj') end end describe '#==' do subject { /foo/ } it "returns true when given Regexp is exactly equal to this Regexp" do should equal_match(/foo/) end it "returns false when given Regexp is not exactly equal to this Regexp" do should_not equal_match(/alkj/) end it "returns false even when given an object that wildcard matches this Regexp" do should_not equal_match('foobarbaz') end it "returns false when not even given a Regexp" do should_not equal_match(:something_else) end end end rr-3.1.0/spec/suites/rspec_2/unit/spy_verification_spec.rb0000644000004100000410000001157614265140426023702 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../spec_helper") class Alpha def bob end end describe RR::SpyVerification do subject { Object.new } attr_reader :recorded_calls include_examples "Swapped Space" include RR::DSL before(:each) do stub(subject).foobar @recorded_calls = RR::RecordedCalls.new([[subject, :foobar, [1, 2], nil]]) end describe "#call" do context "when a subject is expected to receive a method with exact arguments" do context "when the number of times the subject received a method is not specified" do context "when there is an exact match one time" do it "verifies that the method with arguments was called once" do subject.foobar(1, 2) received(subject).foobar(1, 2).call subject.foobar(1, 2) expect { received(subject).foobar(1, 2).call }.to raise_error(RR::Errors::SpyVerificationErrors::InvocationCountError) end end end context "when the number of times the subject received a method is specified" do context "as one time" do it "verifies that the method with arugments was called once" do subject.foobar(1, 2) received(subject).foobar(1, 2).once.call subject.foobar(1, 2) expect { received(subject).foobar(1, 2).once.call }.to raise_error(RR::Errors::SpyVerificationErrors::InvocationCountError) end end context "as an at least matcher" do it "verifies that the method with arugments was called at least the specified number of times" do subject.foobar(1, 2) expect { received(subject).foobar(1, 2).at_least(2).call }.to raise_error(RR::Errors::SpyVerificationErrors::InvocationCountError) subject.foobar(1, 2) received(subject).foobar(1, 2).at_least(2).call subject.foobar(1, 2) received(subject).foobar(1, 2).at_least(2).call end end end end context "when a subject is expected to receive a method with wildcard arguments" do context "when the number of times the subject received a method is not specified" do context "when there is a wildcard match one time" do it "verifies that the method with arguments was called once" do subject.foobar(1, 2) received(subject).foobar(1, is_a(Fixnum)).call subject.foobar(1, 2) expect { received(subject).foobar(1, is_a(Fixnum)).call }.to raise_error(RR::Errors::SpyVerificationErrors::InvocationCountError) end end end context "when the number of times the subject received a method is specified" do context "as one time" do it "verifies that the method with arugments was called once" do subject.foobar(1, 2) received(subject).foobar(1, is_a(Fixnum)).once.call subject.foobar(1, 2) expect { received(subject).foobar(1, is_a(Fixnum)).once.call }.to raise_error(RR::Errors::SpyVerificationErrors::InvocationCountError) end end context "as an at least matcher" do it "verifies that the method with arugments was called at least the specified number of times" do subject.foobar(1, is_a(Fixnum)) expect { received(subject).foobar(1, is_a(Fixnum)).at_least(2).call }.to raise_error(RR::Errors::SpyVerificationErrors::InvocationCountError) subject.foobar(1, 2) received(subject).foobar(1, is_a(Fixnum)).at_least(2).call subject.foobar(1, 2) received(subject).foobar(1, is_a(Fixnum)).at_least(2).call end end end end context "when checking for ordering" do it "when the order is incorrect; raises an error" do subject.foobar(3, 4) subject.foobar(1, 2) expect { received(subject).foobar(1, 2).ordered.call received(subject).foobar(3, 4).ordered.call }.to raise_error(RR::Errors::SpyVerificationErrors::InvocationCountError) end it "when the order is correct; does not raise an error" do subject.foobar(1, 2) subject.foobar(1, 2) subject.foobar(3, 4) received(subject).foobar(1, 2).ordered.call received(subject).foobar(3, 4).ordered.call end end context "when the subject is expected where there is not DoubleInjection" do it "raises a DoubleInjectionNotFoundError" do expect(::RR::Injections::DoubleInjection.exists?(subject, :method_that_does_not_exist)).to be_false expect { received(subject).method_that_does_not_exist.call }.to raise_error(RR::Errors::SpyVerificationErrors::DoubleInjectionNotFoundError) end end end end rr-3.1.0/spec/suites/rspec_2/unit/double_definitions/0000755000004100000410000000000014265140426022621 5ustar www-datawww-datarr-3.1.0/spec/suites/rspec_2/unit/double_definitions/double_definition_create_spec.rb0000644000004100000410000004277214265140426031201 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper") module RR module DoubleDefinitions describe DoubleDefinitionCreate do subject { Object.new } attr_reader :double_definition_create, :strategy_method_name include_examples "Swapped Space" before(:each) do @double_definition_create = DoubleDefinitionCreate.new end describe "#root_subject" do it "returns #subject" do double_definition_create.stub(subject).foobar expect(double_definition_create.root_subject).to eq subject end end describe "StrategySetupMethods" do describe "normal strategy definitions" do def call_strategy(*args, &block) double_definition_create.__send__(strategy_method_name, *args, &block) end describe "#mock" do before do @strategy_method_name = :mock end context "when passing no args" do it "returns self" do expect(call_strategy).to equal double_definition_create end end context "when passed a subject and a method_name argument" do it "creates a mock Double for method" do double_definition = double_definition_create.mock(subject, :foobar).returns {:baz} expect(double_definition.times_matcher).to eq RR::TimesCalledMatchers::IntegerMatcher.new(1) expect(double_definition.argument_expectation.class).to eq RR::Expectations::ArgumentEqualityExpectation expect(double_definition.argument_expectation.expected_arguments).to eq [] expect(subject.foobar).to eq :baz end end end describe "#stub" do before do @strategy_method_name = :stub end context "when passing no args" do it "returns self" do expect(call_strategy).to equal double_definition_create end end context "when passed subject and a method_name argument" do it "creates a stub Double for method when passed a method_name argument" do double_definition = double_definition_create.stub(subject, :foobar).returns {:baz} expect(double_definition.times_matcher).to eq RR::TimesCalledMatchers::AnyTimesMatcher.new expect(double_definition.argument_expectation.class).to eq RR::Expectations::AnyArgumentExpectation expect(subject.foobar).to eq :baz end end end describe "#dont_allow" do before do @strategy_method_name = :dont_allow end context "when passing no args" do it "returns self" do expect(call_strategy).to equal double_definition_create end end context "when passed a subject and a method_name argument_expectation" do it "creates a mock Double for method" do double_definition = double_definition_create.dont_allow(subject, :foobar) expect(double_definition.times_matcher).to eq RR::TimesCalledMatchers::NeverMatcher.new expect(double_definition.argument_expectation.class).to eq RR::Expectations::AnyArgumentExpectation expect { subject.foobar }.to raise_error(RR::Errors::TimesCalledError) RR.reset end end end end describe "! strategy definitions" do attr_reader :strategy_method_name def call_strategy(*args, &definition_eval_block) double_definition_create.__send__(strategy_method_name, *args, &definition_eval_block) end describe "#mock!" do before do @strategy_method_name = :mock! end context "when passed a method_name argument" do it "sets #verification_strategy to Mock" do double_definition_create.mock!(:foobar) expect(double_definition_create.verification_strategy.class).to eq Strategies::Verification::Mock expect { RR.verify }.to raise_error(::RR::Errors::TimesCalledError) end end end describe "#stub!" do before do @strategy_method_name = :stub! end context "when passed a method_name argument" do it "sets #verification_strategy to Stub" do double_definition_create.stub!(:foobar) expect(double_definition_create.verification_strategy.class).to eq Strategies::Verification::Stub end end end describe "#dont_allow!" do before do @strategy_method_name = :dont_allow! end context "when passed a method_name argument" do it "sets #verification_strategy to DontAllow" do double_definition_create.dont_allow!(:foobar) expect(double_definition_create.verification_strategy.class).to eq Strategies::Verification::DontAllow end end end end describe "#stub.proxy" do before do class << subject def foobar(*args) :original_foobar end end end context "when passed a method_name argument" do it "creates a proxy Double for method" do double_definition = double_definition_create.stub.proxy(subject, :foobar).after_call {:baz} expect(double_definition.times_matcher).to eq RR::TimesCalledMatchers::AnyTimesMatcher.new expect(double_definition.argument_expectation.class).to eq RR::Expectations::AnyArgumentExpectation expect(subject.foobar).to eq :baz end end end describe "#instance_of" do context "when not passed a class" do it "raises an ArgumentError" do expect { double_definition_create.instance_of(Object.new).foobar }.to raise_error(ArgumentError, "instance_of only accepts class objects") end end context "when passed a method_name argument" do it "creates a proxy Double for method" do klass = Class.new double_definition = double_definition_create.stub.instance_of(klass, :foobar).returns {:baz} expect(double_definition.times_matcher).to eq RR::TimesCalledMatchers::AnyTimesMatcher.new expect(double_definition.argument_expectation.class).to eq RR::Expectations::AnyArgumentExpectation expect(klass.new.foobar).to eq :baz end end end describe "#instance_of.mock" do before do @klass = Class.new end # context "when passed no arguments" do # it "returns a DoubleDefinitiondouble_definition_create" do # expect(instance_of.instance_of).to be_instance_of(DoubleDefinitionCreate) # end # end context "when passed a method_name argument" do it "creates a instance_of Double for method" do double_definition = instance_of.mock(@klass, :foobar) double_definition.with(1, 2) {:baz} expect(double_definition.times_matcher).to eq RR::TimesCalledMatchers::IntegerMatcher.new(1) expect(double_definition.argument_expectation.class).to eq RR::Expectations::ArgumentEqualityExpectation expect(double_definition.argument_expectation.expected_arguments).to eq [1, 2] expect(@klass.new.foobar(1, 2)).to eq :baz end end end end describe "StrategyExecutionMethods" do describe "#create" do context "when #verification_strategy is a Mock" do context "when #implementation_strategy is a Reimplementation" do before do double_definition_create.mock(subject) end it "sets expectation on the #subject that it will be sent the method_name once with the passed-in arguments" do mock(subject).foobar(1, 2) subject.foobar(1, 2) expect { subject.foobar(1, 2) }.to raise_error(RR::Errors::TimesCalledError) expect { RR.verify }.to raise_error(RR::Errors::TimesCalledError) end describe "#subject.method_name being called" do it "returns the return value of the Double#returns block" do double_definition_create.call(:foobar, [1, 2], {}) {:baz} expect(subject.foobar(1, 2)).to eq :baz end end end context "when #implementation_strategy is a Proxy" do before do double_definition_create.mock double_definition_create.proxy(subject) end it "sets expectation on the #subject that it will be sent the method_name once with the passed-in arguments" do def subject.foobar(*args) :baz end mock(subject).foobar(1, 2) subject.foobar(1, 2) expect { subject.foobar(1, 2) }.to raise_error(RR::Errors::TimesCalledError) expect { RR.verify }.to raise_error(RR::Errors::TimesCalledError) end describe "#subject.method_name being called" do it "calls the original method" do original_method_called = false (class << subject; self; end).class_eval do define_method(:foobar) do |*args| original_method_called = true end end double_definition_create.call(:foobar, [1, 2], {}) subject.foobar(1, 2) expect(original_method_called).to be_true end context "when not passed a block" do it "returns the value of the original method" do def subject.foobar(*args) :baz; end double_definition_create.call(:foobar, [1, 2], {}) expect(subject.foobar(1, 2)).to eq :baz end end context "when passed a block" do attr_reader :real_value before do @real_value = real_value = Object.new (class << subject; self; end).class_eval do define_method(:foobar) {|arg1, arg2| real_value} end end it "calls the block with the return value of the original method" do double_definition_create.call(:foobar, [1, 2], {}) do |value| mock(value).a_method {99} value end subject.foobar(1, 2) expect(real_value.a_method).to eq 99 end it "returns the return value of the block" do double_definition_create.call(:foobar, [1, 2], {}) do |value| :something_else end expect(subject.foobar(1, 2)).to eq :something_else end end end end end context "when #verification_strategy is a Stub" do context "when #implementation_strategy is a Reimplementation" do before do double_definition_create.stub(subject) end context "when not passed a block" do it "returns nil" do double_definition_create.call(:foobar, [], {}) expect(subject.foobar).to be_nil end end context "when passed a block" do describe "#subject.method_name being called" do it "returns the return value of the block" do double_definition_create.call(:foobar, [], {}) {:baz} expect(subject.foobar).to eq :baz end end end context "when not passed args" do describe "#subject.method_name being called with any arguments" do it "invokes the implementation of the Stub" do double_definition_create.call(:foobar, [], {}) {:baz} expect(subject.foobar(1, 2)).to eq :baz expect(subject.foobar()).to eq :baz expect(subject.foobar([])).to eq :baz end end end context "when passed args" do describe "#subject.method_name being called with the passed-in arguments" do it "invokes the implementation of the Stub" do double_definition_create.call(:foobar, [1, 2], {}) {:baz} expect(subject.foobar(1, 2)).to eq :baz end end describe "#subject.method_name being called with different arguments" do it "raises a DoubleNotFoundError" do double_definition_create.call(:foobar, [1, 2], {}) {:baz} expect { subject.foobar }.to raise_error(RR::Errors::DoubleNotFoundError) end end end end context "when #implementation_strategy is a Proxy" do before do def subject.foobar(*args) :original_return_value end double_definition_create.stub double_definition_create.proxy(subject) end context "when not passed a block" do describe "#subject.method_name being called" do it "invokes the original implementanion" do double_definition_create.call(:foobar, [], {}) expect(subject.foobar).to eq :original_return_value end end end context "when passed a block" do describe "#subject.method_name being called" do it "invokes the original implementanion and invokes the block with the return value of the original implementanion" do passed_in_value = nil double_definition_create.call(:foobar, [], {}) do |original_return_value| passed_in_value = original_return_value end subject.foobar expect(passed_in_value).to eq :original_return_value end it "returns the return value of the block" do double_definition_create.call(:foobar, [], {}) do |original_return_value| :new_return_value end expect(subject.foobar).to eq :new_return_value end end end context "when passed args" do describe "#subject.method_name being called with the passed-in arguments" do it "invokes the implementation of the Stub" do double_definition_create.call(:foobar, [1, 2], {}) {:baz} expect(subject.foobar(1, 2)).to eq :baz end end describe "#subject.method_name being called with different arguments" do it "raises a DoubleNotFoundError" do double_definition_create.call(:foobar, [1, 2], {}) {:baz} expect { subject.foobar }.to raise_error(RR::Errors::DoubleNotFoundError) end end end end end context "when #verification_strategy is a DontAllow" do before do double_definition_create.dont_allow(subject) end context "when not passed args" do describe "#subject.method_name being called with any arguments" do it "raises a TimesCalledError" do double_definition_create.call(:foobar, [], {}) expect { subject.foobar }.to raise_error(RR::Errors::TimesCalledError) expect { subject.foobar(1, 2) }.to raise_error(RR::Errors::TimesCalledError) end end end context "when passed args" do describe "#subject.method_name being called with the passed-in arguments" do it "raises a TimesCalledError" do double_definition_create.call(:foobar, [1, 2], {}) expect { subject.foobar(1, 2) }.to raise_error(RR::Errors::TimesCalledError) end end describe "#subject.method_name being called with different arguments" do it "raises a DoubleNotFoundError" do double_definition_create.call(:foobar, [1, 2], {}) expect { subject.foobar() }.to raise_error(RR::Errors::DoubleNotFoundError) end end end end end end end end end rr-3.1.0/spec/suites/rspec_2/unit/double_definitions/child_double_definition_create_spec.rb0000644000004100000410000001107014265140426032327 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper") module RR module DoubleDefinitions describe ChildDoubleDefinitionCreate do attr_reader :parent_subject, :parent_double_definition_create, :parent_double_definition, :child_double_definition_create include_examples "Swapped Space" before(:each) do @parent_subject = Object.new @parent_double_definition_create = DoubleDefinitionCreate.new @parent_double_definition = DoubleDefinition.new(parent_double_definition_create) @child_double_definition_create = ChildDoubleDefinitionCreate.new(parent_double_definition) end describe "#root_subject" do it "returns the #parent_double_definition.root_subject" do child_subject = Object.new parent_double_definition_create.stub(parent_subject) child_double_definition_create.stub(child_subject) expect(child_double_definition_create.root_subject).to eq parent_subject end end describe "Strategies::Verification definitions" do describe "methods without !" do attr_reader :child_subject before do @child_subject = Object.new end describe "#mock" do context "when passed a subject" do it "sets #parent_double_definition.implementation to a Proc returning the passed-in subject" do expect(parent_double_definition.implementation).to be_nil child_double_definition_create.mock(child_subject) expect(parent_double_definition.implementation.call).to eq child_subject end end end describe "#stub" do context "when passed a subject" do it "sets #parent_double_definition.implementation to a Proc returning the passed-in subject" do expect(parent_double_definition.implementation).to be_nil child_double_definition_create.stub(child_subject) expect(parent_double_definition.implementation.call).to eq child_subject end end end describe "#dont_allow" do context "when passed a subject" do it "sets #parent_double_definition.implementation to a Proc returning the passed-in subject" do expect(parent_double_definition.implementation).to be_nil child_double_definition_create.dont_allow(child_subject) expect(parent_double_definition.implementation.call).to eq child_subject end end end end describe "methods with !" do describe "#mock!" do it "sets #parent_double_definition.implementation to a Proc returning the #subject" do expect(parent_double_definition.implementation).to be_nil child_subject = child_double_definition_create.mock!.__double_definition_create__.subject expect(parent_double_definition.implementation.call).to eq child_subject end end describe "#stub!" do it "sets #parent_double_definition.implementation to a Proc returning the #subject" do expect(parent_double_definition.implementation).to be_nil child_subject = child_double_definition_create.stub!.__double_definition_create__.subject expect(parent_double_definition.implementation.call).to eq child_subject end end describe "#dont_allow!" do it "sets #parent_double_definition.implementation to a Proc returning the #subject" do expect(parent_double_definition.implementation).to be_nil child_subject = child_double_definition_create.dont_allow!.__double_definition_create__.subject expect(parent_double_definition.implementation.call).to eq child_subject end end end end describe "Strategies::DoubleInjection definitions" do describe "methods without !" do describe "#instance_of" do it "raises a NoMethodError" do expect { child_double_definition_create.instance_of }.to raise_error(NoMethodError) end end end describe "methods with !" do describe "#instance_of!" do it "raises a NoMethodError" do expect { child_double_definition_create.instance_of! }.to raise_error(NoMethodError) end end end end end end end rr-3.1.0/spec/suites/rspec_2/unit/double_definitions/double_definition_create_blank_slate_spec.rb0000644000004100000410000000602014265140426033522 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper") module RR module DoubleDefinitions describe DoubleDefinitionCreateBlankSlate do attr_reader :double_definition_create, :blank_slate include_examples "Swapped Space" subject { Object.new } before(:each) do @double_definition_create = DoubleDefinitionCreate.new double_definition_create.mock(subject) end describe ".new" do it "does not undefine object_id" do blank_slate = DoubleDefinitionCreateBlankSlate.new(double_definition_create) expect(blank_slate.object_id.class).to eq Fixnum end context "without block" do before do @blank_slate = DoubleDefinitionCreateBlankSlate.new(double_definition_create) end it "clears out all methods from proxy" do expect(stub(subject).i_should_be_a_double).to be_instance_of(DoubleDefinition) end end context "when passed a block" do context "when the block has an arity of 1" do attr_reader :passed_in_argument before do passed_in_argument = nil stub(subject) do |b| passed_in_argument = b b.foobar(1, 2) {:one_two} b.foobar(1) {:one} b.foobar.with_any_args {:default} b.baz() {:baz_result} end @passed_in_argument = passed_in_argument end it "creates double_injections" do expect(subject.foobar(1, 2)).to eq :one_two expect(subject.foobar(1)).to eq :one expect(subject.foobar(:something)).to eq :default expect(subject.baz).to eq :baz_result end it "passes the self into the block" do expect(passed_in_argument.__double_definition_create__).to be_instance_of( ::RR::DoubleDefinitions::DoubleDefinitionCreate ) end end context "when the block has an arity of 0" do attr_reader :self_value before do self_value = nil stub(subject) do || self_value = self foobar(1, 2) {:one_two} foobar(1) {:one} foobar.with_any_args {:default} baz() {:baz_result} end @self_value = self_value end it "creates double_injections" do expect(subject.foobar(1, 2)).to eq :one_two expect(subject.foobar(1)).to eq :one expect(subject.foobar(:something)).to eq :default expect(subject.baz).to eq :baz_result end it "evaluates the block with the context of self" do expect(self_value.__double_definition_create__).to be_instance_of( ::RR::DoubleDefinitions::DoubleDefinitionCreate ) end end end end end end end rr-3.1.0/spec/suites/rspec_2/unit/errors/0000755000004100000410000000000014265140426020270 5ustar www-datawww-datarr-3.1.0/spec/suites/rspec_2/unit/errors/rr_error_spec.rb0000644000004100000410000000345614265140426023473 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper") module RR module Errors describe RRError do describe "#backtrace" do before do @original_trim_backtrace = RR.trim_backtrace end after do RR.trim_backtrace = @original_trim_backtrace end it "does not include the rr library files when trim_backtrace is true" do RR.trim_backtrace = true error = nil begin obj = Object.new mock(obj).foobar RR.verify_double(obj, :foobar) rescue RRError=> e error = e end backtrace = error.backtrace.join("\n") backtrace.should_not include("lib/rr") end it "includes the rr library files when trim_backtrace is false" do RR.trim_backtrace = false error = nil begin obj = Object.new mock(obj).foobar RR.verify_double(obj, :foobar) rescue RRError=> e error = e end backtrace = error.backtrace.join("\n") expect(backtrace).to include("lib/rr") end it "returns custom backtrace when backtrace is set" do error = RRError.new custom_backtrace = caller error.backtrace = custom_backtrace expect(error.backtrace).to eq custom_backtrace end it "returns normal backtrace when backtrace is not set" do error = nil expected_line = __LINE__ + 2 begin raise RRError rescue RRError => e error = e end expect(error.backtrace.first).to include(__FILE__) expect(error.backtrace.first).to include(expected_line.to_s) end end end end end rr-3.1.0/spec/suites/rspec_2/unit/injections/0000755000004100000410000000000014265140426021121 5ustar www-datawww-datarr-3.1.0/spec/suites/rspec_2/unit/injections/double_injection/0000755000004100000410000000000014265140426024435 5ustar www-datawww-datarr-3.1.0/spec/suites/rspec_2/unit/injections/double_injection/double_injection_verify_spec.rb0000644000004100000410000000200014265140426032664 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../../spec_helper") module RR module Injections describe DoubleInjection, "#verify" do subject { Object.new } include_examples "Swapped Space" attr_reader :method_name, :double_injection before do @method_name = :foobar subject.methods.should_not include(method_name.to_s) @double_injection = ::RR::Injections::DoubleInjection.find_or_create_by_subject(subject, method_name) end it "verifies each double was met" do double = RR::Double.new( double_injection, RR::DoubleDefinitions::DoubleDefinition.new(RR::DoubleDefinitions::DoubleDefinitionCreate.new) ) double_injection.register_double double double.definition.with(1).once.returns {nil} expect { double_injection.verify }.to raise_error(RR::Errors::TimesCalledError) subject.foobar(1) expect { double_injection.verify }.to_not raise_error end end end end rr-3.1.0/spec/suites/rspec_2/unit/injections/double_injection/double_injection_spec.rb0000644000004100000410000004730514265140426031321 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../../spec_helper") module RR module Injections describe DoubleInjection do attr_reader :method_name, :double_injection macro("sets up subject and method_name") do it "sets up subject and method_name" do expect(double_injection.subject).to equal subject expect(double_injection.method_name).to eq method_name.to_sym end end subject { Object.new } describe "mock/stub" do context "when the subject responds to the injected method" do before do class << subject attr_reader :original_foobar_called def foobar @original_foobar_called = true :original_foobar end end expect(subject).to respond_to(:foobar) expect(!!subject.methods.detect {|method| method.to_sym == :foobar}).to be_true stub(subject).foobar {:new_foobar} end describe "being bound" do it "sets __rr__original_{method_name} to the original method" do expect(subject.__rr__original_foobar).to eq :original_foobar end describe "being called" do it "returns the return value of the block" do expect(subject.foobar).to eq :new_foobar end it "does not call the original method" do subject.foobar expect(subject.original_foobar_called).to be_nil end end describe "being reset" do before do RR::Space.reset_double(subject, :foobar) end it "rebinds the original method" do expect(subject.foobar).to eq :original_foobar end it "removes __rr__original_{method_name}" do subject.should_not respond_to(:__rr__original_foobar) end end end end context "when the subject does not respond to the injected method" do before do subject.should_not respond_to(:foobar) subject.methods.should_not include('foobar') stub(subject).foobar {:new_foobar} end it "does not set __rr__original_{method_name} to the original method" do subject.should_not respond_to(:__rr__original_foobar) end describe "being called" do it "calls the newly defined method" do expect(subject.foobar).to eq :new_foobar end end describe "being reset" do before do RR::Space.reset_double(subject, :foobar) end it "unsets the foobar method" do subject.should_not respond_to(:foobar) subject.methods.should_not include('foobar') end end end context "when the subject redefines respond_to?" do it "does not try to call the implementation" do class << subject def respond_to?(method_symbol, include_private = false) method_symbol == :foobar end end mock(subject).foobar expect(subject.foobar).to eq nil end end end describe "mock/stub + proxy" do context "when the subject responds to the injected method" do context "when the subject has the method defined" do describe "being bound" do before do def subject.foobar :original_foobar end expect(subject).to respond_to(:foobar) expect(!!subject.methods.detect {|method| method.to_sym == :foobar}).to be_true stub.proxy(subject).foobar {:new_foobar} end it "aliases the original method to __rr__original_{method_name}" do expect(subject.__rr__original_foobar).to eq :original_foobar end it "replaces the original method with the new method" do expect(subject.foobar).to eq :new_foobar end describe "being called" do it "calls the original method first and sends it into the block" do original_return_value = nil stub.proxy(subject).foobar {|arg| original_return_value = arg; :new_foobar} expect(subject.foobar).to eq :new_foobar expect(original_return_value).to eq :original_foobar end end describe "being reset" do before do RR::Space.reset_double(subject, :foobar) end it "rebinds the original method" do expect(subject.foobar).to eq :original_foobar end it "removes __rr__original_{method_name}" do subject.should_not respond_to(:__rr__original_foobar) end end end end context "when the subject does not have the method defined" do describe "being bound" do context "when the subject has not been previously bound to" do before do setup_subject expect(subject).to respond_to(:foobar) stub.proxy(subject).foobar {:new_foobar} end def setup_subject def subject.respond_to?(method_name) if method_name.to_sym == :foobar true else super end end end it "does not define __rr__original_{method_name}" do subject.methods.should_not include("__rr__original_foobar") end context "when method is defined after being bound and before being called" do def setup_subject super def subject.foobar :original_foobar end end describe "being called" do it "defines __rr__original_{method_name} to be the lazily created method" do expect((!!subject.methods.detect {|method| method.to_sym == :__rr__original_foobar})).to be_true expect(subject.__rr__original_foobar).to eq :original_foobar end it "calls the original method first and sends it into the block" do original_return_value = nil stub.proxy(subject).foobar {|arg| original_return_value = arg; :new_foobar} expect(subject.foobar).to eq :new_foobar expect(original_return_value).to eq :original_foobar end end describe "being reset" do before do RR::Space.reset_double(subject, :foobar) end it "rebinds the original method" do expect(subject.foobar).to eq :original_foobar end it "removes __rr__original_{method_name}" do subject.should_not respond_to(:__rr__original_foobar) end end end context "when method is still not defined" do context "when the method is lazily created" do def setup_subject super def subject.method_missing(method_name, *args, &block) if method_name.to_sym == :foobar def self.foobar :original_foobar end foobar else super end end end describe "being called" do it "calls the lazily created method and returns the injected method return value" do original_return_value = nil stub.proxy(subject).foobar {|arg| original_return_value = arg; :new_foobar} expect(subject.foobar).to eq :new_foobar expect(original_return_value).to eq :original_foobar end end describe "being reset" do context "when reset before being called" do before do RR::Space.reset_double(subject, :foobar) end it "rebinds the original method" do expect(subject.foobar).to eq :original_foobar end it "removes __rr__original_{method_name}" do subject.should_not respond_to(:__rr__original_foobar) end end end end context "when the method is not lazily created (handled in method_missing)" do def setup_subject super def subject.method_missing(method_name, *args, &block) if method_name.to_sym == :foobar :original_foobar else super end end end describe "being called" do it "does not define the __rr__original_{method_name}" do subject.foobar subject.methods.should_not include("__rr__original_foobar") end it "calls the lazily created method and returns the injected method return value" do original_return_value = nil stub.proxy(subject).foobar {|arg| original_return_value = arg; :new_foobar} expect(subject.foobar).to eq :new_foobar expect(original_return_value).to eq :original_foobar end end describe "being reset" do before do RR::Space.reset_double(subject, :foobar) end it "rebinds the original method" do expect(subject.foobar).to eq :original_foobar end it "removes __rr__original_{method_name}" do subject.should_not respond_to(:__rr__original_foobar) end end end end end context "when the subject has been previously bound to" do before do setup_subject expect(subject).to respond_to(:foobar) stub.proxy(subject).baz {:new_baz} stub.proxy(subject).foobar {:new_foobar} end def setup_subject def subject.respond_to?(method_name) if method_name.to_sym == :foobar || method_name.to_sym == :baz true else super end end end it "does not define __rr__original_{method_name}" do subject.methods.should_not include("__rr__original_foobar") end context "when method is defined after being bound and before being called" do def setup_subject super def subject.foobar :original_foobar end end describe "being called" do it "defines __rr__original_{method_name} to be the lazily created method" do expect((!!subject.methods.detect {|method| method.to_sym == :__rr__original_foobar})).to be_true expect(subject.__rr__original_foobar).to eq :original_foobar end it "calls the original method first and sends it into the block" do original_return_value = nil stub.proxy(subject).foobar {|arg| original_return_value = arg; :new_foobar} expect(subject.foobar).to eq :new_foobar expect(original_return_value).to eq :original_foobar end end describe "being reset" do before do RR::Space.reset_double(subject, :foobar) end it "rebinds the original method" do expect(subject.foobar).to eq :original_foobar end it "removes __rr__original_{method_name}" do subject.should_not respond_to(:__rr__original_foobar) end end end context "when method is still not defined" do context "when the method is lazily created" do def setup_subject super def subject.method_missing(method_name, *args, &block) if method_name.to_sym == :foobar def self.foobar :original_foobar end foobar else super end end end describe "being called" do it "calls the lazily created method and returns the injected method return value" do original_return_value = nil stub.proxy(subject).foobar {|arg| original_return_value = arg; :new_foobar} expect(subject.foobar).to eq :new_foobar expect(original_return_value).to eq :original_foobar end end describe "being reset" do context "when reset before being called" do before do RR::Space.reset_double(subject, :foobar) end it "rebinds the original method" do expect(subject.foobar).to eq :original_foobar end it "removes __rr__original_{method_name}" do subject.should_not respond_to(:__rr__original_foobar) end end end end context "when the method is not lazily created (handled in method_missing)" do def setup_subject super def subject.method_missing(method_name, *args, &block) if method_name.to_sym == :foobar :original_foobar else super end end end describe "being called" do it "does not define the __rr__original_{method_name}" do subject.foobar subject.methods.should_not include("__rr__original_foobar") end it "calls the lazily created method and returns the injected method return value" do original_return_value = nil stub.proxy(subject).foobar {|arg| original_return_value = arg; :new_foobar} expect(subject.foobar).to eq :new_foobar expect(original_return_value).to eq :original_foobar end end describe "being reset" do before do RR::Space.reset_double(subject, :foobar) end it "rebinds the original method" do expect(subject.foobar).to eq :original_foobar end it "removes __rr__original_{method_name}" do subject.should_not respond_to(:__rr__original_foobar) end end end end end end end end context "when the subject does not respond to the injected method" do context "when the subject responds to the method via method_missing" do describe "being bound" do before do subject.should_not respond_to(:foobar) subject.methods.should_not include('foobar') class << subject def method_missing(method_name, *args, &block) if method_name == :foobar :original_foobar else super end end end stub.proxy(subject).foobar {:new_foobar} end it "adds the method to the subject" do expect(subject).to respond_to(:foobar) expect((!!subject.methods.detect {|method| method.to_sym == :foobar})).to be_true end describe "being called" do it "calls the original method first and sends it into the block" do original_return_value = nil stub.proxy(subject).foobar {|arg| original_return_value = arg; :new_foobar} expect(subject.foobar).to eq :new_foobar expect(original_return_value).to eq :original_foobar end end describe "being reset" do before do RR::Space.reset_double(subject, :foobar) end it "unsets the foobar method" do subject.should_not respond_to(:foobar) subject.methods.should_not include('foobar') end end end end context "when the subject would raise a NoMethodError when the method is called" do describe "being bound" do before do subject.should_not respond_to(:foobar) subject.methods.should_not include('foobar') stub.proxy(subject).foobar {:new_foobar} end it "adds the method to the subject" do expect(subject).to respond_to(:foobar) expect((!!subject.methods.detect {|method| method.to_sym == :foobar})).to be_true end describe "being called" do it "raises a NoMethodError" do expect { subject.foobar }.to raise_error(NoMethodError) end end describe "being reset" do before do RR::Space.reset_double(subject, :foobar) end it "unsets the foobar method" do subject.should_not respond_to(:foobar) subject.methods.should_not include('foobar') end end end end end end end end end rr-3.1.0/spec/suites/rspec_2/unit/dsl/0000755000004100000410000000000014265140426017536 5ustar www-datawww-datarr-3.1.0/spec/suites/rspec_2/unit/dsl/wildcard_matchers_spec.rb0000644000004100000410000000355514265140426024564 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper") module RR describe DSL do include DSL describe "#anything" do it "returns an Anything matcher" do expect(anything).to eq RR::WildcardMatchers::Anything.new end it "rr_anything returns an Anything matcher" do expect(rr_anything).to eq RR::WildcardMatchers::Anything.new end end describe "#is_a" do it "returns an IsA matcher" do expect(is_a(Integer)).to eq RR::WildcardMatchers::IsA.new(Integer) end it "rr_is_a returns an IsA matcher" do expect(rr_is_a(Integer)).to eq RR::WildcardMatchers::IsA.new(Integer) end end describe "#numeric" do it "returns an Numeric matcher" do expect(numeric).to eq RR::WildcardMatchers::Numeric.new end it "rr_numeric returns an Numeric matcher" do expect(rr_numeric).to eq RR::WildcardMatchers::Numeric.new end end describe "#boolean" do it "returns an Boolean matcher" do expect(boolean).to eq RR::WildcardMatchers::Boolean.new end it "rr_boolean returns an Boolean matcher" do expect(rr_boolean).to eq RR::WildcardMatchers::Boolean.new end end describe "#duck_type" do it "returns a DuckType matcher" do expect(duck_type(:one, :two)).to eq RR::WildcardMatchers::DuckType.new(:one, :two) end it "rr_duck_type returns a DuckType matcher" do expect(rr_duck_type(:one, :two)).to eq RR::WildcardMatchers::DuckType.new(:one, :two) end end end describe "#any_times" do it "returns an AnyTimesMatcher" do expect(any_times).to eq RR::TimesCalledMatchers::AnyTimesMatcher.new end it "rr_any_times returns an AnyTimesMatcher" do expect(rr_any_times).to eq RR::TimesCalledMatchers::AnyTimesMatcher.new end end end rr-3.1.0/spec/suites/rspec_2/unit/dsl/double_creators_spec.rb0000644000004100000410000001057014265140426024254 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper") module RR describe DSL do subject { Object.new } after(:each) do RR.reset end describe "normal strategy definitions" do attr_reader :strategy_method_name def call_strategy(*args, &block) __send__(strategy_method_name, *args, &block) end describe "#mock" do before do @strategy_method_name = :mock end context "when passing no args" do it "returns a DoubleDefinitionCreate" do expect(call_strategy.class).to eq RR::DoubleDefinitions::DoubleDefinitionCreate end end context "when passed a method_name argument" do it "creates a mock Double for method" do double_definition = mock(subject, :foobar).returns {:baz} expect(double_definition.times_matcher).to eq RR::TimesCalledMatchers::IntegerMatcher.new(1) expect(double_definition.argument_expectation.class).to eq RR::Expectations::ArgumentEqualityExpectation expect(double_definition.argument_expectation.expected_arguments).to eq [] expect(subject.foobar).to eq :baz end end end describe "#stub" do before do @strategy_method_name = :stub end context "when passing no args" do it "returns a DoubleDefinitionCreate" do expect(call_strategy.class).to eq RR::DoubleDefinitions::DoubleDefinitionCreate end end context "when passed a method_name argument" do it "creates a stub Double for method when passed a method_name argument" do double_definition = stub(subject, :foobar).returns {:baz} expect(double_definition.times_matcher).to eq RR::TimesCalledMatchers::AnyTimesMatcher.new expect(double_definition.argument_expectation.class).to eq RR::Expectations::AnyArgumentExpectation expect(subject.foobar).to eq :baz end end end describe "#dont_allow" do before do @strategy_method_name = :dont_allow end context "when passing no args" do it "returns a DoubleDefinitionCreate" do expect(call_strategy.class).to eq RR::DoubleDefinitions::DoubleDefinitionCreate end end context "when passed a method_name argument_expectation" do it "creates a mock Double for method" do double_definition = dont_allow(subject, :foobar) expect(double_definition.times_matcher).to eq RR::TimesCalledMatchers::NeverMatcher.new expect(double_definition.argument_expectation.class).to eq RR::Expectations::AnyArgumentExpectation expect { subject.foobar }.to raise_error(RR::Errors::TimesCalledError) RR.reset end end end end describe "! strategy definitions" do attr_reader :strategy_method_name def call_strategy(*args, &definition_eval_block) __send__(strategy_method_name, *args, &definition_eval_block) end describe "#mock!" do before do @strategy_method_name = :mock! end context "when passed a method_name argument" do it "sets #verification_strategy to Mock" do proxy = mock!(:foobar) expect(proxy.double_definition_create.verification_strategy.class).to eq RR::DoubleDefinitions::Strategies::Verification::Mock end end end describe "#stub!" do before do @strategy_method_name = :stub! end context "when passed a method_name argument" do it "sets #verification_strategy to Stub" do proxy = stub!(:foobar) expect(proxy.double_definition_create.verification_strategy.class).to eq RR::DoubleDefinitions::Strategies::Verification::Stub end end end describe "#dont_allow!" do before do @strategy_method_name = :dont_allow! end context "when passed a method_name argument" do it "sets #verification_strategy to DontAllow" do proxy = dont_allow!(:foobar) expect(proxy.double_definition_create.verification_strategy.class).to eq RR::DoubleDefinitions::Strategies::Verification::DontAllow end end end end end end rr-3.1.0/spec/suites/rspec_2/unit/dsl/space_spec.rb0000644000004100000410000000562314265140426022176 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper") module RR describe DSL do attr_reader :space, :subject_1, :subject_2, :method_name include_examples "Swapped Space" include RR::DSL before do @subject_1 = Object.new @subject_2 = Object.new @method_name = :foobar end describe "#verify" do it "aliases #rr_verify" do expect(DSL.instance_method("verify")).to eq DSL.instance_method("rr_verify") end end describe "#rr_verify" do it "verifies and deletes the double_injections" do double_1 = ::RR::Injections::DoubleInjection.find_or_create_by_subject(subject_1, method_name) double_1_verify_calls = 0 double_1_reset_calls = 0 ( class << double_1; self; end).class_eval do define_method(:verify) do || double_1_verify_calls += 1 end define_method(:reset) do || double_1_reset_calls += 1 end end double_2 = ::RR::Injections::DoubleInjection.find_or_create_by_subject(subject_2, method_name) double_2_verify_calls = 0 double_2_reset_calls = 0 ( class << double_2; self; end).class_eval do define_method(:verify) do || double_2_verify_calls += 1 end define_method(:reset) do || double_2_reset_calls += 1 end end rr_verify expect(double_1_verify_calls).to eq 1 expect(double_2_verify_calls).to eq 1 expect(double_1_reset_calls).to eq 1 expect(double_1_reset_calls).to eq 1 end end describe "#reset" do it "aliases #rr_reset" do expect(DSL.instance_method("reset")).to eq DSL.instance_method("rr_reset") end end describe "#rr_reset" do it "removes the ordered doubles" do mock(subject_1).foobar1.ordered mock(subject_2).foobar2.ordered ::RR::Injections::DoubleInjection.instances.should_not be_empty rr_reset ::RR::Injections::DoubleInjection.instances expect(::RR::Injections::DoubleInjection.instances).to be_empty end it "resets all double_injections" do double_1 = ::RR::Injections::DoubleInjection.find_or_create_by_subject(subject_1, method_name) double_1_reset_calls = 0 ( class << double_1; self; end).class_eval do define_method(:reset) do || double_1_reset_calls += 1 end end double_2 = ::RR::Injections::DoubleInjection.find_or_create_by_subject(subject_2, method_name) double_2_reset_calls = 0 ( class << double_2; self; end).class_eval do define_method(:reset) do || double_2_reset_calls += 1 end end rr_reset expect(double_1_reset_calls).to eq 1 expect(double_2_reset_calls).to eq 1 end end end end rr-3.1.0/spec/suites/rspec_2/unit/integrations/0000755000004100000410000000000014265140426021462 5ustar www-datawww-datarr-3.1.0/spec/suites/rspec_2/unit/integrations/rspec_spec.rb0000644000004100000410000000347014265140426024141 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper") module RR module Integrations describe RSpec2 do attr_reader :fixture, :method_name describe "#setup_mocks_for_rspec" do subject { Object.new } before do @fixture = Object.new fixture.extend RSpec2::Mixin @method_name = :foobar end it "resets the double_injections" do stub(subject).foobar ::RR::Injections::DoubleInjection.instances.should_not be_empty fixture.setup_mocks_for_rspec expect(::RR::Injections::DoubleInjection.instances).to be_empty end end describe "#verify_mocks_for_rspec" do subject { Object.new } before do @fixture = Object.new fixture.extend RSpec2::Mixin @method_name = :foobar end it "verifies the double_injections" do mock(subject).foobar expect { fixture.verify_mocks_for_rspec }.to raise_error(::RR::Errors::TimesCalledError) expect(::RR::Injections::DoubleInjection.instances).to be_empty end end describe "#teardown_mocks_for_rspec" do subject { Object.new } before do @fixture = Object.new fixture.extend RSpec2::Mixin @method_name = :foobar end it "resets the double_injections" do stub(subject).foobar ::RR::Injections::DoubleInjection.instances.should_not be_empty fixture.teardown_mocks_for_rspec expect(::RR::Injections::DoubleInjection.instances).to be_empty end end describe "#trim_backtrace" do it "does not set trim_backtrace" do expect(RR.trim_backtrace).to eq false end end end end end rr-3.1.0/spec/suites/rspec_2/unit/integrations/rspec/0000755000004100000410000000000014265140426022576 5ustar www-datawww-datarr-3.1.0/spec/suites/rspec_2/unit/integrations/rspec/invocation_matcher_spec.rb0000644000004100000410000002034614265140426030016 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../../spec_helper") module RR module Integrations module RSpec describe InvocationMatcher do describe "matching against a method with no doubles" do before do @matcher = InvocationMatcher.new(:foobar) @result = @matcher.matches?(Object.new) end it "does not match" do @result.should_not be end end describe "defining an expectation using a method invocation" do subject { Object.new } before do stub(subject).foobar subject.foobar(:args) @result = InvocationMatcher.new.foobar(:args).matches?(subject) end it "uses the invoked method as the expected method" do expect(@result).to be end end describe "matching against a stubbed method that was never called" do subject { Object.new } before do stub(subject).foobar @matcher = InvocationMatcher.new(:foobar) @result = @matcher.matches?(subject) end it "does not match" do @result.should_not be end end describe "matching against a stubbed method that was called once" do subject { Object.new } before do stub(subject).foobar subject.foobar @result = InvocationMatcher.new(:foobar).matches?(subject) end it "does match" do expect(@result).to be end end describe "matching against a stubbed method that was called with unexpected arguments" do subject { Object.new } before do @args = %w(one two) stub(subject).foobar subject.foobar(:other) @result = InvocationMatcher.new(:foobar).with(*@args).matches?(subject) end it "does not match" do @result.should_not be end end describe "matching against a stubbed method that was called with expected arguments" do subject { Object.new } before do @args = %w(one two) stub(subject).foobar subject.foobar(*@args) @result = InvocationMatcher.new(:foobar).with(*@args).matches?(subject) end it "does match" do expect(@result).to be end end describe "defining a fulfilled argument expectation using a method invocation" do subject { Object.new } before do @args = %w(one two) stub(subject).foobar subject.foobar(*@args) @result = InvocationMatcher.new.foobar(*@args).matches?(subject) end it "does match" do expect(@result).to be end end describe "defining an unfulfilled argument expectation using a method invocation" do subject { Object.new } before do @args = %w(one two) stub(subject).foobar subject.foobar(:other) @result = InvocationMatcher.new.foobar(*@args).matches?(subject) end it "does not match" do @result.should_not be end end describe "matching against a stubbed method that was called more than once" do subject { Object.new } before do stub(subject).foobar 2.times { subject.foobar } @result = InvocationMatcher.new(:foobar).twice.matches?(subject) end it "does match" do expect(@result).to be end end describe "matching a stubbed method with any arguments" do subject { Object.new } before do stub(subject).foobar subject.foobar(:args) @result = InvocationMatcher.new(:foobar).with_any_args.matches?(subject) end it "does match" do expect(@result).to be end end describe "matching a stubbed method with no arguments when arguments are not provided" do subject { Object.new } before do stub(subject).foobar subject.foobar @result = InvocationMatcher.new(:foobar).with_no_args.matches?(subject) end it "does match" do expect(@result).to be end end describe "matching a stubbed method with no arguments when arguments are provided" do subject { Object.new } before do stub(subject).foobar subject.foobar(:args) @result = InvocationMatcher.new(:foobar).with_no_args.matches?(subject) end it "does not match" do @result.should_not be end end describe "matching a method that was called twice when expected once" do subject { Object.new } before do stub(subject).foobar 2.times { subject.foobar } @matcher = InvocationMatcher.new(:foobar).times(1) @result = @matcher.matches?(subject) end it "does not match" do @result.should_not be end end describe "matching a method that was called twice when expected twice" do subject { Object.new } before do stub(subject).foobar 2.times { subject.foobar } @result = InvocationMatcher.new(:foobar).times(2).matches?(subject) end it "does match" do expect(@result).to be end end describe "matching a method that was called twice when any number of times" do subject { Object.new } before do stub(subject).foobar 2.times { subject.foobar } @result = InvocationMatcher.new(:foobar).any_number_of_times.matches?(subject) end it "does match" do expect(@result).to be end end describe "matching a method that was called three times when expected at most twice" do subject { Object.new } before do stub(subject).foobar 3.times { subject.foobar } @result = InvocationMatcher.new(:foobar).at_most(2).matches?(subject) end it "does not match" do @result.should_not be end end describe "matching a method that was called once when expected at most twice" do subject { Object.new } before do stub(subject).foobar subject.foobar @result = InvocationMatcher.new(:foobar).at_most(2).matches?(subject) end it "does match" do expect(@result).to be end end describe "matching a method that was called once when expected at least twice" do subject { Object.new } before do stub(subject).foobar subject.foobar @result = InvocationMatcher.new(:foobar).at_least(2).matches?(subject) end it "does not match" do @result.should_not be end end describe "matching a method that was called three times when expected at least twice" do subject { Object.new } before do stub(subject).foobar 3.times { subject.foobar } @result = InvocationMatcher.new(:foobar).at_least(2).matches?(subject) end it "does match" do expect(@result).to be end end describe "that does not match" do before do @error = Object.new @message = 'Verification error message' stub(RR::Space.instance.recorded_calls).match_error { @error } stub(@error).message { @message } @matcher = InvocationMatcher.new(:foobar) @result = @matcher.matches?(Object.new) end it "returns false when matching" do @result.should_not be end it "returns a failure messsage" do expect(@matcher.failure_message).to eq @message end end end end end end rr-3.1.0/spec/suites/rspec_2/unit/times_called_matchers/0000755000004100000410000000000014265140426023267 5ustar www-datawww-datarr-3.1.0/spec/suites/rspec_2/unit/times_called_matchers/at_least_matcher_spec.rb0000644000004100000410000000250214265140426030124 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper") module RR module TimesCalledMatchers describe AtLeastMatcher do attr_reader :matcher, :times before do @times = 3 @matcher = AtLeastMatcher.new(times) end describe "#possible_match?" do it "always returns true" do expect(matcher).to be_possible_match(99999) end end describe "#matches?" do it "returns false when times_called less than times" do matcher.should_not be_matches(2) end it "returns true when times_called == times" do expect(matcher).to be_matches(3) end it "returns true when times_called > times" do expect(matcher).to be_matches(4) end end describe "#attempt?" do it "always returns true" do expect(matcher).to be_attempt(1) expect(matcher).to be_attempt(100000) end end describe AnyTimesMatcher, "#terminal?" do it "returns false" do matcher.should_not be_terminal end end describe "#error_message" do it "has an error message" do expect(matcher.error_message(2)).to eq \ "Called 2 times.\nExpected at least 3 times." end end end end end rr-3.1.0/spec/suites/rspec_2/unit/times_called_matchers/times_called_matcher_spec.rb0000644000004100000410000000727314265140426030767 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper") module RR module TimesCalledMatchers describe TimesCalledMatcher do describe ".create" do describe "when passed a AnyTimesMatcher" do it "returns the passed in argument" do matcher = AnyTimesMatcher.new expect(TimesCalledMatcher.create(matcher)).to equal matcher end end describe "when passed a AtLeastMatcher" do it "returns the passed in argument" do matcher = AtLeastMatcher.new(5) expect(TimesCalledMatcher.create(matcher)).to equal matcher end end describe "when passed a AtMostMatcher" do it "returns the passed in argument" do matcher = AtMostMatcher.new(5) expect(TimesCalledMatcher.create(matcher)).to equal matcher end end describe "when passed a IntegerMatcher" do it "returns the passed in argument" do matcher = IntegerMatcher.new(5) expect(TimesCalledMatcher.create(matcher)).to equal matcher end end describe "when passed a Integer" do it "returns IntegerMatcher" do expect(TimesCalledMatcher.create(5)).to eq IntegerMatcher.new(5) end end describe "when passed a ProcMatcher" do it "returns the passed in argument" do matcher = ProcMatcher.new(lambda {|other| other == 5}) expect(TimesCalledMatcher.create(matcher)).to equal matcher end end describe "when passed a Lambda" do it "returns ProcMatcher" do value = lambda {|other| other == 5} expect(TimesCalledMatcher.create(value)).to eq ProcMatcher.new(value) end end describe "when passed a IntegerMatcher" do it "returns the passed in argument" do matcher = RangeMatcher.new(2..4) expect(TimesCalledMatcher.create(matcher)).to equal matcher end end describe "when passed a Integer" do it "returns RangeMatcher" do expect(TimesCalledMatcher.create(2..4)).to eq RangeMatcher.new(2..4) end end describe "when passed a TimesCalledMatcher" do it "returns the passed in argument" do matcher = TimesCalledMatcher.new(5) expect(TimesCalledMatcher.create(matcher)).to equal matcher end end describe "when passed an unsupported type" do it "raises an ArgumentError" do matcher = Object.new expect { TimesCalledMatcher.create(matcher) }.to raise_error(ArgumentError, "There is no TimesCalledMatcher for #{matcher.inspect}.") end end end describe "#error_message" do before do @times = 3 @matcher = TimesCalledMatcher.new(@times) end it "has an error message" do expect(@matcher.error_message(5)).to eq \ "Called 5 times.\nExpected 3 times." end end describe "#==" do before do @times = 3 @matcher = TimesCalledMatcher.new(@times) end it "returns true when other is the same class and times are ==" do expect(@matcher).to eq TimesCalledMatcher.new(@times) end it "returns false when other is a different class and times are ==" do expect(@matcher).to_not eq IntegerMatcher.new(@times) end it "returns false when is the same class and times are not ==" do expect(@matcher).to_not eq TimesCalledMatcher.new(1) end end end end end rr-3.1.0/spec/suites/rspec_2/unit/times_called_matchers/proc_matcher_spec.rb0000644000004100000410000000263714265140426027304 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper") module RR module TimesCalledMatchers describe ProcMatcher do attr_reader :matcher, :times before do @times = lambda {|other| other == 3} @matcher = ProcMatcher.new(times) end describe "#possible_match?" do it "always returns true" do expect(matcher).to be_possible_match(2) expect(matcher).to be_possible_match(3) expect(matcher).to be_possible_match(10) end end describe "#matches?" do it "returns false when lambda returns false" do expect(times.call(2)).to be_false matcher.should_not be_matches(2) end it "returns true when lambda returns true" do expect(times.call(3)).to be_true expect(matcher).to be_matches(3) end end describe "#attempt?" do it "always returns true" do expect(matcher).to be_attempt(2) expect(matcher).to be_attempt(3) expect(matcher).to be_attempt(10) end end describe "#terminal?" do it "returns false" do matcher.should_not be_terminal end end describe "#error_message" do it "has an error message" do expect(matcher.error_message(1)).to match(/Called 1 time.\nExpected # times./) end end end end end rr-3.1.0/spec/suites/rspec_2/unit/times_called_matchers/integer_matcher_spec.rb0000644000004100000410000000336614265140426027776 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper") module RR module TimesCalledMatchers describe IntegerMatcher do attr_reader :matcher, :times before do @times = 3 @matcher = IntegerMatcher.new(times) end describe "#possible_match?" do it "returns true when times called < times" do expect(matcher).to be_possible_match(2) end it "returns true when times called == times" do expect(matcher).to be_possible_match(3) end it "returns false when times called > times" do matcher.should_not be_possible_match(4) end end describe "#matches?" do it "returns false when times_called less than times" do matcher.should_not be_matches(2) end it "returns true when times_called == times" do expect(matcher).to be_matches(3) end it "returns false when times_called > times" do matcher.should_not be_matches(4) end end describe "#attempt?" do it "returns true when less than expected times" do expect(matcher).to be_attempt(2) end it "returns false when == expected times" do matcher.should_not be_attempt(3) end it "returns false when > expected times" do matcher.should_not be_attempt(4) end end describe AnyTimesMatcher, "#terminal?" do it "returns true" do expect(matcher).to be_terminal end end describe "#error_message" do it "has an error message" do expect(matcher.error_message(2)).to eq \ "Called 2 times.\nExpected 3 times." end end end end end rr-3.1.0/spec/suites/rspec_2/unit/times_called_matchers/at_most_matcher_spec.rb0000644000004100000410000000331514265140426030001 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper") module RR module TimesCalledMatchers describe AtMostMatcher do attr_reader :matcher, :times before do @times = 3 @matcher = AtMostMatcher.new(times) end describe AtMostMatcher, "#possible_match?" do it "returns true when times called < times" do expect(matcher).to be_possible_match(2) end it "returns true when times called == times" do expect(matcher).to be_possible_match(3) end it "returns false when times called > times" do matcher.should_not be_possible_match(4) end end describe AtMostMatcher, "#matches?" do it "returns true when times_called less than times" do expect(matcher).to be_matches(2) end it "returns true when times_called == times" do expect(matcher).to be_matches(3) end it "returns false when times_called > times" do matcher.should_not be_matches(4) end end describe AtMostMatcher, "#attempt?" do it "returns true when less than expected times" do expect(matcher).to be_attempt(2) end it "returns false when == expected times" do matcher.should_not be_attempt(3) end it "returns false when > expected times" do matcher.should_not be_attempt(4) end end describe AnyTimesMatcher, "#terminal?" do it "returns true" do expect(matcher).to be_terminal end end describe AtMostMatcher, "#error_message" do it "has an error message" do expect(matcher.error_message(5)).to eq \ "Called 5 times.\nExpected at most 3 times." end end end end end rr-3.1.0/spec/suites/rspec_2/unit/times_called_matchers/range_matcher_spec.rb0000644000004100000410000000401214265140426027422 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper") module RR module TimesCalledMatchers describe RangeMatcher do attr_reader :matcher, :times before do @times = 2..4 @matcher = RangeMatcher.new(times) end describe "#possible_match?" do it "returns true when times called < start of range" do expect(matcher).to be_possible_match(1) end it "returns true when times called in range" do expect(matcher).to be_possible_match(2) expect(matcher).to be_possible_match(3) expect(matcher).to be_possible_match(4) end it "returns false when times called > end of range" do matcher.should_not be_possible_match(5) end end describe "#matches?" do it "returns false when times_called less than start of range" do matcher.should_not be_matches(1) end it "returns true when times_called in range" do expect(matcher).to be_matches(2) expect(matcher).to be_matches(3) expect(matcher).to be_matches(4) end it "returns false when times_called > end of range" do matcher.should_not be_matches(5) end end describe "#attempt?" do it "returns true when less than start of range" do expect(matcher).to be_attempt(1) end it "returns true when in range" do expect(matcher).to be_attempt(2) expect(matcher).to be_attempt(3) expect(matcher).to be_attempt(4) end it "returns false when > end of range" do matcher.should_not be_attempt(5) end end describe "#terminal?" do it "returns true" do expect(matcher).to be_terminal end end describe "#error_message" do it "has an error message" do expect(matcher.error_message(1)).to eq \ "Called 1 time.\nExpected 2..4 times." end end end end end rr-3.1.0/spec/suites/rspec_2/unit/times_called_matchers/any_times_matcher_spec.rb0000644000004100000410000000231514265140426030322 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper") module RR module TimesCalledMatchers describe AnyTimesMatcher do attr_reader :matcher before do @matcher = AnyTimesMatcher.new end describe AnyTimesMatcher, "#possible_match?" do it "always returns true" do expect(matcher).to be_possible_match(0) expect(matcher).to be_possible_match(99999) end end describe AnyTimesMatcher, "#matches?" do it "always returns true" do expect(matcher).to be_matches(0) expect(matcher).to be_matches(99999) end end describe AnyTimesMatcher, "#attempt?" do it "always returns true" do expect(matcher).to be_attempt(0) expect(matcher).to be_attempt(99999) end end describe AnyTimesMatcher, "#terminal?" do it "returns false" do matcher.should_not be_terminal end end describe AnyTimesMatcher, "#error_message" do it "has an error message" do expect(matcher.error_message(2)).to eq \ "Called 2 times.\nExpected any number of times." end end end end end rr-3.1.0/spec/suites/rspec_2/unit/space_spec.rb0000644000004100000410000005446214265140426021421 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../spec_helper") module RR describe Space do include_examples "Swapped Space" attr_reader :method_name, :double_injection subject { Object.new } describe "#record_call" do it "should add a call to the list" do object = Object.new method_name = :to_s arguments = [] keyword_arguments = {} space.record_call(object, method_name, arguments, keyword_arguments, lambda {}) expect(space.recorded_calls[0]).to eq \ RR::RecordedCall.new(object, method_name, arguments, keyword_arguments, lambda {}) end end describe "#double_injection" do context "when existing subject == but not === with the same method name" do it "creates a new DoubleInjection" do subject_1 = [] subject_2 = [] expect((subject_1 === subject_2)).to be_true expect(subject_1.__id__).to_not eq subject_2.__id__ injection_1 = Injections::DoubleInjection.find_or_create_by_subject(subject_1, :foobar) injection_2 = Injections::DoubleInjection.find_or_create_by_subject(subject_2, :foobar) expect(injection_1).to_not eq injection_2 end end context "when a DoubleInjection is not registered for the subject and method_name" do before do def subject.foobar(*args) :original_foobar end @method_name = :foobar end context "when method_name is a symbol" do it "returns double_injection and adds double_injection to double_injection list" do double_injection = Injections::DoubleInjection.find_or_create_by_subject(subject, method_name) expect(Injections::DoubleInjection.find_or_create_by_subject(subject, method_name)).to equal double_injection expect(double_injection.subject_class).to eq(class << subject; self; end) expect(double_injection.method_name).to equal method_name end end context "when method_name is a string" do it "returns double_injection and adds double_injection to double_injection list" do double_injection = Injections::DoubleInjection.find_or_create_by_subject(subject, 'foobar') expect(Injections::DoubleInjection.find_or_create_by_subject(subject, method_name)).to equal double_injection expect(double_injection.subject_class).to eq(class << subject; self; end) expect(double_injection.method_name).to equal method_name end end it "overrides the method when passing a block" do original_method = subject.method(:foobar) Injections::DoubleInjection.find_or_create_by_subject(subject, method_name) expect(subject.method(:foobar)).to_not eq original_method end end context "when double_injection exists" do before do def subject.foobar(*args) :original_foobar end @method_name = :foobar end context "when a DoubleInjection is registered for the subject and method_name" do it "returns the existing DoubleInjection" do @double_injection = Injections::DoubleInjection.find_or_create_by_subject(subject, 'foobar') expect(double_injection.subject_has_original_method?).to be_true expect(Injections::DoubleInjection.find_or_create_by_subject(subject, 'foobar')).to equal double_injection double_injection.reset expect(subject.foobar).to eq :original_foobar end end end end describe "#method_missing_injection" do context "when existing subject == but not === with the same method name" do it "creates a new DoubleInjection" do subject_1 = [] subject_2 = [] expect((subject_1 === subject_2)).to be_true expect(subject_1.__id__).to_not eq subject_2.__id__ injection_1 = Injections::MethodMissingInjection.find_or_create(class << subject_1; self; end) injection_2 = Injections::MethodMissingInjection.find_or_create(class << subject_2; self; end) expect(injection_1).to_not eq injection_2 end end context "when a MethodMissingInjection is not registered for the subject and method_name" do before do def subject.method_missing(method_name, *args, &block) :original_method_missing end end it "overrides the method when passing a block" do original_method = subject.method(:method_missing) Injections::MethodMissingInjection.find_or_create(class << subject; self; end) expect(subject.method(:method_missing)).to_not eq original_method end end context "when a MethodMissingInjection is registered for the subject and method_name" do before do def subject.method_missing(method_name, *args, &block) :original_method_missing end end context "when a DoubleInjection is registered for the subject and method_name" do it "returns the existing DoubleInjection" do injection = Injections::MethodMissingInjection.find_or_create(class << subject; self; end) expect(injection.subject_has_original_method?).to be_true expect(Injections::MethodMissingInjection.find_or_create(class << subject; self; end)).to equal injection injection.reset expect(subject.method_missing(:foobar)).to eq :original_method_missing end end end end describe "#singleton_method_added_injection" do context "when existing subject == but not === with the same method name" do it "creates a new DoubleInjection" do subject_1 = [] subject_2 = [] expect((subject_1 === subject_2)).to be_true expect(subject_1.__id__).to_not eq subject_2.__id__ injection_1 = Injections::SingletonMethodAddedInjection.find_or_create(class << subject_1; self; end) injection_2 = Injections::SingletonMethodAddedInjection.find_or_create(class << subject_2; self; end) expect(injection_1).to_not eq injection_2 end end context "when a SingletonMethodAddedInjection is not registered for the subject and method_name" do before do def subject.singleton_method_added(method_name) :original_singleton_method_added end end it "overrides the method when passing a block" do original_method = subject.method(:singleton_method_added) Injections::SingletonMethodAddedInjection.find_or_create(class << subject; self; end) expect(subject.method(:singleton_method_added)).to_not eq original_method end end context "when a SingletonMethodAddedInjection is registered for the subject and method_name" do before do def subject.singleton_method_added(method_name) :original_singleton_method_added end end context "when a DoubleInjection is registered for the subject and method_name" do it "returns the existing DoubleInjection" do injection = Injections::SingletonMethodAddedInjection.find_or_create(class << subject; self; end) expect(injection.subject_has_original_method?).to be_true expect(Injections::SingletonMethodAddedInjection.find_or_create(class << subject; self; end)).to equal injection injection.reset expect(subject.singleton_method_added(:foobar)).to eq :original_singleton_method_added end end end end describe "#reset" do attr_reader :subject_1, :subject_2 before do @subject_1 = Object.new @subject_2 = Object.new @method_name = :foobar end it "should clear the #recorded_calls" do object = Object.new space.record_call(object, :to_s, [], {}, nil) space.reset expect(space.recorded_calls).to eq RR::RecordedCalls.new([]) end it "removes the ordered doubles" do mock(subject_1).foobar1.ordered mock(subject_2).foobar2.ordered space.ordered_doubles.should_not be_empty space.reset expect(space.ordered_doubles).to be_empty end it "resets all double_injections" do expect(subject_1.respond_to?(method_name)).to be_false expect(subject_2.respond_to?(method_name)).to be_false Injections::DoubleInjection.find_or_create_by_subject(subject_1, method_name) expect(Injections::DoubleInjection.exists_by_subject?(subject_1, method_name)).to be_true expect(subject_1.respond_to?(method_name)).to be_true Injections::DoubleInjection.find_or_create_by_subject(subject_2, method_name) expect(Injections::DoubleInjection.exists_by_subject?(subject_2, method_name)).to be_true expect(subject_2.respond_to?(method_name)).to be_true space.reset expect(subject_1.respond_to?(method_name)).to be_false expect(Injections::DoubleInjection.exists?(subject_1, method_name)).to be_false expect(subject_2.respond_to?(method_name)).to be_false expect(Injections::DoubleInjection.exists?(subject_2, method_name)).to be_false end it "resets all method_missing_injections" do expect(subject_1.respond_to?(:method_missing)).to be_false expect(subject_2.respond_to?(:method_missing)).to be_false Injections::MethodMissingInjection.find_or_create(class << subject_1; self; end) expect(Injections::MethodMissingInjection.exists?(class << subject_1; self; end)).to be_true expect(subject_1.respond_to?(:method_missing)).to be_true Injections::MethodMissingInjection.find_or_create(class << subject_2; self; end) expect(Injections::MethodMissingInjection.exists?(class << subject_2; self; end)).to be_true expect(subject_2.respond_to?(:method_missing)).to be_true space.reset expect(subject_1.respond_to?(:method_missing)).to be_false expect(Injections::MethodMissingInjection.exists?(subject_1)).to be_false expect(subject_2.respond_to?(:method_missing)).to be_false expect(Injections::MethodMissingInjection.exists?(subject_2)).to be_false end it "resets all singleton_method_added_injections" do expect(subject_1.respond_to?(:singleton_method_added)).to be_false expect(subject_2.respond_to?(:singleton_method_added)).to be_false Injections::SingletonMethodAddedInjection.find_or_create(class << subject_1; self; end) expect(Injections::SingletonMethodAddedInjection.exists?(class << subject_1; self; end)).to be_true expect(subject_1.respond_to?(:singleton_method_added)).to be_true Injections::SingletonMethodAddedInjection.find_or_create(class << subject_2; self; end) expect(Injections::SingletonMethodAddedInjection.exists?(class << subject_2; self; end)).to be_true expect(subject_2.respond_to?(:singleton_method_added)).to be_true space.reset expect(subject_1.respond_to?(:singleton_method_added)).to be_false expect(Injections::SingletonMethodAddedInjection.exists?(subject_1)).to be_false expect(subject_2.respond_to?(:singleton_method_added)).to be_false expect(Injections::SingletonMethodAddedInjection.exists?(subject_2)).to be_false end it "clears RR::Injections::DoubleInjection::BoundObjects" do stub(subject).foobar RR::Injections::DoubleInjection::BoundObjects.should_not be_empty space.reset pending "Clearing BoundObjects" do expect(RR::Injections::DoubleInjection::BoundObjects).to be_empty end end end describe "#reset_double" do before do @method_name = :foobar def subject.foobar end end it "resets the double_injections and restores the original method" do original_method = subject.method(method_name) @double_injection = Injections::DoubleInjection.find_or_create_by_subject(subject, method_name) expect(Injections::DoubleInjection.instances.keys).to include(class << subject; self; end) Injections::DoubleInjection.find_by_subject(subject, method_name).should_not be_nil expect(subject.method(method_name)).to_not eq original_method space.reset_double(subject, method_name) Injections::DoubleInjection.instances.keys.should_not include(subject) expect(subject.method(method_name)).to eq original_method end context "when it has no double_injections" do it "removes the subject from the double_injections map" do Injections::DoubleInjection.find_or_create_by_subject(subject, :foobar1) Injections::DoubleInjection.find_or_create_by_subject(subject, :foobar2) expect(Injections::DoubleInjection.instances.include?(class << subject; self; end)).to eq true Injections::DoubleInjection.find_by_subject(subject, :foobar1).should_not be_nil Injections::DoubleInjection.find_by_subject(subject, :foobar2).should_not be_nil space.reset_double(subject, :foobar1) expect(Injections::DoubleInjection.instances.include?(class << subject; self; end)).to eq true expect(Injections::DoubleInjection.find_by_subject(subject, :foobar1)).to be_nil Injections::DoubleInjection.find_by_subject(subject, :foobar2).should_not be_nil space.reset_double(subject, :foobar2) expect(Injections::DoubleInjection.instances.include?(subject)).to eq false end end end describe "#DoubleInjection.reset" do attr_reader :subject_1, :subject_2 before do @subject_1 = Object.new @subject_2 = Object.new @method_name = :foobar end it "resets the double_injection and removes it from the double_injections list" do double_injection_1 = Injections::DoubleInjection.find_or_create_by_subject(subject_1, method_name) double_1_reset_call_count = 0 ( class << double_injection_1; self; end).class_eval do define_method(:reset) do double_1_reset_call_count += 1 end end double_injection_2 = Injections::DoubleInjection.find_or_create_by_subject(subject_2, method_name) double_2_reset_call_count = 0 ( class << double_injection_2; self; end).class_eval do define_method(:reset) do double_2_reset_call_count += 1 end end Injections::DoubleInjection.reset expect(double_1_reset_call_count).to eq 1 expect(double_2_reset_call_count).to eq 1 end end describe "#verify_doubles" do attr_reader :subject_1, :subject_2, :subject3, :double_1, :double_2, :double3 before do @subject_1 = Object.new @subject_2 = Object.new @subject3 = Object.new @method_name = :foobar @double_1 = Injections::DoubleInjection.find_or_create_by_subject(subject_1, method_name) @double_2 = Injections::DoubleInjection.find_or_create_by_subject(subject_2, method_name) @double3 = Injections::DoubleInjection.find_or_create_by_subject(subject3, method_name) end context "when passed no arguments" do it "verifies and deletes the double_injections" do double_1_verify_call_count = 0 double_1_reset_call_count = 0 ( class << double_1; self; end).class_eval do define_method(:verify) do double_1_verify_call_count += 1 end define_method(:reset) do double_1_reset_call_count += 1 end end double_2_verify_call_count = 0 double_2_reset_call_count = 0 ( class << double_2; self; end).class_eval do define_method(:verify) do double_2_verify_call_count += 1 end define_method(:reset) do double_2_reset_call_count += 1 end end space.verify_doubles expect(double_1_verify_call_count).to eq 1 expect(double_2_verify_call_count).to eq 1 expect(double_1_reset_call_count).to eq 1 expect(double_1_reset_call_count).to eq 1 end end context "when passed an Object that has at least one DoubleInjection" do it "verifies all Doubles injected into the Object" do double_1_verify_call_count = 0 double_1_reset_call_count = 0 ( class << double_1; self; end).class_eval do define_method(:verify) do double_1_verify_call_count += 1 end define_method(:reset) do double_1_reset_call_count += 1 end end double_2_verify_call_count = 0 double_2_reset_call_count = 0 ( class << double_2; self; end).class_eval do define_method(:verify) do double_2_verify_call_count += 1 end define_method(:reset) do double_2_reset_call_count += 1 end end space.verify_doubles(subject_1) expect(double_1_verify_call_count).to eq 1 expect(double_1_reset_call_count).to eq 1 expect(double_2_verify_call_count).to eq 0 expect(double_2_reset_call_count).to eq 0 end end context "when passed multiple Objects with at least one DoubleInjection" do it "verifies the Doubles injected into all of the Objects" do double_1_verify_call_count = 0 double_1_reset_call_count = 0 ( class << double_1; self; end).class_eval do define_method(:verify) do double_1_verify_call_count += 1 end define_method(:reset) do double_1_reset_call_count += 1 end end double_2_verify_call_count = 0 double_2_reset_call_count = 0 ( class << double_2; self; end).class_eval do define_method(:verify) do double_2_verify_call_count += 1 end define_method(:reset) do double_2_reset_call_count += 1 end end double3_verify_call_count = 0 double3_reset_call_count = 0 ( class << double3; self; end).class_eval do define_method(:verify) do double3_verify_call_count += 1 end define_method(:reset) do double3_reset_call_count += 1 end end space.verify_doubles(subject_1, subject_2) expect(double_1_verify_call_count).to eq 1 expect(double_1_reset_call_count).to eq 1 expect(double_2_verify_call_count).to eq 1 expect(double_2_reset_call_count).to eq 1 expect(double3_verify_call_count).to eq 0 expect(double3_reset_call_count).to eq 0 end end context "when passed an subject that does not have a DoubleInjection" do it "does not raise an error" do double_1_verify_call_count = 0 double_1_reset_call_count = 0 ( class << double_1; self; end).class_eval do define_method(:verify) do double_1_verify_call_count += 1 end define_method(:reset) do double_1_reset_call_count += 1 end end double_2_verify_call_count = 0 double_2_reset_call_count = 0 ( class << double_2; self; end).class_eval do define_method(:verify) do double_2_verify_call_count += 1 end define_method(:reset) do double_2_reset_call_count += 1 end end double3_verify_call_count = 0 double3_reset_call_count = 0 ( class << double3; self; end).class_eval do define_method(:verify) do double3_verify_call_count += 1 end define_method(:reset) do double3_reset_call_count += 1 end end no_double_injection_object = Object.new space.verify_doubles(no_double_injection_object) expect(double_1_verify_call_count).to eq 0 expect(double_1_reset_call_count).to eq 0 expect(double_2_verify_call_count).to eq 0 expect(double_2_reset_call_count).to eq 0 expect(double3_verify_call_count).to eq 0 expect(double3_reset_call_count).to eq 0 end end end describe "#verify_double" do before do @method_name = :foobar def subject.foobar end end it "verifies and deletes the double_injection" do @double_injection = Injections::DoubleInjection.find_or_create_by_subject(subject, method_name) expect(Injections::DoubleInjection.find_by_subject(subject, method_name)).to equal double_injection verify_call_count = 0 ( class << double_injection; self; end).class_eval do define_method(:verify) do verify_call_count += 1 end end space.verify_double(subject, method_name) expect(verify_call_count).to eq 1 expect(Injections::DoubleInjection.find(subject, method_name)).to be_nil end context "when verifying the double_injection raises an error" do it "deletes the double_injection and restores the original method" do original_method = subject.method(method_name) @double_injection = Injections::DoubleInjection.find_or_create_by_subject(subject, method_name) expect(subject.method(method_name)).to_not eq original_method expect(Injections::DoubleInjection.find_by_subject(subject, method_name)).to equal double_injection verify_called = true ( class << double_injection; self; end).class_eval do define_method(:verify) do verify_called = true raise "An Error" end end expect { space.verify_double(subject, method_name) }.to raise_error expect(verify_called).to be_true expect(Injections::DoubleInjection.find(subject, method_name)).to be_nil expect(subject.method(method_name)).to eq original_method end end end end end rr-3.1.0/spec/suites/rspec_2/unit/deprecations_spec.rb0000644000004100000410000000141414265140426022773 0ustar www-datawww-datarequire File.expand_path('../../spec_helper', __FILE__) describe 'Deprecations' do before do stub(RR::Deprecations).show_warning end specify 'RR::Adapters::MiniTest still works' do expect { RR::Adapters::MiniTest }.not_to raise_error end specify 'RR::Adapters::TestUnit still works' do expect { RR::Adapters::TestUnit }.not_to raise_error end specify 'RR::Adapters::Rspec::InvocationMatcher still works' do expect { RR::Adapters::Rspec::InvocationMatcher }.not_to raise_error end specify 'RR::Adapters::RRMethods should still work' do expect { RR::Adapters::RRMethods }.not_to raise_error end specify 'RR::Extensions::InstanceMethods should still work' do expect { RR::Extensions::InstanceMethods }.not_to raise_error end end rr-3.1.0/spec/suites/rspec_2/unit/expectations/0000755000004100000410000000000014265140426021462 5ustar www-datawww-datarr-3.1.0/spec/suites/rspec_2/unit/expectations/times_called_expectation/0000755000004100000410000000000014265140426026512 5ustar www-datawww-datarr-3.1.0/spec/suites/rspec_2/unit/expectations/times_called_expectation/at_least_matcher_spec.rb0000644000004100000410000000170014265140426033346 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../../spec_helper") module RR module Expectations describe TimesCalledExpectation do context "when using an AtLeastMatcher" do include_examples "RR::Expectations::TimesCalledExpectation" before do mock(subject).foobar.at_least(3) end describe "#verify!" do it "passes when times called > times" do 4.times {subject.foobar} RR.verify end it "passes when times called == times" do 3.times {subject.foobar} RR.verify end it "raises error when times called < times" do subject.foobar expect { RR.verify }.to raise_error( RR::Errors::TimesCalledError, "foobar()\nCalled 1 time.\nExpected at least 3 times." ) end end end end end end rr-3.1.0/spec/suites/rspec_2/unit/expectations/times_called_expectation/proc_matcher_spec.rb0000644000004100000410000000171514265140426032523 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../../spec_helper") module RR module Expectations describe TimesCalledExpectation do context "when using a ProcMatcher" do include_examples "RR::Expectations::TimesCalledExpectation" before do stub(subject).foobar.times(lambda {|value| value == 2}) end describe "#verify" do it "passes after attempt! called 2 times" do subject.foobar subject.foobar RR.verify end it "fails after attempt! called 1 time" do subject.foobar expect { RR.verify }.to raise_error(RR::Errors::TimesCalledError) end it "fails after attempt! called 3 times" do subject.foobar subject.foobar subject.foobar expect { RR.verify }.to raise_error(RR::Errors::TimesCalledError) end end end end end end rr-3.1.0/spec/suites/rspec_2/unit/expectations/times_called_expectation/integer_matcher_spec.rb0000644000004100000410000000351314265140426033213 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../../spec_helper") module RR module Expectations describe TimesCalledExpectation do context "when using an IntegerMatcher" do include_examples "RR::Expectations::TimesCalledExpectation" before do stub(subject).foobar.times(2) end describe "verify" do it "passes after attempt! called 2 times" do subject.foobar subject.foobar RR.verify end it "fails after attempt! called 1 time" do subject.foobar expect { RR.verify }.to raise_error( RR::Errors::TimesCalledError, "foobar()\nCalled 1 time.\nExpected 2 times." ) end it "can't be called when attempt! is called 3 times" do subject.foobar subject.foobar expect { subject.foobar }.to raise_error(RR::Errors::TimesCalledError, "foobar()\nCalled 3 times.\nExpected 2 times.") expect { RR.verify }.to raise_error(RR::Errors::TimesCalledError, "foobar()\nCalled 3 times.\nExpected 2 times.") end it "has a backtrace to where the TimesCalledExpectation was instantiated on failure" do error = nil begin RR.verify rescue RR::Errors::TimesCalledError => e error = e end expect(e.backtrace.join("\n")).to include(__FILE__) end it "has an error message that includes the number of times called and expected number of times" do expect { RR.verify }.to raise_error(RR::Errors::TimesCalledError, "foobar()\nCalled 0 times.\nExpected 2 times.") end end end end end end rr-3.1.0/spec/suites/rspec_2/unit/expectations/times_called_expectation/at_most_matcher_spec.rb0000644000004100000410000000217514265140426033227 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../../spec_helper") module RR module Expectations describe TimesCalledExpectation do context "when using an AtMostMatcher" do include_examples "RR::Expectations::TimesCalledExpectation" before do stub(subject).foobar.at_most(3) end describe "#verify!" do it "passes when times called == times" do 3.times {subject.foobar} RR.verify end it "passes when times called < times" do 2.times {subject.foobar} RR.verify end it "raises error when times called > times" do expect { 4.times {subject.foobar} }.to raise_error( RR::Errors::TimesCalledError, "foobar()\nCalled 4 times.\nExpected at most 3 times." ) expect { RR.verify }.to raise_error( RR::Errors::TimesCalledError, "foobar()\nCalled 4 times.\nExpected at most 3 times." ) end end end end end end rr-3.1.0/spec/suites/rspec_2/unit/expectations/times_called_expectation/range_matcher_spec.rb0000644000004100000410000000213614265140426032652 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../../spec_helper") module RR module Expectations describe TimesCalledExpectation do context "when using a RangeMatcher" do include_examples "RR::Expectations::TimesCalledExpectation" before do stub(subject).foobar.times(1..2) end describe "#verify" do it "passes after attempt! called 1 time" do subject.foobar RR.verify end it "passes after attempt! called 2 times" do subject.foobar subject.foobar RR.verify end it "can't be called when attempt! is called 3 times" do subject.foobar subject.foobar expect { subject.foobar }.to raise_error(RR::Errors::TimesCalledError, "foobar()\nCalled 3 times.\nExpected 1..2 times.") expect { RR.verify }.to raise_error(RR::Errors::TimesCalledError, "foobar()\nCalled 3 times.\nExpected 1..2 times.") end end end end end end rr-3.1.0/spec/suites/rspec_2/unit/expectations/times_called_expectation/any_times_matcher_spec.rb0000644000004100000410000000107314265140426033545 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../../spec_helper") module RR module Expectations describe TimesCalledExpectation do context "when using an AnyTimesMatcher" do include_examples "RR::Expectations::TimesCalledExpectation" describe "#verify!" do it "always passes" do stub(subject).foobar.any_number_of_times RR.verify stub(subject).foobar.any_number_of_times 10.times {subject.foobar} RR.verify end end end end end end rr-3.1.0/spec/suites/rspec_2/unit/expectations/hash_including_argument_equality_expectation_spec.rb0000644000004100000410000000720214265140426034223 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper") module RR module Expectations describe ArgumentEqualityExpectation, "with HashIncluding argument" do attr_reader :expectation, :expected_hash before do @expected_hash = {:texas => "Austin", :maine => "Augusta"} end describe "#exact_match?" do before do @expectation = ArgumentEqualityExpectation.new([hash_including(expected_hash)], {}) end it "returns true when passed in a HashIncluding matcher with the same hash" do expect(expectation).to be_exact_match([RR::WildcardMatchers::HashIncluding.new(expected_hash)], {}) end it "returns false when passed in a HashIncluding matcher with a different argument list" do expectation.should_not be_exact_match([RR::WildcardMatchers::HashIncluding.new(:foo => 1)], {}) end it "returns false otherwise" do expectation.should_not be_exact_match(["hello"], {}) expectation.should_not be_exact_match([:hello], {}) expectation.should_not be_exact_match([1], {}) expectation.should_not be_exact_match([nil], {}) expectation.should_not be_exact_match([true], {}) expectation.should_not be_exact_match([], {}) end end describe "#wildcard_match?" do before do @expectation = ArgumentEqualityExpectation.new([hash_including(expected_hash)], {}) end it "returns true when hash contains same key/values as the expectation" do expect(expectation).to be_wildcard_match([expected_hash], {}) end it "returns true when hash contains at least expectation's key/values" do expect(expectation).to be_wildcard_match([expected_hash.merge(:oregon => "Salem")], {}) end it "returns true when passed the same hash, even after the original is modified" do original_expected_hash = expected_hash.clone expected_hash[:texas] = nil expect(expectation).to be_wildcard_match([original_expected_hash], {}) end it "returns true even if one of the expectation's values is nil" do expectation = ArgumentEqualityExpectation.new([hash_including(:foo => nil)], {}) expect(expectation).to be_wildcard_match([{:foo => nil}], {}) end it "returns false when hash matches only some required key/values" do expectation.should_not be_wildcard_match([{:texas => "Austin"}], {}) end it "returns false when hash matches all the keys but not all the values" do expectation.should_not be_wildcard_match([{:texas => "Austin", :maine => "Portland"}], {}) end it "returns false when passed a hash that matches all values but not all keys" do expectation.should_not be_wildcard_match([{:texas => "Austin", :georgia => "Augusta"}], {}) end it "returns true when an exact match" do expect(expectation).to be_wildcard_match([hash_including(expected_hash)], {}) end it "returns false when not passed correct number of arguments" do expectation.should_not be_wildcard_match([], {}) expectation.should_not be_wildcard_match([:a, :b], {}) end end end end end rr-3.1.0/spec/suites/rspec_2/unit/expectations/satisfy_argument_equality_expectation_spec.rb0000644000004100000410000000405114265140426032725 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper") =begin module RR module Expectations describe ArgumentEqualityExpectation, "with Satisfy argument" do attr_reader :expectation, :expectation_proc, :expected_value, :satisfy_matcher before do @expected_value = :foo @expectation_proc = lambda {|argument| puts 'called'; argument == expected_value} @satisfy_matcher = satisfy(&expectation_proc) @expectation = ArgumentEqualityExpectation.new(satisfy_matcher) end describe "#exact_match?" do before do end it "returns true when passed a Satisfy matcher with the same proc" do expect(expectation).to be_exact_match(RR::WildcardMatchers::Satisfy.new(expectation_proc)) end it "returns false when passed a Satisfy matcher with another proc" do expectation.should_not be_exact_match(RR::WildcardMatchers::Satisfy.new(lambda {})) end it "returns false otherwise" do expectation.should_not be_exact_match("hello") expectation.should_not be_exact_match(:hello) expectation.should_not be_exact_match(1) expectation.should_not be_exact_match(nil) expectation.should_not be_exact_match(true) expectation.should_not be_exact_match() end end describe "#wildcard_match?" do it "returns true when the proc returns a truthy value" do expect((!!expectation_proc.call(expected_value))).to be_true expect(expectation).to be_wildcard_match(expected_value) end it "returns false when the proc returns a falsey value" do expect((!!expectation_proc.call(:bar))).to be_false expectation.should_not be_wildcard_match(:bar) end it "returns true when an exact match" do expect(expectation).to be_wildcard_match(satisfy_matcher) end it "returns false when not passed correct number of arguments" do expectation.should_not be_wildcard_match() expectation.should_not be_wildcard_match(:a, :b) end end end end end =end rr-3.1.0/spec/suites/rspec_2/unit/expectations/boolean_argument_equality_expectation_spec.rb0000644000004100000410000000151114265140426032660 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper") module RR module Expectations describe ArgumentEqualityExpectation do context "with a boolean matcher" do attr_reader :expectation before do @expectation = ArgumentEqualityExpectation.new([boolean], {}) end describe "#wildcard_match?" do context "when passed a Boolean" do it "returns true" do expect(expectation).to be_wildcard_match([true], {}) expect(expectation).to be_wildcard_match([false], {}) end end context "when not passed a Boolean" do it "returns false" do expectation.should_not be_wildcard_match([:not_a_boolean], {}) end end end end end end end rr-3.1.0/spec/suites/rspec_2/unit/expectations/argument_equality_expectation_spec.rb0000644000004100000410000001165514265140426031173 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper") module RR module Expectations describe ArgumentEqualityExpectation do attr_reader :expectation before do @expectation = ArgumentEqualityExpectation.new([1, 2, 3], {}) end describe "#expected_arguments" do it "returns the passed in expected_arguments" do expect(expectation.expected_arguments).to eq [1, 2, 3] end end describe "==" do it "returns true when passed in expected_arguments are equal" do expect(expectation).to eq ArgumentEqualityExpectation.new([1, 2, 3], {}) end it "returns false when passed in expected_arguments are not equal" do expect(expectation).to_not eq ArgumentEqualityExpectation.new([1, 2], {}) expect(expectation).to_not eq ArgumentEqualityExpectation.new([1], {}) expect(expectation).to_not eq ArgumentEqualityExpectation.new([:something], {}) expect(expectation).to_not eq ArgumentEqualityExpectation.new([], {}) end end describe "#exact_match?" do context "when all arguments exactly match" do it "returns true" do expect(expectation).to be_exact_match([1, 2, 3], {}) end end context "when all arguments do not exactly match" do it "returns false" do expectation.should_not be_exact_match([1, 2], {}) expectation.should_not be_exact_match([1], {}) expectation.should_not be_exact_match([], {}) expectation.should_not be_exact_match(["does not match"], {}) end end end describe "#wildcard_match?" do context "when not an exact match" do it "returns false" do expectation = ArgumentEqualityExpectation.new([1], {}) expectation.should_not be_wildcard_match([1, 2, 3], {}) expectation.should_not be_wildcard_match(["whatever"], {}) expectation.should_not be_wildcard_match(["whatever", "else"], {}) end end context "when an exact match" do it "returns true" do expectation = ArgumentEqualityExpectation.new([1, 2], {}) expect(expectation).to be_wildcard_match([1, 2], {}) expectation.should_not be_wildcard_match([1], {}) expectation.should_not be_wildcard_match(["whatever", "else"], {}) end end context "when not passed correct number of arguments" do it "returns false" do expectation.should_not be_wildcard_match([], {}) expectation.should_not be_wildcard_match([Object.new, Object.new], {}) end end end describe "Functional spec" do class ArgumentEqualityFunctionalFixture attr_reader :arg1, :arg2 def initialize(arg1, arg2) @arg1, @arg2 = arg1, arg2 end def ==(other) arg1 == (other.arg1) && arg2 == (other.arg2) end def eql?(other) arg1.eql?(other.arg1) && arg2.eql?(other.arg2) end end before(:each) do @predicate1 = 'first' # these should be mocks, waiting on rr bug fix @predicate2 = 'second' @predicate3 = 'third' end describe "when mock.proxy ==" do it "does not have infinite recursion" do mock.proxy(@predicate1) == @predicate1 mock.proxy(@predicate2) == @predicate2 expect(ArgumentEqualityFunctionalFixture.new(@predicate1, @predicate2)).to eq ArgumentEqualityFunctionalFixture.new(@predicate1, @predicate2) mock.proxy(@predicate1) == @predicate1 mock.proxy(@predicate2) == @predicate3 expect(ArgumentEqualityFunctionalFixture.new(@predicate1, @predicate2)).to_not eq ArgumentEqualityFunctionalFixture.new(@predicate1, @predicate3) end it "matches Hashes properly (using ==)" do mock.proxy(@predicate1) == {:foo => :bar} @predicate1 == {:foo => :bar} end end describe "when mock.proxy .eql?" do it "does not have infinite recursion" do mock.proxy(@predicate1).eql? @predicate1 mock.proxy(@predicate2).eql? @predicate2 expect(ArgumentEqualityFunctionalFixture.new(@predicate1, @predicate2)).to be_eql(ArgumentEqualityFunctionalFixture.new(@predicate1, @predicate2)) mock.proxy(@predicate1).eql? @predicate1 mock.proxy(@predicate2).eql? @predicate3 ArgumentEqualityFunctionalFixture.new(@predicate1, @predicate2).should_not be_eql(ArgumentEqualityFunctionalFixture.new(@predicate1, @predicate3)) end it "matches Hashes properly (using ==)" do mock.proxy(@predicate1).eql?({:foo => :bar}) @predicate1.eql?({:foo => :bar}) end end end end end end rr-3.1.0/spec/suites/rspec_2/unit/expectations/anything_argument_equality_expectation_spec.rb0000644000004100000410000000053514265140426033067 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper") module RR module Expectations describe ArgumentEqualityExpectation do context "when matching anything" do attr_reader :expectation before do @expectation = ArgumentEqualityExpectation.new(anything) end end end end end rr-3.1.0/spec/suites/rspec_2/unit/expectations/any_argument_expectation_spec.rb0000644000004100000410000000300214265140426030110 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper") module RR module Expectations describe AnyArgumentExpectation do attr_reader :expectation before do @expectation = AnyArgumentExpectation.new end describe "#expected_arguments" do it "returns an empty array" do expect(expectation.expected_arguments).to eq [] end end describe "==" do it "returns true when comparing with another AnyArgumentExpectation" do expect(expectation).to eq AnyArgumentExpectation.new end it "returns false when comparing with ArgumentEqualityExpectation" do expect(expectation).to_not eq ArgumentEqualityExpectation.new([1], {}) end end describe "#exact_match?" do it "returns false" do expectation.should_not be_exact_match([1, 2, 3], {}) expectation.should_not be_exact_match([1, 2], {}) expectation.should_not be_exact_match([1], {}) expectation.should_not be_exact_match([], {}) expectation.should_not be_exact_match(["does not match"], {}) end end describe "#wildcard_match?" do it "returns true" do expectation = AnyArgumentExpectation.new expect(expectation).to be_wildcard_match([1, 2, 3], {}) expect(expectation).to be_wildcard_match(["whatever"], {}) expect(expectation).to be_wildcard_match(["whatever", "else"], {}) end end end end end rr-3.1.0/spec/suites/rspec_2/unit/hash_with_object_id_key_spec.rb0000644000004100000410000000403114265140426025141 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../spec_helper") module RR describe HashWithObjectIdKey do describe "#[] and #[]=" do it "stores object via object id" do hash = HashWithObjectIdKey.new array_1 = [] hash[array_1] = 1 array_2 = [] hash[array_2] = 2 expect(hash[array_1]).to_not eq hash[array_2] end it "stores the passed in object" do hash = HashWithObjectIdKey.new obj = Object.new hash[obj] = 1 expect(hash.instance_eval {@keys}).to eq({obj.__id__ => obj}) end end describe "#each" do it "iterates through the items in the hash" do hash = HashWithObjectIdKey.new hash['one'] = 1 hash['two'] = 2 keys = [] values = [] hash.each do |key, value| keys << key values << value end expect(keys.sort).to eq ['one', 'two'] expect(values.sort).to eq [1, 2] end end describe "#delete" do before do @hash = HashWithObjectIdKey.new @key = Object.new @hash[@key] = 1 end it "removes the object from the hash" do @hash.delete(@key) expect(@hash[@key]).to be_nil end it "removes the object from the keys hash" do @hash.delete(@key) expect(@hash.instance_eval { @keys }).to eq({}) end end describe "#keys" do before do @hash = HashWithObjectIdKey.new @key = Object.new @hash[@key] = 1 end it "returns an array of the keys" do expect(@hash.keys).to eq [@key] end end describe "#include?" do before do @hash = HashWithObjectIdKey.new @key = Object.new @hash[@key] = 1 end it "returns true when the key is in the Hash" do expect(@hash.include?(@key)).to be_true end it "returns false when the key is not in the Hash" do expect(@hash.include?(Object.new)).to be_false end end end end rr-3.1.0/spec/suites/rspec_2/unit/rr_spec.rb0000644000004100000410000000122214265140426020733 0ustar www-datawww-datarequire File.expand_path("#{File.dirname(__FILE__)}/../spec_helper") describe "RR" do before do Object.class_eval do def verify raise "Dont call me" end end end after do Object.class_eval do remove_method :verify end end it "has proxy methods for each method defined directly on Space" do space_instance_methods = RR::Space.instance_methods(false) space_instance_methods.should_not be_empty rr_instance_methods = RR.methods(false) space_instance_methods.each do |space_instance_method| expect(rr_instance_methods).to include(space_instance_method) end RR.verify end end rr-3.1.0/spec/suites/rspec_2/spec_helper.rb0000644000004100000410000000022114265140426020606 0ustar www-datawww-datarequire File.expand_path('../../../global_helper', __FILE__) RR::Test.setup_test_suite(:rspec_2) require File.expand_path('../helper', __FILE__) rr-3.1.0/spec/suites/rspec_2/functional/0000755000004100000410000000000014265140426020137 5ustar www-datawww-datarr-3.1.0/spec/suites/rspec_2/functional/stub_bang_spec.rb0000644000004100000410000000122314265140426023440 0ustar www-datawww-datarequire File.expand_path('../../spec_helper', __FILE__) describe 'stub!' do it "is a terser way of creating an object and stubbing it" do object = stub!.some_method { 'value' }.subject expect(object.some_method).to eq 'value' end it "can be used inside the implementation block of a double" do object = Object.new stub(object).some_method { stub!.another_method { 'value' } } expect(object.some_method.another_method).to eq 'value' end it "can be called on a double" do object = Object.new stub(object).some_method.stub!.another_method { 'value' } expect(object.some_method.another_method).to eq 'value' end end rr-3.1.0/spec/suites/rspec_2/functional/dont_allow_spec.rb0000644000004100000410000000107314265140426023641 0ustar www-datawww-datarequire File.expand_path('../../spec_helper', __FILE__) describe 'dont_allow', is_mock: true, is_dont_allow: true do include MockDefinitionCreatorHelpers context 'against instance methods', method_type: :instance do include_context 'tests for a double definition creator method that supports dont_allow' end context 'against class methods', method_type: :class do include_context 'tests for a double definition creator method that supports dont_allow' end def double_definition_creator_for(object, &block) dont_allow(object, &block) end end rr-3.1.0/spec/suites/rspec_2/functional/wildcard_matchers_spec.rb0000644000004100000410000000546514265140426025167 0ustar www-datawww-datarequire File.expand_path('../../spec_helper', __FILE__) require 'ostruct' describe 'wildcard matchers' do subject { Object.new } describe '#anything' do it "works outside a container" do mock(subject).foo(anything) subject.foo(:whatever) end it "works within a container too" do mock(subject).foo([anything]) subject.foo([:whatever]) end end describe '#boolean' do it "works outside a container" do mock(subject).foo(boolean) subject.foo(false) end it "works within a container too" do mock(subject).foo([boolean]) subject.foo([false]) end end describe '#duck_type' do it "works outside a container" do mock(subject).foo(duck_type(:bar)) subject.foo(OpenStruct.new(:bar => 3)) end it "works within a container too" do mock(subject).foo([duck_type(:bar)]) subject.foo([OpenStruct.new(:bar => 3)]) end end describe '#hash_including' do it "works outside a container" do mock(subject).foo(hash_including(:c => 'd')) subject.foo(:a => 'b', :c => 'd') end it "works within a container too" do mock(subject).foo([hash_including(:c => 'd')]) subject.foo([{:a => 'b', :c => 'd'}]) end end describe '#is_a' do context 'when outside a container' do it "matches a simple value" do mock(subject).foo(is_a(Symbol)) subject.foo(:symbol) end it "matches a container value" do mock(subject).foo(is_a(Array)) subject.foo(['x', 'y']) end end context 'within a container' do it "matches a simple value" do mock(subject).foo([is_a(Symbol)]) subject.foo([:symbol]) end it "matches a container" do mock(subject).foo([is_a(Hash)]) subject.foo([{:x => 'y'}]) end end end describe '#numeric' do it "works outside a container" do mock(subject).foo(numeric) subject.foo(3) end it "works within a container too" do mock(subject).foo([numeric]) subject.foo([3]) end end describe 'range' do it "works outside a container" do mock(subject).foo(1..5) subject.foo(3) end it "works within a container too" do mock(subject).foo([1..5]) subject.foo([3]) end end describe 'regexp' do it "works outside a container" do mock(subject).foo(/foo/) subject.foo('foobar') end it "works within a container too" do mock(subject).foo([/foo/]) subject.foo(['foobar']) end end describe '#satisfy' do it "works outside a container" do mock(subject).foo(satisfy {|x| x == 'x' }) subject.foo('x') end it "works within a container too" do mock(subject).foo([satisfy {|x| x == 'x' }]) subject.foo(['x']) end end end rr-3.1.0/spec/suites/rspec_2/functional/mock_strong_spec.rb0000644000004100000410000000061614265140426024026 0ustar www-datawww-datarequire File.expand_path('../../spec_helper', __FILE__) permutations = %w(mock strong).permutation.map { |parts| parts.join('.') } permutations.each do |permutation| describe permutation, is_mock: true, is_strong: true do include_context 'mock + strong' define_method(:double_definition_creator_for) do |object, &block| eval(permutation + '(object, &block)') end end end rr-3.1.0/spec/suites/rspec_2/functional/mock_bang_spec.rb0000644000004100000410000000122214265140426023413 0ustar www-datawww-datarequire File.expand_path('../../spec_helper', __FILE__) describe 'mock!' do it "is a terser way of creating an object and mocking it" do object = mock!.some_method { 'value' }.subject expect(object.some_method).to eq 'value' end it "can be used inside the implementation block of a double" do object = Object.new stub(object).some_method { mock!.another_method { 'value' } } expect(object.some_method.another_method).to eq 'value' end it "can be called on a double" do object = Object.new stub(object).some_method.mock!.another_method { 'value' } expect(object.some_method.another_method).to eq 'value' end end rr-3.1.0/spec/suites/rspec_2/functional/mock_spec.rb0000644000004100000410000000102414265140426022424 0ustar www-datawww-datarequire File.expand_path('../../spec_helper', __FILE__) describe 'mock', is_mock: true do include MockDefinitionCreatorHelpers context 'against instance methods', method_type: :instance do include_context 'tests for a double definition creator method that supports mocking' end context 'against class methods', method_type: :class do include_context 'tests for a double definition creator method that supports mocking' end def double_definition_creator_for(object, &block) mock(object, &block) end end rr-3.1.0/spec/suites/rspec_2/functional/stub_spec.rb0000644000004100000410000000454414265140426022462 0ustar www-datawww-datarequire File.expand_path('../../spec_helper', __FILE__) describe 'stub' do include StubDefinitionCreatorHelpers context 'against instance methods', method_type: :instance do context 'that exist', methods_exist: true do include_context 'tests for a double definition creator method that supports stubbing' end context 'that do not exist', methods_exist: false do include_context 'tests for a double definition creator method that supports stubbing' end end context 'against class methods', method_type: :class do context 'that exist', methods_exist: true do include_context 'tests for a double definition creator method that supports stubbing' end context 'that do not exist', methods_exist: false do include_context 'tests for a double definition creator method that supports stubbing' end end def double_definition_creator_for(object, &block) stub(object, &block) end def expect_that_double_can_be_defined_without_block _, _, return_value = build_object_with_doubled_method_which_is_called('value', nil) expect(return_value).to eq nil end def expect_that_double_sets_implementation(&block) _, _, return_value = build_object_with_doubled_method_which_is_called('old value', -> { 'new value' }, &block) expect(return_value).to eq 'new value' end def expect_that_double_sets_implementation_and_resets(&block) object, method_name, return_value = build_object_with_doubled_method_which_is_reset_and_called('old value', -> { 'new value' }, &block) if methods_being_doubled_exist_already? # This doesn't work quite yet - see btakita#44 #expect(object).not_to respond_to(method_name) else expect(return_value).to eq 'old value' end end def expect_that_double_sets_value(&block) _, _, return_value = build_object_with_doubled_method_which_is_called('old value', 'new value', &block) expect(return_value).to eq 'new value' end def expect_that_double_sets_value_and_resets(&block) _, _, return_value = build_object_with_doubled_method_which_is_reset_and_called('old value', 'new value', &block) if methods_being_doubled_exist_already? # This doesn't work quite yet - see btakita#44 #expect(object).not_to respond_to(method_name) else expect(return_value).to eq 'old value' end end end rr-3.1.0/spec/suites/rspec_2/functional/received_spec.rb0000644000004100000410000000104414265140426023263 0ustar www-datawww-datarequire File.expand_path('../../spec_helper', __FILE__) describe 'received' do it "doesn't throw an error if the invocation occurred" do stub(subject).pig_rabbit subject.pig_rabbit('bacon', 'bunny meat') received(subject).pig_rabbit('bacon', 'bunny meat').call end it "throws a SpyVerificationError if the invocation did not occur" do stub(subject).pig_rabbit expect { received(subject).pig_rabbit('bacon', 'bunny meat').call }.to raise_error(RR::Errors::SpyVerificationErrors::SpyVerificationError) end end rr-3.1.0/spec/suites/rspec_2/functional/stub_instance_of_spec.rb0000644000004100000410000000064214265140426025025 0ustar www-datawww-datarequire File.expand_path('../../spec_helper', __FILE__) permutations = %w(stub instance_of).permutation.map { |parts| parts.join('.') } + %w(instance_of) permutations.each do |permutation| describe permutation, is_instance_of: true do include_context 'stub + instance_of' define_method(:double_definition_creator_for) do |object, &block| eval(permutation + '(object, &block)') end end end rr-3.1.0/spec/suites/rspec_2/functional/mock_instance_of_spec.rb0000644000004100000410000000063514265140426025003 0ustar www-datawww-datarequire File.expand_path('../../spec_helper', __FILE__) permutations = %w(mock instance_of).permutation.map { |parts| parts.join('.') } permutations.each do |permutation| describe permutation, is_mock: true, is_instance_of: true do include_context 'mock + instance_of' define_method(:double_definition_creator_for) do |object, &block| eval(permutation + '(object, &block)') end end end rr-3.1.0/spec/suites/rspec_2/functional/stub_proxy_instance_of_spec.rb0000644000004100000410000000102414265140426026261 0ustar www-datawww-datarequire File.expand_path('../../spec_helper', __FILE__) permutations = %w(stub proxy instance_of).permutation.map { |parts| parts.join('.') } + %w(proxy instance_of).permutation.map { |parts| parts.join('.') } permutations.each do |permutation| describe permutation, is_proxy: true, is_instance_of: true do include_context 'stub + instance_of' include ProxyDefinitionCreatorHelpers define_method(:double_definition_creator_for) do |object, &block| eval(permutation + '(object, &block)') end end end rr-3.1.0/spec/suites/rspec_2/functional/mock_proxy_instance_of_spec.rb0000644000004100000410000000073514265140426026245 0ustar www-datawww-datarequire File.expand_path('../../spec_helper', __FILE__) permutations = %w(mock proxy instance_of).permutation.map { |parts| parts.join('.') } permutations.each do |permutation| describe permutation, is_mock: true, is_proxy: true, is_instance_of: true do include_context 'mock + instance_of' include ProxyDefinitionCreatorHelpers define_method(:double_definition_creator_for) do |object, &block| eval(permutation + '(object, &block)') end end end rr-3.1.0/spec/suites/rspec_2/functional/mock_proxy_spec.rb0000644000004100000410000000061314265140426023670 0ustar www-datawww-datarequire File.expand_path('../../spec_helper', __FILE__) permutations = %w(mock proxy).permutation.map { |parts| parts.join('.') } permutations.each do |permutation| describe permutation, is_mock: true, is_proxy: true do include_context 'mock + proxy' define_method(:double_definition_creator_for) do |object, &block| eval(permutation + '(object, &block)') end end end rr-3.1.0/spec/suites/rspec_2/functional/mock_instance_of_strong_spec.rb0000644000004100000410000000070614265140426026376 0ustar www-datawww-datarequire File.expand_path('../../spec_helper', __FILE__) permutations = %w(mock instance_of strong).permutation.to_a. map { |parts| parts.join('.') } permutations.each do |permutation| describe permutation, is_mock: true, is_instance_of: true, is_strong: true do include_context 'mock + instance_of + strong' define_method(:double_definition_creator_for) do |object, &block| eval(permutation + '(object, &block)') end end end rr-3.1.0/spec/suites/rspec_2/functional/stub_proxy_spec.rb0000644000004100000410000000270614265140426023721 0ustar www-datawww-datarequire File.expand_path('../../spec_helper', __FILE__) permutations = %w(stub proxy).permutation.map { |parts| parts.join('.') } + %w(proxy) permutations.each do |permutation| describe permutation, is_proxy: true do include_context 'stub + proxy' define_method(:double_definition_creator_for) do |object, &block| eval(permutation + '(object, &block)') end end def expect_that_double_can_be_defined_without_block _, _, return_value = build_object_with_doubled_method_which_is_called('value', nil) expect(return_value).to eq 'value' end def expect_that_double_sets_implementation(&block) _, _, return_value = build_object_with_doubled_method_which_is_called('value', ->(v) { v.upcase }, &block) expect(return_value).to eq 'VALUE' end def expect_that_double_sets_implementation_and_resets(&block) _, _, return_value = build_object_with_doubled_method_which_is_reset_and_called('value', ->(v) { v.upcase }, &block) expect(return_value).to eq 'value' end def expect_that_double_sets_value(&block) _, _, return_value = build_object_with_doubled_method_which_is_called('old value', 'new value', &block) expect(return_value).to eq 'new value' end def expect_that_double_sets_value_and_resets(&block) _, _, return_value = build_object_with_doubled_method_which_is_reset_and_called('old value', 'new value', &block) expect(return_value).to eq 'old value' end end rr-3.1.0/spec/suites/rspec_2/functional/spy_spec.rb0000644000004100000410000000514014265140426022311 0ustar www-datawww-datarequire File.expand_path('../../spec_helper', __FILE__) describe 'spy' do it "records invocations of most methods on a given object" do subject = String.new def subject.some_method; end spy(subject) subject.some_method subject.reverse subject.chomp subject.should have_received.some_method subject.should have_received.reverse subject.should have_received.chomp end it "excludes #methods from the list of recorded methods" do subject = Object.new spy(subject) subject.methods subject.should_not have_received.methods end it "excludes #== from the list of recorded methods" do subject = Object.new spy(subject) subject == 5 subject.should_not have_received(:==) end it "excludes #__send__ from the list of recorded methods" do subject = Object.new spy(subject) subject.__send__('to_s') subject.should_not have_received(:__send__) end it "excludes #__id__ from the list of recorded methods" do subject = Object.new spy(subject) subject.__id__ subject.should_not have_received(:__id__) end it "excludes #object_id from the list of recorded methods" do subject = Object.new spy(subject) subject.object_id subject.should_not have_received(:object_id) end it "excludes #class from the list of recorded methods" do subject = Object.new spy(subject) subject.class subject.should_not have_received.class end it "excludes #respond_to? from the list of recorded methods" do subject = Object.new spy(subject) subject.respond_to?(:foo) subject.should_not have_received(:respond_to?) end it "excludes #respond_to? from the list of recorded methods" do subject = Object.new spy(subject) subject.inspect subject.should_not have_received.inspect end it "excludes #respond_to? from the list of recorded methods" do subject = Object.new spy(subject) subject.to_s subject.should_not have_received.to_s end it "excludes #respond_to_missing? from the list of recorded methods" do subject = Object.new spy(subject) subject.__send__(:respond_to_missing?, :foo, []) subject.should_not have_received(:respond_to_missing?) end it "excludes #instance_eval from the list of recorded methods" do subject = Object.new spy(subject) subject.instance_eval {} subject.should_not have_received(:instance_eval) end it "excludes #instance_exec from the list of recorded methods" do subject = Object.new spy(subject) subject.instance_exec {} subject.should_not have_received(:instance_exec) end end rr-3.1.0/spec/suites/rspec_2/functional/any_instance_of_spec.rb0000644000004100000410000001146714265140426024646 0ustar www-datawww-datarequire File.expand_path('../../spec_helper', __FILE__) describe 'any_instance_of' do context 'stubs for instance methods of a class' do context 'via block form' do context 'for existing methods' do it "can be defined" do a_class = Class.new { def some_method; 'value'; end } any_instance_of(a_class) { |c| stub(c).some_method { 'value' } } instance = a_class.new expect(instance.some_method).to eq 'value' end it "can be reset" do a_class = Class.new { def some_method; 'original value'; end } any_instance_of(a_class) { |c| stub(c).some_method { 'value' } } RR.reset instance = a_class.new expect(instance.some_method).to eq 'original value' end end context 'for non-existing methods' do it "can be defined" do a_class = Class.new any_instance_of(a_class) { |c| stub(c).some_method { 'value' } } instance = a_class.new expect(instance.some_method).to eq 'value' end it "can be reset" do a_class = Class.new any_instance_of(a_class) { |c| stub(c).some_method { 'value' } } RR.reset instance = a_class.new expect(instance).not_to respond_to(:some_method) end end end context 'via hash form' do context 'for existing methods' do it "can be defined" do a_class = Class.new { def some_method; 'value'; end } any_instance_of(a_class, :some_method => lambda { 'value' }) instance = a_class.new expect(instance.some_method).to eq 'value' end it "can be reset" do a_class = Class.new { def some_method; 'original value'; end } any_instance_of(a_class, :some_method => lambda { 'value' }) RR.reset instance = a_class.new expect(instance.some_method).to eq 'original value' end end context 'for non-existing methods' do it "can be defined" do a_class = Class.new any_instance_of(a_class, :some_method => lambda { 'value' }) instance = a_class.new expect(instance.some_method).to eq 'value' end it "can be reset" do a_class = Class.new any_instance_of(a_class, :some_method => lambda { 'value' }) RR.reset instance = a_class.new expect(instance).not_to respond_to(:some_method) end end end end context 'stub-proxies for instance methods of a class' do it "can be defined" do a_class = Class.new { def some_method; 'value'; end } any_instance_of(a_class) { |c| stub.proxy(c).some_method { 'value' } } instance = a_class.new expect(instance.some_method).to eq 'value' end it "can be reset" do a_class = Class.new { def some_method; 'original value'; end } any_instance_of(a_class) { |c| stub.proxy(c).some_method { 'value' } } RR.reset instance = a_class.new expect(instance.some_method).to eq 'original value' end end context 'mocks for instance methods of a class' do context 'for existing methods' do it "can be defined" do a_class = Class.new { def some_method; 'value'; end } any_instance_of(a_class) { |c| mock(c).some_method { 'value' } } instance = a_class.new expect(instance.some_method).to eq 'value' end it "can be reset" do a_class = Class.new { def some_method; 'original value'; end } any_instance_of(a_class) { |c| mock(c).some_method { 'value' } } RR.reset instance = a_class.new expect(instance.some_method).to eq 'original value' end end context 'for non-existing methods' do it "can be defined" do a_class = Class.new any_instance_of(a_class) { |c| mock(c).some_method { 'value' } } instance = a_class.new expect(instance.some_method).to eq 'value' end it "can be reset" do a_class = Class.new any_instance_of(a_class) { |c| mock(c).some_method { 'value' } } RR.reset instance = a_class.new expect(instance).not_to respond_to(:some_method) end end end context 'mock-proxies for instance methods of a class' do it "can be defined" do a_class = Class.new { def some_method; 'value'; end } any_instance_of(a_class) { |c| mock.proxy(c).some_method { 'value' } } instance = a_class.new expect(instance.some_method).to eq 'value' end it "can be reset" do a_class = Class.new { def some_method; 'original value'; end } any_instance_of(a_class) { |c| mock.proxy(c).some_method { 'value' } } RR.reset instance = a_class.new expect(instance.some_method).to eq 'original value' end end end rr-3.1.0/spec/suites/rspec_2/functional/stub_strong_spec.rb0000644000004100000410000000061614265140426024052 0ustar www-datawww-datarequire File.expand_path('../../spec_helper', __FILE__) permutations = %w(stub strong).permutation.map { |parts| parts.join('.') } + %w(strong) permutations.each do |permutation| describe permutation, is_strong: true do include_context 'stub + strong' define_method(:double_definition_creator_for) do |object, &block| eval(permutation + '(object, &block)') end end end rr-3.1.0/spec/suites/rspec_2/functional/stub_instance_of_strong_spec.rb0000644000004100000410000000074314265140426026423 0ustar www-datawww-datarequire File.expand_path('../../spec_helper', __FILE__) permutations = (%w(stub instance_of strong).permutation.to_a + %w(instance_of strong).permutation.to_a). map { |parts| parts.join('.') } permutations.each do |permutation| describe permutation, is_instance_of: true, is_strong: true do include_context 'stub + instance_of + strong' define_method(:double_definition_creator_for) do |object, &block| eval(permutation + '(object, &block)') end end end rr-3.1.0/spec/suites/rspec_2/support/0000755000004100000410000000000014265140426017511 5ustar www-datawww-datarr-3.1.0/spec/suites/rspec_2/support/matchers/0000755000004100000410000000000014265140426021317 5ustar www-datawww-datarr-3.1.0/spec/suites/rspec_2/support/matchers/wildcard_matcher_matchers.rb0000644000004100000410000000140314265140426027024 0ustar www-datawww-datamodule WildcardMatcherMatchers extend RSpec::Matchers::DSL matcher :equal_match do |value| match { |matcher| matcher == value && matcher.eql?(value) } failure_message_for_should { "Expected matcher to equal match #{value.inspect}, but it didn't" } failure_message_for_should_not { "Expected matcher to not equal match #{value.inspect}, but it did" } end matcher :wildcard_match do |value| match { |matcher| matcher.wildcard_match?(value) } failure_message_for_should { "Expected matcher to wildcard equal match #{value.inspect}, but it didn't" } failure_message_for_should_not { "Expected matcher to not wildcard equal match #{value.inspect}, but it did" } end end rr-3.1.0/spec/suites/rspec_2/support/shared_contexts/0000755000004100000410000000000014265140426022706 5ustar www-datawww-datarr-3.1.0/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/0000755000004100000410000000000014265140426030272 5ustar www-datawww-data././@LongLink0000644000000000000000000000020500000000000011600 Lustar rootrootrr-3.1.0/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/argument_expectations_with_times_called_qualifier.rbrr-3.1.0/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/argument_expectation0000644000004100000410000000424114265140426034443 0ustar www-datawww-datashared_context 'using 1 of 2 ways to define a mock with an argument expectation with a times-called qualifier' do include DoubleDefinitionCreatorHelpers context 'upon verification after the invocation occurs too few times' do specify "TimesCalledError is raised" do object = build_object_with_possible_methods(some_method: ->(arg) {}) do |subject| double_creator = double_definition_creator_for(subject) define_double_with_argument_expectation(double_creator, :some_method, 1).times(2) end call_possible_method_on(object, :some_method, 1) expect { RR.verify }.to raise_error(RR::Errors::TimesCalledError) end specify "nothing happens upon reset" do object = build_object_with_possible_methods(some_method: ->(arg) {}) do |subject| double_creator = double_definition_creator_for(subject) define_double_with_argument_expectation(double_creator, :some_method, 1).times(2) end RR.reset call_possible_method_on(object, :some_method, 1) expect { RR.verify }.not_to raise_error end end context 'the moment the invocation occurs one too many times' do specify "TimesCalledError is raised" do object = build_object_with_possible_methods(some_method: ->(arg) {}) do |subject| double_creator = double_definition_creator_for(subject) define_double_with_argument_expectation(double_creator, :some_method, 1).times(2) end call_possible_method_on(object, :some_method, 1) call_possible_method_on(object, :some_method, 1) expect { object.some_method(1) }.to raise_error(RR::Errors::TimesCalledError) RR.reset end specify "nothing happens upon reset" do object = build_object_with_possible_methods(some_method: ->(arg) {}) do |subject| double_creator = double_definition_creator_for(subject) define_double_with_argument_expectation(double_creator, :some_method, 1).times(2) end RR.reset call_possible_method_on(object, :some_method, 1) call_possible_method_on(object, :some_method, 1) expect { call_possible_method_on(object, :some_method, 1) }.not_to raise_error end end end ././@LongLink0000644000000000000000000000020500000000000011600 Lustar rootrootrr-3.1.0/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/argument_expectations_with_never_called_qualifier.rbrr-3.1.0/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/argument_expectation0000644000004100000410000000324114265140426034442 0ustar www-datawww-datashared_context 'using 1 of 2 ways to define a mock with an argument expectation with a never-called qualifier' do include DoubleDefinitionCreatorHelpers it "works as long as the invocation never occurs" do build_object_with_possible_methods(some_method: lambda {|arg| }) do |subject| double_creator = double_definition_creator_for(subject) define_double_with_argument_expectation(double_creator, :some_method, 1).never end end it "works as long as the invocation never occurs even if other invocations occur" do object = build_object_with_possible_methods(some_method: lambda {|arg| }) do |subject| double_creator = double_definition_creator_for(subject) define_double_with_argument_expectation(double_creator, :some_method, 1).never end stub(object).some_method.with_any_args object.some_method(2) end specify "TimesCalledError is raised as soon as the invocation occurs" do object = build_object_with_possible_methods(some_method: lambda {|arg| }) do |subject| double_creator = double_definition_creator_for(subject) define_double_with_argument_expectation(double_creator, :some_method, 1).never end expect { object.some_method(1) }.to raise_error(RR::Errors::TimesCalledError) RR.reset end specify "nothing happens upon being reset" do object = build_object_with_possible_methods(some_method: lambda {|arg| }) do |subject| double_creator = double_definition_creator_for(subject) define_double_with_argument_expectation(double_creator, :some_method, 1).never end RR.reset expect { call_possible_method_on(object, :some_method, 1) }.not_to raise_error end end rr-3.1.0/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/dont_allow.rb0000644000004100000410000001517714265140426032774 0ustar www-datawww-datashared_context 'tests for a double definition creator method that supports dont_allow' do include DoubleDefinitionCreatorHelpers specify "TimesCalledError is raised as soon as the method is called" do object = build_object_with_possible_methods(some_method: -> {}) do |subject| dont_allow(subject).some_method end expect { object.some_method }.to raise_error(RR::Errors::TimesCalledError) end context 'defining a mock with an argument expectation with a times-called qualifier' do context 'by passing arguments to the double definition directly' do include_context 'using 1 of 2 ways to define a mock with an argument expectation with a times-called qualifier' def define_double_with_argument_expectation(double_creator, method_name, *args) double_creator.__send__(method_name, *args) end end # https://github.com/rr/rr/issues/23 unless supports_strong? context 'by using #with and arguments' do include_context 'using 1 of 2 ways to define a mock with an argument expectation with a times-called qualifier' def define_double_with_argument_expectation(double_creator, method_name, *args) double_creator.__send__(method_name).with(*args) end end end end context 'defining a mock with an argument expectation with a never-called qualifier' do context 'by passing arguments to the double definition directly' do include_context 'using 1 of 2 ways to define a mock with an argument expectation with a never-called qualifier' def define_double_with_argument_expectation(double_creator, method_name, *args) double_creator.__send__(method_name, *args) end end # https://github.com/rr/rr/issues/23 unless supports_strong? context 'by using #with and arguments' do include_context 'using 1 of 2 ways to define a mock with an argument expectation with a never-called qualifier' def define_double_with_argument_expectation(double_creator, method_name, *args) double_creator.__send__(method_name).with(*args) end end end end context 'defining a mock with an argument expectation without any qualifiers' do context 'by passing arguments to the double definition directly' do include_context 'using 1 of 2 ways to define a method double with an argument expectation without any qualifiers' specify "no error is raised if the method is never called at all" do build_object_with_possible_methods(some_method: -> {}) do |subject| double_creator = double_definition_creator_for(subject) define_double_with_argument_expectation(double_creator, :some_method, 1) end end specify "a DoubleNotFoundError is raised if the method is called but not with the specified arguments" do object = build_object_with_possible_methods(some_method: -> {}) do |subject| double_creator = double_definition_creator_for(subject) define_double_with_argument_expectation(double_creator, :some_method, 1) end expect { object.some_method }.to raise_error(RR::Errors::DoubleNotFoundError) end specify "a TimesCalledError is raised the moment the method is called with the specified arguments" do object = build_object_with_possible_methods(some_method: -> {}) do |subject| double_creator = double_definition_creator_for(subject) define_double_with_argument_expectation(double_creator, :some_method, 1) end expect { object.some_method(1) }.to raise_error(RR::Errors::TimesCalledError) end def define_double_with_argument_expectation(double_creator, method_name, *args) double_creator.__send__(method_name, *args) end end # https://github.com/rr/rr/issues/23 unless supports_strong? context 'by using #with and arguments' do include_context 'using 1 of 2 ways to define a method double with an argument expectation without any qualifiers' specify "no error is raised if the method is never called at all" do build_object_with_possible_methods(some_method: -> {}) do |subject| double_creator = double_definition_creator_for(subject) define_double_with_argument_expectation(double_creator, :some_method, 1) end end specify "a DoubleNotFoundError is raised if the method is called but not with the specified arguments" do object = build_object_with_possible_methods(some_method: -> {}) do |subject| double_creator = double_definition_creator_for(subject) define_double_with_argument_expectation(double_creator, :some_method, 1) end expect { object.some_method }.to raise_error(RR::Errors::DoubleNotFoundError) end specify "a TimesCalledError is raised the moment the method is called with the specified arguments" do object = build_object_with_possible_methods(some_method: -> {}) do |subject| double_creator = double_definition_creator_for(subject) define_double_with_argument_expectation(double_creator, :some_method, 1) end expect { object.some_method(1) }.to raise_error(RR::Errors::TimesCalledError) end def define_double_with_argument_expectation(double_creator, method_name, *args) double_creator.__send__(method_name).with(*args) end end end end it_behaves_like 'defining method doubles using the block form of the double definition creator' it_behaves_like 'defining a method double for sequential invocations of that method using #ordered/#then' it_behaves_like 'an object which has a method double wrapped in an array and flattened' if supports_proxying? && !supports_instance_of? it_behaves_like 'defining a method double on an object which is a proxy for another object' end if methods_being_doubled_exist_already? it "lets you double operator methods as well as normal ones" do object = build_object do |subject| double_definition_creator_for(subject).==(anything) { 'value' } end expect_call_to_return_or_raise_times_called_error('value', object, :==, :whatever) end end if type_of_methods_being_tested == :class && methods_being_doubled_exist_already? && !supports_instance_of? it "in a parent class doesn't affect child classes" do parent_class = Class.new do def self.some_method; 'existing value'; end end child_class = Class.new(parent_class) double_creator = double_definition_creator_for(parent_class) double_creator.some_method { 'value' } expect(child_class.some_method).to eq 'existing value' end end end rr-3.1.0/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/stub_proxy.rb0000644000004100000410000000061114265140426033033 0ustar www-datawww-datashared_context 'stub + proxy' do include ProxyDefinitionCreatorHelpers context 'against instance methods', method_type: :instance do include_context 'tests for a double definition creator method that supports stubbing' end context 'against class methods', method_type: :class do include_context 'tests for a double definition creator method that supports stubbing' end end rr-3.1.0/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/stub_instance_of.rb0000644000004100000410000000233214265140426034144 0ustar www-datawww-datashared_context 'stub + instance_of' do include StubDefinitionCreatorHelpers context 'where subject is a class', method_type: :class do context 'where methods being doubled already exist', methods_exist: true do include_context 'tests for a double definition creator method that supports stubbing' it "lets you stub methods which are called in #initialize" do klass = Class.new do def initialize; method_run_in_initialize; end def method_run_in_initialize; end end method_double_called = false double_creator = double_definition_creator_for(klass) double_creator.method_run_in_initialize { method_double_called = true } klass.new expect(method_double_called).to eq true end end context 'where methods being doubled do not already exist', methods_exist: false do include_context 'tests for a double definition creator method that supports stubbing' end end context 'where subject is an instance of a class', method_type: :instance do it "doesn't work" do double_creator = double_definition_creator_for(Object.new) expect { double_creator.some_method }.to raise_error(ArgumentError) end end end rr-3.1.0/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/mock_instance_of.rb0000644000004100000410000000165414265140426034126 0ustar www-datawww-datashared_context 'mock + instance_of' do include MockDefinitionCreatorHelpers context 'where subject is a class', method_type: :class do include_context 'tests for a double definition creator method that supports mocking' it "lets you stub methods which are called in #initialize" do klass = Class.new do def initialize; method_run_in_initialize; end def method_run_in_initialize; end end method_double_called = false double_creator = double_definition_creator_for(klass) double_creator.method_run_in_initialize { method_double_called = true } klass.new expect(method_double_called).to eq true end end context 'where subject is an instance of a class', method_type: :instance do it "doesn't work" do double_creator = double_definition_creator_for(Object.new) expect { double_creator.some_method }.to raise_error(ArgumentError) end end end rr-3.1.0/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/mock_proxy.rb0000644000004100000410000000060714265140426033014 0ustar www-datawww-datashared_context 'mock + proxy' do include ProxyDefinitionCreatorHelpers context 'against instance methods', method_type: :instance do include_context 'tests for a double definition creator method that supports mocking' end context 'against class methods', method_type: :class do include_context 'tests for a double definition creator method that supports mocking' end end rr-3.1.0/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/stub_strong.rb0000644000004100000410000000243614265140426033175 0ustar www-datawww-datashared_context 'stub + strong' do include StubDefinitionCreatorHelpers context 'against instance methods', method_type: :instance do context 'that exist', methods_exist: true do include_context 'tests for a double definition creator method that supports stubbing' it_behaves_like 'comparing the arity between the method and double definition' end context 'that do not exist', methods_exist: false do it "doesn't work" do object = Object.new double_creator = double_definition_creator_for(object) expect { double_creator.some_method }.to \ raise_error(RR::Errors::SubjectDoesNotImplementMethodError) end end end context 'against class methods', method_type: :class do context 'that exist', methods_exist: true do include_context 'tests for a double definition creator method that supports stubbing' it_behaves_like 'comparing the arity between the method and double definition' end context 'that do not exist', methods_exist: false do it "doesn't work" do klass = Class.new double_creator = double_definition_creator_for(klass) expect { double_creator.some_method }.to \ raise_error(RR::Errors::SubjectDoesNotImplementMethodError) end end end end ././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootrootrr-3.1.0/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/stub_instance_of_strong.rbrr-3.1.0/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/stub_instance_of_str0000644000004100000410000000272314265140426034436 0ustar www-datawww-datashared_context 'stub + instance_of + strong' do include StubDefinitionCreatorHelpers context 'where subject is a class', method_type: :class do context 'where methods being doubled already exist', methods_exist: true do include_context 'tests for a double definition creator method that supports stubbing' it_behaves_like 'comparing the arity between the method and double definition' it "lets you stub methods which are called in #initialize" do klass = Class.new do def initialize; method_run_in_initialize; end def method_run_in_initialize; end end method_double_called = false double_creator = double_definition_creator_for(klass) double_creator.method_run_in_initialize { method_double_called = true } klass.new expect(method_double_called).to eq true end end context 'where methods being doubled do not already exist', methods_exist: false do it "doesn't work" do klass = Class.new double_creator = double_definition_creator_for(klass) expect { double_creator.some_method }.to \ raise_error(RR::Errors::SubjectDoesNotImplementMethodError) end end end context 'where subject is an instance of a class', method_type: :instance do it "doesn't work" do double_creator = double_definition_creator_for(Object.new) expect { double_creator.some_method }.to raise_error(ArgumentError) end end end ././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootrootrr-3.1.0/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/mock_instance_of_strong.rbrr-3.1.0/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/mock_instance_of_str0000644000004100000410000000201214265140426034401 0ustar www-datawww-datashared_context 'mock + instance_of + strong' do include MockDefinitionCreatorHelpers context 'where subject is a class', method_type: :class do include_context 'tests for a double definition creator method that supports stubbing' it_behaves_like 'comparing the arity between the method and double definition' it "lets you stub methods which are called in #initialize" do klass = Class.new do def initialize; method_run_in_initialize; end def method_run_in_initialize; end end method_double_called = false double_creator = double_definition_creator_for(klass) double_creator.method_run_in_initialize { method_double_called = true } klass.new expect(method_double_called).to eq true end end context 'where subject is an instance of a class', method_type: :instance do it "doesn't work" do double_creator = double_definition_creator_for(Object.new) expect { double_creator.some_method }.to raise_error(ArgumentError) end end end rr-3.1.0/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/mocking.rb0000644000004100000410000001060414265140426032247 0ustar www-datawww-datashared_context 'tests for a double definition creator method that supports mocking' do include DoubleDefinitionCreatorHelpers specify "TimesCalledError is raised at the verify step if the method is never called" do build_object_with_possible_methods(some_method: -> {}) do |subject| double_creator = double_definition_creator_for(subject) double_creator.some_method end expect { RR.verify }.to raise_error(RR::Errors::TimesCalledError) end it_behaves_like 'defining a method double that sets the implementation of that method' context 'defining a mock with an argument expectation with a times-called qualifier' do context 'by passing arguments to the double definition directly' do include_context 'using 1 of 2 ways to define a mock with an argument expectation with a times-called qualifier' def define_double_with_argument_expectation(double_creator, method_name, *args) double_creator.__send__(method_name, *args) end end # https://github.com/rr/rr/issues/23 unless supports_strong? context 'by using #with and arguments' do include_context 'using 1 of 2 ways to define a mock with an argument expectation with a times-called qualifier' def define_double_with_argument_expectation(double_creator, method_name, *args) double_creator.__send__(method_name).with(*args) end end end end context 'defining a mock with an argument expectation with a never-called qualifier' do context 'by passing arguments to the double definition directly' do include_context 'using 1 of 2 ways to define a mock with an argument expectation with a never-called qualifier' def define_double_with_argument_expectation(double_creator, method_name, *args) double_creator.__send__(method_name, *args) end end # https://github.com/rr/rr/issues/23 unless supports_strong? context 'by using #with and arguments' do include_context 'using 1 of 2 ways to define a mock with an argument expectation with a never-called qualifier' def define_double_with_argument_expectation(double_creator, method_name, *args) double_creator.__send__(method_name).with(*args) end end end end context 'defining a mock with an argument expectation without any qualifiers' do context 'by passing arguments to the double definition directly' do include_context 'using 1 of 2 ways to define a method double with an argument expectation without any qualifiers' def define_double_with_argument_expectation(double_creator, method_name, *args) double_creator.__send__(method_name, *args) end end # https://github.com/rr/rr/issues/23 unless supports_strong? context 'by using #with and arguments' do include_context 'using 1 of 2 ways to define a method double with an argument expectation without any qualifiers' def define_double_with_argument_expectation(double_creator, method_name, *args) double_creator.__send__(method_name).with(*args) end end end end it_behaves_like 'defining a method double qualified with #yields' it_behaves_like 'defining method doubles using the block form of the double definition creator' it_behaves_like 'defining a method double for sequential invocations of that method using #ordered/#then' it_behaves_like 'an object which has a method double wrapped in an array and flattened' if supports_proxying? && !supports_instance_of? it_behaves_like 'defining a method double on an object which is a proxy for another object' end if methods_being_doubled_exist_already? it "lets you double operator methods as well as normal ones" do object = build_object do |subject| double_definition_creator_for(subject).==(anything) { 'value' } end expect(object == :whatever).to eq 'value' end end if type_of_methods_being_tested == :class && methods_being_doubled_exist_already? && !supports_instance_of? it "in a parent class doesn't affect child classes" do parent_class = Class.new do def self.some_method; 'existing value'; end end child_class = Class.new(parent_class) double_creator = double_definition_creator_for(parent_class) double_creator.some_method { 'value' } parent_class.some_method expect(child_class.some_method).to eq 'existing value' end end end ././@LongLink0000644000000000000000000000017400000000000011605 Lustar rootrootrr-3.1.0/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/argument_expectations_without_qualifiers.rbrr-3.1.0/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/argument_expectation0000644000004100000410000001257114265140426034450 0ustar www-datawww-datashared_context 'using 1 of 2 ways to define a method double with an argument expectation without any qualifiers' do include DoubleDefinitionCreatorHelpers it "defines the double just for that specific invocation" do object = build_object_with_possible_methods(some_method: ->(*args) { 'value' }) do |subject| double_creator = double_definition_creator_for(subject) double = define_double_with_argument_expectation(double_creator, :some_method, 1) double.returns { 'bar' } end expect_call_to_return_or_raise_times_called_error('bar', object, :some_method, 1) end if supports_dont_allow? context 'upon verification after the invocation occurs too few times' do specify "no error is raised if the method is never called at all" do build_object_with_possible_methods(some_method: ->(*args) {}) do |subject| double_creator = double_definition_creator_for(subject) define_double_with_argument_expectation(double_creator, :some_method, 1) end expect { RR.verify }.not_to raise_error end end context 'the moment an unknown invocation occurs' do specify "DoubleNotFoundError is raised" do object = build_object_with_possible_methods(some_method: ->(*args) {}) do |subject| double_creator = double_definition_creator_for(subject) define_double_with_argument_expectation(double_creator, :some_method, 1) end expect { object.some_method }.to raise_error(RR::Errors::DoubleNotFoundError) RR.reset end it "is reset correctly" do object = build_object_with_possible_methods(some_method: ->(*args) {}) do |subject| double_creator = double_definition_creator_for(subject) define_double_with_argument_expectation(double_creator, :some_method, 1) end RR.reset expect { call_possible_method_on(object, :some_method) }.not_to raise_error end end elsif supports_mocking? context 'upon verification after the invocation occurs too few times' do specify "TimesCalledError is raised at the verify step if the method is never called at all" do build_object_with_possible_methods(some_method: ->(*args) {}) do |subject| double_creator = double_definition_creator_for(subject) define_double_with_argument_expectation(double_creator, :some_method, 1) end expect { RR.verify }.to raise_error(RR::Errors::TimesCalledError) end specify "nothing happens upon being reset" do build_object_with_possible_methods(some_method: ->(*args) {}) do |subject| double_creator = double_definition_creator_for(subject) define_double_with_argument_expectation(double_creator, :some_method, 1) end RR.reset expect { RR.verify }.not_to raise_error end end context 'the moment an unknown invocation occurs' do specify "DoubleNotFoundError is raised" do object = build_object_with_possible_methods(some_method: ->(*args) {}) do |subject| double_creator = double_definition_creator_for(subject) define_double_with_argument_expectation(double_creator, :some_method, 1) end expect { object.some_method }.to raise_error(RR::Errors::DoubleNotFoundError) RR.reset end specify "is reset correctly" do object = build_object_with_possible_methods(some_method: ->(*args) {}) do |subject| double_creator = double_definition_creator_for(subject) define_double_with_argument_expectation(double_creator, :some_method, 1) end RR.reset expect { call_possible_method_on(object, :some_method, 1) }.not_to raise_error end end else it "resets the double correctly" do object = build_object_with_possible_methods(some_method: ->(*args) { 'existing value' }) do |subject, object| expect_method_to_have_value_or_be_absent('existing value', object, :some_method, 1) double_creator = double_definition_creator_for(subject) double = define_double_with_argument_expectation(double_creator, :some_method, 1) double.returns { 'new value' } end RR.reset expect_method_to_have_value_or_be_absent('existing value', object, :some_method, 1) end it "raises DoubleNotFoundError the moment the method is called but not with the specified arguments" do object = build_object_with_possible_methods(some_method: ->(*args) {}) do |subject| double_creator = double_definition_creator_for(subject) define_double_with_argument_expectation(double_creator, :some_method, 1) end expect { object.some_method }.to raise_error(RR::Errors::DoubleNotFoundError) RR.reset end end unless supports_dont_allow? it "lets you define a catch-all double by defining a stub without arguments" do object = build_object_with_possible_methods(some_method: ->(*args) {}) do |subject| double_creator = if supports_instance_of? stub.instance_of(subject) else stub(subject) end double_creator.some_method double_creator = double_definition_creator_for(subject) define_double_with_argument_expectation(double_creator, :some_method, 1) end object.some_method(1) object.some_method(2) # shouldn't raise an error end end end rr-3.1.0/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/mock_strong.rb0000644000004100000410000000243414265140426033147 0ustar www-datawww-datashared_context 'mock + strong' do include MockDefinitionCreatorHelpers context 'against instance methods', method_type: :instance do context 'that exist', methods_exist: true do include_context 'tests for a double definition creator method that supports mocking' it_behaves_like 'comparing the arity between the method and double definition' end context 'that do not exist', methods_exist: false do it "doesn't work" do object = Object.new double_creator = double_definition_creator_for(object) expect { double_creator.some_method }.to \ raise_error(RR::Errors::SubjectDoesNotImplementMethodError) end end end context 'against class methods', method_type: :class do context 'that exist', methods_exist: true do include_context 'tests for a double definition creator method that supports mocking' it_behaves_like 'comparing the arity between the method and double definition' end context 'that do not exist', methods_exist: false do it "doesn't work" do klass = Class.new double_creator = double_definition_creator_for(klass) expect { double_creator.some_method }.to \ raise_error(RR::Errors::SubjectDoesNotImplementMethodError) end end end end rr-3.1.0/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/stubbing.rb0000644000004100000410000000455014265140426032440 0ustar www-datawww-datashared_context 'tests for a double definition creator method that supports stubbing' do include DoubleDefinitionCreatorHelpers it_behaves_like 'defining a method double that sets the implementation of that method' context 'defining a method double with an argument expectation' do context 'by passing arguments to the double definition directly' do include_context 'using 1 of 2 ways to define a method double with an argument expectation without any qualifiers' def define_double_with_argument_expectation(double_creator, method_name, *args) double_creator.__send__(method_name, *args) end end # https://github.com/rr/rr/issues/23 unless supports_strong? context 'by using #with and arguments' do include_context 'using 1 of 2 ways to define a method double with an argument expectation without any qualifiers' def define_double_with_argument_expectation(double_creator, method_name, *args) double_creator.__send__(method_name).with(*args) end end end end it_behaves_like 'defining a method double qualified with #yields' it_behaves_like 'defining method doubles using the block form of the double definition creator' it_behaves_like 'defining a method double for sequential invocations of that method using #ordered/#then' it_behaves_like 'an object which has a method double wrapped in an array and flattened' if supports_proxying? && !supports_instance_of? it_behaves_like 'defining a method double on an object which is a proxy for another object' end if methods_being_doubled_exist_already? it "lets you double operator methods as well as normal ones" do object = build_object do |subject| double_definition_creator_for(subject).==(anything) { 'value' } end expect(object == :whatever).to eq 'value' end end if type_of_methods_being_tested == :class && methods_being_doubled_exist_already? && !supports_instance_of? it "in a parent class doesn't affect child classes" do parent_class = Class.new do def self.some_method; 'existing value'; end end child_class = Class.new(parent_class) double_creator = double_definition_creator_for(parent_class) double_creator.some_method { 'value' } parent_class.some_method expect(child_class.some_method).to eq 'existing value' end end end rr-3.1.0/spec/suites/rspec_2/support/shared_examples/0000755000004100000410000000000014265140426022655 5ustar www-datawww-datarr-3.1.0/spec/suites/rspec_2/support/shared_examples/double_definition_creators/0000755000004100000410000000000014265140426030241 5ustar www-datawww-datarr-3.1.0/spec/suites/rspec_2/support/shared_examples/double_definition_creators/yields.rb0000644000004100000410000000552614265140426032067 0ustar www-datawww-datashared_examples_for 'defining a method double qualified with #yields' do include DoubleDefinitionCreatorHelpers context 'without arguments' do it "inserts a yield that passes no arguments" do object = build_object_with_possible_methods(some_method: -> {}) do |subject| double_definition_creator_for(subject).some_method.yields end x = 0 object.some_method { x = 1 } expect(x).to eq 1 end it "does not affect setting the implementation otherwise" do object = build_object_with_possible_methods(some_method: -> { 'existing value' }) do |subject| double_definition_creator_for(subject).some_method { 'value' }.yields end expect(object.some_method { }).to eq 'value' end it "also lets you set the implementation in preference to #returns" do object = build_object_with_possible_methods(some_method: -> { 'existing value' }) do |subject| double_definition_creator_for(subject).some_method.yields { 'value' } end expect(object.some_method { }).to eq 'value' end it "is reset correctly" do object = build_object_with_possible_methods(some_method: -> {}) do |subject| double_definition_creator_for(subject).some_method.yields end RR.reset x = 0 if methods_being_doubled_exist_already? object.some_method { x = 1 } expect(x).to eq 0 else expect_method_to_not_exist(object, :some_method) end end end context 'with arguments' do it "inserts a yield that passes those arguments" do object = build_object_with_possible_methods(some_method: -> {}) do |subject| double_definition_creator_for(subject).some_method.yields(1) end x = 0 object.some_method {|a| x = a } expect(x).to eq 1 end it "does not affect setting the implementation otherwise" do object = build_object_with_possible_methods(some_method: -> { 'existing value' }) do |subject| double_definition_creator_for(subject).some_method { 'value' }.yields(1) end expect(object.some_method { }).to eq 'value' end it "also lets you set the implementation in preference to #returns" do object = build_object_with_possible_methods(some_method: -> { 'existing value' }) do |subject| double_definition_creator_for(subject).some_method.yields(1) { 'value' } end expect(object.some_method { }).to eq 'value' end it "is reset correctly" do object = build_object_with_possible_methods(some_method: -> {}) do |subject| double_definition_creator_for(subject).some_method.yields(1) end RR.reset if methods_being_doubled_exist_already? x = 0 object.some_method {|a| x = a } expect(x).to eq 0 else expect_method_to_not_exist(object, :some_method) end end end end rr-3.1.0/spec/suites/rspec_2/support/shared_examples/double_definition_creators/block_form.rb0000644000004100000410000000240714265140426032706 0ustar www-datawww-datashared_examples_for 'defining method doubles using the block form of the double definition creator' do include DoubleDefinitionCreatorHelpers it "allows multiple methods to be doubled" do object = build_object_with_possible_methods( some_method: -> { 'existing value 1' }, another_method: -> { 'existing value 2' } ) do |subject| double_definition_creator_for(subject) do some_method { 'value 1' } another_method { 'value 2' } end end expect_call_to_return_or_raise_times_called_error('value 1', object, :some_method) expect_call_to_return_or_raise_times_called_error('value 2', object, :another_method) end it "yields rather than using instance_eval if a block argument is given" do object = build_object_with_possible_methods( some_method: -> { 'existing value 1' }, another_method: -> { 'existing value 2' } ) do |subject| double_definition_creator_for(subject) do |double_creator| double_creator.some_method { 'value 1' } double_creator.another_method { 'value 2' } end end expect_call_to_return_or_raise_times_called_error('value 1', object, :some_method) expect_call_to_return_or_raise_times_called_error('value 2', object, :another_method) end end rr-3.1.0/spec/suites/rspec_2/support/shared_examples/double_definition_creators/object_is_proxy.rb0000644000004100000410000000314214265140426033770 0ustar www-datawww-data# btakita/rr issue #24 # this happens when defining a double on an ActiveRecord association object shared_examples_for 'defining a method double on an object which is a proxy for another object' do include DoubleDefinitionCreatorHelpers it "places the double on the proxy object and not the target object by mistake" do target_object = build_object_with_possible_methods(some_method: -> { 'existing value' }) proxy_object = proxy_object_class.new(target_object) expect(proxy_object.methods).to match_array(target_object.methods) double_definition_creator_for(proxy_object).some_method { 'value' } expect(proxy_object.some_method).to eq 'value' end it "resets the double correctly" do target_object = build_object_with_possible_methods(some_method: -> { 'existing value' }) proxy_object = proxy_object_class.new(target_object) expect(proxy_object.methods).to match_array(target_object.methods) double_definition_creator_for(proxy_object).some_method { 'value' } RR.reset expect_method_to_have_value_or_be_absent('existing value', proxy_object, :some_method) end def proxy_object_class Class.new do # This matches what AssociationProxy was like as of Rails 2 instance_methods.each do |m| undef_method m unless m.to_s =~ /^(?:nil\?|send|object_id|to_a)$|^__|^respond_to|proxy_/ end def initialize(target) @target = target end def method_missing(name, *args, &block) if @target.respond_to?(name) @target.__send__(name, *args, &block) else super end end end end end ././@LongLink0000644000000000000000000000015200000000000011601 Lustar rootrootrr-3.1.0/spec/suites/rspec_2/support/shared_examples/double_definition_creators/sequential_invocations.rbrr-3.1.0/spec/suites/rspec_2/support/shared_examples/double_definition_creators/sequential_invocatio0000644000004100000410000000171114265140426034411 0ustar www-datawww-datashared_examples_for 'defining a method double for sequential invocations of that method using #ordered/#then' do include DoubleDefinitionCreatorHelpers it "works" do object = build_object_with_possible_methods(some_method: -> {}) do |subject| double_creator = double_definition_creator_for(subject) double_creator.some_method { 'value 1' }.twice.ordered double_creator.some_method { 'value 2' }.once.ordered end expect(object.some_method).to eq 'value 1' expect(object.some_method).to eq 'value 1' expect(object.some_method).to eq 'value 2' end it "works when using #then instead of #ordered" do object = build_object_with_possible_methods(some_method: -> {}) do |subject| double_definition_creator_for(subject). some_method { 'value 1' }.once.then. some_method { 'value 2' }.once end expect(object.some_method).to eq 'value 1' expect(object.some_method).to eq 'value 2' end end ././@LongLink0000644000000000000000000000015200000000000011601 Lustar rootrootrr-3.1.0/spec/suites/rspec_2/support/shared_examples/double_definition_creators/setting_implementation.rbrr-3.1.0/spec/suites/rspec_2/support/shared_examples/double_definition_creators/setting_implementati0000644000004100000410000000324514265140426034415 0ustar www-datawww-datashared_examples_for 'defining a method double that sets the implementation of that method' do include DoubleDefinitionCreatorHelpers it "works when not given a block" do expect_that_double_can_be_defined_without_block end context 'by giving a block' do it "replaces the implementation with the block" do expect_that_double_sets_implementation do |double_creator, method_name, block| double_creator.__send__(method_name, &block) end end it "resets the double correctly" do expect_that_double_sets_implementation_and_resets do |double_creator, method_name, block| double_creator.__send__(method_name, &block) end end end context 'by using #returns' do context 'with a block' do it "replaces the implementation with the block" do expect_that_double_sets_implementation do |double_creator, method_name, block| double_creator.__send__(method_name).returns(&block) end end it "resets the double correctly" do expect_that_double_sets_implementation_and_resets do |double_creator, method_name, block| double_creator.__send__(method_name).returns(&block) end end end context 'with a straight argument' do it "makes the method return the argument" do expect_that_double_sets_value do |double_creator, method_name, value| double_creator.__send__(method_name).returns(value) end end it "resets the double correctly" do expect_that_double_sets_value_and_resets do |double, method_name, value| double_creator.__send__(method_name).returns(value) end end end end end rr-3.1.0/spec/suites/rspec_2/support/shared_examples/double_definition_creators/array_flatten_bug.rb0000644000004100000410000000240414265140426034256 0ustar www-datawww-data# btakita/rr issue #44 shared_examples_for 'an object which has a method double wrapped in an array and flattened' do include DoubleDefinitionCreatorHelpers it "does not raise an error" do object = build_object_with_possible_methods(some_method: -> {}) do |subject| double_definition_creator_for(subject).some_method end # force RR to define method_missing call_method_rescuing_times_called_error(object, :some_method) expect([object].flatten).to eq [object] end it "honors a #to_ary that already exists" do object = build_object_with_possible_methods(some_method: -> {}) do |subject, object| (class << object; self; end).class_eval do def to_ary; []; end end double_definition_creator_for(subject).some_method end # force RR to define method_missing call_method_rescuing_times_called_error(object, :some_method) expect([object].flatten).to eq [] end it "is reset correctly" do object = build_object_with_possible_methods(some_method: -> {}) do |subject| double_definition_creator_for(subject).some_method end # force RR to define method_missing call_method_rescuing_times_called_error(object, :some_method) RR.reset expect([object].flatten).to eq [object] end end rr-3.1.0/spec/suites/rspec_2/support/shared_examples/double_definition_creators/comparing_arity.rb0000644000004100000410000000455714265140426033770 0ustar www-datawww-datashared_examples_for 'comparing the arity between the method and double definition' do it "succeeds if both have no arity" do object = build_object_with_methods(some_method: -> {}) do |subject| double_creator = double_definition_creator_for(subject) double_creator.some_method end object.some_method end it "fails if the former has no arity and the latter does" do build_object_with_methods(some_method: -> {}) do |subject| double_creator = double_definition_creator_for(subject) expect { double_creator.some_method(1) }.to \ raise_error(RR::Errors::SubjectHasDifferentArityError) end end it "fails if the former has arity but the latter doesn't" do build_object_with_methods(some_method: ->(arg) {}) do |subject| double_creator = double_definition_creator_for(subject) expect { double_creator.some_method }.to \ raise_error(RR::Errors::SubjectHasDifferentArityError) end end it "succeeds if both have a finite number of arguments" do object = build_object_with_methods(some_method: ->(arg) {}) do |subject| double_creator = double_definition_creator_for(subject) double_creator.some_method(1) end object.some_method(1) end it "succeeds if both have a variable number of arguments" do object = build_object_with_methods(some_method: ->(*args) {}) do |subject| double_creator = double_definition_creator_for(subject) double_creator.some_method(1) double_creator.some_method(1, 2, 3) double_creator.some_method(1, 2) end object.some_method(1) object.some_method(1, 2) object.some_method(1, 2, 3) end it "succeeds if both have finite and variable number of arguments" do object = build_object_with_methods(some_method: ->(arg1, arg2, *rest) {}) do |subject| double_creator = double_definition_creator_for(subject) double_creator.some_method(1, 2) double_creator.some_method(1, 2, 3) end object.some_method(1, 2) object.some_method(1, 2, 3) end it "fails if the finite arguments are not matched before the variable arguments" do build_object_with_methods(some_method: ->(arg1, arg2, *rest) {}) do |subject| double_creator = double_definition_creator_for(subject) expect { double_creator.some_method(1) }.to \ raise_error(RR::Errors::SubjectHasDifferentArityError) end end end rr-3.1.0/spec/suites/rspec_2/support/shared_examples/times_called_expectation.rb0000644000004100000410000000037014265140426030232 0ustar www-datawww-datashared_examples_for "RR::Expectations::TimesCalledExpectation" do include_examples "Swapped Space" subject { Object.new } def raises_expectation_error(&block) expect { block.call }.to raise_error(RR::Errors::TimesCalledError) end end rr-3.1.0/spec/suites/rspec_2/support/shared_examples/space.rb0000644000004100000410000000041714265140426024277 0ustar www-datawww-datashared_examples_for "Swapped Space" do attr_reader :space, :original_space before do @original_space = RR::Space.instance RR::Space.instance = RR::Space.new @space = RR::Space.instance end after do RR::Space.instance = @original_space end end rr-3.1.0/spec/suites/rspec_2/support/mixins/0000755000004100000410000000000014265140426021020 5ustar www-datawww-datarr-3.1.0/spec/suites/rspec_2/support/mixins/proxy_definition_creator_helpers.rb0000644000004100000410000000221614265140426030200 0ustar www-datawww-datamodule ProxyDefinitionCreatorHelpers include DoubleDefinitionCreatorHelpers def expect_that_double_can_be_defined_without_block _, _, return_value = build_object_with_doubled_method_which_is_called('value', nil) expect(return_value).to eq 'value' end def expect_that_double_sets_implementation(&block) _, _, return_value = build_object_with_doubled_method_which_is_called('value', ->(v) { v.upcase }, &block) expect(return_value).to eq 'VALUE' end def expect_that_double_sets_implementation_and_resets(&block) _, _, return_value = build_object_with_doubled_method_which_is_reset_and_called('value', ->(v) { v.upcase }, &block) expect(return_value).to eq 'value' end def expect_that_double_sets_value(&block) _, _, return_value = build_object_with_doubled_method_which_is_called('old value', 'new value', &block) expect(return_value).to eq 'new value' end def expect_that_double_sets_value_and_resets(&block) _, _, return_value = build_object_with_doubled_method_which_is_reset_and_called('old value', 'new value', &block) expect(return_value).to eq 'old value' end end rr-3.1.0/spec/suites/rspec_2/support/mixins/stub_creator_helpers.rb0000644000004100000410000000272214265140426025566 0ustar www-datawww-datamodule StubDefinitionCreatorHelpers def expect_that_double_can_be_defined_without_block _, _, return_value = build_object_with_doubled_method_which_is_called('value', nil) expect(return_value).to eq nil end def expect_that_double_sets_implementation(&block) _, _, return_value = build_object_with_doubled_method_which_is_called('old value', -> { 'new value' }, &block) expect(return_value).to eq 'new value' end def expect_that_double_sets_implementation_and_resets(&block) object, method_name, return_value = build_object_with_doubled_method_which_is_reset_and_called('old value', -> { 'new value' }, &block) if methods_being_doubled_exist_already? # This doesn't work quite yet - see btakita#44 #expect(object).not_to respond_to(method_name) else expect(return_value).to eq 'old value' end end def expect_that_double_sets_value(&block) _, _, return_value = build_object_with_doubled_method_which_is_called('old value', 'new value', &block) expect(return_value).to eq 'new value' end def expect_that_double_sets_value_and_resets(&block) _, _, return_value = build_object_with_doubled_method_which_is_reset_and_called('old value', 'new value', &block) if methods_being_doubled_exist_already? # This doesn't work quite yet - see btakita#44 #expect(object).not_to respond_to(method_name) else expect(return_value).to eq 'old value' end end end rr-3.1.0/spec/suites/rspec_2/support/mixins/stub_definition_creator_helpers.rb0000644000004100000410000000277414265140426030005 0ustar www-datawww-datamodule StubDefinitionCreatorHelpers include DoubleDefinitionCreatorHelpers def expect_that_double_can_be_defined_without_block _, _, return_value = build_object_with_doubled_method_which_is_called('value', nil) expect(return_value).to eq nil end def expect_that_double_sets_implementation(&block) _, _, return_value = build_object_with_doubled_method_which_is_called('old value', -> { 'new value' }, &block) expect(return_value).to eq 'new value' end def expect_that_double_sets_implementation_and_resets(&block) object, method_name, return_value = build_object_with_doubled_method_which_is_reset_and_called('old value', -> { 'new value' }, &block) if methods_being_doubled_exist_already? # This doesn't work quite yet - see btakita#44 #expect(object).not_to respond_to(method_name) else expect(return_value).to eq 'old value' end end def expect_that_double_sets_value(&block) _, _, return_value = build_object_with_doubled_method_which_is_called('old value', 'new value', &block) expect(return_value).to eq 'new value' end def expect_that_double_sets_value_and_resets(&block) _, _, return_value = build_object_with_doubled_method_which_is_reset_and_called('old value', 'new value', &block) if methods_being_doubled_exist_already? # This doesn't work quite yet - see btakita#44 #expect(object).not_to respond_to(method_name) else expect(return_value).to eq 'old value' end end end rr-3.1.0/spec/suites/rspec_2/support/mixins/mock_definition_creator_helpers.rb0000644000004100000410000000276714265140426027763 0ustar www-datawww-datamodule MockDefinitionCreatorHelpers include DoubleDefinitionCreatorHelpers def expect_that_double_can_be_defined_without_block _, _, return_value = build_object_with_doubled_method_which_is_called('value') expect(return_value).to eq nil end def expect_that_double_sets_implementation(&block) _, _, return_value = build_object_with_doubled_method_which_is_called('old value', -> { 'new value' }, &block) expect(return_value).to eq 'new value' end def expect_that_double_sets_implementation_and_resets(&block) object, method_name, return_value = build_object_with_doubled_method_which_is_reset_and_called('old value', -> { 'new value' }, &block) if methods_being_doubled_exist_already? # This doesn't work quite yet - see btakita#44 #expect(object).not_to respond_to(method_name) else expect(return_value).to eq 'old value' end end def expect_that_double_sets_value(&block) _, _, return_value = build_object_with_doubled_method_which_is_called('old value', 'new value', &block) expect(return_value).to eq 'new value' end def expect_that_double_sets_value_and_resets(&block) _, _, return_value = build_object_with_doubled_method_which_is_reset_and_called('old value', 'new value', &block) if methods_being_doubled_exist_already? # This doesn't work quite yet - see btakita#44 #expect(object).not_to respond_to(method_name) else expect(return_value).to eq 'old value' end end end rr-3.1.0/spec/suites/rspec_2/support/mixins/double_definition_creator_helpers.rb0000644000004100000410000001061014265140426030266 0ustar www-datawww-datamodule DoubleDefinitionCreatorHelpers module ClassMethods def methods_being_doubled_exist_already? metadata[:methods_exist] || supports_proxying? || supports_mocking? end def type_of_methods_being_tested metadata[:method_type] end def supports_proxying? metadata[:is_proxy] end def supports_instance_of? metadata[:is_instance_of] end def supports_mocking? metadata[:is_mock] end def supports_strong? metadata[:is_strong] end def supports_dont_allow? metadata[:is_dont_allow] end end def self.included(base) base.extend(ClassMethods) end def build_object_with_possible_methods(methods = {}, actually_add_methods = methods_being_doubled_exist_already?) subject = if type_of_methods_being_tested == :class Class.new else Object.new end if actually_add_methods if supports_instance_of? add_methods_to_class(subject, methods) else add_methods_to_class(subject.singleton_class, methods) end end object = if type_of_methods_being_tested == :class && supports_instance_of? subject.new else subject end if block_given? yield subject, object end object end def build_object_with_methods(methods = {}, &block) build_object_with_possible_methods(methods, true, &block) end alias_method :build_object, :build_object_with_methods def add_methods_to_class(klass, methods) klass.class_eval do methods.each do |method_name, implementation| implementation ||= ->(*args) { } define_method(method_name, &implementation) end end end def expect_method_to_have_value_or_be_absent(return_value, object, method_name, *args, &block) if methods_being_doubled_exist_already? expect(object.__send__(method_name, *args, &block)).to eq return_value else expect_method_to_not_exist(object, method_name) end end def expect_method_to_not_exist(object, method_name) expect { object.method_name }.to raise_error(NoMethodError) # Commenting this out for now since this is broken. # See: btakita/rr #43 #expect(object).not_to respond_to(method_name) end def build_object_with_doubled_method_which_is_called(original_value, new_value=nil, opts={}, &define_double) method_name = :some_method object = build_object_with_methods(method_name => -> { original_value }) do |subject| double_creator = double_definition_creator_for(subject) if define_double define_double.call(double_creator, method_name, new_value) else double_creator.__send__(method_name) end end if opts[:before_method_call] opts[:before_method_call].call end return_value = object.__send__(method_name) [object, method_name, return_value] end def build_object_with_doubled_method_which_is_reset_and_called(original_value, new_value, opts={}) opts = opts.merge(before_method_call: -> { RR.reset }) build_object_with_doubled_method_which_is_called(original_value, new_value, opts) end def call_possible_method_on(object, method_name, *args, &block) object.__send__(method_name, *args, &block) rescue NoMethodError end def expect_call_to_return_or_raise_times_called_error(return_value, object, method_name, *args, &block) if supports_dont_allow? expect { object.__send__(method_name, *args, &block) }. to raise_error(RR::Errors::TimesCalledError) else expect(object.__send__(method_name, *args, &block)).to eq return_value end end def call_method_rescuing_times_called_error(object, method_name, *args, &block) if supports_dont_allow? begin object.__send__(method_name, *args, &block) rescue RR::Errors::TimesCalledError end else object.__send__(method_name, *args, &block) end end def methods_being_doubled_exist_already? self.class.methods_being_doubled_exist_already? end def type_of_methods_being_tested self.class.type_of_methods_being_tested end def supports_proxying? self.class.supports_proxying? end def supports_instance_of? self.class.supports_instance_of? end def supports_mocking? self.class.supports_mocking? end def supports_strong? self.class.supports_strong? end def supports_dont_allow? self.class.supports_dont_allow? end end rr-3.1.0/spec/suites/rspec_2/integration/0000755000004100000410000000000014265140426020320 5ustar www-datawww-datarr-3.1.0/spec/suites/rspec_2/integration/minitest_4_spec.rb0000644000004100000410000000574014265140426023744 0ustar www-datawww-datarequire File.expand_path('../../spec_helper', __FILE__) describe 'Integration with MiniTest 4' do include IntegrationTests::RubyMinitest def configure_project_generator(project_generator) super project_generator.configure do |project| project.minitest_version = 4 end end def self.including_the_adapter_manually_works specify "including the adapter manually works" do project = generate_project do |project| project.add_to_prelude <<-EOT class MiniTest::Unit::TestCase include RR::Adapters::MiniTest end EOT end project.add_test_file do |file| file.add_working_test_case_with_adapter_tests do |test_case| test_case.add_to_body <<-EOT def test_the_correct_adapters_are_loaded assert_adapters_loaded #{adapters_that_should_be_loaded.inspect} end EOT end end result = project.run_tests result.should be_success result.should_not have_errors_or_failures end end def self.rr_hooks_into_the_test_framework_automatically specify "RR hooks into the test framework automatically" do project = generate_project project.add_test_file do |file| file.add_working_test_case end result = project.run_tests result.should be_success result.should_not have_errors_or_failures end end context 'when Bundler is autorequiring RR' do def configure_project_generator(project_generator) super project_generator.configure do |project| project.autorequire_gems = true end end def adapters_that_should_be_loaded [:MiniTest4] end including_the_adapter_manually_works end context 'when RR is being required manually' do def configure_project_generator(project_generator) super project_generator.configure do |project| project.autorequire_gems = false end end def adapters_that_should_be_loaded [:MiniTest4] end rr_hooks_into_the_test_framework_automatically including_the_adapter_manually_works specify "when RR raises an error it raises a failure not an exception" do project = generate_project project.add_test_file do |file| file.add_test_case do |test_case| test_case.add_test <<-EOT object = Object.new mock(object).foo EOT end end result = project.run_tests result.should fail_with_output(/1 failure/) end specify "throwing an error in teardown doesn't mess things up" do project = generate_project project.add_test_file do |file| file.add_test_case do |test_case| test_case.add_to_body <<-EOT def teardown raise 'hell' end EOT test_case.add_test("") # doesn't matter end end result = project.run_tests result.should fail_with_output(/1 error/) end end end rr-3.1.0/spec/suites/rspec_2/integration/minitest_spec.rb0000644000004100000410000000574114265140426023522 0ustar www-datawww-datarequire File.expand_path('../../spec_helper', __FILE__) describe 'Integration with MiniTest >= 5' do include IntegrationTests::RubyMinitest def configure_project_generator(project_generator) super project_generator.configure do |project| project.minitest_version = 5 end end def self.including_the_adapter_manually_works specify "including the adapter manually works" do project = generate_project do |project| project.add_to_prelude <<-EOT class MiniTest::Unit::TestCase include RR::Adapters::MiniTest end EOT end project.add_test_file do |file| file.add_working_test_case_with_adapter_tests do |test_case| test_case.add_to_body <<-EOT def test_the_correct_adapters_are_loaded assert_adapters_loaded #{adapters_that_should_be_loaded.inspect} end EOT end end result = project.run_tests result.should be_success result.should_not have_errors_or_failures end end def self.rr_hooks_into_the_test_framework_automatically specify "RR hooks into the test framework automatically" do project = generate_project project.add_test_file do |file| file.add_working_test_case end result = project.run_tests result.should be_success result.should_not have_errors_or_failures end end context 'when Bundler is autorequiring RR' do def configure_project_generator(project_generator) super project_generator.configure do |project| project.autorequire_gems = true end end def adapters_that_should_be_loaded [:Minitest] end including_the_adapter_manually_works end context 'when RR is being required manually' do def configure_project_generator(project_generator) super project_generator.configure do |project| project.autorequire_gems = false end end def adapters_that_should_be_loaded [:Minitest] end rr_hooks_into_the_test_framework_automatically including_the_adapter_manually_works specify "when RR raises an error it raises a failure not an exception" do project = generate_project project.add_test_file do |file| file.add_test_case do |test_case| test_case.add_test <<-EOT object = Object.new mock(object).foo EOT end end result = project.run_tests result.should fail_with_output(/1 failure/) end specify "throwing an error in teardown doesn't mess things up" do project = generate_project project.add_test_file do |file| file.add_test_case do |test_case| test_case.add_to_body <<-EOT def teardown raise 'hell' end EOT test_case.add_test("") # doesn't matter end end result = project.run_tests result.should fail_with_output(/1 error/) end end end rr-3.1.0/spec/spec_suite_runner.rb0000644000004100000410000000216414265140426017210 0ustar www-datawww-dataclass SpecSuiteRunner attr_reader :suite def initialize(suite) @suite = suite end def call command = build_command if ENV['RR_DEBUG'] puts "Running: #{command}" end execute_command(command) end private def execute_command(command) system(command) status = $?.exitstatus OpenStruct.new(:success? => (status == 0)) end def build_command parts = ['env'] + build_env_pairs + ['ruby'] + build_file_list parts.join(" ") end def build_env_pairs # If `bundle exec rake` is run instead of just `rake`, Bundler will set # RUBYOPT to "-I -r bundler/setup". This is unfortunate as # it causes Bundler to be loaded before we load Bundler in # RR::Test.setup_test_suite, thereby rendering our second Bundler.setup a # no-op. env = suite.env.merge( 'BUNDLE_BIN_PATH' => '', 'BUNDLE_GEMFILE' => '', 'RUBYOPT' => '', 'ADAPTER' => suite.name ) env.map { |key, val| "#{key}=\"#{val}\"" } end def build_file_list Dir[ File.expand_path("../suites/#{suite.name}/{.,*,**}/*_spec.rb", __FILE__) ] end end rr-3.1.0/spec/support/0000755000004100000410000000000014265140426014640 5ustar www-datawww-datarr-3.1.0/spec/support/test_helper/0000755000004100000410000000000014265140426017156 5ustar www-datawww-datarr-3.1.0/spec/support/test_helper/rails_rspec.rb0000644000004100000410000000117714265140426022017 0ustar www-datawww-datarequire File.expand_path('../rails', __FILE__) module TestHelper module RailsRSpec include Rails def path File.join(project.directory, 'spec/spec_helper.rb') end def start_of_requires if project.rails_version == 2 Regexp.new(Regexp.escape(%q!require File.expand_path(File.join(File.dirname(__FILE__),'..','config','environment'))!)) else Regexp.new( Regexp.escape('require File.expand_path(') + %q/(?:"|')/ + Regexp.escape('../../config/environment') + %q/(?:"|')/ + Regexp.escape(', __FILE__)') ) end end end end rr-3.1.0/spec/support/test_helper/rails_minitest.rb0000644000004100000410000000020714265140426022530 0ustar www-datawww-datarequire File.expand_path('../rails_test_unit', __FILE__) module TestHelper module RailsMinitest include RailsTestUnit end end rr-3.1.0/spec/support/test_helper/minitest.rb0000644000004100000410000000016714265140426021343 0ustar www-datawww-datarequire File.expand_path('../test_unit', __FILE__) module TestHelper module Minitest include TestUnit end end rr-3.1.0/spec/support/test_helper/rails_test_unit.rb0000644000004100000410000000115414265140426022714 0ustar www-datawww-datarequire File.expand_path('../test_unit', __FILE__) require File.expand_path('../rails', __FILE__) module TestHelper module RailsTestUnit include TestUnit include Rails def start_of_requires if project.rails_version == 2 Regexp.new(Regexp.escape('require File.expand_path(File.dirname(__FILE__) + "/../config/environment")')) else Regexp.new( Regexp.escape('require File.expand_path(') + %q/(?:"|')/ + Regexp.escape('../../config/environment') + %q/(?:"|')/ + Regexp.escape(', __FILE__)') ) end end end end rr-3.1.0/spec/support/test_helper/rails.rb0000644000004100000410000000151514265140426020617 0ustar www-datawww-datamodule TestHelper module Rails def call super content = File.read(path) regexp = Regexp.new( '(' + start_of_requires.source + '.+?\n\n)', Regexp::MULTILINE ) requires = project.requires_with_rr(@requires) require_lines = project.require_lines(requires). map { |str| "#{str}\n" }. join unless content.gsub!(regexp, '\1' + require_lines + "\n") raise "Regexp didn't match!\nRegex: #{regexp}\nContent:\n#{content}" end content << "\n\n" + @prelude File.open(path, 'w') { |f| f.write(content) } if RR.debug? puts "~ Content of #{File.basename(path)} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" puts File.read(path) puts "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" end end end end rr-3.1.0/spec/support/test_helper/ruby.rb0000644000004100000410000000137714265140426020474 0ustar www-datawww-datamodule TestHelper module Ruby def call super File.open(path, 'w') do |f| content = <<-EOT require 'rubygems' require 'bundler' Bundler.setup Bundler.require(:default) EOT requires = project.requires_with_rr(@requires) require_lines = project.require_lines(requires). map { |str| "#{str}\n" }. join content << "\n" + require_lines + "\n" content << @prelude if RR.debug? puts "~ Content of #{File.basename(path)} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" puts content puts "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" end f.write(content) end end end end rr-3.1.0/spec/support/test_helper/rspec.rb0000644000004100000410000000017214265140426020617 0ustar www-datawww-datamodule TestHelper module RSpec def path File.join(project.directory, 'spec/spec_helper.rb') end end end rr-3.1.0/spec/support/test_helper/test_unit.rb0000644000004100000410000000017514265140426021524 0ustar www-datawww-datamodule TestHelper module TestUnit def path File.join(project.directory, 'test/test_helper.rb') end end end rr-3.1.0/spec/support/test_helper/generator.rb0000644000004100000410000000066714265140426021502 0ustar www-datawww-datarequire File.expand_path('../../generator', __FILE__) module TestHelper class Generator include ::Generator attr_reader :project, :requires, :prelude def setup(project) super @project = project @requires = [] @prelude = "" end def add_to_requires(path) @requires << path end def add_to_prelude(string) @prelude << string + "\n" end def call end end end rr-3.1.0/spec/support/adapter.rb0000644000004100000410000000054314265140426016607 0ustar www-datawww-datarequire 'appraisal/file' class Adapter attr_reader :name def initialize(name) @name = name end def appraisal_name parts = [] parts << 'ruby_19' parts << name parts.join('_') end def appraisal @appraisal ||= Appraisal::File.new.appraisals.find do |appraisal| appraisal.name == appraisal_name end end end rr-3.1.0/spec/support/test_file/0000755000004100000410000000000014265140426016616 5ustar www-datawww-datarr-3.1.0/spec/support/test_file/rails_rspec.rb0000644000004100000410000000033114265140426021446 0ustar www-datawww-datarequire File.expand_path('../rspec', __FILE__) module TestFile module RailsRSpec include RSpec # Don't require anything; this will happen in the spec helper def all_requires [] end end end rr-3.1.0/spec/support/test_file/rails_minitest.rb0000644000004100000410000000020514265140426022166 0ustar www-datawww-datarequire File.expand_path('../rails_test_unit', __FILE__) module TestFile module RailsMinitest include RailsTestUnit end end rr-3.1.0/spec/support/test_file/minitest.rb0000644000004100000410000000062014265140426020775 0ustar www-datawww-datarequire File.expand_path('../test_unit', __FILE__) module TestFile module Minitest include TestUnit def setup(project, index) super test_case_generator.configure do |test_case| test_case.superclass = if project.minitest_version == 5 'Minitest::Test' else 'MiniTest::Unit::TestCase' end end end end end rr-3.1.0/spec/support/test_file/rails_test_unit.rb0000644000004100000410000000112214265140426022347 0ustar www-datawww-datarequire File.expand_path('../test_unit', __FILE__) module TestFile module RailsTestUnit include TestUnit def setup(project, index) super self.directory = if project.rails_version == 4 File.join(project.directory, 'test', 'models') else File.join(project.directory, 'test', 'unit') end test_case_generator.configure do |test_case| test_case.superclass = 'ActiveSupport::TestCase' end end # Don't require anything; this will happen in the test helper def all_requires [] end end end rr-3.1.0/spec/support/test_file/rspec.rb0000644000004100000410000000147614265140426020267 0ustar www-datawww-datarequire File.expand_path('../../test_case/rspec', __FILE__) module TestFile module RSpec def setup(project, index) super test_case_generator.mixin TestCase::RSpec self.directory = File.join(project.directory, 'spec') end def content content = super <<-EOT + content require 'spec_helper' require '#{File.join(project.root_dir, 'spec/support/adapter_tests/rspec')}' EOT end def filename_prefix "#{"%02d" % @index}_spec" end # XXX: Do we need this if this is already in RSpecTestCase? def add_working_test_case_with_adapter_tests add_working_test_case do |test_case| test_case.add_to_before_tests <<-EOT include AdapterTests::RSpec EOT yield test_case if block_given? end end end end rr-3.1.0/spec/support/test_file/test_unit.rb0000644000004100000410000000170514265140426021164 0ustar www-datawww-datarequire File.expand_path('../../test_case/test_unit', __FILE__) module TestFile module TestUnit def setup(project, index) super test_case_generator.mixin TestCase::TestUnit self.directory = File.join(project.directory, 'test') test_case_generator.configure do |test_case| test_case.superclass = 'Test::Unit::TestCase' end end def content content = super <<-EOT + content require 'test_helper' require '#{File.join(project.root_dir, 'spec/support/adapter_tests/test_unit')}' EOT end def filename_prefix "#{"%02d" % @index}_test" end # XXX: Do we need this if this is already in TestUnitTestCase? def add_working_test_case_with_adapter_tests add_working_test_case do |test_case| test_case.add_to_before_tests <<-EOT include AdapterTests::TestUnit EOT yield test_case if block_given? end end end end rr-3.1.0/spec/support/test_file/generator.rb0000644000004100000410000000532114265140426021132 0ustar www-datawww-datarequire File.expand_path('../../generator', __FILE__) require File.expand_path('../../test_case/generator', __FILE__) module TestFile class Generator include ::Generator attr_accessor \ :include_rr_before_test_framework, :autorequire_gems, :directory attr_reader :project, :index, :prelude, :requires def setup(project, index) super @project = project self.include_rr_before_test_framework = project.include_rr_before_test_framework self.autorequire_gems = project.autorequire_gems @requires = [] @prelude = "" @index = index @body = "" end def add_to_requires(path) @requires << path end def add_to_prelude(string) @prelude << string + "\n" end def add_to_body(string) @body << string + "\n" end def add_test_case(content=nil, &block) if content.nil? test_case = test_case_generator.call(self, &block) content = test_case.string end @body << content + "\n" end def add_working_test_case add_test_case do |test_case| test_case.add_test <<-EOT object = Object.new mock(object).foo object.foo EOT yield test_case if block_given? end end def call path = File.join(directory, "#{filename_prefix}.rb") if RR.debug? puts "Test file path: #{path}" end File.open(path, 'w') do |f| if RR.debug? puts "~ Test file contents ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" puts content puts "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" end f.write(content) end end def test_case_generator @test_case_generator ||= TestCase::Generator.factory end def add_test_case_with_adapter_tests add_test_case do |test_case| test_case.include_adapter_tests yield test_case if block_given? end end def add_working_test_case add_test_case do |test_case| test_case.add_working_test yield test_case if block_given? end end def add_working_test_case_with_adapter_tests add_working_test_case do |test_case| test_case.include_adapter_tests yield test_case if block_given? end end private def all_requires project.requires_with_rr(requires) end def content prelude_lines = [] if @prelude prelude_lines << @prelude end require_lines = project.require_lines(all_requires) prelude_lines.concat(require_lines) join_lines(prelude_lines) + @body end def join_lines(lines) lines.map { |line| line + "\n" }.join end end end rr-3.1.0/spec/support/matchers/0000755000004100000410000000000014265140426016446 5ustar www-datawww-datarr-3.1.0/spec/support/matchers/be_a_subset_of_matcher.rb0000644000004100000410000000072314265140426023437 0ustar www-datawww-dataclass BeASubsetOfMatcher attr_reader :subset, :set def initialize(set) @set = set end def matches?(subset) @subset = subset (subset - set).empty? end def description "be a subset" end def failure_message_for_should "Expected to be a subset.\nSubset: #{subset.inspect}\nSet: #{set.inspect}" end def failure_message_for_should_not "Expected not to be a subset.\nSubset: #{subset.inspect}\nSet: #{set.inspect}" end end rr-3.1.0/spec/support/project/0000755000004100000410000000000014265140426016306 5ustar www-datawww-datarr-3.1.0/spec/support/project/test_unit_like.rb0000644000004100000410000000016314265140426021655 0ustar www-datawww-datamodule Project module TestUnitLike def test_runner_command ruby_command('rake test') end end end rr-3.1.0/spec/support/project/ruby_minitest.rb0000644000004100000410000000042014265140426021524 0ustar www-datawww-datarequire File.expand_path('../ruby', __FILE__) require File.expand_path('../minitest', __FILE__) require File.expand_path('../ruby_test_unit_like', __FILE__) module Project module RubyMinitest include Ruby include Minitest include RubyTestUnitLike end end rr-3.1.0/spec/support/project/rails_rspec.rb0000644000004100000410000000216414265140426021144 0ustar www-datawww-datarequire File.expand_path('../rspec', __FILE__) require File.expand_path('../rails', __FILE__) require File.expand_path('../../test_file/rails_rspec', __FILE__) require File.expand_path('../../test_helper/rails_rspec', __FILE__) module Project module RailsRSpec include RSpec include Rails def setup super test_file_generator.mixin TestFile::RailsRSpec test_helper_generator.mixin TestHelper::RailsRSpec end def configure super gem_dependencies << gem_dependency( :name => 'rspec-rails', :version => rspec_gem_version, :group => [:development, :test] ) add_to_test_requires(rspec_rails_path) end def generate_skeleton super run_command_within!(generate_rspec_command) end private def rspec_rails_path if rails_version == 2 'spec/rails' else 'rspec/rails' end end def generate_rspec_command if rails_version == 2 ruby_command('script/generate rspec --skip') else ruby_command('rails generate rspec:install --skip') end end end end rr-3.1.0/spec/support/project/rails_test_unit_like.rb0000644000004100000410000000075414265140426023055 0ustar www-datawww-datarequire File.expand_path('../test_unit_like', __FILE__) require File.expand_path('../rails', __FILE__) require File.expand_path('../../test_file/rails_test_unit', __FILE__) require File.expand_path('../../test_helper/rails_test_unit', __FILE__) module Project module RailsTestUnitLike include TestUnitLike include Rails def setup super test_file_generator.mixin TestFile::RailsTestUnit test_helper_generator.mixin TestHelper::RailsTestUnit end end end rr-3.1.0/spec/support/project/rails_minitest.rb0000644000004100000410000000073414265140426021665 0ustar www-datawww-datarequire File.expand_path('../minitest', __FILE__) require File.expand_path('../rails', __FILE__) require File.expand_path('../../test_file/rails_minitest', __FILE__) require File.expand_path('../../test_helper/rails_minitest', __FILE__) module Project module RailsMinitest include Minitest include Rails def setup super test_file_generator.mixin TestFile::RailsMinitest test_helper_generator.mixin TestHelper::RailsMinitest end end end rr-3.1.0/spec/support/project/minitest.rb0000644000004100000410000000174414265140426020475 0ustar www-datawww-datarequire File.expand_path('../test_unit_like', __FILE__) require File.expand_path('../../test_file/minitest', __FILE__) require File.expand_path('../../test_helper/minitest', __FILE__) module Project module Minitest include TestUnitLike attr_accessor :minitest_version def configure super if minitest_version gem_dependencies << gem_dependency( :name => 'minitest', :version => minitest_gem_version ) end add_to_test_requires 'minitest/autorun' end def setup super test_file_generator.mixin TestFile::Minitest test_helper_generator.mixin TestHelper::Minitest end private def minitest_gem_version case minitest_version when 4 then '~> 4.0' when 5 then '~> 5.0' when nil then raise ArgumentError, "minitest_version isn't set!" else raise ArgumentError, "Invalid Minitest version '#{minitest_version}'" end end end end rr-3.1.0/spec/support/project/tests_runner.rb0000644000004100000410000000071714265140426021373 0ustar www-datawww-datamodule Project class TestsRunner def self.call(project) runner = new(project) yield runner if block_given? runner.call end attr_reader :project attr_accessor :command def initialize(project) @project = project self.command = project.test_runner_command end def call match = command.match(/^((?:\w+=[^ ]+ )*)(.+)$/) project.run_command_within(match[2], :env => match[1]) end end end rr-3.1.0/spec/support/project/rails_test_unit.rb0000644000004100000410000000073714265140426022052 0ustar www-datawww-datarequire File.expand_path('../test_unit', __FILE__) require File.expand_path('../rails', __FILE__) require File.expand_path('../../test_file/rails_test_unit', __FILE__) require File.expand_path('../../test_helper/rails_test_unit', __FILE__) module Project module RailsTestUnit include TestUnit include Rails def setup super test_file_generator.mixin TestFile::RailsTestUnit test_helper_generator.mixin TestHelper::RailsTestUnit end end end rr-3.1.0/spec/support/project/ruby_test_unit.rb0000644000004100000410000000042114265140426021707 0ustar www-datawww-datarequire File.expand_path('../ruby_test_unit_like', __FILE__) require File.expand_path('../test_unit', __FILE__) require File.expand_path('../ruby', __FILE__) module Project module RubyTestUnit include RubyTestUnitLike include TestUnit include Ruby end end rr-3.1.0/spec/support/project/ruby_test_unit_like.rb0000644000004100000410000000060414265140426022716 0ustar www-datawww-datamodule Project module RubyTestUnitLike def setup super add_file 'Rakefile', <<-EOT require 'rake/testtask' Rake::TestTask.new do |t| t.libs << 'test' t.test_files = FileList['test/*_test.rb'] end EOT end def generate_skeleton super FileUtils.mkdir_p File.join(directory, 'test') end end end rr-3.1.0/spec/support/project/rails.rb0000644000004100000410000001271714265140426017755 0ustar www-datawww-datarequire File.expand_path('../../test_helper/generator', __FILE__) module Project module Rails attr_accessor :rails_version def add_model_and_migration(model_name, table_name, attributes) model_class_name = model_name.to_s.capitalize symbolized_attribute_names = attributes.keys.map {|v| ":#{v}" }.join(', ') migration_timestamp = Time.now.strftime("%Y%m%d%H%M%S") camelized_table_name = table_name.to_s.capitalize migration_column_definitions = attributes.map do |name, type| "t.#{type} :#{name}" end.join("\n") model_content = "class #{model_class_name} < ActiveRecord::Base\n" if rails_version == 3 model_content << "attr_accessible #{symbolized_attribute_names}\n" end model_content << "end\n" add_file "app/models/#{model_name}.rb", model_content add_file "db/migrate/#{migration_timestamp}_create_#{table_name}.rb", <<-EOT class Create#{camelized_table_name} < ActiveRecord::Migration def #{'self.' if rails_version == 2}up create_table :#{table_name} do |t| #{migration_column_definitions} end end def #{'self.' if rails_version == 2}down drop_table :#{table_name} end end EOT end def gem_dependency(dep) dep = dep.dup dep[:version] ||= '>= 0' groups = Array(dep[:group] || []) groups << :test unless groups.include?(:test) dep[:group] = groups dep end def sqlite_adapter under_jruby? ? 'jdbcsqlite3' : 'sqlite3' end def database_file_path File.join(directory, 'db/test.sqlite3') end def test_helper_generator @test_helper_generator ||= TestHelper::Generator.factory end private def generate_skeleton super create_rails_app within do if rails_version == 2 add_bundler_support fix_obsolete_reference_to_rdoctask_in_rakefile monkeypatch_gem_source_index end if under_jruby? && rails_version == 4 update_activerecord_jdbc_adapter_to_beta_version end declare_and_install_gems create_files configure_database run_migrations end end def create_rails_app # remember that this has to be run with `bundle exec` to catch the correct # 'rails' executable (rails 3 or rails 4)! run_command! create_rails_app_command, :without_bundler_sandbox => true end def create_rails_app_command command = 'rails' if rails_version == 2 command << " #{directory}" else command << " new #{directory} --skip-bundle" end ruby_command(command) end def add_bundler_support create_file 'config/patch_bundler_into_rails_23.rb', <<'EOT' class Rails::Boot def run load_initializer Rails::Initializer.class_eval do def load_gems @bundler_loaded ||= Bundler.require :default, Rails.env end end Rails::Initializer.run(:set_load_path) end end EOT add_in_file_before 'config/boot.rb', "Rails.boot!\n", <<-EOT load File.expand_path('../patch_bundler_into_rails_23.rb', __FILE__) EOT create_file 'config/preinitializer.rb', <<'EOT' begin require 'rubygems' require 'bundler' rescue LoadError raise "Could not load the bundler gem. Install it with `gem install bundler`." end if Gem::Version.new(Bundler::VERSION) <= Gem::Version.new("0.9.24") raise RuntimeError, "Your bundler version is too old for Rails 2.3.\n" + "Run `gem install bundler` to upgrade." end begin # Set up load paths for all bundled gems ENV["BUNDLE_GEMFILE"] = File.expand_path("../../Gemfile", __FILE__) Bundler.setup rescue Bundler::GemNotFound raise RuntimeError, "Bundler couldn't find some gems.\n" + "Did you run `bundle install`?" end EOT create_file 'Gemfile', <<'EOT' source 'https://rubygems.org' gem 'rails', '~> 2.3.0' gem 'sqlite3-ruby', :require => 'sqlite3' gem 'rdoc' EOT end def monkeypatch_gem_source_index create_file 'config/rubygems_patch.rb', File.read(File.expand_path('../../../fixtures/rubygems_patch_for_187.rb', __FILE__)), :without_debug => true # http://djellemah.com/blog/2013/02/27/rails-23-with-ruby-20/ add_in_file_before 'config/boot.rb', "Rails.boot!\n", <<-EOT Rails::GemBoot.module_eval do class << self alias :original_load_rubygems :load_rubygems def load_rubygems original_load_rubygems load File.expand_path('../rubygems_patch.rb', __FILE__) end end end EOT end def fix_obsolete_reference_to_rdoctask_in_rakefile replace_in_file 'Rakefile', 'rake/rdoctask', 'rdoc/task' end def update_activerecord_jdbc_adapter_to_beta_version # The latest version of activerecord-jdbcsqlite3-adapter is not quite # compatible with Rails 4 -- see: # replace_in_file 'Gemfile', "gem 'activerecord-jdbcsqlite3-adapter'\n", "gem 'activerecord-jdbcsqlite3-adapter', '1.3.0.beta2'\n" end def configure_database create_file 'config/database.yml', < 'cucumber-rails', :version => cucumber_gem_version, :require => false ) if rails_version == 2 gem_dependencies << gem_dependency( :name => 'capybara', :version => '~> 0.4.0' ) # 1.5.0 is only compatible with >= 1.9.2 gem_dependencies << gem_dependency( :name => 'nokogiri', :version => '~> 1.4.0' ) end gem_dependencies << gem_dependency( :name => 'database_cleaner' ) end def generate_skeleton super if rails_version == 2 run_command_within! ruby_command('script/generate cucumber --capybara --backtrace') else run_command_within! ruby_command('rails generate cucumber:install') end end def test_runner_command 'cucumber' end private def cucumber_gem_version if rails_version == 2 '~> 0.3.2' else '~> 1.3.1' end end end end rr-3.1.0/spec/support/project/rspec.rb0000644000004100000410000000274514265140426017757 0ustar www-datawww-datarequire File.expand_path('../../test_file/rspec', __FILE__) require File.expand_path('../../test_helper/rspec', __FILE__) module Project module RSpec attr_accessor :rspec_version def setup super test_file_generator.mixin TestFile::RSpec test_helper_generator.mixin TestHelper::RSpec end def configure super gem_dependencies << gem_dependency( :name => 'rspec', :version => rspec_gem_version ) add_to_test_requires(rspec_autorun_path) add_file(rspec_options_filename, dot_rspec_content) end def test_runner_command ruby_command('rake spec') end private def rspec_gem_version case rspec_version when 2 then '~> 2.13' when 1 then '~> 1.3' when nil then raise ArgumentError, "rspec_version isn't set!" else raise ArgumentError, "Invalid RSpec version '#{rspec_version}'" end end def rspec_autorun_path if rspec_version == 1 'spec/autorun' else 'rspec/autorun' end end def rspec_options_filename if rspec_version == 1 'spec/spec.opts' else '.rspec' end end def dot_rspec_content lines = [] lines << '--color' if rspec_version == 1 lines << '--format nested' else lines << '--format documentation' end if RR.debug? lines << '--backtrace' end lines.join("\n") end end end rr-3.1.0/spec/support/project/test_unit.rb0000644000004100000410000000135414265140426020654 0ustar www-datawww-datarequire File.expand_path('../test_unit_like', __FILE__) require File.expand_path('../../test_file/test_unit', __FILE__) require File.expand_path('../../test_helper/test_unit', __FILE__) module Project module TestUnit include TestUnitLike attr_accessor :test_unit_gem_version def configure super if test_unit_gem_version gem_dependencies << gem_dependency( :name => 'test-unit', :version => test_unit_gem_version ) end add_to_test_requires 'test/unit'#, :using_gem_original_require => test_unit_gem_version.nil? end def setup super test_file_generator.mixin TestFile::TestUnit test_helper_generator.mixin TestHelper::TestUnit end end end rr-3.1.0/spec/support/project/generator.rb0000644000004100000410000002165414265140426020631 0ustar www-datawww-datarequire File.expand_path('../../generator', __FILE__) require File.expand_path('../../test_file/generator', __FILE__) require File.expand_path('../../test_helper/generator', __FILE__) require File.expand_path('../../command_runner', __FILE__) require File.expand_path('../tests_runner', __FILE__) require 'tempfile' module Project class Generator include ::Generator attr_accessor \ :autorequire_gems, :include_rr_before_test_framework attr_reader \ :gem_dependencies, :test_requires, :prelude def setup super self.autorequire_gems = false self.include_rr_before_test_framework = false @gem_dependencies = [] @test_requires = [] @number_of_test_files = 0 @prelude = "" @files_to_add = [] end def root_dir File.expand_path('../../../..', __FILE__) end def lib_dir File.join(root_dir, 'lib') end def directory File.join(root_dir, 'tmp', 'rr-integration-tests', 'test_project') end def bundle_dir File.join(directory, '.bundle') end def test_filename raise NotImplementedError end def test_runner_command raise NotImplementedError end def call FileUtils.rm_rf directory FileUtils.mkdir_p File.dirname(directory) generate_skeleton test_helper_generator.call(self) end def add_to_prelude(string) test_helper_generator.configure do |file| file.add_to_prelude(string) end end def add_to_test_requires(path) test_helper_generator.configure do |file| file.add_to_requires(path) end end def add_test_file(&block) test_file_generator.call(self, @number_of_test_files, &block) @number_of_test_files += 1 end def run_tests TestsRunner.call(self) end def declare_and_install_gems declare_gems_within_gemfile install_gems_via_bundler end def declare_gems_within_gemfile append_to_file 'Gemfile', "\n\n#{build_gem_list}" end def install_gems_via_bundler # XXX: This will fail if some gems are not available! #if RR.debug? # run_command! "#{bundle_executable} env" #end run_command! ruby_command('bundle check || bundle install') end def within(&block) ret = nil Dir.chdir(directory) { ret = block.call } ret end def exec(command) CommandRunner.call(command) end def exec!(command) result = exec(command) if not result.success? raise "Command failed: #{command}" end result end def run_command(command, opts={}) f = Tempfile.new('rr-integration-test-file') contents = "" unless opts[:without_bundler_sandbox] # Bundler will set RUBYOPT to "-I -r bundler/setup". # This is unfortunate as it causes Bundler to be loaded before we # load Bundler in RR::Test.setup_test_suite, thereby rendering our # second Bundler.setup a no-op. contents << <<-EOT export BUNDLE_BIN_PATH="" export BUNDLE_GEMFILE="" export RUBYOPT="" EOT end if opts[:env] opts[:env].split(' ').each do |pair| contents << "export #{pair}\n" end end contents << <<-EOT #{format_command(command)} exit $? EOT if RR.debug? puts "~ File to run ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" puts contents puts "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" end f.write(contents) f.close exec("bash #{f.path}") ensure f.unlink if f end def run_command!(command, opts={}) result = run_command(command, opts) if not result.success? raise "Command failed: #{command}" end result end def run_command_within(command, opts={}) within { run_command(command, opts) } end def run_command_within!(command, opts={}) within { run_command!(command, opts) } end def format_command(command) if command =~ /^bundle/ command else "bundle exec #{command}" end end def add_file(file_name, content) @files_to_add << [file_name, content] end def build_gem_list gem_dependencies_with_rr. map { |dep| gem_dependency_line(dep) }. join("\n") end def test_file_generator @test_file_generator ||= TestFile::Generator.factory end def requires_with_rr(requires) requires = requires.dup unless autorequire_gems if include_rr_before_test_framework requires.unshift 'rr' else requires.push 'rr' end end requires end def require_lines(requires) requires.map { |path| "require '#{path}'" } end def test_helper_generator @test_helper_generator ||= TestHelper::Generator.factory end private def generate_skeleton end def create_files @files_to_add.each do |file_name, content| full_file_name = File.join(directory, file_name) FileUtils.mkdir_p File.dirname(full_file_name) create_file full_file_name, content end end def create_link(filename, dest_filename = filename) FileUtils.ln_sf(File.join(root_dir, filename), File.join(directory, dest_filename)) end def copy_file(filename, dest_filename = filename) FileUtils.cp(File.join(root_dir, filename), File.join(directory, dest_filename)) end def create_file(filename, content, opts={}) File.open(filename, 'w') do |f| if RR.debug? && !opts[:without_debug] puts "~ Adding file #{filename} ~~~~~~~~~~~~~~~~~~~~~~~~" puts content puts "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" end f.write(content) end end def replace_in_file(filename, search, replace) content = File.read(filename) content.sub!(search, replace) File.open(filename, 'w') { |f| f.write(content) } if RR.debug? puts "~ #{filename} is now: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" puts File.read(filename) puts "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" end end def append_to_file(filename, additional_content) content = File.read(filename) File.open(filename, 'w') do |f| f.write(content + additional_content) end if RR.debug? puts "~ #{filename} is now: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" puts File.read(filename) puts "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" end end def prepend_to_file(filename, additional_content) content = File.read(filename) File.open(filename, 'w') do |f| f.write(additional_content + content) end if RR.debug? puts "~ #{filename} is now: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" puts File.read(filename) puts "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" end end def add_in_file_before(filename, search, additional_content) content = File.read(filename) content.insert(content.index(search), additional_content) File.open(filename, 'w') { |f| f.write(content) } if RR.debug? puts "~ #{filename} is now: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" puts File.read(filename) puts "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" end end def add_in_file_after(filename, search, additional_content) content = File.read(filename) content.insert(content.index(search) + search.length, additional_content) File.open(filename, 'w') { |f| f.write(content) } if RR.debug? puts "~ #{filename} is now: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" puts File.read(filename) puts "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" end end def under_jruby? RUBY_PLATFORM =~ /java/ end def gem_dependency(dep) dep end def gem_dependency_line(dep) dep = dep.dup name = dep.delete(:name) version = dep.delete(:version) "gem #{name.to_s.inspect}, #{version.inspect}, #{dep.inspect}" end def gem_dependencies_with_rr if RR.debug? puts "Include RR before test framework? #{include_rr_before_test_framework.inspect}" puts "Autorequiring gems? #{autorequire_gems.inspect}" end dependencies = gem_dependencies.dup rr_dep = {:name => 'rr', :path => root_dir, :version => RR.version} rr_dep[:require] = false unless autorequire_gems rr_dep = gem_dependency(rr_dep) if include_rr_before_test_framework dependencies.unshift(rr_dep) else dependencies.push(rr_dep) end dependencies end def ruby_command(command) command end end end rr-3.1.0/spec/support/test.sqlite30000644000004100000410000000000014265140426017113 0ustar www-datawww-datarr-3.1.0/spec/support/adapter_tests/0000755000004100000410000000000014265140426017502 5ustar www-datawww-datarr-3.1.0/spec/support/adapter_tests/base.rb0000644000004100000410000000210114265140426020733 0ustar www-datawww-datarequire 'set' module AdapterTests module Base private def assert_stubs_work subject = Object.new stub(subject).foobar { :baz } assert_equal :baz, subject.foobar("any", "thing") end def assert_mocks_work subject = Object.new mock(subject).foobar(1, 2) { :baz } assert_equal :baz, subject.foobar(1, 2) end def assert_stub_proxies_work subject = Object.new def subject.foobar; :baz; end stub.proxy(subject).foobar assert_equal :baz, subject.foobar end def assert_mock_proxies_work subject = Object.new def subject.foobar; :baz; end mock.proxy(subject).foobar assert_equal :baz, subject.foobar end def assert_times_called_verifications_work subject = Object.new mock(subject).foobar(1, 2) { :baz } assert_raises RR::Errors.error_class(:TimesCalledError) do RR.verify end end def assert_adapters_loaded(matching_adapters) assert_subset Set.new(matching_adapters), Set.new(RR.loaded_adapter_names) end end end rr-3.1.0/spec/support/adapter_tests/minitest.rb0000644000004100000410000000017114265140426021662 0ustar www-datawww-datarequire File.expand_path('../test_unit', __FILE__) module AdapterTests module Minitest include TestUnit end end rr-3.1.0/spec/support/adapter_tests/rspec.rb0000644000004100000410000000314614265140426021147 0ustar www-datawww-datarequire File.expand_path('../base', __FILE__) require File.expand_path('../../matchers/be_a_subset_of_matcher', __FILE__) module AdapterTests module RSpec include Base def self.included(base) base.class_eval do specify 'stubs work' do assert_stubs_work end specify 'mocks work' do assert_mocks_work end specify 'stub proxies work' do assert_stub_proxies_work end specify 'mock proxies work' do assert_mock_proxies_work end specify 'times-called verifications work' do assert_times_called_verifications_work end specify 'have_received works' do subject = Object.new stub(subject).foobar(1, 2) subject.foobar(1, 2) subject.should have_received.foobar(1, 2) expect { subject.should have_received.foobar(1, 2, 3) }.to raise_error( expectation_not_met_error, /Expected foobar\(1, 2, 3\).+to be called 1 time/m ) end end end def expectation_not_met_error if defined?(::RSpec) ::RSpec::Expectations::ExpectationNotMetError else Spec::Expectations::ExpectationNotMetError end end def assert_equal(expected, actual) expected.should be == actual end def assert_subset(subset, set) subset.should be_a_subset_of(set) end def assert_raises(error, &block) expect(&block).to raise_error(error) end def be_a_subset_of(set) BeASubsetOfMatcher.new(set) end end end rr-3.1.0/spec/support/adapter_tests/test_unit.rb0000644000004100000410000000212114265140426022041 0ustar www-datawww-datarequire File.expand_path('../base', __FILE__) module AdapterTests module TestUnit include Base def test_that_stubs_work assert_stubs_work end def test_that_mocks_work assert_mocks_work end def test_that_stub_proxies_work assert_stub_proxies_work end def test_that_mock_proxies_work assert_mock_proxies_work end def test_that_times_called_verifications_work assert_times_called_verifications_work end def test_using_assert_received subject = Object.new stub(subject).foobar(1, 2) subject.foobar(1, 2) assert_received(subject) {|s| s.foobar(1, 2) } error_class = RR::Errors.error_class( RR::Errors::SpyVerificationErrors::InvocationCountError ) assert_raises(error_class) do assert_received(subject) {|s| s.foobar(1, 2, 3) } end end def assert_subset(subset, set) value = (subset - set).empty? message = "Set 1 was not a subset of set 2.\nSet 1: #{subset.inspect}\nSet 2: #{set.inspect}" assert value, message end end end rr-3.1.0/spec/support/integration_tests/0000755000004100000410000000000014265140426020405 5ustar www-datawww-datarr-3.1.0/spec/support/integration_tests/ruby_minitest.rb0000644000004100000410000000045214265140426023630 0ustar www-datawww-datarequire File.expand_path('../ruby', __FILE__) require File.expand_path('../../project/ruby_minitest', __FILE__) module IntegrationTests module RubyMinitest include Ruby def configure_project_generator(generator) super generator.mixin Project::RubyMinitest end end end rr-3.1.0/spec/support/integration_tests/rails_rspec.rb0000644000004100000410000000044614265140426023244 0ustar www-datawww-datarequire File.expand_path('../rails', __FILE__) require File.expand_path('../../project/rails_rspec', __FILE__) module IntegrationTests module RailsRSpec include Rails def configure_project_generator(generator) super generator.mixin Project::RailsRSpec end end end rr-3.1.0/spec/support/integration_tests/rails_test_unit_like.rb0000644000004100000410000000047514265140426025154 0ustar www-datawww-datarequire File.expand_path('../rails', __FILE__) require File.expand_path('../../project/rails_test_unit_like', __FILE__) module IntegrationTests module RailsTestUnitLike include Rails def configure_project_generator(generator) super generator.mixin Project::RailsTestUnitLike end end end rr-3.1.0/spec/support/integration_tests/base.rb0000644000004100000410000000320414265140426021643 0ustar www-datawww-datarequire File.expand_path('../../project/generator', __FILE__) module IntegrationTests module Base class FailWithOutputMatcher < Struct.new(:pattern) def matches?(result) result.output =~ pattern end def description "fail with output #{pattern.inspect}" end def failure_message_for_should "Expected running the test to produce output #{pattern.inspect} but it didn't" end def failure_message_for_should_not "Expected running the test to not produce output #{pattern.inspect} but it did" end end class HaveErrorsOrFailuresMatcher def matches?(result) match = result.output.match(/(\d+) error|(\d+) failure/) match && match.captures.any? {|value| value && value.to_i > 0 } end def description "have errors or failures" end def failure_message_for_should "Expected running the test to result in errors or failures but it did not" end def failure_message_for_should_not "Expected running the test to not result in errors or failures, but it did " end end def build_project_generator Project::Generator.factory do |project_generator| configure_project_generator(project_generator) yield project_generator if block_given? end end def generate_project(&block) build_project_generator.call(&block) end def configure_project_generator(generator) end def fail_with_output(pattern) FailWithOutputMatcher.new(pattern) end def have_errors_or_failures HaveErrorsOrFailuresMatcher.new end end end rr-3.1.0/spec/support/integration_tests/rails_minitest.rb0000644000004100000410000000045714265140426023766 0ustar www-datawww-datarequire File.expand_path('../rails', __FILE__) require File.expand_path('../../project/rails_minitest', __FILE__) module IntegrationTests module RailsMinitest include Rails def configure_project_generator(generator) super generator.mixin Project::RailsMinitest end end end rr-3.1.0/spec/support/integration_tests/rails_test_unit.rb0000644000004100000410000000046014265140426024142 0ustar www-datawww-datarequire File.expand_path('../rails', __FILE__) require File.expand_path('../../project/rails_test_unit', __FILE__) module IntegrationTests module RailsTestUnit include Rails def configure_project_generator(generator) super generator.mixin Project::RailsTestUnit end end end rr-3.1.0/spec/support/integration_tests/ruby_test_unit.rb0000644000004100000410000000045314265140426024013 0ustar www-datawww-datarequire File.expand_path('../ruby', __FILE__) require File.expand_path('../../project/ruby_test_unit', __FILE__) module IntegrationTests module RubyTestUnit include Ruby def configure_project_generator(generator) super generator.mixin Project::RubyTestUnit end end end rr-3.1.0/spec/support/integration_tests/rails.rb0000644000004100000410000000337014265140426022047 0ustar www-datawww-datarequire File.expand_path('../base', __FILE__) require File.expand_path('../../project/rails', __FILE__) module IntegrationTests module Rails class LeaveDatabaseTableClearMatcher < Struct.new(:project, :table_name) def matches?(block) @old_number_of_rows = number_of_rows block.call @new_number_of_rows = number_of_rows @old_number_of_rows == 0 && @new_number_of_rows == 0 end def description "leave the database table #{table_name} unchanged" end def failure_message_for_should "Expected for database table #{table_name} to have been left clear, but it was changed (there are now #{@new_number_of_rows} rows)" end def failure_message_for_should_not "Expected for database table #{table_name} to not have been left clear, but it was" end private def number_of_rows result = project.exec!("echo 'select count(*) from #{table_name};' | sqlite3 #{project.database_file_path}") result.output.chomp.to_i end end include Base def configure_project_generator(project_generator) super configure_rails_project_generator(project_generator) end def build_rails_project_generator Project::Generator.factory do |project_generator| configure_rails_project_generator(project_generator) yield project_generator if block_given? end end def generate_rails_project(&block) build_rails_project_generator.call(&block) end def configure_rails_project_generator(project_generator) project_generator.mixin Project::Rails end def leave_database_table_clear(project, table_name) LeaveDatabaseTableClearMatcher.new(project, table_name) end end end rr-3.1.0/spec/support/integration_tests/ruby_rspec.rb0000644000004100000410000000044114265140426023106 0ustar www-datawww-datarequire File.expand_path('../ruby', __FILE__) require File.expand_path('../../project/ruby_rspec', __FILE__) module IntegrationTests module RubyRSpec include Ruby def configure_project_generator(generator) super generator.mixin Project::RubyRSpec end end end rr-3.1.0/spec/support/integration_tests/ruby.rb0000644000004100000410000000016014265140426021710 0ustar www-datawww-datarequire File.expand_path('../base', __FILE__) module IntegrationTests module Ruby include Base end end rr-3.1.0/spec/support/test_case/0000755000004100000410000000000014265140426016612 5ustar www-datawww-datarr-3.1.0/spec/support/test_case/minitest.rb0000644000004100000410000000035614265140426020777 0ustar www-datawww-datarequire File.expand_path('../test_unit', __FILE__) module TestCase module Minitest include TestUnit def include_adapter_tests add_to_before_tests <<-EOT include AdapterTests::Minitest EOT end end end rr-3.1.0/spec/support/test_case/rspec.rb0000644000004100000410000000055314265140426020256 0ustar www-datawww-datamodule TestCase module RSpec def include_adapter_tests add_to_before_tests <<-EOT include AdapterTests::RSpec EOT end private def start_of_test_case "describe 'A test case' do" end def build_test(index, body) ["it 'is test ##{index}' do", body, "end"].map { |line| line + "\n" }.join end end end rr-3.1.0/spec/support/test_case/test_unit.rb0000644000004100000410000000061414265140426021156 0ustar www-datawww-datamodule TestCase module TestUnit attr_accessor :superclass def include_adapter_tests add_to_before_tests <<-EOT include AdapterTests::TestUnit EOT end private def start_of_test_case "class FooTest < #{superclass}" end def build_test(index, body) ["def test_#{index}", body, "end"].map { |line| line + "\n" }.join end end end rr-3.1.0/spec/support/test_case/generator.rb0000644000004100000410000000200114265140426021116 0ustar www-datawww-datarequire File.expand_path('../../generator', __FILE__) module TestCase class Generator include ::Generator attr_reader :test_file, :string def setup(test_file) super @test_file = test_file @prelude = "" @before_tests = "" @body = "" @number_of_tests = 0 end def add_to_prelude(string) @prelude << string + "\n" end def add_to_before_tests(content) @before_tests << content + "\n" end def add_to_body(content) @body << content + "\n" end def add_test(body) @body << build_test(@number_of_tests, body) + "\n" @number_of_tests += 1 end def add_working_test add_test <<-EOT object = Object.new mock(object).foo object.foo EOT end def call lines = [] lines << @prelude lines << start_of_test_case lines << @before_tests lines << @body lines << "end" @string = lines.map { |line| line + "\n" }.join end end end rr-3.1.0/spec/support/command_runner.rb0000644000004100000410000000433214265140426020176 0ustar www-datawww-datarequire 'open3' class CommandRunner # http://stackoverflow.com/questions/6407141/how-can-i-have-ruby-logger-log-output-to-stdout-as-well-as-file class MultiIO def initialize(*targets) @targets = targets end def write(*args) @targets.each {|t| t.write(*args) } end alias_method :<<, :write def close @targets.each(&:close) end end def self.call(command, options={}) new(command, options).call end attr_reader :command, :output, :exit_status def initialize(command, options) @command = command #@command << " 2>&1" unless @command =~ / 2>&1$/ @output = "" end def call @stdout_buffer = StringIO.new puts "Running: #{@command}" if defined?(JRUBY_VERSION) call_using_popen4 else call_using_spawn end if RR.debug? puts "~ Output from `#{@command}` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" puts @output puts "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" end self end def success? @exit_status == 0 end private def call_using_session reader, writer = IO.pipe require 'session' session = Session::Bash.new session.execute(@command, :stdout => writer, :stderr => writer) writer.close @exit_status = session.exit_status @output = reader.read end def call_using_popen4 reader, writer = IO.pipe # Using popen4 here without a block will always result in an Errno::ECHILD # error under JRuby: block = lambda { |pid, _, stdout, _| writer.write(stdout.read) } if defined?(JRUBY_VERSION) IO.popen4("#{@command} 2>&1", &block) else require 'open4' Open4.popen4("#{@command} 2>&1", &block) end writer.close @exit_status = $?.exitstatus @output = reader.read end def call_using_spawn reader, writer = IO.pipe args = [@command, {[:out, :err] => writer}] require 'posix-spawn' pid = POSIX::Spawn.spawn(*args) Process.waitpid(pid) writer.close @exit_status = $?.exitstatus @output = reader.read end def build_stdout ios = [@stdout_buffer] #if RR.debug? # ios << $stdout #end MultiIO.new(*ios) end end rr-3.1.0/spec/support/generator.rb0000644000004100000410000000155314265140426017157 0ustar www-datawww-datamodule Generator module ClassMethods attr_reader :configurators def factory klass = Class.new(self) yield klass if block_given? klass end def call(*args, &block) new(*args, &block).tap { |object| object.call } end def generate(&block) factory.call(&block) end def mixin(mod) include mod end def configure(&block) configurators << block end def configurators @configurators ||= [] end end def self.included(base) base.extend(ClassMethods) end def initialize(*args) setup(*args) run_configurators configure(*args) yield self if block_given? end def setup(*args) end def configure(*args) end private def run_configurators self.class.configurators.each do |configurator| configurator.call(self) end end end rr-3.1.0/spec/defines_spec_suite_tasks.rb0000644000004100000410000000301014265140426020510 0ustar www-datawww-datarequire File.expand_path('../spec_suite_configuration', __FILE__) require 'ostruct' class DefinesSpecSuiteTasks extend Rake::DSL def self.configuration @configuration ||= SpecSuiteConfiguration.build end def self.call desc 'Run all tests' task :spec do results = [] DefinesSpecSuiteTasks.configuration.each_matching_suite.each do |suite| puts "=== Running #{suite.desc} tests ================================================" results << suite.run puts end if results.any? { |result| not result.success? } raise 'Spec suite failed!' end end namespace :spec do DefinesSpecSuiteTasks.configuration.each_matching_suite do |suite| desc "Run #{suite.desc} tests" task suite.name => "appraisal:#{suite.appraisal_name}:install" do result = suite.run if not result.success? raise "#{suite.desc} suite failed!" end end end require 'rspec/core/rake_task' desc "Run the unit tests" RSpec::Core::RakeTask.new(:unit) do |t| t.pattern = 'spec/suites/rspec_2/unit/**/*_spec.rb' end desc "Run the functional (API) tests" RSpec::Core::RakeTask.new(:functional) do |t| t.pattern = 'spec/suites/rspec_2/functional/**/*_spec.rb' end end namespace :travis do desc 'Regenerate .travis.yml' task :regenerate_config do DefinesSpecSuiteTasks.configuration.generate_travis_config end end end end rr-3.1.0/Appraisals0000644000004100000410000000014414265140426014213 0ustar www-datawww-dataappraise 'ruby_19_rspec_2' do end appraise 'ruby_19_rspec_2_rails_4' do gem 'rails', '4.0.0' end rr-3.1.0/LICENSE0000644000004100000410000000204514265140426013200 0ustar www-datawww-dataCopyright (c) 2010-2013 Brian Takita Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. rr-3.1.0/Rakefile0000644000004100000410000000220514265140426013636 0ustar www-datawww-datarequire 'rubygems' require 'bundler' require 'rake' require 'pp' # build, install, release require 'bundler/gem_tasks' require_relative "lib/rr/version" default_tasks = [] begin # appraisal require 'appraisal' rescue LoadError else # appraisals Appraisal::File.each do |appraisal| desc "Resolve and install dependencies for the #{appraisal.name} appraisal" task "appraisal:#{appraisal.name}:install" do appraisal.install end end default_tasks << 'appraisal:install' end begin # spec require 'rspec/core/rake_task' rescue LoadError else require File.expand_path('../spec/defines_spec_suite_tasks', __FILE__) DefinesSpecSuiteTasks.call default_tasks << :spec end desc "Run tests" task :test do ruby("test/run-test.rb") end default_tasks << :test namespace :"gh-pages" do namespace :version do desc "Update version" task :update do config_yml_path = "gh-pages/_config.yml" config_yml = File.read(config_yml_path) config_yml = config_yml.gsub(/^version: .*$/, "version: #{RR::VERSION}") File.write(config_yml_path, config_yml) end end end task :default => default_tasks rr-3.1.0/lib/0000755000004100000410000000000014265140426012740 5ustar www-datawww-datarr-3.1.0/lib/rr.rb0000644000004100000410000000006414265140426013710 0ustar www-datawww-datarequire 'rr/without_autohook' require 'rr/autohook' rr-3.1.0/lib/rr/0000755000004100000410000000000014265140426013363 5ustar www-datawww-datarr-3.1.0/lib/rr/wildcard_matchers/0000755000004100000410000000000014265140426017042 5ustar www-datawww-datarr-3.1.0/lib/rr/wildcard_matchers/anything.rb0000644000004100000410000000040614265140426021210 0ustar www-datawww-datamodule RR module WildcardMatchers class Anything def wildcard_match?(other) true end def ==(other) other.is_a?(self.class) end alias :eql? :== def inspect 'anything' end end end end rr-3.1.0/lib/rr/wildcard_matchers/satisfy.rb0000644000004100000410000000100314265140426021043 0ustar www-datawww-datamodule RR module WildcardMatchers class Satisfy attr_reader :expectation_proc def initialize(expectation_proc) @expectation_proc = expectation_proc end def wildcard_match?(other) self == other || !!expectation_proc.call(other) end def ==(other) other.is_a?(self.class) && other.expectation_proc.equal?(self.expectation_proc) end alias :eql? :== def inspect "satisfy { ... }" end end end end rr-3.1.0/lib/rr/wildcard_matchers/is_a.rb0000644000004100000410000000062614265140426020306 0ustar www-datawww-datamodule RR module WildcardMatchers class IsA attr_reader :klass def initialize(klass) @klass = klass end def wildcard_match?(other) self == other || other.is_a?(klass) end def ==(other) other.is_a?(self.class) && klass == other.klass end alias :eql? :== def inspect "is_a(#{klass})" end end end end rr-3.1.0/lib/rr/wildcard_matchers/boolean.rb0000644000004100000410000000050214265140426021003 0ustar www-datawww-datamodule RR module WildcardMatchers class Boolean def wildcard_match?(other) self == other || other.equal?(true) || other.equal?(false) end def ==(other) other.is_a?(self.class) end alias :eql? :== def inspect 'boolean' end end end end rr-3.1.0/lib/rr/wildcard_matchers/duck_type.rb0000644000004100000410000000124314265140426021356 0ustar www-datawww-datamodule RR module WildcardMatchers class DuckType attr_accessor :required_methods def initialize(*required_methods) @required_methods = required_methods end def wildcard_match?(other) self == other || required_methods.all? {|m| other.respond_to?(m) } end def ==(other) other.is_a?(self.class) && other.required_methods == self.required_methods end alias :eql? :== def inspect formatted_required_methods = required_methods.map { |method_name| method_name.inspect }.join(', ') "duck_type(#{formatted_required_methods})" end end end end rr-3.1.0/lib/rr/wildcard_matchers/numeric.rb0000644000004100000410000000026614265140426021035 0ustar www-datawww-datamodule RR module WildcardMatchers class Numeric < IsA def initialize @klass = ::Numeric end def inspect 'numeric' end end end endrr-3.1.0/lib/rr/wildcard_matchers/hash_including.rb0000644000004100000410000000117714265140426022354 0ustar www-datawww-datamodule RR module WildcardMatchers class HashIncluding attr_reader :expected_hash def initialize(expected_hash) @expected_hash = expected_hash.dup end def wildcard_match?(other) self == other || ( other.is_a?(Hash) && expected_hash.all? { |k, v| other.key?(k) && other[k] == expected_hash[k] } ) end def ==(other) other.is_a?(self.class) && other.expected_hash == self.expected_hash end alias :eql? :== def inspect "hash_including(#{expected_hash.inspect})" end end end end rr-3.1.0/lib/rr/core_ext/0000755000004100000410000000000014265140426015173 5ustar www-datawww-datarr-3.1.0/lib/rr/core_ext/regexp.rb0000644000004100000410000000022114265140426017005 0ustar www-datawww-dataclass Regexp def wildcard_match?(other) self == other || !!(other.is_a?(String) && other =~ self) end alias_method :eql?, :== end rr-3.1.0/lib/rr/core_ext/array.rb0000644000004100000410000000054014265140426016635 0ustar www-datawww-dataclass Array def wildcard_match?(other) return false unless other.is_a?(Array) return false unless size == other.size each_with_index do |value, i| if value.respond_to?(:wildcard_match?) return false unless value.wildcard_match?(other[i]) else return false unless value == other[i] end end end end rr-3.1.0/lib/rr/core_ext/hash.rb0000644000004100000410000000217114265140426016444 0ustar www-datawww-dataclass Hash def wildcard_match?(other) return false unless other.is_a?(Hash) return false if size != other.size wildcards, exacts = partition {|key, _| key.respond_to?(:wildcard_match?)} other = other.dup exacts.each do |key, value| return false unless other.key?(key) other_value = other.delete(key) if value.respond_to?(:wildcard_match?) return false unless value.wildcard_match?(other_value) else return false unless value == other_value end end # TODO: Add support for the following case: # { # is_a(Symbol) => anything, # is_a(Symbol) => 1, # }.wildcard_match?(d: 1, c: 3) wildcards.each do |key, value| found = false other.each do |other_key, other_value| next unless key.wildcard_match?(other_key) if value.respond_to?(:wildcard_match?) next unless value.wildcard_match?(other_value) else next unless value == other_value end other.delete(other_key) found = true break end return false unless found end true end end rr-3.1.0/lib/rr/core_ext/range.rb0000644000004100000410000000022014265140426016606 0ustar www-datawww-dataclass Range def wildcard_match?(other) self == other || (other.is_a?(Numeric) && include?(other)) end alias_method :eql, :== end rr-3.1.0/lib/rr/core_ext/enumerable.rb0000644000004100000410000000075014265140426017641 0ustar www-datawww-datamodule Enumerable def wildcard_match?(other) if is_a?(String) return RR::Expectations::ArgumentEqualityExpectation.recursive_safe_eq(self, other) end return false unless other.is_a?(Enumerable) other_entries = other.entries each_with_index do |value, i| if value.respond_to?(:wildcard_match?) return false unless value.wildcard_match?(other_entries[i]) else return false unless value == other_entries[i] end end end end rr-3.1.0/lib/rr/version.rb0000644000004100000410000000011214265140426015367 0ustar www-datawww-datamodule RR VERSION = '3.1.0'.freeze def self.version; VERSION; end end rr-3.1.0/lib/rr/integrations.rb0000644000004100000410000000214214265140426016415 0ustar www-datawww-datarequire 'set' module RR module Integrations end def self.register_adapter(klass) adapter = Integrations::Decorator.new(klass.new) unless adapters_by_name.key?(adapter.name) adapters << adapter adapters_by_name[adapter.name] = adapter end end def self.adapters @adapters ||= [] end def self.adapters_by_name @adapters_by_name ||= {} end def self.loaded_adapter_names adapters. select { |adapter| adapter.loaded? }. map { |adapter| adapter.name } end def self.applicable_adapters adapters.select { |adapter| adapter.applies? } end def self.find_applicable_adapter(name) adapters. select { |adapter| name === adapter.name.to_s }. find { |adapter| adapter.applies? } end def self.module_shim_for_adapter(adapter) mod = Module.new (class << mod; self; end).class_eval do define_method(:included) do |base| # Note: This assumes that the thing that is including this module # is the same that the adapter detected and will hook into. adapter.load end end mod end end rr-3.1.0/lib/rr/deprecations.rb0000644000004100000410000000475714265140426016405 0ustar www-datawww-datamodule RR module Adapters # People who manually include RR into their test framework will use # these constants module MiniTest def self.included(base) RR::Deprecations.show_warning_for_deprecated_adapter RR.autohook end end module TestUnit def self.included(base) RR::Deprecations.show_warning_for_deprecated_adapter RR.autohook end end module RSpec2 def self.included(base) RR::Deprecations.show_warning_for_deprecated_adapter RR.autohook end end module Rspec def self.const_missing(name) if name == :InvocationMatcher # Old versions of the RSpec-2 adapter for RR floating out in the wild # still refer to this constant RR::Deprecations.constant_deprecated_in_favor_of( 'RR::Adapters::Rspec::InvocationMatcher', 'RR::Integrations::RSpec::InvocationMatcher' ) RR::Integrations::RSpec::InvocationMatcher else super end end end module RRMethods include RR::DSL def self.included(base) # This was once here but is now deprecated RR::Deprecations.constant_deprecated_in_favor_of( 'RR::Adapters::RRMethods', 'RR::DSL' ) end end end # This is here because RSpec-2's RR adapters uses it module Extensions def self.const_missing(name) if name == :InstanceMethods RR.autohook RR::Integrations::RSpec2::Mixin else super end end end module Deprecations def self.show_warning(msg, options = {}) start_backtrace_at_frame = options.fetch(:start_backtrace_at_frame, 2) backtrace = caller(start_backtrace_at_frame) lines = [] lines << ('-' * 80) lines << 'Warning from RR:' lines.concat msg.split(/\n/).map {|l| " #{l}" } lines << "" lines << "Called from:" lines.concat backtrace[0..2].map {|l| " - #{l}" } lines << ('-' * 80) Kernel.warn lines.join("\n") end def self.constant_deprecated_in_favor_of(old_name, new_name) show_warning "#{old_name} is deprecated;\nplease use #{new_name} instead.", :start_backtrace_at_frame => 3 end def self.show_warning_for_deprecated_adapter RR::Deprecations.show_warning(< "my/socks") # # stub.proxy(controller.template).render(:partial => "my/socks") do |html| # html.should include("My socks are wet") # html # end # # mock.proxy(controller.template).render(:partial => "my/socks") do |html| # html.should include("My socks are wet") # "My new return value" # end # # mock.proxy also takes a block for definitions. # mock.proxy(subject) do # render(:partial => "my/socks") # # render(:partial => "my/socks") do |html| # html.should include("My socks are wet") # html # end # # render(:partial => "my/socks") do |html| # html.should include("My socks are wet") # html # end # # render(:partial => "my/socks") do |html| # html.should include("My socks are wet") # "My new return value" # end # end # # Passing a block to the Double (after the method name and arguments) # allows you to intercept the return value. # The return value can be modified, validated, and/or overridden by # passing in a block. The return value of the block will replace # the actual return value. # # mock.proxy(controller.template).render(:partial => "my/socks") do |html| # html.should include("My socks are wet") # "My new return value" # end class Proxy < ImplementationStrategy protected def do_call definition.implemented_by_original_method definition.after_call(&handler) if handler end end end end end endrr-3.1.0/lib/rr/double_definitions/strategies/implementation/strongly_typed_reimplementation.rb0000644000004100000410000000046614265140426033504 0ustar www-datawww-datamodule RR module DoubleDefinitions module Strategies module Implementation class StronglyTypedReimplementation < Reimplementation protected def do_call super definition.verify_method_signature end end end end end endrr-3.1.0/lib/rr/double_definitions/strategies/implementation/implementation_strategy.rb0000644000004100000410000000025614265140426031726 0ustar www-datawww-datamodule RR module DoubleDefinitions module Strategies module Implementation class ImplementationStrategy < Strategy end end end end endrr-3.1.0/lib/rr/double_definitions/strategies/implementation/reimplementation.rb0000644000004100000410000000041314265140426030326 0ustar www-datawww-datamodule RR module DoubleDefinitions module Strategies module Implementation class Reimplementation < ImplementationStrategy protected def do_call reimplementation end end end end end endrr-3.1.0/lib/rr/double_definitions/strategies/double_injection/0000755000004100000410000000000014265140426024716 5ustar www-datawww-datarr-3.1.0/lib/rr/double_definitions/strategies/double_injection/instance.rb0000644000004100000410000000065714265140426027057 0ustar www-datawww-datamodule RR module DoubleDefinitions module Strategies module DoubleInjection class Instance < DoubleInjectionStrategy protected def do_call double_injection = Injections::DoubleInjection.find_or_create( (class << subject; self; end), method_name ) Double.new(double_injection, definition) end end end end end endrr-3.1.0/lib/rr/double_definitions/strategies/double_injection/any_instance_of.rb0000644000004100000410000000211714265140426030403 0ustar www-datawww-datamodule RR module DoubleDefinitions module Strategies module DoubleInjection # This class is Deprecated. # Calling instance_of will cause all instances of the passed in Class # to have the Double defined. # # The following example mocks all User's valid? method and return false. # mock.instance_of(User).valid? {false} # # The following example mocks and proxies User#projects and returns the # first 3 projects. # mock.instance_of(User).projects do |projects| # projects[0..2] # end class AnyInstanceOf < DoubleInjectionStrategy protected def do_call if !double_definition_create.no_subject? && !double_definition_create.subject.is_a?(Class) raise ArgumentError, "instance_of only accepts class objects" end double_injection = Injections::DoubleInjection.find_or_create(subject, method_name) Double.new(double_injection, definition) end end end end end endrr-3.1.0/lib/rr/double_definitions/strategies/double_injection/double_injection_strategy.rb0000644000004100000410000000026014265140426032477 0ustar www-datawww-datamodule RR module DoubleDefinitions module Strategies module DoubleInjection class DoubleInjectionStrategy < Strategy end end end end endrr-3.1.0/lib/rr/double_definitions/strategies/verification/0000755000004100000410000000000014265140426024064 5ustar www-datawww-datarr-3.1.0/lib/rr/double_definitions/strategies/verification/verification_strategy.rb0000644000004100000410000000025214265140426031014 0ustar www-datawww-datamodule RR module DoubleDefinitions module Strategies module Verification class VerificationStrategy < Strategy end end end end endrr-3.1.0/lib/rr/double_definitions/strategies/verification/dont_allow.rb0000644000004100000410000000207614265140426026560 0ustar www-datawww-datamodule RR module DoubleDefinitions module Strategies module Verification # This method sets the Double to have a dont_allow strategy. # A dont_allow strategy sets the default state of the Double # to expect never to be called. The Double's expectations can be # changed. # # The following example sets the expectation that subject.method_name # will never be called with arg1 and arg2. # # do_not_allow(subject).method_name(arg1, arg2) # # dont_allow also supports a block sytnax. # dont_allow(subject) do |m| # m.method1 # Do not allow method1 with any arguments # m.method2(arg1, arg2) # Do not allow method2 with arguments arg1 and arg2 # m.method3.with_no_args # Do not allow method3 with no arguments # end class DontAllow < VerificationStrategy protected def do_call definition.never permissive_argument end end end end end endrr-3.1.0/lib/rr/double_definitions/strategies/verification/stub.rb0000644000004100000410000000315414265140426025371 0ustar www-datawww-datamodule RR module DoubleDefinitions module Strategies module Verification # This method sets the Double to have a stub strategy. A stub strategy # sets the default state of the Double to expect the method call # with any arguments any number of times. The Double's # expectations can be changed. # # This method can be chained with proxy. # stub.proxy(subject).method_name_1 # or # proxy.stub(subject).method_name_1 # # When passed the subject, a DoubleDefinitionCreateBlankSlate is returned. Passing # a method with arguments to the proxy will set up expectations that # the a call to the subject's method with the arguments will happen, # and return the prescribed value. # stub(subject).method_name_1 {return_value_1} # stub(subject).method_name_2(arg_1, arg_2) {return_value_2} # # When passed the subject and the method_name, this method returns # a stub Double with the method already set. # # mock(subject, :method_name_1) {return_value_1} # mock(subject, :method_name_2).with(arg1, arg2) {return_value_2} # # stub also takes a block for definitions. # stub(subject) do # method_name_1 {return_value_1} # method_name_2(arg_1, arg_2) {return_value_2} # end class Stub < VerificationStrategy protected def do_call definition.any_number_of_times permissive_argument end end end end end endrr-3.1.0/lib/rr/double_definitions/strategies/verification/mock.rb0000644000004100000410000000334314265140426025345 0ustar www-datawww-datamodule RR module DoubleDefinitions module Strategies module Verification # This method sets the Double to have a mock strategy. A mock strategy # sets the default state of the Double to expect the method call # with arguments exactly one time. The Double's expectations can be # changed. # # This method can be chained with proxy. # mock.proxy(subject).method_name_1 # or # proxy.mock(subject).method_name_1 # # When passed the subject, a DoubleDefinitionCreateBlankSlate is returned. Passing # a method with arguments to the proxy will set up expectations that # a call to the subject's method with the arguments will happen, # and return the prescribed value. # mock(subject).method_name_1 {return_value_1} # mock(subject).method_name_2(arg1, arg2) {return_value_2} # # When passed the subject and the method_name, this method returns # a mock Double with the method already set. # # mock(subject, :method_name_1) {return_value_1} # mock(subject, :method_name_2).with(arg1, arg2) {return_value_2} # # mock also takes a block for definitions. # mock(subject) do # method_name_1 {return_value_1} # method_name_2(arg_1, arg_2) {return_value_2} # end class Mock < VerificationStrategy protected if KeywordArguments.fully_supported? def do_call definition.with(*args, **kwargs).once end else def do_call definition.with(*args).once end end end end end end end rr-3.1.0/lib/rr/double_definitions/strategies/strategy.rb0000644000004100000410000000265114265140426023575 0ustar www-datawww-datamodule RR module DoubleDefinitions module Strategies class Strategy attr_reader :double_definition_create attr_reader :definition attr_reader :method_name attr_reader :args attr_reader :kwargs attr_reader :handler include Space::Reader def initialize(double_definition_create) @double_definition_create = double_definition_create end def call(definition, method_name, args, kwargs, handler) @definition = definition @method_name = method_name @args = args @kwargs = kwargs @handler = handler do_call end def verify_subject(subject) end protected def do_call raise NotImplementedError end if KeywordArguments.fully_supported? def permissive_argument if args.empty? and kwargs.empty? definition.with_any_args else definition.with(*args, **kwargs) end end else def permissive_argument if args.empty? definition.with_any_args else definition.with(*args) end end end def reimplementation definition.returns(&handler) end def subject definition.subject end end end end end rr-3.1.0/lib/rr/double_definitions/double_definition_create.rb0000644000004100000410000001276614265140426024576 0ustar www-datawww-datamodule RR module DoubleDefinitions class DoubleDefinitionCreate # :nodoc extend(Module.new do def default_double_injection_strategy @default_double_injection_strategy ||= lambda do |double_injection_create| Strategies::DoubleInjection::Instance.new(double_injection_create) end end def set_default_double_injection_strategy(strategy_lambda) original_strategy_lambda = default_double_injection_strategy begin @default_double_injection_strategy = strategy_lambda yield ensure @default_double_injection_strategy = original_strategy_lambda end end end) attr_reader :subject, :verification_strategy, :implementation_strategy, :double_injection_strategy NO_SUBJECT = Object.new include Space::Reader def initialize @verification_strategy = Strategies::Verification::Stub.new(self) @implementation_strategy = Strategies::Implementation::Reimplementation.new(self) @double_injection_strategy = self.class.default_double_injection_strategy.call(self) end def call(method_name, args, kwargs, &handler) definition = DoubleDefinition.new(self) verification_strategy.call(definition, method_name, args, kwargs, handler) implementation_strategy.call(definition, method_name, args, kwargs, handler) double_injection_strategy.call(definition, method_name, args, kwargs, handler) definition end def root_subject subject end def method_name @verification_strategy.method_name end module StrategySetupMethods def no_subject? subject.__id__ === NO_SUBJECT.__id__ end protected def add_verification_strategy(verification_strategy_class, subject=NO_SUBJECT, method_name=nil, &definition_eval_block) add_strategy(subject, method_name, definition_eval_block) do self.verification_strategy = verification_strategy_class.new(self) end end def add_implementation_strategy(implementation_strategy_class, subject=NO_SUBJECT, method_name=nil, &definition_eval_block) add_strategy(subject, method_name, definition_eval_block) do self.implementation_strategy = implementation_strategy_class.new(self) end end def add_double_injection_strategy(double_injection_strategy_class, subject=NO_SUBJECT, method_name=nil, &definition_eval_block) add_strategy(subject, method_name, definition_eval_block) do self.double_injection_strategy = double_injection_strategy_class.new(self) end end def add_strategy(subject, method_name, definition_eval_block) if method_name && definition_eval_block raise ArgumentError, "Cannot pass in a method name and a block" end @subject = subject yield # TODO: Allow hash argument to simulate a Struct. if no_subject? self elsif method_name # TODO: Pass in arguments. call(method_name, [], {}) else DoubleDefinitionCreateBlankSlate.new(self, &definition_eval_block) end end def verification_strategy=(verification_strategy) @verification_strategy = verification_strategy verification_strategy end def implementation_strategy=(implementation_strategy) @implementation_strategy = implementation_strategy end def double_injection_strategy=(double_injection_strategy) @double_injection_strategy = double_injection_strategy end end include StrategySetupMethods class DoubleDefinitionCreateError < Errors::RRError end ## Verification Strategies include ::RR::DoubleDefinitions::Strategies::StrategyMethods def mock(subject=NO_SUBJECT, method_name=nil, &definition_eval_block) self.add_verification_strategy(::RR::DoubleDefinitions::Strategies::Verification::Mock, subject, method_name, &definition_eval_block) end def stub(subject=NO_SUBJECT, method_name=nil, &definition_eval_block) self.add_verification_strategy(::RR::DoubleDefinitions::Strategies::Verification::Stub, subject, method_name, &definition_eval_block) end def dont_allow(subject=NO_SUBJECT, method_name=nil, &definition_eval_block) self.add_verification_strategy(::RR::DoubleDefinitions::Strategies::Verification::DontAllow, subject, method_name, &definition_eval_block) end ## Implementation Strategies def proxy(subject=NO_SUBJECT, method_name=nil, &definition_eval_block) self.add_implementation_strategy(::RR::DoubleDefinitions::Strategies::Implementation::Proxy, subject, method_name, &definition_eval_block) end def strong(subject=NO_SUBJECT, method_name=nil, &definition_eval_block) self.add_implementation_strategy(::RR::DoubleDefinitions::Strategies::Implementation::StronglyTypedReimplementation, subject, method_name, &definition_eval_block) end ## DoubleInjection Strategies def instance_of(subject=NO_SUBJECT, method_name=nil, &definition_eval_block) self.add_double_injection_strategy(::RR::DoubleDefinitions::Strategies::DoubleInjection::AnyInstanceOf, subject, method_name, &definition_eval_block) end alias_method :any_instance_of, :instance_of alias_method :all_instances_of, :instance_of end end end rr-3.1.0/lib/rr/double_definitions/child_double_definition_create.rb0000644000004100000410000000125214265140426025725 0ustar www-datawww-datamodule RR module DoubleDefinitions class ChildDoubleDefinitionCreate < DoubleDefinitionCreate # :nodoc attr_reader :parent_double_definition def initialize(parent_double_definition) @parent_double_definition = parent_double_definition super() end def root_subject parent_double_definition.root_subject end def instance_of(*args) raise NoMethodError end protected def add_strategy(subject, method_name, definition_eval_block, &block) super do block.call parent_double_definition.implemented_by(lambda {|*args| subject }) end end end end end rr-3.1.0/lib/rr/double_definitions/double_injections/0000755000004100000410000000000014265140426022727 5ustar www-datawww-datarr-3.1.0/lib/rr/double_definitions/double_injections/instance.rb0000644000004100000410000000067714265140426025072 0ustar www-datawww-datamodule RR module DoubleDefinitions module DoubleInjections class Instance extend(Module.new do include ::RR::DSL def call(double_method_name, *args, &definition_eval_block) double_definition_create = DoubleDefinitions::DoubleDefinitionCreate.new double_definition_create.send(double_method_name, *args, &definition_eval_block) end end) end end end end rr-3.1.0/lib/rr/double_definitions/double_injections/any_instance_of.rb0000644000004100000410000000174214265140426026417 0ustar www-datawww-datamodule RR module DoubleDefinitions module DoubleInjections class AnyInstanceOf extend(Module.new do include RR::DSL def call(subject_class, stubbed_methods=nil, &block) strategy_lambda = lambda do |double_definition_create| ::RR::DoubleDefinitions::Strategies::DoubleInjection::AnyInstanceOf.new(double_definition_create) end ::RR::DoubleDefinitions::DoubleDefinitionCreate.set_default_double_injection_strategy(strategy_lambda) do if stubbed_methods subject_class.class_eval do stubbed_methods.each do |name, value| value_proc = value.is_a?(Proc) ? value : lambda {value} RR.stub(subject_class, name).returns(&value_proc) end end else block.call(subject_class) end end end end) end end end end rr-3.1.0/lib/rr/errors/0000755000004100000410000000000014265140426014677 5ustar www-datawww-datarr-3.1.0/lib/rr/errors/double_not_found_error.rb0000644000004100000410000000012314265140426021756 0ustar www-datawww-datamodule RR module Errors class DoubleNotFoundError < RRError end end endrr-3.1.0/lib/rr/errors/spy_verification_errors/0000755000004100000410000000000014265140426021650 5ustar www-datawww-datarr-3.1.0/lib/rr/errors/spy_verification_errors/double_injection_not_found_error.rb0000644000004100000410000000023414265140426030774 0ustar www-datawww-datamodule RR module Errors module SpyVerificationErrors class DoubleInjectionNotFoundError < SpyVerificationError end end end endrr-3.1.0/lib/rr/errors/spy_verification_errors/invocation_count_error.rb0000644000004100000410000000021614265140426026766 0ustar www-datawww-datamodule RR module Errors module SpyVerificationErrors class InvocationCountError < SpyVerificationError end end end endrr-3.1.0/lib/rr/errors/spy_verification_errors/spy_verification_error.rb0000644000004100000410000000020114265140426026754 0ustar www-datawww-datamodule RR module Errors module SpyVerificationErrors class SpyVerificationError < RRError end end end endrr-3.1.0/lib/rr/errors/double_order_error.rb0000644000004100000410000000012014265140426021073 0ustar www-datawww-datamodule RR module Errors class DoubleOrderError < RRError end end endrr-3.1.0/lib/rr/errors/times_called_error.rb0000644000004100000410000000012014265140426021053 0ustar www-datawww-datamodule RR module Errors class TimesCalledError < RRError end end endrr-3.1.0/lib/rr/errors/double_definition_error.rb0000644000004100000410000000012514265140426022115 0ustar www-datawww-datamodule RR module Errors class DoubleDefinitionError < RRError end end endrr-3.1.0/lib/rr/errors/subject_does_not_implement_method_error.rb0000644000004100000410000000014214265140426025375 0ustar www-datawww-datamodule RR module Errors class SubjectDoesNotImplementMethodError < RRError end end endrr-3.1.0/lib/rr/errors/rr_error.rb0000644000004100000410000000106314265140426017060 0ustar www-datawww-datamodule RR module Errors BACKTRACE_IDENTIFIER = Regexp.new("/lib/rr") class RRError < RuntimeError attr_writer :backtrace def backtrace @backtrace ||= super original_backtrace = @backtrace return original_backtrace unless RR.trim_backtrace return original_backtrace unless original_backtrace.respond_to?(:each) new_backtrace = [] original_backtrace.each do |line| new_backtrace << line unless line =~ BACKTRACE_IDENTIFIER end new_backtrace end end end endrr-3.1.0/lib/rr/errors/subject_has_different_arity_error.rb0000644000004100000410000000013514265140426024164 0ustar www-datawww-datamodule RR module Errors class SubjectHasDifferentArityError < RRError end end endrr-3.1.0/lib/rr/hash_with_object_id_key.rb0000644000004100000410000000140314265140426020536 0ustar www-datawww-datamodule RR # TODO: Refactor to a side-effect-free strategy. class HashWithObjectIdKey < ::Hash #:nodoc: def initialize @keys = {} super end alias_method :get_with_object_id, :[] def [](key) @keys[key.__id__] = key super(key.__id__) end def has_key?(key) super(key.__id__) end alias_method :set_with_object_id, :[]= def []=(key, value) @keys[key.__id__] = key super(key.__id__, value) end def each super do |object_id, value| yield @keys[object_id], value end end def delete(key) @keys.delete(key.__id__) super(key.__id__) end def keys @keys.values end def include?(key) super(key.__id__) end end endrr-3.1.0/lib/rr/keyword_arguments.rb0000644000004100000410000000043014265140426017456 0ustar www-datawww-datamodule RR module KeywordArguments class << self if (RUBY_VERSION <=> "3.0.0") >= 0 and RUBY_ENGINE != "truffleruby" def fully_supported? true end else def fully_supported? false end end end end end rr-3.1.0/lib/rr/injections/0000755000004100000410000000000014265140426015530 5ustar www-datawww-datarr-3.1.0/lib/rr/injections/double_injection.rb0000644000004100000410000002246214265140426021377 0ustar www-datawww-datamodule RR module Injections # RR::DoubleInjection is the binding of an subject and a method. # A double_injection has 0 to many Double objects. Each Double # has Argument Expectations and Times called Expectations. class DoubleInjection < Injection extend(Module.new do def find_or_create(subject_class, method_name) instances[subject_class][method_name.to_sym] ||= begin new(subject_class, method_name.to_sym).bind end end def find_or_create_by_subject(subject, method_name) find_or_create(class << subject; self; end, method_name) end def find(subject_class, method_name) instances[subject_class] && instances[subject_class][method_name.to_sym] end def find_by_subject(subject, method_name) find(class << subject; self; end, method_name) end def exists?(subject_class, method_name) !!find(subject_class, method_name) end def exists_by_subject?(subject, method_name) exists?((class << subject; self; end), method_name) end def dispatch_method(subject, subject_class, method_name, arguments, keyword_arguments, block) subject_eigenclass = (class << subject; self; end) if ( exists?(subject_class, method_name) && ((subject_class == subject_eigenclass) || !subject.is_a?(Class)) ) find(subject_class, method_name.to_sym).dispatch_method(subject, arguments, keyword_arguments, block) else new(subject_class, method_name.to_sym).dispatch_original_method(subject, arguments, keyword_arguments, block) end end def reset instances.each do |subject_class, method_double_map| SingletonMethodAddedInjection.find(subject_class) && SingletonMethodAddedInjection.find(subject_class).reset method_double_map.keys.each do |method_name| reset_double(subject_class, method_name) end Injections::DoubleInjection.instances.delete(subject_class) if Injections::DoubleInjection.instances.has_key?(subject_class) end end def verify(*subjects) subject_classes = subjects.empty? ? Injections::DoubleInjection.instances.keys : subjects.map {|subject| class << subject; self; end} subject_classes.each do |subject_class| instances.include?(subject_class) && instances[subject_class].keys.each do |method_name| verify_double(subject_class, method_name) end && instances.delete(subject_class) end end # Verifies the DoubleInjection for the passed in subject and method_name. def verify_double(subject_class, method_name) Injections::DoubleInjection.find(subject_class, method_name).verify ensure reset_double subject_class, method_name end # Resets the DoubleInjection for the passed in subject and method_name. def reset_double(subject_class, method_name) double_injection = Injections::DoubleInjection.instances[subject_class].delete(method_name) double_injection.reset Injections::DoubleInjection.instances.delete(subject_class) if Injections::DoubleInjection.instances[subject_class].empty? end def instances @instances ||= HashWithObjectIdKey.new do |hash, subject_class| hash.set_with_object_id(subject_class, {}) end end end) include ClassInstanceMethodDefined attr_reader :subject_class, :method_name, :doubles MethodArguments = Struct.new(:arguments, :keyword_arguments, :block) def initialize(subject_class, method_name) @subject_class = subject_class @method_name = method_name.to_sym @doubles = [] @dispatch_method_delegates_to_dispatch_original_method = nil end # RR::DoubleInjection#register_double adds the passed in Double # into this DoubleInjection's list of Double objects. def register_double(double) @doubles << double end # RR::DoubleInjection#bind injects a method that acts as a dispatcher # that dispatches to the matching Double when the method # is called. def bind if subject_has_method_defined?(method_name) if subject_has_original_method? bind_method else bind_method_with_alias end else Injections::MethodMissingInjection.find_or_create(subject_class) Injections::SingletonMethodAddedInjection.find_or_create(subject_class) bind_method_that_self_destructs_and_delegates_to_method_missing end self end BoundObjects = {} def bind_method_that_self_destructs_and_delegates_to_method_missing id = BoundObjects.size BoundObjects[id] = subject_class subject_class.class_eval(<<-RUBY, __FILE__, __LINE__ + 1) def #{method_name}(*args, &block) ::RR::Injections::DoubleInjection::BoundObjects[#{id}].class_eval do remove_method(:#{method_name}) end method_missing(:#{method_name}, *args, &block) end ruby2_keywords(:#{method_name}) if respond_to?(:ruby2_keywords, true) RUBY self end def bind_method id = BoundObjects.size BoundObjects[id] = subject_class if KeywordArguments.fully_supported? subject_class.class_eval(<<-RUBY, __FILE__, __LINE__ + 1) def #{method_name}(*args, **kwargs, &block) arguments = MethodArguments.new(args, kwargs, block) obj = ::RR::Injections::DoubleInjection::BoundObjects[#{id}] ::RR::Injections::DoubleInjection.dispatch_method( self, obj, :#{method_name}, arguments.arguments, arguments.keyword_arguments, arguments.block ) end RUBY else subject_class.class_eval(<<-RUBY, __FILE__, __LINE__ + 1) def #{method_name}(*args, &block) arguments = MethodArguments.new(args, {}, block) obj = ::RR::Injections::DoubleInjection::BoundObjects[#{id}] ::RR::Injections::DoubleInjection.dispatch_method( self, obj, :#{method_name}, arguments.arguments, arguments.keyword_arguments, arguments.block ) end ruby2_keywords(:#{method_name}) if respond_to?(:ruby2_keywords, true) RUBY end self end # RR::DoubleInjection#verify verifies each Double # TimesCalledExpectation are met. def verify @doubles.each do |double| double.verify end end # RR::DoubleInjection#reset removes the injected dispatcher method. # It binds the original method implementation on the subject # if one exists. def reset if subject_has_original_method? subject_class.__send__(:remove_method, method_name) subject_class.__send__(:alias_method, method_name, original_method_alias_name) subject_class.__send__(:remove_method, original_method_alias_name) else if subject_has_method_defined?(method_name) subject_class.__send__(:remove_method, method_name) end end end def dispatch_method(subject, args, kwargs, block) if @dispatch_method_delegates_to_dispatch_original_method dispatch_original_method(subject, args, kwargs, block) else dispatch = MethodDispatches::MethodDispatch.new( self, subject, args, kwargs, block ) dispatch.call end end def dispatch_original_method(subject, args, kwargs, block) dispatch = MethodDispatches::MethodDispatch.new( self, subject, args, kwargs, block ) dispatch.call_original_method end def subject_has_original_method_missing? class_instance_method_defined(subject_class, MethodDispatches::MethodMissingDispatch.original_method_missing_alias_name) end def original_method_alias_name "__rr__original_#{@method_name}" end def dispatch_method_delegates_to_dispatch_original_method @dispatch_method_delegates_to_dispatch_original_method = true yield ensure @dispatch_method_delegates_to_dispatch_original_method = nil end protected def deferred_bind_method if respond_to?(method_name) and not subject_has_method_defined?(original_method_alias_name) bind_method_with_alias end @performed_deferred_bind = true end def bind_method_with_alias subject_class.__send__(:alias_method, original_method_alias_name, method_name) bind_method end end end end rr-3.1.0/lib/rr/injections/singleton_method_added_injection.rb0000644000004100000410000000466614265140426024616 0ustar www-datawww-datamodule RR module Injections class SingletonMethodAddedInjection < Injection extend(Module.new do def find_or_create(subject_class) instances[subject_class] ||= begin new(subject_class).bind end end def find(subject) instances[subject] end def exists?(subject) instances.include?(subject) end end) include ClassInstanceMethodDefined attr_reader :subject_class def initialize(subject_class) @subject_class = subject_class @placeholder_method_defined = false end def bind unless class_instance_method_defined(subject_class, original_method_alias_name, false) unless class_instance_method_defined(subject_class, :singleton_method_added, false) @placeholder_method_defined = true subject_class.class_eval do #def singleton_method_added(method_name) # super #end end end memoized_original_method_alias_name = original_method_alias_name subject_class.__send__(:alias_method, original_method_alias_name, :singleton_method_added) memoized_subject_class = subject_class memoized_original_method_alias_name = original_method_alias_name subject_class.__send__(:define_method, :singleton_method_added) do |method_name_arg| if Injections::DoubleInjection.exists?(memoized_subject_class, method_name_arg) Injections::DoubleInjection.find_or_create(memoized_subject_class, method_name_arg).send(:deferred_bind_method) end __send__(memoized_original_method_alias_name, method_name_arg) end end self end def reset if subject_has_method_defined?(original_method_alias_name) memoized_original_method_alias_name = original_method_alias_name placeholder_method_defined = @placeholder_method_defined subject_class.class_eval do remove_method :singleton_method_added unless placeholder_method_defined alias_method :singleton_method_added, memoized_original_method_alias_name end remove_method memoized_original_method_alias_name end end end protected def original_method_alias_name "__rr__original_singleton_method_added" end end end end rr-3.1.0/lib/rr/injections/method_missing_injection.rb0000644000004100000410000000771614265140426023143 0ustar www-datawww-datamodule RR module Injections class MethodMissingInjection < Injection extend(Module.new do def find_or_create(subject_class) instances[subject_class] ||= begin new(subject_class).bind end end def exists?(subject) instances.include?(subject) end end) BoundObjects = {} include ClassInstanceMethodDefined attr_reader :subject_class def initialize(subject_class) @subject_class = subject_class @placeholder_method_defined = false end def bind unless class_instance_method_defined(subject_class, original_method_alias_name) unless class_instance_method_defined(subject_class, :method_missing) @placeholder_method_defined = true subject_class.class_eval do def method_missing(method_name, *args, &block) super end end end # Ruby 1.9 will raise a NoMethodError when #method_missing is defined # on the subject, but #to_ary isn't. #method_missing will always be # defined thanks to BasicObject, but #to_ary may not, so in this case # we need to supply our own. Furthermore, Ruby has special logic to # handle the return value of #to_ary; if it is nil, then it tells Ruby # to ignore #to_ary altogether and use a default rule to arrayify the # object in question. unless class_instance_method_defined(subject_class, :to_ary) subject_class.class_eval do def to_ary; nil; end end end subject_class.__send__(:alias_method, original_method_alias_name, :method_missing) bind_method end self end def reset if subject_has_method_defined?(original_method_alias_name) memoized_original_method_alias_name = original_method_alias_name placeholder_method_defined = @placeholder_method_defined subject_class.class_eval do remove_method :method_missing unless placeholder_method_defined alias_method :method_missing, memoized_original_method_alias_name end remove_method memoized_original_method_alias_name end end end protected def bind_method id = BoundObjects.size BoundObjects[id] = subject_class if KeywordArguments.fully_supported? subject_class.class_eval((<<-METHOD), __FILE__, __LINE__ + 1) def method_missing(method_name, *args, **kwargs, &block) if respond_to_missing?(method_name, true) super(method_name, *args, **kwargs, &block) else obj = ::RR::Injections::MethodMissingInjection::BoundObjects[#{id}] MethodDispatches::MethodMissingDispatch.new( self, obj, method_name, args, kwargs, block ).call end end METHOD else subject_class.class_eval((<<-METHOD), __FILE__, __LINE__ + 1) def method_missing(method_name, *args, &block) if respond_to_missing?(method_name, true) super(method_name, *args, &block) else obj = ::RR::Injections::MethodMissingInjection::BoundObjects[#{id}] MethodDispatches::MethodMissingDispatch.new( self, obj, method_name, args, {}, block ).call end end ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true) METHOD end end def original_method_alias_name MethodDispatches::MethodMissingDispatch.original_method_missing_alias_name end end end end rr-3.1.0/lib/rr/injections/injection.rb0000644000004100000410000000155714265140426020047 0ustar www-datawww-datamodule RR module Injections class Injection extend(Module.new do def instances @instances ||= HashWithObjectIdKey.new end end) include Space::Reader include ClassInstanceMethodDefined def subject_has_method_defined?(method_name_in_question) class_instance_method_defined(subject_class, method_name_in_question) end def subject_has_original_method? subject_has_method_defined?(original_method_alias_name) end def original_method subject_class.instance_method(original_method_alias_name) end protected def subject_respond_to_method?(subject, method_name) subject_has_method_defined?(method_name) || class_instance_method_defined(subject_class, :respond_to?) && subject.respond_to?(method_name) end end end end rr-3.1.0/lib/rr/wildcard_matchers.rb0000644000004100000410000001060214265140426017366 0ustar www-datawww-data=begin rdoc = Writing your own custom wildcard matchers. Writing new wildcard matchers is not too difficult. If you've ever written a custom expectation in RSpec, the implementation is very similar. As an example, let's say that you want a matcher that will match any number divisible by a certain integer. In use, it might look like this: # Will pass if BananaGrabber#bunch_bananas is called with an integer # divisible by 5. mock(BananaGrabber).bunch_bananas(divisible_by(5)) To implement this, we need a class RR::WildcardMatchers::DivisibleBy with these instance methods: * ==(other) * eql?(other) (usually aliased to #==) * inspect * wildcard_match?(other) and optionally, a sensible initialize method. Let's look at each of these. === .initialize Most custom wildcard matchers will want to define initialize to store some information about just what should be matched. DivisibleBy#initialize might look like this: class RR::WildcardMatchers::DivisibleBy def initialize(divisor) @expected_divisor = divisor end end === #==(other) DivisibleBy#==(other) should return true if other is a wildcard matcher that matches the same things as self, so a natural way to write DivisibleBy#== is: class RR::WildcardMatchers::DivisibleBy def ==(other) # Ensure that other is actually a DivisibleBy return false unless other.is_a?(self.class) # Does other expect to match the same divisor we do? self.expected_divisor = other.expected_divisor end end Note that this implementation of #== assumes that we've also declared attr_reader :expected_divisor === #inspect Technically we don't have to declare DivisibleBy#inspect, since inspect is defined for every object already. But putting a helpful message in inspect will make test failures much clearer, and it only takes about two seconds to write it, so let's be nice and do so: class RR::WildcardMatchers::DivisibleBy def inspect "integer divisible by #{expected.divisor}" end end Now if we run the example from above: mock(BananaGrabber).bunch_bananas(divisible_by(5)) and it fails, we get a helpful message saying bunch_bananas(integer divisible by 5) Called 0 times. Expected 1 times. === #wildcard_matches?(other) wildcard_matches? is the method that actually checks the argument against the expectation. It should return true if other is considered to match, false otherwise. In the case of DivisibleBy, wildcard_matches? reads: class RR::WildcardMatchers::DivisibleBy def wildcard_matches?(other) # If other isn't a number, how can it be divisible by anything? return false unless other.is_a?(Numeric) # If other is in fact divisible by expected_divisor, then # other modulo expected_divisor should be 0. other % expected_divisor == 0 end end === A finishing touch: wrapping it neatly We could stop here if we were willing to resign ourselves to using DivisibleBy this way: mock(BananaGrabber).bunch_bananas(DivisibleBy.new(5)) But that's less expressive than the original: mock(BananaGrabber).bunch_bananas(divisible_by(5)) To be able to use the convenient divisible_by matcher rather than the uglier DivisibleBy.new version, re-open the module RR::DSL and define divisible_by there as a simple wrapper around DivisibleBy.new: module RR::DSL def divisible_by(expected_divisor) RR::WildcardMatchers::DivisibleBy.new(expected_divisor) end end == Recap Here's all the code for DivisibleBy in one place for easy reference: class RR::WildcardMatchers::DivisibleBy def initialize(divisor) @expected_divisor = divisor end def ==(other) # Ensure that other is actually a DivisibleBy return false unless other.is_a?(self.class) # Does other expect to match the same divisor we do? self.expected_divisor = other.expected_divisor end def inspect "integer divisible by #{expected.divisor}" end def wildcard_matches?(other) # If other isn't a number, how can it be divisible by anything? return false unless other.is_a?(Numeric) # If other is in fact divisible by expected_divisor, then # other modulo expected_divisor should be 0. other % expected_divisor == 0 end end module RR::DSL def divisible_by(expected_divisor) RR::WildcardMatchers::DivisibleBy.new(expected_divisor) end end =end module RR::WildcardMatchers end rr-3.1.0/lib/rr/method_dispatches/0000755000004100000410000000000014265140426017052 5ustar www-datawww-datarr-3.1.0/lib/rr/method_dispatches/base_method_dispatch.rb0000644000004100000410000000557714265140426023546 0ustar www-datawww-datamodule RR module MethodDispatches class BaseMethodDispatch extend Forwardable include Space::Reader attr_reader :args, :kwargs, :block, :double def call raise NotImplementedError end protected def find_double_to_attempt matches = DoubleMatches.new(doubles).find_all_matches(args, kwargs) unless matches.exact_terminal_doubles_to_attempt.empty? return matches.exact_terminal_doubles_to_attempt.first end unless matches.exact_non_terminal_doubles_to_attempt.empty? return matches.exact_non_terminal_doubles_to_attempt.last end unless matches.wildcard_terminal_doubles_to_attempt.empty? return matches.wildcard_terminal_doubles_to_attempt.first end unless matches.wildcard_non_terminal_doubles_to_attempt.empty? return matches.wildcard_non_terminal_doubles_to_attempt.last end unless matches.matching_doubles.empty? return matches.matching_doubles.first # This will raise a TimesCalledError end return nil end def call_yields if definition.yields_value if block block.call(*definition.yields_value) else raise ArgumentError, "A Block must be passed into the method call when using yields" end end end if KeywordArguments.fully_supported? def call_original_method_missing subject.__send__( MethodMissingDispatch.original_method_missing_alias_name, method_name, *args, **kwargs, &block ) end else def call_original_method_missing subject.__send__( MethodMissingDispatch.original_method_missing_alias_name, method_name, *args, &block ) end end def implementation_is_original_method? double.implementation_is_original_method? end def extract_subject_from_return_value(return_value) case return_value when DoubleDefinitions::DoubleDefinition return_value.root_subject when DoubleDefinitions::DoubleDefinitionCreateBlankSlate return_value.__double_definition_create__.root_subject else return_value end end def double_not_found_error message = "On subject #{subject},\n" << "unexpected method invocation:\n" << " #{Double.formatted_name(method_name, args, kwargs)}\n" << "expected invocations:\n" << Double.list_message_part(doubles) raise RR::Errors.build_error(:DoubleNotFoundError, message) end def_delegators :definition, :after_call_proc def_delegators :double, :definition def_delegators :double_injection, :doubles end end end rr-3.1.0/lib/rr/method_dispatches/method_dispatch.rb0000644000004100000410000000425514265140426022544 0ustar www-datawww-datamodule RR module MethodDispatches class MethodDispatch < BaseMethodDispatch attr_reader :double_injection, :subject def initialize(double_injection, subject, args, kwargs, block) @double_injection = double_injection @subject = subject @args = args @kwargs = kwargs @block = block @double = find_double_to_attempt end def call space.record_call(subject, method_name, args, kwargs, block) if double double.method_call(args, kwargs) call_yields return_value_1 = call_implementation return_value_2 = extract_subject_from_return_value(return_value_1) if after_call_proc extract_subject_from_return_value(after_call_proc.call(return_value_2)) else return_value_2 end else double_not_found_error end end def call_original_method if subject_has_original_method? if KeywordArguments.fully_supported? subject.__send__(original_method_alias_name, *args, **kwargs, &block) else subject.__send__(original_method_alias_name, *args, &block) end elsif subject_has_original_method_missing? call_original_method_missing else if KeywordArguments.fully_supported? subject.__send__(:method_missing, method_name, *args, **kwargs, &block) else subject.__send__(:method_missing, method_name, *args, &block) end end end protected def call_implementation if implementation_is_original_method? call_original_method else if implementation if KeywordArguments.fully_supported? implementation.call(*args, **kwargs, &block) else implementation.call(*args, &block) end else nil end end end def_delegators :definition, :implementation def_delegators :double_injection, :subject_has_original_method?, :subject_has_original_method_missing?, :method_name, :original_method_alias_name end end end rr-3.1.0/lib/rr/method_dispatches/method_missing_dispatch.rb0000644000004100000410000000421214265140426024266 0ustar www-datawww-datamodule RR module MethodDispatches class MethodMissingDispatch < BaseMethodDispatch extend(Module.new do def original_method_missing_alias_name "__rr__original_method_missing" end end) attr_reader :subject, :subject_class, :method_name def initialize(subject, subject_class, method_name, args, kwargs, block) @subject = subject @subject_class = subject_class @method_name = method_name @args = args @kwargs = kwargs @block = block end def call if Injections::DoubleInjection.exists?(subject_class, method_name) @double = find_double_to_attempt if double return_value = extract_subject_from_return_value(call_implementation) if after_call_proc extract_subject_from_return_value(after_call_proc.call(return_value)) else return_value end else double_not_found_error end else call_original_method end end def call_original_method Injections::DoubleInjection.find_or_create(subject_class, method_name).dispatch_method_delegates_to_dispatch_original_method do call_original_method_missing end end protected def call_implementation if implementation_is_original_method? space.record_call(subject, method_name, args, kwargs, block) double.method_call(args, kwargs) call_original_method else if double_injection = Injections::DoubleInjection.find(subject_class, method_name) double_injection.bind_method # The DoubleInjection takes care of calling double.method_call if KeywordArguments.fully_supported? subject.__send__(method_name, *args, **kwargs, &block) else subject.__send__(method_name, *args, &block) end else nil end end end def double_injection Injections::DoubleInjection.find_or_create(subject_class, method_name) end end end end rr-3.1.0/lib/rr/integrations/0000755000004100000410000000000014265140426016071 5ustar www-datawww-datarr-3.1.0/lib/rr/integrations/decorator.rb0000644000004100000410000000162014265140426020377 0ustar www-datawww-datarequire 'delegate' module RR module Integrations class Decorator < SimpleDelegator def initialize(adapter) super(adapter) @loaded = false end def name __getobj__.class.to_s.split('::').last.to_sym end def applies? __getobj__.applies? rescue => e if RR.debug? puts "#{__getobj__.class}#applies? failed: #{e.class} (#{e.message})" puts e.backtrace.map {|x| " " + x }.join("\n") end end def load return if @loaded hook if RR.debug? puts "Loaded adapter: #{name}" end @loaded = true rescue => e if RR.debug? puts "Couldn't load adapter #{name}: #{e.class} (#{e.message})" puts e.backtrace.map {|x| " " + x }.join("\n") end end def loaded? @loaded end end end end rr-3.1.0/lib/rr/integrations/minitest_4_active_support.rb0000644000004100000410000000155114265140426023626 0ustar www-datawww-datamodule RR module Integrations class MiniTest4ActiveSupport def initialize @mt_adapter = parent_adapter_class.new end def parent_adapter_class MiniTest4 end def name 'MiniTest 4 + ActiveSupport' end def applies? @mt_adapter.applies? && defined?(::ActiveSupport::TestCase) end def hook parent_adapter_class = self.parent_adapter_class ::ActiveSupport::TestCase.class_eval do include RR::DSL include parent_adapter_class::Mixin setup do RR.reset RR.trim_backtrace = true RR.overridden_error_class = ::ActiveSupport::TestCase::Assertion end teardown do RR.verify end end end end RR.register_adapter MiniTest4ActiveSupport end end rr-3.1.0/lib/rr/integrations/minitest_4.rb0000644000004100000410000000370714265140426020504 0ustar www-datawww-datamodule RR module Integrations class MiniTest4 module Mixin def assert_received(subject, &block) block.call(received(subject)).call end end def name 'MiniTest 4' end def applies? mt_version < 5 rescue NameError false end def test_case_class ::MiniTest::Unit::TestCase end def assertion_error_class ::MiniTest::Assertion end def version_constant ::MiniTest::Unit::VERSION end def mt_version version_constant.split('.')[0].to_i end def hook assertion_error_class = self.assertion_error_class test_case_class.class_eval do include RR::DSL include Mixin if defined?(::ActiveSupport::TestCase) is_active_support_test_case = lambda do |target| target.is_a?(::ActiveSupport::TestCase) end else is_active_support_test_case = lambda do |target| false end end unless instance_methods.any? { |method_name| method_name.to_sym == :setup_with_rr } alias_method :setup_without_rr, :setup define_method(:setup_with_rr) do setup_without_rr return if is_active_support_test_case.call(self) RR.reset RR.trim_backtrace = true RR.overridden_error_class = assertion_error_class end alias_method :setup, :setup_with_rr alias_method :teardown_without_rr, :teardown define_method(:teardown_with_rr) do begin RR.verify unless is_active_support_test_case.call(self) ensure teardown_without_rr end end alias_method :teardown, :teardown_with_rr end end end end RR.register_adapter MiniTest4 end end rr-3.1.0/lib/rr/integrations/minitest.rb0000644000004100000410000000070314265140426020252 0ustar www-datawww-datamodule RR module Integrations class Minitest < MiniTest4 def name 'Minitest' end def applies? mt_version >= 5 rescue NameError false end def test_case_class ::Minitest::Test end def assertion_error_class ::Minitest::Assertion end def version_constant ::Minitest::VERSION end end RR.register_adapter Minitest end end rr-3.1.0/lib/rr/integrations/minitest_active_support.rb0000644000004100000410000000042114265140426023376 0ustar www-datawww-datamodule RR module Integrations class MinitestActiveSupport < MiniTest4ActiveSupport def parent_adapter_class Minitest end def name 'Minitest + ActiveSupport' end end RR.register_adapter MinitestActiveSupport end end rr-3.1.0/lib/rr/integrations/rspec/0000755000004100000410000000000014265140426017205 5ustar www-datawww-datarr-3.1.0/lib/rr/integrations/rspec/invocation_matcher.rb0000644000004100000410000000161614265140426023412 0ustar www-datawww-datamodule RR module Integrations module RSpec class InvocationMatcher < SpyVerificationProxy attr_reader :failure_message, :spy_verification_proxy def initialize(method = nil) @verification = nil @subject = nil method_missing(method) if method end def matches?(subject) @verification.subject = subject calls = RR::Space.instance.recorded_calls if error = calls.match_error(@verification) @failure_message = error.message false else true end end def nil? false end def method_missing(method_name, *args, &block) if @verification @verification.send(method_name, *args) else @verification = super end self end end end end end rr-3.1.0/lib/rr/integrations/rspec_2.rb0000644000004100000410000000221114265140426017747 0ustar www-datawww-datamodule RR module Integrations class RSpec2 module Mixin def setup_mocks_for_rspec RR.reset end def verify_mocks_for_rspec RR.verify end def teardown_mocks_for_rspec RR.reset end def have_received(method = nil) RSpec::InvocationMatcher.new(method) end end def name 'RSpec 2' end def applies? defined?(::RSpec) && defined?(::RSpec::Core::Version::STRING) && ::RSpec::Core::Version::STRING =~ /^2/ end def hook ::RSpec.configure do |config| config.mock_with Mixin config.include RR::DSL end patterns = if ::RSpec.configuration.respond_to?(:backtrace_exclusion_patterns) ::RSpec.configuration.backtrace_exclusion_patterns else ::RSpec.configuration.backtrace_clean_patterns end unless patterns.include?(RR::Errors::BACKTRACE_IDENTIFIER) patterns.push(RR::Errors::BACKTRACE_IDENTIFIER) end end end RR.register_adapter RSpec2 end end rr-3.1.0/lib/rr/spy_verification_proxy.rb0000644000004100000410000000102614265140426020525 0ustar www-datawww-datamodule RR class SpyVerificationProxy BlankSlate.call(self) def initialize(subject) @subject = subject end if KeywordArguments.fully_supported? def method_missing(method_name, *args, **kwargs, &block) SpyVerification.new(@subject, method_name, args, kwargs) end else def method_missing(method_name, *args, &block) SpyVerification.new(@subject, method_name, args, {}) end ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true) end end end rr-3.1.0/lib/rr/errors.rb0000644000004100000410000000106114265140426015222 0ustar www-datawww-datamodule RR class << self attr_accessor :overridden_error_class end module Errors def self.build_error(given_error, message = nil, backtrace = nil) error_class = self.error_class(given_error) error = message ? error_class.new(message) : error_class.new error.backtrace = backtrace if error_class < RR::Errors::RRError error end def self.error_class(given_error) RR.overridden_error_class || (given_error.is_a?(Symbol) ? RR::Errors.const_get(given_error) : given_error) end end end rr-3.1.0/lib/rr/times_called_matchers/0000755000004100000410000000000014265140426017676 5ustar www-datawww-datarr-3.1.0/lib/rr/times_called_matchers/terminal.rb0000644000004100000410000000123614265140426022040 0ustar www-datawww-datamodule RR module TimesCalledMatchers # Including this module marks the TimesCalledMatcher as Terminal. # Being Terminal the Double will "terminate" when times called is # finite. # # The Double that uses a Terminal TimesCalledMatcher will # eventually be passed over to the next Double when passed # the matching arguments enough times. This is done by the attempt? # method returning false when executed a finite number of times. # # This is in opposition to NonTerminal TimesCalledMatchers, where # attempt? will always return true. module Terminal #:nodoc: def terminal? true end end end endrr-3.1.0/lib/rr/times_called_matchers/integer_matcher.rb0000644000004100000410000000055514265140426023370 0ustar www-datawww-datamodule RR module TimesCalledMatchers #:nodoc: class IntegerMatcher < TimesCalledMatcher include Terminal def possible_match?(times_called) times_called <= @times end def matches?(times_called) times_called == @times end def attempt?(times_called) times_called < @times end end end endrr-3.1.0/lib/rr/times_called_matchers/any_times_matcher.rb0000644000004100000410000000045514265140426023722 0ustar www-datawww-datamodule RR module TimesCalledMatchers #:nodoc: class AnyTimesMatcher < TimesCalledMatcher include NonTerminal def initialize end def matches?(times_called) true end def expected_times_message "any number of times" end end end endrr-3.1.0/lib/rr/times_called_matchers/at_most_matcher.rb0000644000004100000410000000070214265140426023373 0ustar www-datawww-datamodule RR module TimesCalledMatchers #:nodoc: class AtMostMatcher < TimesCalledMatcher include Terminal def possible_match?(times_called) times_called <= @times end def matches?(times_called) times_called <= @times end def attempt?(times_called) times_called < @times end def expected_times_message "at most #{@times.inspect} times" end end end endrr-3.1.0/lib/rr/times_called_matchers/non_terminal.rb0000644000004100000410000000134614265140426022714 0ustar www-datawww-datamodule RR module TimesCalledMatchers # Including this module marks the TimesCalledMatcher as NonTerminal. # Being NonTerminal means the Double will not "terminate" even when # called infinite times. # # The Double that uses a NonTerminal TimesCalledMatcher will # continue using the Double when passed the matching arguments. # This is done by the attempt? always returning true. # # This is in opposition to Terminal TimesCalledMatchers, where # attempt? will eventually return false. module NonTerminal #:nodoc: def terminal? false end def possible_match?(times_called) true end def attempt?(times_called) true end end end endrr-3.1.0/lib/rr/times_called_matchers/at_least_matcher.rb0000644000004100000410000000045314265140426023524 0ustar www-datawww-datamodule RR module TimesCalledMatchers #:nodoc: class AtLeastMatcher < TimesCalledMatcher include NonTerminal def matches?(times_called) times_called >= @times end def expected_times_message "at least #{@times.inspect} times" end end end endrr-3.1.0/lib/rr/times_called_matchers/times_called_matcher.rb0000644000004100000410000000215014265140426024351 0ustar www-datawww-datamodule RR module TimesCalledMatchers class TimesCalledMatcher #:nodoc: extend(Module.new do def create(value) return value if value.is_a?(TimesCalledMatcher) return IntegerMatcher.new(value) if value.is_a?(Integer) return RangeMatcher.new(value) if value.is_a?(Range ) return ProcMatcher.new(value) if value.is_a?(Proc) raise ArgumentError, "There is no TimesCalledMatcher for #{value.inspect}." end end) attr_reader :times def initialize(times) @times = times end def matches?(times_called) end def attempt?(times_called) end def error_message(times_called) "Called #{times_called.inspect} #{pluralized_time(times_called)}.\nExpected #{expected_times_message}." end def ==(other) self.class == other.class && self.times == other.times end def expected_times_message "#{@times.inspect} times" end protected def pluralized_time(times_called) (times_called == 1) ? "time" : "times" end end end end rr-3.1.0/lib/rr/times_called_matchers/proc_matcher.rb0000644000004100000410000000032414265140426022670 0ustar www-datawww-datamodule RR module TimesCalledMatchers class ProcMatcher < TimesCalledMatcher #:nodoc: include NonTerminal def matches?(times_called) @times.call(times_called) end end end endrr-3.1.0/lib/rr/times_called_matchers/range_matcher.rb0000644000004100000410000000073014265140426023022 0ustar www-datawww-datamodule RR module TimesCalledMatchers class RangeMatcher < TimesCalledMatcher #:nodoc: include Terminal def possible_match?(times_called) return true if times_called < @times.begin return true if @times.include?(times_called) return false end def matches?(times_called) @times.include?(times_called) end def attempt?(times_called) possible_match?(times_called) end end end endrr-3.1.0/lib/rr/times_called_matchers/never_matcher.rb0000644000004100000410000000064414265140426023051 0ustar www-datawww-datamodule RR module TimesCalledMatchers #:nodoc: class NeverMatcher < TimesCalledMatcher include Terminal def initialize super 0 end def possible_match?(times_called) true end def matches?(times_called) true end def attempt?(times_called) raise RR::Errors.build_error(:TimesCalledError, error_message(1)) end end end end rr-3.1.0/lib/rr/without_autohook.rb0000644000004100000410000001050414265140426017324 0ustar www-datawww-datarequire 'forwardable' require 'rr/core_ext/enumerable' require 'rr/core_ext/hash' require 'rr/core_ext/array' require 'rr/core_ext/range' require 'rr/core_ext/regexp' require 'rr/keyword_arguments' require 'rr/class_instance_method_defined' require 'rr/blank_slate' require 'rr/errors' require 'rr/errors/rr_error' require 'rr/errors/subject_does_not_implement_method_error' require 'rr/errors/subject_has_different_arity_error' require 'rr/errors/double_definition_error' require 'rr/errors/double_not_found_error' require 'rr/errors/double_order_error' require 'rr/errors/times_called_error' require 'rr/errors/spy_verification_errors/spy_verification_error' require 'rr/errors/spy_verification_errors/double_injection_not_found_error' require 'rr/errors/spy_verification_errors/invocation_count_error' require 'rr/space' require 'rr/double_definitions/strategies/strategy' require 'rr/double_definitions/strategies/strategy_methods' require 'rr/double_definitions/strategies/verification/verification_strategy' require 'rr/double_definitions/strategies/verification/mock' require 'rr/double_definitions/strategies/verification/stub' require 'rr/double_definitions/strategies/verification/dont_allow' require 'rr/double_definitions/strategies/implementation/implementation_strategy' require 'rr/double_definitions/strategies/implementation/reimplementation' require 'rr/double_definitions/strategies/implementation/strongly_typed_reimplementation' require 'rr/double_definitions/strategies/implementation/proxy' require 'rr/double_definitions/strategies/double_injection/double_injection_strategy' require 'rr/double_definitions/strategies/double_injection/instance' require 'rr/double_definitions/strategies/double_injection/any_instance_of' require 'rr/dsl' require 'rr/double_definitions/double_injections/instance' require 'rr/double_definitions/double_injections/any_instance_of' require 'rr/double_definitions/double_definition' require 'rr/injections/injection' require 'rr/injections/double_injection' require 'rr/injections/method_missing_injection' require 'rr/injections/singleton_method_added_injection' require 'rr/method_dispatches/base_method_dispatch' require 'rr/method_dispatches/method_dispatch' require 'rr/method_dispatches/method_missing_dispatch' require 'rr/hash_with_object_id_key' require 'rr/recorded_call' require 'rr/recorded_calls' require 'rr/double_definitions/double_definition_create_blank_slate' require 'rr/double_definitions/double_definition_create' require 'rr/double_definitions/child_double_definition_create' require 'rr/double' require 'rr/double_matches' require 'rr/expectations/argument_equality_expectation' require 'rr/expectations/any_argument_expectation' require 'rr/expectations/times_called_expectation' require 'rr/wildcard_matchers/anything' require 'rr/wildcard_matchers/is_a' require 'rr/wildcard_matchers/numeric' require 'rr/wildcard_matchers/boolean' require 'rr/wildcard_matchers/duck_type' require 'rr/wildcard_matchers/satisfy' require 'rr/wildcard_matchers/hash_including' require 'rr/times_called_matchers/terminal' require 'rr/times_called_matchers/non_terminal' require 'rr/times_called_matchers/times_called_matcher' require 'rr/times_called_matchers/never_matcher' require 'rr/times_called_matchers/any_times_matcher' require 'rr/times_called_matchers/integer_matcher' require 'rr/times_called_matchers/range_matcher' require 'rr/times_called_matchers/proc_matcher' require 'rr/times_called_matchers/at_least_matcher' require 'rr/times_called_matchers/at_most_matcher' require 'rr/spy_verification_proxy' require 'rr/spy_verification' require 'rr/integrations' require 'rr/integrations/decorator' require 'rr/integrations/rspec/invocation_matcher' require 'rr/integrations/rspec_2' require 'rr/integrations/minitest_4' require 'rr/integrations/minitest_4_active_support' require 'rr/integrations/minitest' require 'rr/integrations/minitest_active_support' require 'rr/deprecations' require 'rr/version' module RR class << self include DSL (RR::Space.instance_methods - Object.instance_methods).each do |method_name| class_eval((<<-METHOD), __FILE__, __LINE__ + 1) def #{method_name}(*args, &block) RR::Space.instance.__send__(:#{method_name}, *args, &block) end METHOD end attr_accessor :debug alias_method :debug?, :debug end end RR.debug = (ENV['RR_DEBUG'] == '1') rr-3.1.0/lib/rr/spy_verification.rb0000644000004100000410000000270514265140426017271 0ustar www-datawww-datamodule RR class SpyVerification def initialize(subject, method_name, args, kwargs) @subject = subject @method_name = method_name.to_sym set_argument_expectation_for_args(args, kwargs) @ordered = false once end attr_reader :argument_expectation, :method_name, :times_matcher attr_accessor :subject include RR::DoubleDefinitions::DoubleDefinition::TimesDefinitionConstructionMethods include RR::DoubleDefinitions::DoubleDefinition::ArgumentDefinitionConstructionMethods def ordered @ordered = true self end def ordered? @ordered end def call (error = RR.recorded_calls.match_error(self)) && raise(error) end def to_proc lambda do call end end def subject_inspect if subject.respond_to?(:__rr__original_inspect, true) subject.__rr__original_inspect else subject.inspect end end protected attr_writer :times_matcher def set_argument_expectation_for_args(args, kwargs) if args.empty? and kwargs.empty? # with_no_args and with actually set @argument_expectation with_no_args else if KeywordArguments.fully_supported? with(*args, **kwargs) else with(*args) end end end def install_method_callback(return_value_block) # Do nothing. This is to support DefinitionConstructionMethods end end end rr-3.1.0/lib/rr/dsl.rb0000644000004100000410000001275214265140426014501 0ustar www-datawww-datamodule RR module DSL METHODS_TO_EXCLUDE_FROM_SPYING = [ :methods, :==, :__send__, :__id__, :object_id, :class, :respond_to?, :inspect, :to_s, :respond_to_missing?, :instance_eval, :instance_exec ] include DoubleDefinitions::Strategies::StrategyMethods def mock(subject=DoubleDefinitions::DoubleDefinitionCreate::NO_SUBJECT, method_name=nil, &definition_eval_block) double_definition_create = DoubleDefinitions::DoubleDefinitionCreate.new double_definition_create.mock(subject, method_name, &definition_eval_block) end def stub(subject=DoubleDefinitions::DoubleDefinitionCreate::NO_SUBJECT, method_name=nil, &definition_eval_block) double_definition_create = DoubleDefinitions::DoubleDefinitionCreate.new double_definition_create.stub(subject, method_name, &definition_eval_block) end def dont_allow(subject=DoubleDefinitions::DoubleDefinitionCreate::NO_SUBJECT, method_name=nil, &definition_eval_block) double_definition_create = DoubleDefinitions::DoubleDefinitionCreate.new double_definition_create.dont_allow(subject, method_name, &definition_eval_block) end def proxy(subject=DoubleDefinitions::DoubleDefinitionCreate::NO_SUBJECT, method_name=nil, &definition_eval_block) double_definition_create = DoubleDefinitions::DoubleDefinitionCreate.new double_definition_create.proxy(subject, method_name, &definition_eval_block) end def strong(subject=DoubleDefinitions::DoubleDefinitionCreate::NO_SUBJECT, method_name=nil, &definition_eval_block) double_definition_create = DoubleDefinitions::DoubleDefinitionCreate.new double_definition_create.strong(subject, method_name, &definition_eval_block) end def instance_of(subject=DoubleDefinitions::DoubleDefinitionCreate::NO_SUBJECT, method_name=nil, &definition_eval_block) double_definition_create = DoubleDefinitions::DoubleDefinitionCreate.new double_definition_create.instance_of(subject, method_name, &definition_eval_block) end def any_instance_of(*args, &block) RR::DoubleDefinitions::DoubleInjections::AnyInstanceOf.call(*args, &block) end # Verifies all the DoubleInjection objects have met their # TimesCalledExpectations. def verify RR::Space.instance.verify_doubles end # Resets the registered Doubles and ordered Doubles def reset RR::Space.instance.reset end # Returns a AnyTimesMatcher. This is meant to be passed in as an argument # to Double#times. # # mock(object).method_name(anything).times(any_times) {return_value} def any_times TimesCalledMatchers::AnyTimesMatcher.new end # Sets up an Anything wildcard ArgumentEqualityExpectation # that succeeds when passed any argument. # mock(object).method_name(anything) {return_value} # object.method_name("an arbitrary value") # passes def anything RR::WildcardMatchers::Anything.new end # Sets up an IsA wildcard ArgumentEqualityExpectation # that succeeds when passed an argument of a certain type. # mock(object).method_name(is_a(String)) {return_value} # object.method_name("A String") # passes def is_a(klass) RR::WildcardMatchers::IsA.new(klass) end # Sets up an Numeric wildcard ArgumentEqualityExpectation # that succeeds when passed an argument that is ::Numeric. # mock(object).method_name(numeric) {return_value} # object.method_name(99) # passes def numeric RR::WildcardMatchers::Numeric.new end # Sets up an Boolean wildcard ArgumentEqualityExpectation # that succeeds when passed an argument that is a ::Boolean. # mock(object).method_name(boolean) {return_value} # object.method_name(false) # passes def boolean RR::WildcardMatchers::Boolean.new end # Sets up a DuckType wildcard ArgumentEqualityExpectation # that succeeds when the passed argument implements the methods. # arg = Object.new # def arg.foo; end # def arg.bar; end # mock(object).method_name(duck_type(:foo, :bar)) {return_value} # object.method_name(arg) # passes def duck_type(*args) RR::WildcardMatchers::DuckType.new(*args) end # Sets up a HashIncluding wildcard ArgumentEqualityExpectation # that succeeds when the passed argument contains at least those keys # and values of the expectation. # mock(object).method_name(hash_including(:foo => 1)) {return_value} # object.method_name({:foo => 1, :bar => 2) # passes def hash_including(expected_hash) RR::WildcardMatchers::HashIncluding.new(expected_hash) end # Sets up a Satisfy wildcard ArgumentEqualityExpectation # that succeeds when the passed argument causes the expectation's # proc to return true. # mock(object).method_name(satisfy {|arg| arg == :foo}) {return_value} # object.method_name(:foo) # passes def satisfy(expectation_proc=nil, &block) expectation_proc ||= block RR::WildcardMatchers::Satisfy.new(expectation_proc) end def spy(subject) subject_methods = subject.public_methods.map {|method_name| method_name.to_sym } methods_to_stub = subject_methods - METHODS_TO_EXCLUDE_FROM_SPYING methods_to_stub.each do |method| stub.proxy(subject, method) end end def received(subject) RR::SpyVerificationProxy.new(subject) end instance_methods.each do |name| alias_method "rr_#{name}", name end end end rr-3.1.0/lib/rr/autohook.rb0000644000004100000410000000034314265140426015541 0ustar www-datawww-datamodule RR class << self def autohook applicable_adapters.each { |adapter| adapter.load } if applicable_adapters.empty? puts "No adapters matched!" if RR.debug? end end end end RR.autohook rr-3.1.0/lib/rr/recorded_call.rb0000644000004100000410000000154114265140426016473 0ustar www-datawww-datamodule RR class RecordedCall < Struct.new(:subject, :method_name, :arguments, :keyword_arguments, :block) def inspect '[%s, %s, %s, %s, %s]' % [ subject_to_s, method_name.inspect, arguments.inspect, keyword_arguments.inspect, block.inspect ] end def ==(other) other.is_a?(self.class) && subject == other.subject && method_name == other.method_name && arguments == other.arguments && keyword_arguments == other.keyword_arguments end private def subject_to_s if subject.respond_to?(:__rr__original_to_s, true) subject.__rr__original_to_s else subject.to_s end end end end rr-3.1.0/lib/rr/expectations/0000755000004100000410000000000014265140426016071 5ustar www-datawww-datarr-3.1.0/lib/rr/expectations/argument_equality_expectation.rb0000644000004100000410000000565514265140426024573 0ustar www-datawww-datamodule RR module Expectations class ArgumentEqualityExpectation #:nodoc: def self.recursive_safe_eq(arg1, arg2) if arg1.respond_to?(:'__rr__original_==') arg1.__send__(:'__rr__original_==', arg2) else arg1 == arg2 end end attr_reader :expected_arguments attr_reader :expected_keyword_arguments def initialize(expected_arguments, expected_keyword_arguments) @expected_arguments = expected_arguments @expected_keyword_arguments = expected_keyword_arguments end def exact_match?(arguments, keyword_arguments) return false unless arguments.length == expected_arguments.length arguments.each_with_index do |arg, index| expected_arg = expected_arguments[index] return false unless self.class.recursive_safe_eq(expected_arg, arg) end keywords = keyword_arguments.keys expected_keywords = expected_keyword_arguments.keys unless keywords.length == expected_keywords.length return false end keywords.each do |keyword| keyword_argument = keyword_arguments[keyword] expected_keyword_argument = expected_keyword_arguments[keyword] unless self.class.recursive_safe_eq(expected_keyword_argument, keyword_argument) return false end end true end def wildcard_match?(arguments, keyword_arguments) return false unless arguments.length == expected_arguments.length arguments.each_with_index do |arg, index| expected_argument = expected_arguments[index] if expected_argument.respond_to?(:wildcard_match?) return false unless expected_argument.wildcard_match?(arg) else return false unless self.class.recursive_safe_eq(expected_argument, arg) end end keywords = keyword_arguments.keys expected_keywords = expected_keyword_arguments.keys unless keywords.length == expected_keywords.length return false end keywords.each do |keyword| keyword_argument = keyword_arguments[keyword] expected_keyword_argument = expected_keyword_arguments[keyword] if expected_keyword_argument.respond_to?(:wildcard_match?) unless expected_keyword_argument.wildcard_match?(keyword_argument) return false end else unless self.class.recursive_safe_eq(expected_keyword_argument, keyword_argument) return false end end end true end def ==(other) other.is_a?(self.class) and expected_arguments == other.expected_arguments and expected_keyword_arguments == other.expected_keyword_arguments end end end end rr-3.1.0/lib/rr/expectations/times_called_expectation.rb0000644000004100000410000000225514265140426023452 0ustar www-datawww-datamodule RR module Expectations class TimesCalledExpectation #:nodoc: attr_reader :double, :times_called def initialize(double) @double = double @times_called = 0 @verify_backtrace = caller[1..-1] end def attempt? times_matcher.attempt?(@times_called) end def attempt @times_called += 1 verify_input_error unless times_matcher.possible_match?(@times_called) return end def verify return false unless times_matcher.is_a?(TimesCalledMatchers::TimesCalledMatcher) return times_matcher.matches?(@times_called) end def verify! unless verify raise RR::Errors.build_error(:TimesCalledError, error_message, @verify_backtrace) end end def terminal? times_matcher.terminal? end protected def times_matcher double.definition.times_matcher end def verify_input_error raise RR::Errors.build_error(:TimesCalledError, error_message) end def error_message "#{double.formatted_name}\n#{times_matcher.error_message(@times_called)}" end end end end rr-3.1.0/lib/rr/expectations/any_argument_expectation.rb0000644000004100000410000000061414265140426023513 0ustar www-datawww-datamodule RR module Expectations class AnyArgumentExpectation < ArgumentEqualityExpectation #:nodoc: def initialize super([], {}) end def exact_match?(arguments, keyword_arguments) false end def wildcard_match?(arguments, keyword_arguments) true end def ==(other) other.is_a?(self.class) end end end end rr-3.1.0/lib/rr/double.rb0000644000004100000410000001170014265140426015161 0ustar www-datawww-datamodule RR # RR::Double is the use case for a method call. # It has the ArgumentEqualityExpectation, TimesCalledExpectation, # and the implementation. class Double extend(Module.new do def formatted_name(method_name, args, kwargs) formatted_arguments = args.collect {|arg| arg.inspect} + kwargs.collect {|keyword, value| "#{keyword}: #{value.inspect}"} formatted_errors = formatted_arguments.join(', ') "#{method_name}(#{formatted_errors})" end def list_message_part(doubles) doubles.collect do |double| name = formatted_name(double.method_name, double.expected_arguments, double.expected_keyword_arguments) "- #{name}" end.join("\n") end end) attr_reader :times_called, :double_injection, :definition, :times_called_expectation include Space::Reader def initialize(double_injection, definition) @double_injection = double_injection @definition = definition @times_called = 0 @times_called_expectation = Expectations::TimesCalledExpectation.new(self) definition.double = self verify_method_signature if definition.verify_method_signature? double_injection.register_double self end # Double#exact_match? returns true when the passed in arguments # exactly match the ArgumentEqualityExpectation arguments. def exact_match?(arguments, keyword_arguments) definition.exact_match?(arguments, keyword_arguments) end # Double#wildcard_match? returns true when the passed in arguments # wildcard match the ArgumentEqualityExpectation arguments. def wildcard_match?(arguments, keyword_arguments) definition.wildcard_match?(arguments, keyword_arguments) end # Double#attempt? returns true when the # TimesCalledExpectation is satisfied. def attempt? verify_times_matcher_is_set times_called_expectation.attempt? end # Double#verify verifies the the TimesCalledExpectation # is satisfied for this double. A TimesCalledError # is raised if the TimesCalledExpectation is not met. def verify verify_times_matcher_is_set times_called_expectation.verify! true end def terminal? verify_times_matcher_is_set times_called_expectation.terminal? end # The method name that this Double is attatched to def method_name double_injection.method_name end # The Arguments that this Double expects def expected_arguments verify_argument_expectation_is_set argument_expectation.expected_arguments end # The keyword arguments that this Double expects def expected_keyword_arguments verify_argument_expectation_is_set argument_expectation.expected_keyword_arguments end # The TimesCalledMatcher for the TimesCalledExpectation def times_matcher definition.times_matcher end def formatted_name self.class.formatted_name(method_name, expected_arguments, expected_keyword_arguments) end def method_call(args, kwargs) if verbose? puts Double.formatted_name(method_name, args, kwargs) end times_called_expectation.attempt if definition.times_matcher space.verify_ordered_double(self) if ordered? end def implementation_is_original_method? definition.implementation_is_original_method? end protected def ordered? definition.ordered? end def verbose? definition.verbose? end def verify_times_matcher_is_set unless definition.times_matcher raise RR::Errors.build_error(:DoubleDefinitionError, "#definition.times_matcher is not set") end end def verify_argument_expectation_is_set unless definition.argument_expectation raise RR::Errors.build_error(:DoubleDefinitionError, "#definition.argument_expectation is not set") end end def verify_method_signature unless double_injection.subject_has_original_method? raise RR::Errors.build_error(:SubjectDoesNotImplementMethodError) end raise RR::Errors.build_error(:SubjectHasDifferentArityError) unless arity_matches? end def subject_arity double_injection.original_method.arity end def subject_accepts_only_varargs? subject_arity == -1 end def subject_accepts_varargs? subject_arity < 0 end def arity_matches? return true if subject_accepts_only_varargs? if subject_accepts_varargs? return ((subject_arity * -1) - 1) <= args.size else return subject_arity == args.size end end def args definition.argument_expectation.expected_arguments end def kwargs definition.argument_expectation.expected_keyword_arguments end def argument_expectation definition.argument_expectation end end end rr-3.1.0/lib/rr/class_instance_method_defined.rb0000644000004100000410000000077614265140426021731 0ustar www-datawww-datamodule RR module ClassInstanceMethodDefined def class_instance_method_defined(klass, instance_method, include_super=true) klass.instance_methods(include_super).detect {|method_name| method_name.to_sym == instance_method.to_sym} || klass.protected_instance_methods(include_super).detect {|method_name| method_name.to_sym == instance_method.to_sym} || klass.private_instance_methods(include_super).detect {|method_name| method_name.to_sym == instance_method.to_sym} end end end rr-3.1.0/lib/rr/recorded_calls.rb0000644000004100000410000001017614265140426016662 0ustar www-datawww-datamodule RR class RecordedCalls include RR::Space::Reader def initialize(recorded_calls=[]) @recorded_calls = recorded_calls @ordered_index = 0 end attr_reader :recorded_calls def [](index) @recorded_calls[index] end def clear self.ordered_index = 0 recorded_calls.clear end def add(subject, method_name, arguments, keyword_arguments, block) recorded_calls << RecordedCall.new(subject, method_name, arguments, keyword_arguments, block) end def any?(&block) recorded_calls.any?(&block) end def ==(other) recorded_calls == other.recorded_calls end def match_error(spy_verification) double_injection_exists_error(spy_verification) || begin if spy_verification.ordered? ordered_match_error(spy_verification) else unordered_match_error(spy_verification) end end end protected attr_accessor :ordered_index def double_injection_exists_error(spy_verification) unless Injections::DoubleInjection.exists_by_subject?(spy_verification.subject, spy_verification.method_name) RR::Errors.build_error(RR::Errors::SpyVerificationErrors::DoubleInjectionNotFoundError, "A Double Injection for the subject and method call:\n" << "#{spy_verification.subject_inspect}\n" << "#{spy_verification.method_name}\ndoes not exist in:\n" << "\t#{recorded_calls.map {|call| call.inspect }.join("\n\t")}" ) end end def ordered_match_error(spy_verification) memoized_matching_recorded_calls = matching_recorded_calls(spy_verification) if memoized_matching_recorded_calls.last self.ordered_index = recorded_calls.index(memoized_matching_recorded_calls.last) end (0..memoized_matching_recorded_calls.size).to_a.any? do |i| spy_verification.times_matcher.matches?(i) end ? nil : invocation_count_error(spy_verification, memoized_matching_recorded_calls) end def unordered_match_error(spy_verification) memoized_matching_recorded_calls = matching_recorded_calls(spy_verification) spy_verification.times_matcher.matches?( memoized_matching_recorded_calls.size ) ? nil : invocation_count_error(spy_verification, memoized_matching_recorded_calls) end def matching_recorded_calls(spy_verification) recorded_calls[ordered_index..-1]. select(&match_double_injection(spy_verification)). select(&match_argument_expectation(spy_verification)) end def match_double_injection(spy_verification) lambda do |recorded_call| recorded_call.subject == spy_verification.subject && recorded_call.method_name == spy_verification.method_name end end def match_argument_expectation(spy_verification) lambda do |recorded_call| expectation = spy_verification.argument_expectation arguments = recorded_call.arguments keyword_arguments = recorded_call.keyword_arguments expectation.exact_match?(arguments, keyword_arguments) || expectation.wildcard_match?(arguments, keyword_arguments) end end def invocation_count_error(spy_verification, matching_recorded_calls) method_name = spy_verification.method_name arguments = spy_verification.argument_expectation.expected_arguments keyword_arguments = spy_verification.argument_expectation.expected_keyword_arguments RR::Errors.build_error(RR::Errors::SpyVerificationErrors::InvocationCountError, "On subject #{spy_verification.subject.inspect}\n" << "Expected #{Double.formatted_name(method_name, arguments, keyword_arguments)}\n" << "to be called #{spy_verification.times_matcher.expected_times_message},\n" << "but was called #{matching_recorded_calls.size} times.\n" << "All of the method calls related to Doubles are:\n" << "\t#{recorded_calls.map {|call| call.inspect}.join("\n\t")}" ) end end end rr-3.1.0/lib/rr/double_matches.rb0000644000004100000410000000252114265140426016666 0ustar www-datawww-datamodule RR class DoubleMatches attr_reader :matching_doubles, :exact_terminal_doubles_to_attempt, :exact_non_terminal_doubles_to_attempt, :wildcard_terminal_doubles_to_attempt, :wildcard_non_terminal_doubles_to_attempt def initialize(doubles) #:nodoc: @doubles = doubles @matching_doubles = [] @exact_terminal_doubles_to_attempt = [] @exact_non_terminal_doubles_to_attempt = [] @wildcard_terminal_doubles_to_attempt = [] @wildcard_non_terminal_doubles_to_attempt = [] end def find_all_matches(args, kwargs) kwargs ||= {} @doubles.each do |double| if double.exact_match?(args, kwargs) matching_doubles << double if double.attempt? if double.terminal? exact_terminal_doubles_to_attempt << double else exact_non_terminal_doubles_to_attempt << double end end elsif double.wildcard_match?(args, kwargs) matching_doubles << double if double.attempt? if double.terminal? wildcard_terminal_doubles_to_attempt << double else wildcard_non_terminal_doubles_to_attempt << double end end end end self end end end rr-3.1.0/lib/rr/blank_slate.rb0000644000004100000410000000104314265140426016165 0ustar www-datawww-datamodule RR module BlankSlate extend(Module.new do def call(klass) klass.instance_eval do instance_methods.each do |unformatted_method_name| method_name = unformatted_method_name.to_s unless method_name =~ /^_/ || Space.blank_slate_whitelist.any? {|whitelisted_method_name| method_name == whitelisted_method_name} alias_method "__blank_slated_#{method_name}", method_name undef_method method_name end end end end end) end endrr-3.1.0/lib/rr/space.rb0000644000004100000410000001016214265140426015003 0ustar www-datawww-datamodule RR # RR::Space.instance is the global state subject for the RR framework. class Space module Reader def space RR::Space.instance end end class << self def instance @instance ||= new end attr_writer :instance protected if KeywordArguments.fully_supported? def method_missing(method_name, *args, **kwargs, &block) instance.__send__(method_name, *args, **kwargs, &block) end else def method_missing(method_name, *args, &block) instance.__send__(method_name, *args, &block) end ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true) end end attr_reader :ordered_doubles, :recorded_calls attr_accessor :trim_backtrace def initialize @ordered_doubles = [] @trim_backtrace = false @recorded_calls = RR::RecordedCalls.new end # Registers the ordered Double to be verified. def register_ordered_double(double) @ordered_doubles << double unless ordered_doubles.include?(double) end # Verifies that the passed in ordered Double is being called # in the correct position. def verify_ordered_double(double) unless double.terminal? raise RR::Errors.build_error(:DoubleOrderError, "Ordered Doubles cannot have a NonTerminal TimesCalledExpectation") end unless @ordered_doubles.first == double message = Double.formatted_name(double.method_name, double.expected_arguments) message << " called out of order in list\n" message << Double.list_message_part(@ordered_doubles) raise RR::Errors.build_error(:DoubleOrderError, message) end @ordered_doubles.shift unless double.attempt? double end # Verifies all the DoubleInjection objects have met their # TimesCalledExpectations. def verify_doubles(*subjects) Injections::DoubleInjection.verify(*subjects) end alias_method :verify, :verify_doubles # Resets the registered Doubles and ordered Doubles def reset RR.trim_backtrace = false RR.overridden_error_class = nil reset_ordered_doubles Injections::DoubleInjection.reset reset_method_missing_injections reset_singleton_method_added_injections reset_recorded_calls reset_bound_objects end # Verifies the DoubleInjection for the passed in subject and method_name. def verify_double(subject, method_name) Injections::DoubleInjection.verify_double(class << subject; self; end, method_name) end # Resets the DoubleInjection for the passed in subject and method_name. def reset_double(subject, method_name) Injections::DoubleInjection.reset_double(class << subject; self; end, method_name) end def record_call(subject, method_name, arguments, keyword_arguments, block) @recorded_calls.add(subject, method_name, arguments, keyword_arguments, block) end def blank_slate_whitelist @blank_slate_whitelist ||= [ "object_id", "respond_to?", "respond_to_missing?", "method_missing", "instance_eval", "instance_exec", "class_eval" ] end protected # Removes the ordered Doubles from the list def reset_ordered_doubles @ordered_doubles.clear end def reset_method_missing_injections Injections::MethodMissingInjection.instances.each do |subject_class, injection| injection.reset end Injections::MethodMissingInjection.instances.clear end def reset_singleton_method_added_injections Injections::SingletonMethodAddedInjection.instances.each do |subject, injection| injection.reset end Injections::SingletonMethodAddedInjection.instances.clear end def reset_recorded_calls @recorded_calls.clear end def reset_bound_objects # TODO: Figure out how to clear and reset these bindings #RR::Injections::DoubleInjection::BoundObjects.clear #RR::Injections::DoubleInjection::MethodMissingInjection.clear end end end rr-3.1.0/doc/0000755000004100000410000000000014265140426012737 5ustar www-datawww-datarr-3.1.0/doc/03_api_overview.md0000644000004100000410000003351214265140426016266 0ustar www-datawww-data# API overview To create a double on an object, you can use the following methods: * #mock / #mock! * #stub / #stub! * #dont_allow / #dont_allow! * #proxy / #proxy! * #instance_of / #instance_of! These methods are composable. #mock, #stub, and #dont_allow can be used by themselves and are mutually exclusive. #proxy and #instance_of must be chained with #mock or #stub. You can also chain #proxy and #instance_of together. The ! (bang) version of these methods causes the subject object of the Double to be instantiated. ## #mock \#mock replaces the method on the object with an expectation and implementation. The expectations are a mock will be called with certain arguments a certain number of times (the default is once). You can also set the return value of the method invocation. *Learn more: * The following example sets an expectation that the view will receive a method call to #render with the arguments `{:partial => "user_info"}` once. When the method is called, `"Information"` is returned. ~~~ ruby view = controller.template mock(view).render(:partial => "user_info") {"Information"} ~~~ You can also allow any number of arguments to be passed into the mock like this: ~~~ ruby mock(view).render.with_any_args.twice do |*args| if args.first == {:partial => "user_info"} "User Info" else "Stuff in the view #{args.inspect}" end end ~~~ ## #stub \#stub replaces the method on the object with only an implementation. You can still use arguments to differentiate which stub gets invoked. *Learn more: * The following example makes the User.find method return `jane` when passed "42" and returns `bob` when passed "99". If another id is passed to User.find, an exception is raised. ~~~ ruby jane = User.new bob = User.new stub(User).find('42') {jane} stub(User).find('99') {bob} stub(User).find do |id| raise "Unexpected id #{id.inspect} passed to me" end ~~~ ## #dont_allow (aliased to #do_not_allow, #dont_call, and #do_not_call) \#dont_allow is the opposite of #mock -- it sets an expectation on the Double that it will never be called. If the Double actually does end up being called, a TimesCalledError is raised. ~~~ ruby dont_allow(User).find('42') User.find('42') # raises a TimesCalledError ~~~ ## `mock.proxy` `mock.proxy` replaces the method on the object with an expectation, implementation, and also invokes the actual method. `mock.proxy` also intercepts the return value and passes it into the return value block. The following example makes sets an expectation that `view.render({:partial => "right_navigation"})` gets called once and returns the actual content of the rendered partial template. A call to `view.render({:partial => "user_info"})` will render the "user_info" partial template and send the content into the block and is represented by the `html` variable. An assertion is done on the value of `html` and `"Different html"` is returned. ~~~ ruby view = controller.template mock.proxy(view).render(:partial => "right_navigation") mock.proxy(view).render(:partial => "user_info") do |html| html.should include("John Doe") "Different html" end ~~~ You can also use `mock.proxy` to set expectations on the returned value. In the following example, a call to User.find('5') does the normal ActiveRecord implementation and passes the actual value, represented by the variable `bob`, into the block. `bob` is then set with a `mock.proxy` for projects to return only the first 3 projects. `bob` is also mocked so that #valid? returns false. ~~~ ruby mock.proxy(User).find('5') do |bob| mock.proxy(bob).projects do |projects| projects[0..3] end mock(bob).valid? { false } bob end ~~~ ## `stub.proxy` Intercept the return value of a method call. The following example verifies `render(:partial)` will be called and renders the partial. ~~~ ruby view = controller.template stub.proxy(view).render(:partial => "user_info") do |html| html.should include("Joe Smith") html end ~~~ ## #any_instance_of Allows stubs to be added to all instances of a class. It works by binding to methods from the class itself, rather than the eigenclass. This allows all instances (excluding instances with the method redefined in the eigenclass) to get the change. Due to Ruby runtime limitations, mocks will not work as expected. It's not obviously feasible (without an ObjectSpace lookup) to support all of RR's methods (such as mocking). ObjectSpace is not readily supported in JRuby, since it causes general slowness in the interpreter. I'm of the opinion that test speed is more important than having mocks on all instances of a class. If there is another solution, I'd be willing to add it. ~~~ ruby any_instance_of(User) do |u| stub(u).valid? { false } end or any_instance_of(User, :valid? => false) or any_instance_of(User, :valid? => lambda { false }) ~~~ ## Spies Adding a DoubleInjection to an object + method (done by #stub, #mock, or \#dont_allow) causes RR to record any method invocations to the object + method. Assertions can then be made on the recorded method calls. ### Test::Unit ~~~ ruby subject = Object.new stub(subject).foo subject.foo(1) assert_received(subject) {|subject| subject.foo(1) } assert_received(subject) {|subject| subject.bar } # This fails ~~~ ### RSpec ~~~ ruby subject = Object.new stub(subject).foo subject.foo(1) subject.should have_received.foo(1) subject.should have_received.bar # This fails ~~~ ## Block syntax The block syntax has two modes: * A normal block mode with a DoubleDefinitionCreatorProxy argument: ~~~ ruby script = MyScript.new mock(script) do |expect| expect.system("cd #{RAILS_ENV}") {true} expect.system("rake foo:bar") {true} expect.system("rake baz") {true} end ~~~ * An instance_eval mode where the DoubleDefinitionCreatorProxy is instance_eval'ed: ~~~ ruby script = MyScript.new mock(script) do system("cd #{RAILS_ENV}") {true} system("rake foo:bar") {true} system("rake baz") {true} end ~~~ ## Double graphs RR has a method-chaining API support for double graphs. For example, let's say you want an object to receive a method call to #foo, and have the return value receive a method call to #bar. In RR, you would do: ~~~ ruby stub(object).foo.stub!.bar { :baz } object.foo.bar #=> :baz or: stub(object).foo { stub!.bar {:baz} } object.foo.bar #=> :baz or: bar = stub!.bar { :baz } stub(object).foo { bar } object.foo.bar #=> :baz ~~~ ## Modifying doubles Whenever you create a double by calling a method on an object you've wrapped, you get back a special object: a DoubleDefinition. In other words: ~~~ ruby stub(object).foo #=> RR::DoubleDefinitions::DoubleDefinition ~~~ There are several ways you can modify the behavior of these doubles via the DoubleDefinition API, and they are listed in this section. Quick note: all of these methods accept blocks as a shortcut for setting the return value at the same time. In other words, if you have something like this: ~~~ ruby mock(object).foo { 'bar' } ~~~ you can modify the mock and keep the return value like so: ~~~ ruby mock(object).foo.times(2) { 'bar' } ~~~ You can even flip around the block: ~~~ ruby mock(object).foo { 'bar' }.times(2) ~~~ And as we explain below, this is just a shortcut for: ~~~ ruby mock(object).foo.returns { 'bar' }.times(2) ~~~ ### Stubbing method implementation / return value There are two ways here. We have already covered this usage: ~~~ ruby stub(object).foo { 'bar' } ~~~ However, you can also use #returns if it's more clear to you: ~~~ ruby stub(object).foo.returns { 'bar' } ~~~ Regardless, keep in mind that you're actually supplying the implementation of the method in question here, so you can put whatever you want in this block: ~~~ ruby stub(object).foo { |age, count| raise 'hell' if age < 16 ret = yield count blue? ? ret : 'whatever' } ~~~ This works for mocks as well as stubs. ### Stubbing method implementation based on argument expectation A double's implementation is always tied to its argument expectation. This means that it is possible to return one value if the method is called one way and return a second value if the method is called a second way. For example: ~~~ ruby stub(object).foo { 'bar' } stub(object).foo(1, 2) { 'baz' } object.foo #=> 'bar' object.foo(1, 2) #=> 'baz' ~~~ This works for mocks as well as stubs. ### Stubbing method to yield given block If you need to stub a method such that a block given to it is guaranteed to be called when the method is called, then use #yields. ~~~ ruby This outputs: [1, 2, 3] stub(object).foo.yields(1, 2, 3) object.foo {|*args| pp args } ~~~ This works for mocks as well as stubs. ### Expecting method to be called with exact argument list There are two ways to do this. Here is the way we have shown before: ~~~ ruby mock(object).foo(1, 2) object.foo(1, 2) # ok object.foo(3) # fails ~~~ But if this is not clear enough to you, you can use #with: ~~~ ruby mock(object).foo.with(1, 2) object.foo(1, 2) # ok object.foo(3) # fails ~~~ As seen above, if you create an the expectation for a set of arguments and the method is called with another set of arguments, even if *those* arguments are of a completely different size, you will need to create another expectation for them somehow. A simple way to do this is to #stub the method beforehand: ~~~ ruby stub(object).foo mock(object).foo(1, 2) object.foo(1, 2) # ok object.foo(3) # ok too ~~~ ### Expecting method to be called with any arguments Use #with_any_args: ~~~ ruby mock(object).foo.with_any_args object.foo # ok object.foo(1) # also ok object.foo(1, 2) # also ok # ... you get the idea ~~~ ### Expecting method to be called with no arguments Use #with_no_args: ~~~ ruby mock(object).foo.with_no_args object.foo # ok object.foo(1) # fails ~~~ ### Expecting method to never be called Use #never: ~~~ ruby mock(object).foo.never object.foo # fails ~~~ You can also narrow the negative expectation to a specific set of arguments. Of course, you will still need to set explicit expectations for any other ways that your method could be called. For instance: ~~~ ruby mock(object).foo.with(1, 2).never object.foo(3, 4) # fails ~~~ RR will complain here that this is an unexpected invocation, so we need to add an expectation for this beforehand. We can do this easily with #stub: ~~~ ruby stub(object).foo ~~~ So, a full example would look like: ~~~ ruby stub(object).foo mock(object).foo.with(1, 2).never object.foo(3, 4) # ok object.foo(1, 2) # fails ~~~ Alternatively, you can also use #dont_allow, although the same rules apply as above: ~~~ ruby stub(object).foo dont_allow(object).foo.with(1, 2) object.foo(3, 4) # ok object.foo(1, 2) # fails ~~~ ### Expecting method to be called only once Use #once: ~~~ ruby mock(object).foo.once object.foo object.foo # fails ~~~ ### Expecting method to called exact number of times Use #times: ~~~ ruby mock(object).foo.times(3) object.foo object.foo object.foo object.foo # fails ~~~ ### Expecting method to be called minimum number of times Use #at_least. For instance, this would pass: ~~~ ruby mock(object).foo.at_least(3) object.foo object.foo object.foo object.foo ~~~ But this would fail: ~~~ ruby mock(object).foo.at_least(3) object.foo object.foo ~~~ ### Expecting method to be called maximum number of times Use #at_most. For instance, this would pass: ~~~ ruby mock(object).foo.at_most(3) object.foo object.foo ~~~ But this would fail: ~~~ ruby mock(object).foo.at_most(3) object.foo object.foo object.foo object.foo ~~~ ### Expecting method to be called any number of times Use #any_times. This effectively disables the times-called expectation. ~~~ ruby mock(object).foo.any_times object.foo object.foo object.foo ... ~~~ You can also use #times + the argument invocation #any_times matcher: ~~~ ruby mock(object).foo.times(any_times) object.foo object.foo object.foo ... ~~~ ## Argument wildcard matchers RR also has several methods which you can use with argument expectations which act as placeholders for arguments. When RR goes to verify the argument expectation it will compare the placeholders with the actual arguments the method was called with, and if they match then the test passes (hence "matchers"). ### #anything Matches any value. ~~~ ruby mock(object).foobar(1, anything) object.foobar(1, :my_symbol) ~~~ ### #is_a Matches an object which `.is_a?(*Class*)`. ~~~ ruby mock(object).foobar(is_a(Time)) object.foobar(Time.now) ~~~ ### #numeric Matches a value which `.is_a?(Numeric)`. ~~~ ruby mock(object).foobar(numeric) object.foobar(99) ~~~~ ### #boolean Matches true or false. ~~~ ruby mock(object).foobar(boolean) object.foobar(false) ~~~ ### #duck_type Matches an object which responds to certain methods. ~~~ ruby mock(object).foobar(duck_type(:walk, :talk)) arg = Object.new def arg.walk; 'waddle'; end def arg.talk; 'quack'; end object.foobar(arg) ~~~ ### Ranges Matches a number within a certain range. ~~~ ruby mock(object).foobar(1..10) object.foobar(5) ~~~ ### Regexps Matches a string which matches a certain regex. ~~~ ruby mock(object).foobar(/on/) object.foobar("ruby on rails") ~~~ ### #hash_including Matches a hash which contains a subset of keys and values. ~~~ ruby mock(object).foobar(hash_including(:red => "#FF0000", :blue => "#0000FF")) object.foobar({:red => "#FF0000", :blue => "#0000FF", :green => "#00FF00"}) ~~~ ### #satisfy Matches an argument which satisfies a custom requirement. ~~~ ruby mock(object).foobar(satisfy {|arg| arg.length == 2 }) object.foobar("xy") ~~~ ### Writing your own argument matchers Writing a custom argument wildcard matcher is not difficult. See RR::WildcardMatchers for details. ## Invocation amount wildcard matchers ### #any_times Only used with #times and matches any number. ~~~ ruby mock(object).foo.times(any_times) { return_value } object.foo object.foo object.foo ... ~~~ rr-3.1.0/doc/01_test_double.md0000644000004100000410000000067214265140426016077 0ustar www-datawww-data# What is a test double? A test double is a generalization of something that replaces a real object to make it easier to test another object. It's like a stunt double for tests. The following are test doubles: * Mocks * Stubs * Fakes * Spies * Proxies *Learn more: * Currently RR implements mocks, stubs, proxies, and spies. Fakes usually require custom code, so it is beyond the scope of RR. rr-3.1.0/doc/02_syntax_comparison.md0000644000004100000410000000533614265140426017351 0ustar www-datawww-data# Syntax between RR and other double/mock frameworks ## Terse syntax One of the goals of RR is to make doubles more scannable. This is accomplished by making the double declaration look as much as the actual method invocation as possible. Here is RR compared to other mock frameworks: ~~~ ruby # Flexmock flexmock(User).should_receive(:find).with('42').and_return(jane) # Mocha User.expects(:find).with('42').returns { jane } # rspec-mocks User.should_receive(:find).with('42') { jane } # RR mock(User).find('42') { jane } ~~~ ## Double injections (aka partial mocking) RR utilizes a technique known as "double injection". ~~~ ruby my_object = MyClass.new mock(my_object).hello ~~~ Compare this with doing a mock in Mocha: ~~~ ruby my_mocked_object = mock() my_mocked_object.expects(:hello) ~~~ ## Pure mock objects If you wish to use objects for the sole purpose of being a mock, you can do so by creating an empty object: ~~~ ruby mock(my_mock_object = Object.new).hello ~~~ However as a shortcut you can also use #mock!: ~~~ ruby # Create a new mock object with an empty #hello method, then retrieve that mock # object via the #subject method my_mock_object = mock!.hello.subject ~~~ ## No #should_receive or #expects method RR uses #method_missing to set your method expectation. This means you do not need to use a method such as #should_receive or #expects. ~~~ ruby # In Mocha, #expects sets the #hello method expectation: my_object.expects(:hello) # Using rspec-mocks, #should_receive sets the #hello method expectation: my_object.should_receive(:hello) # And here's how you say it using RR: mock(my_object).hello ~~~ ## #with method call is not necessary The fact that RR uses #method_missing also makes using the #with method unnecessary in most circumstances to set the argument expectation itself (although you can still use it if you want): ~~~ ruby # Mocha my_object.expects(:hello).with('bob', 'jane') # rspec-mocks my_object.should_receive(:hello).with('bob', 'jane') # RR mock(my_object).hello('bob', 'jane') mock(my_object).hello.with('bob', 'jane') # same thing, just more verbose ~~~ ## Using a block to set the return value RR supports using a block to set the return value as opposed to a specific method call (although again, you can use #returns if you like): ~~~ ruby # Mocha my_object.expects(:hello).with('bob', 'jane').returns('Hello Bob and Jane') # rspec-mocks my_object.should_receive(:hello).with('bob', 'jane') { 'Hello Bob and Jane' } my_object.should_receive(:hello).with('bob', 'jane').and_return('Hello Bob and Jane') # same thing, just more verbose # RR mock(my_object).hello('bob', 'jane') { 'Hello Bob and Jane' } mock(my_object).hello('bob', 'jane').returns('Hello Bob and Jane') # same thing, just more verbose ~~~ rr-3.1.0/CREDITS.md0000644000004100000410000000476714265140426013627 0ustar www-datawww-data# Credits ## Maintainer * Kouhei Sutou ([@kou](https://github.com/kou)) ## Authors * Brian Takita ([@btakita](http://github.com/btakita)) * Elliot Winkler ([@mcmire](http://github.com/mcmire)) ## Contributors * Andreas Haller ([@ahx](http://github.com/ahx)) * Bryan Helmkamp ([@brynary](http://github.com/brynary)) * [@bonkydog](http://github.com/bonkydog) * Caleb Spare ([@cespare](http://github.com/cespare)) * Christopher Redinger ([@redinger](http://github.com/redinger)) * David Chelimsky ([@dchelimsky](http://github.com/dchelimsky)) * David Padilla ([@dabit](http://github.com/dabit)) * Dmitry Ratnikov ([@ratnikov](http://github.com/ratnikov)) * Eugene Pimenov ([@libc](http://github.com/libc)) * Evan Phoenix ([@evanphx](http://github.com/evanphx)) * Gabriel Horner ([@cldwalker](http://github.com/cldwalker)) * Gavin Miller ([@gavingmiller](http://github.com/gavingmiller)) * James McCarthy ([@james2m](http://github.com/james2m)) * Jan Nelson * Jay Adkisson ([@jayferd](http://github.com/jayferd)) * Joe Ferris ([@jferris](http://github.com/jferris)) * Matt Buck ([@techpeace](http://github.com/techpeace)) * Matthew O'Connor * Michael Niessner ([@niessner](http://github.com/niessner)) * Mike Mangino ([@mmangino](http://github.com/mmangino)) * Nathan Sobo ([@nathansobo](http://github.com/nathansobo)) * Nick Kallen ([@nkallen](http://github.com/nkallen)) * Nick Novitski ([@nicknovitski](http://github.com/nicknovitski)) * Phil Darnowsky ([@phildarnowsky](http://github.com/phildarnowsky)) * Steven R. Baker ([@srbaker](http://github.com/srbaker)) * Tatsuya Ono ([@ono](http://github.com/ono)) * Thibaut Corouble ([@thibaut](http://github.com/thibaut)) * Wincent Colaiuta ([@wincent](http://github.com/wincent)) * [@wynst](http://github.com/wynst) ## Honorable mentions * Aslak Hellesoy for developing RSpec * Dan North for syntax ideas * Dave Astels for some BDD inspiration * Dave Myron for a bug report * David Chelimsky for encouragement to make the RR framework, for developing the RSpec mock framework, syntax ideas, and patches * Daniel Sudol for identifing performance issues with RR * Gerard Meszaros for his excellent book "xUnit Test Patterns" * Felix Morio for pairing * James Mead for developing Mocha * Jeff Whitmire for documentation suggestions * Jim Weirich for developing Flexmock, the first terse ruby mock framework in Ruby * Myron Marston for bug reports * Parker Thompson for pairing * Pivotal Labs for sponsoring RR development * Steven Baker for developing RSpec * Tuomas Kareinen for a bug report rr-3.1.0/Gemfile0000644000004100000410000000023514265140426013465 0ustar www-datawww-datasource 'https://rubygems.org' gemspec case ENV["RR_INTEGRATION"] when "minitest" gem "minitest" when "minitest-active-support" gem "activesupport" end rr-3.1.0/CHANGES.md0000644000004100000410000004645514265140426013602 0ustar www-datawww-data# Changelog ## 3.1.0 - 2022-07-14 ### Improvements * Improved CI. [GitHub#89](https://github.com/rr/rr/pull/89)[Patch by Peter Goldstein] [GitHub#90](https://github.com/rr/rr/pull/90)[Patch by mishina] [GitHub#91](https://github.com/rr/rr/pull/91)[Patch by mishina] * Improved `wildcard_match?` against `Hash`. [GitHub#94](https://github.com/rr/rr/issues/94) [Reported by kawamotosatoshi] ### Fixes * Fixed document. [GitHub#92](https://github.com/rr/rr/pull/92)[Patch by mishina] ### Thanks * Peter Goldstein * mishina * kawamotosatoshi ## 3.0.9 - 2021-12-07 ### Improvements * Marked TruffleRuby as "keyword arguments aren't fully supported yet". ## 3.0.8 - 2021-10-17 ### Fixes * Minitest integration: Fixed a bug that `NameError` is raised. [GitHub#88][Reported by Matijs van Zuijlen] ### Thanks * Matijs van Zuijlen ## 3.0.7 - 2021-08-17 ### Fixes * Minitest + Active Support integration: Fixed a bug that `stub` in `setup {...}` is ignored. [GitHub#87][Reported by Boris] ### Thanks * Boris ## 3.0.6 - 2021-08-07 ### Improvements * `assert_received`: Added support for keyword arguments. [GitHub#86][Reported by imadoki] ### Thanks * imadoki ## 3.0.5 - 2021-06-26 ### Improvements * Improved keyword arguments support on Ruby 2.7. [GitHub#85][Patch by akira yamada] ### Thanks * akira yamada ## 3.0.4 - 2021-06-23 ### Fixes * Fix inverted condition in keyword arguments related code. [GitHub#84][Patch by akira yamada] ### Thanks * akira yamada ## 3.0.3 - 2021-06-22 ### Improvements * Improved keyword arguments support. [GitHub#83][Patch by akira yamada] ### Thanks * akira yamada ## 3.0.2 - 2021-06-18 ### Improvements * `stub`: Added support for Ruby 3.0's keyword arguments. [GitHub#82][Reported by akira yamada] ### Thanks * akira yamada ## 3.0.1 - 2021-06-18 ### Improvements * Suppressed keyword arguments related warnings on Ruby 2.7. [GitHub#81][Reported by akira yamada] ### Thanks * akira yamada ## 3.0.0 - 2021-03-31 ### Improvements * Added support for Ruby 3.0's keyword arguments. [GitHub#77][Reported by Takuro Ashie] ### Fixes * Fixed a bug that `any_instance_of` doesn't work with class hierarchies. [GitHub#12][Reported by Étienne Barrié] ### Thanks * Étienne Barrié * Takuro Ashie ## 1.2.1 - 2017-06-22 ### Fixes * Fixed a bug that `RR.reset` resets newly created methods. [GitHub#8] ## 1.2.0 - 2016-05-30 ### Improvements * Renamed RR::Adapters::RRMethods to RR::DSL. * Deprecated RRMethods. * Updated document. [GitHub#57][Patch by Nikolay Shebanov] * Dropped Ruby 1.8 support. * Dropped Ruby 1.9 support. * Dropped Rails 3 support. * Dropped test-unit integration support. Use [test-unit-rr](https://test-unit.github.io/#test-unit-rr). * Supported OpenStruct in Ruby 2.3 [GitHub#64][Reported by soylent][Reported by Arthur Le Maitre] ### Fixes * Fixed using RSpec's RR adapter to not override our RSpec adapter. If RR is required and then you use `mock_with :rr` you would not be able to use `have_received`. * Fixed a bug that `Hash` argument is too wild. [GitHub#54][Reported by Yutaka HARA] * Fixed a bug that `Array` argument is too wild. [GitHub#54][Reported by Skye Shaw] ### Thanks * Nikolay Shebanov * Yutaka HARA * Skye Shaw * soylent * Arthur Le Maitre ## 1.1.2 (August 17, 2013) * Add tests, appraisals, etc. back to the published gem ([#32][i32]). This is necessary because Debian wraps rr in a package, and they depend on the tests to be present in order to run them prior to packaging. * Add back RR::Adapters::RSpec2 which was removed accidentally ([#34][i34]). This fixes failures when running tests against sham_rack (which is no longer using RR, but, oh well). * Remove deprecation warning about RSpec.configuration.backtrace_clean_patterns under RSpec 2.14 ([#37][i37]). NOTE: This warning will continue to appear if you are configuring RSpec using `mock_with :rr`. This is because the RR adapter bundled with RSpec still refers to `backtrace_clean_patterns` instead of `backtrace_exclusion_patterns`. You can either wait until the next release of rspec-core, or remove `mock_with :rr` (which is recommended at this point as we consider RSpec's adapter to be slightly out of date, and RR provides its own adapter for RSpec). * RR now officially supports Rails 4.0.0. (It worked before, but now we're explicitly testing against it instead of 4.0.0.rc1.) * Fix Test::Unit 1 and 2 adapters to avoid a possible "undefined Test::Unit::TestCase" error. * Prevent adapters from being double-loaded. * Including RR::Adapters::TestUnit, RR::Adapters::MiniTest, or RR::Adapters::RSpec2 now just re-runs the autohook mechanism instead of building a fake adapter, as it was possible to include both a real and fake adapter in the same space and they could conflict with each other. ## 1.1.1 (June 17, 2013) * Fix incompatibility issues with Rails 4 ([#26][i26]) and Cucumber ([#29][i29]). * Add missing adapter for Test::Unit 2.0.0 (version which is built into Ruby 1.9/2.0). The tests for Jekyll were failing because of this ([#27][i27]). * If an error occurs while checking to see whether an adapter applies or when loading the adapter itself, it is now swallowed so that the user can move on. ## 1.1.0 (May 20, 2013) NOTE: RR development moved from [btakita/rr][btakita-rr] to [rr/rr][rr-rr]. Issues are re-numbered beginning from 1 from this point on. * Fix a line in RR::Injections::DoubleInjection to use top-level RR constant ([#3][i3]) [[@Thibaut][Thibaut]] * Fix all wildcard matches so they work within hashes and arrays. This means that `stub([hash_containing(:foo => 'bar')])` will match `stub([{:foo => 'bar', :baz => 'qux'}])`. ([#4][i4]) * RR now auto-hooks into whichever test framework you have loaded; there is no longer a need to `include RR::Adapters::Whatever` into your test framework. If you don't like the autohook and prefer the old way, simply use `require 'rr/without_autohook'` instead of `require 'rr'`. (There are now nine adapters; see [lib/rr/autohook.rb][autohook] for the full list.) * Fix Test::Unit adapters to ensure that any additional teardown is completely run in the event that RR's verify step produces an error. This was causing weirdness when using Test::Unit alongside Rails. ([#2][i2]) * Add an explicit Test::Unit / ActiveSupport adapter. As ActiveSupport::TestCase introduces its own setup/teardown hooks, use these when autohooking in RR. ([#2][i2]) * Add support for Minitest 5 * Upon release, the tests are now packaged up and uploaded to S3. This is for Linux distros like Fedora who wrap gems in RPM packages. You can always find the latest tests at , where X.Y.Z represents a version. I have retroactively packaged the tests for 1.0.4 and 1.0.5. ## 1.0.5 (March 28, 2013) * Compatibility with RSpec-2. There are now two adapters for RSpec, one that works with RSpec-1 and a new one that works with RSpec-2. Currently, saying `RSpec.configure {|c| c.mock_with(:rr) }` still uses RSpec-1; to use the new one, you say `RSpec.configure {|c| c.mock_framework = RR::Adapters::RSpec2 }`. ([#66][xi66], [#68][xi68], [#80][xi80]) [[@njay][njay], [@james2m][james2m]] * Fix MethodMissingInjection so that `[stub].flatten` works without throwing a NoMethodError (`undefined method `to_ary'`) error under Ruby 1.9 ([#44][xi44]) * Raise a MiniTest::Assertion error in the MiniTest adapter so that mock failures appear in the output as failures rather than uncaught exceptions ([#69][xi69]) [[@jayferd][jayferd]] * Completely remove leftover #new_instance_of method, and also remove mention of #new_instance_of from the README * Fix tests so they all work and pass again ## 1.0.4 (June 11, 2011) * Fixed bug using workaround with leftover MethodMissingInjections ## 1.0.3 (June 11, 2011) * Eliminate usage of ObjectSpace._id2ref ([#63][xi63]) [[@evanphx][evanphx]] * Added minitest adapter ([#62][xi62]) [[@cespare][cespare]] * Added instructions on installing the gem ([#57][xi57]) [[@gavingmiller][gavingmiller]] * delete missing scratch.rb file from gemspec ([#60][xi60]) [[@bonkydog][bonkydog]] ## 1.0.2 (November 1, 2010) * Fixed Two calls recorded to a mock expecting only one call when called via another mock's yield block ([#42][xi42]) [[@libc][libc]] ## 1.0.1 (October 30, 2010) * Removed new_instance_of for Ruby 1.9.2 compatibility. instance_of is now an alias for any_instance_of. * Compatible with Ruby 1.9.2 ## 1.0.0 (August 23, 2010) * Added any_instance_of (aliased by all_instances_of), which binds methods directly to the class (instead of the eigenclass). * Subclasses of a injected class do not have their methods overridden. * any_instance_of and new_instance_of now have a block syntax ## 0.10.11 (March 22, 2010) * Added RR.blank_slate_whitelist * Fixed class_eval method redefinition warning in jruby ## 0.10.10 (February 25, 2010) * Suite passes for Ruby 1.9.1 ## 0.10.9 (February 17, 2010) * Fixed 1.8.6 bug for real ## 0.10.8 (February 17, 2010) * Fixed 1.8.6 bug ## 0.10.7 (February 15, 2010) * Fixed issue with DoubleInjections binding to objects overriding the method method. ## 0.10.6 (February 15, 2010) * Added MIT license * Fixed Bug - dont_allow doesn't work when it follows stub ([#20][xi20]) * Fixed exception with DoubleInjections on proxy objects ([#24][xi24]) * Fixed Bug - Can't stub attribute methods on a BelongsToAssociation ([#24][xi24]) ## 0.10.5 (December 20, 2009) * Fixed stack overflow caused by double include in Test::Unit adapter ([#16][xi16]) * Fixed warnings [[@brynary][brynary]] ## 0.10.4 (September 26, 2009) * Handle lazily defined methods (where respond_to? returns true yet the method is not yet defined and the first call to method_missing defines the method). This pattern is used in ActiveRecord and ActionMailer. * Fixed warning about aliasing #instance_exec in jruby. ([#9][xi9]) [[@nathansobo][nathansobo]] ## 0.10.2 (August 30, 2009) * RR properly proxies subjects with private methods ([#7][xi7]) ## 0.10.1 (???) * Fixed issue with DoubleInjection not invoking methods that are lazily created ([#4][xi4]) * Fixed issue with mock.proxy and returns ([#2][xi2]) ## 0.10.0 (June 1, 2009) * Method is no longer invoked if respond_to? returns false. This was in place to support ActiveRecord association proxies, and is no longer needed. ## 0.9.0 (April 25, 2009) * instance_of Doubles now apply to methods invoked in the subject's #initialize method. ## 0.8.1 (March 29, 2009) * Fixed exception where the Subject uses method delegation via method_missing (e.g. certain ActiveRecord AssociationProxy methods) ## 0.8.0 (March 29, 2009) * Fixed compatibility issues with Ruby 1.9 * Aliased any_number_of_times with any_times * Better error messages for have_received and assert_received matchers [[@jferris][jferris]] * Better documentation on RR wilcard matchers [[@phildarnowsky][phildarnowsky]] ## 0.7.1 (January 16, 2009) * Performance improvements ## 0.7.0 (December 14, 2008) * Added spies [[@jferris][jferris], [@niessner][niessner], [@mmangino][mmangino]] * Added strongly typed reimplementation doubles [[@niessner][niessner]] ## 0.6.2 (???) * Fixed DoubleDefinition chaining edge cases ## 0.6.1 (???) * DoubleDefinitionCreatorProxy definition eval block is instance_evaled when the arity is not 1. When the arity is 1, the block is yielded with the DoubleDefinitionCreatorProxy passed in. ## 0.6.0 (October 13, 2008) * Friendlier DoubleNotFound error message * Implemented Double strategy creation methods (#mock, #stub, #proxy, #instance_of, and ! equivalents) on DoubleDefinition * Implemented hash_including matcher [Matthew O'Connor] * Implemented satisfy matcher [Matthew O'Connor] * Implemented DoubleDefinitionCreator#mock!, #stub!, and #dont_allow! * Modified api to method chain Doubles * Fix conflict with Mocha overriding Object#verify ## 0.5.0 (???) * Method chaining Doubles [[@nkallen][nkallen]] * Chained ordered expectations [[@nkallen][nkallen]] * Space#verify_doubles can take one or more objects with DoubleInjections to be verified ## 0.4.10 (July 6, 2008) * DoubleDefinitionCreatorProxy does not undef #object_id * Fixed rdoc pointer to README ## 0.4.9 (June 18, 2008) * Proxying from RR module to RR::Space.instance ## 0.4.8 (January 23, 2008) * Fixed issue with Hash arguments ## 0.4.7 (January 23, 2008) * Improved error message ## 0.4.6 (January 23, 2008) * Added Double#verbose and Double#verbose? ## 0.4.5 (January 15, 2008) * Fixed doubles for == and #eql? methods ## 0.4.4 (January 15, 2008) * Doc improvements * Methods that are not alphabetic, such as ==, can be doubles ## 0.4.3 (January 7, 2008) * Doc improvements * Cleanup * Finished renaming scenario to double ## 0.4.2 (December 31, 2007) * Renamed DoubleInsertion to DoubleInjection to be consistent with Mocha terminology ## 0.4.1 (December 31, 2007) * Fixed backward compatability issues with rspec * Renamed Space#verify_double_insertions to #verify_doubles ## 0.4.0 (December 30, 2007) * Documentation improvements * Renamed Double to DoubleInsertion * Renamed Scenario to Double ## 0.3.11 (September 6, 2007) * Fixed [#13724] Mock Proxy on Active Record Association proxies causes error ## 0.3.10 (August 18, 2007) * Fixed [#13139] Blocks added to proxy sets the return_value and not the after_call callback ## 0.3.9 (August 14, 2007) * Alias probe to proxy ## 0.3.8 (August 12, 2007) * Implemented [#13009] Better error mesage from TimesCalledMatcher ## 0.3.7 (August 9, 2007) * Fixed [#12928] Reset doubles fails on Rails association proxies ## 0.3.6 (August 1, 2007) * Fixed [#12765] Issues with ObjectSpace._id2ref ## 0.3.5 (July 29, 2007) * trim_backtrace is only set for Test::Unit ## 0.3.4 (July 22, 2007) * Implemented instance_of ## 0.3.3 (July 22, 2007) * Fixed [#12495] Error Probing method_missing interaction ## 0.3.2 (July 22, 2007) * Fixed [#12486] ScenarioMethodProxy when Kernel passed into instance methods ## 0.3.1 (July 22, 2007) * Automatically require Test::Unit and Rspec adapters ## 0.3.0 (July 22, 2007) * ScenarioCreator strategy method chaining * Removed mock_probe * Removed stub_probe ## 0.2.5 (July 21, 2007) * mock takes method_name argument * stub takes method_name argument * mock_probe takes method_name argument * stub_probe takes method_name argument * probe takes method_name argument * dont_allow takes method_name argument * do_not_allow takes method_name argument ## 0.2.4 (July 19, 2007) * Space#doubles key is now the object id * Fixed [#12402] Stubbing return value of probes fails after calling the stubbed method two times ## 0.2.3 (July 18, 2007) * Added RRMethods#rr_verify and RRMethods#rr_reset ## 0.2.2 (July 17, 2007) * Fixed "singleton method bound for a different object" * Doing Method aliasing again to store original method ## 0.2.1 (July 17, 2007) * Added mock_probe * Added stub_probe * Probe returns the return value of the passed in block, instead of ignoring its return value * Scenario#after_call returns the return value of the passed in block * Not using method aliasing to store original method * Renamed DoubleMethods to RRMethods * Added RRMethods#mock_probe ## 0.1.15 (July 17, 2007) * Fixed [#12333] Rebinding original_methods causes blocks not to work ## 0.1.14 (July 16, 2007) * Introduced concept of Terminal and NonTerminal TimesCalledMatchers * Doubles that can be called many times can be replaced * Terminal Scenarios are called before NonTerminal Scenarios * Error message tweaking * Raise error when making a Scenarios with NonTerminal TimesMatcher Ordered ## 0.1.13 (July 14, 2007) * Fixed [#12290] Scenario#returns with false causes a return value of nil ## 0.1.12 (July 14, 2007) * Fixed bug where Creators methods are not removed when methods are defined on Object * Fixed [#12289] Creators methods are not removed in Rails environment ## 0.1.11 (July 14, 2007) * Fixed [#12287] AtLeastMatcher does not cause Scenario to be called ## 0.1.10 (July 14, 2007) * Fixed [#12286] AnyArgumentExpectation#expected_arguments not implemented ## 0.1.9 (July 14, 2007) * Added DoubleMethods#any_times * Added Scenario#any_number_of_times ## 0.1.8 (July 14, 2007) * TimesCalledError Message Formatted to be on multiple lines * ScenarioNotFoundError Message includes all Scenarios for the Double * ScenarioOrderError shows list of remaining ordered scenarios ## 0.1.7 (July 14, 2007) * Fixed [#12194] Double#reset_doubles are not clearing Ordered Scenarios bug * Added Space#reset * Space#reset_doubles and Space#reset_ordered_scenarios is now protected * Added Scenario#at_least * Added Scenario#at_most ## 0.1.6 (July 10, 2007) * [#12120] probe allows a the return value to be intercepted ## 0.1.5 (July 9, 2007) * TimesCalledExpectation says how many times were called and how many times called were expected on error ## 0.1.4 (July 9, 2007) * TimesCalledError prints the backtrace to where the Scenario was defined when being verified * Error message includes method name when Scenario is not found ## 0.1.3 (July 9, 2007) * Fixed issue where Double#placeholder_name issues when Double method name has a ! or ? ## 0.1.2 (July 8, 2007) * Scenario#returns also accepts an argument * Implemented Scenario#yields ## 0.1.1 (July 8, 2007) * Trim the backtrace for Rspec and Test::Unit * Rspec and Test::Unit integration fixes ## 0.1.0 (July 7, 2007) * Initial Release [btakita-rr]: http://github.com/btakita/rr [rr-rr]: http://github.com/rr/rr [i2]: http://github.com/rr/rr/issues/2 [i3]: http://github.com/rr/rr/issues/3 [Thibaut]: http://github.com/Thibaut [i4]: http://github.com/rr/rr/issues/4 [xi66]: http://github.com/btakita/rr/issues/66 [xi68]: http://github.com/btakita/rr/issues/68 [xi80]: http://github.com/btakita/rr/issues/80 [njay]: http://github.com/njay [james2m]: http://github.com/james2m [xi44]: http://github.com/btakita/rr/issues/44 [xi69]: http://github.com/btakita/rr/issues/69 [jayferd]: http://github.com/jayferd [autohook]: https://github.com/rr/rr/blob/master/lib/rr/autohook.rb [evanphx]: http://github.com/evanphx [xi63]: http://github.com/btakita/rr/issues/63 [xi63]: http://github.com/btakita/rr/issues/62 [cespare]: http://github.com/cespare [gavingmiller]: http://github.com/gavingmiller [bonkydog]: http://github.com/bonkydog [xi42]: http://github.com/btakita/rr/issues/42 [libc]: http://github.com/libc [brynary]: http://github.com/brynary [xi9]: http://github.com/btakita/rr/issues/9 [nathansobo]: http://github.com/nathansobo [xi7]: http://github.com/btakita/rr/issues/7 [xi4]: http://github.com/btakita/rr/issues/4 [xi2]: http://github.com/btakita/rr/issues/2 [nkallen]: http://github.com/nkallen [jferris]: http://github.com/jferris [phildarnowsky]: http://github.com/phildarnowsky [niessner]: http://github.com/niessner [mmangino]: http://github.com/mmangino [xi20]: http://github.com/btakita/rr/issues/20 [xi24]: http://github.com/btakita/rr/issues/24 [xi16]: http://github.com/btakita/rr/issues/16 [xi62]: http://github.com/btakita/rr/issues/62 [xi57]: http://github.com/btakita/rr/issues/57 [xi60]: http://github.com/btakita/rr/issues/60 [i26]: http://github.com/rr/rr/issues/26 [i29]: http://github.com/rr/rr/issues/29 [i27]: http://github.com/rr/rr/issues/27 [i34]: http://github.com/rr/rr/issues/34 [i32]: http://github.com/rr/rr/issues/32 [i37]: http://github.com/rr/rr/issues/37