2022-12-14 01:22:22 +00:00
|
|
|
require "../spec_helper"
|
|
|
|
|
|
|
|
Spectator.describe "GitHub Issue #48" do
|
|
|
|
class Test
|
|
|
|
def return_this(thing : T) : T forall T
|
|
|
|
thing
|
|
|
|
end
|
|
|
|
|
|
|
|
def map(thing : T, & : T -> U) : U forall T, U
|
|
|
|
yield thing
|
|
|
|
end
|
|
|
|
|
|
|
|
def make_nilable(thing : T) : T? forall T
|
|
|
|
thing.as(T?)
|
|
|
|
end
|
2022-12-14 05:48:21 +00:00
|
|
|
|
|
|
|
def itself : self
|
|
|
|
self
|
|
|
|
end
|
|
|
|
|
|
|
|
def itself? : self?
|
|
|
|
self.as(self?)
|
|
|
|
end
|
|
|
|
|
|
|
|
def generic(thing : T) : Array(T) forall T
|
|
|
|
Array.new(100) { thing }
|
|
|
|
end
|
|
|
|
|
|
|
|
def union : Int32 | String
|
|
|
|
42.as(Int32 | String)
|
|
|
|
end
|
2022-12-17 23:41:22 +00:00
|
|
|
|
|
|
|
def capture(&block : -> T) forall T
|
|
|
|
block
|
|
|
|
end
|
|
|
|
|
|
|
|
def capture(thing : T, &block : T -> T) forall T
|
|
|
|
block.call(thing)
|
|
|
|
block
|
|
|
|
end
|
2022-12-18 18:35:43 +00:00
|
|
|
|
|
|
|
def range(r : Range)
|
|
|
|
r
|
|
|
|
end
|
2022-12-14 01:22:22 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
mock Test, make_nilable: nil
|
|
|
|
|
|
|
|
let(fake) { mock(Test) }
|
|
|
|
|
|
|
|
it "handles free variables" do
|
|
|
|
allow(fake).to receive(:return_this).and_return("different")
|
|
|
|
expect(fake.return_this("test")).to eq("different")
|
|
|
|
end
|
|
|
|
|
|
|
|
it "raises on type cast error with free variables" do
|
|
|
|
allow(fake).to receive(:return_this).and_return(42)
|
|
|
|
expect { fake.return_this("test") }.to raise_error(TypeCastError, /String/)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "handles free variables with a block" do
|
|
|
|
allow(fake).to receive(:map).and_return("stub")
|
|
|
|
expect(fake.map(:mapped, &.to_s)).to eq("stub")
|
|
|
|
end
|
|
|
|
|
|
|
|
it "raises on type cast error with a block and free variables" do
|
|
|
|
allow(fake).to receive(:map).and_return(42)
|
|
|
|
expect { fake.map(:mapped, &.to_s) }.to raise_error(TypeCastError, /String/)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "handles nilable free variables" do
|
|
|
|
expect(fake.make_nilable("foo")).to be_nil
|
|
|
|
end
|
2022-12-14 05:48:21 +00:00
|
|
|
|
|
|
|
it "handles 'self' return type" do
|
|
|
|
not_self = mock(Test)
|
|
|
|
allow(fake).to receive(:itself).and_return(not_self)
|
|
|
|
expect(fake.itself).to be(not_self)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "raises on type cast error with 'self' return type" do
|
|
|
|
allow(fake).to receive(:itself).and_return(42)
|
|
|
|
expect { fake.itself }.to raise_error(TypeCastError, /#{class_mock(Test)}/)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "handles nilable 'self' return type" do
|
|
|
|
not_self = mock(Test)
|
|
|
|
allow(fake).to receive(:itself?).and_return(not_self)
|
|
|
|
expect(fake.itself?).to be(not_self)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "handles generic return type" do
|
|
|
|
allow(fake).to receive(:generic).and_return([42])
|
|
|
|
expect(fake.generic(42)).to eq([42])
|
|
|
|
end
|
|
|
|
|
|
|
|
it "raises on type cast error with generic return type" do
|
|
|
|
allow(fake).to receive(:generic).and_return("test")
|
|
|
|
expect { fake.generic(42) }.to raise_error(TypeCastError, /Array\(Int32\)/)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "handles union return types" do
|
|
|
|
allow(fake).to receive(:union).and_return("test")
|
|
|
|
expect(fake.union).to eq("test")
|
|
|
|
end
|
|
|
|
|
|
|
|
it "raises on type cast error with union return type" do
|
|
|
|
allow(fake).to receive(:union).and_return(:test)
|
|
|
|
expect { fake.union }.to raise_error(TypeCastError, /Symbol/)
|
|
|
|
end
|
2022-12-17 23:41:22 +00:00
|
|
|
|
|
|
|
it "handles captured blocks" do
|
|
|
|
proc = ->{}
|
|
|
|
allow(fake).to receive(:capture).and_return(proc)
|
|
|
|
expect(fake.capture { nil }).to be(proc)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "raises on type cast error with captured blocks" do
|
|
|
|
proc = ->{ 42 }
|
|
|
|
allow(fake).to receive(:capture).and_return(proc)
|
|
|
|
expect { fake.capture { "other" } }.to raise_error(TypeCastError, /Proc\(String\)/)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "handles captured blocks with arguments" do
|
|
|
|
proc = ->(x : Int32) { x * 2 }
|
|
|
|
allow(fake).to receive(:capture).and_return(proc)
|
|
|
|
expect(fake.capture(5) { 5 }).to be(proc)
|
|
|
|
end
|
2022-12-18 18:35:43 +00:00
|
|
|
|
|
|
|
it "handles range comparisons against non-comparable types" do
|
|
|
|
range = 1..10
|
|
|
|
allow(fake).to receive(:range).and_return(range)
|
|
|
|
expect(fake.range(1..3)).to eq(range)
|
|
|
|
end
|
2022-12-14 01:22:22 +00:00
|
|
|
end
|