arbo 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ci.yaml +21 -0
  3. data/.github/workflows/daily.yaml +23 -0
  4. data/.gitignore +11 -0
  5. data/CHANGELOG.md +95 -0
  6. data/CONTRIBUTING.md +3 -0
  7. data/Gemfile +17 -0
  8. data/LICENSE +20 -0
  9. data/README.md +29 -0
  10. data/Rakefile +18 -0
  11. data/arbo.gemspec +25 -0
  12. data/docs/Gemfile +2 -0
  13. data/docs/_config.yml +7 -0
  14. data/docs/_includes/footer.html +8 -0
  15. data/docs/_includes/google-analytics.html +16 -0
  16. data/docs/_includes/head.html +7 -0
  17. data/docs/_includes/toc.html +12 -0
  18. data/docs/_includes/top-menu.html +8 -0
  19. data/docs/_layouts/default.html +21 -0
  20. data/docs/index.md +106 -0
  21. data/docs/stylesheets/main.css +1152 -0
  22. data/lib/arbo/component.rb +22 -0
  23. data/lib/arbo/context.rb +118 -0
  24. data/lib/arbo/element/builder_methods.rb +83 -0
  25. data/lib/arbo/element/proxy.rb +28 -0
  26. data/lib/arbo/element.rb +225 -0
  27. data/lib/arbo/element_collection.rb +31 -0
  28. data/lib/arbo/html/attributes.rb +41 -0
  29. data/lib/arbo/html/class_list.rb +28 -0
  30. data/lib/arbo/html/document.rb +31 -0
  31. data/lib/arbo/html/html5_elements.rb +47 -0
  32. data/lib/arbo/html/tag.rb +220 -0
  33. data/lib/arbo/html/text_node.rb +43 -0
  34. data/lib/arbo/rails/forms.rb +101 -0
  35. data/lib/arbo/rails/rendering.rb +17 -0
  36. data/lib/arbo/rails/template_handler.rb +35 -0
  37. data/lib/arbo/rails.rb +5 -0
  38. data/lib/arbo/version.rb +3 -0
  39. data/lib/arbo.rb +21 -0
  40. data/spec/arbo/integration/html_spec.rb +307 -0
  41. data/spec/arbo/unit/component_spec.rb +54 -0
  42. data/spec/arbo/unit/context_spec.rb +35 -0
  43. data/spec/arbo/unit/element_finder_methods_spec.rb +116 -0
  44. data/spec/arbo/unit/element_spec.rb +272 -0
  45. data/spec/arbo/unit/html/class_list_spec.rb +16 -0
  46. data/spec/arbo/unit/html/tag_attributes_spec.rb +104 -0
  47. data/spec/arbo/unit/html/tag_spec.rb +124 -0
  48. data/spec/arbo/unit/html/text_node_spec.rb +5 -0
  49. data/spec/rails/integration/forms_spec.rb +117 -0
  50. data/spec/rails/integration/rendering_spec.rb +98 -0
  51. data/spec/rails/rails_spec_helper.rb +46 -0
  52. data/spec/rails/stub_app/config/database.yml +3 -0
  53. data/spec/rails/stub_app/config/routes.rb +3 -0
  54. data/spec/rails/stub_app/db/schema.rb +3 -0
  55. data/spec/rails/stub_app/log/.gitignore +1 -0
  56. data/spec/rails/stub_app/public/favicon.ico +0 -0
  57. data/spec/rails/support/mock_person.rb +15 -0
  58. data/spec/rails/templates/arbo/_partial.arb +1 -0
  59. data/spec/rails/templates/arbo/_partial_with_assignment.arb +1 -0
  60. data/spec/rails/templates/arbo/empty.arb +0 -0
  61. data/spec/rails/templates/arbo/page_with_arb_partial_and_assignment.arb +3 -0
  62. data/spec/rails/templates/arbo/page_with_assignment.arb +1 -0
  63. data/spec/rails/templates/arbo/page_with_erb_partial.arb +3 -0
  64. data/spec/rails/templates/arbo/page_with_helpers.arb +7 -0
  65. data/spec/rails/templates/arbo/page_with_partial.arb +3 -0
  66. data/spec/rails/templates/arbo/simple_page.arb +8 -0
  67. data/spec/rails/templates/erb/_partial.erb +1 -0
  68. data/spec/spec_helper.rb +7 -0
  69. data/spec/support/bundle.rb +4 -0
  70. metadata +169 -0
