2018-09-27 22:11:45 +00:00
|
|
|
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
|
|
|
|
# ```
|
|
|
|
#
|
2021-07-17 23:42:25 +00:00
|
|
|
# An optional message can be used in case the expectation fails.
|
|
|
|
# It can be a string or proc returning a string.
|
|
|
|
# ```
|
|
|
|
# subject.should_not be_nil, "Shouldn't be nil"
|
|
|
|
# ```
|
|
|
|
#
|
2018-09-27 22:11:45 +00:00
|
|
|
# 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"
|
|
|
|
# ```
|
2022-12-20 05:27:58 +00:00
|
|
|
def should(matcher, message = nil, *, _file = __FILE__, _line = __LINE__)
|
2021-01-16 18:12:41 +00:00
|
|
|
actual = ::Spectator::Value.new(self)
|
2022-12-20 05:27:58 +00:00
|
|
|
location = ::Spectator::Location.new(_file, _line)
|
2021-01-16 18:12:41 +00:00
|
|
|
match_data = matcher.match(actual)
|
2022-12-20 05:27:58 +00:00
|
|
|
expectation = ::Spectator::Expectation.new(match_data, location, message)
|
2021-01-16 18:12:41 +00:00
|
|
|
::Spectator::Harness.current.report(expectation)
|
2018-09-27 22:11:45 +00:00
|
|
|
end
|
|
|
|
|
2022-12-20 05:40:55 +00:00
|
|
|
# Asserts that some criteria defined by the matcher is satisfied.
|
|
|
|
# Allows a custom message to be used.
|
|
|
|
# Returns the expected value cast as the expected type, if the matcher is satisfied.
|
|
|
|
def should(matcher : ::Spectator::Matchers::TypeMatcher(U), message = nil, *, _file = __FILE__, _line = __LINE__) forall U
|
|
|
|
actual = ::Spectator::Value.new(self)
|
|
|
|
location = ::Spectator::Location.new(_file, _line)
|
|
|
|
match_data = matcher.match(actual)
|
|
|
|
expectation = ::Spectator::Expectation.new(match_data, location, message)
|
|
|
|
if ::Spectator::Harness.current.report(expectation)
|
|
|
|
return self if self.is_a?(U)
|
|
|
|
|
|
|
|
raise "Spectator bug: expected value should have cast to #{U}"
|
|
|
|
else
|
|
|
|
raise TypeCastError.new("Expected value should be a #{U}, but was actually #{self.class}")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-09-27 22:11:45 +00:00
|
|
|
# Works the same as `#should` except the condition is inverted.
|
|
|
|
# When `#should` succeeds, this method will fail, and vice-versa.
|
2022-12-20 05:27:58 +00:00
|
|
|
def should_not(matcher, message = nil, *, _file = __FILE__, _line = __LINE__)
|
2021-01-16 18:12:41 +00:00
|
|
|
actual = ::Spectator::Value.new(self)
|
2022-12-20 05:27:58 +00:00
|
|
|
location = ::Spectator::Location.new(_file, _line)
|
2021-01-16 18:12:41 +00:00
|
|
|
match_data = matcher.negated_match(actual)
|
2022-12-20 05:27:58 +00:00
|
|
|
expectation = ::Spectator::Expectation.new(match_data, location, message)
|
2021-01-16 18:12:41 +00:00
|
|
|
::Spectator::Harness.current.report(expectation)
|
2018-09-27 22:11:45 +00:00
|
|
|
end
|
2019-11-15 01:26:24 +00:00
|
|
|
|
2022-12-20 05:40:55 +00:00
|
|
|
# Asserts that some criteria defined by the matcher is not satisfied.
|
|
|
|
# Allows a custom message to be used.
|
|
|
|
# Returns the expected value cast without the unexpected type, if the matcher is satisfied.
|
|
|
|
def should_not(matcher : ::Spectator::Matchers::TypeMatcher(U), message = nil, *, _file = __FILE__, _line = __LINE__) forall U
|
|
|
|
actual = ::Spectator::Value.new(self)
|
|
|
|
location = ::Spectator::Location.new(_file, _line)
|
|
|
|
match_data = matcher.negated_match(actual)
|
|
|
|
expectation = ::Spectator::Expectation.new(match_data, location, message)
|
|
|
|
if ::Spectator::Harness.current.report(expectation)
|
|
|
|
return self unless self.is_a?(U)
|
|
|
|
|
|
|
|
raise "Spectator bug: expected value should not be #{U}"
|
|
|
|
else
|
|
|
|
raise TypeCastError.new("Expected value is not expected to be a #{U}, but was actually #{self.class}")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# Asserts that some criteria defined by the matcher is not satisfied.
|
|
|
|
# Allows a custom message to be used.
|
|
|
|
# Returns the expected value cast as a non-nillable type, if the matcher is satisfied.
|
|
|
|
def should_not(matcher : ::Spectator::Matchers::NilMatcher, message = nil, *, _file = __FILE__, _line = __LINE__)
|
|
|
|
actual = ::Spectator::Value.new(self)
|
|
|
|
location = ::Spectator::Location.new(_file, _line)
|
|
|
|
match_data = matcher.negated_match(actual)
|
|
|
|
expectation = ::Spectator::Expectation.new(match_data, location, message)
|
|
|
|
if ::Spectator::Harness.current.report(expectation)
|
|
|
|
return self unless self.nil?
|
|
|
|
|
|
|
|
raise "Spectator bug: expected value should not be nil"
|
|
|
|
else
|
|
|
|
raise NilAssertionError.new("Expected value should not be nil.")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-11-28 22:45:17 +00:00
|
|
|
# Works the same as `#should` except that the condition check is postponed.
|
2019-11-15 01:26:24 +00:00
|
|
|
# The expectation is checked after the example finishes and all hooks have run.
|
2022-12-20 05:27:58 +00:00
|
|
|
def should_eventually(matcher, message = nil, *, _file = __FILE__, _line = __LINE__)
|
|
|
|
::Spectator::Harness.current.defer { should(matcher, message, _file: _file, _line: _line) }
|
2019-11-15 01:26:24 +00:00
|
|
|
end
|
|
|
|
|
2021-11-28 22:45:17 +00:00
|
|
|
# Works the same as `#should_not` except that the condition check is postponed.
|
2019-11-15 01:26:24 +00:00
|
|
|
# The expectation is checked after the example finishes and all hooks have run.
|
2022-12-20 05:27:58 +00:00
|
|
|
def should_never(matcher, message = nil, *, _file = __FILE__, _line = __LINE__)
|
|
|
|
::Spectator::Harness.current.defer { should_not(matcher, message, _file: _file, _line: _line) }
|
2019-11-15 01:26:24 +00:00
|
|
|
end
|
2018-09-27 22:11:45 +00:00
|
|
|
end
|
2019-03-24 02:20:15 +00:00
|
|
|
|
|
|
|
struct Proc(*T, R)
|
|
|
|
# Extension method to create an expectation for a block of code (proc).
|
|
|
|
# Depending on the matcher, the proc may be executed multiple times.
|
2022-12-20 05:27:58 +00:00
|
|
|
def should(matcher, message = nil, *, _file = __FILE__, _line = __LINE__)
|
2021-01-16 18:12:41 +00:00
|
|
|
actual = ::Spectator::Block.new(self)
|
2022-12-20 05:27:58 +00:00
|
|
|
location = ::Spectator::Location.new(_file, _line)
|
2021-01-16 18:12:41 +00:00
|
|
|
match_data = matcher.match(actual)
|
2022-12-20 05:27:58 +00:00
|
|
|
expectation = ::Spectator::Expectation.new(match_data, location, message)
|
2021-01-16 18:12:41 +00:00
|
|
|
::Spectator::Harness.current.report(expectation)
|
2019-03-24 02:20:15 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
# Works the same as `#should` except the condition is inverted.
|
|
|
|
# When `#should` succeeds, this method will fail, and vice-versa.
|
2022-12-20 05:27:58 +00:00
|
|
|
def should_not(matcher, message = nil, *, _file = __FILE__, _line = __LINE__)
|
2021-01-16 18:12:41 +00:00
|
|
|
actual = ::Spectator::Block.new(self)
|
2022-12-20 05:27:58 +00:00
|
|
|
location = ::Spectator::Location.new(_file, _line)
|
2021-01-16 18:12:41 +00:00
|
|
|
match_data = matcher.negated_match(actual)
|
2022-12-20 05:27:58 +00:00
|
|
|
expectation = ::Spectator::Expectation.new(match_data, location, message)
|
2021-01-16 18:12:41 +00:00
|
|
|
::Spectator::Harness.current.report(expectation)
|
2019-03-24 02:20:15 +00:00
|
|
|
end
|
|
|
|
end
|
2021-01-10 18:09:28 +00:00
|
|
|
|
2021-01-31 03:27:36 +00:00
|
|
|
module Spectator::DSL::Expectations
|
2021-07-17 23:42:25 +00:00
|
|
|
macro should(*args)
|
|
|
|
expect(subject).to({{args.splat}})
|
2021-01-10 18:09:28 +00:00
|
|
|
end
|
|
|
|
|
2021-07-17 23:42:25 +00:00
|
|
|
macro should_not(*args)
|
|
|
|
expect(subject).to_not({{args.splat}})
|
2021-01-10 18:09:28 +00:00
|
|
|
end
|
|
|
|
|
2021-07-17 23:42:25 +00:00
|
|
|
macro should_eventually(*args)
|
|
|
|
expect(subject).to_eventually({{args.splat}})
|
2021-01-10 18:09:28 +00:00
|
|
|
end
|
|
|
|
|
2021-07-17 23:42:25 +00:00
|
|
|
macro should_never(*args)
|
|
|
|
expect(subject).to_never({{args.splat}})
|
2021-01-10 18:09:28 +00:00
|
|
|
end
|
|
|
|
end
|