# frozen_string_literal: true require "assert" require "much-result/aggregate" class MuchResult::Aggregate class UnitTests < Assert::Context desc "MuchResult::Aggregate" subject{ unit_class } let(:unit_class){ MuchResult::Aggregate } let(:values1) do [Factory.value, Factory.value, Factory.value, {}] end let(:hash_values1) do [Factory.hash_value, Factory.hash_value, Factory.hash_value] end should have_imeths :call should "build instances and call them" do Assert.stub_tap_on_call(subject, :new) do |instance, call| @instance_new_call = call Assert.stub(instance, :call){ @instance_called = true } end subject.call(values1) assert_that(@instance_new_call.args).equals([values1]) assert_that(@instance_called).is_true end end class InitTests < UnitTests desc "when init" subject{ unit_class.new(init_values) } let(:init_values){ [values1, hash_values1, [], nil].sample } should have_imeths :call end class CalledWithAnEmptyArrayTests < InitTests desc "and called with an empty Array" let(:init_values){ [] } # let(:init_values) { [[], nil, [nil, nil]].sample } should "return an empty Array" do assert_that(subject.call).equals([]) end end class CalledWithASingleNonHashValueTests < InitTests desc "and called with single non-Hash value" let(:init_values){ [Factory.value, nil].sample } should "return the value wrapped in an Array" do assert_that(subject.call).equals([init_values]) end end class CalledWithASingleHashValueTests < InitTests desc "and called with single Hash value" let(:value1){ [Factory.value, nil].sample } let(:init_values){ { value: value1 } } should "return the Hash with its values wrapped in an Array" do assert_that(subject.call).equals(value: [value1]) end end class CalledWithAMixedValueArrayTests < InitTests desc "and called with a mixed-value Array" let(:init_values){ [nil, values1, [], { value: 1 }, nil] } should "combines the values into an Array, flattening any sub-Arrays" do assert_that(subject.call).equals([nil, *values1, { value: 1 }, nil]) end end class CalledWithAnAllHashValueArrayTests < InitTests desc "and called with an all-Hash-value Array" let(:init_values){ [nil] + hash_values1 + [nil] } let(:expected_aggregate_value) do { value1: init_values.map{ |hash| (hash || {})[:value1] }, value2: { value1: init_values.map{ |hash| (hash || {}).dig(:value2, :value1) }, value2: init_values.map{ |hash| (hash || {}).dig(:value2, :value2) }, }, } end should "recursively combine the hash values, removing any nils" do assert_that(subject.call).equals(expected_aggregate_value) end end end