porthole 0.99.4
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.
- data/LICENSE +20 -0
- data/README.md +415 -0
- data/Rakefile +89 -0
- data/bin/porthole +94 -0
- data/lib/porthole.rb +304 -0
- data/lib/porthole/context.rb +142 -0
- data/lib/porthole/generator.rb +195 -0
- data/lib/porthole/parser.rb +263 -0
- data/lib/porthole/settings.rb +226 -0
- data/lib/porthole/sinatra.rb +205 -0
- data/lib/porthole/template.rb +58 -0
- data/lib/porthole/version.rb +3 -0
- data/lib/rack/bug/panels/mustache_panel.rb +81 -0
- data/lib/rack/bug/panels/mustache_panel/mustache_extension.rb +27 -0
- data/lib/rack/bug/panels/mustache_panel/view.mustache +46 -0
- data/man/porthole.1 +165 -0
- data/man/porthole.1.html +213 -0
- data/man/porthole.1.ron +127 -0
- data/man/porthole.5 +539 -0
- data/man/porthole.5.html +422 -0
- data/man/porthole.5.ron +324 -0
- data/test/autoloading_test.rb +56 -0
- data/test/fixtures/comments.porthole +1 -0
- data/test/fixtures/comments.rb +14 -0
- data/test/fixtures/complex_view.porthole +17 -0
- data/test/fixtures/complex_view.rb +34 -0
- data/test/fixtures/crazy_recursive.porthole +9 -0
- data/test/fixtures/crazy_recursive.rb +31 -0
- data/test/fixtures/delimiters.porthole +8 -0
- data/test/fixtures/delimiters.rb +23 -0
- data/test/fixtures/dot_notation.porthole +10 -0
- data/test/fixtures/dot_notation.rb +25 -0
- data/test/fixtures/double_section.porthole +7 -0
- data/test/fixtures/double_section.rb +14 -0
- data/test/fixtures/escaped.porthole +1 -0
- data/test/fixtures/escaped.rb +14 -0
- data/test/fixtures/inner_partial.porthole +1 -0
- data/test/fixtures/inner_partial.txt +1 -0
- data/test/fixtures/inverted_section.porthole +7 -0
- data/test/fixtures/inverted_section.rb +14 -0
- data/test/fixtures/lambda.porthole +7 -0
- data/test/fixtures/lambda.rb +31 -0
- data/test/fixtures/method_missing.rb +19 -0
- data/test/fixtures/namespaced.porthole +1 -0
- data/test/fixtures/namespaced.rb +25 -0
- data/test/fixtures/nested_objects.porthole +17 -0
- data/test/fixtures/nested_objects.rb +35 -0
- data/test/fixtures/node.porthole +8 -0
- data/test/fixtures/partial_with_module.porthole +4 -0
- data/test/fixtures/partial_with_module.rb +37 -0
- data/test/fixtures/passenger.conf +5 -0
- data/test/fixtures/passenger.rb +27 -0
- data/test/fixtures/recursive.porthole +4 -0
- data/test/fixtures/recursive.rb +14 -0
- data/test/fixtures/simple.porthole +5 -0
- data/test/fixtures/simple.rb +26 -0
- data/test/fixtures/template_partial.porthole +2 -0
- data/test/fixtures/template_partial.rb +18 -0
- data/test/fixtures/template_partial.txt +4 -0
- data/test/fixtures/unescaped.porthole +1 -0
- data/test/fixtures/unescaped.rb +14 -0
- data/test/fixtures/utf8.porthole +3 -0
- data/test/fixtures/utf8_partial.porthole +1 -0
- data/test/helper.rb +7 -0
- data/test/parser_test.rb +78 -0
- data/test/partial_test.rb +168 -0
- data/test/porthole_test.rb +677 -0
- data/test/spec_test.rb +68 -0
- data/test/template_test.rb +20 -0
- metadata +127 -0
@@ -0,0 +1,677 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
$LOAD_PATH.unshift File.dirname(__FILE__)
|
3
|
+
require 'helper'
|
4
|
+
|
5
|
+
class PortholeTest < Test::Unit::TestCase
|
6
|
+
def test_instance_render
|
7
|
+
klass = Class.new(Porthole)
|
8
|
+
klass.template = "Hi %%thing%%!"
|
9
|
+
assert_equal "Hi world!", klass.render(:thing => :world)
|
10
|
+
assert_equal "Nice.", klass.render("%%compliment%%.", :compliment => "Nice")
|
11
|
+
assert_equal <<-end_simple, Simple.new.render(:name => "yo", :in_ca => false)
|
12
|
+
Hello yo
|
13
|
+
You have just won $10000!
|
14
|
+
end_simple
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_passenger
|
18
|
+
assert_equal <<-end_passenger, Passenger.to_text
|
19
|
+
<VirtualHost *>
|
20
|
+
ServerName example.com
|
21
|
+
DocumentRoot /var/www/example.com
|
22
|
+
RailsEnv production
|
23
|
+
</VirtualHost>
|
24
|
+
end_passenger
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_complex_view
|
28
|
+
assert_equal <<-end_complex, ComplexView.render
|
29
|
+
<h1>Colors</h1>
|
30
|
+
<ul>
|
31
|
+
<li><strong>red</strong></li>
|
32
|
+
<li><a href="#Green">green</a></li>
|
33
|
+
<li><a href="#Blue">blue</a></li>
|
34
|
+
</ul>
|
35
|
+
|
36
|
+
end_complex
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_nested_objects
|
40
|
+
assert_equal <<-end_complex, NestedObjects.render
|
41
|
+
<h1>Colors</h1>
|
42
|
+
<ul>
|
43
|
+
<li><strong>red</strong></li>
|
44
|
+
<li><a href="#Green">green</a></li>
|
45
|
+
<li><a href="#Blue">blue</a></li>
|
46
|
+
</ul>
|
47
|
+
|
48
|
+
end_complex
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_single_line_sections
|
52
|
+
html = %(<p class="flash-notice" %%# no_flash %%style="display: none;"%%/ no_flash %%>)
|
53
|
+
|
54
|
+
instance = Porthole.new
|
55
|
+
instance.template = html
|
56
|
+
instance[:no_flash] = true
|
57
|
+
assert_equal %Q'<p class="flash-notice" style="display: none;">', instance.render
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_strings_as_sections_do_not_enumerate
|
61
|
+
instance = Porthole.new
|
62
|
+
instance[:contact] = "Call 1-888-FLOWERS\nAsk for Johnson."
|
63
|
+
instance.template = "%%#contact%%<div id='contact'>%%contact%%</div>%%/contact%%"
|
64
|
+
|
65
|
+
assert_equal "<div id='contact'>Call 1-888-FLOWERS\nAsk for Johnson.</div>",
|
66
|
+
instance.render
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_sassy_single_line_sections
|
70
|
+
instance = Porthole.new
|
71
|
+
instance[:full_time] = true
|
72
|
+
instance.template = "\n %%#full_time%%full time%%/full_time%%\n"
|
73
|
+
|
74
|
+
assert_equal "\n full time\n", instance.render
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_sassier_single_line_sections
|
78
|
+
instance = Porthole.new
|
79
|
+
instance.template = "\t%%#list%%\r\n\t%%/list%%"
|
80
|
+
|
81
|
+
assert_equal "", instance.render
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_padding_before_section
|
85
|
+
instance = Porthole.new
|
86
|
+
instance.template = "\t%%#list%%a%%/list%%"
|
87
|
+
|
88
|
+
assert_equal "\taa", instance.render(:list => [1, 2])
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_padding_before_section_on_eos
|
92
|
+
instance = Porthole.new
|
93
|
+
instance.template = "%%#list%%\n\t%%/list%%"
|
94
|
+
|
95
|
+
assert_equal "", instance.render(:list => [1, 2])
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_two_line_sections
|
99
|
+
html = %(<p class="flash-notice" %%# no_flash %%style="display: none;"\n%%/ no_flash %%>)
|
100
|
+
|
101
|
+
instance = Porthole.new
|
102
|
+
instance.template = html
|
103
|
+
instance[:no_flash] = true
|
104
|
+
assert_equal %Q'<p class="flash-notice" style="display: none;"\n>', instance.render
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_multi_line_sections_preserve_trailing_newline
|
108
|
+
view = Porthole.new
|
109
|
+
view.template = <<template
|
110
|
+
%%#something%%
|
111
|
+
yay
|
112
|
+
%%/something%%
|
113
|
+
Howday.
|
114
|
+
template
|
115
|
+
|
116
|
+
view[:something] = true
|
117
|
+
assert_equal <<-rendered, view.render
|
118
|
+
yay
|
119
|
+
Howday.
|
120
|
+
rendered
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_single_line_inverted_sections
|
124
|
+
html = %(<p class="flash-notice" %%^ flash %%style="display: none;"%%/ flash %%>)
|
125
|
+
|
126
|
+
instance = Porthole.new
|
127
|
+
instance.template = html
|
128
|
+
assert_equal %Q'<p class="flash-notice" style="display: none;">', instance.render
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_simple
|
132
|
+
assert_equal <<-end_simple, Simple.render
|
133
|
+
Hello Chris
|
134
|
+
You have just won $10000!
|
135
|
+
Well, $6000.0, after taxes.
|
136
|
+
end_simple
|
137
|
+
end
|
138
|
+
|
139
|
+
def test_hash_assignment
|
140
|
+
view = Simple.new
|
141
|
+
view[:name] = 'Bob'
|
142
|
+
view[:value] = '4000'
|
143
|
+
view[:in_ca] = false
|
144
|
+
|
145
|
+
assert_equal <<-end_simple, view.render
|
146
|
+
Hello Bob
|
147
|
+
You have just won $4000!
|
148
|
+
end_simple
|
149
|
+
end
|
150
|
+
|
151
|
+
def test_crazier_hash_assignment
|
152
|
+
view = Simple.new
|
153
|
+
view[:name] = 'Crazy'
|
154
|
+
view[:in_ca] = [
|
155
|
+
{ :taxed_value => 1 },
|
156
|
+
{ :taxed_value => 2 },
|
157
|
+
{ :taxed_value => 3 },
|
158
|
+
]
|
159
|
+
|
160
|
+
assert_equal <<-end_simple, view.render
|
161
|
+
Hello Crazy
|
162
|
+
You have just won $10000!
|
163
|
+
Well, $1, after taxes.
|
164
|
+
Well, $2, after taxes.
|
165
|
+
Well, $3, after taxes.
|
166
|
+
end_simple
|
167
|
+
end
|
168
|
+
|
169
|
+
def test_fileless_templates
|
170
|
+
view = Simple.new
|
171
|
+
view.template = 'Hi %%person%%!'
|
172
|
+
view[:person] = 'mom'
|
173
|
+
|
174
|
+
assert_equal 'Hi mom!', view.render
|
175
|
+
end
|
176
|
+
|
177
|
+
def test_delimiters
|
178
|
+
assert_equal <<-end_template, Delimiters.render
|
179
|
+
* It worked the first time.
|
180
|
+
* And it worked the second time.
|
181
|
+
* As well as the third.
|
182
|
+
* Then, surprisingly, it worked the final time.
|
183
|
+
end_template
|
184
|
+
end
|
185
|
+
|
186
|
+
def test_double_section
|
187
|
+
assert_equal <<-end_section, DoubleSection.render
|
188
|
+
* first
|
189
|
+
* second
|
190
|
+
* third
|
191
|
+
end_section
|
192
|
+
end
|
193
|
+
|
194
|
+
def test_inverted_section
|
195
|
+
assert_equal <<-end_section, InvertedSection.render
|
196
|
+
* first
|
197
|
+
* second
|
198
|
+
* third
|
199
|
+
end_section
|
200
|
+
end
|
201
|
+
|
202
|
+
def test_comments
|
203
|
+
assert_equal "<h1>A Comedy of Errors</h1>\n", Comments.render
|
204
|
+
end
|
205
|
+
|
206
|
+
def test_multi_linecomments
|
207
|
+
view = Comments.new
|
208
|
+
view.template = "<h1>%%title%%%%! just something interesting... \n#or not... %%</h1>\n"
|
209
|
+
assert_equal "<h1>A Comedy of Errors</h1>\n", view.render
|
210
|
+
end
|
211
|
+
|
212
|
+
def test_escaped
|
213
|
+
assert_equal '<h1>Bear > Shark</h1>', Escaped.render
|
214
|
+
end
|
215
|
+
|
216
|
+
def test_unescaped
|
217
|
+
assert_equal '<h1>Bear > Shark</h1>', Unescaped.render
|
218
|
+
end
|
219
|
+
|
220
|
+
def test_unescaped_ampersand
|
221
|
+
view = Porthole.new
|
222
|
+
view.template = "<h1>%%& title%%</h1>"
|
223
|
+
view[:title] = "Bear > Shark"
|
224
|
+
assert_equal '<h1>Bear > Shark</h1>', view.render
|
225
|
+
end
|
226
|
+
|
227
|
+
def test_classify
|
228
|
+
assert_equal 'TemplatePartial', Porthole.classify('template_partial')
|
229
|
+
assert_equal 'Admin::TemplatePartial', Porthole.classify('admin/template_partial')
|
230
|
+
end
|
231
|
+
|
232
|
+
def test_underscore
|
233
|
+
assert_equal 'template_partial', Porthole.underscore('TemplatePartial')
|
234
|
+
assert_equal 'admin/template_partial', Porthole.underscore('Admin::TemplatePartial')
|
235
|
+
assert_equal 'views/in/sub/directories', Porthole.underscore('Views::In::Sub::Directories')
|
236
|
+
end
|
237
|
+
|
238
|
+
def test_anon_subclass_underscore
|
239
|
+
klass = Class.new(TemplatePartial)
|
240
|
+
assert_equal 'template_partial', klass.underscore
|
241
|
+
end
|
242
|
+
|
243
|
+
def test_namespaced_underscore
|
244
|
+
Object.const_set(:Views, Class.new)
|
245
|
+
klass = Class.new(Porthole)
|
246
|
+
klass.view_namespace = Views
|
247
|
+
assert_equal 'stat_stuff', klass.underscore('Views::StatStuff')
|
248
|
+
|
249
|
+
assert_equal 'views/stat_stuff', Porthole.underscore('Views::StatStuff')
|
250
|
+
end
|
251
|
+
|
252
|
+
def test_render
|
253
|
+
assert_equal 'Hello World!', Porthole.render('Hello World!')
|
254
|
+
end
|
255
|
+
|
256
|
+
def test_render_with_params
|
257
|
+
assert_equal 'Hello World!', Porthole.render('Hello %%planet%%!', :planet => 'World')
|
258
|
+
end
|
259
|
+
|
260
|
+
def test_render_from_file
|
261
|
+
expected = <<-data
|
262
|
+
<VirtualHost *>
|
263
|
+
ServerName example.com
|
264
|
+
DocumentRoot /var/www/example.com
|
265
|
+
RailsEnv production
|
266
|
+
</VirtualHost>
|
267
|
+
data
|
268
|
+
template = File.read(File.dirname(__FILE__) + "/fixtures/passenger.conf")
|
269
|
+
assert_equal expected, Porthole.render(template, :stage => 'production',
|
270
|
+
:server => 'example.com',
|
271
|
+
:deploy_to => '/var/www/example.com' )
|
272
|
+
end
|
273
|
+
|
274
|
+
def test_render_from_symbol
|
275
|
+
expected = <<-data
|
276
|
+
<VirtualHost *>
|
277
|
+
ServerName example.com
|
278
|
+
DocumentRoot /var/www/example.com
|
279
|
+
RailsEnv production
|
280
|
+
</VirtualHost>
|
281
|
+
data
|
282
|
+
old_path, Porthole.template_path = Porthole.template_path, File.dirname(__FILE__) + "/fixtures"
|
283
|
+
old_extension, Porthole.template_extension = Porthole.template_extension, "conf"
|
284
|
+
|
285
|
+
assert_equal expected, Porthole.render(:passenger, :stage => 'production',
|
286
|
+
:server => 'example.com',
|
287
|
+
:deploy_to => '/var/www/example.com' )
|
288
|
+
|
289
|
+
Porthole.template_path, Porthole.template_extension = old_path, old_extension
|
290
|
+
end
|
291
|
+
|
292
|
+
def test_doesnt_execute_what_it_doesnt_need_to
|
293
|
+
instance = Porthole.new
|
294
|
+
instance[:show] = false
|
295
|
+
instance.instance_eval do
|
296
|
+
def die
|
297
|
+
raise "bummer"
|
298
|
+
end
|
299
|
+
end
|
300
|
+
instance.template = '%%#show%% <li>%%die%%</li> %%/show%% yay'
|
301
|
+
|
302
|
+
assert_equal " yay", instance.render
|
303
|
+
end
|
304
|
+
|
305
|
+
def test_reports_unclosed_sections
|
306
|
+
instance = Porthole.new
|
307
|
+
instance[:list] = [ :item => 1234 ]
|
308
|
+
instance.template = '%%#list%% <li>%%item%%</li> %%/gist%%'
|
309
|
+
|
310
|
+
begin
|
311
|
+
instance.render
|
312
|
+
rescue => e
|
313
|
+
end
|
314
|
+
|
315
|
+
assert e.message.include?('Unclosed section')
|
316
|
+
end
|
317
|
+
|
318
|
+
def test_unclosed_sections_reports_the_line_number
|
319
|
+
instance = Porthole.new
|
320
|
+
instance[:list] = [ :item => 1234 ]
|
321
|
+
instance.template = "hi\nmom\n%%#list%% <li>%%item%%</li> %%/gist%%"
|
322
|
+
|
323
|
+
begin
|
324
|
+
instance.render
|
325
|
+
rescue => e
|
326
|
+
end
|
327
|
+
|
328
|
+
assert e.message.include?('Line 3')
|
329
|
+
end
|
330
|
+
|
331
|
+
def test_enumerable_sections_accept_a_hash_as_a_context
|
332
|
+
instance = Porthole.new
|
333
|
+
instance[:list] = { :item => 1234 }
|
334
|
+
instance.template = '%%#list%% <li>%%item%%</li> %%/list%%'
|
335
|
+
|
336
|
+
assert_equal ' <li>1234</li> ', instance.render
|
337
|
+
end
|
338
|
+
|
339
|
+
def test_enumerable_sections_accept_a_string_keyed_hash_as_a_context
|
340
|
+
instance = Porthole.new
|
341
|
+
instance[:list] = { 'item' => 1234 }
|
342
|
+
instance.template = '%%#list%% <li>%%item%%</li> %%/list%%'
|
343
|
+
|
344
|
+
assert_equal ' <li>1234</li> ', instance.render
|
345
|
+
end
|
346
|
+
|
347
|
+
def test_not_found_in_context_renders_empty_string
|
348
|
+
instance = Porthole.new
|
349
|
+
instance.template = '%%#list%% <li>%%item%%</li> %%/list%%'
|
350
|
+
|
351
|
+
assert_equal '', instance.render
|
352
|
+
end
|
353
|
+
|
354
|
+
def test_not_found_in_nested_context_renders_empty_string
|
355
|
+
instance = Porthole.new
|
356
|
+
instance[:list] = { :item => 1234 }
|
357
|
+
instance.template = '%%#list%% <li>%%prefix%%%%item%%</li> %%/list%%'
|
358
|
+
|
359
|
+
assert_equal ' <li>1234</li> ', instance.render
|
360
|
+
end
|
361
|
+
|
362
|
+
def test_not_found_in_context_raises_when_asked_to
|
363
|
+
instance = Porthole.new
|
364
|
+
instance.raise_on_context_miss = true
|
365
|
+
instance.template = '%%#list%% <li>%%item%%</li> %%/list%%'
|
366
|
+
|
367
|
+
assert_raises Porthole::ContextMiss do
|
368
|
+
instance.render
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
def test_knows_when_its_been_compiled_when_set_with_string
|
373
|
+
klass = Class.new(Porthole)
|
374
|
+
|
375
|
+
assert ! klass.compiled?
|
376
|
+
klass.template = 'Hi, %%person%%!'
|
377
|
+
assert klass.compiled?
|
378
|
+
end
|
379
|
+
|
380
|
+
def test_knows_when_its_been_compiled_when_using_a_file_template
|
381
|
+
klass = Class.new(Simple)
|
382
|
+
klass.template_file = File.dirname(__FILE__) + '/fixtures/simple.porthole'
|
383
|
+
|
384
|
+
assert ! klass.compiled?
|
385
|
+
klass.render
|
386
|
+
assert klass.compiled?
|
387
|
+
end
|
388
|
+
|
389
|
+
def test_an_instance_knows_when_its_class_is_compiled
|
390
|
+
instance = Simple.new
|
391
|
+
|
392
|
+
assert ! Simple.compiled?
|
393
|
+
assert ! instance.compiled?
|
394
|
+
|
395
|
+
Simple.render
|
396
|
+
|
397
|
+
assert Simple.compiled?
|
398
|
+
assert instance.compiled?
|
399
|
+
end
|
400
|
+
|
401
|
+
def test_knows_when_its_been_compiled_at_the_instance_level
|
402
|
+
klass = Class.new(Porthole)
|
403
|
+
instance = klass.new
|
404
|
+
|
405
|
+
assert ! instance.compiled?
|
406
|
+
instance.template = 'Hi, %%person%%!'
|
407
|
+
assert instance.compiled?
|
408
|
+
end
|
409
|
+
|
410
|
+
def test_sections_returning_lambdas_get_called_with_text
|
411
|
+
view = Lambda.new
|
412
|
+
view[:name] = 'Chris'
|
413
|
+
|
414
|
+
assert_equal "Hi Chris.\n\nHi %%name%%.", view.render.chomp
|
415
|
+
assert_equal 1, view.calls
|
416
|
+
|
417
|
+
assert_equal "Hi Chris.\n\nHi %%name%%.", view.render.chomp
|
418
|
+
assert_equal 1, view.calls
|
419
|
+
|
420
|
+
assert_equal "Hi Chris.\n\nHi %%name%%.", view.render.chomp
|
421
|
+
assert_equal 1, view.calls
|
422
|
+
end
|
423
|
+
|
424
|
+
def test_sections_which_refer_to_unary_method_call_them_as_proc
|
425
|
+
kls = Class.new(Porthole) do
|
426
|
+
def unary_method(arg)
|
427
|
+
"(#{arg})"
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
431
|
+
str = kls.render("%%#unary_method%%test%%/unary_method%%")
|
432
|
+
assert_equal "(test)", str
|
433
|
+
end
|
434
|
+
|
435
|
+
def test_lots_of_staches
|
436
|
+
template = "%%%%foo%%%%"
|
437
|
+
|
438
|
+
begin
|
439
|
+
Porthole.render(template, :foo => "defunkt")
|
440
|
+
rescue => e
|
441
|
+
end
|
442
|
+
|
443
|
+
assert e.message.include?("Illegal content in tag")
|
444
|
+
end
|
445
|
+
|
446
|
+
def test_liberal_tag_names
|
447
|
+
template = "%%first-name%% %%middle_name!%% %%lastName?%%"
|
448
|
+
hash = {
|
449
|
+
'first-name' => 'chris',
|
450
|
+
'middle_name!' => 'j',
|
451
|
+
'lastName?' => 'strath'
|
452
|
+
}
|
453
|
+
|
454
|
+
assert_equal "chris j strath", Porthole.render(template, hash)
|
455
|
+
end
|
456
|
+
|
457
|
+
def test_nested_sections_same_names
|
458
|
+
template = <<template
|
459
|
+
%%#items%%
|
460
|
+
start
|
461
|
+
%%#items%%
|
462
|
+
%%a%%
|
463
|
+
%%/items%%
|
464
|
+
end
|
465
|
+
%%/items%%
|
466
|
+
template
|
467
|
+
|
468
|
+
data = {
|
469
|
+
"items" => [
|
470
|
+
{ "items" => [ {"a" => 1}, {"a" => 2}, {"a" => 3} ] },
|
471
|
+
{ "items" => [ {"a" => 4}, {"a" => 5}, {"a" => 6} ] },
|
472
|
+
{ "items" => [ {"a" => 7}, {"a" => 8}, {"a" => 9} ] }
|
473
|
+
]
|
474
|
+
}
|
475
|
+
|
476
|
+
assert_equal <<expected, Porthole.render(template, data)
|
477
|
+
start
|
478
|
+
1
|
479
|
+
2
|
480
|
+
3
|
481
|
+
end
|
482
|
+
start
|
483
|
+
4
|
484
|
+
5
|
485
|
+
6
|
486
|
+
end
|
487
|
+
start
|
488
|
+
7
|
489
|
+
8
|
490
|
+
9
|
491
|
+
end
|
492
|
+
expected
|
493
|
+
end
|
494
|
+
|
495
|
+
def test_id_with_nested_context
|
496
|
+
html = %(<div>%%id%%</div>\n<div>%%# has_a? %%%%id%%%%/ has_a? %%</div>\n<div>%%# has_b? %%%%id%%%%/ has_b? %%</div>\n)
|
497
|
+
|
498
|
+
instance = Porthole.new
|
499
|
+
instance.template = html
|
500
|
+
instance[:id] = 3
|
501
|
+
instance[:has_a?] = true
|
502
|
+
instance[:has_b?] = true
|
503
|
+
assert_equal <<-rendered, instance.render
|
504
|
+
<div>3</div>
|
505
|
+
<div>3</div>
|
506
|
+
<div>3</div>
|
507
|
+
rendered
|
508
|
+
end
|
509
|
+
|
510
|
+
def test_utf8
|
511
|
+
klass = Class.new(Porthole)
|
512
|
+
klass.template_name = 'utf8'
|
513
|
+
klass.template_path = 'test/fixtures'
|
514
|
+
view = klass.new
|
515
|
+
view[:test] = "中文"
|
516
|
+
|
517
|
+
assert_equal <<-rendered, view.render
|
518
|
+
<h1>中文 中文</h1>
|
519
|
+
|
520
|
+
<h2>中文又来啦</h2>
|
521
|
+
rendered
|
522
|
+
end
|
523
|
+
|
524
|
+
def test_indentation
|
525
|
+
view = Porthole.new
|
526
|
+
view[:name] = 'indent'
|
527
|
+
view[:text] = 'puts :indented!'
|
528
|
+
view.template = <<template
|
529
|
+
def %%name%%
|
530
|
+
%%text%%
|
531
|
+
end
|
532
|
+
template
|
533
|
+
|
534
|
+
assert_equal <<template, view.render
|
535
|
+
def indent
|
536
|
+
puts :indented!
|
537
|
+
end
|
538
|
+
template
|
539
|
+
end
|
540
|
+
|
541
|
+
def test_struct
|
542
|
+
person = Struct.new(:name, :age)
|
543
|
+
view = Porthole.new
|
544
|
+
view[:person] = person.new('Marvin', 25)
|
545
|
+
view.template = '%%#person%%%%name%% is %%age%%%%/person%%'
|
546
|
+
assert_equal 'Marvin is 25', view.render
|
547
|
+
end
|
548
|
+
|
549
|
+
def test_method_missing
|
550
|
+
assert_equal('[ 0 1 2 3 4 5 6 7 8 9 10 ]', MethodMissing.render)
|
551
|
+
end
|
552
|
+
|
553
|
+
def test_custom_escaping
|
554
|
+
view = Class.new(Porthole) do
|
555
|
+
def escapeHTML(str)
|
556
|
+
"pong"
|
557
|
+
end
|
558
|
+
end
|
559
|
+
|
560
|
+
assert_equal 'pong', view.render("%%thing%%", :thing => "nothing")
|
561
|
+
assert_equal 'nothing', Porthole.render("%%thing%%", :thing => "nothing")
|
562
|
+
end
|
563
|
+
|
564
|
+
def test_implicit_iterator
|
565
|
+
view = Porthole.new
|
566
|
+
view.template = "%%#people%%* %%.%%\n%%/people%%"
|
567
|
+
view[:people] = %w( Chris Mark Scott )
|
568
|
+
|
569
|
+
assert_equal <<text, view.render
|
570
|
+
* Chris
|
571
|
+
* Mark
|
572
|
+
* Scott
|
573
|
+
text
|
574
|
+
end
|
575
|
+
|
576
|
+
def test_unescaped_implicit_iterator
|
577
|
+
view = Porthole.new
|
578
|
+
view.template = "%%#people%%* %%{.}%%\n%%/people%%"
|
579
|
+
view[:people] = %w( Chris Mark Scott )
|
580
|
+
|
581
|
+
assert_equal <<text, view.render
|
582
|
+
* Chris
|
583
|
+
* Mark
|
584
|
+
* Scott
|
585
|
+
text
|
586
|
+
end
|
587
|
+
|
588
|
+
def test_dot_notation
|
589
|
+
assert_equal <<-text, DotNotation.render
|
590
|
+
* Chris Firescythe
|
591
|
+
* 24
|
592
|
+
* Cincinnati, OH
|
593
|
+
* Cincinnati, OH
|
594
|
+
* Cincinnati, OH
|
595
|
+
* Cincinnati, OH
|
596
|
+
* Normal
|
597
|
+
|
598
|
+
* Chris Firescythe
|
599
|
+
* Cincinnati, OH
|
600
|
+
text
|
601
|
+
end
|
602
|
+
|
603
|
+
def test_inherited_attributes
|
604
|
+
Object.const_set :TestNamespace, Module.new
|
605
|
+
base = Class.new(Porthole)
|
606
|
+
tmpl = Class.new(base)
|
607
|
+
|
608
|
+
{:template_path => File.expand_path('./foo'),
|
609
|
+
:template_extension => 'stache',
|
610
|
+
:view_namespace => TestNamespace,
|
611
|
+
:view_path => './foo'
|
612
|
+
}.each do |attr, value|
|
613
|
+
base.send("#{attr}=", value)
|
614
|
+
assert_equal value, tmpl.send(attr)
|
615
|
+
end
|
616
|
+
end
|
617
|
+
def test_array_of_arrays
|
618
|
+
template = <<template
|
619
|
+
%%#items%%
|
620
|
+
start
|
621
|
+
%%#map%%
|
622
|
+
%%a%%
|
623
|
+
%%/map%%
|
624
|
+
end
|
625
|
+
%%/items%%
|
626
|
+
template
|
627
|
+
|
628
|
+
data = {
|
629
|
+
"items" => [
|
630
|
+
[ {"a" => 1}, {"a" => 2}, {"a" => 3} ],
|
631
|
+
[ {"a" => 4}, {"a" => 5}, {"a" => 6} ],
|
632
|
+
[ {"a" => 7}, {"a" => 8}, {"a" => 9} ]
|
633
|
+
]
|
634
|
+
}
|
635
|
+
|
636
|
+
assert_equal <<expected, Porthole.render(template, data)
|
637
|
+
start
|
638
|
+
1
|
639
|
+
2
|
640
|
+
3
|
641
|
+
end
|
642
|
+
start
|
643
|
+
4
|
644
|
+
5
|
645
|
+
6
|
646
|
+
end
|
647
|
+
start
|
648
|
+
7
|
649
|
+
8
|
650
|
+
9
|
651
|
+
end
|
652
|
+
expected
|
653
|
+
end
|
654
|
+
def test_indentation_again
|
655
|
+
template = <<template
|
656
|
+
SELECT
|
657
|
+
%%#cols%%
|
658
|
+
%%name%%,
|
659
|
+
%%/cols%%
|
660
|
+
FROM
|
661
|
+
DUMMY1
|
662
|
+
template
|
663
|
+
|
664
|
+
view = Porthole.new
|
665
|
+
view[:cols] = [{:name => 'Name'}, {:name => 'Age'}, {:name => 'Weight'}]
|
666
|
+
view.template = template
|
667
|
+
|
668
|
+
assert_equal <<template, view.render
|
669
|
+
SELECT
|
670
|
+
Name,
|
671
|
+
Age,
|
672
|
+
Weight,
|
673
|
+
FROM
|
674
|
+
DUMMY1
|
675
|
+
template
|
676
|
+
end
|
677
|
+
end
|