From 260e1884abf5cd459ecb5aaa34fbe127d72b0867 Mon Sep 17 00:00:00 2001 From: Michael Miller Date: Sat, 19 Jan 2019 14:40:14 -0700 Subject: [PATCH] Implement `match` (regex) matcher --- src/spectator/dsl/matcher_dsl.cr | 14 ++++++++++++++ src/spectator/matchers/regex_matcher.cr | 25 +++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 src/spectator/matchers/regex_matcher.cr diff --git a/src/spectator/dsl/matcher_dsl.cr b/src/spectator/dsl/matcher_dsl.cr index 2f2fa83..411e611 100644 --- a/src/spectator/dsl/matcher_dsl.cr +++ b/src/spectator/dsl/matcher_dsl.cr @@ -43,5 +43,19 @@ module Spectator::DSL macro be_a(expected) ::Spectator::Matchers::TypeMatcher({{expected}}).new end + + # Indicates that some value should match another. + # The `=~` operator is used for this check. + # Typically a regular expression is used, + # but any type that has the `=~` operator will work. + # + # Examples: + # ``` + # expect("foo").to match(/foo|bar/) + # expect("BAR").to match(/foo|bar/i) + # ``` + macro match(expected) + ::Spectator::Matchers::RegexMatcher.new({{expected.stringify}}, {{expected}}) + end end end diff --git a/src/spectator/matchers/regex_matcher.cr b/src/spectator/matchers/regex_matcher.cr new file mode 100644 index 0000000..eca5192 --- /dev/null +++ b/src/spectator/matchers/regex_matcher.cr @@ -0,0 +1,25 @@ +require "./value_matcher" + +module Spectator::Matchers + # Matcher that tests whether a value matches a regular expression. + # The value is compared with the `=~` operator. + struct RegexMatcher(ExpectedType) < ValueMatcher(ExpectedType) + # Determines whether the matcher is satisfied with the value given to it. + # True is returned if the match was successful, false otherwise. + def match?(partial : Expectations::ValueExpectationPartial(ActualType)) : Bool forall ActualType + !!(partial.actual =~ expected) + end + + # Describes the condition that satisfies the matcher. + # This is informational and displayed to the end-user. + def message(partial : Expectations::ValueExpectationPartial(ActualType)) : String forall ActualType + "Expected #{partial.label} to match #{label} (using =~)" + end + + # Describes the condition that won't satsify the matcher. + # This is informational and displayed to the end-user. + def negated_message(partial : Expectations::ValueExpectationPartial(ActualType)) : String forall ActualType + "Expected #{partial.label} to not match #{label} (using =~)" + end + end +end