require "spec_helper" describe Array do describe ".evolve" do context "when provided an Array" do let(:array) do [ 1, 2, 3 ] end it "returns an array" do expect(described_class.evolve(array)).to eq([ 1, 2, 3 ]) end it "doesn't mutate its argument" do expect{ described_class.evolve(array.freeze) }.not_to raise_error end end context "when provided nil" do it "returns nil" do expect(described_class.evolve(nil)).to be_nil end end context "when provided another object" do it "returns the object" do expect(described_class.evolve("testing")).to eq("testing") end end end describe "#__add__" do context "when the other object is a non-enumerable" do context "when all values are unique" do it "returns an array of both" do expect([ 5, 6 ].__add__(7)).to eq([ 5, 6, 7 ]) end end context "when values are not unique" do it "returns a unique array of both" do expect([ 5, 6 ].__add__(6)).to eq([ 5, 6 ]) end end end context "when the other object is an array" do context "when all values are unique" do it "returns an array of both" do expect([ 4, 5 ].__add__([ 6, 7 ])).to eq([ 4, 5, 6, 7 ]) end end context "when values are not unique" do it "returns a unique array of both" do expect([ 4, 5 ].__add__([ 5, 6, 7 ])).to eq([ 4, 5, 6, 7 ]) end end end context "when the other object is a hash" do context "when all values are unique" do it "returns a hash of both" do expect([ 4, 5 ].__add__({ "$in" => [ 6, 7 ] })).to eq( { "$in" => [ 4, 5, 6, 7 ] } ) end end context "when values are not unique" do it "returns a unique array of both" do expect([ 4, 5 ].__add__({ "$in" => [ 5, 6, 7 ] })).to eq( { "$in" => [ 4, 5, 6, 7 ] } ) end end end end describe "#__array__" do it "returns self" do expect([ 1, 2, 3 ].__array__).to eq([ 1, 2, 3 ]) end end describe "__deep_copy__" do let(:inner) do [ 3, 4 ] end let(:array) do [ 1, 2, inner ] end let(:copy) do array.__deep_copy__ end it "returns an equal array" do expect(copy).to eq(array) end it "returns a copy" do expect(copy).to_not equal(array) end it "deep copies the elements" do expect(copy[2]).to_not equal(inner) end end describe "#__evolve_date__" do context "when the array is composed of dates" do let(:date) do Date.new(2010, 1, 1) end let(:evolved) do [ date ].__evolve_date__ end let(:expected) do Time.utc(2010, 1, 1, 0, 0, 0, 0) end it "returns the array with evolved times" do expect(evolved).to eq([ expected ]) end end context "when the array is composed of strings" do let(:date) do Date.parse("1st Jan 2010") end let(:evolved) do [ date.to_s ].__evolve_date__ end it "returns the strings as a times" do expect(evolved).to eq([ Time.new(2010, 1, 1, 0, 0, 0, 0).utc ]) end end context "when the array is composed of integers" do let(:time) do Time.utc(2010, 1, 1, 0, 0, 0, 0) end let(:integer) do time.to_i end let(:evolved) do [ integer ].__evolve_date__ end let(:expected) do Time.at(integer) end it "returns the integers as times" do expect(evolved).to eq([ time ]) end end context "when the array is composed of floats" do let(:time) do Time.utc(2010, 1, 1, 0, 0, 0, 0) end let(:float) do time.to_f end let(:evolved) do [ float ].__evolve_date__ end let(:expected) do Time.at(float) end it "returns the floats as times" do expect(evolved).to eq([ time ]) end end end describe "__evolve_time__" do context "when the array is composed of times" do let(:date) do Time.new(2010, 1, 1, 12, 0, 0) end let(:evolved) do [ date ].__evolve_time__ end let(:expected) do Time.new(2010, 1, 1, 12, 0, 0).utc end it "returns the array with evolved times" do expect(evolved).to eq([ expected ]) end it "returns utc times" do expect(evolved.first.utc_offset).to eq(0) end end context "when the array is composed of strings" do let(:date) do Time.parse("1st Jan 2010 12:00:00+01:00") end let(:evolved) do [ date.to_s ].__evolve_time__ end it "returns the strings as a times" do expect(evolved).to eq([ date.to_time ]) end it "returns the times in utc" do expect(evolved.first.utc_offset).to eq(0) end end context "when the array is composed of integers" do let(:integer) do 1331890719 end let(:evolved) do [ integer ].__evolve_time__ end let(:expected) do Time.at(integer).utc end it "returns the integers as times" do expect(evolved).to eq([ expected ]) end it "returns the times in utc" do expect(evolved.first.utc_offset).to eq(0) end end context "when the array is composed of floats" do let(:float) do 1331890719.413 end let(:evolved) do [ float ].__evolve_time__ end let(:expected) do Time.at(float).utc end it "returns the floats as times" do expect(evolved).to eq([ expected ]) end it "returns the times in utc" do expect(evolved.first.utc_offset).to eq(0) end end end describe "#__expand_complex__" do let(:array) do [{ :test.in => [ "value" ] }] end it "expands all keys inside the array" do expect(array.__expand_complex__).to eq([{ "test" => { "$in" => [ "value" ]}}]) end end describe "#__intersect__" do context "when the other object is a non-enumerable" do context "when the values intersect" do it "returns an intersected array" do expect([ 5, 6, 7 ].__intersect__(6)).to eq([ 6 ]) end end context "when the values do not intersect" do it "returns an empty array" do expect([ 5, 6, 7 ].__intersect__(8)).to be_empty end end end context "when the other object is an array" do context "when the values intersect" do it "returns an intersected array" do expect([ 4, 5, 6 ].__intersect__([ 6, 7 ])).to eq([ 6 ]) end end context "when values do not intersect" do it "returns an empty array" do expect([ 4, 5 ].__intersect__([ 6, 7 ])).to be_empty end end end context "when the other object is a hash" do context "when the values intersect" do it "returns a hash of both" do expect([ 4, 5 ].__intersect__({ "$in" => [ 5, 6 ] })).to eq( { "$in" => [ 5 ] } ) end end context "when values do not intersect" do it "returns an empty array" do expect([ 4, 5 ].__intersect__({ "$in" => [ 6, 7 ] })).to eq( { "$in" => [] } ) end end end end describe "#__sort_option__" do context "when the array is one dimensional" do it "returns a hash of sort options" do expect([ :field, 1 ].__sort_option__).to eq({ field: 1 }) end end context "when the array is multi dimensional" do it "returns a hash of sort options" do expect([[ :field, 1 ]].__sort_option__).to eq({ field: 1 }) end end end describe "#__sort_pair__" do context "when the direction is a symbol" do it "converts the symbol to an integer" do expect([ :field, :asc ].__sort_pair__).to eq({ field: 1 }) end end context "when the direction is an integer" do it "returns the array as a hash" do expect([ :field, 1 ].__sort_pair__).to eq({ field: 1 }) end end end describe "#__union__" do context "when the other object is a non-enumerable" do it "returns an unioned array" do expect([ 5, 6, 7 ].__union__(6)).to eq([ 5, 6, 7 ]) end end context "when the other object is an array" do it "returns an unioned array" do expect([ 4, 5, 6 ].__union__([ 6, 7 ])).to eq([ 4, 5, 6, 7 ]) end end context "when the other object is a hash" do it "returns a hash with a unioned array" do expect([ 4, 5 ].__union__({ "$in" => [ 5, 6 ] })).to eq( { "$in" => [ 4, 5, 6 ] } ) end end end describe "#__sort_option__" do context "when the array is multi-dimensional" do context "when the arrays have integer values" do let(:selection) do [[ :field_one, 1 ],[ :field_two, -1 ]] end it "adds the sorting criteria" do expect(selection.__sort_option__).to eq( { field_one: 1, field_two: -1 } ) end end context "when the arrays have symbol values" do let(:selection) do [[ :field_one, :asc ],[ :field_two, :desc ]] end it "adds the sorting criteria" do expect(selection.__sort_option__).to eq( { field_one: 1, field_two: -1 } ) end end context "when the arrays have string values" do let(:selection) do [[ :field_one, "asc" ],[ :field_two, "desc" ]] end it "adds the sorting criteria" do expect(selection.__sort_option__).to eq( { field_one: 1, field_two: -1 } ) end end end context "when the array is one-dimensional" do context "when the arrays have integer values" do let(:selection) do [ :field_one, 1 ] end it "adds the sorting criteria" do expect(selection.__sort_option__).to eq( { field_one: 1 } ) end end end context "when the array is selectable keys" do let(:selection) do [ :field_one.asc, :field_two.desc ] end it "adds the sorting criteria" do expect(selection.__sort_option__).to eq( { field_one: 1, field_two: -1 } ) end end end describe "#update_values" do let(:array) do [ 1, 2, 3 ] end let(:updated) do array.update_values(&:to_s) end it "replaces each of the values with the result of the block" do expect(updated).to eq([ "1", "2", "3" ]) end it "returns the same instance of the array" do expect(updated).to equal(array) end end end