1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
require_relative '../spec_helper'
require 'recursive_open_struct'
describe RecursiveOpenStruct do
let(:hash) { {} }
subject(:ros) { RecursiveOpenStruct.new(hash) }
describe "behavior it inherits from OpenStruct" do
context 'when not initialized from anything' do
subject(:ros) { RecursiveOpenStruct.new }
it "can represent arbitrary data objects" do
ros.blah = "John Smith"
expect(ros.blah).to eq "John Smith"
end
it 'returns nil for missing attributes' do
expect(ros.foo).to be_nil
end
end
context 'when initialized with nil' do
let(:hash) { nil }
it 'returns nil for missing attributes' do
expect(ros.foo).to be_nil
end
end
context 'when initialized with an empty hash' do
it 'returns nil for missing attributes' do
expect(ros.foo).to be_nil
end
end
context "when initialized from a hash" do
let(:hash) { { :asdf => 'John Smith' } }
context 'that contains symbol keys' do
it "turns those symbol keys into method names" do
expect(ros.asdf).to eq "John Smith"
end
end
it "can modify an existing key" do
ros.asdf = "George Washington"
expect(ros.asdf).to eq "George Washington"
end
context 'that contains string keys' do
let(:hash) { { 'asdf' => 'John Smith' } }
it "turns those string keys into method names" do
expect(ros.asdf).to eq "John Smith"
end
end
context 'that contains keys that mirror existing private methods' do
let(:hash) { { test: :foo, rand: 'not a number' } }
# https://github.com/aetherknight/recursive-open-struct/issues/42
it 'handles subscript notation without calling the method name first (#42)' do
expect(ros['test']).to eq :foo
expect(ros['rand']).to eq 'not a number'
expect(ros.test).to eq :foo
expect(ros.rand).to eq 'not a number'
end
end
context 'that contains keys that mirror existing public methods inherited from Object' do
let(:hash) { { method: :something } }
it 'handles subscript notation without calling the existing methods' do
expect(ros[:method]).to eq :something
expect(ros['method']).to eq :something
end
end
if [/\A([0-9]+)\.([0-9]+)\.([0-9]+)\z/.match(RUBY_VERSION)].tap { |l| m = l[0] ; l[0] = (m[1].to_i >= 2 && m[2].to_i >= 4) }.first
context 'when Ruby 2.4.0 or newer' do
specify 'new_ostruct_member! is private' do
expect {
ros.new_ostruct_member!(:bonsoir)
}.to raise_error(NoMethodError)
# OpenStruct.new().new_ostruct_member!(:foo)
end
end
end
end
describe "handling of arbitrary attributes" do
subject { RecursiveOpenStruct.new }
before(:each) do
subject.blah = "John Smith"
end
describe "#respond?" do
it { expect(subject).to respond_to :blah }
it { expect(subject).to respond_to :blah= }
it { expect(subject).to_not respond_to :asdf }
it { expect(subject).to_not respond_to :asdf= }
end # describe #respond?
describe "#methods" do
it { expect(subject.methods.map(&:to_sym)).to include :blah }
it { expect(subject.methods.map(&:to_sym)).to include :blah= }
it { expect(subject.methods.map(&:to_sym)).to_not include :asdf }
it { expect(subject.methods.map(&:to_sym)).to_not include :asdf= }
end # describe #methods
end # describe handling of arbitrary attributes
describe "handling of freezing" do
let(:hash) { { :asdf => 'John Smith' } }
before do
ros.freeze
end
it "can read existing keys" do
expect(ros.asdf).to eq 'John Smith'
end
it "cannot write new keys" do
expect { ros.new_key = 'new_value' }.to raise_error FrozenError
end
it "cannot write existing keys" do
expect { ros.asdf = 'new_value' }.to raise_error FrozenError
end
context "with recursive structure" do
let(:hash) { { :key => { :subkey => 42 } } }
it "can read existing sub-elements" do
expect(ros.key.subkey).to eq 42
end
it "can write new sub-elements" do
expect { ros.key.new_subkey = 43 }.not_to raise_error
end
it "can write existing sub-elements" do
expect { ros.key.subkey = 43 }.not_to raise_error
end
end
end
end # describe behavior it inherits from OpenStruct
end
|