Handle case with typeless block

Fixes syntax:
`stub method(&block)`

To stub a block with args, use:
`stub method(&block : Type -> Type)`

Addresses https://github.com/icy-arctic-fox/spectator/issues/42
This commit is contained in:
Michael Miller 2022-02-21 18:17:44 -07:00
parent cbe05cd637
commit eb8bd88927
No known key found for this signature in database
GPG key ID: AC78B32D30CE34A2
2 changed files with 87 additions and 16 deletions

View file

@ -0,0 +1,43 @@
require "../spec_helper"
abstract class SdkInterface
abstract def register_hook(name, &block)
end
class Example
def initialize(@sdk : Sdk)
end
def configure
@sdk.register_hook("name") do
nil
end
end
end
class Sdk < SdkInterface
def initialize
end
def register_hook(name, &block)
nil
end
end
Spectator.describe Example do
mock Sdk do
stub register_hook(name, &block)
end
describe "#configure" do
it "registers a block on configure" do
sdk = Sdk.new
example_class = Example.new(sdk)
allow(sdk).to receive(register_hook())
example_class.configure
expect(sdk).to have_received(register_hook()).with("name")
end
end
end

View file

@ -7,11 +7,13 @@ module Spectator::Mocks
params = nil
args = nil
body = nil
block_arg = nil
if definition.is_a?(Call) # stub foo { :bar }
receiver = definition.receiver.id
named = false
name = definition.name.id
params = definition.args
block_arg = definition.block_arg
if params.last.is_a?(Call)
body = params.last.block
params[-1] = params.last.name
@ -100,28 +102,54 @@ module Spectator::Mocks
end
end
def {{receiver}}{{name}}({{params.splat}}){% if return_type.is_a?(ArrayLiteral) %} : {{return_type.type}}{% elsif return_type != :undefined %} : {{return_type.id}}{% elsif definition.is_a?(TypeDeclaration) %} : {{definition.type}}{% end %}
if (%harness = ::Spectator::Harness.current?)
%args = ::Spectator::Mocks::GenericArguments.create({{args.splat}})
%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) { {{fallback}} { |*%ya| yield *%ya } }
end
{% if block_arg.is_a?(Call) %}
def {{receiver}}{{name}}({{params.splat}}){% if return_type.is_a?(ArrayLiteral) %} : {{return_type.type}}{% elsif return_type != :undefined %} : {{return_type.id}}{% elsif definition.is_a?(TypeDeclaration) %} : {{definition.type}}{% end %}
if (%harness = ::Spectator::Harness.current?)
%args = ::Spectator::Mocks::GenericArguments.create({{args.splat}})
%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) { {{fallback}} { yield } }
end
{% if body && !body.is_a?(Nop) || return_type.is_a?(ArrayLiteral) %}
%method({{args.splat}}) { |*%ya| yield *%ya }
{% else %}
{% if body && !body.is_a?(Nop) || return_type.is_a?(ArrayLiteral) %}
%method({{args.splat}}) { yield }
{% else %}
{{fallback}} do
yield
end
{% end %}
else
{{fallback}} do
yield
end
end
end
{% else %}
def {{receiver}}{{name}}({{params.splat}}){% if return_type.is_a?(ArrayLiteral) %} : {{return_type.type}}{% elsif return_type != :undefined %} : {{return_type.id}}{% elsif definition.is_a?(TypeDeclaration) %} : {{definition.type}}{% end %}
if (%harness = ::Spectator::Harness.current?)
%args = ::Spectator::Mocks::GenericArguments.create({{args.splat}})
%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) { {{fallback}} { |*%ya| yield *%ya } }
end
{% if body && !body.is_a?(Nop) || return_type.is_a?(ArrayLiteral) %}
%method({{args.splat}}) { |*%ya| yield *%ya }
{% else %}
{{fallback}} do |*%yield_args|
yield *%yield_args
end
{% end %}
else
{{fallback}} do |*%yield_args|
yield *%yield_args
end
{% end %}
else
{{fallback}} do |*%yield_args|
yield *%yield_args
end
end
end
{% end %}
end
end
end