File: open_struct_behavior_spec.rb

package info (click to toggle)
ruby-recursive-open-struct 2.1.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 208 kB
  • sloc: ruby: 1,050; makefile: 6
file content (148 lines) | stat: -rw-r--r-- 4,638 bytes parent folder | download
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