From 350c98de92a7709b70728f29e8a8d0305b1b0660 Mon Sep 17 00:00:00 2001 From: DualFroz Date: Sun, 13 Sep 2026 20:51:35 +0200 Subject: [PATCH] test: cover RouterConstraintsTest --- test/test_router_advanced.rb | 69 ++++++++++++++++++++++++++++++++++++ test/test_router_mount.rb | 55 ++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 test/test_router_advanced.rb create mode 100644 test/test_router_mount.rb diff --git a/test/test_router_advanced.rb b/test/test_router_advanced.rb new file mode 100644 index 0000000..47b557e --- /dev/null +++ b/test/test_router_advanced.rb @@ -0,0 +1,69 @@ +require 'minitest/autorun' +require 'prism' + +class RouterConstraintsTest < Minitest::Test + def setup + @router = Prism::Router.new + end + + def test_constraint_accepts_matching_segment + @router.add('GET', '/users/:id', constraints: { id: /\d+/ }) {} + _, params = @router.matches('GET', '/users/42').first + assert_equal '42', params['id'] + end + + def test_constraint_rejects_non_matching_segment + @router.add('GET', '/users/:id', constraints: { id: /\d+/ }) {} + assert_empty @router.matches('GET', '/users/not-a-number') + end + + def test_constraint_only_applies_to_the_named_segment + @router.add('GET', '/users/:id/posts/:slug', constraints: { id: /\d+/ }) {} + _, params = @router.matches('GET', '/users/7/posts/hello-world').first + assert_equal '7', params['id'] + assert_equal 'hello-world', params['slug'] + assert_empty @router.matches('GET', '/users/seven/posts/hello-world') + end +end + +class RouterFormatTest < Minitest::Test + def setup + @router = Prism::Router.new + end + + def test_format_disabled_by_default_dynamic_segment_keeps_dots + @router.add('GET', '/files/:name') {} + _, params = @router.matches('GET', '/files/report.pdf').first + assert_equal 'report.pdf', params['name'] + refute params.key?('format') + end + + def test_format_enabled_extracts_extension_and_shrinks_segment + @router.add('GET', '/posts/:id', format: true) {} + _, params = @router.matches('GET', '/posts/7.json').first + assert_equal '7', params['id'] + assert_equal 'json', params['format'] + end + + def test_format_enabled_still_matches_without_extension + @router.add('GET', '/posts/:id', format: true) {} + _, params = @router.matches('GET', '/posts/7').first + assert_equal '7', params['id'] + refute params.key?('format') + end + + def test_format_and_constraints_combine + @router.add('GET', '/posts/:id', format: true, constraints: { id: /\d+/ }) {} + _, params = @router.matches('GET', '/posts/7.xml').first + assert_equal '7', params['id'] + assert_equal 'xml', params['format'] + assert_empty @router.matches('GET', '/posts/seven.xml') + end + + def test_format_is_ignored_for_wildcard_patterns + @router.add('GET', '/files/*', format: true) {} + _, params = @router.matches('GET', '/files/a/b/report.pdf').first + assert_equal ['a/b/report.pdf'], params['splat'] + refute params.key?('format') + end +end diff --git a/test/test_router_mount.rb b/test/test_router_mount.rb new file mode 100644 index 0000000..3364d43 --- /dev/null +++ b/test/test_router_mount.rb @@ -0,0 +1,55 @@ +require 'minitest/autorun' +require 'prism' + +class RouterMountTest < Minitest::Test + def setup + @router = Prism::Router.new + end + + def test_finds_mount_for_exact_prefix + app = Object.new + @router.mount('/admin', app) + prefix, found = @router.find_mount('/admin') + assert_equal '/admin', prefix + assert_same app, found + end + + def test_finds_mount_for_nested_path + app = Object.new + @router.mount('/admin', app) + prefix, found = @router.find_mount('/admin/users/1') + assert_equal '/admin', prefix + assert_same app, found + end + + def test_does_not_match_sibling_path_with_shared_prefix + app = Object.new + @router.mount('/admin', app) + assert_nil @router.find_mount('/administrator') + end + + def test_returns_nil_when_no_mount_matches + assert_nil @router.find_mount('/nowhere') + end + + def test_trailing_slash_on_prefix_is_normalized + app = Object.new + @router.mount('/admin/', app) + prefix, found = @router.find_mount('/admin/users') + assert_equal '/admin', prefix + assert_same app, found + end + + def test_longest_matching_prefix_wins_when_mounts_overlap + outer = Object.new + inner = Object.new + @router.mount('/api', outer) + @router.mount('/api/v2', inner) + + _, found = @router.find_mount('/api/v2/widgets') + assert_same inner, found + + _, found = @router.find_mount('/api/v1/widgets') + assert_same outer, found + end +end