Skip to content

Commit

Permalink
Allow modules to be included in custom matchers.
Browse files Browse the repository at this point in the history
Closes rspec-core #344.
  • Loading branch information
myronmarston committed Mar 10, 2011
1 parent 268f8c0 commit a832e96
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 0 deletions.
29 changes: 29 additions & 0 deletions features/custom_matchers/define_matcher.feature
Original file line number Diff line number Diff line change
Expand Up @@ -309,3 +309,32 @@ Feature: define matcher
| 4 examples, 2 failures |
| expected 9 to be a multiple of 2 |
| expected 9 not to be a multiple of 3 |

Scenario: include a module with helper methods in the matcher
Given a file named "include_module_spec.rb" with:
"""
module MatcherHelpers
def is_multiple?(actual, expected)
actual % expected == 0
end
end
RSpec::Matchers.define :be_a_multiple_of do |expected|
include MatcherHelpers
match { |actual| is_multiple?(actual, expected) }
end
describe 9 do
it { should be_a_multiple_of(3) }
it { should_not be_a_multiple_of(4) }
# deliberate failures
it { should be_a_multiple_of(2) }
it { should_not be_a_multiple_of(3) }
end
"""
When I run "rspec include_module_spec.rb"
Then the output should contain all of these:
| 4 examples, 2 failures |
| expected 9 to be a multiple of 2 |
| expected 9 not to be a multiple of 3 |
4 changes: 4 additions & 0 deletions lib/rspec/matchers/matcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ def does_not_match?(actual)
!matches?(actual)
end

def include(*args)
singleton_class.__send__(:include, *args)
end

def define_method(name, &block) # :nodoc:
singleton_class.__send__(:define_method, name, &block)
end
Expand Down
46 changes: 46 additions & 0 deletions spec/rspec/matchers/matcher_spec.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,56 @@
require 'spec_helper'

class UnexpectedError < StandardError; end
module MatcherHelperModule
def self.included(base)
base.module_eval do
def included_method; end
end
end

def self.extended(base)
base.instance_eval do
def extended_method; end
end
end

def greeting
"Hello, World"
end
end

module RSpec
module Matchers
describe Matcher do
context "with an included module" do
let(:matcher) do
RSpec::Matchers::Matcher.new(:be_a_greeting) do
include MatcherHelperModule
match { |actual| actual == greeting }
end
end

it "has access to the module's methods" do
matcher.matches?("Hello, World")
end

it "runs the module's included hook" do
matcher.should respond_to(:included_method)
end

it "does not run the module's extended hook" do
matcher.should_not respond_to(:extended_method)
end

it 'allows multiple modules to be included at once' do
m = RSpec::Matchers::Matcher.new(:multiple_modules) do
include Enumerable, Comparable
end
m.should be_a(Enumerable)
m.should be_a(Comparable)
end
end

context "without overrides" do
before(:each) do
@matcher = RSpec::Matchers::Matcher.new(:be_a_multiple_of, 3) do |multiple|
Expand Down

0 comments on commit a832e96

Please sign in to comment.