@@ -0,0 +1,307 @@
1
+ require 'spec_helper'
2
+
3
+ describe Arbo do
4
+
5
+ let(:helpers){ nil }
6
+ let(:assigns){ {} }
7
+
8
+ def output_buffer(actx)
9
+ actx.render_in(actx) && actx.output_buffer
10
+ end
11
+
12
+ it "should render a single element" do
13
+ actx = arbo {
14
+ span "Hello World"
15
+ }
16
+ html = "<span>Hello World</span>\n"
17
+ expect(actx.to_s).to eq(html)
18
+ expect(output_buffer actx).to eq(html)
19
+ end
20
+
21
+ it "should render a child element" do
22
+ actx = arbo {
23
+ span do
24
+ span "Hello World"
25
+ end
26
+ }
27
+ html = <<-HTML
28
+ <span>
29
+ <span>Hello World</span>
30
+ </span>
31
+ HTML
32
+ expect(actx.to_s).to eq(html)
33
+ expect(output_buffer actx).to eq(html)
34
+ end
35
+
36
+ it "should render an unordered list" do
37
+ actx = arbo {
38
+ ul do
39
+ li "First"
40
+ li "Second"
41
+ li "Third"
42
+ end
43
+ }
44
+ html = <<-HTML
45
+ <ul>
46
+ <li>First</li>
47
+ <li>Second</li>
48
+ <li>Third</li>
49
+ </ul>
50
+ HTML
51
+ expect(actx.to_s).to eq(html)
52
+ expect(output_buffer actx).to eq(html)
53
+ end
54
+
55
+ it "should allow local variables inside the tags" do
56
+ actx = arbo {
57
+ first = "First"
58
+ second = "Second"
59
+ ul do
60
+ li first
61
+ li second
62
+ end
63
+ }
64
+ html = <<-HTML
65
+ <ul>
66
+ <li>First</li>
67
+ <li>Second</li>
68
+ </ul>
69
+ HTML
70
+ expect(actx.to_s).to eq(html)
71
+ expect(output_buffer actx).to eq(html)
72
+ end
73
+
74
+
75
+ it "should add children and nested" do
76
+ actx = arbo {
77
+ div do
78
+ ul
79
+ li do
80
+ li
81
+ end
82
+ end
83
+ }
84
+ html = <<-HTML
85
+ <div>
86
+ <ul></ul>
87
+ <li>
88
+ <li></li>
89
+ </li>
90
+ </div>
91
+ HTML
92
+ expect(actx.to_s).to eq(html)
93
+ expect(output_buffer actx).to eq(html)
94
+ end
95
+
96
+
97
+ it "should pass the element in to the block if asked for" do
98
+ actx = arbo {
99
+ div do |d|
100
+ d.ul do
101
+ li
102
+ end
103
+ end
104
+ }
105
+ html = <<-HTML
106
+ <div>
107
+ <ul>
108
+ <li></li>
109
+ </ul>
110
+ </div>
111
+ HTML
112
+ expect(actx.to_s).to eq(html)
113
+ expect(output_buffer actx).to eq(html)
114
+ end
115
+
116
+
117
+ it "should move content tags between parents" do
118
+ actx = arbo {
119
+ div do
120
+ span(ul(li))
121
+ end
122
+ }
123
+ html = <<-HTML
124
+ <div>
125
+ <span>
126
+ <ul>
127
+ <li></li>
128
+ </ul>
129
+ </span>
130
+ </div>
131
+ HTML
132
+ expect(actx.to_s).to eq(html)
133
+ expect(output_buffer actx).to eq(html)
134
+ end
135
+
136
+ it "should add content to the parent if the element is passed into block" do
137
+ actx = arbo {
138
+ div do |d|
139
+ d.id = "my-tag"
140
+ ul do
141
+ li
142
+ end
143
+ end
144
+ }
145
+ html = <<-HTML
146
+ <div id="my-tag">
147
+ <ul>
148
+ <li></li>
149
+ </ul>
150
+ </div>
151
+ HTML
152
+ expect(actx.to_s).to eq(html)
153
+ expect(output_buffer actx).to eq(html)
154
+ end
155
+
156
+ it "should have the parent set on it" do
157
+ list, item = nil
158
+ arbo {
159
+ list = ul do
160
+ li "Hello"
161
+ item = li "World"
162
+ end
163
+ }
164
+ expect(item.parent).to eq list
165
+ end
166
+
167
+ it "should set a string content return value with no children" do
168
+ actx = arbo {
169
+ li do
170
+ "Hello World"
171
+ end
172
+ }
173
+ html = <<-HTML
174
+ <li>Hello World</li>
175
+ HTML
176
+ expect(actx.to_s).to eq(html)
177
+ expect(output_buffer actx).to eq(html)
178
+ end
179
+
180
+ it "should turn string return values into text nodes" do
181
+ node = nil
182
+ arbo {
183
+ list = li do
184
+ "Hello World"
185
+ end
186
+ node = list.children.first
187
+ }
188
+ expect(node).to be_a Arbo::HTML::TextNode
189
+ end
190
+
191
+ it "should not render blank arrays" do
192
+ actx = arbo {
193
+ tbody do
194
+ []
195
+ end
196
+ }
197
+ html = <<-HTML
198
+ <tbody></tbody>
199
+ HTML
200
+ expect(actx.to_s).to eq(html)
201
+ expect(output_buffer actx).to eq(html)
202
+ end
203
+
204
+ describe "self-closing nodes" do
205
+
206
+ it "should not self-close script tags" do
207
+ actx = arbo {
208
+ script type: 'text/javascript'
209
+ }
210
+ html = "<script type=\"text/javascript\"></script>\n"
211
+ expect(actx.to_s).to eq(html)
212
+ expect(output_buffer actx).to eq(html)
213
+ end
214
+
215
+ it "should self-close meta tags" do
216
+ actx = arbo {
217
+ meta content: "text/html; charset=utf-8"
218
+ }
219
+ html = "<meta content=\"text/html; charset=utf-8\"/>\n"
220
+ expect(actx.to_s).to eq(html)
221
+ expect(output_buffer actx).to eq(html)
222
+ end
223
+
224
+ it "should self-close link tags" do
225
+ actx = arbo {
226
+ link rel: "stylesheet"
227
+ }
228
+ html = "<link rel=\"stylesheet\"/>\n"
229
+ expect(actx.to_s).to eq(html)
230
+ expect(output_buffer actx).to eq(html)
231
+ end
232
+
233
+ Arbo::HTML::Tag::SELF_CLOSING_ELEMENTS.each do |tag|
234
+ it "should self-close #{tag} tags" do
235
+ actx = arbo {
236
+ send(tag)
237
+ }
238
+ html = "<#{tag}/>\n"
239
+ expect(actx.to_s).to eq(html)
240
+ expect(output_buffer actx).to eq(html)
241
+ end
242
+ end
243
+
244
+ end
245
+
246
+ describe "html safe" do
247
+
248
+ it "should escape the contents" do
249
+ actx = arbo {
250
+ span("<br />")
251
+ }
252
+ html = <<-HTML
253
+ <span>&lt;br /&gt;</span>
254
+ HTML
255
+ expect(actx.to_s).to eq(html)
256
+ expect(output_buffer actx).to eq(html)
257
+ end
258
+
259
+ it "should return html safe strings" do
260
+ expect(arbo {
261
+ span("<br />")
262
+ }.to_s).to be_html_safe
263
+ end
264
+
265
+ it "should not escape html passed in" do
266
+ actx = arbo {
267
+ span(span("<br />"))
268
+ }
269
+ html = <<-HTML
270
+ <span>
271
+ <span>&lt;br /&gt;</span>
272
+ </span>
273
+ HTML
274
+ expect(actx.to_s).to eq(html)
275
+ expect(output_buffer actx).to eq(html)
276
+ end
277
+
278
+ it "should escape string contents when passed in block" do
279
+ actx = arbo {
280
+ span {
281
+ span {
282
+ "<br />"
283
+ }
284
+ }
285
+ }
286
+ html = <<-HTML
287
+ <span>
288
+ <span>&lt;br /&gt;</span>
289
+ </span>
290
+ HTML
291
+ expect(actx.to_s).to eq(html)
292
+ expect(output_buffer actx).to eq(html)
293
+ end
294
+
295
+ it "should escape the contents of attributes" do
296
+ actx = arbo {
297
+ span(class: "<br />")
298
+ }
299
+ html = <<-HTML
300
+ <span class="&lt;br /&gt;"></span>
301
+ HTML
302
+ expect(actx.to_s).to eq(html)
303
+ end
304
+
305
+ end
306
+
307
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ # A mock subclass to play with
4
+ class MockComponent < Arbo::Component
5
+
6
+ builder_method :mock_component
7
+
8
+ def build
9
+ h2 "Hello World"
10
+ end
11
+
12
+ end
13
+
14
+ describe Arbo::Component do
15
+
16
+ let(:assigns) { {} }
17
+ let(:helpers) { nil }
18
+
19
+ let(:component_class){ MockComponent }
20
+ let(:component){ component_class.new }
21
+
22
+ it "should be a subclass of an html div" do
23
+ expect(Arbo::Component.ancestors).to include(Arbo::HTML::Div)
24
+ end
25
+
26
+ it "should render to a div, even as a subclass" do
27
+ expect(component.tag_name).to eq('div')
28
+ end
29
+
30
+ it "should add a class by default" do
31
+ expect(component.class_list).to include("mock_component")
32
+ end
33
+
34
+ it "should render (to_s) the object using the builder method name" do
35
+ comp = expect(arbo {
36
+ mock_component
37
+ }.to_s).to eq <<-HTML
38
+ <div class="mock_component">
39
+ <h2>Hello World</h2>
40
+ </div>
41
+ HTML
42
+ end
43
+
44
+ it "should render (render_in) the object using the builder method name" do
45
+ context = arbo { mock_component }
46
+ output_buffer = context.render_in(context)
47
+
48
+ expect(output_buffer).to eq <<-HTML
49
+ <div class="mock_component">
50
+ <h2>Hello World</h2>
51
+ </div>
52
+ HTML
53
+ end
54
+ end
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe Arbo::Context do
5
+
6
+ let(:context) do
7
+ Arbo::Context.new do
8
+ h1 "札幌市北区" # Add some HTML to the context
9
+ end
10
+ end
11
+
12
+ it "should not increment the indent_level" do
13
+ expect(context.indent_level).to eq(-1)
14
+ end
15
+
16
+ it "should return a bytesize" do
17
+ expect(context.bytesize).to eq(25)
18
+ end
19
+
20
+ it "should return a length" do
21
+ expect(context.length).to eq(25)
22
+ end
23
+
24
+ it "should delegate missing methods to the html string" do
25
+ expect(context).to respond_to(:index)
26
+ expect(context.index('<')).to eq(0)
27
+ end
28
+
29
+ it "should use a cached version of the HTML for method delegation" do
30
+ expect(context).to receive(:render_in).once.and_return("<h1>札幌市北区</h1>")
31
+ expect(context.index('<')).to eq(0)
32
+ expect(context.index('<')).to eq(0)
33
+ end
34
+
35
+ end
@@ -0,0 +1,116 @@
1
+ require 'spec_helper'
2
+
3
+ describe Arbo::Element, "Finder Methods" do
4
+ let(:assigns){ {} }
5
+ let(:helpers){ {} }
6
+
7
+ describe "finding elements by tag name" do
8
+
9
+ it "should return 0 when no elements exist" do
10
+ expect(arbo {
11
+ div
12
+ }.get_elements_by_tag_name("li").size).to eq(0)
13
+ end
14
+
15
+ it "should return a child element" do
16
+ html = arbo do
17
+ ul
18
+ li
19
+ ul
20
+ end
21
+ elements = html.get_elements_by_tag_name("li")
22
+ expect(elements.size).to eq(1)
23
+ expect(elements[0]).to be_instance_of(Arbo::HTML::Li)
24
+ end
25
+
26
+ it "should return multple child elements" do
27
+ html = arbo do
28
+ ul
29
+ li
30
+ ul
31
+ li
32
+ end
33
+ elements = html.get_elements_by_tag_name("li")
34
+ expect(elements.size).to eq(2)
35
+ expect(elements[0]).to be_instance_of(Arbo::HTML::Li)
36
+ expect(elements[1]).to be_instance_of(Arbo::HTML::Li)
37
+ end
38
+
39
+ it "should return children's child elements" do
40
+ html = arbo do
41
+ ul
42
+ li do
43
+ li
44
+ end
45
+ end
46
+ elements = html.get_elements_by_tag_name("li")
47
+ expect(elements.size).to eq(2)
48
+ expect(elements[0]).to be_instance_of(Arbo::HTML::Li)
49
+ expect(elements[1]).to be_instance_of(Arbo::HTML::Li)
50
+ expect(elements[1].parent).to eq(elements[0])
51
+ end
52
+ end
53
+
54
+ #TODO: describe "finding an element by id"
55
+
56
+ describe "finding an element by a class name" do
57
+
58
+ it "should return 0 when no elements exist" do
59
+ expect(arbo {
60
+ div
61
+ }.get_elements_by_class_name("my_class").size).to eq(0)
62
+ end
63
+
64
+ it "should allow text nodes on tree" do
65
+ expect(arbo {
66
+ text_node "text"
67
+ }.get_elements_by_class_name("my_class").size).to eq(0)
68
+ end
69
+
70
+ it "should return a child element" do
71
+ html = arbo do
72
+ div class: "some_class"
73
+ div class: "my_class"
74
+ end
75
+ elements = html.get_elements_by_class_name("my_class")
76
+ expect(elements.size).to eq(1)
77
+ expect(elements[0]).to be_instance_of(Arbo::HTML::Div)
78
+ end
79
+
80
+ it "should return multple child elements" do
81
+ html = arbo do
82
+ div class: "some_class"
83
+ div class: "my_class"
84
+ div class: "my_class"
85
+ end
86
+ elements = html.get_elements_by_class_name("my_class")
87
+ expect(elements.size).to eq(2)
88
+ expect(elements[0]).to be_instance_of(Arbo::HTML::Div)
89
+ expect(elements[1]).to be_instance_of(Arbo::HTML::Div)
90
+ end
91
+
92
+ it "should return elements that match one of several classes" do
93
+ html = arbo do
94
+ div class: "some_class this_class"
95
+ div class: "some_class"
96
+ div class: "other_class"
97
+
98
+ end
99
+ elements = html.get_elements_by_class_name("this_class")
100
+ expect(elements.size).to eq(1)
101
+ expect(elements[0]).to be_instance_of(Arbo::HTML::Div)
102
+ end
103
+
104
+ it "should return a grandchild element" do
105
+ html = arbo do
106
+ div class: "some_class" do
107
+ div class: "my_class"
108
+ end
109
+ end
110
+ elements = html.get_elements_by_class_name("my_class")
111
+ expect(elements.size).to eq(1)
112
+ expect(elements[0]).to be_instance_of(Arbo::HTML::Div)
113
+ end
114
+
115
+ end
116
+ end