diff --git a/shard.yml b/shard.yml index 49a9fe3..3b3e779 100644 --- a/shard.yml +++ b/shard.yml @@ -1,5 +1,5 @@ name: spectator -version: 0.9.0 +version: 0.9.1 description: | A feature-rich spec testing framework for Crystal with similarities to RSpec. diff --git a/src/spectator.cr b/src/spectator.cr index a752c60..1d43e65 100644 --- a/src/spectator.cr +++ b/src/spectator.cr @@ -6,7 +6,7 @@ module Spectator extend self # Current version of the Spectator library. - VERSION = "0.9.0" + VERSION = "0.9.1" # Top-level describe method. # All specs in a file must be wrapped in this call. diff --git a/src/spectator/mocks/anonymous_double.cr b/src/spectator/mocks/anonymous_double.cr index 439901a..7a2c0c4 100644 --- a/src/spectator/mocks/anonymous_double.cr +++ b/src/spectator/mocks/anonymous_double.cr @@ -9,7 +9,7 @@ module Spectator::Mocks macro method_missing(call) args = ::Spectator::Mocks::GenericArguments.create({{call.args.splat}}) - call = ::Spectator::Mocks::GenericMethodCall.new({{call.name.symbolize}}, args) + call = ::Spectator::Mocks::MethodCall.new({{call.name.symbolize}}, args) ::Spectator::Harness.current.mocks.record_call(self, call) if (stub = ::Spectator::Harness.current.mocks.find_stub(self, call)) stub.call!(args) do diff --git a/src/spectator/mocks/anonymous_null_double.cr b/src/spectator/mocks/anonymous_null_double.cr index 8fa338c..441eafa 100644 --- a/src/spectator/mocks/anonymous_null_double.cr +++ b/src/spectator/mocks/anonymous_null_double.cr @@ -5,7 +5,7 @@ module Spectator::Mocks macro method_missing(call) args = ::Spectator::Mocks::GenericArguments.create({{call.args.splat}}) - call = ::Spectator::Mocks::GenericMethodCall.new({{call.name.symbolize}}, args) + call = ::Spectator::Mocks::MethodCall.new({{call.name.symbolize}}, args) ::Spectator::Harness.current.mocks.record_call(self, call) if (stub = ::Spectator::Harness.current.mocks.find_stub(self, call)) stub.call!(args) { @values.fetch({{call.name.symbolize}}) { self } } diff --git a/src/spectator/mocks/double.cr b/src/spectator/mocks/double.cr index de218ba..45071ac 100644 --- a/src/spectator/mocks/double.cr +++ b/src/spectator/mocks/double.cr @@ -1,5 +1,5 @@ -require "./generic_method_call" require "./generic_method_stub" +require "./method_call" require "./unexpected_message_error" module Spectator::Mocks @@ -36,7 +36,7 @@ module Spectator::Mocks def {{name}}({{params.splat}}){% if definition.is_a?(TypeDeclaration) %} : {{definition.type}}{% end %} %args = ::Spectator::Mocks::GenericArguments.create({{args.splat}}) - %call = ::Spectator::Mocks::GenericMethodCall.new({{name.symbolize}}, %args) + %call = ::Spectator::Mocks::MethodCall.new({{name.symbolize}}, %args) ::Spectator::Harness.current.mocks.record_call(self, %call) if (%stub = ::Spectator::Harness.current.mocks.find_stub(self, %call)) %stub.call!(%args) { %method({{args.splat}}) } @@ -47,7 +47,7 @@ module Spectator::Mocks def {{name}}({{params.splat}}){% if definition.is_a?(TypeDeclaration) %} : {{definition.type}}{% end %} %args = ::Spectator::Mocks::GenericArguments.create({{args.splat}}) - %call = ::Spectator::Mocks::GenericMethodCall.new({{name.symbolize}}, %args) + %call = ::Spectator::Mocks::MethodCall.new({{name.symbolize}}, %args) ::Spectator::Harness.current.mocks.record_call(self, %call) if (%stub = ::Spectator::Harness.current.mocks.find_stub(self, %call)) %stub.call!(%args) { %method({{args.splat}}) { |*%ya| yield *%ya } } @@ -62,8 +62,8 @@ module Spectator::Mocks {% if body && !body.is_a?(Nop) %} {{body.body}} {% else %} - %args = ::Spectator::Mocks::GenericArguments.create({{params.splat}}) - %call = ::Spectator::Mocks::GenericMethodCall.new({{name.symbolize}}, %args) + %args = ::Spectator::Mocks::GenericArguments.create({{args.splat}}) + %call = ::Spectator::Mocks::MethodCall.new({{name.symbolize}}, %args) unless ::Spectator::Harness.current.mocks.expected?(self, %call) raise ::Spectator::Mocks::UnexpectedMessageError.new("#{self} received unexpected message {{name}}") end @@ -80,7 +80,7 @@ module Spectator::Mocks macro method_missing(call) args = ::Spectator::Mocks::GenericArguments.create({{call.args.splat}}) - call = ::Spectator::Mocks::GenericMethodCall.new({{call.name.symbolize}}, args) + call = ::Spectator::Mocks::MethodCall.new({{call.name.symbolize}}, args) ::Spectator::Harness.current.mocks.record_call(self, call) return self if @null diff --git a/src/spectator/mocks/expect_any_instance.cr b/src/spectator/mocks/expect_any_instance.cr index c51c0e8..9d9769e 100644 --- a/src/spectator/mocks/expect_any_instance.cr +++ b/src/spectator/mocks/expect_any_instance.cr @@ -7,7 +7,7 @@ module Spectator::Mocks def to(stub : MethodStub) : Nil actual = TestValue.new(T) - Harness.current.mocks.expect(T, stub.name) + Harness.current.mocks.expect(T, stub) value = TestValue.new(stub.name, stub.to_s) matcher = Matchers::ReceiveTypeMatcher.new(value, stub.arguments?) partial = Expectations::ExpectationPartial.new(actual, @source) diff --git a/src/spectator/mocks/generic_method_call.cr b/src/spectator/mocks/generic_method_call.cr deleted file mode 100644 index 64f8999..0000000 --- a/src/spectator/mocks/generic_method_call.cr +++ /dev/null @@ -1,19 +0,0 @@ -require "./generic_arguments" -require "./method_call" - -module Spectator::Mocks - class GenericMethodCall(T, NT) < MethodCall - getter args - - def initialize(name : Symbol, @args : GenericArguments(T, NT)) - super(name) - end - - def to_s(io) - super - io << '(' - io << @args - io << ')' - end - end -end diff --git a/src/spectator/mocks/generic_method_stub.cr b/src/spectator/mocks/generic_method_stub.cr index c0ee38f..dc8eba6 100644 --- a/src/spectator/mocks/generic_method_stub.cr +++ b/src/spectator/mocks/generic_method_stub.cr @@ -11,7 +11,7 @@ module Spectator::Mocks super(name, source) end - def callable?(call : GenericMethodCall(T, NT)) : Bool forall T, NT + def callable?(call : MethodCall) : Bool super && (!@args || @args === call.args) end diff --git a/src/spectator/mocks/method_call.cr b/src/spectator/mocks/method_call.cr index 00c6d0c..f89138f 100644 --- a/src/spectator/mocks/method_call.cr +++ b/src/spectator/mocks/method_call.cr @@ -1,8 +1,9 @@ module Spectator::Mocks - abstract class MethodCall + class MethodCall getter name : Symbol + getter args : Arguments - def initialize(@name : Symbol) + def initialize(@name : Symbol, @args : Arguments) end def to_s(io) diff --git a/src/spectator/mocks/method_stub.cr b/src/spectator/mocks/method_stub.cr index 245bff3..ad1d8d0 100644 --- a/src/spectator/mocks/method_stub.cr +++ b/src/spectator/mocks/method_stub.cr @@ -1,5 +1,5 @@ require "../source" -require "./generic_method_call" +require "./method_call" module Spectator::Mocks abstract class MethodStub @@ -10,7 +10,7 @@ module Spectator::Mocks def initialize(@name, @source) end - def callable?(call : GenericMethodCall(T, NT)) : Bool forall T, NT + def callable?(call : MethodCall) : Bool @name == call.name end diff --git a/src/spectator/mocks/reflection.cr b/src/spectator/mocks/reflection.cr index 43f20f2..3dbd264 100644 --- a/src/spectator/mocks/reflection.cr +++ b/src/spectator/mocks/reflection.cr @@ -7,10 +7,19 @@ module Spectator::Mocks %source = ::Spectator::Source.new({{meth.filename}}, {{meth.line_number}}) %args = ::Spectator::Mocks::GenericArguments.create( {% for arg, i in meth.args %} + {% matcher = if arg.restriction + if arg.restriction == :self.id + @type.id + else + arg.restriction + end + else + "::Spectator::Anything.new".id + end %} {% if meth.splat_index && i == meth.splat_index %} - *{{arg.restriction || "::Spectator::Anything.new".id}}{% if i < meth.args.size %},{% end %} + *{{matcher}}{% if i < meth.args.size %},{% end %} {% else %} - {{arg.restriction || "::Spectator::Anything.new".id}}{% if i < meth.args.size %},{% end %} + {{matcher}}{% if i < meth.args.size %},{% end %} {% end %} {% end %} ) diff --git a/src/spectator/mocks/registry.cr b/src/spectator/mocks/registry.cr index a946ae4..37af7ca 100644 --- a/src/spectator/mocks/registry.cr +++ b/src/spectator/mocks/registry.cr @@ -47,7 +47,7 @@ module Spectator::Mocks fetch_type(object.class).stubs.any? { |stub| stub.name == method_name } end - def find_stub(object, call : GenericMethodCall(T, NT)) forall T, NT + def find_stub(object, call : MethodCall) fetch_instance(object).stubs.find(&.callable?(call)) || fetch_type(object.class).stubs.find(&.callable?(call)) end @@ -65,7 +65,7 @@ module Spectator::Mocks fetch_type(type).calls.select { |call| call.name == method_name } end - def expected?(object, call : GenericMethodCall(T, NT)) : Bool forall T, NT + def expected?(object, call : MethodCall) : Bool fetch_instance(object).expected.any?(&.callable?(call)) || fetch_type(object.class).expected.any?(&.callable?(call)) end diff --git a/src/spectator/mocks/stubs.cr b/src/spectator/mocks/stubs.cr index 089e637..374cc78 100644 --- a/src/spectator/mocks/stubs.cr +++ b/src/spectator/mocks/stubs.cr @@ -53,7 +53,7 @@ module Spectator::Mocks def {{receiver}}{{name}}({{params.splat}}){% if definition.is_a?(TypeDeclaration) %} : {{definition.type}}{% end %} if (%harness = ::Spectator::Harness.current?) %args = ::Spectator::Mocks::GenericArguments.create({{args.splat}}) - %call = ::Spectator::Mocks::GenericMethodCall.new({{name.symbolize}}, %args) + %call = ::Spectator::Mocks::MethodCall.new({{name.symbolize}}, %args) %harness.mocks.record_call(self, %call) if (%stub = %harness.mocks.find_stub(self, %call)) return %stub.call!(%args) { {{original}}({{args.splat}}) } @@ -65,7 +65,7 @@ module Spectator::Mocks def {{receiver}}{{name}}({{params.splat}}){% if definition.is_a?(TypeDeclaration) %} : {{definition.type}}{% end %} if (%harness = ::Spectator::Harness.current?) %args = ::Spectator::Mocks::GenericArguments.create({{args.splat}}) - %call = ::Spectator::Mocks::GenericMethodCall.new({{name.symbolize}}, %args) + %call = ::Spectator::Mocks::MethodCall.new({{name.symbolize}}, %args) %harness.mocks.record_call(self, %call) if (%stub = %harness.mocks.find_stub(self, %call)) return %stub.call!(%args) { {{original}}({{args.splat}}) { |*%ya| yield *%ya } } diff --git a/src/spectator/mocks/type_registry.cr b/src/spectator/mocks/type_registry.cr index c3cb0b6..4f960f3 100644 --- a/src/spectator/mocks/type_registry.cr +++ b/src/spectator/mocks/type_registry.cr @@ -16,7 +16,7 @@ module Spectator::Mocks list << NilMethodStub.new(method_name, source, args) end - def exists?(type_name : String, call : GenericMethodCall(T, NT)) : Bool forall T, NT + def exists?(type_name : String, call : MethodCall) : Bool key = {type_name, call.name} list = @@entries.fetch(key) { return false } list.any?(&.callable?(call)) diff --git a/src/spectator/mocks/verifying_double.cr b/src/spectator/mocks/verifying_double.cr index 3f451cb..6c8e157 100644 --- a/src/spectator/mocks/verifying_double.cr +++ b/src/spectator/mocks/verifying_double.cr @@ -32,7 +32,7 @@ module Spectator::Mocks def {{name}}({{params.splat}}){% if definition.is_a?(TypeDeclaration) %} : {{definition.type}}{% end %} %args = ::Spectator::Mocks::GenericArguments.create({{args.splat}}) - %call = ::Spectator::Mocks::GenericMethodCall.new({{name.symbolize}}, %args) + %call = ::Spectator::Mocks::MethodCall.new({{name.symbolize}}, %args) ::Spectator::Harness.current.mocks.record_call(self, %call) unless ::Spectator::Mocks::TypeRegistry.exists?(T.to_s, %call) @@ -48,7 +48,7 @@ module Spectator::Mocks def {{name}}({{params.splat}}){% if definition.is_a?(TypeDeclaration) %} : {{definition.type}}{% end %} %args = ::Spectator::Mocks::GenericArguments.create({{args.splat}}) - %call = ::Spectator::Mocks::GenericMethodCall.new({{name.symbolize}}, %args) + %call = ::Spectator::Mocks::MethodCall.new({{name.symbolize}}, %args) ::Spectator::Harness.current.mocks.record_call(self, %call) unless ::Spectator::Mocks::TypeRegistry.exists?(T.to_s, %call) @@ -68,8 +68,8 @@ module Spectator::Mocks {% if body && !body.is_a?(Nop) %} {{body.body}} {% else %} - %args = ::Spectator::Mocks::GenericArguments.create({{params.splat}}) - %call = ::Spectator::Mocks::GenericMethodCall.new({{name.symbolize}}, %args) + %args = ::Spectator::Mocks::GenericArguments.create({{args.splat}}) + %call = ::Spectator::Mocks::MethodCall.new({{name.symbolize}}, %args) unless ::Spectator::Harness.current.mocks.expected?(self, %call) raise ::Spectator::Mocks::UnexpectedMessageError.new("#{self} received unexpected message {{name}}") end @@ -86,7 +86,7 @@ module Spectator::Mocks macro method_missing(call) args = ::Spectator::Mocks::GenericArguments.create({{call.args.splat}}) - call = ::Spectator::Mocks::GenericMethodCall.new({{call.name.symbolize}}, args) + call = ::Spectator::Mocks::MethodCall.new({{call.name.symbolize}}, args) ::Spectator::Harness.current.mocks.record_call(self, call) unless ::Spectator::Mocks::TypeRegistry.exists?(T.to_s, call)