halogen 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+ #
3
+ require 'spec_helper'
4
+
5
+ describe Halogen::Definitions do
6
+ let :definitions do
7
+ Halogen::Definitions.new
8
+ end
9
+
10
+ let :definition do
11
+ Halogen::Definition.new(:name, {}, nil)
12
+ end
13
+
14
+ describe '#add' do
15
+ it 'validates and adds definition' do
16
+ expect(definitions.keys).to eq([])
17
+
18
+ definitions.add(definition)
19
+
20
+ expect(definitions.keys).to eq(['Halogen::Definition'])
21
+ expect(definitions['Halogen::Definition']).to eq([definition])
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+ #
3
+ require 'spec_helper'
4
+
5
+ describe Halogen::Embeds::Definition do
6
+ describe '#validate' do
7
+ it 'returns true with procedure' do
8
+ result = Halogen::Embeds::Definition.new(:name, {}, proc {}).validate
9
+
10
+ expect(result).to eq(true)
11
+ end
12
+
13
+ it 'raises exception without procedure' do
14
+ expect {
15
+ Halogen::Embeds::Definition.new(:name, {}, nil).validate
16
+ }.to raise_error do |exception|
17
+ expect(exception).to be_an_instance_of(Halogen::InvalidDefinition)
18
+ expect(exception.message).to(
19
+ eq('Embed name must be defined with a proc'))
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,201 @@
1
+ # encoding: utf-8
2
+ #
3
+ require 'spec_helper'
4
+
5
+ describe Halogen::Embeds do
6
+ let :klass do
7
+ Class.new do
8
+ include Halogen
9
+ include Halogen::Embeds
10
+ end
11
+ end
12
+
13
+ describe Halogen::Embeds::ClassMethods do
14
+ it 'adds simple embed definition' do
15
+ expect(klass.definitions).to receive(:add)
16
+
17
+ klass.embed(:foo, {}) { 'bar' }
18
+ end
19
+ end
20
+
21
+ describe Halogen::Embeds::InstanceMethods do
22
+ describe '#embedded' do
23
+ describe 'when no embeds are defined' do
24
+ it 'returns empty hash when no embeds are requested' do
25
+ representer = klass.new
26
+
27
+ expect(representer.embedded).to eq({})
28
+ end
29
+
30
+ it 'returns empty hash when embeds are requested' do
31
+ representer = klass.new(embed: { foo: true })
32
+
33
+ expect(representer.embedded).to eq({})
34
+ end
35
+ end
36
+
37
+ describe 'when embeds are defined' do
38
+ before :each do
39
+ klass.embed(:just_nil, {}) { nil }
40
+ klass.embed(:non_repr, {}) { 'some object' }
41
+ klass.embed(:child_repr, {}) { child }
42
+
43
+ klass.send(:define_method, :child) do
44
+ # just build another representer instance to be rendered
45
+ Class.new { include Halogen }.new
46
+ end
47
+ end
48
+
49
+ it 'returns empty hash when no embeds are requested' do
50
+ representer = klass.new(embed: {})
51
+
52
+ expect(representer.embedded).to eq({})
53
+ end
54
+
55
+ it 'builds embedded resources as expected' do
56
+ embed_opts = { just_nil: true, non_repr: true, child_repr: true }
57
+
58
+ representer = klass.new(embed: embed_opts)
59
+
60
+ expect(representer.embedded).to eq(child_repr: {})
61
+ end
62
+ end
63
+ end
64
+
65
+ describe '#embedded_child' do
66
+ let :representer do
67
+ klass.new
68
+ end
69
+
70
+ let :child_class do
71
+ Class.new do
72
+ include Halogen
73
+
74
+ property(:foo) { 'bar' }
75
+ end
76
+ end
77
+
78
+ let :child do
79
+ child_class.new
80
+ end
81
+
82
+ it 'returns nil if value is falsey' do
83
+ [nil, false, 0].each do |value|
84
+ expect(representer.embedded_child(:foo, value)).to be_nil
85
+ end
86
+ end
87
+
88
+ describe 'when value is an array' do
89
+ it 'renders children' do
90
+ array = [child, nil, 0, child, 1]
91
+
92
+ result = representer.embedded_child(:embed_key, array)
93
+
94
+ expect(result).to eq([{ foo: 'bar' }, { foo: 'bar' }])
95
+ end
96
+ end
97
+
98
+ describe 'when value is a representer' do
99
+ it 'renders child' do
100
+ result = representer.embedded_child(:embed_key, child)
101
+
102
+ expect(result).to eq(foo: 'bar')
103
+ end
104
+ end
105
+ end
106
+
107
+ describe '#child_embed_opts' do
108
+ it 'returns empty options for unknown key' do
109
+ representer = klass.new
110
+
111
+ opts = representer.send(:child_embed_opts, :unknown_key)
112
+
113
+ expect(opts).to eq({})
114
+ end
115
+
116
+ it 'returns empty options for known key with no child options' do
117
+ representer = klass.new(embed: { requested_key: 1 })
118
+
119
+ opts = representer.send(:child_embed_opts, 'requested_key')
120
+
121
+ expect(opts).to eq({})
122
+ end
123
+
124
+ it 'returns child options for known key with child options' do
125
+ representer = klass.new(embed: { requested_key: { child_key: 0 } })
126
+
127
+ opts = representer.send(:child_embed_opts, 'requested_key')
128
+
129
+ expect(opts).to eq(child_key: 0)
130
+ end
131
+
132
+ it 'returns deeply nested child options' do
133
+ representer = klass.new(
134
+ embed: {
135
+ requested_key: {
136
+ child_key: { grandchild_key: { great_grandchild_key: 1 } }
137
+ }
138
+ }
139
+ )
140
+
141
+ opts = representer.send(:child_embed_opts, 'requested_key')
142
+
143
+ expect(opts).to eq(
144
+ child_key: { grandchild_key: { great_grandchild_key: 1 } })
145
+ end
146
+ end
147
+
148
+ describe '#render_child' do
149
+ let :representer do
150
+ klass.new
151
+ end
152
+
153
+ it 'returns nil if child is not a representer' do
154
+ [nil, 1, ''].each do |child|
155
+ expect(representer.render_child(child, {})).to be_nil
156
+ end
157
+ end
158
+
159
+ it 'renders child representer with correct parent and options' do
160
+ child = Class.new do
161
+ include Halogen
162
+
163
+ property(:verify_parent) { parent.object_id }
164
+ property(:verify_opts) { options[:embed] }
165
+ end.new
166
+
167
+ result = representer.render_child(child, foo: 'bar')
168
+
169
+ expect(result).to eq(
170
+ verify_parent: representer.object_id,
171
+ verify_opts: { foo: 'bar' })
172
+ end
173
+ end
174
+
175
+ describe '#embed_options' do
176
+ it 'stringifies top level keys' do
177
+ representer = klass.new(embed: { some: { options: 1 } })
178
+
179
+ expect(representer.embed_options).to eq('some' => { options: 1 })
180
+ end
181
+ end
182
+
183
+ describe '#embed?' do
184
+ it 'is true for expected values' do
185
+ [1, 2, true, '1', '2', 'true', 'yes'].each do |value|
186
+ representer = klass.new(embed: { foo: value })
187
+
188
+ expect(representer.embed?('foo')).to eq(true)
189
+ end
190
+ end
191
+
192
+ it 'is false for expected values' do
193
+ [0, false, '0', 'false'].each do |value|
194
+ representer = klass.new(embed: { foo: value })
195
+
196
+ expect(representer.embed?('foo')).to eq(false)
197
+ end
198
+ end
199
+ end
200
+ end
201
+ end
@@ -0,0 +1,68 @@
1
+ # encoding: utf-8
2
+ #
3
+ require 'spec_helper'
4
+
5
+ describe Halogen::Links::Definition do
6
+ describe '#validate' do
7
+ it 'returns true with procedure' do
8
+ result = Halogen::Links::Definition.new(:name, proc {}).validate
9
+
10
+ expect(result).to eq(true)
11
+ end
12
+
13
+ it 'raises exception without procedure or explicit value' do
14
+ expect {
15
+ Halogen::Links::Definition.new(:name, nil).validate
16
+ }.to raise_error do |exception|
17
+ expect(exception).to be_an_instance_of(Halogen::InvalidDefinition)
18
+ expect(exception.message).to(
19
+ eq('Link requires either procedure or explicit value'))
20
+ end
21
+ end
22
+ end
23
+
24
+ describe '.build_options' do
25
+ it 'has expected value without options hash' do
26
+ options = Halogen::Links::Definition.build_options([])
27
+
28
+ expect(options).to eq(attrs: {})
29
+ end
30
+
31
+ it 'has expected value with options hash' do
32
+ options = Halogen::Links::Definition.build_options([foo: 'bar'])
33
+
34
+ expect(options).to eq(attrs: {}, foo: 'bar')
35
+ end
36
+
37
+ it 'merges attrs from options' do
38
+ options = Halogen::Links::Definition.build_options([
39
+ :templated,
40
+ attrs: { properties: {} },
41
+ foo: 'bar'])
42
+
43
+ expect(options).to(
44
+ eq(attrs: { properties: {}, templated: true }, foo: 'bar'))
45
+ end
46
+ end
47
+
48
+ describe '.build_attrs' do
49
+ it 'returns empty hash if no keywords are provided' do
50
+ expect(Halogen::Links::Definition.build_attrs([])).to eq({})
51
+ end
52
+
53
+ it 'builds expected hash with recognized keywords' do
54
+ attrs = Halogen::Links::Definition.build_attrs([:templated])
55
+
56
+ expect(attrs).to eq(templated: true)
57
+ end
58
+
59
+ it 'raises exception if unrecognized keyword is included' do
60
+ expect {
61
+ Halogen::Links::Definition.build_attrs([:templated, :wat])
62
+ }.to raise_error do |exception|
63
+ expect(exception.class).to eq(Halogen::InvalidDefinition)
64
+ expect(exception.message).to eq('Unrecognized link keyword: wat')
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,59 @@
1
+ # encoding: utf-8
2
+ #
3
+ require 'spec_helper'
4
+
5
+ describe Halogen::Links do
6
+ let :klass do
7
+ Class.new { include Halogen }
8
+ end
9
+
10
+ describe Halogen::Links::ClassMethods do
11
+ describe '#link' do
12
+ describe 'with procedure' do
13
+ it 'builds simple definition' do
14
+ link = klass.link(:self) { 'path' }
15
+
16
+ expect(link.name).to eq(:self)
17
+ expect(link.options).to eq(attrs: {})
18
+ expect(link.procedure.call).to eq('path')
19
+ end
20
+
21
+ it 'builds complex definition' do
22
+ link = klass.link(
23
+ :self, :templated, foo: 'foo', attrs: { bar: 'bar' }) { 'path' }
24
+
25
+ expect(link.name).to eq(:self)
26
+ expect(link.options).to eq(
27
+ foo: 'foo', attrs: { templated: true, bar: 'bar' })
28
+ expect(link.procedure.call).to eq('path')
29
+ end
30
+ end
31
+
32
+ describe 'without procedure' do
33
+ describe 'with explicit value' do
34
+ it 'builds simple definition' do
35
+ link = klass.link(:self, value: 'path')
36
+
37
+ expect(link.name).to eq(:self)
38
+ expect(link.options).to eq(attrs: {}, value: 'path')
39
+ expect(link.procedure).to be_nil
40
+ end
41
+
42
+ it 'builds complex definition' do
43
+ link = klass.link(
44
+ :self,
45
+ :templated,
46
+ foo: 'foo', attrs: { bar: 'bar' }, value: 'path')
47
+
48
+ expect(link.name).to eq(:self)
49
+ expect(link.options).to eq(
50
+ foo: 'foo',
51
+ attrs: { templated: true, bar: 'bar' },
52
+ value: 'path')
53
+ expect(link.procedure).to be_nil
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,41 @@
1
+ # encoding: utf-8
2
+ #
3
+ require 'spec_helper'
4
+
5
+ describe Halogen::Properties do
6
+ let :klass do
7
+ Class.new { include Halogen }
8
+ end
9
+
10
+ describe Halogen::Properties::ClassMethods do
11
+ describe '#property' do
12
+ it 'defines property 'do
13
+ expect {
14
+ klass.property(:foo)
15
+ }.to change(klass.definitions, :size).by(1)
16
+ end
17
+ end
18
+ end
19
+
20
+ describe Halogen::Properties::InstanceMethods do
21
+ let :repr do
22
+ klass.new
23
+ end
24
+
25
+ describe '#render' do
26
+ it 'merges super with rendered properties' do
27
+ allow(repr).to receive(:properties).and_return(foo: 'bar')
28
+
29
+ expect(repr.render).to eq(foo: 'bar')
30
+ end
31
+ end
32
+
33
+ describe '#properties' do
34
+ it 'builds properties from definitions' do
35
+ klass.property(:foo, value: 'bar')
36
+
37
+ expect(repr.properties).to eq(foo: 'bar')
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,77 @@
1
+ # encoding: utf-8
2
+ #
3
+ require 'spec_helper'
4
+
5
+ describe Halogen::Resource do
6
+ let :klass do
7
+ Class.new do
8
+ include Halogen
9
+ include Halogen::Resource
10
+ end
11
+ end
12
+
13
+ describe '.included' do
14
+ it 'raises error if base is already a collection' do
15
+ resource_class = Class.new do
16
+ include Halogen
17
+ include Halogen::Collection
18
+ end
19
+
20
+ expect {
21
+ resource_class.send :include, Halogen::Resource
22
+ }.to raise_error do |exception|
23
+ expect(exception).to be_an_instance_of(Halogen::InvalidResource)
24
+ expect(exception.message).to match(/has already defined a collection/i)
25
+ end
26
+ end
27
+ end
28
+
29
+ describe Halogen::Resource::ClassMethods do
30
+ describe '#define_resource' do
31
+ it 'defines resource' do
32
+ klass.define_resource :foo
33
+
34
+ expect(klass.resource_name).to eq('foo')
35
+ expect(klass.new(nil).respond_to?(:foo)).to eq(true)
36
+ end
37
+ end
38
+
39
+ describe '#property' do
40
+ it 'returns result of super if procedure is present' do
41
+ original = proc { 'bar' }
42
+
43
+ definition = klass.property(:foo, &original)
44
+
45
+ expect(definition.procedure).to eq(original)
46
+ end
47
+
48
+ it 'returns result of super if value is present' do
49
+ definition = klass.property(:foo, value: 'bar')
50
+
51
+ expect(definition.procedure).to be_nil
52
+ end
53
+
54
+ it 'assigns procedure without original procedure or value' do
55
+ definition = klass.property(:foo)
56
+
57
+ expect(definition.procedure).to be_an_instance_of(Proc)
58
+ end
59
+ end
60
+ end
61
+
62
+ describe Halogen::Resource::InstanceMethods do
63
+ describe '#initialize' do
64
+ it 'raises error if resource is not provided' do
65
+ expect { klass.new }.to raise_error(ArgumentError)
66
+ end
67
+
68
+ it 'assigns resource' do
69
+ resource = double(:resource)
70
+
71
+ repr = klass.new(resource)
72
+
73
+ expect(repr.instance_variable_get(:@resource)).to eq(resource)
74
+ end
75
+ end
76
+ end
77
+ end