halogen 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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