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.
Files changed (76) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +30 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +6 -0
  6. data/CHANGELOG.md +75 -0
  7. data/Gemfile +2 -0
  8. data/Gemfile.lock +93 -0
  9. data/LICENSE +20 -0
  10. data/README.md +92 -0
  11. data/Rakefile +7 -0
  12. data/arbre.gemspec +28 -0
  13. data/lib/arbre/child_element_collection.rb +86 -0
  14. data/lib/arbre/container.rb +20 -0
  15. data/lib/arbre/context.rb +83 -0
  16. data/lib/arbre/element/building.rb +151 -0
  17. data/lib/arbre/element.rb +194 -0
  18. data/lib/arbre/element_collection.rb +93 -0
  19. data/lib/arbre/html/attributes.rb +91 -0
  20. data/lib/arbre/html/class_list.rb +53 -0
  21. data/lib/arbre/html/comment.rb +47 -0
  22. data/lib/arbre/html/document.rb +93 -0
  23. data/lib/arbre/html/html_tags.rb +67 -0
  24. data/lib/arbre/html/querying.rb +256 -0
  25. data/lib/arbre/html/tag.rb +317 -0
  26. data/lib/arbre/rails/layouts.rb +126 -0
  27. data/lib/arbre/rails/legacy_document.rb +29 -0
  28. data/lib/arbre/rails/rendering.rb +76 -0
  29. data/lib/arbre/rails/rspec/arbre_support.rb +61 -0
  30. data/lib/arbre/rails/rspec.rb +2 -0
  31. data/lib/arbre/rails/template_handler.rb +32 -0
  32. data/lib/arbre/rails.rb +35 -0
  33. data/lib/arbre/rspec/be_rendered_as_matcher.rb +103 -0
  34. data/lib/arbre/rspec/be_scripted_as_matcher.rb +68 -0
  35. data/lib/arbre/rspec/contain_script_matcher.rb +64 -0
  36. data/lib/arbre/rspec.rb +3 -0
  37. data/lib/arbre/text_node.rb +35 -0
  38. data/lib/arbre/version.rb +3 -0
  39. data/lib/arbre.rb +27 -0
  40. data/spec/arbre/integration/html_document_spec.rb +90 -0
  41. data/spec/arbre/integration/html_spec.rb +283 -0
  42. data/spec/arbre/integration/querying_spec.rb +187 -0
  43. data/spec/arbre/integration/rails_spec.rb +183 -0
  44. data/spec/arbre/rails/rspec/arbre_support_spec.rb +75 -0
  45. data/spec/arbre/rspec/be_rendered_as_matcher_spec.rb +80 -0
  46. data/spec/arbre/rspec/be_scripted_as_matcher_spec.rb +61 -0
  47. data/spec/arbre/rspec/contain_script_matcher_spec.rb +40 -0
  48. data/spec/arbre/support/arbre_example_group.rb +0 -0
  49. data/spec/arbre/unit/child_element_collection_spec.rb +146 -0
  50. data/spec/arbre/unit/container_spec.rb +23 -0
  51. data/spec/arbre/unit/context_spec.rb +95 -0
  52. data/spec/arbre/unit/element/building_spec.rb +300 -0
  53. data/spec/arbre/unit/element_collection_spec.rb +169 -0
  54. data/spec/arbre/unit/element_spec.rb +297 -0
  55. data/spec/arbre/unit/html/attributes_spec.rb +219 -0
  56. data/spec/arbre/unit/html/class_list_spec.rb +109 -0
  57. data/spec/arbre/unit/html/comment_spec.rb +42 -0
  58. data/spec/arbre/unit/html/querying_spec.rb +32 -0
  59. data/spec/arbre/unit/html/tag_spec.rb +300 -0
  60. data/spec/arbre/unit/rails/layouts_spec.rb +127 -0
  61. data/spec/arbre/unit/text_node_spec.rb +40 -0
  62. data/spec/rails/app/controllers/example_controller.rb +18 -0
  63. data/spec/rails/app/views/example/_arbre_partial.html.arb +7 -0
  64. data/spec/rails/app/views/example/_erb_partial.html.erb +1 -0
  65. data/spec/rails/app/views/example/arbre.html.arb +1 -0
  66. data/spec/rails/app/views/example/arbre_partial_result.html.arb +3 -0
  67. data/spec/rails/app/views/example/erb.html.erb +5 -0
  68. data/spec/rails/app/views/example/erb_partial_result.html.arb +3 -0
  69. data/spec/rails/app/views/example/partials.html.arb +11 -0
  70. data/spec/rails/app/views/layouts/empty.html.arb +1 -0
  71. data/spec/rails/app/views/layouts/with_title.html.arb +5 -0
  72. data/spec/rails/config/routes.rb +4 -0
  73. data/spec/rails_spec_helper.rb +13 -0
  74. data/spec/spec_helper.rb +20 -0
  75. data/spec/support/arbre_example_group.rb +19 -0
  76. metadata +254 -0
