spec/dottie_spec.rb in dottie-0.0.1 vs spec/dottie_spec.rb in dottie-0.0.2

- old
+ new

@@ -18,10 +18,34 @@ end it 'creates a Dottie::Freckle from an Array using Dottie()' do arr = ['a', 'b', 'c'] expect(Dottie(arr)).to be_a Dottie::Freckle end + it 'returns a Dottie::Freckle<Hash> instead of rewrapping it using Dottie[]' do + dottie = Dottie[{ 'a' => 'b' }] + expect(Dottie[dottie]).to eq dottie + end + it 'returns a Dottie::Freckle<Array> instead of rewrapping it using Dottie[]' do + dottie = Dottie[['a', 'b', 'c']] + expect(Dottie[dottie]).to eq dottie + end + it 'returns a Dottie::Freckle<Hash> instead of rewrapping it using Dottie()' do + dottie = Dottie({ 'a' => 'b' }) + expect(Dottie(dottie)).to eq dottie + end + it 'returns a Dottie::Freckle<Array> instead of rewrapping it using Dottie()' do + dottie = Dottie(['a', 'b', 'c']) + expect(Dottie(dottie)).to eq dottie + end + ['a', nil, 1].each do |val| + it "fails to create a Dottie::Freckle from an invalid type (#{val.class}) using Dottie[]" do + expect{ Dottie[val] }.to raise_error(TypeError) + end + it "fails to create a Dottie::Freckle from an invalid type (#{val.class}) using Dottie()" do + expect{ Dottie(val) }.to raise_error(TypeError) + end + end end describe 'reading' do @@ -118,10 +142,24 @@ it 'returns nil for a missing array' do expect(Dottie.get(hash, 'x[4][5]')).to be_nil end end + context 'lax keys' do + let(:hash) {{ 'a' => 'b', 'c' => [{ 'd' => 'e', '0' => 1 }, { 'f' => 'g' }] }} + + it 'reads a targeted array index number as an integer' do + expect(Dottie.get(hash, 'c.0.d')).to eq 'e' + end + it 'reads a targeted hash key number as a string' do + expect(Dottie.get(hash, 'c.0.0')).to eq 1 + end + it 'reads an targeted hash key integer as an integer' do + expect(Dottie.get(hash, 'c.0[0]')).to be_nil + end + end + end describe 'key existence' do let(:hash) {{ 'a' => 'b', 'c' => { 'd' => ['e', 'f', 'g'] } }} @@ -253,10 +291,35 @@ Dottie.set(@hash, 'c[3]', 'g') expect(@hash).to eq({ 'a' => 'b', 'c' => ['d', 'e', 'f', 'g'] }) end end + context 'array prepend/append' do + before :each do + @hash = { 'a' => 'b', 'c' => ['g', 'h', 'i'] } + end + + %w( - prepend >> ).each do |key| + it "prepends an array element with [#{key}]" do + Dottie.set(@hash, "c[#{key}]", 'f') + expect(@hash).to eq({ 'a' => 'b', 'c' => ['f', 'g', 'h', 'i'] }) + end + end + %w( + append << ).each do |key| + it "appends an array element with [#{key}]" do + Dottie.set(@hash, "c[#{key}]", 'j') + expect(@hash).to eq({ 'a' => 'b', 'c' => ['g', 'h', 'i', 'j'] }) + end + end + %w( - + prepend append >> << ).each do |key| + it "creates an array at a non-existent key with [#{key}]" do + Dottie.set(@hash, "r[#{key}]", 's') + expect(@hash).to eq({ 'a' => 'b', 'c' => ['g', 'h', 'i'], 'r' => ['s'] }) + end + end + end + context 'invalid' do before :each do @hash = { 'a' => 'b', 'c' => { 'd' => 'e' }, 'f' => ['g', 'h'] } end @@ -275,10 +338,114 @@ end end end + describe 'deleting' do + + context 'simple' do + before :each do + @hash = { 'a' => 'b', 'c' => { 'd' => 'e' } } + end + + it 'deletes a standard key' do + ret = Dottie.delete(@hash, 'c') + expect(ret).to eq({ 'd' => 'e' }) + expect(@hash).to eq({ 'a' => 'b' }) + end + it 'deletes a dotted key' do + ret = Dottie.delete(@hash, 'c.d') + expect(ret).to eq 'e' + expect(@hash).to eq({ 'a' => 'b', 'c' => {} }) + end + it 'returns nil when attempting to delete a non-existent standard key' do + ret = Dottie.delete(@hash, 'x') + expect(ret).to be_nil + expect(@hash).to eq({ 'a' => 'b', 'c' => { 'd' => 'e' } }) + end + it 'returns nil when attempting to delete a non-existent dotted key' do + ret = Dottie.delete(@hash, 'x.y') + expect(ret).to be_nil + expect(@hash).to eq({ 'a' => 'b', 'c' => { 'd' => 'e' } }) + end + end + + context 'array indexes' do + before :each do + @hash = { 'a' => 'b', 'c' => [{ 'd' => 'e', 'f' => 'g' }, { 'h' => 'i' }] } + end + + it 'deletes an element from an array (positive index)' do + ret = Dottie.delete(@hash, 'c[0]') + expect(ret).to eq({ 'd' => 'e', 'f' => 'g' }) + expect(@hash).to eq({ 'a' => 'b', 'c' => [{ 'h' => 'i' }] }) + end + it 'deletes an element from an array (negative index)' do + ret = Dottie.delete(@hash, 'c[-1]') + expect(ret).to eq({ 'h' => 'i' }) + expect(@hash).to eq({ 'a' => 'b', 'c' => [{ 'd' => 'e', 'f' => 'g' }] }) + end + it 'deletes an element from an array (first)' do + ret = Dottie.delete(@hash, 'c[first]') + expect(ret).to eq({ 'd' => 'e', 'f' => 'g' }) + expect(@hash).to eq({ 'a' => 'b', 'c' => [{ 'h' => 'i' }] }) + end + it 'deletes an element from an array (last)' do + ret = Dottie.delete(@hash, 'c[last]') + expect(ret).to eq({ 'h' => 'i' }) + expect(@hash).to eq({ 'a' => 'b', 'c' => [{ 'd' => 'e', 'f' => 'g' }] }) + end + it 'deletes an element from a nested structure' do + ret = Dottie.delete(@hash, 'c[0].d') + expect(ret).to eq('e') + expect(@hash).to eq({ 'a' => 'b', 'c' => [{ 'f' => 'g' }, { 'h' => 'i' }] }) + end + it 'returns nil when attempting to delete a non-existent array index' do + ret = Dottie.delete(@hash, 'c[3]') + expect(ret).to be_nil + expect(@hash).to eq({ 'a' => 'b', 'c' => [{ 'd' => 'e', 'f' => 'g' }, { 'h' => 'i' }] }) + end + end + + end + + describe 'flattening' do + + context 'hash' do + let(:hash) {{ 'a' => 'b', 'c' => { 'd' => ['e', 'f', 'g'] } }} + + it 'flattens a hash' do + expect(Dottie.flatten(hash)).to eq({ 'a' => 'b', 'c.d[0]' => 'e', 'c.d[1]' => 'f', 'c.d[2]' => 'g' }) + end + it 'gets flattened hash keys' do + expect(Dottie.keys(hash)).to eq ['a', 'c.d[0]', 'c.d[1]', 'c.d[2]'] + end + it 'gets all flattened hash keys' do + expect(Dottie.keys(hash, intermediate: true)).to eq ['a', 'c', 'c.d', 'c.d[0]', 'c.d[1]', 'c.d[2]'] + end + end + + context 'array' do + let(:arr) { ['x', { 'a' => 'b', 'c' => { 'd' => ['e', 'f', 'g'] } }, 'y'] } + + it 'flattens an array' do + expect(Dottie.flatten(arr)).to eq({ + '[0]' => 'x', + '[1].a' => 'b', '[1].c.d[0]' => 'e', '[1].c.d[1]' => 'f', '[1].c.d[2]' => 'g', + '[2]' => 'y' }) + end + it 'gets flattened array keys' do + expect(Dottie.keys(arr)).to eq ['[0]', '[1].a', '[1].c.d[0]', '[1].c.d[1]', '[1].c.d[2]', '[2]'] + end + it 'gets all flattened array keys' do + expect(Dottie.keys(arr, intermediate: true)).to eq [ + '[0]', '[1]', '[1].a', '[1].c', '[1].c.d', '[1].c.d[0]', '[1].c.d[1]', '[1].c.d[2]', '[2]'] + end + end + + end + describe 'key identification' do it 'recognizes a dotted key' do key = 'a.b.c' expect(Dottie.dottie_key?(key)).to be_true @@ -394,9 +561,37 @@ it 'collapses multiple dots into a single dot' do str = 'a.b..c' arr = ['a', 'b', 'c'] expect(Dottie.key_parts(str)).to eq arr + end + + end + + describe 'key building' do + + it 'builds a single-element key' do + expect(Dottie.build_key(['a'])).to eq 'a' + end + + it 'builds a dotted key' do + expect(Dottie.build_key(['a', 'b', 'c'])).to eq 'a.b.c' + end + + it 'builds a dotted key a number' do + expect(Dottie.build_key(['a', '0', '1', 'b'])).to eq 'a.0.1.b' + end + + it 'builds a complex key with a positive integer' do + expect(Dottie.build_key(['a', 0, 'b'])).to eq 'a[0].b' + end + + it 'builds a complex key with a negative integer' do + expect(Dottie.build_key(['a', -1, 'b'])).to eq 'a[-1].b' + end + + it 'builds a complex key with consecutive integers' do + expect(Dottie.build_key(['a', 0, 1, 'b'])).to eq 'a[0][1].b' end end describe 'key format variants' do