Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom RSpec Matcher That Takes A Block

Tags:

ruby

rspec

How can a create the following RSpec matcher?

foo.bars.should incude_at_least_one {|bar| bar.id == 42 }

Let me know if I'm reinventing the wheel, but I'm also curious to know how to create a custom matcher that takes a block. Some of the built in matchers do it, so it's possible. I tried this:

RSpec::Matchers.define :incude_at_least_one do |expected|
  match do |actual|
    actual.each do |item|
      return true if yield(item)
    end
    false
  end
end

I aslo tried passing &block at both leves. I'm missing something simple.

like image 448
Tim Scott Avatar asked Nov 12 '22 06:11

Tim Scott


1 Answers

I started with the code from Neil Slater, and got it to work:

class IncludeAtLeastOne
  def initialize(&block)
    @block = block
  end

  def matches?(actual)
    @actual = actual
    @actual.any? {|item| @block.call(item) }
  end

  def failure_message_for_should
    "expected #{@actual.inspect} to include at least one matching item, but it did not"
  end

  def failure_message_for_should_not
    "expected #{@actual.inspect} not to include at least one, but it did"
  end
end

def include_at_least_one(&block)
  IncludeAtLeastOne.new &block
end
like image 109
Tim Scott Avatar answered Nov 15 '22 04:11

Tim Scott