arbre2 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +30 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +6 -0
- data/CHANGELOG.md +75 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +93 -0
- data/LICENSE +20 -0
- data/README.md +92 -0
- data/Rakefile +7 -0
- data/arbre.gemspec +28 -0
- data/lib/arbre/child_element_collection.rb +86 -0
- data/lib/arbre/container.rb +20 -0
- data/lib/arbre/context.rb +83 -0
- data/lib/arbre/element/building.rb +151 -0
- data/lib/arbre/element.rb +194 -0
- data/lib/arbre/element_collection.rb +93 -0
- data/lib/arbre/html/attributes.rb +91 -0
- data/lib/arbre/html/class_list.rb +53 -0
- data/lib/arbre/html/comment.rb +47 -0
- data/lib/arbre/html/document.rb +93 -0
- data/lib/arbre/html/html_tags.rb +67 -0
- data/lib/arbre/html/querying.rb +256 -0
- data/lib/arbre/html/tag.rb +317 -0
- data/lib/arbre/rails/layouts.rb +126 -0
- data/lib/arbre/rails/legacy_document.rb +29 -0
- data/lib/arbre/rails/rendering.rb +76 -0
- data/lib/arbre/rails/rspec/arbre_support.rb +61 -0
- data/lib/arbre/rails/rspec.rb +2 -0
- data/lib/arbre/rails/template_handler.rb +32 -0
- data/lib/arbre/rails.rb +35 -0
- data/lib/arbre/rspec/be_rendered_as_matcher.rb +103 -0
- data/lib/arbre/rspec/be_scripted_as_matcher.rb +68 -0
- data/lib/arbre/rspec/contain_script_matcher.rb +64 -0
- data/lib/arbre/rspec.rb +3 -0
- data/lib/arbre/text_node.rb +35 -0
- data/lib/arbre/version.rb +3 -0
- data/lib/arbre.rb +27 -0
- data/spec/arbre/integration/html_document_spec.rb +90 -0
- data/spec/arbre/integration/html_spec.rb +283 -0
- data/spec/arbre/integration/querying_spec.rb +187 -0
- data/spec/arbre/integration/rails_spec.rb +183 -0
- data/spec/arbre/rails/rspec/arbre_support_spec.rb +75 -0
- data/spec/arbre/rspec/be_rendered_as_matcher_spec.rb +80 -0
- data/spec/arbre/rspec/be_scripted_as_matcher_spec.rb +61 -0
- data/spec/arbre/rspec/contain_script_matcher_spec.rb +40 -0
- data/spec/arbre/support/arbre_example_group.rb +0 -0
- data/spec/arbre/unit/child_element_collection_spec.rb +146 -0
- data/spec/arbre/unit/container_spec.rb +23 -0
- data/spec/arbre/unit/context_spec.rb +95 -0
- data/spec/arbre/unit/element/building_spec.rb +300 -0
- data/spec/arbre/unit/element_collection_spec.rb +169 -0
- data/spec/arbre/unit/element_spec.rb +297 -0
- data/spec/arbre/unit/html/attributes_spec.rb +219 -0
- data/spec/arbre/unit/html/class_list_spec.rb +109 -0
- data/spec/arbre/unit/html/comment_spec.rb +42 -0
- data/spec/arbre/unit/html/querying_spec.rb +32 -0
- data/spec/arbre/unit/html/tag_spec.rb +300 -0
- data/spec/arbre/unit/rails/layouts_spec.rb +127 -0
- data/spec/arbre/unit/text_node_spec.rb +40 -0
- data/spec/rails/app/controllers/example_controller.rb +18 -0
- data/spec/rails/app/views/example/_arbre_partial.html.arb +7 -0
- data/spec/rails/app/views/example/_erb_partial.html.erb +1 -0
- data/spec/rails/app/views/example/arbre.html.arb +1 -0
- data/spec/rails/app/views/example/arbre_partial_result.html.arb +3 -0
- data/spec/rails/app/views/example/erb.html.erb +5 -0
- data/spec/rails/app/views/example/erb_partial_result.html.arb +3 -0
- data/spec/rails/app/views/example/partials.html.arb +11 -0
- data/spec/rails/app/views/layouts/empty.html.arb +1 -0
- data/spec/rails/app/views/layouts/with_title.html.arb +5 -0
- data/spec/rails/config/routes.rb +4 -0
- data/spec/rails_spec_helper.rb +13 -0
- data/spec/spec_helper.rb +20 -0
- data/spec/support/arbre_example_group.rb +19 -0
- metadata +254 -0
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
include Arbre
|
3
|
+
|
4
|
+
describe Context do
|
5
|
+
|
6
|
+
######
|
7
|
+
# Attributes
|
8
|
+
|
9
|
+
it "should not allow a parent to be set" do
|
10
|
+
expect{ Context.new.parent = Element.new }.to raise_error(NotImplementedError)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should always have an indentation level of -1" do
|
14
|
+
context = Context.new
|
15
|
+
expect(context.indent_level).to eql(-1)
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#assigns' do
|
19
|
+
it "should be its own assigns" do
|
20
|
+
expect(Context.new.assigns).to eql({})
|
21
|
+
expect(Context.new(:one => :two).assigns).to eql(:one => :two)
|
22
|
+
end
|
23
|
+
it "should have symbolic keys only" do
|
24
|
+
expect(Context.new('one' => :two).assigns).to eql(:one => :two)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#helpers' do
|
29
|
+
it "should be its own helpers" do
|
30
|
+
expect(Context.new.helpers).to eql(nil)
|
31
|
+
helpers = double()
|
32
|
+
expect(Context.new({}, helpers).helpers).to be(helpers)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
######
|
37
|
+
# Element & flow stack
|
38
|
+
|
39
|
+
let(:context) { Context.new }
|
40
|
+
|
41
|
+
it "should have the context itself as the current element" do
|
42
|
+
expect(context.current_element).to be(context)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should have :append as the current flow" do
|
46
|
+
expect(context.current_flow).to be(:append)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should change the current element and flow temporarily using #with_current" do
|
50
|
+
element1 = Element.new
|
51
|
+
element2 = Element.new
|
52
|
+
|
53
|
+
expect(context.current_element).to be(context)
|
54
|
+
expect(context.current_flow).to be(:append)
|
55
|
+
context.with_current element: element1, flow: :prepend do
|
56
|
+
expect(context.current_element).to be(element1)
|
57
|
+
expect(context.current_flow).to be(:prepend)
|
58
|
+
context.with_current element: element2, flow: [ :after, element1 ] do
|
59
|
+
expect(context.current_element).to be(element2)
|
60
|
+
expect(context.current_flow).to eql([ :after, element1 ])
|
61
|
+
end
|
62
|
+
expect(context.current_element).to be(element1)
|
63
|
+
expect(context.current_flow).to be(:prepend)
|
64
|
+
end
|
65
|
+
expect(context.current_element).to be(context)
|
66
|
+
expect(context.current_flow).to be(:append)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should replace the original element if an error occurs" do
|
70
|
+
begin
|
71
|
+
context.with_current(element: Element.new, flow: :prepend) { raise 'test' }
|
72
|
+
rescue
|
73
|
+
expect(context.current_element).to be(context)
|
74
|
+
expect(context.current_flow).to be(:append)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe '#replace_current_flow' do
|
79
|
+
# Note - this method is for internal purposes only.
|
80
|
+
|
81
|
+
it "should replace the current flow" do
|
82
|
+
element = Element.new
|
83
|
+
|
84
|
+
expect(context.current_flow).to be(:append)
|
85
|
+
context.with_current element: element, flow: :prepend do
|
86
|
+
expect(context.current_flow).to be(:prepend)
|
87
|
+
context.replace_current_flow [ :after, element ]
|
88
|
+
expect(context.current_flow).to eql([:after, element])
|
89
|
+
end
|
90
|
+
expect(context.current_flow).to be(:append)
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
@@ -0,0 +1,300 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
include Arbre
|
3
|
+
|
4
|
+
describe Element::Building do
|
5
|
+
|
6
|
+
# Note - builder methods are specced in integration/element_building_spec.rb.
|
7
|
+
|
8
|
+
let(:element_class) { Class.new(Element) }
|
9
|
+
let(:element) { element_class.new(arbre) }
|
10
|
+
|
11
|
+
######
|
12
|
+
# Build & insert element
|
13
|
+
|
14
|
+
describe '#build' do
|
15
|
+
|
16
|
+
it "should create an element from the given class and build it using the given arguments and block" do
|
17
|
+
block = proc {}
|
18
|
+
|
19
|
+
expect(element_class).to receive(:new).with(arbre).and_return(element)
|
20
|
+
expect(element).to receive(:build!).with(:arg1, :arg2) do |&blk|
|
21
|
+
expect(blk).to be(block)
|
22
|
+
expect(element.current_element).to be(element)
|
23
|
+
end
|
24
|
+
|
25
|
+
result = arbre.build(element_class, :arg1, :arg2, &block)
|
26
|
+
expect(result).to be(element)
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#insert' do
|
32
|
+
|
33
|
+
it "should create an element from the given class, insert it, and build it using the given arguments and block" do
|
34
|
+
block = proc {}
|
35
|
+
parent = Element.new
|
36
|
+
|
37
|
+
expect(element_class).to receive(:new).with(arbre).and_return(element)
|
38
|
+
expect(element).to receive(:build!).with(:arg1, :arg2) do |&blk|
|
39
|
+
# Note: the parent should be known when the build method is called!
|
40
|
+
expect(element.parent).to be(parent)
|
41
|
+
expect(blk).to be(block)
|
42
|
+
expect(element.current_element).to be(element)
|
43
|
+
end
|
44
|
+
|
45
|
+
result = arbre.within(parent) { arbre.insert(element_class, :arg1, :arg2, &block) }
|
46
|
+
expect(result).to be(element)
|
47
|
+
expect(parent.children).to eq([element])
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
######
|
53
|
+
# Within
|
54
|
+
|
55
|
+
describe '#append_within' do
|
56
|
+
it "should call within_element on to arbre_context" do
|
57
|
+
block = proc{}
|
58
|
+
element = Element.new
|
59
|
+
expect(arbre).to receive(:with_current).with(element: element, flow: :append) do |&blk|
|
60
|
+
expect(blk).to be(block)
|
61
|
+
end
|
62
|
+
|
63
|
+
Element.new(arbre).instance_exec do
|
64
|
+
append_within element, &block
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should resolve any string into an element using 'find'" do
|
69
|
+
block = proc{}
|
70
|
+
element = Element.new
|
71
|
+
expect(arbre).to receive(:with_current).with(element: element, flow: :append)
|
72
|
+
|
73
|
+
context_element = Element.new(arbre)
|
74
|
+
expect(context_element).to receive(:find).with('fieldset#username').and_return([element])
|
75
|
+
context_element.instance_exec do
|
76
|
+
within 'fieldset#username', &block
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe '#prepend_within' do
|
82
|
+
it "should call within and with_flow(:prepend) on the context" do
|
83
|
+
block = proc {}
|
84
|
+
element = Element.new
|
85
|
+
expect(arbre).to receive(:with_current).with(element: element, flow: :prepend) do |&blk|
|
86
|
+
expect(blk).to be(block)
|
87
|
+
end
|
88
|
+
|
89
|
+
Element.new(arbre).instance_exec do
|
90
|
+
prepend_within element, &block
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should resolve any string into an element using 'find'" do
|
95
|
+
block = proc{}
|
96
|
+
element = Element.new
|
97
|
+
expect(arbre).to receive(:with_current).with(element: element, flow: :prepend)
|
98
|
+
|
99
|
+
context_element = Element.new(arbre)
|
100
|
+
expect(context_element).to receive(:find).with('fieldset#username').and_return([element])
|
101
|
+
context_element.instance_exec do
|
102
|
+
prepend_within 'fieldset#username', &block
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
######
|
108
|
+
# Append / prepend
|
109
|
+
|
110
|
+
describe '#append' do
|
111
|
+
|
112
|
+
it "should insert an element of the given class using the :append flow" do
|
113
|
+
block = proc {}
|
114
|
+
expect(arbre).to receive(:insert).with(element_class, :one, :two) do |&blk|
|
115
|
+
expect(blk).to be(block)
|
116
|
+
expect(arbre.current_flow).to be(:append)
|
117
|
+
end
|
118
|
+
|
119
|
+
arbre.append element_class, :one, :two, &block
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should run the given block :append flow if no block is given" do
|
123
|
+
block = proc do
|
124
|
+
expect(arbre.current_flow).to be(:append)
|
125
|
+
end
|
126
|
+
|
127
|
+
arbre.append &block
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
describe '#prepend' do
|
133
|
+
|
134
|
+
it "should insert an element of the given class using the :prepend flow" do
|
135
|
+
block = proc {}
|
136
|
+
expect(arbre).to receive(:insert).with(element_class, :one, :two) do |&blk|
|
137
|
+
expect(blk).to be(block)
|
138
|
+
expect(arbre.current_flow).to be(:prepend)
|
139
|
+
end
|
140
|
+
|
141
|
+
arbre.prepend element_class, :one, :two, &block
|
142
|
+
end
|
143
|
+
|
144
|
+
it "should run the given block :prepend flow if no block is given" do
|
145
|
+
block = proc do
|
146
|
+
expect(arbre.current_flow).to be(:prepend)
|
147
|
+
end
|
148
|
+
|
149
|
+
arbre.prepend &block
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
|
154
|
+
######
|
155
|
+
# After / before
|
156
|
+
|
157
|
+
describe '#after' do
|
158
|
+
let(:parent) { Element.new }
|
159
|
+
let(:element) { Element.new }
|
160
|
+
before { parent << element }
|
161
|
+
|
162
|
+
it "should insert an element of the given class using the :after flow" do
|
163
|
+
block = proc {}
|
164
|
+
expect(arbre).to receive(:insert).with(element_class, :one, :two) do |&blk|
|
165
|
+
expect(blk).to be(block)
|
166
|
+
expect(arbre.current_element).to be(parent)
|
167
|
+
expect(arbre.current_flow).to eql([:after, element])
|
168
|
+
end
|
169
|
+
|
170
|
+
arbre.after element, element_class, :one, :two, &block
|
171
|
+
end
|
172
|
+
|
173
|
+
it "should run the given block :after flow if no block is given" do
|
174
|
+
block = proc do
|
175
|
+
expect(arbre.current_flow).to eql([:after, element])
|
176
|
+
end
|
177
|
+
|
178
|
+
arbre.after element, &block
|
179
|
+
end
|
180
|
+
|
181
|
+
end
|
182
|
+
|
183
|
+
describe '#before' do
|
184
|
+
let(:parent) { Element.new }
|
185
|
+
let(:element) { Element.new }
|
186
|
+
before { parent << element }
|
187
|
+
|
188
|
+
it "should insert an element of the given class using the :before flow" do
|
189
|
+
block = proc {}
|
190
|
+
expect(arbre).to receive(:insert).with(element_class, :one, :two) do |&blk|
|
191
|
+
expect(blk).to be(block)
|
192
|
+
expect(arbre.current_element).to be(parent)
|
193
|
+
expect(arbre.current_flow).to eql([:before, element])
|
194
|
+
end
|
195
|
+
|
196
|
+
arbre.before element, element_class, :one, :two, &block
|
197
|
+
end
|
198
|
+
|
199
|
+
it "should run the given block :before flow if no block is given" do
|
200
|
+
block = proc do
|
201
|
+
expect(arbre.current_flow).to eql([:before, element])
|
202
|
+
end
|
203
|
+
|
204
|
+
arbre.before element, &block
|
205
|
+
end
|
206
|
+
|
207
|
+
end
|
208
|
+
|
209
|
+
######
|
210
|
+
# Insert child
|
211
|
+
|
212
|
+
describe '#insert_child' do
|
213
|
+
|
214
|
+
let(:element) { Element.new(arbre) }
|
215
|
+
let(:existing) { Element.new(arbre) }
|
216
|
+
let(:child) { Element.new(arbre) }
|
217
|
+
|
218
|
+
context "flow :append" do
|
219
|
+
before { allow(arbre).to receive(:current_flow).and_return(:append) }
|
220
|
+
|
221
|
+
it "should add the child to the element" do
|
222
|
+
expect(element.children).to receive(:<<).with(child)
|
223
|
+
element.insert_child child
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
context "flow :prepend" do
|
228
|
+
before { allow(arbre).to receive(:current_flow).and_return(:prepend) }
|
229
|
+
|
230
|
+
it "should insert the child at the beginning of the element's children" do
|
231
|
+
expect(element.children).to receive(:insert_at).with(0, child)
|
232
|
+
element.insert_child child
|
233
|
+
end
|
234
|
+
|
235
|
+
it "should change the flow after inserting the first element" do
|
236
|
+
expect(element.children).to receive(:insert_at).with(0, child)
|
237
|
+
expect(arbre).to receive(:replace_current_flow).with([ :after, child ])
|
238
|
+
element.insert_child child
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
context "flow :after" do
|
243
|
+
before { allow(arbre).to receive(:current_flow).and_return([:after, existing]) }
|
244
|
+
|
245
|
+
it "should insert the child after the existing child" do
|
246
|
+
expect(element.children).to receive(:insert_after).with(existing, child)
|
247
|
+
element.insert_child child
|
248
|
+
end
|
249
|
+
|
250
|
+
it "should change the flow after inserting the first element" do
|
251
|
+
expect(element.children).to receive(:insert_after).with(existing, child)
|
252
|
+
expect(arbre).to receive(:replace_current_flow).with([ :after, child ])
|
253
|
+
element.insert_child child
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
context "flow :before" do
|
258
|
+
before { allow(arbre).to receive(:current_flow).and_return([:before, existing]) }
|
259
|
+
|
260
|
+
it "should insert the child before the existing child" do
|
261
|
+
expect(element.children).to receive(:insert_before).with(existing, child)
|
262
|
+
element.insert_child child
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
end
|
267
|
+
|
268
|
+
|
269
|
+
######
|
270
|
+
# Support
|
271
|
+
|
272
|
+
describe '#temporary' do
|
273
|
+
it "should build an element with the given block and return it" do
|
274
|
+
block = proc {}
|
275
|
+
expect(arbre).to receive(:build).with(Element) do |&blk|
|
276
|
+
expect(blk).to be(block)
|
277
|
+
element
|
278
|
+
end
|
279
|
+
expect(arbre.temporary(&block)).to be(element)
|
280
|
+
expect(element).to be_orphan
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
it "should delegate #current_element to the context" do
|
285
|
+
current_element = Element.new
|
286
|
+
expect(arbre).to receive(:current_element).and_return(current_element)
|
287
|
+
|
288
|
+
element = Element.new(arbre)
|
289
|
+
expect(element.current_element).to be(current_element)
|
290
|
+
end
|
291
|
+
|
292
|
+
it "should delegate #current_flow to the context" do
|
293
|
+
current_flow = double(:flow)
|
294
|
+
expect(arbre).to receive(:current_flow).and_return(current_flow)
|
295
|
+
|
296
|
+
element = Element.new(arbre)
|
297
|
+
expect(element.current_flow).to be(current_flow)
|
298
|
+
end
|
299
|
+
|
300
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
include Arbre
|
3
|
+
|
4
|
+
describe ElementCollection do
|
5
|
+
|
6
|
+
######
|
7
|
+
# Collection stuff
|
8
|
+
|
9
|
+
let(:element1) { Element.new }
|
10
|
+
let(:element2) { Element.new }
|
11
|
+
let(:element3) { Element.new }
|
12
|
+
|
13
|
+
it "should initialize as an empty collection by default" do
|
14
|
+
elements = ElementCollection.new
|
15
|
+
expect(elements).to be_empty
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should behave like an array" do
|
19
|
+
elements = ElementCollection.new([element1])
|
20
|
+
expect(elements).to have(1).item
|
21
|
+
expect(elements[0]).to be(element1)
|
22
|
+
|
23
|
+
elements << element2
|
24
|
+
expect(elements).to have(2).item
|
25
|
+
expect(elements[0]).to be(element1)
|
26
|
+
expect(elements[1]).to be(element2)
|
27
|
+
|
28
|
+
elements = ElementCollection.new
|
29
|
+
elements.concat [ element1, element2 ]
|
30
|
+
expect(elements).to have(2).item
|
31
|
+
expect(elements[0]).to be(element1)
|
32
|
+
expect(elements[1]).to be(element2)
|
33
|
+
|
34
|
+
elements.clear
|
35
|
+
expect(elements).to be_empty
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should wrap any enumerable indexing result in another element collection" do
|
39
|
+
collection = ElementCollection.new([element1, element2, element3])
|
40
|
+
|
41
|
+
expect(collection[0]).to be_a(Element)
|
42
|
+
|
43
|
+
expect(collection[0..1]).to be_a(ElementCollection)
|
44
|
+
expect(collection[0..1]).to have(2).items
|
45
|
+
expect(collection[0..1][0]).to be(element1)
|
46
|
+
expect(collection[0..1][1]).to be(element2)
|
47
|
+
|
48
|
+
expect(collection[0, 1]).to be_a(ElementCollection)
|
49
|
+
expect(collection[0, 1]).to have(1).items
|
50
|
+
expect(collection[0, 1][0]).to be(element1)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should equate to an array" do
|
54
|
+
expect(ElementCollection.new([element1, element2])).to eq([element1, element2])
|
55
|
+
expect(ElementCollection.new([element1, element2])).not_to eq([element2, element1])
|
56
|
+
expect(ElementCollection.new([element1, element2])).not_to eq([element1])
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should equate to another collection with the same elements" do
|
60
|
+
collection = ElementCollection.new([element1, element2])
|
61
|
+
expect(collection).to eq(ElementCollection.new([element1, element2]))
|
62
|
+
expect(collection).not_to eq(ElementCollection.new([element2, element1]))
|
63
|
+
expect(collection).not_to eq(ElementCollection.new([element1]))
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should not be eql? an array" do
|
67
|
+
expect(ElementCollection.new([element1, element2])).not_to eql([element1, element2])
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should be eql? to another collection with the same elements" do
|
71
|
+
collection = ElementCollection.new([element1, element2])
|
72
|
+
expect(collection).to eq(ElementCollection.new([element1, element2]))
|
73
|
+
expect(collection).not_to eq(ElementCollection.new([element2, element1]))
|
74
|
+
expect(collection).not_to eq(ElementCollection.new([element1]))
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should rename 'delete' to 'remove'" do
|
78
|
+
elements = ElementCollection.new([element1, element2])
|
79
|
+
elements.remove element2
|
80
|
+
expect(elements).to eq([element1])
|
81
|
+
end
|
82
|
+
|
83
|
+
describe '#+' do
|
84
|
+
|
85
|
+
it "should combine itself with another collection" do
|
86
|
+
collection1 = ElementCollection.new([element1, element2])
|
87
|
+
collection2 = ElementCollection.new([element2, element3])
|
88
|
+
expect(collection1 + collection2).to be_a(ElementCollection)
|
89
|
+
expect(collection1 + collection2).to eq([element1, element2, element3])
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should combine itself with an array" do
|
93
|
+
collection = ElementCollection.new([element1, element2])
|
94
|
+
expect(collection + [element2, element3]).to be_a(ElementCollection)
|
95
|
+
expect(collection + [element2, element3]).to eq([element1, element2, element3])
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
describe '#-' do
|
101
|
+
|
102
|
+
it "should subtract another collection from itself" do
|
103
|
+
collection1 = ElementCollection.new([element1, element2])
|
104
|
+
collection2 = ElementCollection.new([element2, element3])
|
105
|
+
expect(collection1 - collection2).to be_a(ElementCollection)
|
106
|
+
expect(collection1 - collection2).to eq([element1])
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should combine itself with an array" do
|
110
|
+
collection = ElementCollection.new([element1, element2])
|
111
|
+
expect(collection - [element2, element3]).to be_a(ElementCollection)
|
112
|
+
expect(collection - [element2, element3]).to eq([element1])
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
describe '#&' do
|
118
|
+
|
119
|
+
it "should intersect itself with another collection" do
|
120
|
+
collection1 = ElementCollection.new([element1, element2])
|
121
|
+
collection2 = ElementCollection.new([element2, element3])
|
122
|
+
expect(collection1 & collection2).to be_a(ElementCollection)
|
123
|
+
expect(collection1 & collection2).to eq([element2])
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should intersect itself with an array" do
|
127
|
+
collection = ElementCollection.new([element1, element2])
|
128
|
+
expect(collection & [element2, element3]).to be_a(ElementCollection)
|
129
|
+
expect(collection & [element2, element3]).to eq([element2])
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should not add the same element more than once" do
|
135
|
+
collection = ElementCollection.new
|
136
|
+
element = Element.new
|
137
|
+
collection << element << element
|
138
|
+
expect(collection).to have(1).element
|
139
|
+
end
|
140
|
+
|
141
|
+
specify "#to_a should create a copy of the elements and #to_ary not" do
|
142
|
+
collection = ElementCollection.new([element1, element2])
|
143
|
+
expect(collection.to_ary).to be(collection.to_ary)
|
144
|
+
expect(collection.to_a).not_to be(collection.to_a)
|
145
|
+
expect(collection.to_a).to eql(collection.to_a)
|
146
|
+
end
|
147
|
+
|
148
|
+
######
|
149
|
+
# Rendering
|
150
|
+
|
151
|
+
describe '#to_s' do
|
152
|
+
|
153
|
+
let(:collection) { ElementCollection.new([element1, element2]) }
|
154
|
+
|
155
|
+
it "should join all elements' to_s result with a return" do
|
156
|
+
expect(element1).to receive(:to_s).and_return('(ELEMENT1)')
|
157
|
+
expect(element2).to receive(:to_s).and_return('(ELEMENT2)')
|
158
|
+
expect(collection.to_s).to eql("(ELEMENT1)\n(ELEMENT2)")
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should be HTML-safe" do
|
162
|
+
expect(element1).to receive(:to_s).and_return('<span>')
|
163
|
+
expect(element2).to receive(:to_s).and_return('<span>'.html_safe)
|
164
|
+
expect(collection.to_s).to eql("<span>\n<span>")
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|