shard-spectator/spec/spectator/mocks/arguments_spec.cr
Michael Miller c77da67341
Hide splat label in certain situations
Undefined double methods were reporting splat arguments, which is technically correct.
But for output in these cases, it makes more sense to show the exact calling args.
2022-10-23 21:56:37 -06:00

268 lines
8.9 KiB
Crystal

require "../../spec_helper"
Spectator.describe Spectator::Arguments do
subject(arguments) { Spectator::Arguments.new({42, "foo"}, :splat, {:x, :y, :z}, {bar: "baz", qux: 123}) }
it "stores the arguments" do
expect(arguments).to have_attributes(
args: {42, "foo"},
splat_name: :splat,
splat: {:x, :y, :z},
kwargs: {bar: "baz", qux: 123}
)
end
describe ".capture" do
subject { Spectator::Arguments.capture(42, "foo", bar: "baz", qux: 123) }
it "stores the arguments and keyword arguments" do
is_expected.to have_attributes(args: {42, "foo"}, kwargs: {bar: "baz", qux: 123})
end
end
describe "#[](index)" do
it "returns a positional argument" do
aggregate_failures do
expect(arguments[0]).to eq(42)
expect(arguments[1]).to eq("foo")
end
end
it "returns splat arguments" do
aggregate_failures do
expect(arguments[2]).to eq(:x)
expect(arguments[3]).to eq(:y)
expect(arguments[4]).to eq(:z)
end
end
context "with named positional arguments" do
subject(arguments) { Spectator::Arguments.new({arg1: 42, arg2: "foo"}, :splat, {:x, :y, :z}, {bar: "baz", qux: 123}) }
it "returns a positional argument" do
aggregate_failures do
expect(arguments[0]).to eq(42)
expect(arguments[1]).to eq("foo")
end
end
it "returns splat arguments" do
aggregate_failures do
expect(arguments[2]).to eq(:x)
expect(arguments[3]).to eq(:y)
expect(arguments[4]).to eq(:z)
end
end
end
end
describe "#[](symbol)" do
it "returns a keyword argument" do
aggregate_failures do
expect(arguments[:bar]).to eq("baz")
expect(arguments[:qux]).to eq(123)
end
end
context "with named positional arguments" do
subject(arguments) { Spectator::Arguments.new({arg1: 42, arg2: "foo"}, :splat, {:x, :y, :z}, {bar: "baz", qux: 123}) }
it "returns a positional argument" do
aggregate_failures do
expect(arguments[:arg1]).to eq(42)
expect(arguments[:arg2]).to eq("foo")
end
end
it "returns a keyword argument" do
aggregate_failures do
expect(arguments[:bar]).to eq("baz")
expect(arguments[:qux]).to eq(123)
end
end
end
end
describe "#to_s" do
subject { arguments.to_s }
it "formats the arguments" do
is_expected.to eq("(42, \"foo\", *splat: {:x, :y, :z}, bar: \"baz\", qux: 123)")
end
context "when empty" do
let(arguments) { Spectator::Arguments.none }
it "returns (no args)" do
is_expected.to eq("(no args)")
end
end
context "with a splat and no arguments" do
let(arguments) { Spectator::Arguments.build(NamedTuple.new, :splat, {:x, :y, :z}, {bar: "baz", qux: 123}) }
it "omits the splat name" do
is_expected.to eq("(:x, :y, :z, bar: \"baz\", qux: 123)")
end
end
end
describe "#==" do
subject { arguments == other }
context "with equal arguments" do
let(other) { arguments }
it { is_expected.to be_true }
end
context "with different arguments" do
let(other) { Spectator::Arguments.new({123, :foo, "bar"}, :splat, {1, 2, 3}, {opt: "foobar"}) }
it { is_expected.to be_false }
end
context "with the same kwargs in a different order" do
let(other) { Spectator::Arguments.new(arguments.args, arguments.splat_name, arguments.splat, {qux: 123, bar: "baz"}) }
it { is_expected.to be_true }
end
context "with a missing kwarg" do
let(other) { Spectator::Arguments.new(arguments.args, arguments.splat_name, arguments.splat, {bar: "baz"}) }
it { is_expected.to be_false }
end
context "with an extra kwarg" do
let(other) { Spectator::Arguments.new(arguments.args, arguments.splat_name, arguments.splat, {bar: "baz", qux: 123, extra: 0}) }
it { is_expected.to be_false }
end
context "with different splat arguments" do
let(other) { Spectator::Arguments.new(arguments.args, arguments.splat_name, {1, 2, 3}, arguments.kwargs) }
it { is_expected.to be_false }
end
context "with mixed positional tuple types" do
let(other) { Spectator::Arguments.new({arg1: 42, arg2: "foo"}, arguments.splat_name, arguments.splat, arguments.kwargs) }
it { is_expected.to be_true }
end
context "with mixed positional tuple types (flipped)" do
let(arguments) { Spectator::Arguments.new({arg1: 42, arg2: "foo"}, :splat, {:x, :y, :z}, {bar: "baz", qux: 123}) }
let(other) { Spectator::Arguments.new({42, "foo"}, :splat, {:x, :y, :z}, {bar: "baz", qux: 123}) }
it { is_expected.to be_true }
end
context "with args spilling over into splat and mixed positional tuple types" do
let(arguments) { Spectator::Arguments.new({arg1: 42, arg2: "foo"}, :splat, {:x, :y, :z}, {bar: "baz", qux: 123}) }
let(other) { Spectator::Arguments.new({42, "foo", :x, :y, :z}, nil, nil, {bar: "baz", qux: 123}) }
it { is_expected.to be_true }
end
end
describe "#===" do
subject { pattern === arguments }
context "with equal arguments" do
let(pattern) { arguments }
it { is_expected.to be_true }
end
context "with matching arguments" do
let(pattern) { Spectator::Arguments.new({Int32, /foo/}, :splat, {Symbol, Symbol, :z}, {bar: /baz/, qux: Int32}) }
it { is_expected.to be_true }
end
context "with non-matching arguments" do
let(pattern) { Spectator::Arguments.new({Float64, /bar/}, :splat, {String, Int32, :x}, {bar: /foo/, qux: "123"}) }
it { is_expected.to be_false }
end
context "with different arguments" do
let(pattern) { Spectator::Arguments.new({123, :foo, "bar"}, :splat, {1, 2, 3}, {opt: "foobar"}) }
it { is_expected.to be_false }
end
context "with the same kwargs in a different order" do
let(pattern) { Spectator::Arguments.new(arguments.args, arguments.splat_name, arguments.splat, {qux: Int32, bar: /baz/}) }
it { is_expected.to be_true }
end
context "with an additional kwarg" do
let(pattern) { Spectator::Arguments.new(arguments.args, arguments.splat_name, arguments.splat, {bar: /baz/}) }
it { is_expected.to be_true }
end
context "with a missing kwarg" do
let(pattern) { Spectator::Arguments.new(arguments.args, arguments.splat_name, arguments.splat, {bar: /baz/, qux: Int32, extra: 0}) }
it { is_expected.to be_false }
end
context "with different splat arguments" do
let(pattern) { Spectator::Arguments.new(arguments.args, arguments.splat_name, {1, 2, 3}, arguments.kwargs) }
it { is_expected.to be_false }
end
context "with matching mixed positional tuple types" do
let(pattern) { Spectator::Arguments.new({arg1: Int32, arg2: /foo/}, arguments.splat_name, arguments.splat, arguments.kwargs) }
it { is_expected.to be_true }
end
context "with non-matching mixed positional tuple types" do
let(pattern) { Spectator::Arguments.new({arg1: Float64, arg2: /bar/}, arguments.splat_name, arguments.splat, arguments.kwargs) }
it { is_expected.to be_false }
end
context "with matching args spilling over into splat and mixed positional tuple types" do
let(arguments) { Spectator::Arguments.new({arg1: 42, arg2: "foo"}, :splat, {:x, :y, :z}, {bar: "baz", qux: 123}) }
let(pattern) { Spectator::Arguments.capture(Int32, /foo/, Symbol, Symbol, :z, bar: /baz/, qux: Int32) }
it { is_expected.to be_true }
end
context "with non-matching args spilling over into splat and mixed positional tuple types" do
let(arguments) { Spectator::Arguments.new({arg1: 42, arg2: "foo"}, :splat, {:x, :y, :z}, {bar: "baz", qux: 123}) }
let(pattern) { Spectator::Arguments.capture(Float64, /bar/, Symbol, String, :z, bar: /foo/, qux: Int32) }
it { is_expected.to be_false }
end
context "with matching mixed named positional and keyword arguments" do
let(arguments) { Spectator::Arguments.new({arg1: 42, arg2: "foo"}, :splat, {:x, :y, :z}, {bar: "baz", qux: 123}) }
let(pattern) { Spectator::Arguments.capture(/foo/, Symbol, :y, Symbol, arg1: Int32, bar: /baz/, qux: 123) }
it { is_expected.to be_true }
end
context "with non-matching mixed named positional and keyword arguments" do
let(arguments) { Spectator::Arguments.new({arg1: 42, arg2: "foo"}, :splat, {:x, :y, :z}, {bar: "baz", qux: 123}) }
let(pattern) { Spectator::Arguments.capture(5, Symbol, :z, Symbol, arg2: /foo/, bar: /baz/, qux: Int32) }
it { is_expected.to be_false }
end
context "with non-matching mixed named positional and keyword arguments" do
let(arguments) { Spectator::Arguments.new({arg1: 42, arg2: "foo"}, :splat, {:x, :y, :z}, {bar: "baz", qux: 123}) }
let(pattern) { Spectator::Arguments.capture(/bar/, String, :y, Symbol, arg1: 0, bar: /foo/, qux: Float64) }
it { is_expected.to be_false }
end
end
end