impression 0.1 → 0.5

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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +1 -0
  3. data/.github/workflows/test.yml +32 -0
  4. data/CHANGELOG.md +23 -0
  5. data/Gemfile +5 -0
  6. data/Gemfile.lock +63 -32
  7. data/README.md +44 -2
  8. data/Rakefile +10 -0
  9. data/examples/markdown/_assets/style.css +98 -0
  10. data/examples/markdown/app.rb +11 -5
  11. data/examples/markdown/docs/tutorial.md +15 -0
  12. data/impression.gemspec +11 -7
  13. data/lib/impression/app.rb +9 -0
  14. data/lib/impression/file_tree.rb +124 -0
  15. data/lib/impression/file_watcher.rb +50 -0
  16. data/lib/impression/jamstack.rb +179 -0
  17. data/lib/impression/request_extensions/responses.rb +48 -0
  18. data/lib/impression/request_extensions/routing.rb +52 -0
  19. data/lib/impression/request_extensions.rb +8 -2
  20. data/lib/impression/resource.rb +168 -0
  21. data/lib/impression/version.rb +1 -1
  22. data/lib/impression.rb +8 -0
  23. data/test/helper.rb +94 -0
  24. data/test/jamstack/_layouts/article.rb +9 -0
  25. data/test/jamstack/_layouts/default.rb +12 -0
  26. data/test/jamstack/articles/2008-06-14-manu.md +6 -0
  27. data/test/jamstack/articles/2009-06-12-noatche.md +6 -0
  28. data/test/jamstack/articles/a.md +6 -0
  29. data/test/jamstack/assets/js/a.js +1 -0
  30. data/test/jamstack/bar.html +1 -0
  31. data/test/jamstack/baz/index.md +7 -0
  32. data/test/jamstack/foo.rb +7 -0
  33. data/test/jamstack/foobar.rb +10 -0
  34. data/test/jamstack/index.md +4 -0
  35. data/test/run.rb +5 -0
  36. data/test/static/bar/index.html +1 -0
  37. data/test/static/foo.html +1 -0
  38. data/test/static/index.html +1 -0
  39. data/test/static/js/a.js +1 -0
  40. data/test/test_app.rb +52 -0
  41. data/test/test_file_tree.rb +116 -0
  42. data/test/test_file_watcher.rb +57 -0
  43. data/test/test_jamstack.rb +263 -0
  44. data/test/test_resource.rb +201 -0
  45. metadata +57 -35
  46. data/lib/impression/pages.rb +0 -120