@@ -0,0 +1,90 @@
1
+ require 'spec_helper'
2
+ include Arbre::Html
3
+
4
+ describe Document do
5
+
6
+ it "should by default be rendered as an empty document" do
7
+ arbre.append Document
8
+
9
+ expect(arbre).to be_rendered_as(<<-HTML)
10
+ <!DOCTYPE html>
11
+
12
+ <html>
13
+ <head>
14
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
15
+ </head>
16
+ <body>
17
+ </body>
18
+ </html>
19
+ HTML
20
+ end
21
+
22
+ it "should allow content to be appended to the head using the #head method" do
23
+ arbre do
24
+ append Document do |doc|
25
+ doc.head { title "My Title" }
26
+ end
27
+ end
28
+
29
+ expect(arbre).to be_rendered_as(<<-HTML)
30
+ <!DOCTYPE html>
31
+
32
+ <html>
33
+ <head>
34
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
35
+ <title>My Title</title>
36
+ </head>
37
+ <body>
38
+ </body>
39
+ </html>
40
+ HTML
41
+ end
42
+
43
+ it "should allow content to be appended to the body using the #body method" do
44
+ arbre do
45
+ append Document do |doc|
46
+ doc.body { div 'Content Area' }
47
+ end
48
+ end
49
+
50
+ expect(arbre).to be_rendered_as(<<-HTML)
51
+ <!DOCTYPE html>
52
+
53
+ <html>
54
+ <head>
55
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
56
+ </head>
57
+ <body>
58
+ <div>Content Area</div>
59
+ </body>
60
+ </html>
61
+ HTML
62
+ end
63
+
64
+ it "should allow setting the title through a property" do
65
+ arbre do
66
+ append Document do |doc|
67
+ doc.title = 'My Title'
68
+ end
69
+ end
70
+
71
+ expect(arbre.find('head')).to be_rendered_as(<<-HTML)
72
+ <head>
73
+ <title>My Title</title>
74
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
75
+ </head>
76
+ HTML
77
+ end
78
+
79
+ it "should allow getting the title through an attribute" do
80
+ arbre do
81
+ append Document do |doc|
82
+ doc.head { title "My Title" }
83
+ end
84
+ end
85
+
86
+ document = arbre.children[0]
87
+ expect(document.title).to eql('My Title')
88
+ end
89
+
90
+ end
@@ -0,0 +1,283 @@
1
+ require 'spec_helper'
2
+
3
+ describe Arbre do
4
+
5
+ let(:helpers) { double(:helpers) }
6
+ let(:assigns) { {} }
7
+
8
+ it "should render a single element" do
9
+ arbre { span "Hello World" }
10
+ expect(arbre).to be_rendered_as("<span>Hello World</span>")
11
+ end
12
+
13
+ it "should access assigns through instance variables" do
14
+ assigns[:my_var] = 'Hello World'
15
+ arbre { span @my_var }
16
+ expect(arbre).to be_rendered_as("<span>Hello World</span>")
17
+ end
18
+
19
+ it "should allow access to helper methods" do
20
+ expect(helpers).to receive(:my_helper).and_return('Hello World')
21
+ arbre { span my_helper }
22
+ expect(arbre).to be_rendered_as("<span>Hello World</span>")
23
+ end
24
+
25
+ it "should render a child element" do
26
+ arbre do
27
+ span do
28
+ span "Hello World"
29
+ end
30
+ end
31
+
32
+ expect(arbre).to be_rendered_as(<<-HTML)
33
+ <span>
34
+ <span>Hello World</span>
35
+ </span>
36
+ HTML
37
+ end
38
+
39
+ it "should render an unordered list" do
40
+ arbre do
41
+ ul do
42
+ li "First"
43
+ li "Second"
44
+ li "Third"
45
+ end
46
+ end
47
+
48
+ expect(arbre).to be_rendered_as(<<-HTML)
49
+ <ul>
50
+ <li>First</li>
51
+ <li>Second</li>
52
+ <li>Third</li>
53
+ </ul>
54
+ HTML
55
+ end
56
+
57
+ it "should allow local variables inside the tags" do
58
+ arbre do
59
+ first = "First"
60
+ second = "Second"
61
+ ul do
62
+ li first
63
+ li second
64
+ end
65
+ end
66
+
67
+ expect(arbre).to be_rendered_as(<<-HTML)
68
+ <ul>
69
+ <li>First</li>
70
+ <li>Second</li>
71
+ </ul>
72
+ HTML
73
+ end
74
+
75
+ it "should add children and nested" do
76
+ arbre do
77
+ div do
78
+ ul
79
+ li do
80
+ li
81
+ end
82
+ end
83
+ end
84
+
85
+ expect(arbre).to be_rendered_as(<<-HTML)
86
+ <div>
87
+ <ul></ul>
88
+ <li>
89
+ <li></li>
90
+ </li>
91
+ </div>
92
+ HTML
93
+ end
94
+
95
+ it "should allow flow" do
96
+ arbre do
97
+ div do
98
+ span2 = span('Span 2')
99
+ span1 = prepend { span 'Span 1' }
100
+ span4 = after(span2) { span 'Span 4' }
101
+ before(span4) { span 'Span 3' }
102
+ span 'Span 5'
103
+ end
104
+ end
105
+
106
+ expect(arbre).to be_rendered_as(<<-HTML)
107
+ <div>
108
+ <span>Span 1</span>
109
+ <span>Span 2</span>
110
+ <span>Span 3</span>
111
+ <span>Span 4</span>
112
+ <span>Span 5</span>
113
+ </div>
114
+ HTML
115
+ end
116
+
117
+ it "should allow adding elements relative to others using queries" do
118
+ arbre do
119
+ div1 = div(:class => 'div1')
120
+
121
+ within('.div1') { span 'Span 1.1', :id => 'my-span' }
122
+ after('.div1 > #my-span') { span 'Span 1.2' }
123
+ end
124
+
125
+ expect(arbre).to be_rendered_as(<<-HTML)
126
+ <div class="div1">
127
+ <span id="my-span">Span 1.1</span>
128
+ <span>Span 1.2</span>
129
+ </div>
130
+ HTML
131
+ end
132
+
133
+ it "should pass the element in to the block if asked for" do
134
+ arbre do
135
+ div do |d|
136
+ d.ul do
137
+ li
138
+ end
139
+ end
140
+ end
141
+
142
+ expect(arbre).to be_rendered_as(<<-HTML)
143
+ <div>
144
+ <ul>
145
+ <li></li>
146
+ </ul>
147
+ </div>
148
+ HTML
149
+ end
150
+
151
+
152
+ it "should move content tags between parents" do
153
+ arbre do
154
+ div do
155
+ span(ul(li))
156
+ end
157
+ end
158
+
159
+ expect(arbre).to be_rendered_as(<<-HTML)
160
+ <div>
161
+ <span>
162
+ <ul>
163
+ <li></li>
164
+ </ul>
165
+ </span>
166
+ </div>
167
+ HTML
168
+ end
169
+
170
+ it "should add content to the parent if the element is passed into block" do
171
+ arbre do
172
+ div do |d|
173
+ d.id = "my-tag"
174
+ ul do
175
+ li
176
+ end
177
+ end
178
+ end
179
+
180
+ expect(arbre).to be_rendered_as(<<-HTML)
181
+ <div id="my-tag">
182
+ <ul>
183
+ <li></li>
184
+ </ul>
185
+ </div>
186
+ HTML
187
+ end
188
+
189
+ it "should have the parent set on it" do
190
+ item = nil
191
+ list = nil
192
+
193
+ arbre do
194
+ list = ul do
195
+ li "Hello"
196
+ item = li("World")
197
+ end
198
+ end
199
+
200
+ expect(item.parent).to be(list)
201
+ end
202
+
203
+ describe "html safe" do
204
+
205
+ it "should escape the contents" do
206
+ arbre do
207
+ span("<br />")
208
+ end
209
+
210
+ expect(arbre).to be_rendered_as(<<-HTML)
211
+ <span>&lt;br /&gt;</span>
212
+ HTML
213
+ end
214
+
215
+ it "should return html safe strings" do
216
+ arbre do
217
+ span("<br />")
218
+ end
219
+
220
+ expect(arbre.to_s).to be_html_safe
221
+ end
222
+
223
+ it "should not escape html passed in" do
224
+ arbre do
225
+ span(span("<br />"))
226
+ end
227
+
228
+ expect(arbre).to be_rendered_as(<<-HTML)
229
+ <span>
230
+ <span>&lt;br /&gt;</span>
231
+ </span>
232
+ HTML
233
+ end
234
+
235
+ it "should escape the contents of attributes" do
236
+ arbre do
237
+ span(:class => "<br />")
238
+ end
239
+
240
+ expect(arbre).to be_rendered_as(<<-HTML)
241
+ <span class="&lt;br /&gt;"></span>
242
+ HTML
243
+ end
244
+
245
+ end
246
+
247
+
248
+ describe 'indentation' do
249
+
250
+ # All specs in this file use the be_rendered_as matcher, which ignores whitespace. These specs are explicitly
251
+ # designed to exemplify the indentation pattern.
252
+
253
+ it "should use proper indentation" do
254
+ arbre { div(span('Test')) }
255
+
256
+ expect(arbre.to_s).to eql(<<-HTML.gsub(/^ {8}/, '').chomp)
257
+ <div>
258
+ <span>Test</span>
259
+ </div>
260
+ HTML
261
+ end
262
+
263
+ it "should not indent containers" do
264
+ arbre do
265
+ div do
266
+ append Arbre::Container do
267
+ span 'One'
268
+ span 'Two'
269
+ end
270
+ end
271
+ end
272
+
273
+ expect(arbre.to_s).to eql(<<-HTML.gsub(/^ {8}/, '').chomp)
274
+ <div>
275
+ <span>One</span>
276
+ <span>Two</span>
277
+ </div>
278
+ HTML
279
+ end
280
+
281
+ end
282
+
283
+ end
@@ -0,0 +1,187 @@
1
+ require 'spec_helper'
2
+ include Arbre
3
+
4
+ describe Arbre::Html::Querying do
5
+
6
+ let(:arbre) do
7
+ Arbre::Context.new do
8
+ div :id => 'one'
9
+ div :id => 'two' do
10
+ a 'Link 1', :href => '/', :class => 'one two'
11
+
12
+ input :type => :checkbox, 'data-attribute' => 'some_value'
13
+ input :type => 'file'
14
+
15
+ insert Container do
16
+ span :id => 'in_container'
17
+ a 'Link 2', :href => '/blah', :class => 'external two', :target => '_blank'
18
+ end
19
+ end
20
+ div :id => 'three' do
21
+ a 'Link 3', :class => 'three'
22
+
23
+ div do
24
+ a 'Link 4', :class => 'four'
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ describe Arbre::Html::Query do
31
+
32
+ it "should find all descendants using the '*' selector" do
33
+ elements = "[<div#one>, <div#two>, <a.one.two>, <input[type=checkbox]>, <input[type=file]>, <span#in_container>, <a.external.two>, <div#three>, <a.three>, <div>, <a.four>]"
34
+ expect(arbre.find('*').to_a.inspect).to eql(elements)
35
+ end
36
+
37
+ it "should find all links using 'a'" do
38
+ result = arbre.find('a')
39
+ expect(result.to_a.inspect).to eql('[<a.one.two>, <a.external.two>, <a.three>, <a.four>]')
40
+ end
41
+
42
+ it "should find all external links using 'a.external'" do
43
+ result = arbre.find('a.external')
44
+ expect(result.to_a.inspect).to eql('[<a.external.two>]')
45
+ end
46
+
47
+ it "should find only direct children using a direct child operator" do
48
+ result = arbre.find('div#two > a.external')
49
+ expect(result.to_a.inspect).to eql('[<a.external.two>]')
50
+ end
51
+
52
+ it "should match all given classes" do
53
+ result = arbre.find('a.one.two')
54
+ expect(result.to_a.inspect).to eql('[<a.one.two>]')
55
+ end
56
+
57
+ it "should match multiple selectors" do
58
+ result = arbre.find('div#one, a')
59
+ expect(result.to_a.inspect).to eql('[<div#one>, <a.one.two>, <a.external.two>, <a.three>, <a.four>]')
60
+ end
61
+
62
+ describe 'pseudo selectors' do
63
+
64
+ it "should accept the :first pseudo selector" do
65
+ result = arbre.find('a:first')
66
+ expect(result.to_a.inspect).to eql('[<a.one.two>]')
67
+ end
68
+
69
+ it "should accept the :last pseudo selector" do
70
+ result = arbre.find('a:last')
71
+ expect(result.to_a.inspect).to eql('[<a.four>]')
72
+ end
73
+
74
+ it "should accept the :first-child pseudo selector" do
75
+ result = arbre.find('a:first-child')
76
+ expect(result.to_a.inspect).to eql('[<a.one.two>, <a.three>, <a.four>]')
77
+ end
78
+
79
+ it "should accept the :last-child pseudo selector" do
80
+ result = arbre.find('a:last-child')
81
+ expect(result.to_a.inspect).to eql('[<a.external.two>, <a.four>]')
82
+ end
83
+
84
+ it "should accept multiple pseudo selectors" do
85
+ result = arbre.find('a:first-child:last-child')
86
+ expect(result.to_a.inspect).to eql('[<a.four>]')
87
+ end
88
+
89
+ end
90
+
91
+ describe 'attribute selectors' do
92
+
93
+ it "should accept an attribute selector without a value" do
94
+ result = arbre.find('a[href]')
95
+ expect(result.to_a.inspect).to eql('[<a.one.two>, <a.external.two>]')
96
+ end
97
+
98
+ it "should accept an attribute selector with a value" do
99
+ result = arbre.find('input[type=checkbox]')
100
+ expect(result.to_a.inspect).to eql('[<input[type=checkbox]>]')
101
+ end
102
+
103
+ it "should accept an attribute selector with a dash and a quoted value" do
104
+ result = arbre.find('input[data-attribute="some_value"]')
105
+ expect(result.to_a.inspect).to eql('[<input[type=checkbox]>]')
106
+ end
107
+
108
+ it "should accept multiple attribute selectors" do
109
+ result = arbre.find('a[href="/blah"][target]')
110
+ expect(result.to_a.inspect).to eql('[<a.external.two>]')
111
+ end
112
+
113
+ end
114
+
115
+ it "should allow various selector properties to be combined" do
116
+ result = arbre.find('a.two:last')
117
+ expect(result.to_a.inspect).to eql('[<a.external.two>]')
118
+ end
119
+
120
+ it "should allow a descendant selector" do
121
+ result = arbre.find('#three a')
122
+ expect(result.to_a.inspect).to eql('[<a.three>, <a.four>]')
123
+ end
124
+
125
+ it "should allow a child selector" do
126
+ result = arbre.find('#three > a')
127
+ expect(result.to_a.inspect).to eql('[<a.three>]')
128
+ end
129
+
130
+ it "should find something inside a container" do
131
+ result = arbre.find('#in_container')
132
+ expect(result.to_a.inspect).to eql('[<span#in_container>]')
133
+ end
134
+
135
+ it "should find something 'through' a container" do
136
+ result = arbre.find('#two > #in_container')
137
+ expect(result.to_a.inspect).to eql('[<span#in_container>]')
138
+ end
139
+
140
+ end
141
+
142
+ describe '#descendant_tags' do
143
+
144
+ it "should find all descendant tags" do
145
+ elements = "[<div#one>, <div#two>, <a.one.two>, <input[type=checkbox]>, <input[type=file]>, <span#in_container>, <a.external.two>, <div#three>, <a.three>, <div>, <a.four>]"
146
+ expect(arbre.descendant_tags.to_a.inspect).to eql(elements)
147
+ end
148
+
149
+ end
150
+
151
+ describe '#child_tags' do
152
+
153
+ it "should find all child tags of an element" do
154
+ result = arbre.find_first('#two').child_tags
155
+ expect(result.to_a.inspect).to eql('[<a.one.two>, <input[type=checkbox]>, <input[type=file]>, <span#in_container>, <a.external.two>]')
156
+ end
157
+
158
+ end
159
+
160
+ describe '#find_by_id' do
161
+
162
+ it "should find the first descendant tag with the given ID" do
163
+ result = arbre.find_by_id('two')
164
+ expect(result.inspect).to eql('<div#two>')
165
+ end
166
+
167
+ end
168
+
169
+ describe '#find_by_tag' do
170
+
171
+ it "should find the first descendant tag with the given tag name" do
172
+ result = arbre.find_by_tag('span')
173
+ expect(result.to_a.inspect).to eql('[<span#in_container>]')
174
+ end
175
+
176
+ end
177
+
178
+ describe '#find_by_classes' do
179
+
180
+ it "should find the first descendant tag with the given tag name" do
181
+ result = arbre.find_by_classes(['one', 'two'])
182
+ expect(result.to_a.inspect).to eql('[<a.one.two>]')
183
+ end
184
+
185
+ end
186
+
187
+ end