Permalink
Browse files

Merge pull request #194 from stevenharman/issue_188_custom_matchers_w…

…ith_match

Allow custom matchers to use built-in #match
  • Loading branch information...
2 parents cf52fe6 + c956506 commit 7fe9ec4428285c8c6fc7ba6a8b3ff78374db14e3 @myronmarston myronmarston committed Dec 7, 2012
Showing with 46 additions and 8 deletions.
  1. +28 −0 features/custom_matchers/define_matcher.feature
  2. +18 −8 lib/rspec/matchers.rb
@@ -338,3 +338,31 @@ 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: matching against a regular expression
+ Given a file named "regular_expression_matcher_spec.rb" with:
+ """ruby
+ # Due to Ruby's method dispatch mechanism, use the `#match_regex` alias
+ # rather than the `#match` matcher when defining custom matchers via the
+ # DSL.
+
+ RSpec::Matchers.define :be_valid_us_zipcode do
+ match do |actual|
+ expect(actual).to match_regex(/\A\d{5}(-\d{4})?\z/)
+ end
+ end
+
+ describe "30316" do
+ it { should be_valid_us_zipcode }
+ end
+
+ describe "30316-0001" do
+ it { should be_valid_us_zipcode }
+ end
+
+ describe "1000-61303" do
+ it { should_not be_valid_us_zipcode }
+ end
+ """
+ When I run `rspec regular_expression_matcher_spec.rb`
+ Then the stdout should contain "3 examples, 0 failures"
View
@@ -214,7 +214,7 @@ def be_nil
#
# Given true, false, or nil, will pass if actual value is true, false or
# nil (respectively). Given no args means the caller should satisfy an if
- # condition (to be or not to be).
+ # condition (to be or not to be).
#
# Predicates are any Ruby method that ends in a "?" and returns true or
# false. Given be_ followed by arbitrary_predicate (without the "?"),
@@ -246,7 +246,7 @@ def be_a(klass)
def be_an_instance_of(expected)
BuiltIn::BeAnInstanceOf.new(expected)
end
-
+
alias_method :be_instance_of, :be_an_instance_of
# Passes if actual.kind_of?(expected)
@@ -288,20 +288,20 @@ def be_within(delta)
# @example
#
# lambda {
- # team.add_player(player)
+ # team.add_player(player)
# }.should change(roster, :count)
#
# lambda {
- # team.add_player(player)
+ # team.add_player(player)
# }.should change(roster, :count).by(1)
#
# lambda {
- # team.add_player(player)
+ # team.add_player(player)
# }.should change(roster, :count).by_at_least(1)
#
# lambda {
# team.add_player(player)
- # }.should change(roster, :count).by_at_most(1)
+ # }.should change(roster, :count).by_at_most(1)
#
# string = "string"
# lambda {
@@ -311,7 +311,7 @@ def be_within(delta)
# lambda {
# person.happy_birthday
# }.should change(person, :birthday).from(32).to(33)
- #
+ #
# lambda {
# employee.develop_great_new_social_networking_app
# }.should change(employee, :title).from("Mail Clerk").to("CEO")
@@ -491,10 +491,20 @@ def include(*expected)
#
# email.should match(/^([^\s]+)((?:[-a-z0-9]+\.)+[a-z]{2,})$/i)
# email.should match("@example.com")
+ # zipcode.should match_regex(/\A\d{5}(-\d{4})?\z/)
+ # zipcode.should match_regex("90210")
+ #
+ # @note Due to Ruby's method dispatch mechanism, using the `#match` matcher
+ # within a custom matcher defined via the matcher DSL
+ # (`RSpec::Matcher.define`) will result Ruby calling the wrong `#match`
+ # method and raising an `ArgumentError`. Instead, use the aliased
+ # `#match_regex` method.
def match(expected)
BuiltIn::Match.new(expected)
end
+ alias_method :match_regex, :match
+
# With no args, matches if any error is raised.
# With a named error, matches only if that specific error is raised.
# With a named error and messsage specified as a String, matches only if both match.
@@ -523,7 +533,7 @@ def raise_error(error=Exception, message=nil, &block)
# provided. Names can be Strings or Symbols.
#
# @example
- #
+ #
def respond_to(*names)
BuiltIn::RespondTo.new(*names)
end

0 comments on commit 7fe9ec4

Please sign in to comment.