arbre2 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
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