compo 0.1.5 → 0.2.0
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.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/CHANGELOG +8 -0
- data/lib/compo/composite.rb +1 -1
- data/lib/compo/parent_tracker.rb +2 -1
- data/lib/compo/parentless.rb +112 -0
- data/lib/compo/url_referenceable.rb +20 -1
- data/lib/compo/version.rb +1 -1
- data/lib/compo.rb +1 -0
- data/spec/array_branch_spec.rb +4 -9
- data/spec/array_composite_shared_examples.rb +240 -0
- data/spec/array_composite_spec.rb +2 -220
- data/spec/branch_shared_examples.rb +33 -0
- data/spec/composite_shared_examples.rb +283 -0
- data/spec/composite_spec.rb +9 -250
- data/spec/hash_branch_spec.rb +4 -9
- data/spec/hash_composite_shared_examples.rb +208 -0
- data/spec/hash_composite_spec.rb +2 -179
- data/spec/leaf_spec.rb +4 -25
- data/spec/movable_shared_examples.rb +154 -0
- data/spec/movable_spec.rb +2 -191
- data/spec/null_composite_shared_examples.rb +68 -0
- data/spec/null_composite_spec.rb +2 -62
- data/spec/parent_tracker_spec.rb +2 -2
- data/spec/parentless_spec.rb +52 -0
- data/spec/url_referenceable_shared_examples.rb +78 -0
- data/spec/url_referenceable_spec.rb +2 -65
- metadata +18 -1
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'url_referenceable_shared_examples'
|
2
|
+
require 'movable_shared_examples'
|
3
|
+
|
4
|
+
shared_examples 'a branch' do
|
5
|
+
it_behaves_like 'a URL referenceable object'
|
6
|
+
it_behaves_like 'a movable object'
|
7
|
+
|
8
|
+
describe '#initialize' do
|
9
|
+
it 'initialises with a Parentless as parent' do
|
10
|
+
expect(subject.parent).to be_a(Compo::Parentless)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'initialises with an ID function returning nil' do
|
14
|
+
expect(subject.id).to be_nil
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#url' do
|
19
|
+
context 'when the Leaf has no parent' do
|
20
|
+
it 'returns the empty string' do
|
21
|
+
expect(subject.url).to eq('')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
context 'when the Leaf is the child of a root' do
|
25
|
+
let(:parent) { Compo::HashBranch.new }
|
26
|
+
before(:each) { subject.move_to(parent, :id) }
|
27
|
+
|
28
|
+
it 'returns /ID, where ID is the ID of the Leaf' do
|
29
|
+
expect(subject.url).to eq('/id')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,283 @@
|
|
1
|
+
require 'compo'
|
2
|
+
|
3
|
+
shared_examples 'a removal of a child from its parent' do
|
4
|
+
it 'calls #update_parent on the child with a Parentless' do
|
5
|
+
expect(child).to receive(:update_parent).once do |parent, _|
|
6
|
+
expect(parent).to be_a(Compo::Parentless)
|
7
|
+
end
|
8
|
+
op.call
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'calls #update_parent on the child with a nil-returning ID proc' do
|
12
|
+
expect(child).to receive(:update_parent).once do |_, idp|
|
13
|
+
expect(idp.call).to be_nil
|
14
|
+
end
|
15
|
+
op.call
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
shared_examples 'a composite' do
|
20
|
+
let(:id) { double(:id) }
|
21
|
+
let(:child) { double(:child) }
|
22
|
+
|
23
|
+
describe '#each' do
|
24
|
+
it 'delegates to the #each implementation of the hash from #children' do
|
25
|
+
children = double(:children)
|
26
|
+
|
27
|
+
allow(subject).to receive(:children).and_return(children)
|
28
|
+
expect(subject).to receive(:children).once.with(no_args)
|
29
|
+
expect(children).to receive(:each).once
|
30
|
+
|
31
|
+
subject.each
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#add' do
|
36
|
+
before(:each) { allow(subject).to receive(:add!) }
|
37
|
+
|
38
|
+
context 'when #add! returns nil' do
|
39
|
+
before(:each) { allow(subject).to receive(:add!).and_return(nil) }
|
40
|
+
|
41
|
+
specify { expect(subject.add(id, child)).to be_nil }
|
42
|
+
|
43
|
+
it 'calls #add! with the ID and child given' do
|
44
|
+
expect(subject).to receive(:add!).once.with(id, child)
|
45
|
+
subject.add(id, child)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'when #add! returns the child' do
|
50
|
+
before(:each) do
|
51
|
+
allow(subject).to receive(:add!).and_return(child)
|
52
|
+
allow(subject).to receive(:id_function)
|
53
|
+
allow(child).to receive(:update_parent)
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'calls #add! with the ID and child given' do
|
57
|
+
expect(subject).to receive(:add!).once.with(id, child)
|
58
|
+
subject.add(id, child)
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'calls #id_function with the child given' do
|
62
|
+
expect(subject).to receive(:id_function).once.with(child)
|
63
|
+
subject.add(id, child)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'calls #update_parent on the child with the parent and ID function' do
|
67
|
+
idf = double(:id_function)
|
68
|
+
allow(subject).to receive(:id_function).and_return(idf)
|
69
|
+
expect(child).to receive(:update_parent).once.with(subject, idf)
|
70
|
+
subject.add(id, child)
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'returns the given child' do
|
74
|
+
expect(subject.add(id, child)).to eq(child)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe '#get_child' do
|
80
|
+
let(:child) { double(:child) }
|
81
|
+
|
82
|
+
before(:each) do
|
83
|
+
allow(subject).to receive(:children).and_return(in_children: child)
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'when the argument is in #children' do
|
87
|
+
it 'returns the child' do
|
88
|
+
expect(subject.get_child(:in_children)).to eq(child)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'when the argument is not in #children' do
|
93
|
+
specify { expect(subject.get_child(:not_in_children)).to be_nil }
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
shared_examples 'a composite with default #remove!' do
|
99
|
+
let(:child) { double(:child) }
|
100
|
+
let(:id) { double(:id) }
|
101
|
+
|
102
|
+
describe '#remove' do
|
103
|
+
context 'when #remove! is defined' do
|
104
|
+
before(:each) { allow(subject).to receive(:remove!) }
|
105
|
+
|
106
|
+
context 'when #remove! returns nil' do
|
107
|
+
before(:each) { allow(subject).to receive(:remove!).and_return(nil) }
|
108
|
+
|
109
|
+
specify { expect(subject.remove(child)).to be_nil }
|
110
|
+
|
111
|
+
it 'calls #remove! with the child given' do
|
112
|
+
expect(subject).to receive(:remove!).once.with(child)
|
113
|
+
subject.remove(child)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context 'when #remove! returns the child' do
|
118
|
+
before(:each) do
|
119
|
+
allow(subject).to receive(:remove!).and_return(child)
|
120
|
+
allow(child).to receive(:update_parent)
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'calls #remove! with the child given' do
|
124
|
+
expect(subject).to receive(:remove!).once.with(child)
|
125
|
+
subject.remove(child)
|
126
|
+
end
|
127
|
+
|
128
|
+
it_behaves_like 'a removal of a child from its parent' do
|
129
|
+
let(:op) { -> { subject.remove(child) } }
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'returns the given child' do
|
133
|
+
expect(subject.remove(child)).to eq(child)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
context 'when #remove_id! is defined but #remove! is not' do
|
139
|
+
before(:each) do
|
140
|
+
allow(subject).to receive(:remove_id!)
|
141
|
+
allow(subject).to receive(:children).and_return(id => child)
|
142
|
+
end
|
143
|
+
|
144
|
+
context 'when #remove_id! returns nil' do
|
145
|
+
before(:each) do
|
146
|
+
allow(subject).to receive(:remove_id!).and_return(nil)
|
147
|
+
end
|
148
|
+
|
149
|
+
specify { expect(subject.remove(child)).to be_nil }
|
150
|
+
|
151
|
+
it 'calls #remove! with the child given' do
|
152
|
+
expect(subject).to receive(:remove!).once.with(child)
|
153
|
+
subject.remove(child)
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'calls #remove_id! with the ID of the child' do
|
157
|
+
expect(subject).to receive(:remove_id!).once.with(id)
|
158
|
+
subject.remove(child)
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'calls #children' do
|
162
|
+
expect(subject).to receive(:children).once
|
163
|
+
subject.remove(child)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
context 'when #remove_id! returns the child' do
|
168
|
+
before(:each) do
|
169
|
+
allow(subject).to receive(:remove_id!).and_return(child)
|
170
|
+
allow(child).to receive(:update_parent)
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'calls #remove_id! with the child given' do
|
174
|
+
expect(subject).to receive(:remove!).once.with(child)
|
175
|
+
subject.remove(child)
|
176
|
+
end
|
177
|
+
|
178
|
+
it_behaves_like 'a removal of a child from its parent' do
|
179
|
+
let(:op) { -> { subject.remove(child) } }
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'returns the given child' do
|
183
|
+
expect(subject.remove(child)).to eq(child)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
shared_examples 'a composite with default #remove_id!' do
|
191
|
+
let(:child) { double(:child) }
|
192
|
+
let(:id) { double(:id) }
|
193
|
+
|
194
|
+
describe '#remove_id' do
|
195
|
+
let(:id) { double(:id) }
|
196
|
+
|
197
|
+
context 'when #remove_id! is defined' do
|
198
|
+
before(:each) { allow(subject).to receive(:remove_id!) }
|
199
|
+
|
200
|
+
context 'and #remove_id! returns nil' do
|
201
|
+
before(:each) do
|
202
|
+
allow(subject).to receive(:remove_id!).and_return(nil)
|
203
|
+
end
|
204
|
+
|
205
|
+
specify { expect(subject.remove_id(id)).to be_nil }
|
206
|
+
|
207
|
+
it 'calls #remove_id! with the ID given' do
|
208
|
+
expect(subject).to receive(:remove_id!).once.with(id)
|
209
|
+
subject.remove_id(id)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
context 'and #remove_id! returns the child' do
|
214
|
+
before(:each) do
|
215
|
+
allow(subject).to receive(:remove_id!).and_return(child)
|
216
|
+
allow(child).to receive(:update_parent)
|
217
|
+
end
|
218
|
+
|
219
|
+
it 'calls #remove_id! with the ID given' do
|
220
|
+
expect(subject).to receive(:remove_id!).once.with(id)
|
221
|
+
subject.remove_id(id)
|
222
|
+
end
|
223
|
+
|
224
|
+
it_behaves_like 'a removal of a child from its parent' do
|
225
|
+
let(:op) { -> { subject.remove_id(id) } }
|
226
|
+
end
|
227
|
+
|
228
|
+
it 'returns the child' do
|
229
|
+
expect(subject.remove_id(id)).to eq(child)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
context 'when #remove! is defined but #remove_id! is not' do
|
235
|
+
before(:each) { allow(subject).to receive(:remove!) }
|
236
|
+
|
237
|
+
context 'and #remove! returns nil' do
|
238
|
+
before(:each) do
|
239
|
+
allow(subject).to receive(:remove!).and_return(nil)
|
240
|
+
allow(subject).to receive(:get_child).and_return(child)
|
241
|
+
end
|
242
|
+
|
243
|
+
specify { expect(subject.remove_id(id)).to be_nil }
|
244
|
+
|
245
|
+
it 'calls #remove_id! with the ID given' do
|
246
|
+
expect(subject).to receive(:remove_id!).once.with(id)
|
247
|
+
subject.remove_id(id)
|
248
|
+
end
|
249
|
+
|
250
|
+
it 'calls #get_child with the ID given' do
|
251
|
+
expect(subject).to receive(:get_child).once.with(id)
|
252
|
+
subject.remove_id(id)
|
253
|
+
end
|
254
|
+
|
255
|
+
it 'calls #remove! with the child given' do
|
256
|
+
expect(subject).to receive(:remove!).once.with(child)
|
257
|
+
subject.remove_id(id)
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
context 'and #remove! returns the child' do
|
262
|
+
before(:each) do
|
263
|
+
allow(subject).to receive(:remove!).and_return(child)
|
264
|
+
allow(subject).to receive(:get_child).and_return(child)
|
265
|
+
allow(child).to receive(:update_parent)
|
266
|
+
end
|
267
|
+
|
268
|
+
it 'calls #remove! with the child given' do
|
269
|
+
expect(subject).to receive(:remove!).once.with(child)
|
270
|
+
subject.remove_id(id)
|
271
|
+
end
|
272
|
+
|
273
|
+
it_behaves_like 'a removal of a child from its parent' do
|
274
|
+
let(:op) { -> { subject.remove_id(id) } }
|
275
|
+
end
|
276
|
+
|
277
|
+
it 'returns the given child' do
|
278
|
+
expect(subject.remove_id(id)).to eq(child)
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
data/spec/composite_spec.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'compo'
|
3
|
+
require 'composite_shared_examples'
|
3
4
|
|
4
5
|
# Mock implementation of a Composite
|
5
6
|
class MockComposite
|
@@ -7,263 +8,21 @@ class MockComposite
|
|
7
8
|
end
|
8
9
|
|
9
10
|
describe MockComposite do
|
10
|
-
|
11
|
+
before(:each) { allow(subject).to receive(:children).and_return(children) }
|
12
|
+
let(:children) { { in_children: child } }
|
11
13
|
let(:child) { double(:child) }
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
context 'when #add! returns nil' do
|
17
|
-
before(:each) { allow(subject).to receive(:add!).and_return(nil) }
|
18
|
-
|
19
|
-
specify { expect(subject.add(id, child)).to be_nil }
|
20
|
-
|
21
|
-
it 'calls #add! with the ID and child given' do
|
22
|
-
expect(subject).to receive(:add!).once.with(id, child)
|
23
|
-
subject.add(id, child)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
context 'when #add! returns the child' do
|
28
|
-
before(:each) do
|
29
|
-
allow(subject).to receive(:add!).and_return(child)
|
30
|
-
allow(subject).to receive(:id_function)
|
31
|
-
allow(child).to receive(:update_parent)
|
32
|
-
end
|
33
|
-
|
34
|
-
it 'calls #add! with the ID and child given' do
|
35
|
-
expect(subject).to receive(:add!).once.with(id, child)
|
36
|
-
subject.add(id, child)
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'calls #id_function with the child given' do
|
40
|
-
expect(subject).to receive(:id_function).once.with(child)
|
41
|
-
subject.add(id, child)
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'calls #update_parent on the child with the parent and ID function' do
|
45
|
-
idf = double(:id_function)
|
46
|
-
allow(subject).to receive(:id_function).and_return(idf)
|
47
|
-
expect(child).to receive(:update_parent).once.with(subject, idf)
|
48
|
-
subject.add(id, child)
|
49
|
-
end
|
50
|
-
|
51
|
-
it 'returns the given child' do
|
52
|
-
expect(subject.add(id, child)).to eq(child)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
describe '#remove' do
|
58
|
-
context 'when #remove! is defined' do
|
59
|
-
before(:each) { allow(subject).to receive(:remove!) }
|
60
|
-
|
61
|
-
context 'when #remove! returns nil' do
|
62
|
-
before(:each) { allow(subject).to receive(:remove!).and_return(nil) }
|
63
|
-
|
64
|
-
specify { expect(subject.remove(child)).to be_nil }
|
65
|
-
|
66
|
-
it 'calls #remove! with the child given' do
|
67
|
-
expect(subject).to receive(:remove!).once.with(child)
|
68
|
-
subject.remove(child)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
context 'when #remove! returns the child' do
|
73
|
-
before(:each) do
|
74
|
-
allow(subject).to receive(:remove!).and_return(child)
|
75
|
-
allow(child).to receive(:remove_parent)
|
76
|
-
end
|
77
|
-
|
78
|
-
it 'calls #remove! with the child given' do
|
79
|
-
expect(subject).to receive(:remove!).once.with(child)
|
80
|
-
subject.remove(child)
|
81
|
-
end
|
82
|
-
|
83
|
-
it 'calls #remove_parent on the child with no arguments' do
|
84
|
-
expect(child).to receive(:remove_parent).once.with(no_args)
|
85
|
-
subject.remove(child)
|
86
|
-
end
|
87
|
-
|
88
|
-
it 'returns the given child' do
|
89
|
-
expect(subject.remove(child)).to eq(child)
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
context 'when #remove_id! is defined but #remove! is not' do
|
95
|
-
before(:each) do
|
96
|
-
allow(subject).to receive(:remove_id!)
|
97
|
-
allow(subject).to receive(:children).and_return(id => child)
|
98
|
-
end
|
99
|
-
|
100
|
-
context 'when #remove_id! returns nil' do
|
101
|
-
before(:each) do
|
102
|
-
allow(subject).to receive(:remove_id!).and_return(nil)
|
103
|
-
end
|
104
|
-
|
105
|
-
specify { expect(subject.remove(child)).to be_nil }
|
106
|
-
|
107
|
-
it 'calls #remove! with the child given' do
|
108
|
-
expect(subject).to receive(:remove!).once.with(child)
|
109
|
-
subject.remove(child)
|
110
|
-
end
|
111
|
-
|
112
|
-
it 'calls #remove_id! with the ID of the child' do
|
113
|
-
expect(subject).to receive(:remove_id!).once.with(id)
|
114
|
-
subject.remove(child)
|
115
|
-
end
|
116
|
-
|
117
|
-
it 'calls #children' do
|
118
|
-
expect(subject).to receive(:children).once
|
119
|
-
subject.remove(child)
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
context 'when #remove_id! returns the child' do
|
124
|
-
before(:each) do
|
125
|
-
allow(subject).to receive(:remove_id!).and_return(child)
|
126
|
-
allow(child).to receive(:remove_parent)
|
127
|
-
end
|
128
|
-
|
129
|
-
it 'calls #remove_id! with the child given' do
|
130
|
-
expect(subject).to receive(:remove!).once.with(child)
|
131
|
-
subject.remove(child)
|
132
|
-
end
|
133
|
-
|
134
|
-
it 'calls #remove_parent on the child with no arguments' do
|
135
|
-
expect(child).to receive(:remove_parent).once.with(no_args)
|
136
|
-
subject.remove(child)
|
137
|
-
end
|
138
|
-
|
139
|
-
it 'returns the given child' do
|
140
|
-
expect(subject.remove(child)).to eq(child)
|
141
|
-
end
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
describe '#remove_id' do
|
147
|
-
let(:id) { double(:id) }
|
148
|
-
|
149
|
-
context 'when #remove_id! is defined' do
|
150
|
-
before(:each) { allow(subject).to receive(:remove_id!) }
|
151
|
-
|
152
|
-
context 'and #remove_id! returns nil' do
|
153
|
-
before(:each) do
|
154
|
-
allow(subject).to receive(:remove_id!).and_return(nil)
|
155
|
-
end
|
156
|
-
|
157
|
-
specify { expect(subject.remove_id(id)).to be_nil }
|
158
|
-
|
159
|
-
it 'calls #remove_id! with the ID given' do
|
160
|
-
expect(subject).to receive(:remove_id!).once.with(id)
|
161
|
-
subject.remove_id(id)
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
context 'and #remove_id! returns the child' do
|
166
|
-
before(:each) do
|
167
|
-
allow(subject).to receive(:remove_id!).and_return(child)
|
168
|
-
allow(child).to receive(:remove_parent)
|
169
|
-
end
|
170
|
-
|
171
|
-
it 'calls #remove_id! with the ID given' do
|
172
|
-
expect(subject).to receive(:remove_id!).once.with(id)
|
173
|
-
subject.remove_id(id)
|
174
|
-
end
|
175
|
-
|
176
|
-
it 'calls #remove_parent on the child with no arguments' do
|
177
|
-
expect(child).to receive(:remove_parent).once.with(no_args)
|
178
|
-
subject.remove_id(id)
|
179
|
-
end
|
180
|
-
|
181
|
-
it 'returns the child' do
|
182
|
-
expect(subject.remove_id(id)).to eq(child)
|
183
|
-
end
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
context 'when #remove! is defined but #remove_id! is not' do
|
188
|
-
before(:each) { allow(subject).to receive(:remove!) }
|
189
|
-
|
190
|
-
context 'and #remove! returns nil' do
|
191
|
-
before(:each) do
|
192
|
-
allow(subject).to receive(:remove!).and_return(nil)
|
193
|
-
allow(subject).to receive(:get_child).and_return(child)
|
194
|
-
end
|
195
|
-
|
196
|
-
specify { expect(subject.remove_id(id)).to be_nil }
|
197
|
-
|
198
|
-
it 'calls #remove_id! with the ID given' do
|
199
|
-
expect(subject).to receive(:remove_id!).once.with(id)
|
200
|
-
subject.remove_id(id)
|
201
|
-
end
|
202
|
-
|
203
|
-
it 'calls #get_child with the ID given' do
|
204
|
-
expect(subject).to receive(:get_child).once.with(id)
|
205
|
-
subject.remove_id(id)
|
206
|
-
end
|
207
|
-
|
208
|
-
it 'calls #remove! with the child given' do
|
209
|
-
expect(subject).to receive(:remove!).once.with(child)
|
210
|
-
subject.remove_id(id)
|
211
|
-
end
|
212
|
-
end
|
213
|
-
|
214
|
-
context 'and #remove! returns the child' do
|
215
|
-
before(:each) do
|
216
|
-
allow(subject).to receive(:remove!).and_return(child)
|
217
|
-
allow(subject).to receive(:get_child).and_return(child)
|
218
|
-
allow(child).to receive(:remove_parent)
|
219
|
-
end
|
220
|
-
|
221
|
-
it 'calls #remove! with the child given' do
|
222
|
-
expect(subject).to receive(:remove!).once.with(child)
|
223
|
-
subject.remove_id(id)
|
224
|
-
end
|
225
|
-
|
226
|
-
it 'calls #remove_parent on the child with no arguments' do
|
227
|
-
expect(child).to receive(:remove_parent).once.with(no_args)
|
228
|
-
subject.remove_id(id)
|
229
|
-
end
|
230
|
-
|
231
|
-
it 'returns the given child' do
|
232
|
-
expect(subject.remove_id(id)).to eq(child)
|
233
|
-
end
|
234
|
-
end
|
235
|
-
end
|
236
|
-
end
|
237
|
-
|
238
|
-
describe '#each' do
|
239
|
-
it 'delegates to the #each implementation of the hash from #children' do
|
240
|
-
children = double(:children)
|
241
|
-
|
242
|
-
allow(subject).to receive(:children).and_return(children)
|
243
|
-
expect(subject).to receive(:children).once.with(no_args)
|
244
|
-
expect(children).to receive(:each).once
|
245
|
-
|
246
|
-
subject.each
|
247
|
-
end
|
248
|
-
end
|
15
|
+
it_behaves_like 'a composite'
|
16
|
+
it_behaves_like 'a composite with default #remove!'
|
17
|
+
it_behaves_like 'a composite with default #remove_id!'
|
249
18
|
|
19
|
+
#
|
20
|
+
# Specifications for Composite's default behaviour.
|
21
|
+
#
|
250
22
|
describe '#get_child' do
|
251
|
-
before(:each) { allow(subject).to receive(:children).and_return(children) }
|
252
|
-
let(:children) { { in_children: child } }
|
253
|
-
|
254
23
|
it 'calls #children' do
|
255
24
|
expect(subject).to receive(:children).once
|
256
25
|
subject.get_child(:in_children)
|
257
26
|
end
|
258
|
-
|
259
|
-
context 'when the argument is in #children' do
|
260
|
-
it 'returns the child' do
|
261
|
-
expect(subject.get_child(:in_children)).to eq(child)
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
265
|
-
context 'when the argument is in #children' do
|
266
|
-
specify { expect(subject.get_child(:not_in_children)).to be_nil }
|
267
|
-
end
|
268
27
|
end
|
269
28
|
end
|
data/spec/hash_branch_spec.rb
CHANGED
@@ -1,14 +1,9 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'compo'
|
3
|
+
require 'branch_shared_examples'
|
4
|
+
require 'hash_composite_shared_examples'
|
3
5
|
|
4
6
|
describe Compo::HashBranch do
|
5
|
-
|
6
|
-
|
7
|
-
expect(subject.parent).to be_nil
|
8
|
-
end
|
9
|
-
|
10
|
-
it 'initialises with an ID function returning nil' do
|
11
|
-
expect(subject.id).to be_nil
|
12
|
-
end
|
13
|
-
end
|
7
|
+
it_behaves_like 'a branch'
|
8
|
+
it_behaves_like 'a hash composite'
|
14
9
|
end
|