arbre2 2.1.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 +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
|