diff --git a/rspec-expectations/Changelog.md b/rspec-expectations/Changelog.md index 1c7c425cc..a2ee4608b 100644 --- a/rspec-expectations/Changelog.md +++ b/rspec-expectations/Changelog.md @@ -1,6 +1,10 @@ ### Development [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.10.0...main) +Breaking Changes: + +* Ruby < 2.3 is no longer supported. (Phil Pirozhkov, #1231) + Enhancements: * Return `true` from `aggregate_failures` when no exception occurs. (Jon Rowe, #1225) diff --git a/rspec-expectations/Gemfile b/rspec-expectations/Gemfile index aaf2ed449..b8bf9481e 100644 --- a/rspec-expectations/Gemfile +++ b/rspec-expectations/Gemfile @@ -12,14 +12,6 @@ branch = File.read(File.expand_path("../maintenance-branch", __FILE__)).chomp end end -if RUBY_VERSION < '1.9.3' - gem 'rake', '< 11.0.0' # rake 11 requires Ruby 1.9.3 or later -elsif RUBY_VERSION < '2.0.0' - gem 'rake', '< 12.0.0' # rake 12 requires Ruby 2.0.0 or later -else - gem 'rake', '> 12.3.2' -end - if ENV['DIFF_LCS_VERSION'] gem 'diff-lcs', ENV['DIFF_LCS_VERSION'] else @@ -37,50 +29,14 @@ end gem 'simplecov' -if RUBY_VERSION < '2.0.0' || RUBY_ENGINE == 'java' - gem 'json', '< 2.0.0' # is a dependency of simplecov -else - gem 'json', '> 2.3.0' -end - -# allow gems to be installed on older rubies and/or windows -if RUBY_VERSION < '2.2.0' && !!(RbConfig::CONFIG['host_os'] =~ /cygwin|mswin|mingw|bccwin|wince|emx/) - gem 'ffi', '< 1.10' -elsif RUBY_VERSION < '1.9' - gem 'ffi', '< 1.9.19' # ffi dropped Ruby 1.8 support in 1.9.19 -elsif RUBY_VERSION < '2.0' - gem 'ffi', '< 1.11.0' # ffi dropped Ruby 1.9 support in 1.11.0 -else - gem 'ffi', '> 1.9.24' # prevent Github security vulnerability warning -end - -# on windows -if !!(RbConfig::CONFIG['host_os'] =~ /cygwin|mswin|mingw|bccwin|wince|emx/) - if RUBY_VERSION.to_f < 2.3 - # Ruby 2.2,2.1 etc require this - gem "childprocess", "< 1.0.0" - end -end - -if RUBY_VERSION < '1.9.2' - gem 'contracts', '~> 0.15.0' # is a dependency of aruba -end +gem 'ffi', '~> 1.12.0' # Version 5.12 of minitest requires Ruby 2.4 if RUBY_VERSION < '2.4.0' gem 'minitest', '< 5.12.0' end -platforms :jruby do - if RUBY_VERSION < '1.9.0' - # Pin jruby-openssl on older J Ruby - gem "jruby-openssl", "< 0.10.0" - # Pin childprocess on older J Ruby - gem "childprocess", "< 1.0.0" - else - gem "jruby-openssl" - end -end +gem "jruby-openssl", platforms: :jruby if RUBY_VERSION >= '2.4' && RUBY_ENGINE == 'ruby' gem 'rubocop', "~> 0.52.1" diff --git a/rspec-expectations/Gemfile-custom.sample b/rspec-expectations/Gemfile-custom.sample index a5017674b..eb66baa10 100644 --- a/rspec-expectations/Gemfile-custom.sample +++ b/rspec-expectations/Gemfile-custom.sample @@ -3,17 +3,9 @@ group :development do gem 'relish', '~> 0.6.0' gem 'guard-rspec', '~> 1.2.1' gem 'growl', '1.0.3' - gem 'spork', '0.9.0' platform :mri do gem 'rb-fsevent', '~> 0.9.0' gem 'ruby-prof', '~> 0.10.0' - - case RUBY_VERSION - when /^1.8/ - gem 'ruby-debug' - when /^1.9/ - gem 'debugger' - end end end diff --git a/rspec-expectations/cucumber.yml b/rspec-expectations/cucumber.yml index d9fb47d17..7870eae8e 100644 --- a/rspec-expectations/cucumber.yml +++ b/rspec-expectations/cucumber.yml @@ -1,10 +1,2 @@ -<% -def tags(tag) - tags = [tag] - tags << "~@ruby-1.9" if RUBY_VERSION.to_f < 1.9 - tags.join(" --tags ") -end -%> - -default: --require features --tags <%= tags("~@wip") %> --format progress +default: --require features --tags ~@wip --format progress wip: --require features --tags @wip:3 --wip features diff --git a/rspec-expectations/features/built_in_matchers/README.md b/rspec-expectations/features/built_in_matchers/README.md index 53fa2dc3e..a9cda832d 100644 --- a/rspec-expectations/features/built_in_matchers/README.md +++ b/rspec-expectations/features/built_in_matchers/README.md @@ -94,7 +94,7 @@ e.g. expect([1, 2, 3]).to contain_exactly(2, 1, 3) expect([1, 2, 3]).to match_array([3, 2, 1]) -## Ranges (1.9+ only) +## Ranges expect(1..10).to cover(3) diff --git a/rspec-expectations/features/built_in_matchers/cover.feature b/rspec-expectations/features/built_in_matchers/cover.feature index 1ac85ce85..f43f03a08 100644 --- a/rspec-expectations/features/built_in_matchers/cover.feature +++ b/rspec-expectations/features/built_in_matchers/cover.feature @@ -1,4 +1,3 @@ -@ruby-1.9 Feature: `cover` matcher Use the `cover` matcher to specify that a range covers one or more diff --git a/rspec-expectations/features/built_in_matchers/respond_to.feature b/rspec-expectations/features/built_in_matchers/respond_to.feature index 49d02e4fc..84a3e4dfd 100644 --- a/rspec-expectations/features/built_in_matchers/respond_to.feature +++ b/rspec-expectations/features/built_in_matchers/respond_to.feature @@ -93,7 +93,6 @@ Feature: `respond_to` matcher | expected 7 to respond to :between? with 7 arguments | | expected 7 not to respond to :between? with 2 arguments | - @skip-when-splat-args-unsupported Scenario: specify arguments range Given a file named "respond_to_matcher_argument_range_checking_spec.rb" with: """ruby @@ -127,7 +126,6 @@ Feature: `respond_to` matcher | expected my_object to respond to :build with 2..3 arguments | | expected my_object to respond to :build with 0..3 arguments | - @skip-when-splat-args-unsupported Scenario: specify unlimited arguments Given a file named "respond_to_matcher_unlimited_argument_checking_spec.rb" with: """ruby @@ -164,7 +162,6 @@ Feature: `respond_to` matcher | expected my_object to respond to :hail with unlimited arguments | | expected my_object to respond to :hail with 1 argument and unlimited arguments | - @skip-when-keyword-args-unsupported Scenario: specify keywords Given a file named "respond_to_matcher_keyword_checking_spec.rb" with: """ruby @@ -201,7 +198,6 @@ Feature: `respond_to` matcher | expected my_object not to respond to :find with keywords :limit and :offset | | expected my_object not to respond to :find with 1 argument and keywords :limit and :offset | - @skip-when-keyword-args-unsupported Scenario: specify any keywords Given a file named "respond_to_matcher_any_keywords_checking_spec.rb" with: """ruby @@ -238,7 +234,6 @@ Feature: `respond_to` matcher | expected my_object to respond to :create with any keywords | | expected my_object to respond to :create with keyword :name and any keywords | - @skip-when-required-keyword-args-unsupported Scenario: specify required keywords Given a file named "respond_to_matcher_required_keyword_checking_spec.rb" with: """ruby diff --git a/rspec-expectations/features/step_definitions/additional_cli_steps.rb b/rspec-expectations/features/step_definitions/additional_cli_steps.rb index b896a3adf..958007b8f 100644 --- a/rspec-expectations/features/step_definitions/additional_cli_steps.rb +++ b/rspec-expectations/features/step_definitions/additional_cli_steps.rb @@ -7,11 +7,7 @@ Then /^the output should contain all of these:$/ do |table| table.raw.flatten.each do |string| - if RUBY_VERSION == '1.8.7' && string =~ /\{.+=>.+\}/ - warn "Skipping checking #{string} on 1.8.7 because hash ordering is not consistent" - else - expect(all_output).to include_output_string string - end + expect(all_output).to include_output_string string end end diff --git a/rspec-expectations/features/support/ruby_features.rb b/rspec-expectations/features/support/ruby_features.rb index e4d45a4cc..98b300440 100644 --- a/rspec-expectations/features/support/ruby_features.rb +++ b/rspec-expectations/features/support/ruby_features.rb @@ -1,33 +1,3 @@ -Around "@skip-when-splat-args-unsupported" do |scenario, block| - require 'rspec/support/ruby_features' - - if ::RSpec::Support::RubyFeatures.optional_and_splat_args_supported? - block.call - else - warn "Skipping scenario #{scenario.title} because splat arguments are not supported" - end -end - -Around "@skip-when-keyword-args-unsupported" do |scenario, block| - require 'rspec/support/ruby_features' - - if ::RSpec::Support::RubyFeatures.kw_args_supported? - block.call - else - warn "Skipping scenario #{scenario.title} because keyword arguments are not supported" - end -end - -Around "@skip-when-required-keyword-args-unsupported" do |scenario, block| - require 'rspec/support/ruby_features' - - if ::RSpec::Support::RubyFeatures.required_kw_args_supported? - block.call - else - warn "Skipping scenario #{scenario.title} because required keyword arguments are not supported" - end -end - Around "@skip-when-ripper-unsupported" do |scenario, block| require 'rspec/support/ruby_features' diff --git a/rspec-expectations/lib/rspec/expectations/configuration.rb b/rspec-expectations/lib/rspec/expectations/configuration.rb index 974a9cdf2..a16b5b5e4 100644 --- a/rspec-expectations/lib/rspec/expectations/configuration.rb +++ b/rspec-expectations/lib/rspec/expectations/configuration.rb @@ -104,8 +104,7 @@ def color? # Adds `should` and `should_not` to the given classes # or modules. This can be used to ensure `should` works - # properly on things like proxy objects (particular - # `Delegator`-subclassed objects on 1.8). + # properly on things like proxy objects. # # @param [Array] modules the list of classes or modules # to add `should` and `should_not` to. diff --git a/rspec-expectations/lib/rspec/expectations/syntax.rb b/rspec-expectations/lib/rspec/expectations/syntax.rb index b8430346f..c61670cd4 100644 --- a/rspec-expectations/lib/rspec/expectations/syntax.rb +++ b/rspec-expectations/lib/rspec/expectations/syntax.rb @@ -100,33 +100,31 @@ def expect_enabled?(syntax_host=::RSpec::Matchers) end end -if defined?(BasicObject) - # The legacy `:should` syntax adds the following methods directly to - # `BasicObject` so that they are available off of any object. Note, however, - # that this syntax does not always play nice with delegate/proxy objects. - # We recommend you use the non-monkeypatching `:expect` syntax instead. - class BasicObject - # @method should(matcher, message) - # Passes if `matcher` returns true. Available on every `Object`. - # @example - # actual.should eq expected - # actual.should match /expression/ - # @param [Matcher] - # matcher - # @param [String] message optional message to display when the expectation fails - # @return [Boolean] true if the expectation succeeds (else raises) - # @note This is only available when you have enabled the `:should` syntax. - # @see RSpec::Matchers - - # @method should_not(matcher, message) - # Passes if `matcher` returns false. Available on every `Object`. - # @example - # actual.should_not eq expected - # @param [Matcher] - # matcher - # @param [String] message optional message to display when the expectation fails - # @return [Boolean] false if the negative expectation succeeds (else raises) - # @note This is only available when you have enabled the `:should` syntax. - # @see RSpec::Matchers - end +# The legacy `:should` syntax adds the following methods directly to +# `BasicObject` so that they are available off of any object. Note, however, +# that this syntax does not always play nice with delegate/proxy objects. +# We recommend you use the non-monkeypatching `:expect` syntax instead. +class BasicObject + # @method should(matcher, message) + # Passes if `matcher` returns true. Available on every `Object`. + # @example + # actual.should eq expected + # actual.should match /expression/ + # @param [Matcher] + # matcher + # @param [String] message optional message to display when the expectation fails + # @return [Boolean] true if the expectation succeeds (else raises) + # @note This is only available when you have enabled the `:should` syntax. + # @see RSpec::Matchers + + # @method should_not(matcher, message) + # Passes if `matcher` returns false. Available on every `Object`. + # @example + # actual.should_not eq expected + # @param [Matcher] + # matcher + # @param [String] message optional message to display when the expectation fails + # @return [Boolean] false if the negative expectation succeeds (else raises) + # @note This is only available when you have enabled the `:should` syntax. + # @see RSpec::Matchers end diff --git a/rspec-expectations/lib/rspec/matchers.rb b/rspec-expectations/lib/rspec/matchers.rb index 443c8f158..dc978411a 100644 --- a/rspec-expectations/lib/rspec/matchers.rb +++ b/rspec-expectations/lib/rspec/matchers.rb @@ -238,7 +238,7 @@ module RSpec # best to find a more positive name for the negated form, such as # `avoid_changing` rather than `not_change`. # - module Matchers # rubocop:disable Metrics/ModuleLength + module Matchers extend ::RSpec::Matchers::DSL # @!macro [attach] alias_matcher @@ -524,7 +524,6 @@ def contain_exactly(*items) # expect(1..10).not_to cover(11) # expect(1..10).not_to cover(5) # fails # - # ### Warning:: Ruby >= 1.9 only def cover(*values) BuiltIn::Cover.new(*values) end @@ -967,18 +966,8 @@ def method_missing(method, *args, &block) end ruby2_keywords :method_missing if respond_to?(:ruby2_keywords, true) - if RUBY_VERSION.to_f >= 1.9 - def respond_to_missing?(method, *) - method =~ DYNAMIC_MATCHER_REGEX || super - end - else # for 1.8.7 - # :nocov: - def respond_to?(method, *) - method = method.to_s - method =~ DYNAMIC_MATCHER_REGEX || super - end - public :respond_to? - # :nocov: + def respond_to_missing?(method, *) + method =~ DYNAMIC_MATCHER_REGEX || super end # @api private @@ -1005,37 +994,5 @@ def self.is_a_matcher?(obj) def self.is_a_describable_matcher?(obj) is_a_matcher?(obj) && obj.respond_to?(:description) end - - class << self - private - - if RSpec::Support::Ruby.mri? && RUBY_VERSION[0, 3] == '1.9' - # Note that `included` doesn't work for this because it is triggered - # _after_ `RSpec::Matchers` is an ancestor of the inclusion host, rather - # than _before_, like `append_features`. It's important we check this before - # in order to find the cases where it was already previously included. - # @api private - def append_features(mod) - return super if mod < self # `mod < self` indicates a re-inclusion. - - subclasses = ObjectSpace.each_object(Class).select { |c| c < mod && c < self } - return super unless subclasses.any? - - subclasses.reject! { |s| subclasses.any? { |s2| s < s2 } } # Filter to the root ancestor. - subclasses = subclasses.map { |s| "`#{s}`" }.join(", ") - - RSpec.warning "`#{self}` has been included in a superclass (`#{mod}`) " \ - "after previously being included in subclasses (#{subclasses}), " \ - "which can trigger infinite recursion from `super` due to an MRI 1.9 bug " \ - "(https://redmine.ruby-lang.org/issues/3351). To work around this, " \ - "either upgrade to MRI 2.0+, include a dup of the module (e.g. " \ - "`include #{self}.dup`), or find a way to include `#{self}` in `#{mod}` " \ - "before it is included in subclasses (#{subclasses}). See " \ - "https://github.com/rspec/rspec-expectations/issues/814 for more info" - - super - end - end - end end end diff --git a/rspec-expectations/lib/rspec/matchers/built_in/base_matcher.rb b/rspec-expectations/lib/rspec/matchers/built_in/base_matcher.rb index 7699c92ac..5c39b80fc 100644 --- a/rspec-expectations/lib/rspec/matchers/built_in/base_matcher.rb +++ b/rspec-expectations/lib/rspec/matchers/built_in/base_matcher.rb @@ -122,21 +122,11 @@ def self.underscore(camel_cased_word) private def assert_ivars(*expected_ivars) - return unless (expected_ivars - present_ivars).any? + return unless (expected_ivars - instance_variables).any? ivar_list = EnglishPhrasing.list(expected_ivars) raise "#{self.class.name} needs to supply#{ivar_list}" end - if RUBY_VERSION.to_f < 1.9 - # :nocov: - def present_ivars - instance_variables.map(&:to_sym) - end - # :nocov: - else - alias present_ivars instance_variables - end - # @private module HashFormatting # `{ :a => 5, :b => 2 }.inspect` produces: diff --git a/rspec-expectations/lib/rspec/matchers/built_in/contain_exactly.rb b/rspec-expectations/lib/rspec/matchers/built_in/contain_exactly.rb index 1bf7f9831..a15d4401a 100644 --- a/rspec-expectations/lib/rspec/matchers/built_in/contain_exactly.rb +++ b/rspec-expectations/lib/rspec/matchers/built_in/contain_exactly.rb @@ -1,7 +1,6 @@ module RSpec module Matchers module BuiltIn - # rubocop:disable ClassLength # @api private # Provides the implementation for `contain_exactly` and `match_array`. # Not intended to be instantiated directly. @@ -99,17 +98,8 @@ def safe_sort(array) array end - if RUBY_VERSION == "1.8.7" - def to_a_disallowed?(object) - case object - when NilClass, String then true - else Kernel == RSpec::Support.method_handle_for(object, :to_a).owner - end - end - else - def to_a_disallowed?(object) - NilClass === object - end + def to_a_disallowed?(object) + NilClass === object end def missing_items @@ -296,7 +286,6 @@ def apply_pairing_to(indeterminates, original_matches, other_list_index) end end end - # rubocop:enable ClassLength end end end diff --git a/rspec-expectations/lib/rspec/matchers/built_in/count_expectation.rb b/rspec-expectations/lib/rspec/matchers/built_in/count_expectation.rb index 32272abf6..c0210ae8e 100644 --- a/rspec-expectations/lib/rspec/matchers/built_in/count_expectation.rb +++ b/rspec-expectations/lib/rspec/matchers/built_in/count_expectation.rb @@ -56,20 +56,10 @@ def times private - if RUBY_VERSION.to_f > 1.8 - def cover?(count, number) - count.cover?(number) - end - else - def cover?(count, number) - number >= count.first && number <= count.last - end - end - def expected_count_matches?(actual_count) @actual_count = actual_count return @actual_count > 0 unless count_expectation_type - return cover?(expected_count, actual_count) if count_expectation_type == :<=> + return expected_count.cover?(actual_count) if count_expectation_type == :<=> @actual_count.__send__(count_expectation_type, expected_count) end diff --git a/rspec-expectations/lib/rspec/matchers/built_in/has.rb b/rspec-expectations/lib/rspec/matchers/built_in/has.rb index 5036a6405..6b4b6e30b 100644 --- a/rspec-expectations/lib/rspec/matchers/built_in/has.rb +++ b/rspec-expectations/lib/rspec/matchers/built_in/has.rb @@ -50,17 +50,8 @@ def predicate_accessible? @actual.respond_to? predicate end - # support 1.8.7, evaluate once at load time for performance - if String === methods.first - # :nocov: - def private_predicate? - @actual.private_methods.include? predicate.to_s - end - # :nocov: - else - def private_predicate? - @actual.private_methods.include? predicate - end + def private_predicate? + @actual.private_methods.include? predicate end def predicate_result @@ -80,11 +71,7 @@ def predicate_matches?(value=true) end def root - # On 1.9, there appears to be a bug where String#match can return `false` - # rather than the match data object. Changing to Regex#match appears to - # work around this bug. For an example of this bug, see: - # https://travis-ci.org/rspec/rspec-expectations/jobs/27549635 - self.class::REGEX.match(@method_name.to_s).captures.first + self.class::REGEX.match(@method_name).captures.first end def method_description diff --git a/rspec-expectations/lib/rspec/matchers/built_in/include.rb b/rspec-expectations/lib/rspec/matchers/built_in/include.rb index 5a0d697f0..6fa40b2d1 100644 --- a/rspec-expectations/lib/rspec/matchers/built_in/include.rb +++ b/rspec-expectations/lib/rspec/matchers/built_in/include.rb @@ -166,14 +166,8 @@ def actual_collection_includes?(expected_item) actual.any? { |value| values_match?(expected_item, value) } end - if RUBY_VERSION < '1.9' - def count_enumerable(expected_item) - actual.select { |value| values_match?(expected_item, value) }.size - end - else - def count_enumerable(expected_item) - actual.count { |value| values_match?(expected_item, value) } - end + def count_enumerable(expected_item) + actual.count { |value| values_match?(expected_item, value) } end def count_inclusions diff --git a/rspec-expectations/lib/rspec/matchers/built_in/match.rb b/rspec-expectations/lib/rspec/matchers/built_in/match.rb index 9ed4b068c..a082a3af5 100644 --- a/rspec-expectations/lib/rspec/matchers/built_in/match.rb +++ b/rspec-expectations/lib/rspec/matchers/built_in/match.rb @@ -52,7 +52,6 @@ def can_safely_call_match?(expected, actual) def match_captures(expected, actual) match = actual.match(expected) if match - match = ReliableMatchData.new(match) if match.names.empty? values_match?(@expected_captures, match.captures) else @@ -66,41 +65,6 @@ def match_captures(expected, actual) end end end - - # @api private - # Used to wrap match data and make it reliable for 1.8.7 - class ReliableMatchData - def initialize(match_data) - @match_data = match_data - end - - if RUBY_VERSION == "1.8.7" - # @api private - # Returns match data names for named captures - # @return Array - def names - [] - end - else - # @api private - # Returns match data names for named captures - # @return Array - def names - match_data.names - end - end - - # @api private - # returns an array of captures from the match data - # @return Array - def captures - match_data.captures - end - - protected - - attr_reader :match_data - end end end end diff --git a/rspec-expectations/lib/rspec/matchers/built_in/throw_symbol.rb b/rspec-expectations/lib/rspec/matchers/built_in/throw_symbol.rb index 1b6b8bcb4..97b7be4ff 100644 --- a/rspec-expectations/lib/rspec/matchers/built_in/throw_symbol.rb +++ b/rspec-expectations/lib/rspec/matchers/built_in/throw_symbol.rb @@ -36,10 +36,7 @@ def matches?(given_proc) @caught_symbol = @expected_symbol end end - - # Ruby 1.8 uses NameError with `symbol' - # Ruby 1.9 uses ArgumentError with :symbol - rescue NameError, ArgumentError => e + rescue ArgumentError => e unless (match_data = e.message.match(/uncaught throw (`|\:)([a-zA-Z0-9_]*)(')?/)) other_exception = e raise diff --git a/rspec-expectations/lib/rspec/matchers/built_in/yield.rb b/rspec-expectations/lib/rspec/matchers/built_in/yield.rb index 9ca6b1b47..9f16d1c57 100644 --- a/rspec-expectations/lib/rspec/matchers/built_in/yield.rb +++ b/rspec-expectations/lib/rspec/matchers/built_in/yield.rb @@ -74,24 +74,11 @@ def assert_used! 'are.' end - if RUBY_VERSION.to_f > 1.8 - def assert_valid_expect_block! - block_signature = RSpec::Support::BlockSignature.new(@block) - return if RSpec::Support::StrictSignatureVerifier.new(block_signature, [self]).valid? - raise 'Your expect block must accept an argument to be used with this ' \ - 'matcher. Pass the argument as a block on to the method you are testing.' - end - else - # :nocov: - # On 1.8.7, `lambda { }.arity` and `lambda { |*a| }.arity` both return -1, - # so we can't distinguish between accepting no args and an arg splat. - # It's OK to skip, this, though; it just provides a nice error message - # when the user forgets to accept an arg in their block. They'll still get - # the `assert_used!` error message from above, which is sufficient. - def assert_valid_expect_block! - # nothing to do - end - # :nocov: + def assert_valid_expect_block! + block_signature = RSpec::Support::BlockSignature.new(@block) + return if RSpec::Support::StrictSignatureVerifier.new(block_signature, [self]).valid? + raise 'Your expect block must accept an argument to be used with this ' \ + 'matcher. Pass the argument as a block on to the method you are testing.' end end diff --git a/rspec-expectations/lib/rspec/matchers/dsl.rb b/rspec-expectations/lib/rspec/matchers/dsl.rb index 1a1f9c50f..641a637e9 100644 --- a/rspec-expectations/lib/rspec/matchers/dsl.rb +++ b/rspec-expectations/lib/rspec/matchers/dsl.rb @@ -79,21 +79,13 @@ def define(name, &declarations) private - if Proc.method_defined?(:parameters) - def warn_about_block_args(name, declarations) - declarations.parameters.each do |type, arg_name| - next unless type == :block - RSpec.warning("Your `#{name}` custom matcher receives a block argument (`#{arg_name}`), " \ - "but due to limitations in ruby, RSpec cannot provide the block. Instead, " \ - "use the `block_arg` method to access the block") - end - end - else - # :nocov: - def warn_about_block_args(*) - # There's no way to detect block params on 1.8 since the method reflection APIs don't expose it + def warn_about_block_args(name, declarations) + declarations.parameters.each do |type, arg_name| + next unless type == :block + RSpec.warning("Your `#{name}` custom matcher receives a block argument (`#{arg_name}`), " \ + "but due to limitations in ruby, RSpec cannot provide the block. Instead, " \ + "use the `block_arg` method to access the block") end - # :nocov: end RSpec.configure { |c| c.extend self } if RSpec.respond_to?(:configure) @@ -308,6 +300,8 @@ def chain(method_name, *attr_names, &definition) end end + private + def assign_attributes(attr_names) attr_reader(*attr_names) private(*attr_names) @@ -319,12 +313,6 @@ def assign_attributes(attr_names) end end - # assign_attributes isn't defined in the private section below because - # that makes MRI 1.9.2 emit a warning about private attributes. - private :assign_attributes - - private - # Does the following: # # - Defines the named method using a user-provided block @@ -495,21 +483,11 @@ def inspect "#<#{self.class.name} #{name}>" end - if RUBY_VERSION.to_f >= 1.9 - # Indicates that this matcher responds to messages - # from the `@matcher_execution_context` as well. - # Also, supports getting a method object for such methods. - def respond_to_missing?(method, include_private=false) - super || @matcher_execution_context.respond_to?(method, include_private) - end - else # for 1.8.7 - # :nocov: - # Indicates that this matcher responds to messages - # from the `@matcher_execution_context` as well. - def respond_to?(method, include_private=false) - super || @matcher_execution_context.respond_to?(method, include_private) - end - # :nocov: + # Indicates that this matcher responds to messages + # from the `@matcher_execution_context` as well. + # Also, supports getting a method object for such methods. + def respond_to_missing?(method, include_private=false) + super || @matcher_execution_context.respond_to?(method, include_private) end private diff --git a/rspec-expectations/lib/rspec/matchers/english_phrasing.rb b/rspec-expectations/lib/rspec/matchers/english_phrasing.rb index fff803ccc..9619e4efb 100644 --- a/rspec-expectations/lib/rspec/matchers/english_phrasing.rb +++ b/rspec-expectations/lib/rspec/matchers/english_phrasing.rb @@ -37,22 +37,6 @@ def self.list(obj) " #{items[0...-1].join(', ')}, and #{items[-1]}" end end - - if RUBY_VERSION == '1.8.7' - # Not sure why, but on travis on 1.8.7 we have gotten these warnings: - # lib/rspec/matchers/english_phrasing.rb:28: warning: default `to_a' will be obsolete - # So it appears that `Array` can trigger that (e.g. by calling `to_a` on the passed object?) - # So here we replace `Kernel#Array` with our own warning-free implementation for 1.8.7. - # @private - # rubocop:disable Naming/MethodName - def self.Array(obj) - case obj - when Array then obj - else [obj] - end - end - # rubocop:enable Naming/MethodName - end end end end diff --git a/rspec-expectations/lib/rspec/matchers/matcher_delegator.rb b/rspec-expectations/lib/rspec/matchers/matcher_delegator.rb index e17b2ee59..d0bc9d9b5 100644 --- a/rspec-expectations/lib/rspec/matchers/matcher_delegator.rb +++ b/rspec-expectations/lib/rspec/matchers/matcher_delegator.rb @@ -14,16 +14,8 @@ def method_missing(*args, &block) base_matcher.__send__(*args, &block) end - if ::RUBY_VERSION.to_f > 1.8 - def respond_to_missing?(name, include_all=false) - super || base_matcher.respond_to?(name, include_all) - end - else - # :nocov: - def respond_to?(name, include_all=false) - super || base_matcher.respond_to?(name, include_all) - end - # :nocov: + def respond_to_missing?(name, include_all=false) + super || base_matcher.respond_to?(name, include_all) end def initialize_copy(other) diff --git a/rspec-expectations/rspec-expectations.gemspec b/rspec-expectations/rspec-expectations.gemspec index f4e7867fa..ecc2de74b 100644 --- a/rspec-expectations/rspec-expectations.gemspec +++ b/rspec-expectations/rspec-expectations.gemspec @@ -26,7 +26,7 @@ Gem::Specification.new do |s| s.rdoc_options = ["--charset=UTF-8"] s.require_path = "lib" - s.required_ruby_version = '>= 1.8.7' # rubocop:disable Gemspec/RequiredRubyVersion + s.required_ruby_version = '>= 2.3.0' # rubocop:disable Gemspec/RequiredRubyVersion private_key = File.expand_path('~/.gem/rspec-gem-private_key.pem') if File.exist?(private_key) @@ -47,5 +47,5 @@ Gem::Specification.new do |s| s.add_development_dependency "aruba", "~> 0.14.10" s.add_development_dependency 'cucumber', '~> 1.3' s.add_development_dependency 'minitest', '~> 5.2' - s.add_development_dependency 'rake', '> 10.0.0' + s.add_development_dependency 'rake', '> 12.3.2' end diff --git a/rspec-expectations/spec/rspec/expectations/configuration_spec.rb b/rspec-expectations/spec/rspec/expectations/configuration_spec.rb index f7000e9ca..a488068f4 100644 --- a/rspec-expectations/spec/rspec/expectations/configuration_spec.rb +++ b/rspec-expectations/spec/rspec/expectations/configuration_spec.rb @@ -44,32 +44,6 @@ class << rspec_dup; undef configuration; end end end - context 'on an interpreter that does not provide BasicObject', :uses_should, :unless => defined?(::BasicObject) do - def with_delegate - in_sub_process_if_possible do - require 'delegate' - RSpec::Expectations::Syntax.disable_should(Delegator) - yield - end - end - - let(:klass) do - Class.new(SimpleDelegator) do - def delegated?; true; end - end - end - - let(:instance) { klass.new(Object.new) } - - it 'provides a means to manually add it Delegator' do - with_delegate do - instance.should_not respond_to(:delegated?) # because #should is being delegated... - config.add_should_and_should_not_to Delegator - instance.should respond_to(:delegated?) # now it should work! - end - end - end - describe "#include_chain_clauses_in_custom_matcher_descriptions?" do it "is false by default" do expect(config.include_chain_clauses_in_custom_matcher_descriptions?).to be false diff --git a/rspec-expectations/spec/rspec/expectations/extensions/kernel_spec.rb b/rspec-expectations/spec/rspec/expectations/extensions/kernel_spec.rb index 00c68a8c4..c8c4e20b5 100644 --- a/rspec-expectations/spec/rspec/expectations/extensions/kernel_spec.rb +++ b/rspec-expectations/spec/rspec/expectations/extensions/kernel_spec.rb @@ -19,7 +19,7 @@ }.to fail_with("the failure message") end - context "on interpretters that have BasicObject", :if => defined?(BasicObject) do + context "on interpretters that have BasicObject" do let(:proxy_class) do Class.new(BasicObject) do def initialize(target) diff --git a/rspec-expectations/spec/rspec/expectations/failure_aggregator_spec.rb b/rspec-expectations/spec/rspec/expectations/failure_aggregator_spec.rb index cf533b1a2..a60e10b58 100644 --- a/rspec-expectations/spec/rspec/expectations/failure_aggregator_spec.rb +++ b/rspec-expectations/spec/rspec/expectations/failure_aggregator_spec.rb @@ -429,24 +429,14 @@ def fail_including fail { |e| expect(e.message).to include(yield) } end - # Each Ruby version return a different exception complement. - # This method gets the current version and return the - # right complement. - if RSpec::Support::Ruby.mri? && RUBY_VERSION > "1.8.7" + # Ruby imprementations return different exception complements + if RSpec::Support::Ruby.mri? def exception_complement(block_levels) ":in `block (#{block_levels} levels) in '" end - elsif RSpec::Support::Ruby.mri? - def exception_complement(block_levels) - "" - end - elsif RUBY_VERSION > "2.0.0" - def exception_complement(block_levels) - ":in `block in Expectations'" - end else def exception_complement(block_levels) - ":in `Expectations'" + ":in `block in Expectations'" end end end diff --git a/rspec-expectations/spec/rspec/expectations/syntax_spec.rb b/rspec-expectations/spec/rspec/expectations/syntax_spec.rb index a1b147f89..a931aee4f 100644 --- a/rspec-expectations/spec/rspec/expectations/syntax_spec.rb +++ b/rspec-expectations/spec/rspec/expectations/syntax_spec.rb @@ -84,10 +84,4 @@ module Expectations end end end - - RSpec.describe Expectations do - it "does not inadvertently define BasicObject on 1.8", :if => RUBY_VERSION.to_f < 1.9 do - expect(defined?(::BasicObject)).to be nil - end - end end diff --git a/rspec-expectations/spec/rspec/matchers/aliased_matcher_spec.rb b/rspec-expectations/spec/rspec/matchers/aliased_matcher_spec.rb index 0902ecfeb..ca3c45b6b 100644 --- a/rspec-expectations/spec/rspec/matchers/aliased_matcher_spec.rb +++ b/rspec-expectations/spec/rspec/matchers/aliased_matcher_spec.rb @@ -49,7 +49,7 @@ def description include_examples "making a copy", :dup include_examples "making a copy", :clone - it 'can get a method object for delegated methods', :if => (RUBY_VERSION.to_f > 1.8) do + it 'can get a method object for delegated methods' do matcher = my_base_matcher decorated = AliasedMatcher.new(matcher, Proc.new {}) diff --git a/rspec-expectations/spec/rspec/matchers/built_in/be_spec.rb b/rspec-expectations/spec/rspec/matchers/built_in/be_spec.rb index 47fa0ba2e..7ef0d9762 100644 --- a/rspec-expectations/spec/rspec/matchers/built_in/be_spec.rb +++ b/rspec-expectations/spec/rspec/matchers/built_in/be_spec.rb @@ -128,9 +128,8 @@ def to_return expect(object).to be_predicate(hash_a_like.new) end - it 'handles keyword arguments to the predicate', :if => RSpec::Support::RubyFeatures.required_kw_args_supported? do + it 'handles keyword arguments to the predicate' do object = Object.new - binding.eval(<<-CODE, __FILE__, __LINE__) def object.predicate?(returns:); returns; end expect(object).to be_predicate(returns: true) @@ -138,7 +137,6 @@ def object.predicate?(returns:); returns; end expect { expect(object).to be_predicate(returns: false) }.to fail expect { expect(object).to_not be_predicate(returns: true) }.to fail - CODE expect { expect(object).to be_predicate }.to raise_error(ArgumentError) expect { expect(object).to be_predicate(true) }.to raise_error(ArgumentError) diff --git a/rspec-expectations/spec/rspec/matchers/built_in/captures_spec.rb b/rspec-expectations/spec/rspec/matchers/built_in/captures_spec.rb index 417297dbc..653520c39 100644 --- a/rspec-expectations/spec/rspec/matchers/built_in/captures_spec.rb +++ b/rspec-expectations/spec/rspec/matchers/built_in/captures_spec.rb @@ -18,28 +18,26 @@ }.to fail_with(/expected \/\(a\)\/ to match "123"/) end - if RUBY_VERSION != "1.8.7" - it "matches a regex with named captures" do - expect("a123a").to match(Regexp.new("(?123)")).with_captures(:num => "123") - end + it "matches a regex with named captures" do + expect("a123a").to match(Regexp.new("(?123)")).with_captures(:num => "123") + end - it "matches a regex with a nested matcher" do - expect("a123a").to match(Regexp.new("(?123)(asdf)?")).with_captures(a_hash_including(:num => "123")) - end + it "matches a regex with a nested matcher" do + expect("a123a").to match(Regexp.new("(?123)(asdf)?")).with_captures(a_hash_including(:num => "123")) + end - it "does not match a regex with an incorrect named group match" do - expect("a123a").not_to match(Regexp.new("(?a)")).with_captures(:name => "b") - end + it "does not match a regex with an incorrect named group match" do + expect("a123a").not_to match(Regexp.new("(?a)")).with_captures(:name => "b") + end - it "has a sensible failure description with a hash including matcher" do - expect { - expect("a123a").not_to match(Regexp.new("(?123)(asdf)?")).with_captures(a_hash_including(:num => "123")) - }.to fail_with(/num => "123"/) - end + it "has a sensible failure description with a hash including matcher" do + expect { + expect("a123a").not_to match(Regexp.new("(?123)(asdf)?")).with_captures(a_hash_including(:num => "123")) + }.to fail_with(/num => "123"/) + end - it "matches named captures when not passing a hash" do - expect("a123a").to match(Regexp.new("(?123)")).with_captures("123") - end + it "matches named captures when not passing a hash" do + expect("a123a").to match(Regexp.new("(?123)")).with_captures("123") end end @@ -62,28 +60,26 @@ }.to fail_with(/expected \/\(a\)\/ to match "123"/) end - if RUBY_VERSION != "1.8.7" - it "matches a regex with named captures" do - expect(Regexp.new("(?123)")).to match("a123a").with_captures(:num => "123") - end + it "matches a regex with named captures" do + expect(Regexp.new("(?123)")).to match("a123a").with_captures(:num => "123") + end - it "matches a regex with a nested matcher" do - expect(Regexp.new("(?123)(asdf)?")).to match("a123a").with_captures(a_hash_including(:num => "123")) - end + it "matches a regex with a nested matcher" do + expect(Regexp.new("(?123)(asdf)?")).to match("a123a").with_captures(a_hash_including(:num => "123")) + end - it "does not match a regex with an incorrect named group match" do - expect(Regexp.new("(?a)")).not_to match("a123a").with_captures(:name => "b") - end + it "does not match a regex with an incorrect named group match" do + expect(Regexp.new("(?a)")).not_to match("a123a").with_captures(:name => "b") + end - it "has a sensible failure description with a hash including matcher" do - expect { - expect(Regexp.new("(?123)(asdf)?")).not_to match("a123a").with_captures(a_hash_including(:num => "123")) - }.to fail_with(/num => "123"/) - end + it "has a sensible failure description with a hash including matcher" do + expect { + expect(Regexp.new("(?123)(asdf)?")).not_to match("a123a").with_captures(a_hash_including(:num => "123")) + }.to fail_with(/num => "123"/) + end - it "matches named captures when not passing a hash" do - expect(Regexp.new("(?123)")).to match("a123a").with_captures("123") - end + it "matches named captures when not passing a hash" do + expect(Regexp.new("(?123)")).to match("a123a").with_captures("123") end end end diff --git a/rspec-expectations/spec/rspec/matchers/built_in/change_spec.rb b/rspec-expectations/spec/rspec/matchers/built_in/change_spec.rb index dbcba5b9d..eb6172b2c 100644 --- a/rspec-expectations/spec/rspec/matchers/built_in/change_spec.rb +++ b/rspec-expectations/spec/rspec/matchers/built_in/change_spec.rb @@ -303,26 +303,8 @@ def hash end context 'when the receiver is an object that does not respond to #class such as BasicObject' do - let(:basic_object) do - basic_object_class.new - end - - let(:basic_object_class) do - defined?(BasicObject) ? BasicObject : fake_basic_object_class - end - - let(:fake_basic_object_class) do - Class.new do - def self.to_s - 'BasicObject' - end - - undef class, inspect, respond_to? - end - end - it 'can properly extract the class name' do - expect(change(basic_object, :__id__).description).to eq 'change `BasicObject#__id__`' + expect(change(BasicObject.new, :__id__).description).to eq 'change `BasicObject#__id__`' end end diff --git a/rspec-expectations/spec/rspec/matchers/built_in/eq_spec.rb b/rspec-expectations/spec/rspec/matchers/built_in/eq_spec.rb index 48cc4576f..45fa37635 100644 --- a/rspec-expectations/spec/rspec/matchers/built_in/eq_spec.rb +++ b/rspec-expectations/spec/rspec/matchers/built_in/eq_spec.rb @@ -78,9 +78,6 @@ module Matchers end describe '#description' do - # Ruby 1.8.7 produces a less precise output - expected_seconds = Time.method_defined?(:nsec) ? '000000000' : '000000' - [ [nil, 'eq nil'], [true, 'eq true'], @@ -94,7 +91,7 @@ module Matchers [{ :foo => :bar }, 'eq {:foo=>:bar}'], [Class, 'eq Class'], [RSpec, 'eq RSpec'], - [Time.utc(2014, 1, 1), "eq 2014-01-01 00:00:00.#{expected_seconds} +0000"], + [Time.utc(2014, 1, 1), "eq 2014-01-01 00:00:00.000000000 +0000"], ].each do |expected, expected_description| context "with #{expected.inspect}" do around { |ex| with_env_vars('TZ' => 'UTC', &ex) } if expected.is_a?(Time) @@ -118,10 +115,6 @@ module Matchers context "with Complex(1, 2)" do it "is eq to Complex(1, 2).inspect" do in_sub_process_if_possible do - # complex is available w/o requiring on ruby 1.9+. - # Loading it on 1.9+ issues a warning, so we only load it on 1.8.7. - require 'complex' if RUBY_VERSION == '1.8.7' - complex = Complex(1, 2) expect(eq(complex).description).to eq "eq #{complex.inspect}" end diff --git a/rspec-expectations/spec/rspec/matchers/built_in/has_spec.rb b/rspec-expectations/spec/rspec/matchers/built_in/has_spec.rb index 8a3bb5ca7..fbb128bc9 100644 --- a/rspec-expectations/spec/rspec/matchers/built_in/has_spec.rb +++ b/rspec-expectations/spec/rspec/matchers/built_in/has_spec.rb @@ -8,22 +8,14 @@ expect({ :a => "A" }).to have_key(:a) end - if RSpec::Support::RubyFeatures.required_kw_args_supported? - binding.eval(<<-CODE, __FILE__, __LINE__) - it 'supports the use of required keyword arguments' do - thing = Class.new { def has_keyword?(keyword:); keyword == 'a'; end } - expect(thing.new).to have_keyword(keyword: 'a') - end - CODE + it 'supports the use of required keyword arguments' do + thing = Class.new { def has_keyword?(keyword:); keyword == 'a'; end } + expect(thing.new).to have_keyword(keyword: 'a') end - if RSpec::Support::RubyFeatures.kw_args_supported? - binding.eval(<<-CODE, __FILE__, __LINE__) - it 'supports the use of optional keyword arguments' do - thing = Class.new { def has_keyword?(keyword: 'b'); keyword == 'a'; end } - expect(thing.new).to have_keyword(keyword: 'a') - end - CODE + it 'supports the use of optional keyword arguments' do + thing = Class.new { def has_keyword?(keyword: 'b'); keyword == 'a'; end } + expect(thing.new).to have_keyword(keyword: 'a') end it "fails if #has_sym?(*args) returns false" do diff --git a/rspec-expectations/spec/rspec/matchers/built_in/include_spec.rb b/rspec-expectations/spec/rspec/matchers/built_in/include_spec.rb index 09c425bff..29df24d88 100644 --- a/rspec-expectations/spec/rspec/matchers/built_in/include_spec.rb +++ b/rspec-expectations/spec/rspec/matchers/built_in/include_spec.rb @@ -890,7 +890,7 @@ def matches?(_) end describe "expect(hash).to include(key_matcher)" do - it "passes when the matcher matches a key", :if => (RUBY_VERSION.to_f > 1.8) do + it "passes when the matcher matches a key" do expect(:drink => "water", :food => "bread").to include(match(/foo/)) end @@ -899,7 +899,7 @@ def matches?(_) expect(description).to eq("include (match /foo/)") end - it 'fails with a clear message when the matcher does not match', :if => (RUBY_VERSION.to_f > 1.8) do + it 'fails with a clear message when the matcher does not match' do expect { expect(:drink => "water", :food => "bread").to include(match(/bar/)) }.to fail_matching('expected {:drink => "water", :food => "bread"} to include (match /bar/)') @@ -907,19 +907,19 @@ def matches?(_) end describe "expect(hash).to include(key_matcher => value)" do - it "passes when the matcher matches a pair", :if => (RUBY_VERSION.to_f > 1.8) do + it "passes when the matcher matches a pair" do expect(:drink => "water", :food => "bread").to include(match(/foo/) => "bread") end - it "passes when the matcher matches all pairs", :if => (RUBY_VERSION.to_f > 1.8) do + it "passes when the matcher matches all pairs" do expect(:drink => "water", :food => "bread").to include(match(/foo/) => "bread", match(/ink/) => "water") end - it "passes with a natural matcher", :if => (RUBY_VERSION.to_f > 1.8) do + it "passes with a natural matcher" do expect(:drink => "water", :food => "bread").to include(/foo/ => "bread") end - it "passes with a natural matcher", :if => (RUBY_VERSION.to_f > 1.8) do + it "passes with a natural matcher" do expect(:drink => "water", :food => "bread").to include(/foo/ => /read/) end @@ -928,19 +928,19 @@ def matches?(_) expect(description).to eq('include {(match /foo/) => "bread"}') end - it 'fails with a clear message when the value does not match', :if => (RUBY_VERSION.to_f > 1.8) do + it 'fails with a clear message when the value does not match' do expect { expect(:drink => "water", :food => "bread").to include(match(/foo/) => "meat") }.to fail_matching('expected {:drink => "water", :food => "bread"} to include {(match /foo/) => "meat"}') end - it 'fails with a clear message when the matcher does not match', :if => (RUBY_VERSION.to_f > 1.8) do + it 'fails with a clear message when the matcher does not match' do expect { expect(:drink => "water", :food => "bread").to include(match(/bar/) => "bread") }.to fail_matching('expected {:drink => "water", :food => "bread"} to include {(match /bar/) => "bread"}') end - it 'fails with a clear message when several matchers do not match', :if => (RUBY_VERSION.to_f > 1.8) do + it 'fails with a clear message when several matchers do not match' do expect { expect(:drink => "water", :food => "bread").to include(match(/bar/) => "bread", match(/baz/) => "water") }.to fail_matching('expected {:drink => "water", :food => "bread"} to include {(match /bar/) => "bread", (match /baz/) => "water"}') diff --git a/rspec-expectations/spec/rspec/matchers/built_in/operators_spec.rb b/rspec-expectations/spec/rspec/matchers/built_in/operators_spec.rb index 5db34a3ab..830ff38d8 100644 --- a/rspec-expectations/spec/rspec/matchers/built_in/operators_spec.rb +++ b/rspec-expectations/spec/rspec/matchers/built_in/operators_spec.rb @@ -47,7 +47,7 @@ def method_missing(name, *args, &block) end end - describe "unsupported operators", :if => RUBY_VERSION.to_f == 1.9 do + describe "unsupported operators" do it "raises an appropriate error for should != expected" do expect { "apple".should != "pear" diff --git a/rspec-expectations/spec/rspec/matchers/built_in/respond_to_spec.rb b/rspec-expectations/spec/rspec/matchers/built_in/respond_to_spec.rb index c02d2c58c..fa918b8df 100644 --- a/rspec-expectations/spec/rspec/matchers/built_in/respond_to_spec.rb +++ b/rspec-expectations/spec/rspec/matchers/built_in/respond_to_spec.rb @@ -611,408 +611,394 @@ def obj.some_method(arg, arg2, arg3, *args); end end end -if RSpec::Support::RubyFeatures.kw_args_supported? - RSpec.describe "expect(...).to respond_to(:sym).with_keywords(:foo, :bar)" do - it 'passes if target responds to :sym with specified optional keywords' do - obj = Object.new - eval %{def obj.foo(a: nil, b: nil); end} - expect(obj).to respond_to(:foo).with_keywords(:a, :b) - end +RSpec.describe "expect(...).to respond_to(:sym).with_keywords(:foo, :bar)" do + it 'passes if target responds to :sym with specified optional keywords' do + obj = Object.new + eval %{def obj.foo(a: nil, b: nil); end} + expect(obj).to respond_to(:foo).with_keywords(:a, :b) + end + + it 'passes if target responds to :sym with any keywords' do + obj = Object.new + eval %{def obj.foo(**kw_args); end} + expect(obj).to respond_to(:foo).with_keywords(:a, :b) + end + + it 'passes if target is :new with keywords' do + # note we can't use the metaobject definition for initialize + klass = eval %{Class.new { def initialize(a: nil, b: nil); end}} + expect(klass).to respond_to(:new).with_keywords(:a, :b) + + # note we can't use the metaobject definition for initialize + klass_2 = eval %{Class.new { def initialize(**kw_args); end}} + expect(klass_2).to respond_to(:new).with_keywords(:a, :b) + end + + it "fails if target does not respond to :sym" do + obj = Object.new + expect { + expect(obj).to respond_to(:some_method).with_keywords(:a, :b) + }.to fail_with(/expected .* to respond to :some_method with keywords :a and :b/) + end - it 'passes if target responds to :sym with any keywords' do - obj = Object.new - eval %{def obj.foo(**kw_args); end} + it "fails if :sym does not expect specified keywords" do + obj = Object.new + def obj.foo; end + expect { expect(obj).to respond_to(:foo).with_keywords(:a, :b) - end + }.to fail_with(/expected .* to respond to :foo with keywords :a and :b/) + end - it 'passes if target is :new with keywords' do - # note we can't use the metaobject definition for initialize - klass = eval %{Class.new { def initialize(a: nil, b: nil); end}} + it "fails if :sym does not expect many specified keywords" do + obj = Object.new + def obj.foo; end + expect { + expect(obj).to respond_to(:foo).with_keywords(:a, :b, :c, :d, :e, :f) + }.to fail_with(/expected .* to respond to :foo with keywords :a, :b, :c, :d, :e, and :f/) + end + + it 'fails if target is :new but initialize does not expect the right keywords' do + # note we can't use the metaobject definition for initialize + klass = eval %{Class.new { def initialize(a: nil); end}} + expect { expect(klass).to respond_to(:new).with_keywords(:a, :b) + }.to fail_with(/expected .* to respond to :new with keywords :a and :b/) + end - # note we can't use the metaobject definition for initialize - klass_2 = eval %{Class.new { def initialize(**kw_args); end}} - expect(klass_2).to respond_to(:new).with_keywords(:a, :b) - end + it "passes if target responds to :sym with specified required keywords" do + obj = Object.new + eval %{def obj.foo(a:, b:, c: nil, d: nil); end} + expect(obj).to respond_to(:foo).with_keywords(:a, :b) + end - it "fails if target does not respond to :sym" do - obj = Object.new - expect { - expect(obj).to respond_to(:some_method).with_keywords(:a, :b) - }.to fail_with(/expected .* to respond to :some_method with keywords :a and :b/) - end + it "passes if target responds to :sym with keyword arg splat" do + obj = Object.new + eval %{def obj.foo(**rest); end} + expect(obj).to respond_to(:foo).with_keywords(:a, :b) + end - it "fails if :sym does not expect specified keywords" do - obj = Object.new - def obj.foo; end - expect { - expect(obj).to respond_to(:foo).with_keywords(:a, :b) - }.to fail_with(/expected .* to respond to :foo with keywords :a and :b/) - end + it 'passes if target is :new and initialize has specified required keywords' do + # note we can't use the metaobject definition for initialize + klass = eval %{Class.new { def initialize(a:, b:); end}} + expect(klass).to respond_to(:new).with_keywords(:a, :b) + end - it "fails if :sym does not expect many specified keywords" do - obj = Object.new - def obj.foo; end - expect { - expect(obj).to respond_to(:foo).with_keywords(:a, :b, :c, :d, :e, :f) - }.to fail_with(/expected .* to respond to :foo with keywords :a, :b, :c, :d, :e, and :f/) - end + it "fails if :sym expects specified optional keywords but expects missing required keywords" do + obj = Object.new + eval %{def obj.foo(a:, b:, c: nil, d: nil); end} + expect { + expect(obj).to respond_to(:some_method).with_keywords(:c, :d) + }.to fail_with(/expected .* to respond to :some_method with keywords :c and :d/) + end - it 'fails if target is :new but initialize does not expect the right keywords' do - # note we can't use the metaobject definition for initialize - klass = eval %{Class.new { def initialize(a: nil); end}} - expect { - expect(klass).to respond_to(:new).with_keywords(:a, :b) - }.to fail_with(/expected .* to respond to :new with keywords :a and :b/) - end + it "fails if target responds to :sym with keyword arg splat but missing required keywords" do + obj = Object.new + eval %{def obj.foo(a:, b:, **rest); end} + expect { + expect(obj).to respond_to(:some_method).with_keywords(:c, :d) + }.to fail_with(/expected .* to respond to :some_method with keywords :c and :d/) + end - if RSpec::Support::RubyFeatures.required_kw_args_supported? - it "passes if target responds to :sym with specified required keywords" do - obj = Object.new - eval %{def obj.foo(a:, b:, c: nil, d: nil); end} - expect(obj).to respond_to(:foo).with_keywords(:a, :b) - end - - it "passes if target responds to :sym with keyword arg splat" do - obj = Object.new - eval %{def obj.foo(**rest); end} - expect(obj).to respond_to(:foo).with_keywords(:a, :b) - end - - it 'passes if target is :new and initialize has specified required keywords' do - # note we can't use the metaobject definition for initialize - klass = eval %{Class.new { def initialize(a:, b:); end}} - expect(klass).to respond_to(:new).with_keywords(:a, :b) - end - - it "fails if :sym expects specified optional keywords but expects missing required keywords" do - obj = Object.new - eval %{def obj.foo(a:, b:, c: nil, d: nil); end} - expect { - expect(obj).to respond_to(:some_method).with_keywords(:c, :d) - }.to fail_with(/expected .* to respond to :some_method with keywords :c and :d/) - end - - it "fails if target responds to :sym with keyword arg splat but missing required keywords" do - obj = Object.new - eval %{def obj.foo(a:, b:, **rest); end} - expect { - expect(obj).to respond_to(:some_method).with_keywords(:c, :d) - }.to fail_with(/expected .* to respond to :some_method with keywords :c and :d/) - end - - it 'fails if target is :new and initialize has is missing required keywords' do - # note we can't use the metaobject definition for initialize - klass = eval %{Class.new { def initialize(a:, b:); end}} - expect { - expect(klass).to respond_to(:new).with_keywords(:c, :d) - }.to fail_with(/expected .* to respond to :new with keywords :c and :d/) - end - end + it 'fails if target is :new and initialize has is missing required keywords' do + # note we can't use the metaobject definition for initialize + klass = eval %{Class.new { def initialize(a:, b:); end}} + expect { + expect(klass).to respond_to(:new).with_keywords(:c, :d) + }.to fail_with(/expected .* to respond to :new with keywords :c and :d/) end +end - RSpec.describe "expect(...).to respond_to(:sym).with(2).arguments.and_keywords(:foo, :bar)" do - it "passes if target responds to :sym with 2 args and specified optional keywords" do - obj = Object.new - eval %{def obj.foo(a, b, u: nil, v: nil); end} - expect(obj).to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) - end +RSpec.describe "expect(...).to respond_to(:sym).with(2).arguments.and_keywords(:foo, :bar)" do + it "passes if target responds to :sym with 2 args and specified optional keywords" do + obj = Object.new + eval %{def obj.foo(a, b, u: nil, v: nil); end} + expect(obj).to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) + end - it "passes if target responds to :sym with any number of arguments and specified optional keywords" do - obj = Object.new - eval %{def obj.foo(*args, u: nil, v: nil); end} - expect(obj).to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) - end + it "passes if target responds to :sym with any number of arguments and specified optional keywords" do + obj = Object.new + eval %{def obj.foo(*args, u: nil, v: nil); end} + expect(obj).to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) + end - it "passes if target responds to :sym with one or more arguments and specified optional keywords" do - obj = Object.new - eval %{def obj.foo(a, *args, u: nil, v: nil); end} - expect(obj).to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) - end + it "passes if target responds to :sym with one or more arguments and specified optional keywords" do + obj = Object.new + eval %{def obj.foo(a, *args, u: nil, v: nil); end} + expect(obj).to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) + end - it "passes if target responds to :sym with two or more arguments and specified optional keywords" do - obj = Object.new - eval %{def obj.foo(a, b, *args, u: nil, v: nil); end} - expect(obj).to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) - end + it "passes if target responds to :sym with two or more arguments and specified optional keywords" do + obj = Object.new + eval %{def obj.foo(a, b, *args, u: nil, v: nil); end} + expect(obj).to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) + end - it "fails if target does not respond to :sym" do - obj = Object.new - expect { - expect(obj).to respond_to(:some_method).with(2).arguments.and_keywords(:u, :v) - }.to fail_with(/expected .* to respond to :some_method with 2 arguments and keywords :u and :v/) - end + it "fails if target does not respond to :sym" do + obj = Object.new + expect { + expect(obj).to respond_to(:some_method).with(2).arguments.and_keywords(:u, :v) + }.to fail_with(/expected .* to respond to :some_method with 2 arguments and keywords :u and :v/) + end - it "fails if :sym expects 1 argument" do - obj = Object.new - eval %{def obj.foo(a, u: nil, v: nil); end} - expect { - expect(obj).to respond_to(:some_method).with(2).arguments.and_keywords(:u, :v) - }.to fail_with(/expected .* to respond to :some_method with 2 arguments and keywords :u and :v/) - end + it "fails if :sym expects 1 argument" do + obj = Object.new + eval %{def obj.foo(a, u: nil, v: nil); end} + expect { + expect(obj).to respond_to(:some_method).with(2).arguments.and_keywords(:u, :v) + }.to fail_with(/expected .* to respond to :some_method with 2 arguments and keywords :u and :v/) + end - it "fails if :sym does not expect specified keywords" do - obj = Object.new - def obj.foo(a, b); end - expect { - expect(obj).to respond_to(:some_method).with(2).arguments.and_keywords(:u, :v) - }.to fail_with(/expected .* to respond to :some_method with 2 arguments and keywords :u and :v/) - end + it "fails if :sym does not expect specified keywords" do + obj = Object.new + def obj.foo(a, b); end + expect { + expect(obj).to respond_to(:some_method).with(2).arguments.and_keywords(:u, :v) + }.to fail_with(/expected .* to respond to :some_method with 2 arguments and keywords :u and :v/) + end - if RSpec::Support::RubyFeatures.required_kw_args_supported? - it "passes if target responds to :sym with 2 args and specified required keywords" do - obj = Object.new - eval %{def obj.foo(a, b, u:, v:); end} - expect(obj).to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) - end - - it "passes if target responds to :sym with 2 args and keyword arg splat" do - obj = Object.new - eval %{def obj.foo(a, b, **rest); end} - expect(obj).to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) - end - - it "passes for new when target responds to initialize with a mixture of arguments" do - klass = eval %{Class.new { def initialize(a, b, c:, d: nil); end }} - expect(klass).to respond_to(:new).with(2).arguments.and_keywords(:c, :d) - end - - it "fails if :sym expects 2 arguments and specified optional keywords but expects missing required keywords" do - obj = Object.new - eval %{def obj.foo(a, b, u: nil, v: nil, x:, y:); end} - expect { - expect(obj).to respond_to(:some_method).with(2).arguments.and_keywords(:u, :v) - }.to fail_with(/expected .* to respond to :some_method with 2 arguments and keywords :u and :v/) - end - - it "fails for new when target responds to initialize with the wrong mixture of arguments" do - klass = eval %{Class.new { def initialize(a, b, c:); end }} - expect { - expect(klass).to respond_to(:new).with(2).arguments.and_keywords(:c, :d) - }.to fail_with(/expected .* to respond to :new with 2 arguments and keywords :c and :d/) - end - end + it "passes if target responds to :sym with 2 args and specified required keywords" do + obj = Object.new + eval %{def obj.foo(a, b, u:, v:); end} + expect(obj).to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) end - RSpec.describe "expect(...).to respond_to(:sym).with_any_keywords" do - it "passes if target responds to any keywords" do - obj = Object.new - eval %{def obj.foo(**kw_args); end} - expect(obj).to respond_to(:foo).with_any_keywords - end + it "passes if target responds to :sym with 2 args and keyword arg splat" do + obj = Object.new + eval %{def obj.foo(a, b, **rest); end} + expect(obj).to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) + end + + it "passes for new when target responds to initialize with a mixture of arguments" do + klass = eval %{Class.new { def initialize(a, b, c:, d: nil); end }} + expect(klass).to respond_to(:new).with(2).arguments.and_keywords(:c, :d) + end + + it "fails if :sym expects 2 arguments and specified optional keywords but expects missing required keywords" do + obj = Object.new + eval %{def obj.foo(a, b, u: nil, v: nil, x:, y:); end} + expect { + expect(obj).to respond_to(:some_method).with(2).arguments.and_keywords(:u, :v) + }.to fail_with(/expected .* to respond to :some_method with 2 arguments and keywords :u and :v/) + end + + it "fails for new when target responds to initialize with the wrong mixture of arguments" do + klass = eval %{Class.new { def initialize(a, b, c:); end }} + expect { + expect(klass).to respond_to(:new).with(2).arguments.and_keywords(:c, :d) + }.to fail_with(/expected .* to respond to :new with 2 arguments and keywords :c and :d/) + end +end + +RSpec.describe "expect(...).to respond_to(:sym).with_any_keywords" do + it "passes if target responds to any keywords" do + obj = Object.new + eval %{def obj.foo(**kw_args); end} + expect(obj).to respond_to(:foo).with_any_keywords + end + + it "passes when initialize responds to any keywords and we check new" do + klass = eval %{Class.new { def initialize(**kw_args); end }} + expect(klass).to respond_to(:new).with_any_keywords + end + + it "fails if target does not respond to :sym" do + obj = Object.new + expect { + expect(obj).to respond_to(:some_method).with_any_keywords + }.to fail_with(/expected .* to respond to :some_method/) + end - it "passes when initialize responds to any keywords and we check new" do - klass = eval %{Class.new { def initialize(**kw_args); end }} + it "fails if :sym expects a limited set of keywords" do + obj = Object.new + eval %{def obj.some_method(a: nil, b: nil); end} + expect { + expect(obj).to respond_to(:some_method).with_any_keywords + }.to fail_with(/expected .* to respond to :some_method with any keywords/) + end + + it "fails when initialize expects a limited set of keywords and we check new" do + klass = eval %{Class.new { def initialize(a: nil); end }} + expect { expect(klass).to respond_to(:new).with_any_keywords - end + }.to fail_with(/expected .* to respond to :new with any keywords/) + end - it "fails if target does not respond to :sym" do - obj = Object.new - expect { - expect(obj).to respond_to(:some_method).with_any_keywords - }.to fail_with(/expected .* to respond to :some_method/) - end + it "fails if :sym expects missing required keywords" do + obj = Object.new + eval %{def obj.some_method(a:, b:, **kw_args); end} + expect { + expect(obj).to respond_to(:some_method).with_any_keywords + }.to fail_with(/expected .* to respond to :some_method with any keywords/) + end - it "fails if :sym expects a limited set of keywords" do - obj = Object.new - eval %{def obj.some_method(a: nil, b: nil); end} - expect { - expect(obj).to respond_to(:some_method).with_any_keywords - }.to fail_with(/expected .* to respond to :some_method with any keywords/) - end + it "fails if :initialize expects missing required keywords when we test new" do + klass = eval %{Class.new { def initialize(a:, **kw_args); end }} + eval %{def initialize(a:, b:, **kw_args); end} + expect { + expect(klass).to respond_to(:new).with_any_keywords + }.to fail_with(/expected .* to respond to :new with any keywords/) + end +end - it "fails when initialize expects a limited set of keywords and we check new" do - klass = eval %{Class.new { def initialize(a: nil); end }} - expect { - expect(klass).to respond_to(:new).with_any_keywords - }.to fail_with(/expected .* to respond to :new with any keywords/) - end +RSpec.describe "expect(...).not_to respond_to(:sym).with_keywords(:foo, :bar)" do + it "fails if target responds to :sym with specified optional keywords" do + obj = Object.new + eval %{def obj.foo(a: nil, b: nil); end} + expect { + expect(obj).not_to respond_to(:foo).with_keywords(:a, :b) + }.to fail_with(/expected # not to respond to :foo with keywords :a and :b/) + end - if RSpec::Support::RubyFeatures.required_kw_args_supported? - it "fails if :sym expects missing required keywords" do - obj = Object.new - eval %{def obj.some_method(a:, b:, **kw_args); end} - expect { - expect(obj).to respond_to(:some_method).with_any_keywords - }.to fail_with(/expected .* to respond to :some_method with any keywords/) - end - - it "fails if :initialize expects missing required keywords when we test new" do - klass = eval %{Class.new { def initialize(a:, **kw_args); end }} - eval %{def initialize(a:, b:, **kw_args); end} - expect { - expect(klass).to respond_to(:new).with_any_keywords - }.to fail_with(/expected .* to respond to :new with any keywords/) - end - end + it "fails if target responds to :sym with any keywords" do + obj = Object.new + eval %{def obj.foo(**kw_args); end} + expect { + expect(obj).not_to respond_to(:foo).with_keywords(:a, :b) + }.to fail_with(/expected # not to respond to :foo with keywords :a and :b/) end - RSpec.describe "expect(...).not_to respond_to(:sym).with_keywords(:foo, :bar)" do - it "fails if target responds to :sym with specified optional keywords" do - obj = Object.new - eval %{def obj.foo(a: nil, b: nil); end} - expect { - expect(obj).not_to respond_to(:foo).with_keywords(:a, :b) - }.to fail_with(/expected # not to respond to :foo with keywords :a and :b/) - end + it "fails if target initialize responds to expected keywords when checking new" do + klass = eval %{Class.new { def initialize(**kw_args); end }} + expect { + expect(klass).not_to respond_to(:new).with_keywords(:a, :b) + }.to fail_with(/expected .* not to respond to :new with keywords :a and :b/) + end - it "fails if target responds to :sym with any keywords" do - obj = Object.new - eval %{def obj.foo(**kw_args); end} - expect { - expect(obj).not_to respond_to(:foo).with_keywords(:a, :b) - }.to fail_with(/expected # not to respond to :foo with keywords :a and :b/) - end + it "passes if target does not respond to :sym" do + obj = Object.new + expect(obj).not_to respond_to(:some_method).with_keywords(:a, :b) + end - it "fails if target initialize responds to expected keywords when checking new" do - klass = eval %{Class.new { def initialize(**kw_args); end }} - expect { - expect(klass).not_to respond_to(:new).with_keywords(:a, :b) - }.to fail_with(/expected .* not to respond to :new with keywords :a and :b/) - end + it "passes if :sym does not expect specified keywords" do + obj = Object.new + eval %{def obj.foo(a: nil, b: nil); end} + expect(obj).not_to respond_to(:some_method).with_keywords(:c, :d) + end - it "passes if target does not respond to :sym" do - obj = Object.new - expect(obj).not_to respond_to(:some_method).with_keywords(:a, :b) - end + it "fails if target responds to :sym with specified required keywords" do + obj = Object.new + eval %{def obj.foo(a:, b:); end} + expect { + expect(obj).not_to respond_to(:foo).with_keywords(:a, :b) + }.to fail_with(/expected # not to respond to :foo with keywords :a and :b/) + end - it "passes if :sym does not expect specified keywords" do - obj = Object.new - eval %{def obj.foo(a: nil, b: nil); end} - expect(obj).not_to respond_to(:some_method).with_keywords(:c, :d) - end + it "fails if target responds to :sym with keyword arg splat" do + obj = Object.new + eval %{def obj.foo(**rest); end} + expect { + expect(obj).not_to respond_to(:foo).with_keywords(:a, :b) + }.to fail_with(/expected # not to respond to :foo with keywords :a and :b/) + end - if RSpec::Support::RubyFeatures.required_kw_args_supported? - it "fails if target responds to :sym with specified required keywords" do - obj = Object.new - eval %{def obj.foo(a:, b:); end} - expect { - expect(obj).not_to respond_to(:foo).with_keywords(:a, :b) - }.to fail_with(/expected # not to respond to :foo with keywords :a and :b/) - end - - it "fails if target responds to :sym with keyword arg splat" do - obj = Object.new - eval %{def obj.foo(**rest); end} - expect { - expect(obj).not_to respond_to(:foo).with_keywords(:a, :b) - }.to fail_with(/expected # not to respond to :foo with keywords :a and :b/) - end - - it "passes if :sym expects missing required keywords" do - obj = Object.new - eval %{def obj.foo(a:, b:, c: nil, d: nil); end} - expect(obj).not_to respond_to(:some_method).with_keywords(:c, :d) - end - - it "passes if :initialize expects missing required keywords for :new" do - klass = eval %{Class.new { def initialize(a:, b:, c: nil, d: nil); end }} - expect(klass).not_to respond_to(:new).with_keywords(:c, :d) - end - end + it "passes if :sym expects missing required keywords" do + obj = Object.new + eval %{def obj.foo(a:, b:, c: nil, d: nil); end} + expect(obj).not_to respond_to(:some_method).with_keywords(:c, :d) end - RSpec.describe "expect(...).not_to respond_to(:sym).with(2).arguments.and_keywords(:foo, :bar)" do - it "fails if target responds to :sym with 2 args and specified optional keywords" do - obj = Object.new - eval %{def obj.foo(a, b, u: nil, v: nil); end} - expect { - expect(obj).not_to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) - }.to fail_with(/expected # not to respond to :foo with 2 arguments and keywords :u and :v/) - end + it "passes if :initialize expects missing required keywords for :new" do + klass = eval %{Class.new { def initialize(a:, b:, c: nil, d: nil); end }} + expect(klass).not_to respond_to(:new).with_keywords(:c, :d) + end +end - it "fails if target responds to :sym with any number of arguments and specified optional keywords" do - obj = Object.new - eval %{def obj.foo(*args, u: nil, v: nil); end} - expect { - expect(obj).not_to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) - }.to fail_with(/expected # not to respond to :foo with 2 arguments and keywords :u and :v/) - end +RSpec.describe "expect(...).not_to respond_to(:sym).with(2).arguments.and_keywords(:foo, :bar)" do + it "fails if target responds to :sym with 2 args and specified optional keywords" do + obj = Object.new + eval %{def obj.foo(a, b, u: nil, v: nil); end} + expect { + expect(obj).not_to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) + }.to fail_with(/expected # not to respond to :foo with 2 arguments and keywords :u and :v/) + end - it "fails if target responds to :sym with one or more arguments and specified optional keywords" do - obj = Object.new - eval %{def obj.foo(a, *args, u: nil, v: nil); end} - expect { - expect(obj).not_to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) - }.to fail_with(/expected # not to respond to :foo with 2 arguments and keywords :u and :v/) - end + it "fails if target responds to :sym with any number of arguments and specified optional keywords" do + obj = Object.new + eval %{def obj.foo(*args, u: nil, v: nil); end} + expect { + expect(obj).not_to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) + }.to fail_with(/expected # not to respond to :foo with 2 arguments and keywords :u and :v/) + end - it "fails if target responds to :sym with two or more arguments and specified optional keywords" do - obj = Object.new - eval %{def obj.foo(a, b, *args, u: nil, v: nil); end} - expect { - expect(obj).not_to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) - }.to fail_with(/expected # not to respond to :foo with 2 arguments and keywords :u and :v/) - end + it "fails if target responds to :sym with one or more arguments and specified optional keywords" do + obj = Object.new + eval %{def obj.foo(a, *args, u: nil, v: nil); end} + expect { + expect(obj).not_to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) + }.to fail_with(/expected # not to respond to :foo with 2 arguments and keywords :u and :v/) + end - it "passes if target does not respond to :sym" do - obj = Object.new - expect(obj).not_to respond_to(:some_method).with(2).arguments.and_keywords(:u, :v) - end + it "fails if target responds to :sym with two or more arguments and specified optional keywords" do + obj = Object.new + eval %{def obj.foo(a, b, *args, u: nil, v: nil); end} + expect { + expect(obj).not_to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) + }.to fail_with(/expected # not to respond to :foo with 2 arguments and keywords :u and :v/) + end - it "passes if :sym expects 1 argument" do - obj = Object.new - eval %{def obj.foo(a, u: nil, v: nil); end} - expect(obj).not_to respond_to(:some_method).with(2).arguments.and_keywords(:u, :v) - end + it "passes if target does not respond to :sym" do + obj = Object.new + expect(obj).not_to respond_to(:some_method).with(2).arguments.and_keywords(:u, :v) + end - it "passes if :sym does not expect specified keywords" do - obj = Object.new - def obj.foo(a, b); end - expect(obj).not_to respond_to(:some_method).with(2).arguments.and_keywords(:u, :v) - end + it "passes if :sym expects 1 argument" do + obj = Object.new + eval %{def obj.foo(a, u: nil, v: nil); end} + expect(obj).not_to respond_to(:some_method).with(2).arguments.and_keywords(:u, :v) + end - if RSpec::Support::RubyFeatures.required_kw_args_supported? - it "fails if target responds to :sym with 2 args and specified required keywords" do - obj = Object.new - eval %{def obj.foo(a, b, u:, v:); end} - expect { - expect(obj).not_to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) - }.to fail_with(/expected # not to respond to :foo with 2 arguments and keywords :u and :v/) - end - - it "fails if target responds to :sym with 2 args and keyword arg splat" do - obj = Object.new - eval %{def obj.foo(a, b, **rest); end} - expect { - expect(obj).not_to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) - }.to fail_with(/expected # not to respond to :foo with 2 arguments and keywords :u and :v/) - end - - it "passes if :sym expects 2 arguments and specified optional keywords but expects missing required keywords" do - obj = Object.new - eval %{def obj.foo(a, b, u: nil, v: nil, x:, y:); end} - expect(obj).not_to respond_to(:some_method).with(2).arguments.and_keywords(:u, :v) - end - end + it "passes if :sym does not expect specified keywords" do + obj = Object.new + def obj.foo(a, b); end + expect(obj).not_to respond_to(:some_method).with(2).arguments.and_keywords(:u, :v) end - RSpec.describe "expect(...).not_to respond_to(:sym).with_any_keywords" do - it "fails if target responds to any keywords" do - obj = Object.new - eval %{def obj.foo(**kw_args); end} - expect { - expect(obj).not_to respond_to(:foo).with_any_keywords - }.to fail_with(/expected # not to respond to :foo with any keywords/) - end + it "fails if target responds to :sym with 2 args and specified required keywords" do + obj = Object.new + eval %{def obj.foo(a, b, u:, v:); end} + expect { + expect(obj).not_to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) + }.to fail_with(/expected # not to respond to :foo with 2 arguments and keywords :u and :v/) + end - it "passes if target does not respond to :sym" do - obj = Object.new - expect(obj).not_to respond_to(:some_method).with_any_keywords - end + it "fails if target responds to :sym with 2 args and keyword arg splat" do + obj = Object.new + eval %{def obj.foo(a, b, **rest); end} + expect { + expect(obj).not_to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) + }.to fail_with(/expected # not to respond to :foo with 2 arguments and keywords :u and :v/) + end - it "passes if :sym expects a limited set of keywords" do - obj = Object.new - eval %{def obj.some_method(a: nil, b: nil); end} - expect(obj).not_to respond_to(:some_method).with_any_keywords - end + it "passes if :sym expects 2 arguments and specified optional keywords but expects missing required keywords" do + obj = Object.new + eval %{def obj.foo(a, b, u: nil, v: nil, x:, y:); end} + expect(obj).not_to respond_to(:some_method).with(2).arguments.and_keywords(:u, :v) + end +end - if RSpec::Support::RubyFeatures.required_kw_args_supported? - it "passes if :sym expects missing required keywords" do - obj = Object.new - eval %{def obj.some_method(a:, b:, **kw_args); end} - expect(obj).not_to respond_to(:some_method).with_any_keywords - end - end +RSpec.describe "expect(...).not_to respond_to(:sym).with_any_keywords" do + it "fails if target responds to any keywords" do + obj = Object.new + eval %{def obj.foo(**kw_args); end} + expect { + expect(obj).not_to respond_to(:foo).with_any_keywords + }.to fail_with(/expected # not to respond to :foo with any keywords/) + end + + it "passes if target does not respond to :sym" do + obj = Object.new + expect(obj).not_to respond_to(:some_method).with_any_keywords + end + + it "passes if :sym expects a limited set of keywords" do + obj = Object.new + eval %{def obj.some_method(a: nil, b: nil); end} + expect(obj).not_to respond_to(:some_method).with_any_keywords + end + + it "passes if :sym expects missing required keywords" do + obj = Object.new + eval %{def obj.some_method(a:, b:, **kw_args); end} + expect(obj).not_to respond_to(:some_method).with_any_keywords end end diff --git a/rspec-expectations/spec/rspec/matchers/built_in/yield_spec.rb b/rspec-expectations/spec/rspec/matchers/built_in/yield_spec.rb index 6075f4f12..cee5e13e3 100644 --- a/rspec-expectations/spec/rspec/matchers/built_in/yield_spec.rb +++ b/rspec-expectations/spec/rspec/matchers/built_in/yield_spec.rb @@ -222,7 +222,7 @@ def each_arg(*args, &block) }.to fail_with(/expected given block not to yield control/) end - it 'fails if the expect block does not accept an argument', :if => (RUBY_VERSION.to_f > 1.8) do + it 'fails if the expect block does not accept an argument' do expect { expect {}.not_to yield_control }.to raise_error(/expect block must accept an argument/) @@ -309,7 +309,7 @@ def each_arg(*args, &block) }.to fail_with(/expected given block not to yield with no arguments, but did/) end - it 'fails if the expect block does not accept an argument', :if => (RUBY_VERSION.to_f > 1.8) do + it 'fails if the expect block does not accept an argument' do expect { expect {}.not_to yield_with_no_args }.to raise_error(/expect block must accept an argument/) @@ -428,7 +428,7 @@ def each_arg(*args, &block) }.not_to yield_with_args(be_empty) end - it 'fails if the expect block does not accept an argument', :if => (RUBY_VERSION.to_f > 1.8) do + it 'fails if the expect block does not accept an argument' do expect { expect {}.not_to yield_with_args }.to raise_error(/expect block must accept an argument/) @@ -731,7 +731,7 @@ def each_arg(*args, &block) }.to fail_with(/expected given block not to yield successively/) end - it 'fails if the expect block does not accept an argument', :if => (RUBY_VERSION.to_f > 1.8) do + it 'fails if the expect block does not accept an argument' do expect { expect {}.not_to yield_successive_args(1, 2, 3) }.to raise_error(/expect block must accept an argument/) diff --git a/rspec-expectations/spec/rspec/matchers/dsl_spec.rb b/rspec-expectations/spec/rspec/matchers/dsl_spec.rb index 88477ccfd..46b085e34 100644 --- a/rspec-expectations/spec/rspec/matchers/dsl_spec.rb +++ b/rspec-expectations/spec/rspec/matchers/dsl_spec.rb @@ -29,44 +29,36 @@ def ok expect { matcher_b.i_dont_exist }.to raise_error(NameError) end - if RSpec::Support::RubyFeatures.required_kw_args_supported? - binding.eval(<<-CODE, __FILE__, __LINE__) - it 'supports the use of required keyword arguments in definition block' do - RSpec::Matchers.define(:match_required_kw) do |bar:| - match { expect(actual).to eq bar } - end - expect(1).to match_required_kw(bar: 1) + it 'supports the use of required keyword arguments in definition block' do + RSpec::Matchers.define(:match_required_kw) do |bar:| + match { expect(actual).to eq bar } end + expect(1).to match_required_kw(bar: 1) + end - def kw(a:) - a - end + def kw(a:) + a + end - it "supports the use of required keyword arguments on methods" do - RSpec::Matchers.define(:matcher_required_kw_on_method) {} - expect(matcher_required_kw_on_method.kw(a: 1)).to eq(1) - end - CODE + it "supports the use of required keyword arguments on methods" do + RSpec::Matchers.define(:matcher_required_kw_on_method) {} + expect(matcher_required_kw_on_method.kw(a: 1)).to eq(1) end - if RSpec::Support::RubyFeatures.kw_args_supported? - binding.eval(<<-CODE, __FILE__, __LINE__) - it 'supports the use of optional keyword arguments in definition block' do - RSpec::Matchers.define(:match_optional_kw) do |bar: nil| - match { expect(actual).to eq bar } - end - expect(1).to match_optional_kw(bar: 1) + it 'supports the use of optional keyword arguments in definition block' do + RSpec::Matchers.define(:match_optional_kw) do |bar: nil| + match { expect(actual).to eq bar } end + expect(1).to match_optional_kw(bar: 1) + end - def optional_kw(a: nil) - a - end + def optional_kw(a: nil) + a + end - it "supports the use of optional keyword arguments on methods" do - RSpec::Matchers.define(:matcher_optional_kw_on_method) {} - expect(matcher_optional_kw_on_method.optional_kw(a: 1)).to eq(1) - end - CODE + it "supports the use of optional keyword arguments on methods" do + RSpec::Matchers.define(:matcher_optional_kw_on_method) {} + expect(matcher_optional_kw_on_method.optional_kw(a: 1)).to eq(1) end it "clears user instance variables between invocations" do @@ -101,7 +93,7 @@ def optional_kw(a: nil) end end - it "warns when passing block to the block of define", :if => (RUBY_VERSION.to_f > 1.8) do + it "warns when passing block to the block of define" do expect(RSpec).to receive(:warning).with(/be_warning.*a_block.*block_arg/) RSpec::Matchers.define :be_warning do |&a_block| @@ -1318,7 +1310,7 @@ def a_method_in_the_example expect(example).to __access_running_example end - it 'can get a method object for methods in the running example', :if => (RUBY_VERSION.to_f > 1.8) do + it 'can get a method object for methods in the running example' do matcher = new_matcher(:get_method_object) {} method = matcher.method(:a_method_in_the_example) expect(method.call).to eq("method defined in the example") diff --git a/rspec-expectations/spec/rspec/matchers_spec.rb b/rspec-expectations/spec/rspec/matchers_spec.rb index a6e7e1b0f..880dfde25 100644 --- a/rspec-expectations/spec/rspec/matchers_spec.rb +++ b/rspec-expectations/spec/rspec/matchers_spec.rb @@ -11,8 +11,6 @@ it 'can be mixed into `main`' do in_sub_process do - allow_warning if RSpec::Support::Ruby.mri? && RUBY_VERSION[0, 3] == '1.9' - main.instance_eval do include RSpec::Matchers include RSpec::Matchers::FailMatchers @@ -28,13 +26,8 @@ end context "when included into a superclass after a subclass has already included it" do - if RSpec::Support::Ruby.mri? && RUBY_VERSION[0, 3] == '1.9' - desc_start = "print" - matcher_method = :output - else - desc_start = "does not print" - matcher_method = :avoid_outputting - end + desc_start = "does not print" + matcher_method = :avoid_outputting it "#{desc_start} a warning so the user is made aware of the MRI 1.9 bug that can cause infinite recursion" do superclass = stub_const("Superclass", Class.new) @@ -68,7 +61,7 @@ expect(respond_to?(:puts)).to eq false end - it "allows `method` to get dynamic matcher methods", :if => RUBY_VERSION.to_f >= 1.9 do + it "allows `method` to get dynamic matcher methods" do expect(method(:be_happy).call).to be_a(be_happy.class) end end @@ -77,7 +70,7 @@ module RSpec module Matchers RSpec.describe ".is_a_matcher?" do - it 'does not match BasicObject', :if => RUBY_VERSION.to_f > 1.8 do + it 'does not match BasicObject' do expect(RSpec::Matchers.is_a_matcher?(BasicObject.new)).to eq(false) end diff --git a/rspec-expectations/spec/spec_helper.rb b/rspec-expectations/spec/spec_helper.rb index 092d2d81b..6934bc9a1 100644 --- a/rspec-expectations/spec/spec_helper.rb +++ b/rspec-expectations/spec/spec_helper.rb @@ -2,7 +2,7 @@ require 'rspec/support/spec/in_sub_process' RSpec::Support::Spec.setup_simplecov do - minimum_coverage 92 + minimum_coverage 91 end Dir['./spec/support/**/*'].each do |f| @@ -25,19 +25,9 @@ def dedent(string) string.gsub(/^\s+\|/, '').chomp end - # We have to use Hash#inspect in examples that have multi-entry - # hashes because the #inspect output on 1.8.7 is non-deterministic - # due to the fact that hashes are not ordered. So we can't simply - # put a literal string for what we expect because it varies. - if RUBY_VERSION.to_f == 1.8 - def hash_inspect(hash) - "\\{(#{hash.map { |key, value| "#{key.inspect} => #{value.inspect}.*" }.join "|"}){#{hash.size}}\\}" - end - else - def hash_inspect(hash) - RSpec::Matchers::BuiltIn::BaseMatcher::HashFormatting. - improve_hash_formatting hash.inspect - end + def hash_inspect(hash) + RSpec::Matchers::BuiltIn::BaseMatcher::HashFormatting. + improve_hash_formatting hash.inspect end end