module RSpec::Matchers::DSL

Defines the custom matcher DSL.

Public Instance Methods

alias_matcher(new_name, old_name, options={}, &description_override) click to toggle source

Defines a matcher alias. The returned matcher’s ‘description` will be overriden to reflect the phrasing of the new name, which will be used in failure messages when passed as an argument to another matcher in a composed matcher expression.

@example

RSpec::Matchers.alias_matcher :a_list_that_sums_to, :sum_to
sum_to(3).description # => "sum to 3"
a_list_that_sums_to(3).description # => "a list that sums to 3"

@example

RSpec::Matchers.alias_matcher :a_list_sorted_by, :be_sorted_by do |description|
  description.sub("be sorted by", "a list sorted by")
end

be_sorted_by(:age).description # => "be sorted by age"
a_list_sorted_by(:age).description # => "a list sorted by age"

@param new_name [Symbol] the new name for the matcher @param old_name [Symbol] the original name for the matcher @param options [Hash] options for the aliased matcher @option options [Class] :klass the ruby class to use as the decorator. (Not normally used). @yield [String] optional block that, when given, is used to define the overriden

logic. The yielded arg is the original description or failure message. If no
block is provided, a default override is used based on the old and new names.

@see RSpec::Matchers

# File lib/rspec/matchers/dsl.rb, line 32
def alias_matcher(new_name, old_name, options={}, &description_override)
  description_override ||= lambda do |old_desc|
    old_desc.gsub(EnglishPhrasing.split_words(old_name), EnglishPhrasing.split_words(new_name))
  end
  klass = options.fetch(:klass) { AliasedMatcher }

  define_method(new_name) do |*args, &block|
    matcher = __send__(old_name, *args, &block)
    matcher.matcher_name = new_name if matcher.respond_to?(:matcher_name=)
    klass.new(matcher, description_override)
  end
end
define(name, &declarations) click to toggle source

Defines a custom matcher.

@param name [Symbol] the name for the matcher @yield [Object] block that is used to define the matcher.

The block is evaluated in the context of your custom matcher class.
When args are passed to your matcher, they will be yielded here,
usually representing the expected value(s).

@see RSpec::Matchers

# File lib/rspec/matchers/dsl.rb, line 72
def define(name, &declarations)
  warn_about_block_args(name, declarations)
  define_method name do |*expected, &block_arg|
    RSpec::Matchers::DSL::Matcher.new(name, declarations, self, *expected, &block_arg)
  end
end
Also aliased as: matcher
define_negated_matcher(negated_name, base_name, &description_override) click to toggle source

Defines a negated matcher. The returned matcher’s ‘description` and `failure_message` will be overriden to reflect the phrasing of the new name, and the match logic will be based on the original matcher but negated.

@example

RSpec::Matchers.define_negated_matcher :exclude, :include
include(1, 2).description # => "include 1 and 2"
exclude(1, 2).description # => "exclude 1 and 2"

@param negated_name [Symbol] the name for the negated matcher @param base_name [Symbol] the name of the original matcher that will be negated @yield [String] optional block that, when given, is used to define the overriden

logic. The yielded arg is the original description or failure message. If no
block is provided, a default override is used based on the old and new names.

@see RSpec::Matchers

# File lib/rspec/matchers/dsl.rb, line 60
def define_negated_matcher(negated_name, base_name, &description_override)
  alias_matcher(negated_name, base_name, :klass => AliasedNegatedMatcher, &description_override)
end
matcher(name, &declarations)
Alias for: define

Private Instance Methods

warn_about_block_args(name, declarations) click to toggle source
# File lib/rspec/matchers/dsl.rb, line 83
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