data/test/test_app.rb ADDED
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+
5
+ class AppTest < MiniTest::Test
6
+ def test_empty_app
7
+ app = Impression::App.new(path: '/')
8
+ req = mock_req(':method' => 'GET', ':path' => '/')
9
+
10
+ app.call(req)
11
+ assert_equal Qeweney::Status::NOT_FOUND, req.adapter.status
12
+ end
13
+
14
+ def test_app_each
15
+ app = Impression::App.new(path: '/')
16
+
17
+ buffer = []
18
+ app.each { |r| buffer << r }
19
+ assert_equal [app], buffer
20
+
21
+ foo = PathRenderingResource.new(parent: app, path: 'foo')
22
+ bar = PathRenderingResource.new(parent: app, path: 'bar')
23
+
24
+ buffer = []
25
+ app.each { |r| buffer << r }
26
+ assert_equal [app, foo, bar], buffer
27
+ end
28
+
29
+ def test_app_to_proc
30
+ app = Impression::App.new(path: '/')
31
+ app_proc = app.to_proc
32
+
33
+ foo = PathRenderingResource.new(parent: app, path: 'foo')
34
+ bar = PathRenderingResource.new(parent: app, path: 'bar')
35
+
36
+ # req = mock_req(':method' => 'GET', ':path' => '/')
37
+ # app_proc.(req)
38
+ # assert_equal Qeweney::Status::NOT_FOUND, req.adapter.status
39
+
40
+ req = mock_req(':method' => 'GET', ':path' => '/foo')
41
+ app_proc.(req)
42
+ assert_equal '/foo', req.adapter.body
43
+
44
+ req = mock_req(':method' => 'GET', ':path' => '/bar')
45
+ app_proc.(req)
46
+ assert_equal '/bar', req.adapter.body
47
+
48
+ req = mock_req(':method' => 'GET', ':path' => '/baz')
49
+ app_proc.(req)
50
+ assert_equal Qeweney::Status::NOT_FOUND, req.adapter.status
51
+ end
52
+ end
@@ -0,0 +1,116 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+ require 'qeweney/test_adapter'
5
+
6
+ class FileTreeTest < MiniTest::Test
7
+ STATIC_PATH = File.join(__dir__, 'static')
8
+
9
+ def setup
10
+ @file_tree = Impression::FileTree.new(path: '/', directory: STATIC_PATH)
11
+ end
12
+
13
+ def test_file_tree_routing
14
+ req = mock_req(':method' => 'GET', ':path' => '/')
15
+ assert_equal @file_tree, @file_tree.route(req)
16
+
17
+ req = mock_req(':method' => 'GET', ':path' => '/nonexistent')
18
+ assert_equal @file_tree, @file_tree.route(req)
19
+
20
+ req = mock_req(':method' => 'GET', ':path' => '/index.html')
21
+ assert_equal @file_tree, @file_tree.route(req)
22
+
23
+ req = mock_req(':method' => 'GET', ':path' => '/foo')
24
+ assert_equal @file_tree, @file_tree.route(req)
25
+ end
26
+
27
+ def static(path)
28
+ IO.read(File.join(STATIC_PATH, path))
29
+ end
30
+
31
+ def test_file_tree_response
32
+ req = mock_req(':method' => 'GET', ':path' => '/roo')
33
+ @file_tree.route_and_call(req)
34
+ assert_equal Qeweney::Status::NOT_FOUND, req.response_status
35
+
36
+ req = mock_req(':method' => 'GET', ':path' => '/foo2')
37
+ @file_tree.route_and_call(req)
38
+ assert_equal Qeweney::Status::NOT_FOUND, req.response_status
39
+
40
+ req = mock_req(':method' => 'GET', ':path' => '/bar2')
41
+ @file_tree.route_and_call(req)
42
+ assert_equal Qeweney::Status::NOT_FOUND, req.response_status
43
+
44
+ req = mock_req(':method' => 'GET', ':path' => '/js/a.js')
45
+ @file_tree.route_and_call(req)
46
+ assert_response static('js/a.js'), :js, req
47
+
48
+ req = mock_req(':method' => 'GET', ':path' => '/foo.html')
49
+ @file_tree.route_and_call(req)
50
+ assert_response static('foo.html'), :html, req
51
+
52
+ req = mock_req(':method' => 'GET', ':path' => '/foo')
53
+ @file_tree.route_and_call(req)
54
+ assert_response static('foo.html'), :html, req
55
+
56
+ req = mock_req(':method' => 'GET', ':path' => '/index.html')
57
+ @file_tree.route_and_call(req)
58
+ assert_response static('index.html'), :html, req
59
+
60
+ req = mock_req(':method' => 'GET', ':path' => '/')
61
+ @file_tree.route_and_call(req)
62
+ assert_response static('index.html'), :html, req
63
+
64
+ req = mock_req(':method' => 'GET', ':path' => '/bar/index.html')
65
+ @file_tree.route_and_call(req)
66
+ assert_response static('bar/index.html'), :html, req
67
+
68
+ req = mock_req(':method' => 'GET', ':path' => '/bar')
69
+ @file_tree.route_and_call(req)
70
+ assert_response static('bar/index.html'), :html, req
71
+ end
72
+
73
+ def test_non_root_file_tree_response
74
+ @file_tree = Impression::FileTree.new(path: '/app', directory: STATIC_PATH)
75
+
76
+ req = mock_req(':method' => 'GET', ':path' => '/app/roo')
77
+ @file_tree.route_and_call(req)
78
+ assert_equal Qeweney::Status::NOT_FOUND, req.response_status
79
+
80
+ req = mock_req(':method' => 'GET', ':path' => '/app/foo2')
81
+ @file_tree.route_and_call(req)
82
+ assert_equal Qeweney::Status::NOT_FOUND, req.response_status
83
+
84
+ req = mock_req(':method' => 'GET', ':path' => '/app/bar2')
85
+ @file_tree.route_and_call(req)
86
+ assert_equal Qeweney::Status::NOT_FOUND, req.response_status
87
+
88
+ req = mock_req(':method' => 'GET', ':path' => '/app/js/a.js')
89
+ @file_tree.route_and_call(req)
90
+ assert_response static('js/a.js'), :js, req
91
+
92
+ req = mock_req(':method' => 'GET', ':path' => '/app/foo.html')
93
+ @file_tree.route_and_call(req)
94
+ assert_response static('foo.html'), :html, req
95
+
96
+ req = mock_req(':method' => 'GET', ':path' => '/app/foo')
97
+ @file_tree.route_and_call(req)
98
+ assert_response static('foo.html'), :html, req
99
+
100
+ req = mock_req(':method' => 'GET', ':path' => '/app/index.html')
101
+ @file_tree.route_and_call(req)
102
+ assert_response static('index.html'), :html, req
103
+
104
+ req = mock_req(':method' => 'GET', ':path' => '/app/')
105
+ @file_tree.route_and_call(req)
106
+ assert_response static('index.html'), :html, req
107
+
108
+ req = mock_req(':method' => 'GET', ':path' => '/app/bar/index.html')
109
+ @file_tree.route_and_call(req)
110
+ assert_response static('bar/index.html'), :html, req
111
+
112
+ req = mock_req(':method' => 'GET', ':path' => '/app/bar')
113
+ @file_tree.route_and_call(req)
114
+ assert_response static('bar/index.html'), :html, req
115
+ end
116
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+ require 'fileutils'
5
+
6
+ # class FileWatcherTest < MiniTest::Test
7
+ # def setup
8
+ # @tmp_path = File.expand_path('../tmp', __dir__)
9
+ # FileUtils.mkdir(@tmp_path)
10
+ # end
11
+
12
+ # def teardown
13
+ # FileUtils.rm_rf(@tmp_path)
14
+ # end
15
+
16
+ # def test_directory_watcher
17
+ # watcher = Impression::FileWatcher.new(@tmp_path)
18
+ # file_path = File.join(@tmp_path, 'foo')
19
+
20
+ # buffer = []
21
+ # spin do
22
+ # watcher.each { |kind, path| buffer << [kind, path] }
23
+ # end
24
+
25
+ # assert_equal [], buffer
26
+
27
+ # # create
28
+ # buffer.clear
29
+ # IO.write(file_path, 'bar')
30
+ # sleep 0.01
31
+ # assert_equal [[:create, file_path]], buffer
32
+
33
+ # # modify
34
+ # buffer.clear
35
+ # IO.write(file_path, 'baz')
36
+ # sleep 0.01
37
+ # assert_equal [[:modify, file_path]], buffer
38
+
39
+ # # move
40
+ # tmp_file_path = File.join("/tmp/#{rand(1024)}")
41
+ # file2_path = File.join(@tmp_path, 'foo2')
42
+ # buffer.clear
43
+ # IO.write(tmp_file_path, '---')
44
+ # FileUtils.mv(tmp_file_path, file2_path)
45
+ # sleep 0.01
46
+ # assert_equal [[:moved_to, file2_path]], buffer
47
+
48
+ # # delete
49
+ # buffer.clear
50
+ # FileUtils.rm(file_path)
51
+ # sleep 0.01
52
+ # assert_equal [[:delete, file_path]], buffer
53
+ # end
54
+
55
+ # def test_recursive_directory_watcher
56
+ # end
57
+ # end
@@ -0,0 +1,263 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+ require 'qeweney/test_adapter'
5
+
6
+ class JamstackTest < MiniTest::Test
7
+ JAMSTACK_PATH = File.join(__dir__, 'jamstack')
8
+
9
+ def setup
10
+ @jamstack = Impression::Jamstack.new(path: '/', directory: JAMSTACK_PATH)
11
+ end
12
+
13
+ def test_jamstack_routing
14
+ req = mock_req(':method' => 'GET', ':path' => '/')
15
+ assert_equal @jamstack, @jamstack.route(req)
16
+
17
+ req = mock_req(':method' => 'GET', ':path' => '/nonexistent')
18
+ assert_equal @jamstack, @jamstack.route(req)
19
+
20
+ req = mock_req(':method' => 'GET', ':path' => '/index.html')
21
+ assert_equal @jamstack, @jamstack.route(req)
22
+
23
+ req = mock_req(':method' => 'GET', ':path' => '/foo')
24
+ assert_equal @jamstack, @jamstack.route(req)
25
+ end
26
+
27
+ def static(path)
28
+ IO.read(File.join(JAMSTACK_PATH, path))
29
+ end
30
+
31
+ def test_jamstack_response
32
+ req = mock_req(':method' => 'GET', ':path' => '/roo')
33
+ @jamstack.route_and_call(req)
34
+ assert_equal Qeweney::Status::NOT_FOUND, req.response_status
35
+
36
+ req = mock_req(':method' => 'GET', ':path' => '/foo2')
37
+ @jamstack.route_and_call(req)
38
+ assert_equal Qeweney::Status::NOT_FOUND, req.response_status
39
+
40
+ req = mock_req(':method' => 'GET', ':path' => '/bar2')
41
+ @jamstack.route_and_call(req)
42
+ assert_equal Qeweney::Status::NOT_FOUND, req.response_status
43
+
44
+ req = mock_req(':method' => 'GET', ':path' => '/assets/js/a.js')
45
+ @jamstack.route_and_call(req)
46
+ assert_response static('assets/js/a.js'), :js, req
47
+
48
+ req = mock_req(':method' => 'GET', ':path' => '/foo')
49
+ @jamstack.route_and_call(req)
50
+
51
+ foo = H {
52
+ html5 {
53
+ head {
54
+ title 'Foo title'
55
+ }
56
+ body {
57
+ h1 'foo'
58
+ }
59
+ }
60
+ }
61
+ assert_response foo.render, :html, req
62
+
63
+ req = mock_req(':method' => 'GET', ':path' => '/index')
64
+ @jamstack.route_and_call(req)
65
+
66
+ index = H {
67
+ html5 {
68
+ head {
69
+ title 'Hello'
70
+ }
71
+ body {
72
+ h1 'Index'
73
+ }
74
+ }
75
+ }
76
+ assert_response index.render, :html, req
77
+
78
+ req = mock_req(':method' => 'GET', ':path' => '/')
79
+ @jamstack.route_and_call(req)
80
+ assert_response index.render, :html, req
81
+
82
+ req = mock_req(':method' => 'GET', ':path' => '/bar')
83
+ @jamstack.route_and_call(req)
84
+ assert_response static('bar.html'), :html, req
85
+
86
+ req = mock_req(':method' => 'GET', ':path' => '/baz')
87
+ @jamstack.route_and_call(req)
88
+
89
+ baz_index = H {
90
+ html5 {
91
+ head {
92
+ title 'BarBar'
93
+ }
94
+ body {
95
+ h1 'BarIndex'
96
+ }
97
+ }
98
+ }
99
+ assert_response baz_index.render, :html, req
100
+
101
+ req = mock_req(':method' => 'GET', ':path' => '/articles/a')
102
+ @jamstack.route_and_call(req)
103
+
104
+ a = H {
105
+ html5 {
106
+ head {
107
+ title 'AAA'
108
+ }
109
+ body {
110
+ article {
111
+ h2 'BBB', id: 'bbb'
112
+ }
113
+ }
114
+ }
115
+ }
116
+ assert_response a.render, :html, req
117
+ end
118
+
119
+ def test_non_root_jamstack_response
120
+ @jamstack = Impression::Jamstack.new(path: '/app', directory: JAMSTACK_PATH)
121
+
122
+ req = mock_req(':method' => 'GET', ':path' => '/app/roo')
123
+ @jamstack.route_and_call(req)
124
+ assert_equal Qeweney::Status::NOT_FOUND, req.response_status
125
+
126
+ req = mock_req(':method' => 'GET', ':path' => '/app/foo2')
127
+ @jamstack.route_and_call(req)
128
+ assert_equal Qeweney::Status::NOT_FOUND, req.response_status
129
+
130
+ req = mock_req(':method' => 'GET', ':path' => '/app/bar2')
131
+ @jamstack.route_and_call(req)
132
+ assert_equal Qeweney::Status::NOT_FOUND, req.response_status
133
+
134
+ req = mock_req(':method' => 'GET', ':path' => '/app/assets/js/a.js')
135
+ @jamstack.route_and_call(req)
136
+ assert_response static('assets/js/a.js'), :js, req
137
+
138
+ req = mock_req(':method' => 'GET', ':path' => '/app/foo')
139
+ @jamstack.route_and_call(req)
140
+
141
+ foo = H {
142
+ html5 {
143
+ head {
144
+ title 'Foo title'
145
+ }
146
+ body {
147
+ h1 'foo'
148
+ }
149
+ }
150
+ }
151
+ assert_response foo.render, :html, req
152
+
153
+ req = mock_req(':method' => 'GET', ':path' => '/app/index')
154
+ @jamstack.route_and_call(req)
155
+
156
+ index = H {
157
+ html5 {
158
+ head {
159
+ title 'Hello'
160
+ }
161
+ body {
162
+ h1 'Index'
163
+ }
164
+ }
165
+ }
166
+ assert_response index.render, :html, req
167
+
168
+ req = mock_req(':method' => 'GET', ':path' => '/app/')
169
+ @jamstack.route_and_call(req)
170
+ assert_response index.render, :html, req
171
+
172
+ req = mock_req(':method' => 'GET', ':path' => '/app/bar')
173
+ @jamstack.route_and_call(req)
174
+ assert_response static('bar.html'), :html, req
175
+
176
+ req = mock_req(':method' => 'GET', ':path' => '/app/baz')
177
+ @jamstack.route_and_call(req)
178
+
179
+ baz_index = H {
180
+ html5 {
181
+ head {
182
+ title 'BarBar'
183
+ }
184
+ body {
185
+ h1 'BarIndex'
186
+ }
187
+ }
188
+ }
189
+ assert_response baz_index.render, :html, req
190
+
191
+ req = mock_req(':method' => 'GET', ':path' => '/app/articles/a')
192
+ @jamstack.route_and_call(req)
193
+
194
+ a = H {
195
+ html5 {
196
+ head {
197
+ title 'AAA'
198
+ }
199
+ body {
200
+ article {
201
+ h2 'BBB', id: 'bbb'
202
+ }
203
+ }
204
+ }
205
+ }
206
+ assert_response a.render, :html, req
207
+ end
208
+
209
+ def test_page_list
210
+ @jamstack = Impression::Jamstack.new(path: '/app', directory: JAMSTACK_PATH)
211
+
212
+ list = @jamstack.page_list('/')
213
+ assert_equal [
214
+ { path: File.join(JAMSTACK_PATH, 'bar.html'), url: '/app/bar' },
215
+ { path: File.join(JAMSTACK_PATH, 'index.md'), title: 'Hello', url: '/app/index' },
216
+ ], list
217
+
218
+
219
+ list = @jamstack.page_list('/articles')
220
+ assert_equal [
221
+ {
222
+ path: File.join(JAMSTACK_PATH, 'articles/2008-06-14-manu.md'),
223
+ url: '/app/articles/2008-06-14-manu',
224
+ title: 'MMM',
225
+ layout: 'article',
226
+ date: Date.new(2008, 06, 14)
227
+ },
228
+ {
229
+ path: File.join(JAMSTACK_PATH, 'articles/2009-06-12-noatche.md'),
230
+ url: '/app/articles/2009-06-12-noatche',
231
+ title: 'NNN',
232
+ layout: 'article',
233
+ date: Date.new(2009, 06, 12)
234
+ },
235
+ {
236
+ path: File.join(JAMSTACK_PATH, 'articles/a.md'),
237
+ url: '/app/articles/a',
238
+ title: 'AAA',
239
+ layout: 'article'
240
+ },
241
+ ], list
242
+ end
243
+
244
+ def test_template_resource_and_request
245
+ req = mock_req(':method' => 'GET', ':path' => '/foobar?q=42')
246
+ @jamstack.route_and_call(req)
247
+
248
+ foo = H {
249
+ html5 {
250
+ head {
251
+ title 'Foobar'
252
+ }
253
+ body {
254
+ h1 '42'
255
+ a 'MMM', href: '/articles/2008-06-14-manu'
256
+ a 'NNN', href: '/articles/2009-06-12-noatche'
257
+ a 'AAA', href: '/articles/a'
258
+ }
259
+ }
260
+ }
261
+ assert_response foo.render, :html, req
262
+ end
263
+ end
@@ -0,0 +1,201 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+
5
+ class ResourceTest < MiniTest::Test
6
+ def test_absolute_path
7
+ r1 = Impression::Resource.new(path: 'foo')
8
+ assert_equal '/foo', r1.absolute_path
9
+
10
+ r2 = Impression::Resource.new(parent: r1, path: 'bar')
11
+ assert_equal '/foo/bar', r2.absolute_path
12
+ end
13
+
14
+ def test_each
15
+ r1 = Impression::Resource.new(path: 'foo')
16
+ r2 = Impression::Resource.new(parent: r1, path: 'bar')
17
+ r3 = Impression::Resource.new(parent: r1, path: 'baz')
18
+
19
+ assert_equal [r2, r3], r1.children.values
20
+
21
+ buffer = []
22
+ r1.each { |r| buffer << r }
23
+ assert_equal [r1, r2, r3], buffer
24
+ end
25
+
26
+ def test_route
27
+ r1 = Impression::Resource.new(path: 'foo')
28
+ r2 = Impression::Resource.new(parent: r1, path: 'bar')
29
+ r3 = Impression::Resource.new(parent: r1, path: 'baz')
30
+ r4 = Impression::Resource.new(parent: r2, path: 'littlebar')
31
+
32
+ assert_equal [r2, r3], r1.children.values
33
+ assert_equal [r4], r2.children.values
34
+
35
+ req = mock_req(':method' => 'GET', ':path' => '/')
36
+ assert_nil r1.route(req)
37
+ assert_equal '/', req.resource_relative_path
38
+
39
+ req = mock_req(':method' => 'GET', ':path' => '/foo2')
40
+ assert_nil r1.route(req)
41
+ assert_equal '/foo2', req.resource_relative_path
42
+
43
+ req = mock_req(':method' => 'GET', ':path' => '/foo')
44
+ assert_equal r1, r1.route(req)
45
+ assert_equal '/', req.resource_relative_path
46
+
47
+ req = mock_req(':method' => 'GET', ':path' => '/foo/bar')
48
+ assert_equal r2, r1.route(req)
49
+ assert_equal '/', req.resource_relative_path
50
+
51
+ req = mock_req(':method' => 'GET', ':path' => '/foo/baz')
52
+ assert_equal r3, r1.route(req)
53
+ assert_equal '/', req.resource_relative_path
54
+
55
+ req = mock_req(':method' => 'GET', ':path' => '/foo/bar/littlebar')
56
+ assert_equal r4, r1.route(req)
57
+ assert_equal '/', req.resource_relative_path
58
+
59
+ req = mock_req(':method' => 'GET', ':path' => '/foo/bar/littlebar/littlebaz')
60
+ assert_equal r4, r1.route(req)
61
+ assert_equal '/littlebaz', req.resource_relative_path
62
+
63
+ req = mock_req(':method' => 'GET', ':path' => '/foo/hi')
64
+ assert_equal r1, r1.route(req)
65
+ assert_equal '/hi', req.resource_relative_path
66
+
67
+ req = mock_req(':method' => 'GET', ':path' => '/foo/hi/bye')
68
+ assert_equal r1, r1.route(req)
69
+ assert_equal '/hi/bye', req.resource_relative_path
70
+ end
71
+
72
+ def test_nested_resource_rendering
73
+ r1 = Impression::Resource.new(path: 'foo')
74
+ r2 = PathRenderingResource.new(parent: r1, path: 'bar')
75
+ r3 = PathRenderingResource.new(parent: r1, path: 'baz')
76
+
77
+ req = mock_req(':method' => 'GET', ':path' => '/')
78
+ assert_nil r1.route(req)
79
+
80
+ req = mock_req(':method' => 'GET', ':path' => '/foo')
81
+ r1.route_and_call(req)
82
+ # default reply
83
+ assert_equal Qeweney::Status::NOT_FOUND, req.response_status
84
+
85
+ req = mock_req(':method' => 'GET', ':path' => '/foo/bar')
86
+ r1.route_and_call(req)
87
+ assert_equal '/foo/bar', req.response_body
88
+
89
+ req = mock_req(':method' => 'GET', ':path' => '/foo/baz')
90
+ r1.route_and_call(req)
91
+ assert_equal '/foo/baz', req.response_body
92
+
93
+ req = mock_req(':method' => 'GET', ':path' => '/foo/bbb')
94
+ assert_equal r1, r1.route(req)
95
+ end
96
+
97
+ def test_relative_path
98
+ r1 = CompletePathInfoRenderingResource.new(path: 'foo')
99
+ r2 = CompletePathInfoRenderingResource.new(parent: r1, path: 'bar')
100
+ r3 = CompletePathInfoRenderingResource.new(parent: r1, path: 'baz')
101
+
102
+ req = mock_req(':method' => 'GET', ':path' => '/')
103
+ assert_nil r1.route(req)
104
+
105
+ req = mock_req(':method' => 'GET', ':path' => '/foo')
106
+ r1.route_and_call(req)
107
+ assert_equal '/foo /', req.response_body
108
+
109
+ req = mock_req(':method' => 'GET', ':path' => '/foo/zzz')
110
+ r1.route_and_call(req)
111
+ assert_equal '/foo /zzz', req.response_body
112
+
113
+ req = mock_req(':method' => 'GET', ':path' => '/foo/bar')
114
+ r1.route_and_call(req)
115
+ assert_equal '/foo/bar /', req.response_body
116
+
117
+ req = mock_req(':method' => 'GET', ':path' => '/foo/bar/zzz')
118
+ r1.route_and_call(req)
119
+ assert_equal '/foo/bar /zzz', req.response_body
120
+
121
+ req = mock_req(':method' => 'GET', ':path' => '/foo/baz')
122
+ r1.route_and_call(req)
123
+ assert_equal '/foo/baz /', req.response_body
124
+
125
+ req = mock_req(':method' => 'GET', ':path' => '/foo/baz/xxx/yyy')
126
+ r1.route_and_call(req)
127
+ assert_equal '/foo/baz /xxx/yyy', req.response_body
128
+ end
129
+
130
+ class CallableResource < Impression::Resource
131
+ def initialize(**props, &block)
132
+ super(**props)
133
+ @block = block
134
+ end
135
+
136
+ def call(req)
137
+ @block.call(req)
138
+ end
139
+ end
140
+
141
+ def test_callable_resource
142
+ r1 = CompletePathInfoRenderingResource.new(path: 'foo')
143
+ r2 = CallableResource.new(parent: r1, path: 'bar') { |req| req.respond('hi') }
144
+
145
+ req = mock_req(':method' => 'GET', ':path' => '/foo/bar')
146
+ r1.route_and_call(req)
147
+ assert_equal 'hi', req.response_body
148
+ end
149
+
150
+ class CallableRouteResource < Impression::Resource
151
+ def initialize(**props, &block)
152
+ super(**props)
153
+ @block = block
154
+ end
155
+
156
+ def route(req)
157
+ @block
158
+ end
159
+ end
160
+
161
+ def test_callable_from_route_method
162
+ r1 = CompletePathInfoRenderingResource.new(path: 'foo')
163
+ r2 = CallableRouteResource.new(parent: r1, path: 'bar') { |req| req.respond('bye') }
164
+
165
+ req = mock_req(':method' => 'GET', ':path' => '/foo/bar')
166
+ r1.route_and_call(req)
167
+ assert_equal 'bye', req.response_body
168
+ end
169
+
170
+ def test_text_response
171
+ c = Class.new(Impression::Resource) do
172
+ def route(req)
173
+ case req.path
174
+ when '/text'
175
+ text_response('foo')
176
+ when '/html'
177
+ html_response('bar')
178
+ when '/json'
179
+ json_response({ :baz => 123 })
180
+ end
181
+ end
182
+ end
183
+
184
+ r = c.new(path: '/')
185
+
186
+ req = mock_req(':method' => 'GET', ':path' => '/text')
187
+ r.route_and_call(req)
188
+ assert_equal 'foo', req.response_body
189
+ assert_equal 'text/plain', req.response_content_type
190
+
191
+ req = mock_req(':method' => 'GET', ':path' => '/html')
192
+ r.route_and_call(req)
193
+ assert_equal 'bar', req.response_body
194
+ assert_equal 'text/html', req.response_content_type
195
+
196
+ req = mock_req(':method' => 'GET', ':path' => '/json')
197
+ r.route_and_call(req)
198
+ assert_equal '{"baz":123}', req.response_body
199
+ assert_equal 'application/json', req.response_content_type
200
+ end
201
+ end