syntropy 0.33.0 → 0.34.0
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 +4 -4
- data/CHANGELOG.md +7 -0
- data/cmd/console.rb +18 -7
- data/cmd/serve.rb +26 -18
- data/cmd/test.rb +37 -24
- data/examples/blog/.gitignore +1 -0
- data/examples/blog/app/_lib/database.rb +13 -0
- data/examples/blog/app/_lib/{post_store.rb → posts.rb} +3 -1
- data/examples/blog/app/posts/[id]/edit.rb +2 -2
- data/examples/blog/app/posts/[id]/index.rb +4 -4
- data/examples/blog/app/posts/index.rb +4 -4
- data/examples/blog/app/posts/new.rb +1 -1
- data/examples/blog/config/development.rb +5 -0
- data/examples/blog/config/production.rb +4 -0
- data/examples/blog/config/test.rb +5 -0
- data/examples/blog/test/test_posts.rb +65 -0
- data/examples/mcp-oauth/app/oauth/token.rb +1 -1
- data/lib/syntropy/app.rb +48 -40
- data/lib/syntropy/applets/builtin/auto_refresh/watch.sse.rb +1 -1
- data/lib/syntropy/db/schema.rb +1 -1
- data/lib/syntropy/db/store.rb +2 -0
- data/lib/syntropy/errors.rb +6 -2
- data/lib/syntropy/http/client.rb +1 -0
- data/lib/syntropy/http/server_connection.rb +0 -4
- data/lib/syntropy/json_api.rb +27 -1
- data/lib/syntropy/logger.rb +81 -27
- data/lib/syntropy/markdown.rb +61 -32
- data/lib/syntropy/mime_types.rb +9 -5
- data/lib/syntropy/module_loader.rb +20 -9
- data/lib/syntropy/papercraft_extensions.rb +2 -2
- data/lib/syntropy/request/mock_adapter.rb +10 -8
- data/lib/syntropy/request/request_info.rb +91 -0
- data/lib/syntropy/request/response.rb +1 -12
- data/lib/syntropy/request/validation.rb +1 -0
- data/lib/syntropy/request.rb +51 -19
- data/lib/syntropy/routing_tree.rb +27 -28
- data/lib/syntropy/session.rb +198 -0
- data/lib/syntropy/side_run.rb +25 -2
- data/lib/syntropy/test.rb +105 -10
- data/lib/syntropy/utils.rb +53 -18
- data/lib/syntropy/version.rb +1 -1
- data/lib/syntropy.rb +44 -10
- data/test/bm_router_proc.rb +4 -4
- data/test/fixtures/app/class_instance.rb +5 -0
- data/test/fixtures/app/http.rb +5 -0
- data/test/fixtures/app/post_ct.rb +5 -0
- data/test/fixtures/app/singleton.rb +3 -0
- data/test/test_app.rb +13 -52
- data/test/test_caching.rb +2 -2
- data/test/test_db_schema.rb +1 -1
- data/test/test_http_server_connection.rb +3 -3
- data/test/test_module_loader.rb +5 -2
- data/test/test_response.rb +0 -19
- data/test/test_routing_tree.rb +69 -69
- data/test/test_server.rb +5 -9
- data/test/test_test.rb +70 -0
- metadata +52 -42
- data/examples/blog/app/_setup.rb +0 -4
- data/lib/syntropy/request/session.rb +0 -113
- /data/test/{app → fixtures/app}/.well-known/foo.rb +0 -0
- /data/test/{app → fixtures/app}/_hook.rb +0 -0
- /data/test/{app → fixtures/app}/_layout/default.rb +0 -0
- /data/test/{app → fixtures/app}/_lib/callable.rb +0 -0
- /data/test/{app → fixtures/app}/_lib/dep.rb +0 -0
- /data/test/{app → fixtures/app}/_lib/env.rb +0 -0
- /data/test/{app → fixtures/app}/_lib/klass.rb +0 -0
- /data/test/{app → fixtures/app}/_lib/missing-export.rb +0 -0
- /data/test/{app → fixtures/app}/_lib/self.rb +0 -0
- /data/test/{app → fixtures/app}/about/_error.rb +0 -0
- /data/test/{app → fixtures/app}/about/foo.md +0 -0
- /data/test/{app → fixtures/app}/about/index.rb +0 -0
- /data/test/{app → fixtures/app}/about/raise.rb +0 -0
- /data/test/{app → fixtures/app}/api+.rb +0 -0
- /data/test/{app → fixtures/app}/assets/style.css +0 -0
- /data/test/{app → fixtures/app}/bad_mod.rb +0 -0
- /data/test/{app → fixtures/app}/bar.rb +0 -0
- /data/test/{app → fixtures/app}/baz.rb +0 -0
- /data/test/{app → fixtures/app}/by_method.rb +0 -0
- /data/test/{app → fixtures/app}/deps.rb +0 -0
- /data/test/{app → fixtures/app}/index.html +0 -0
- /data/test/{app → fixtures/app}/mod/bar/index+.rb +0 -0
- /data/test/{app → fixtures/app}/mod/foo/index.rb +0 -0
- /data/test/{app → fixtures/app}/mod/path/a.rb +0 -0
- /data/test/{app → fixtures/app}/mod/path/b.rb +0 -0
- /data/test/{app → fixtures/app}/params/[foo].rb +0 -0
- /data/test/{app → fixtures/app}/rss.rb +0 -0
- /data/test/{app → fixtures/app}/tmp.rb +0 -0
- /data/test/{app_custom → fixtures/app_custom}/_site.rb +0 -0
- /data/test/{app_multi_site → fixtures/app_multi_site}/_site.rb +0 -0
- /data/test/{app_multi_site → fixtures/app_multi_site}/bar.baz/index.html +0 -0
- /data/test/{app_multi_site → fixtures/app_multi_site}/foo.bar/index.html +0 -0
- /data/test/{app_setup → fixtures/app_setup}/_setup.rb +0 -0
- /data/test/{app_setup → fixtures/app_setup}/index.rb +0 -0
- /data/test/{app_with_schema → fixtures/app_with_schema}/_schema/2026-01-02-foo.rb +0 -0
- /data/test/{app_with_schema → fixtures/app_with_schema}/_schema/2026-05-30-bar.rb +0 -0
- /data/test/{schema → fixtures/schema}/2026-01-02-foo.rb +0 -0
- /data/test/{schema → fixtures/schema}/2026-05-30-bar.rb +0 -0
data/test/test_routing_tree.rb
CHANGED
|
@@ -54,19 +54,19 @@ class RoutingTreeTest < Minitest::Test
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
def setup
|
|
57
|
-
@
|
|
58
|
-
make_tmp_file_tree(@
|
|
59
|
-
@rt = Syntropy::RoutingTree.new(
|
|
57
|
+
@app_root = "/tmp/#{__FILE__.gsub('/', '-')}-#{SecureRandom.hex}"
|
|
58
|
+
make_tmp_file_tree(@app_root, FILE_TREE)
|
|
59
|
+
@rt = Syntropy::RoutingTree.new(app_root: File.join(@app_root, 'site'), mount_path: '/docs')
|
|
60
60
|
end
|
|
61
61
|
|
|
62
62
|
def test_compute_clean_url_path
|
|
63
63
|
c = ->(fn) { @rt.send(:compute_clean_url_path, fn) }
|
|
64
|
-
assert_equal '/', c.(File.join(@rt.
|
|
65
|
-
assert_equal '/about', c.(File.join(@rt.
|
|
66
|
-
assert_equal '/[org]', c.(File.join(@rt.
|
|
67
|
-
assert_equal '/favicon.ico', c.(File.join(@rt.
|
|
68
|
-
assert_equal '/assets/style.css', c.(File.join(@rt.
|
|
69
|
-
assert_equal '/foo.js', c.(File.join(@rt.
|
|
64
|
+
assert_equal '/', c.(File.join(@rt.app_root, '/index.rb'))
|
|
65
|
+
assert_equal '/about', c.(File.join(@rt.app_root, '/about.md'))
|
|
66
|
+
assert_equal '/[org]', c.(File.join(@rt.app_root, '/[org]'))
|
|
67
|
+
assert_equal '/favicon.ico', c.(File.join(@rt.app_root, '/favicon.ico'))
|
|
68
|
+
assert_equal '/assets/style.css', c.(File.join(@rt.app_root, '/assets/style.css'))
|
|
69
|
+
assert_equal '/foo.js', c.(File.join(@rt.app_root, '/foo.js'))
|
|
70
70
|
end
|
|
71
71
|
|
|
72
72
|
def test_routing_tree_generation
|
|
@@ -80,40 +80,40 @@ class RoutingTreeTest < Minitest::Test
|
|
|
80
80
|
], root[:children].keys.sort_by(&:to_s)
|
|
81
81
|
|
|
82
82
|
entry = @rt.static_map['/docs']
|
|
83
|
-
assert_equal File.join(@rt.
|
|
83
|
+
assert_equal File.join(@rt.app_root, 'index.rb'), entry[:target][:fn]
|
|
84
84
|
|
|
85
85
|
about = root[:children]['about']
|
|
86
86
|
assert_equal '/docs/about', about[:path]
|
|
87
87
|
assert_equal root, about[:parent]
|
|
88
|
-
assert_equal File.join(@rt.
|
|
88
|
+
assert_equal File.join(@rt.app_root, 'about.md'), about[:target][:fn]
|
|
89
89
|
assert_nil about[:children]
|
|
90
90
|
|
|
91
91
|
org = root[:children]['[]']
|
|
92
92
|
assert_equal '/docs/[org]', org[:path]
|
|
93
93
|
assert_equal 'org', org[:param]
|
|
94
94
|
refute_nil org[:target]
|
|
95
|
-
assert_equal File.join(@rt.
|
|
95
|
+
assert_equal File.join(@rt.app_root, '[org]/index.rb'), org[:target][:fn]
|
|
96
96
|
assert_equal ['[]'], org[:children].keys.sort_by(&:to_s)
|
|
97
97
|
|
|
98
98
|
repo = org[:children]['[]']
|
|
99
99
|
assert_equal org, repo[:parent]
|
|
100
100
|
assert_equal '/docs/[org]/[repo]', repo[:path]
|
|
101
101
|
assert_equal 'repo', repo[:param]
|
|
102
|
-
assert_equal File.join(@rt.
|
|
102
|
+
assert_equal File.join(@rt.app_root, '[org]/[repo]/index.rb'), repo[:target][:fn]
|
|
103
103
|
assert_equal ['commits', 'issues'], repo[:children].keys.sort_by(&:to_s)
|
|
104
104
|
|
|
105
105
|
issues = repo[:children]['issues']
|
|
106
106
|
assert_equal repo, issues[:parent]
|
|
107
107
|
assert_equal '/docs/[org]/[repo]/issues', issues[:path]
|
|
108
108
|
assert_nil issues[:param]
|
|
109
|
-
assert_equal File.join(@rt.
|
|
109
|
+
assert_equal File.join(@rt.app_root, '[org]/[repo]/issues/index.rb'), issues[:target][:fn]
|
|
110
110
|
assert_equal ['[]'], issues[:children].keys.sort_by(&:to_s)
|
|
111
111
|
|
|
112
112
|
id = issues[:children]['[]']
|
|
113
113
|
assert_equal issues, id[:parent]
|
|
114
114
|
assert_equal '/docs/[org]/[repo]/issues/[id]', id[:path]
|
|
115
115
|
assert_equal 'id', id[:param]
|
|
116
|
-
assert_equal File.join(@rt.
|
|
116
|
+
assert_equal File.join(@rt.app_root, '[org]/[repo]/issues/[id]/index.rb'), id[:target][:fn]
|
|
117
117
|
assert_equal [], id[:children].keys.sort_by(&:to_s)
|
|
118
118
|
|
|
119
119
|
posts = root[:children]['posts']
|
|
@@ -126,7 +126,7 @@ class RoutingTreeTest < Minitest::Test
|
|
|
126
126
|
assert_equal posts, id[:parent]
|
|
127
127
|
assert_equal '/docs/posts/[id]', id[:path]
|
|
128
128
|
assert_equal 'id', id[:param]
|
|
129
|
-
assert_equal File.join(@rt.
|
|
129
|
+
assert_equal File.join(@rt.app_root, 'posts/[id].rb'), id[:target][:fn]
|
|
130
130
|
assert_nil id[:children]
|
|
131
131
|
|
|
132
132
|
old = root[:children]['old']
|
|
@@ -154,35 +154,35 @@ class RoutingTreeTest < Minitest::Test
|
|
|
154
154
|
], keys
|
|
155
155
|
|
|
156
156
|
o = map['/docs/.well-known/foo']
|
|
157
|
-
assert_equal File.join(@rt.
|
|
157
|
+
assert_equal File.join(@rt.app_root, '.well-known/foo.rb'), o[:target][:fn]
|
|
158
158
|
|
|
159
159
|
o = map['/docs/assets/css/style.css']
|
|
160
|
-
assert_equal File.join(@rt.
|
|
160
|
+
assert_equal File.join(@rt.app_root, 'assets/css/style.css'), o[:target][:fn]
|
|
161
161
|
|
|
162
162
|
o = map['/docs/assets/img/foo.jpg']
|
|
163
|
-
assert_equal File.join(@rt.
|
|
163
|
+
assert_equal File.join(@rt.app_root, 'assets/img/foo.jpg'), o[:target][:fn]
|
|
164
164
|
|
|
165
165
|
o = map['/docs/old/baz']
|
|
166
|
-
assert_equal File.join(@rt.
|
|
166
|
+
assert_equal File.join(@rt.app_root, 'old/baz.html'), o[:target][:fn]
|
|
167
167
|
|
|
168
168
|
o = map['/docs/posts']
|
|
169
|
-
assert_equal File.join(@rt.
|
|
169
|
+
assert_equal File.join(@rt.app_root, 'posts/index.rb'), o[:target][:fn]
|
|
170
170
|
refute_nil o[:parent]
|
|
171
171
|
assert_equal '/docs', o[:parent][:path]
|
|
172
172
|
|
|
173
173
|
o = map['/docs/old/baz']
|
|
174
|
-
assert_equal File.join(@rt.
|
|
174
|
+
assert_equal File.join(@rt.app_root, 'old/baz.html'), o[:target][:fn]
|
|
175
175
|
|
|
176
176
|
o = map['/docs/old']
|
|
177
|
-
assert_equal File.join(@rt.
|
|
177
|
+
assert_equal File.join(@rt.app_root, 'old/index.html'), o[:target][:fn]
|
|
178
178
|
refute_nil o[:parent]
|
|
179
179
|
assert_equal '/docs', o[:parent][:path]
|
|
180
180
|
|
|
181
181
|
o = map['/docs']
|
|
182
|
-
assert_equal File.join(@rt.
|
|
182
|
+
assert_equal File.join(@rt.app_root, 'index.rb'), o[:target][:fn]
|
|
183
183
|
|
|
184
184
|
o = map['/docs/about']
|
|
185
|
-
assert_equal File.join(@rt.
|
|
185
|
+
assert_equal File.join(@rt.app_root, 'about.md'), o[:target][:fn]
|
|
186
186
|
end
|
|
187
187
|
|
|
188
188
|
def test_dynamic_map
|
|
@@ -210,7 +210,7 @@ class RoutingTreeTest < Minitest::Test
|
|
|
210
210
|
'[org]/[repo]/issues/[id]/index.rb',
|
|
211
211
|
'api+.rb',
|
|
212
212
|
'posts/[id].rb'
|
|
213
|
-
].map { File.join(@rt.
|
|
213
|
+
].map { File.join(@rt.app_root, it) }, keys.map { map[it][:target][:fn] }
|
|
214
214
|
end
|
|
215
215
|
|
|
216
216
|
def test_router_proc
|
|
@@ -244,35 +244,35 @@ class RoutingTreeTest < Minitest::Test
|
|
|
244
244
|
assert_nil route
|
|
245
245
|
|
|
246
246
|
route = router.('/docs/assets/img/foo.jpg', {})
|
|
247
|
-
assert_equal File.join(@rt.
|
|
247
|
+
assert_equal File.join(@rt.app_root, 'assets/img/foo.jpg'), route[:target][:fn]
|
|
248
248
|
|
|
249
249
|
route = router.('/docs/assets/img/bar.jpg', {})
|
|
250
250
|
assert_nil route
|
|
251
251
|
|
|
252
252
|
route = router.('/docs/about', {})
|
|
253
|
-
assert_equal File.join(@rt.
|
|
253
|
+
assert_equal File.join(@rt.app_root, 'about.md'), route[:target][:fn]
|
|
254
254
|
|
|
255
255
|
route = router.('/docs/foo', params = {})
|
|
256
|
-
assert_equal File.join(@rt.
|
|
256
|
+
assert_equal File.join(@rt.app_root, '[org]/index.rb'), route[:target][:fn]
|
|
257
257
|
assert_equal 'foo', params['org']
|
|
258
258
|
|
|
259
259
|
route = router.('/docs/foo/bar', params = {})
|
|
260
|
-
assert_equal File.join(@rt.
|
|
260
|
+
assert_equal File.join(@rt.app_root, '[org]/[repo]/index.rb'), route[:target][:fn]
|
|
261
261
|
assert_equal 'foo', params['org']
|
|
262
262
|
assert_equal 'bar', params['repo']
|
|
263
263
|
|
|
264
264
|
route = router.('/docs/bar/baz/commits', params = {})
|
|
265
|
-
assert_equal File.join(@rt.
|
|
265
|
+
assert_equal File.join(@rt.app_root, '[org]/[repo]/commits/index.rb'), route[:target][:fn]
|
|
266
266
|
assert_equal 'bar', params['org']
|
|
267
267
|
assert_equal 'baz', params['repo']
|
|
268
268
|
|
|
269
269
|
route = router.('/docs/foo/bar/issues', params = {})
|
|
270
|
-
assert_equal File.join(@rt.
|
|
270
|
+
assert_equal File.join(@rt.app_root, '[org]/[repo]/issues/index.rb'), route[:target][:fn]
|
|
271
271
|
assert_equal 'foo', params['org']
|
|
272
272
|
assert_equal 'bar', params['repo']
|
|
273
273
|
|
|
274
274
|
route = router.('/docs/bar/baz/issues/14', params = {})
|
|
275
|
-
assert_equal File.join(@rt.
|
|
275
|
+
assert_equal File.join(@rt.app_root, '[org]/[repo]/issues/[id]/index.rb'), route[:target][:fn]
|
|
276
276
|
assert_equal 'bar', params['org']
|
|
277
277
|
assert_equal 'baz', params['repo']
|
|
278
278
|
assert_equal '14', params['id']
|
|
@@ -284,24 +284,24 @@ class RoutingTreeTest < Minitest::Test
|
|
|
284
284
|
assert_nil route
|
|
285
285
|
|
|
286
286
|
route = router.('/docs/api', {})
|
|
287
|
-
assert_equal File.join(@rt.
|
|
287
|
+
assert_equal File.join(@rt.app_root, 'api+.rb'), route[:target][:fn]
|
|
288
288
|
|
|
289
289
|
route = router.('/docs/api/foo/bar', {})
|
|
290
|
-
assert_equal File.join(@rt.
|
|
290
|
+
assert_equal File.join(@rt.app_root, 'api+.rb'), route[:target][:fn]
|
|
291
291
|
|
|
292
292
|
route = router.('/docs/api/foo/bar', {})
|
|
293
|
-
assert_equal File.join(@rt.
|
|
293
|
+
assert_equal File.join(@rt.app_root, 'api+.rb'), route[:target][:fn]
|
|
294
294
|
|
|
295
295
|
route = router.('/docs/posts', {})
|
|
296
|
-
assert_equal File.join(@rt.
|
|
296
|
+
assert_equal File.join(@rt.app_root, 'posts/index.rb'), route[:target][:fn]
|
|
297
297
|
|
|
298
298
|
route = router.('/docs/posts/foo', params = {})
|
|
299
|
-
assert_equal File.join(@rt.
|
|
299
|
+
assert_equal File.join(@rt.app_root, 'posts/[id].rb'), route[:target][:fn]
|
|
300
300
|
assert_equal 'foo', params['id']
|
|
301
301
|
end
|
|
302
302
|
|
|
303
303
|
def test_routing_root_mounted
|
|
304
|
-
rt = Syntropy::RoutingTree.new(
|
|
304
|
+
rt = Syntropy::RoutingTree.new(app_root: File.join(@app_root, 'site'), mount_path: '/')
|
|
305
305
|
router = rt.router_proc
|
|
306
306
|
|
|
307
307
|
route = router.('/docs/df/papercraft/issues/14', {})
|
|
@@ -326,35 +326,35 @@ class RoutingTreeTest < Minitest::Test
|
|
|
326
326
|
assert_nil route
|
|
327
327
|
|
|
328
328
|
route = router.('/assets/img/foo.jpg', {})
|
|
329
|
-
assert_equal File.join(@rt.
|
|
329
|
+
assert_equal File.join(@rt.app_root, 'assets/img/foo.jpg'), route[:target][:fn]
|
|
330
330
|
|
|
331
331
|
route = router.('/assets/img/bar.jpg', {})
|
|
332
332
|
assert_nil route
|
|
333
333
|
|
|
334
334
|
route = router.('/about', {})
|
|
335
|
-
assert_equal File.join(@rt.
|
|
335
|
+
assert_equal File.join(@rt.app_root, 'about.md'), route[:target][:fn]
|
|
336
336
|
|
|
337
337
|
route = router.('/foo', params = {})
|
|
338
|
-
assert_equal File.join(@rt.
|
|
338
|
+
assert_equal File.join(@rt.app_root, '[org]/index.rb'), route[:target][:fn]
|
|
339
339
|
assert_equal 'foo', params['org']
|
|
340
340
|
|
|
341
341
|
route = router.('/foo/bar', params = {})
|
|
342
|
-
assert_equal File.join(@rt.
|
|
342
|
+
assert_equal File.join(@rt.app_root, '[org]/[repo]/index.rb'), route[:target][:fn]
|
|
343
343
|
assert_equal 'foo', params['org']
|
|
344
344
|
assert_equal 'bar', params['repo']
|
|
345
345
|
|
|
346
346
|
route = router.('/bar/baz/commits', params = {})
|
|
347
|
-
assert_equal File.join(@rt.
|
|
347
|
+
assert_equal File.join(@rt.app_root, '[org]/[repo]/commits/index.rb'), route[:target][:fn]
|
|
348
348
|
assert_equal 'bar', params['org']
|
|
349
349
|
assert_equal 'baz', params['repo']
|
|
350
350
|
|
|
351
351
|
route = router.('/foo/bar/issues', params = {})
|
|
352
|
-
assert_equal File.join(@rt.
|
|
352
|
+
assert_equal File.join(@rt.app_root, '[org]/[repo]/issues/index.rb'), route[:target][:fn]
|
|
353
353
|
assert_equal 'foo', params['org']
|
|
354
354
|
assert_equal 'bar', params['repo']
|
|
355
355
|
|
|
356
356
|
route = router.('/bar/baz/issues/14', params = {})
|
|
357
|
-
assert_equal File.join(@rt.
|
|
357
|
+
assert_equal File.join(@rt.app_root, '[org]/[repo]/issues/[id]/index.rb'), route[:target][:fn]
|
|
358
358
|
assert_equal 'bar', params['org']
|
|
359
359
|
assert_equal 'baz', params['repo']
|
|
360
360
|
assert_equal '14', params['id']
|
|
@@ -366,24 +366,24 @@ class RoutingTreeTest < Minitest::Test
|
|
|
366
366
|
assert_nil route
|
|
367
367
|
|
|
368
368
|
route = router.('/api', {})
|
|
369
|
-
assert_equal File.join(@rt.
|
|
369
|
+
assert_equal File.join(@rt.app_root, 'api+.rb'), route[:target][:fn]
|
|
370
370
|
|
|
371
371
|
route = router.('/api/foo/bar', {})
|
|
372
|
-
assert_equal File.join(@rt.
|
|
372
|
+
assert_equal File.join(@rt.app_root, 'api+.rb'), route[:target][:fn]
|
|
373
373
|
|
|
374
374
|
route = router.('/api/foo/bar', {})
|
|
375
|
-
assert_equal File.join(@rt.
|
|
375
|
+
assert_equal File.join(@rt.app_root, 'api+.rb'), route[:target][:fn]
|
|
376
376
|
|
|
377
377
|
route = router.('/posts', {})
|
|
378
|
-
assert_equal File.join(@rt.
|
|
378
|
+
assert_equal File.join(@rt.app_root, 'posts/index.rb'), route[:target][:fn]
|
|
379
379
|
|
|
380
380
|
route = router.('/posts/foo', params = {})
|
|
381
|
-
assert_equal File.join(@rt.
|
|
381
|
+
assert_equal File.join(@rt.app_root, 'posts/[id].rb'), route[:target][:fn]
|
|
382
382
|
assert_equal 'foo', params['id']
|
|
383
383
|
end
|
|
384
384
|
|
|
385
385
|
def test_mount_applet
|
|
386
|
-
rt = Syntropy::RoutingTree.new(
|
|
386
|
+
rt = Syntropy::RoutingTree.new(app_root: File.join(@app_root, 'site'), mount_path: '/')
|
|
387
387
|
applet = ->(req) { :foo }
|
|
388
388
|
rt.mount_applet('/foo/bar', applet)
|
|
389
389
|
router = rt.router_proc
|
|
@@ -396,7 +396,7 @@ class RoutingTreeTest < Minitest::Test
|
|
|
396
396
|
end
|
|
397
397
|
|
|
398
398
|
def test_mount_applet_nested_mount_path
|
|
399
|
-
rt = Syntropy::RoutingTree.new(
|
|
399
|
+
rt = Syntropy::RoutingTree.new(app_root: File.join(@app_root, 'site'), mount_path: '/my/site')
|
|
400
400
|
applet = ->(req) { :foo }
|
|
401
401
|
rt.mount_applet('/my/site/foo/bar', applet)
|
|
402
402
|
router = rt.router_proc
|
|
@@ -409,7 +409,7 @@ class RoutingTreeTest < Minitest::Test
|
|
|
409
409
|
end
|
|
410
410
|
|
|
411
411
|
def test_mount_applet_clash
|
|
412
|
-
rt = Syntropy::RoutingTree.new(
|
|
412
|
+
rt = Syntropy::RoutingTree.new(app_root: File.join(@app_root, 'site'), mount_path: '/')
|
|
413
413
|
applet = ->(req) { :foo }
|
|
414
414
|
assert_raises(Syntropy::Error) {
|
|
415
415
|
rt.mount_applet('/about', applet)
|
|
@@ -429,9 +429,9 @@ class RoutingTreeWildcardIndexTest < Minitest::Test
|
|
|
429
429
|
}
|
|
430
430
|
}
|
|
431
431
|
|
|
432
|
-
@
|
|
433
|
-
make_tmp_file_tree(@
|
|
434
|
-
@rt = Syntropy::RoutingTree.new(
|
|
432
|
+
@app_root = "/tmp/#{__FILE__.gsub('/', '-')}-#{SecureRandom.hex}"
|
|
433
|
+
make_tmp_file_tree(@app_root, file_tree)
|
|
434
|
+
@rt = Syntropy::RoutingTree.new(app_root: File.join(@app_root, 'site'), mount_path: '/docs')
|
|
435
435
|
|
|
436
436
|
router = @rt.router_proc
|
|
437
437
|
|
|
@@ -455,9 +455,9 @@ class RoutingTreeWildcardIndexTest < Minitest::Test
|
|
|
455
455
|
}
|
|
456
456
|
}
|
|
457
457
|
|
|
458
|
-
@
|
|
459
|
-
make_tmp_file_tree(@
|
|
460
|
-
@rt = Syntropy::RoutingTree.new(
|
|
458
|
+
@app_root = "/tmp/#{__FILE__.gsub('/', '-')}-#{SecureRandom.hex}"
|
|
459
|
+
make_tmp_file_tree(@app_root, file_tree)
|
|
460
|
+
@rt = Syntropy::RoutingTree.new(app_root: File.join(@app_root, 'site'), mount_path: '/')
|
|
461
461
|
|
|
462
462
|
router = @rt.router_proc
|
|
463
463
|
|
|
@@ -480,9 +480,9 @@ class RoutingTreeWildcardIndexTest < Minitest::Test
|
|
|
480
480
|
}
|
|
481
481
|
}
|
|
482
482
|
|
|
483
|
-
@
|
|
484
|
-
make_tmp_file_tree(@
|
|
485
|
-
@rt = Syntropy::RoutingTree.new(
|
|
483
|
+
@app_root = "/tmp/#{__FILE__.gsub('/', '-')}-#{SecureRandom.hex}"
|
|
484
|
+
make_tmp_file_tree(@app_root, file_tree)
|
|
485
|
+
@rt = Syntropy::RoutingTree.new(app_root: File.join(@app_root, 'site'), mount_path: '/docs')
|
|
486
486
|
router = @rt.router_proc
|
|
487
487
|
|
|
488
488
|
route = router.('/docs', {})
|
|
@@ -513,9 +513,9 @@ class RoutingTreeWildcardIndexTest < Minitest::Test
|
|
|
513
513
|
}
|
|
514
514
|
}
|
|
515
515
|
|
|
516
|
-
@
|
|
517
|
-
make_tmp_file_tree(@
|
|
518
|
-
@rt = Syntropy::RoutingTree.new(
|
|
516
|
+
@app_root = "/tmp/#{__FILE__.gsub('/', '-')}-#{SecureRandom.hex}"
|
|
517
|
+
make_tmp_file_tree(@app_root, file_tree)
|
|
518
|
+
@rt = Syntropy::RoutingTree.new(app_root: File.join(@app_root, 'site'), mount_path: '/docs')
|
|
519
519
|
router = @rt.router_proc
|
|
520
520
|
|
|
521
521
|
route = router.('/docs', {})
|
|
@@ -552,9 +552,9 @@ class RoutingTreeWildcardIndexTest < Minitest::Test
|
|
|
552
552
|
}
|
|
553
553
|
}
|
|
554
554
|
|
|
555
|
-
@
|
|
556
|
-
make_tmp_file_tree(@
|
|
557
|
-
@rt = Syntropy::RoutingTree.new(
|
|
555
|
+
@app_root = "/tmp/#{__FILE__.gsub('/', '-')}-#{SecureRandom.hex}"
|
|
556
|
+
make_tmp_file_tree(@app_root, file_tree)
|
|
557
|
+
@rt = Syntropy::RoutingTree.new(app_root: File.join(@app_root, 'site'), mount_path: '/docs')
|
|
558
558
|
router = @rt.router_proc
|
|
559
559
|
|
|
560
560
|
route = router.('/docs', {})
|
data/test/test_server.rb
CHANGED
|
@@ -150,8 +150,7 @@ class ServerTest < Minitest::Test
|
|
|
150
150
|
':path' => '/foo',
|
|
151
151
|
'server' => 'foo.com',
|
|
152
152
|
'content-length' => '3',
|
|
153
|
-
':body-done-reading' => true
|
|
154
|
-
':tx' => 56,
|
|
153
|
+
':body-done-reading' => true
|
|
155
154
|
}, headers)
|
|
156
155
|
body = @bodies.shift
|
|
157
156
|
assert_equal 'abc', body
|
|
@@ -163,8 +162,7 @@ class ServerTest < Minitest::Test
|
|
|
163
162
|
':path' => '/bar',
|
|
164
163
|
'server' => 'bar.com',
|
|
165
164
|
'content-length' => '6',
|
|
166
|
-
':body-done-reading' => true
|
|
167
|
-
':tx' => 56,
|
|
165
|
+
':body-done-reading' => true
|
|
168
166
|
}, headers)
|
|
169
167
|
body = @bodies.shift
|
|
170
168
|
assert_equal 'defghi', body
|
|
@@ -177,7 +175,7 @@ class ServerTest < Minitest::Test
|
|
|
177
175
|
@reqs << req
|
|
178
176
|
@bodies << (b = req.read)
|
|
179
177
|
req.respond("method: #{req.method}")
|
|
180
|
-
rescue => e
|
|
178
|
+
rescue StandardError => e
|
|
181
179
|
p e
|
|
182
180
|
p e.backtrace
|
|
183
181
|
exit!
|
|
@@ -218,8 +216,7 @@ class ServerTest < Minitest::Test
|
|
|
218
216
|
':path' => '/foo',
|
|
219
217
|
'server' => 'foo.com',
|
|
220
218
|
'transfer-encoding' => 'chunked',
|
|
221
|
-
':body-done-reading' => true
|
|
222
|
-
':tx' => 56
|
|
219
|
+
':body-done-reading' => true
|
|
223
220
|
}, headers)
|
|
224
221
|
body = @bodies.shift
|
|
225
222
|
assert_equal 'abcde', body
|
|
@@ -231,8 +228,7 @@ class ServerTest < Minitest::Test
|
|
|
231
228
|
':path' => '/bar',
|
|
232
229
|
'server' => 'bar.com',
|
|
233
230
|
'transfer-encoding' => 'chunked',
|
|
234
|
-
':body-done-reading' => true
|
|
235
|
-
':tx' => 56
|
|
231
|
+
':body-done-reading' => true
|
|
236
232
|
}, headers)
|
|
237
233
|
body = @bodies.shift
|
|
238
234
|
assert_equal '123456789abcdefghijklmnopqrstuv', body
|
data/test/test_test.rb
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'helper'
|
|
4
|
+
require 'syntropy/test'
|
|
5
|
+
|
|
6
|
+
class TestTest < Syntropy::Test
|
|
7
|
+
self.env = {
|
|
8
|
+
app_root: File.join(__dir__, 'fixtures/app'),
|
|
9
|
+
mount_path: '/syntest'
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
def test_http_request
|
|
13
|
+
req = http_request({
|
|
14
|
+
':method' => 'GET',
|
|
15
|
+
':path' => '/syntest'
|
|
16
|
+
})
|
|
17
|
+
assert_kind_of Syntropy::Request, req
|
|
18
|
+
assert_equal HTTP::OK, req.response_status
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def test_env
|
|
22
|
+
assert_kind_of Hash, env
|
|
23
|
+
assert_equal File.join(__dir__, 'fixtures/app'), env[:app_root]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def test_app
|
|
27
|
+
assert_kind_of Syntropy::App, app
|
|
28
|
+
assert_equal File.join(__dir__, 'fixtures/app'), app.app_root
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def test_machine
|
|
32
|
+
assert_kind_of UM, machine
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def test_load_module
|
|
36
|
+
mod = load_module('_lib/env')
|
|
37
|
+
assert_kind_of Syntropy::Module, mod
|
|
38
|
+
assert_equal app, mod.app
|
|
39
|
+
|
|
40
|
+
assert_raises(Syntropy::Error) { load_module('_lib/blah')}
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def test_get
|
|
44
|
+
req = get('/syntest/bar')
|
|
45
|
+
assert_kind_of Syntropy::Request, req
|
|
46
|
+
assert_equal HTTP::OK, req.response_status
|
|
47
|
+
assert_equal 'foobar', req.response_body
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def test_post
|
|
51
|
+
req = post('/syntest/post_ct', 'text/plain', 'foo')
|
|
52
|
+
assert_kind_of Syntropy::Request, req
|
|
53
|
+
assert_equal HTTP::OK, req.response_status
|
|
54
|
+
assert_equal 'text/plain:foo', req.response_body
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def test_post_json
|
|
58
|
+
req = post_json('/syntest/post_ct', { a: 42, b: [3]})
|
|
59
|
+
assert_kind_of Syntropy::Request, req
|
|
60
|
+
assert_equal HTTP::OK, req.response_status
|
|
61
|
+
assert_equal 'application/json:{"a":42,"b":[3]}', req.response_body
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def test_post_form
|
|
65
|
+
req = post_form('/syntest/post_ct', { a: 'b&c', d: 1})
|
|
66
|
+
assert_kind_of Syntropy::Request, req
|
|
67
|
+
assert_equal HTTP::OK, req.response_status
|
|
68
|
+
assert_equal 'application/x-www-form-urlencoded:a=b%26c&d=1', req.response_body
|
|
69
|
+
end
|
|
70
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: syntropy
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.34.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sharon Rosner
|
|
@@ -204,15 +204,20 @@ files:
|
|
|
204
204
|
- examples/basic/favicon.ico
|
|
205
205
|
- examples/basic/index.md
|
|
206
206
|
- examples/basic/templates.rb
|
|
207
|
+
- examples/blog/.gitignore
|
|
207
208
|
- examples/blog/app/_layout/default.rb
|
|
208
|
-
- examples/blog/app/_lib/
|
|
209
|
+
- examples/blog/app/_lib/database.rb
|
|
210
|
+
- examples/blog/app/_lib/posts.rb
|
|
209
211
|
- examples/blog/app/_schema/2026-01-01-initial.rb
|
|
210
|
-
- examples/blog/app/_setup.rb
|
|
211
212
|
- examples/blog/app/index.rb
|
|
212
213
|
- examples/blog/app/posts/[id]/edit.rb
|
|
213
214
|
- examples/blog/app/posts/[id]/index.rb
|
|
214
215
|
- examples/blog/app/posts/index.rb
|
|
215
216
|
- examples/blog/app/posts/new.rb
|
|
217
|
+
- examples/blog/config/development.rb
|
|
218
|
+
- examples/blog/config/production.rb
|
|
219
|
+
- examples/blog/config/test.rb
|
|
220
|
+
- examples/blog/test/test_posts.rb
|
|
216
221
|
- examples/mcp-oauth/.ruby-version
|
|
217
222
|
- examples/mcp-oauth/Gemfile
|
|
218
223
|
- examples/mcp-oauth/README.md
|
|
@@ -261,56 +266,60 @@ files:
|
|
|
261
266
|
- lib/syntropy/request/mock_adapter.rb
|
|
262
267
|
- lib/syntropy/request/request_info.rb
|
|
263
268
|
- lib/syntropy/request/response.rb
|
|
264
|
-
- lib/syntropy/request/session.rb
|
|
265
269
|
- lib/syntropy/request/validation.rb
|
|
266
270
|
- lib/syntropy/routing_tree.rb
|
|
271
|
+
- lib/syntropy/session.rb
|
|
267
272
|
- lib/syntropy/side_run.rb
|
|
268
273
|
- lib/syntropy/test.rb
|
|
269
274
|
- lib/syntropy/utils.rb
|
|
270
275
|
- lib/syntropy/version.rb
|
|
271
276
|
- syntropy.gemspec
|
|
272
|
-
- test/app/.well-known/foo.rb
|
|
273
|
-
- test/app/_hook.rb
|
|
274
|
-
- test/app/_layout/default.rb
|
|
275
|
-
- test/app/_lib/callable.rb
|
|
276
|
-
- test/app/_lib/dep.rb
|
|
277
|
-
- test/app/_lib/env.rb
|
|
278
|
-
- test/app/_lib/klass.rb
|
|
279
|
-
- test/app/_lib/missing-export.rb
|
|
280
|
-
- test/app/_lib/self.rb
|
|
281
|
-
- test/app/about/_error.rb
|
|
282
|
-
- test/app/about/foo.md
|
|
283
|
-
- test/app/about/index.rb
|
|
284
|
-
- test/app/about/raise.rb
|
|
285
|
-
- test/app/api+.rb
|
|
286
|
-
- test/app/assets/style.css
|
|
287
|
-
- test/app/bad_mod.rb
|
|
288
|
-
- test/app/bar.rb
|
|
289
|
-
- test/app/baz.rb
|
|
290
|
-
- test/app/by_method.rb
|
|
291
|
-
- test/app/deps.rb
|
|
292
|
-
- test/app/index.html
|
|
293
|
-
- test/app/mod/bar/index+.rb
|
|
294
|
-
- test/app/mod/foo/index.rb
|
|
295
|
-
- test/app/mod/path/a.rb
|
|
296
|
-
- test/app/mod/path/b.rb
|
|
297
|
-
- test/app/params/[foo].rb
|
|
298
|
-
- test/app/rss.rb
|
|
299
|
-
- test/app/tmp.rb
|
|
300
|
-
- test/app_custom/_site.rb
|
|
301
|
-
- test/app_multi_site/_site.rb
|
|
302
|
-
- test/app_multi_site/bar.baz/index.html
|
|
303
|
-
- test/app_multi_site/foo.bar/index.html
|
|
304
|
-
- test/app_setup/_setup.rb
|
|
305
|
-
- test/app_setup/index.rb
|
|
306
|
-
- test/app_with_schema/_schema/2026-01-02-foo.rb
|
|
307
|
-
- test/app_with_schema/_schema/2026-05-30-bar.rb
|
|
308
277
|
- test/bm_router_proc.rb
|
|
309
278
|
- test/bm_server.rb
|
|
279
|
+
- test/fixtures/app/.well-known/foo.rb
|
|
280
|
+
- test/fixtures/app/_hook.rb
|
|
281
|
+
- test/fixtures/app/_layout/default.rb
|
|
282
|
+
- test/fixtures/app/_lib/callable.rb
|
|
283
|
+
- test/fixtures/app/_lib/dep.rb
|
|
284
|
+
- test/fixtures/app/_lib/env.rb
|
|
285
|
+
- test/fixtures/app/_lib/klass.rb
|
|
286
|
+
- test/fixtures/app/_lib/missing-export.rb
|
|
287
|
+
- test/fixtures/app/_lib/self.rb
|
|
288
|
+
- test/fixtures/app/about/_error.rb
|
|
289
|
+
- test/fixtures/app/about/foo.md
|
|
290
|
+
- test/fixtures/app/about/index.rb
|
|
291
|
+
- test/fixtures/app/about/raise.rb
|
|
292
|
+
- test/fixtures/app/api+.rb
|
|
293
|
+
- test/fixtures/app/assets/style.css
|
|
294
|
+
- test/fixtures/app/bad_mod.rb
|
|
295
|
+
- test/fixtures/app/bar.rb
|
|
296
|
+
- test/fixtures/app/baz.rb
|
|
297
|
+
- test/fixtures/app/by_method.rb
|
|
298
|
+
- test/fixtures/app/class_instance.rb
|
|
299
|
+
- test/fixtures/app/deps.rb
|
|
300
|
+
- test/fixtures/app/http.rb
|
|
301
|
+
- test/fixtures/app/index.html
|
|
302
|
+
- test/fixtures/app/mod/bar/index+.rb
|
|
303
|
+
- test/fixtures/app/mod/foo/index.rb
|
|
304
|
+
- test/fixtures/app/mod/path/a.rb
|
|
305
|
+
- test/fixtures/app/mod/path/b.rb
|
|
306
|
+
- test/fixtures/app/params/[foo].rb
|
|
307
|
+
- test/fixtures/app/post_ct.rb
|
|
308
|
+
- test/fixtures/app/rss.rb
|
|
309
|
+
- test/fixtures/app/singleton.rb
|
|
310
|
+
- test/fixtures/app/tmp.rb
|
|
311
|
+
- test/fixtures/app_custom/_site.rb
|
|
312
|
+
- test/fixtures/app_multi_site/_site.rb
|
|
313
|
+
- test/fixtures/app_multi_site/bar.baz/index.html
|
|
314
|
+
- test/fixtures/app_multi_site/foo.bar/index.html
|
|
315
|
+
- test/fixtures/app_setup/_setup.rb
|
|
316
|
+
- test/fixtures/app_setup/index.rb
|
|
317
|
+
- test/fixtures/app_with_schema/_schema/2026-01-02-foo.rb
|
|
318
|
+
- test/fixtures/app_with_schema/_schema/2026-05-30-bar.rb
|
|
319
|
+
- test/fixtures/schema/2026-01-02-foo.rb
|
|
320
|
+
- test/fixtures/schema/2026-05-30-bar.rb
|
|
310
321
|
- test/helper.rb
|
|
311
322
|
- test/run.rb
|
|
312
|
-
- test/schema/2026-01-02-foo.rb
|
|
313
|
-
- test/schema/2026-05-30-bar.rb
|
|
314
323
|
- test/test_app.rb
|
|
315
324
|
- test/test_caching.rb
|
|
316
325
|
- test/test_db_connection_pool.rb
|
|
@@ -330,6 +339,7 @@ files:
|
|
|
330
339
|
- test/test_routing_tree.rb
|
|
331
340
|
- test/test_server.rb
|
|
332
341
|
- test/test_side_run.rb
|
|
342
|
+
- test/test_test.rb
|
|
333
343
|
homepage: https://github.com/digital-fabric/syntropy
|
|
334
344
|
licenses:
|
|
335
345
|
- MIT
|
data/examples/blog/app/_setup.rb
DELETED