2018-03-04 10:09:32 -05:00
|
|
|
require_relative '../spec_helper'
|
2017-05-07 08:04:49 -04:00
|
|
|
|
2018-04-28 15:50:06 -04:00
|
|
|
describe "Safe navigator" do
|
|
|
|
it "requires a method name to be provided" do
|
2019-07-27 06:40:09 -04:00
|
|
|
-> { eval("obj&. {}") }.should raise_error(SyntaxError)
|
2018-04-28 15:50:06 -04:00
|
|
|
end
|
2017-05-07 08:04:49 -04:00
|
|
|
|
2018-04-28 15:50:06 -04:00
|
|
|
context "when context is nil" do
|
|
|
|
it "always returns nil" do
|
|
|
|
eval("nil&.unknown").should == nil
|
|
|
|
eval("[][10]&.unknown").should == nil
|
|
|
|
end
|
2017-05-07 08:04:49 -04:00
|
|
|
|
2018-04-28 15:50:06 -04:00
|
|
|
it "can be chained" do
|
|
|
|
eval("nil&.one&.two&.three").should == nil
|
|
|
|
end
|
2017-05-07 08:04:49 -04:00
|
|
|
|
2018-04-28 15:50:06 -04:00
|
|
|
it "doesn't evaluate arguments" do
|
|
|
|
obj = Object.new
|
|
|
|
obj.should_not_receive(:m)
|
|
|
|
eval("nil&.unknown(obj.m) { obj.m }")
|
2017-05-07 08:04:49 -04:00
|
|
|
end
|
2018-04-28 15:50:06 -04:00
|
|
|
end
|
2017-05-07 08:04:49 -04:00
|
|
|
|
2018-04-28 15:50:06 -04:00
|
|
|
context "when context is false" do
|
|
|
|
it "calls the method" do
|
|
|
|
eval("false&.to_s").should == "false"
|
2017-05-07 08:04:49 -04:00
|
|
|
|
2019-07-27 06:40:09 -04:00
|
|
|
-> { eval("false&.unknown") }.should raise_error(NoMethodError)
|
2017-05-07 08:04:49 -04:00
|
|
|
end
|
2018-04-28 15:50:06 -04:00
|
|
|
end
|
2017-05-07 08:04:49 -04:00
|
|
|
|
2018-04-28 15:50:06 -04:00
|
|
|
context "when context is truthy" do
|
|
|
|
it "calls the method" do
|
|
|
|
eval("1&.to_s").should == "1"
|
2017-05-07 08:04:49 -04:00
|
|
|
|
2019-07-27 06:40:09 -04:00
|
|
|
-> { eval("1&.unknown") }.should raise_error(NoMethodError)
|
2017-05-07 08:04:49 -04:00
|
|
|
end
|
2018-04-28 15:50:06 -04:00
|
|
|
end
|
2017-05-07 08:04:49 -04:00
|
|
|
|
2018-04-28 15:50:06 -04:00
|
|
|
it "takes a list of arguments" do
|
|
|
|
eval("[1,2,3]&.first(2)").should == [1,2]
|
|
|
|
end
|
2017-05-07 08:04:49 -04:00
|
|
|
|
2018-04-28 15:50:06 -04:00
|
|
|
it "takes a block" do
|
|
|
|
eval("[1,2]&.map { |i| i * 2 }").should == [2, 4]
|
|
|
|
end
|
2017-05-07 08:04:49 -04:00
|
|
|
|
2018-04-28 15:50:06 -04:00
|
|
|
it "allows assignment methods" do
|
|
|
|
klass = Class.new do
|
|
|
|
attr_reader :foo
|
|
|
|
def foo=(val)
|
|
|
|
@foo = val
|
|
|
|
42
|
2017-05-07 08:04:49 -04:00
|
|
|
end
|
2018-04-28 15:50:06 -04:00
|
|
|
end
|
|
|
|
obj = klass.new
|
2017-05-07 08:04:49 -04:00
|
|
|
|
2018-04-28 15:50:06 -04:00
|
|
|
eval("obj&.foo = 3").should == 3
|
|
|
|
obj.foo.should == 3
|
2017-05-07 08:04:49 -04:00
|
|
|
|
2018-04-28 15:50:06 -04:00
|
|
|
obj = nil
|
|
|
|
eval("obj&.foo = 3").should == nil
|
|
|
|
end
|
2017-05-07 08:04:49 -04:00
|
|
|
|
2018-04-28 15:50:06 -04:00
|
|
|
it "allows assignment operators" do
|
|
|
|
klass = Class.new do
|
|
|
|
attr_accessor :m
|
2017-05-07 08:04:49 -04:00
|
|
|
|
2018-04-28 15:50:06 -04:00
|
|
|
def initialize
|
|
|
|
@m = 0
|
2017-05-07 08:04:49 -04:00
|
|
|
end
|
2018-04-28 15:50:06 -04:00
|
|
|
end
|
2017-05-07 08:04:49 -04:00
|
|
|
|
2018-04-28 15:50:06 -04:00
|
|
|
obj = klass.new
|
2017-05-07 08:04:49 -04:00
|
|
|
|
2018-04-28 15:50:06 -04:00
|
|
|
eval("obj&.m += 3")
|
|
|
|
obj.m.should == 3
|
2017-05-07 08:04:49 -04:00
|
|
|
|
2018-04-28 15:50:06 -04:00
|
|
|
obj = nil
|
|
|
|
eval("obj&.m += 3").should == nil
|
|
|
|
end
|
2017-05-07 08:04:49 -04:00
|
|
|
|
2018-04-28 15:50:06 -04:00
|
|
|
it "does not call the operator method lazily with an assignment operator" do
|
|
|
|
klass = Class.new do
|
|
|
|
attr_writer :foo
|
|
|
|
def foo
|
|
|
|
nil
|
2017-05-07 08:04:49 -04:00
|
|
|
end
|
|
|
|
end
|
2018-04-28 15:50:06 -04:00
|
|
|
obj = klass.new
|
|
|
|
|
2019-07-27 06:40:09 -04:00
|
|
|
-> {
|
2018-04-28 15:50:06 -04:00
|
|
|
eval("obj&.foo += 3")
|
|
|
|
}.should raise_error(NoMethodError) { |e|
|
|
|
|
e.name.should == :+
|
|
|
|
}
|
2017-05-07 08:04:49 -04:00
|
|
|
end
|
|
|
|
end
|