File: templates_test.rb

package info (click to toggle)
ruby-sinatra 1.4.5-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 1,524 kB
  • ctags: 483
  • sloc: ruby: 9,521; makefile: 5
file content (382 lines) | stat: -rw-r--r-- 10,365 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
# encoding: UTF-8
require File.expand_path('../helper', __FILE__)
File.delete(File.dirname(__FILE__) + '/views/layout.test') rescue nil

class TestTemplate < Tilt::Template
  def prepare
  end

  def evaluate(scope, locals={}, &block)
    inner = block ? block.call : ''
    data + inner
  end

  Tilt.register 'test', self
end

class TemplatesTest < Test::Unit::TestCase
  def render_app(base=Sinatra::Base, options = {}, &block)
    base, options = Sinatra::Base, base if base.is_a? Hash
    mock_app(base) do
      set :views, File.dirname(__FILE__) + '/views'
      set options
      get('/', &block)
      template(:layout3) { "Layout 3!\n" }
    end
    get '/'
  end

  def with_default_layout
    layout = File.dirname(__FILE__) + '/views/layout.test'
    File.open(layout, 'wb') { |io| io.write "Layout!\n" }
    yield
  ensure
    File.unlink(layout) rescue nil
  end

  it 'falls back to engine layout' do
    mock_app do
      template(:layout3) { 'Layout 3!<%= yield %>' }
      set :erb, :layout => :layout3

      get('/') do
        erb('Hello World!', { :layout => true })
      end
    end

    get '/'
    assert ok?
    assert_equal "Layout 3!Hello World!", body
  end

  it 'falls back to default layout if engine layout is true' do
    mock_app do
      template(:layout) { 'Layout!!! <%= yield %>' }
      set :erb, :layout => true

      get('/') do
        erb('Hello World!', { :layout => true })
      end
    end

    get '/'
    assert ok?
    assert_equal "Layout!!! Hello World!", body
  end

  it 'renders no layout if layout if falsy' do
    mock_app do
      template(:layout) { 'Layout!!! <%= yield %>' }
      set :erb, :layout => true

      get('/') do
        erb('Hello World!', { :layout => nil })
      end
    end

    get '/'
    assert ok?
    assert_equal "Hello World!", body
  end

  it 'allows overriding false default layout with explicit true' do
    mock_app do
      template(:layout) { 'Layout!!! <%= yield %>' }
      set :erb, :layout => false

      get('/') do
        erb('Hello World!', { :layout => true })
      end
    end

    get '/'
    assert ok?
    assert_equal "Layout!!! Hello World!", body
  end

  it 'renders String templates directly' do
    render_app { render(:test, 'Hello World') }
    assert ok?
    assert_equal 'Hello World', body
  end

  it 'renders Proc templates using the call result' do
    render_app { render(:test, Proc.new {'Hello World'}) }
    assert ok?
    assert_equal 'Hello World', body
  end

  it 'looks up Symbol templates in views directory' do
    render_app { render(:test, :hello) }
    assert ok?
    assert_equal "Hello World!\n", body
  end

  it 'uses the default layout template if not explicitly overridden' do
    with_default_layout do
      render_app { render(:test, :hello) }
      assert ok?
      assert_equal "Layout!\nHello World!\n", body
    end
  end

  it 'uses the default layout template if not really overriden' do
    with_default_layout do
      render_app { render(:test, :hello, :layout => true) }
      assert ok?
      assert_equal "Layout!\nHello World!\n", body
    end
  end

  it 'uses the layout template specified' do
    render_app { render(:test, :hello, :layout => :layout2) }
    assert ok?
    assert_equal "Layout 2!\nHello World!\n", body
  end

  it 'uses layout templates defined with the #template method' do
    render_app { render(:test, :hello, :layout => :layout3) }
    assert ok?
    assert_equal "Layout 3!\nHello World!\n", body
  end

  it 'avoids wrapping layouts around nested templates' do
    render_app { render(:str, :nested, :layout => :layout2) }
    assert ok?
    assert_equal(
      "<h1>String Layout!</h1>\n<content><h1>Hello From String</h1></content>",
      body
    )
  end

  it 'allows explicitly wrapping layouts around nested templates' do
    render_app { render(:str, :explicitly_nested, :layout => :layout2) }
    assert ok?
    assert_equal(
      "<h1>String Layout!</h1>\n<content><h1>String Layout!</h1>\n<h1>Hello From String</h1></content>",
      body
    )
  end

  it 'two independent render calls do not disable layouts' do
    render_app do
      render :str, :explicitly_nested, :layout => :layout2
      render :str, :nested, :layout => :layout2
    end
    assert ok?
    assert_equal(
      "<h1>String Layout!</h1>\n<content><h1>Hello From String</h1></content>",
      body
    )
  end

  it 'is possible to use partials in layouts' do
    render_app do
      settings.layout { "<%= erb 'foo' %><%= yield %>" }
      erb 'bar'
    end
    assert ok?
    assert_equal "foobar", body
  end

  it 'loads templates from source file' do
    mock_app { enable(:inline_templates) }
    assert_equal "this is foo\n\n", @app.templates[:foo][0]
    assert_equal "X\n= yield\nX\n", @app.templates[:layout][0]
  end

  it 'ignores spaces after names of inline templates' do
    mock_app { enable(:inline_templates) }
    assert_equal "There's a space after 'bar'!\n\n", @app.templates[:bar][0]
    assert_equal "this is not foo\n\n", @app.templates[:"foo bar"][0]
  end

  it 'loads templates from given source file' do
    mock_app { set(:inline_templates, __FILE__) }
    assert_equal "this is foo\n\n", @app.templates[:foo][0]
  end

  test 'inline_templates ignores IO errors' do
    assert_nothing_raised { mock_app { set(:inline_templates, '/foo/bar') } }

    assert @app.templates.empty?
  end

  it 'allows unicode in inline templates' do
    mock_app { set(:inline_templates, __FILE__) }
    assert_equal(
      "Den som tror at hemma det är där man bor har aldrig vart hos mig.\n\n",
      @app.templates[:umlaut][0]
    )
  end

  it 'loads templates from specified views directory' do
    render_app { render(:test, :hello, :views => settings.views + '/foo') }

    assert_equal "from another views directory\n", body
  end

  it 'takes views directory into consideration for caching' do
    render_app do
      render(:test, :hello) + render(:test, :hello, :views => settings.views + '/foo')
    end
    assert_equal "Hello World!\nfrom another views directory\n", body
  end

  it 'passes locals to the layout' do
    mock_app do
      template(:my_layout) { 'Hello <%= name %>!<%= yield %>' }

      get('/') do
        erb('<p>content</p>', { :layout => :my_layout }, { :name => 'Mike'})
      end
    end

    get '/'
    assert ok?
    assert_equal 'Hello Mike!<p>content</p>', body
  end

  it 'sets layout-only options via layout_options' do
    render_app do
      render(:str, :in_a,
        :views          => settings.views + '/a',
        :layout_options => { :views => settings.views },
        :layout         => :layout2)
    end

    assert ok?
    assert_equal "<h1>String Layout!</h1>\nGimme an A!\n", body
  end

  it 'loads templates defined in subclasses' do
    base = Class.new(Sinatra::Base)
    base.template(:foo) { 'bar' }
    render_app(base) { render(:test, :foo) }
    assert ok?
    assert_equal 'bar', body
  end

  it 'allows setting default content type per template engine' do
    render_app(:str => { :content_type => :txt }) {
      render :str, 'foo'
    }
    assert_equal 'text/plain;charset=utf-8', response['Content-Type']
  end

  it 'setting default content type does not affect other template engines' do
    render_app(:str => { :content_type => :txt }) {
      render :test, 'foo'
    }
    assert_equal 'text/html;charset=utf-8', response['Content-Type']
  end

  it 'setting default content type per template engine does not override content_type' do
    render_app :str => { :content_type => :txt } do
      content_type :html
      render :str, 'foo'
    end
    assert_equal 'text/html;charset=utf-8', response['Content-Type']
  end

  it 'uses templates in superclasses before subclasses' do
    base = Class.new(Sinatra::Base)
    base.template(:foo) { 'template in superclass' }
    assert_equal 'template in superclass', base.templates[:foo].first.call

    mock_app(base) do
      set :views, File.dirname(__FILE__) + '/views'
      template(:foo) { 'template in subclass' }
      get('/') { render :test, :foo }
    end
    assert_equal 'template in subclass', @app.templates[:foo].first.call

    get '/'
    assert ok?
    assert_equal 'template in subclass', body
  end

  it "is possible to use a different engine for the layout than for the template itself explicitly" do
    render_app do
      settings.template(:layout) { 'Hello <%= yield %>!' }
      render :str, "<%= 'World' %>", :layout_engine => :erb
    end
    assert_equal "Hello <%= 'World' %>!", body
  end

  it "is possible to use a different engine for the layout than for the template itself globally" do
    render_app :str => { :layout_engine => :erb } do
      settings.template(:layout) { 'Hello <%= yield %>!' }
      render :str, "<%= 'World' %>"
    end
    assert_equal "Hello <%= 'World' %>!", body
  end

  it "does not leak the content type to the template" do
    render_app :str => { :layout_engine => :erb } do
      settings.template(:layout) { 'Hello <%= yield %>!' }
      render :str, "<%= 'World' %>", :content_type => :txt
    end
    assert_equal "text/html;charset=utf-8", headers['Content-Type']
  end

  it "is possible to register another template" do
    Tilt.register "html.erb", Tilt[:erb]
    render_app { render :erb, :calc }
    assert_equal '2', body
  end

  it "passes scope to the template" do
    mock_app do
      template(:scoped) { 'Hello <%= foo %>' }

      get('/') do
        some_scope = Object.new
        def some_scope.foo() 'World!' end
        erb :scoped, :scope => some_scope
      end
    end

    get '/'
    assert ok?
    assert_equal 'Hello World!', body
  end

  it "is possible to use custom logic for finding template files" do
    mock_app do
      set :views, ["a", "b"].map { |d| File.dirname(__FILE__) + '/views/' + d }
      def find_template(views, name, engine, &block)
        Array(views).each { |v| super(v, name, engine, &block) }
      end

      get('/:name') { render(:str, params[:name].to_sym) }
    end

    get '/in_a'
    assert_body 'Gimme an A!'

    get '/in_b'
    assert_body 'Gimme a B!'
  end
end

# __END__ : this is not the real end of the script.

__END__

@@ foo
this is foo

@@ bar
There's a space after 'bar'!

@@ foo bar
this is not foo

@@ umlaut
Den som tror at hemma det är där man bor har aldrig vart hos mig.

@@ layout
X
= yield
X