diff --git a/README.md b/README.md index c18dbf6..47efd96 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ In no particular order, features that have been implemented and are planned: - [X] Before and after hooks - `before_each`, `before_all`, `after_each`, `after_all`, `around_each` - [ ] Other hooks - `on_success`, `on_failure`, `on_error` - [ ] One-liner syntax - - [ ] Should syntax + - [X] Should syntax - `should`, `should_not` - [X] Helper methods and modules - [ ] Aliasing - custom example group types with preset attributes - [X] Pending tests - `pending` diff --git a/src/spectator/should.cr b/src/spectator/should.cr new file mode 100644 index 0000000..5d0282e --- /dev/null +++ b/src/spectator/should.cr @@ -0,0 +1,37 @@ +class Object + # Extension method to create an expectation for an object. + # This is part of the spec DSL and mimics Crystal Spec's default should-syntax. + # A matcher should immediately follow this method, or be the only argument to it. + # Example usage: + # ``` + # it "equals the expected value" do + # subject.should eq(42) + # end + # ``` + # + # NOTE: By default, the should-syntax is disabled. + # The expect-syntax is preferred, + # since it doesn't [monkey-patch](https://en.wikipedia.org/wiki/Monkey_patch) all objects. + # To enable should-syntax, add the following to your `spec_helper.cr` file: + # ``` + # require "spectator/should" + # ``` + def should(matcher : ::Spectator::Matchers::Matcher) + # First argument of the `Expectation` initializer is the expression label. + # However, since this isn't a macro and we can't "look behind" this method call + # to see what it was invoked on, the argument is an empty string. + expectation = ::Spectator::Expectation.new("", self) + unless matcher.match?(expectation) + raise ::Spectator::ExpectationFailed.new(matcher.message(expectation)) + end + end + + # Works the same as `#should` except the condition is inverted. + # When `#should` succeeds, this method will fail, and vice-versa. + def should_not(matcher : ::Spectator::Matchers::Matcher) + expectation = ::Spectator::Expectation.new("", self) + if matcher.match?(expectation) + raise ::Spectator::ExpectationFailed.new(matcher.message(expectation)) + end + end +end