summaryrefslogtreecommitdiff
path: root/spec/hashie/lash_spec.rb
blob: 708766fecf9ece4171f84ffab087c8ec845c269c (plain)
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
require 'spec_helper'

Hashie::Hash.class_eval do
  def self.inherited(klass)
    klass.instance_variable_set('@inheritance_test', true)
  end
end

class LashTest < Hashie::Lash
  property :first_name, :required => true
  property :email, :required => true
  property :count, :default => 0, :required => true
end

class SubclassedLash < LashTest
  property :last_name, :required => true
end

describe LashTest, :wip => true do

  context "without a required value" do
    it "errors out when values are missing" do
      expect { LashTest.new }.to raise_error(ArgumentError)
    end
  end

  subject { LashTest.new(:first_name => 'Bob', :email => 'bob@example.com') }

  it('subclasses Hashie::Hash') { should respond_to(:to_mash) }

  it 'lists all set properties in inspect' do
    subject.first_name = 'Bob'
    subject.email = 'bob@example.com'
    subject.inspect.should == '<#LashTest count=0 email="bob@example.com" first_name="Bob">'
  end

  its(:count) { should be_zero }

  it { should respond_to(:first_name) }
  it { should respond_to(:first_name=) }
  it { should_not respond_to(:nonexistent) }

  it 'errors out for a non-existent property' do
    lambda { subject['nonexistent'] }.should raise_error(NoMethodError)
  end

  it 'errors out when attempting to set a required property to nil' do
    lambda { subject.first_name = nil }.should raise_error(ArgumentError)
  end

  context 'writing to properties' do
    it 'fails writing to a non-existent property using []=' do
      lambda { subject['nonexistent'] = 123 }.should raise_error(NoMethodError)
    end

    it 'works for an existing property using []=' do
      subject['first_name'] = 'Bob'
      subject['first_name'].should == 'Bob'
      subject[:first_name].should == 'Bob'
    end

    it 'works for an existing property using a method call' do
      subject.first_name = 'Franklin'
      subject.first_name.should == 'Franklin'
    end
  end

  context 'reading from properties' do
    it 'fails reading from a non-existent property using []' do
      lambda { subject['nonexistent'] }.should raise_error(NoMethodError)
    end

    it "should be able to retrieve properties through blocks" do
      subject["first_name"] = "Aiden"
      value = nil
      subject.[]("first_name") { |v| value = v }
      value.should == "Aiden"
    end

    it "should be able to retrieve properties through blocks with method calls" do
      subject["first_name"] = "Frodo"
      value = nil
      subject.first_name { |v| value = v }
      value.should == "Frodo"
    end
  end

  describe '.new' do
    it 'fails with non-existent properties' do
      lambda { described_class.new(:bork => '') }.should raise_error(NoMethodError)
    end

    it 'should set properties that it is able to' do
      obj = described_class.new :first_name => 'Michael', :email => 'michael@example.com'
      obj.first_name.should == 'Michael'
    end

    it 'does not accept nil' do
      lambda { described_class.new(nil) }.should raise_error(ArgumentError)
    end

    it 'accepts block to define a global default' do
      obj = described_class.new { |hash, key| key.to_s.upcase }
      obj.first_name.should == 'FIRST_NAME'
      obj.count.should be_zero
    end
  end

  describe 'properties' do
    it 'lists defined properties' do
      described_class.properties.should == Set.new([:first_name, :email, :count])
    end

    it 'checks if a property exists' do
      described_class.property?('first_name').should be_true
      described_class.property?(:first_name).should be_true
    end

    it 'doesnt include property from subclass' do
      described_class.property?(:last_name).should be_false
    end

    it 'lists declared defaults' do
      described_class.defaults.should == { :count => 0 }
    end
  end
end

describe Hashie::Lash, 'inheritance' do
  before do
    @top = Class.new(Hashie::Lash)
    @middle = Class.new(@top)
    @bottom = Class.new(@middle)
  end

  it 'reports empty properties when nothing defined' do
    @top.properties.should be_empty
    @top.defaults.should be_empty
  end

  it 'inherits properties downwards' do
    @top.property :echo
    @middle.properties.should include(:echo)
    @bottom.properties.should include(:echo)
  end

  it 'doesnt inherit properties upwards' do
    @middle.property :echo
    @top.properties.should_not include(:echo)
    @bottom.properties.should include(:echo)
  end

  it 'allows overriding a default on an existing property' do
    @top.property :echo
    @middle.property :echo, :default => 123
    @bottom.properties.to_a.should == [:echo]
    @bottom.new.echo.should == 123
  end

  it 'allows clearing an existing default' do
    @top.property :echo
    @middle.property :echo, :default => 123
    @bottom.property :echo
    @bottom.properties.to_a.should == [:echo]
    @bottom.new.echo.should be_nil
  end

  it 'should allow nil defaults' do
    @bottom.property :echo, :default => nil
    @bottom.new.should have_key('echo')
  end

end

describe SubclassedLash do

  subject { SubclassedLash.new(:first_name => 'Bob', :email => 'bob@example.com', :last_name => 'Example') }

  its(:count) { should be_zero }

  it { should respond_to(:first_name) }
  it { should respond_to(:first_name=) }
  it { should respond_to(:last_name) }
  it { should respond_to(:last_name=) }

  it 'has one additional property' do
    described_class.property?(:last_name).should be_true
  end

  it "didn't override superclass inheritance logic" do
    described_class.instance_variable_get('@inheritance_test').should be_true
  end

end