rasti-web 0.0.1
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.
- checksums.yaml +7 -0
- data/.coveralls.yml +2 -0
- data/.gitignore +22 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +6 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +35 -0
- data/Rakefile +18 -0
- data/lib/rasti/web/application.rb +52 -0
- data/lib/rasti/web/controller.rb +48 -0
- data/lib/rasti/web/endpoint.rb +18 -0
- data/lib/rasti/web/render.rb +82 -0
- data/lib/rasti/web/request.rb +25 -0
- data/lib/rasti/web/route.rb +41 -0
- data/lib/rasti/web/router.rb +43 -0
- data/lib/rasti/web/template.rb +23 -0
- data/lib/rasti/web/version.rb +5 -0
- data/lib/rasti/web/view_context.rb +18 -0
- data/lib/rasti/web.rb +33 -0
- data/lib/rasti-web.rb +1 -0
- data/rasti-web.gemspec +32 -0
- data/spec/application_spec.rb +77 -0
- data/spec/controller_spec.rb +58 -0
- data/spec/coverage_helper.rb +8 -0
- data/spec/endpoint_spec.rb +22 -0
- data/spec/minitest_helper.rb +22 -0
- data/spec/render_spec.rb +263 -0
- data/spec/request_spec.rb +35 -0
- data/spec/route_spec.rb +67 -0
- data/spec/router_spec.rb +38 -0
- data/spec/template_spec.rb +29 -0
- data/spec/views/context_and_locals.erb +1 -0
- data/spec/views/context_method.erb +1 -0
- data/spec/views/custom_layout.erb +1 -0
- data/spec/views/layout.erb +1 -0
- data/spec/views/local_variable.erb +1 -0
- data/spec/views/plain_html.erb +1 -0
- metadata +238 -0
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'minitest_helper'
|
2
|
+
|
3
|
+
class TestController < Rasti::Web::Controller
|
4
|
+
CustomError = Class.new StandardError
|
5
|
+
|
6
|
+
def test
|
7
|
+
render.html 'Test HTML'
|
8
|
+
end
|
9
|
+
|
10
|
+
def exception
|
11
|
+
raise 'Unexpected error'
|
12
|
+
end
|
13
|
+
|
14
|
+
def fail
|
15
|
+
raise CustomError, 'Expected error'
|
16
|
+
end
|
17
|
+
|
18
|
+
rescue_from CustomError do |ex|
|
19
|
+
render.status 500, ex.message
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe Rasti::Web::Controller do
|
24
|
+
|
25
|
+
it 'Action endpoint' do
|
26
|
+
action = TestController.action :test
|
27
|
+
env = Rack::MockRequest.env_for '/test'
|
28
|
+
status, headers, response = action.call env
|
29
|
+
|
30
|
+
action.must_be_instance_of Rasti::Web::Endpoint
|
31
|
+
status.must_equal 200
|
32
|
+
headers['Content-Type'].must_equal 'text/html'
|
33
|
+
response.body.must_equal ['Test HTML']
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'Invalid action' do
|
37
|
+
error = proc { TestController.action :invalid }.must_raise RuntimeError
|
38
|
+
error.message.must_equal "Undefined action 'invalid' in TestController"
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'Rescue exception' do
|
42
|
+
action = TestController.action :fail
|
43
|
+
env = Rack::MockRequest.env_for '/fail'
|
44
|
+
status, headers, response = action.call env
|
45
|
+
|
46
|
+
status.must_equal 500
|
47
|
+
response.body.must_equal ['Expected error']
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'Unexpected exception' do
|
51
|
+
action = TestController.action :exception
|
52
|
+
env = Rack::MockRequest.env_for '/exception'
|
53
|
+
|
54
|
+
error = proc { action.call env }.must_raise RuntimeError
|
55
|
+
error.message.must_equal 'Unexpected error'
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'minitest_helper'
|
2
|
+
|
3
|
+
describe Rasti::Web::Endpoint do
|
4
|
+
|
5
|
+
it 'Call' do
|
6
|
+
endpoint = Rasti::Web::Endpoint.new do |req, res, render|
|
7
|
+
req.must_be_instance_of Rasti::Web::Request
|
8
|
+
res.must_be_instance_of Rack::Response
|
9
|
+
|
10
|
+
render.text 'Content'
|
11
|
+
end
|
12
|
+
|
13
|
+
env = Rack::MockRequest.env_for '/'
|
14
|
+
|
15
|
+
status, headers, response = endpoint.call env
|
16
|
+
|
17
|
+
status.must_equal 200
|
18
|
+
headers['Content-Type'].must_equal 'text/plain'
|
19
|
+
response.body.must_equal ['Content']
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'coverage_helper'
|
2
|
+
require 'rasti-web'
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require 'turn'
|
5
|
+
require 'rack/test'
|
6
|
+
|
7
|
+
Turn.config do |c|
|
8
|
+
c.format = :pretty
|
9
|
+
c.natural = true
|
10
|
+
c.ansi = true
|
11
|
+
end
|
12
|
+
|
13
|
+
module ContextMethodHelper
|
14
|
+
def page_header(text)
|
15
|
+
"<h1>#{text}</h1>"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
Rasti::Web.configure do |config|
|
20
|
+
config.views_path = File.expand_path '../views', __FILE__
|
21
|
+
config.helpers << ContextMethodHelper
|
22
|
+
end
|
data/spec/render_spec.rb
ADDED
@@ -0,0 +1,263 @@
|
|
1
|
+
require 'minitest_helper'
|
2
|
+
|
3
|
+
describe Rasti::Web::Render do
|
4
|
+
|
5
|
+
let(:request) { Rack::Request.new Hash.new }
|
6
|
+
let(:response) { Rack::Response.new }
|
7
|
+
let(:render) { Rasti::Web::Render.new request, response }
|
8
|
+
|
9
|
+
describe 'Status' do
|
10
|
+
|
11
|
+
it 'Code' do
|
12
|
+
render.status 404
|
13
|
+
|
14
|
+
response.status.must_equal 404
|
15
|
+
response['Content-Type'].must_be_nil
|
16
|
+
response.body.must_equal []
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'Code and body' do
|
20
|
+
render.status 500, 'Internal server error'
|
21
|
+
|
22
|
+
response.status.must_equal 500
|
23
|
+
response['Content-Type'].must_be_nil
|
24
|
+
response.body.must_equal ['Internal server error']
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'Code and headers' do
|
28
|
+
render.status 201, 'Content-Type' => 'application/json'
|
29
|
+
|
30
|
+
response.status.must_equal 201
|
31
|
+
response['Content-Type'].must_equal 'application/json'
|
32
|
+
response.body.must_equal []
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'Code, body and headers' do
|
36
|
+
render.status 403, 'Forbidden', 'Content-Type' => 'text/html'
|
37
|
+
|
38
|
+
response.status.must_equal 403
|
39
|
+
response['Content-Type'].must_equal 'text/html'
|
40
|
+
response.body.must_equal ['Forbidden']
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
describe 'Text' do
|
46
|
+
|
47
|
+
it 'Body' do
|
48
|
+
render.text 'Plain text'
|
49
|
+
|
50
|
+
response.status.must_equal 200
|
51
|
+
response['Content-Type'].must_equal 'text/plain'
|
52
|
+
response.body.must_equal ['Plain text']
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'Body and status' do
|
56
|
+
render.text 'Internal server error', 500
|
57
|
+
|
58
|
+
response.status.must_equal 500
|
59
|
+
response['Content-Type'].must_equal 'text/plain'
|
60
|
+
response.body.must_equal ['Internal server error']
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'Body and headers' do
|
64
|
+
render.text 'Encoded text', 'Content-Encoding' => 'gzip'
|
65
|
+
|
66
|
+
response.status.must_equal 200
|
67
|
+
response['Content-Type'].must_equal 'text/plain'
|
68
|
+
response['Content-Encoding'].must_equal 'gzip'
|
69
|
+
response.body.must_equal ['Encoded text']
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'Body, status and headers' do
|
73
|
+
render.text 'Not found', 404, 'Content-Encoding' => 'gzip'
|
74
|
+
|
75
|
+
response.status.must_equal 404
|
76
|
+
response['Content-Type'].must_equal 'text/plain'
|
77
|
+
response['Content-Encoding'].must_equal 'gzip'
|
78
|
+
response.body.must_equal ['Not found']
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
describe 'HTML' do
|
84
|
+
|
85
|
+
it 'Body' do
|
86
|
+
render.html '<h1>Title</h1>'
|
87
|
+
|
88
|
+
response.status.must_equal 200
|
89
|
+
response['Content-Type'].must_equal 'text/html'
|
90
|
+
response.body.must_equal ['<h1>Title</h1>']
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'Body and status' do
|
94
|
+
render.html '<h1>Internal server error</h1>', 500
|
95
|
+
|
96
|
+
response.status.must_equal 500
|
97
|
+
response['Content-Type'].must_equal 'text/html'
|
98
|
+
response.body.must_equal ['<h1>Internal server error</h1>']
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'Body and headers' do
|
102
|
+
render.html '<p>Encoded text</p>', 'Content-Encoding' => 'gzip'
|
103
|
+
|
104
|
+
response.status.must_equal 200
|
105
|
+
response['Content-Type'].must_equal 'text/html'
|
106
|
+
response['Content-Encoding'].must_equal 'gzip'
|
107
|
+
response.body.must_equal ['<p>Encoded text</p>']
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'Body, status and headers' do
|
111
|
+
render.html '<h1>Not found</h1>', 404, 'Content-Encoding' => 'gzip'
|
112
|
+
|
113
|
+
response.status.must_equal 404
|
114
|
+
response['Content-Type'].must_equal 'text/html'
|
115
|
+
response['Content-Encoding'].must_equal 'gzip'
|
116
|
+
response.body.must_equal ['<h1>Not found</h1>']
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
describe 'Json' do
|
122
|
+
|
123
|
+
let(:object) { {id: 123, color: 'red'} }
|
124
|
+
|
125
|
+
it 'Body' do
|
126
|
+
render.json object
|
127
|
+
|
128
|
+
response.status.must_equal 200
|
129
|
+
response['Content-Type'].must_equal 'application/json'
|
130
|
+
response.body.must_equal [object.to_json]
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'Body string' do
|
134
|
+
render.json '{"x":1,"y":2}'
|
135
|
+
|
136
|
+
response.status.must_equal 200
|
137
|
+
response['Content-Type'].must_equal 'application/json'
|
138
|
+
response.body.must_equal ['{"x":1,"y":2}']
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'Body and status' do
|
142
|
+
render.json object, 422
|
143
|
+
|
144
|
+
response.status.must_equal 422
|
145
|
+
response['Content-Type'].must_equal 'application/json'
|
146
|
+
response.body.must_equal [object.to_json]
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'Body and headers' do
|
150
|
+
render.json object, 'Content-Encoding' => 'gzip'
|
151
|
+
|
152
|
+
response.status.must_equal 200
|
153
|
+
response['Content-Type'].must_equal 'application/json'
|
154
|
+
response['Content-Encoding'].must_equal 'gzip'
|
155
|
+
response.body.must_equal [object.to_json]
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'Body, status and headers' do
|
159
|
+
render.json object, 422, 'Content-Encoding' => 'gzip'
|
160
|
+
|
161
|
+
response.status.must_equal 422
|
162
|
+
response['Content-Type'].must_equal 'application/json'
|
163
|
+
response['Content-Encoding'].must_equal 'gzip'
|
164
|
+
response.body.must_equal [object.to_json]
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
|
169
|
+
describe 'Javascript' do
|
170
|
+
|
171
|
+
it 'Body' do
|
172
|
+
render.js 'alert("hello");'
|
173
|
+
|
174
|
+
response.status.must_equal 200
|
175
|
+
response['Content-Type'].must_equal 'application/javascript'
|
176
|
+
response.body.must_equal ['alert("hello");']
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'Body and status' do
|
180
|
+
render.js 'alert("hello");', 206
|
181
|
+
|
182
|
+
response.status.must_equal 206
|
183
|
+
response['Content-Type'].must_equal 'application/javascript'
|
184
|
+
response.body.must_equal ['alert("hello");']
|
185
|
+
end
|
186
|
+
|
187
|
+
it 'Body and headers' do
|
188
|
+
render.js 'alert("hello");', 'Content-Encoding' => 'gzip'
|
189
|
+
|
190
|
+
response.status.must_equal 200
|
191
|
+
response['Content-Type'].must_equal 'application/javascript'
|
192
|
+
response['Content-Encoding'].must_equal 'gzip'
|
193
|
+
response.body.must_equal ['alert("hello");']
|
194
|
+
end
|
195
|
+
|
196
|
+
it 'Body, status and headers' do
|
197
|
+
render.js 'alert("hello");', 206, 'Content-Encoding' => 'gzip'
|
198
|
+
|
199
|
+
response.status.must_equal 206
|
200
|
+
response['Content-Type'].must_equal 'application/javascript'
|
201
|
+
response['Content-Encoding'].must_equal 'gzip'
|
202
|
+
response.body.must_equal ['alert("hello");']
|
203
|
+
end
|
204
|
+
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'Partial' do
|
208
|
+
render.partial 'context_and_locals', title: 'Welcome', text: 'Hello world'
|
209
|
+
|
210
|
+
response.status.must_equal 200
|
211
|
+
response['Content-Type'].must_equal 'text/html'
|
212
|
+
response.body.must_equal ['<h1>Welcome</h1><div>Hello world</div>']
|
213
|
+
end
|
214
|
+
|
215
|
+
describe 'Layout' do
|
216
|
+
|
217
|
+
it 'Default' do
|
218
|
+
render.layout { 'Page content' }
|
219
|
+
|
220
|
+
response.status.must_equal 200
|
221
|
+
response['Content-Type'].must_equal 'text/html'
|
222
|
+
response.body.must_equal ['<html><body>Page content</body></html>']
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'Custom' do
|
226
|
+
render.layout('custom_layout') { 'Page content' }
|
227
|
+
|
228
|
+
response.status.must_equal 200
|
229
|
+
response['Content-Type'].must_equal 'text/html'
|
230
|
+
response.body.must_equal ['<html><body class="custom">Page content</body></html>']
|
231
|
+
end
|
232
|
+
|
233
|
+
it 'Empty' do
|
234
|
+
render.layout
|
235
|
+
|
236
|
+
response.status.must_equal 200
|
237
|
+
response['Content-Type'].must_equal 'text/html'
|
238
|
+
response.body.must_equal ['<html><body></body></html>']
|
239
|
+
end
|
240
|
+
|
241
|
+
end
|
242
|
+
|
243
|
+
describe 'View' do
|
244
|
+
|
245
|
+
it 'Default layout' do
|
246
|
+
render.view 'context_and_locals', title: 'Welcome', text: 'Hello world'
|
247
|
+
|
248
|
+
response.status.must_equal 200
|
249
|
+
response['Content-Type'].must_equal 'text/html'
|
250
|
+
response.body.must_equal ['<html><body><h1>Welcome</h1><div>Hello world</div></body></html>']
|
251
|
+
end
|
252
|
+
|
253
|
+
it 'Custom layout' do
|
254
|
+
render.view 'context_and_locals', {title: 'Welcome', text: 'Hello world'}, 'custom_layout'
|
255
|
+
|
256
|
+
response.status.must_equal 200
|
257
|
+
response['Content-Type'].must_equal 'text/html'
|
258
|
+
response.body.must_equal ['<html><body class="custom"><h1>Welcome</h1><div>Hello world</div></body></html>']
|
259
|
+
end
|
260
|
+
|
261
|
+
end
|
262
|
+
|
263
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'minitest_helper'
|
2
|
+
|
3
|
+
describe Rasti::Web::Request do
|
4
|
+
|
5
|
+
it 'Route params' do
|
6
|
+
env = Rack::MockRequest.env_for '/'
|
7
|
+
env[Rasti::Web::ROUTE_PARAMS] = {'x' => 1, 'y' => 2}
|
8
|
+
|
9
|
+
request = Rasti::Web::Request.new env
|
10
|
+
|
11
|
+
request['x'].must_equal 1
|
12
|
+
request['y'].must_equal 2
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'Json body params' do
|
16
|
+
env = Rack::MockRequest.env_for '/', input: '{"lat": 10, "lon": 20}', 'CONTENT_TYPE' => 'application/json'
|
17
|
+
|
18
|
+
request = Rasti::Web::Request.new env
|
19
|
+
|
20
|
+
request.must_be :json?
|
21
|
+
request['lat'].must_equal 10
|
22
|
+
request['lon'].must_equal 20
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'No json body params' do
|
26
|
+
env = Rack::MockRequest.env_for '/', input: '{"lat": 10, "lon": 20}', 'CONTENT_TYPE' => 'other/type'
|
27
|
+
|
28
|
+
request = Rasti::Web::Request.new env
|
29
|
+
|
30
|
+
request.wont_be :json?
|
31
|
+
request['lat'].must_be_nil
|
32
|
+
request['lon'].must_be_nil
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
data/spec/route_spec.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'minitest_helper'
|
2
|
+
|
3
|
+
describe Rasti::Web::Route do
|
4
|
+
|
5
|
+
def build_route(pattern, endpoint=:fake_endpoint)
|
6
|
+
Rasti::Web::Route.new pattern, :fake_endpoint
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'Static' do
|
10
|
+
route = build_route '/resource'
|
11
|
+
|
12
|
+
route.pattern.must_equal '/resource'
|
13
|
+
route.regexp.to_s.must_equal /^\/resource$/.to_s
|
14
|
+
route.endpoint.must_equal :fake_endpoint
|
15
|
+
route.params.must_equal []
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'Params' do
|
19
|
+
route = build_route '/resource/:id/:action'
|
20
|
+
|
21
|
+
route.pattern.must_equal '/resource/:id/:action'
|
22
|
+
route.regexp.to_s.must_equal /^\/resource\/([^\/?#]+)\/([^\/?#]+)$/.to_s
|
23
|
+
route.endpoint.must_equal :fake_endpoint
|
24
|
+
route.params.must_equal %w(id action)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'Match' do
|
28
|
+
build_route('/').must_be :match?, '/'
|
29
|
+
build_route('/').wont_be :match?, '/resource'
|
30
|
+
|
31
|
+
build_route('/resource').must_be :match?, '/resource'
|
32
|
+
build_route('/resource').must_be :match?, '/resource/'
|
33
|
+
build_route('/resource').wont_be :match?, '/'
|
34
|
+
|
35
|
+
build_route('/resource/:id/:action').must_be :match?, '/resource/123/show'
|
36
|
+
build_route('/resource/:id/:action').wont_be :match?, '/123/show'
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'Extract params' do
|
40
|
+
build_route('/resource').extract_params('/resource').must_equal Hash.new
|
41
|
+
build_route('/resource/:id/:action').extract_params('/resource/123/show').must_equal 'id' => '123', 'action' => 'show'
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'Normalize path' do
|
45
|
+
build_route('').pattern.must_equal '/'
|
46
|
+
build_route('/').pattern.must_equal '/'
|
47
|
+
build_route('/resource').pattern.must_equal '/resource'
|
48
|
+
build_route('/resource/').pattern.must_equal '/resource'
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'Block endpoint' do
|
52
|
+
route = Rasti::Web::Route.new('/') do |req, res|
|
53
|
+
res.status = 404
|
54
|
+
res['Content-Type'] = 'text/html'
|
55
|
+
res.write '<h1>Not found</h1>'
|
56
|
+
end
|
57
|
+
|
58
|
+
route.endpoint.must_be_instance_of Rasti::Web::Endpoint
|
59
|
+
|
60
|
+
status, headers, response = route.endpoint.call(:fake_env)
|
61
|
+
|
62
|
+
status.must_equal 404
|
63
|
+
headers['Content-Type'].must_equal 'text/html'
|
64
|
+
response.body.must_equal ['<h1>Not found</h1>']
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
data/spec/router_spec.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'minitest_helper'
|
2
|
+
|
3
|
+
describe Rasti::Web::Router do
|
4
|
+
|
5
|
+
let(:router) { Rasti::Web::Router.new }
|
6
|
+
|
7
|
+
def get(path)
|
8
|
+
Rack::MockRequest.env_for path, method: :get
|
9
|
+
end
|
10
|
+
|
11
|
+
def post(path)
|
12
|
+
Rack::MockRequest.env_for path, method: :post
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'Verbs' do
|
16
|
+
%w(delete get head options patch post put).each do |verb|
|
17
|
+
router.must_respond_to verb
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'Route matching' do
|
22
|
+
router.get '/resources', ->(env) { :index }
|
23
|
+
router.post '/resources/:id', ->(env) { :update }
|
24
|
+
router.not_found ->(env) { :not_found }
|
25
|
+
|
26
|
+
router.call(get('/resources')).must_equal :index
|
27
|
+
router.call(post('/resources/123')).must_equal :update
|
28
|
+
router.call(post('/resources')).must_equal :not_found
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'Not found' do
|
32
|
+
status, headers, response = router.call get('/not_found')
|
33
|
+
|
34
|
+
status.must_equal 404
|
35
|
+
response.body.must_equal ['Not found: GET /not_found']
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'minitest_helper'
|
2
|
+
|
3
|
+
describe Rasti::Web::Template do
|
4
|
+
|
5
|
+
class Context
|
6
|
+
include ContextMethodHelper
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'Plain HTML' do
|
10
|
+
Rasti::Web::Template.render('plain_html').must_equal '<div>Hello world</div>'
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'Context method' do
|
14
|
+
Rasti::Web::Template.render('context_method', Context.new).must_equal '<h1>Hello world</h1>'
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'Local variable' do
|
18
|
+
Rasti::Web::Template.render('local_variable', nil, text: 'Welcome').must_equal '<h1>Welcome</h1>'
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'Invalid template' do
|
22
|
+
proc { Rasti::Web::Template.render 'invalid' }.must_raise RuntimeError
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'Nested' do
|
26
|
+
Rasti::Web::Template.render('layout') { 'inner text' }.must_equal '<html><body>inner text</body></html>'
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= page_header title %><div><%= text %></div>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= page_header 'Hello world' %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<html><body class="custom"><%= yield %></body></html>
|
@@ -0,0 +1 @@
|
|
1
|
+
<html><body><%= yield %></body></html>
|
@@ -0,0 +1 @@
|
|
1
|
+
<h1><%= text %></h1>
|
@@ -0,0 +1 @@
|
|
1
|
+
<div>Hello world</div>
|