diff options
Diffstat (limited to 'actionpack/test/journey/path/pattern_test.rb')
-rw-r--r-- | actionpack/test/journey/path/pattern_test.rb | 286 |
1 files changed, 286 insertions, 0 deletions
diff --git a/actionpack/test/journey/path/pattern_test.rb b/actionpack/test/journey/path/pattern_test.rb new file mode 100644 index 0000000000..3e7aea57f1 --- /dev/null +++ b/actionpack/test/journey/path/pattern_test.rb @@ -0,0 +1,286 @@ +# frozen_string_literal: true + +require "abstract_unit" + +module ActionDispatch + module Journey + module Path + class TestPattern < ActiveSupport::TestCase + SEPARATORS = ["/", ".", "?"].join + + x = /.+/ + { + "/:controller(/:action)" => %r{\A/(#{x})(?:/([^/.?]+))?\Z}, + "/:controller/foo" => %r{\A/(#{x})/foo\Z}, + "/:controller/:action" => %r{\A/(#{x})/([^/.?]+)\Z}, + "/:controller" => %r{\A/(#{x})\Z}, + "/:controller(/:action(/:id))" => %r{\A/(#{x})(?:/([^/.?]+)(?:/([^/.?]+))?)?\Z}, + "/:controller/:action.xml" => %r{\A/(#{x})/([^/.?]+)\.xml\Z}, + "/:controller.:format" => %r{\A/(#{x})\.([^/.?]+)\Z}, + "/:controller(.:format)" => %r{\A/(#{x})(?:\.([^/.?]+))?\Z}, + "/:controller/*foo" => %r{\A/(#{x})/(.+)\Z}, + "/:controller/*foo/bar" => %r{\A/(#{x})/(.+)/bar\Z}, + "/:foo|*bar" => %r{\A/(?:([^/.?]+)|(.+))\Z}, + }.each do |path, expected| + define_method(:"test_to_regexp_#{Regexp.escape(path)}") do + path = Pattern.build( + path, + { controller: /.+/ }, + SEPARATORS, + true + ) + assert_equal(expected, path.to_regexp) + end + end + + { + "/:controller(/:action)" => %r{\A/(#{x})(?:/([^/.?]+))?}, + "/:controller/foo" => %r{\A/(#{x})/foo}, + "/:controller/:action" => %r{\A/(#{x})/([^/.?]+)}, + "/:controller" => %r{\A/(#{x})}, + "/:controller(/:action(/:id))" => %r{\A/(#{x})(?:/([^/.?]+)(?:/([^/.?]+))?)?}, + "/:controller/:action.xml" => %r{\A/(#{x})/([^/.?]+)\.xml}, + "/:controller.:format" => %r{\A/(#{x})\.([^/.?]+)}, + "/:controller(.:format)" => %r{\A/(#{x})(?:\.([^/.?]+))?}, + "/:controller/*foo" => %r{\A/(#{x})/(.+)}, + "/:controller/*foo/bar" => %r{\A/(#{x})/(.+)/bar}, + "/:foo|*bar" => %r{\A/(?:([^/.?]+)|(.+))}, + }.each do |path, expected| + define_method(:"test_to_non_anchored_regexp_#{Regexp.escape(path)}") do + path = Pattern.build( + path, + { controller: /.+/ }, + SEPARATORS, + false + ) + assert_equal(expected, path.to_regexp) + end + end + + { + "/:controller(/:action)" => %w{ controller action }, + "/:controller/foo" => %w{ controller }, + "/:controller/:action" => %w{ controller action }, + "/:controller" => %w{ controller }, + "/:controller(/:action(/:id))" => %w{ controller action id }, + "/:controller/:action.xml" => %w{ controller action }, + "/:controller.:format" => %w{ controller format }, + "/:controller(.:format)" => %w{ controller format }, + "/:controller/*foo" => %w{ controller foo }, + "/:controller/*foo/bar" => %w{ controller foo }, + }.each do |path, expected| + define_method(:"test_names_#{Regexp.escape(path)}") do + path = Pattern.build( + path, + { controller: /.+/ }, + SEPARATORS, + true + ) + assert_equal(expected, path.names) + end + end + + def test_to_regexp_with_extended_group + path = Pattern.build( + "/page/:name", + { name: / + #ROFL + (tender|love + #MAO + )/x }, + SEPARATORS, + true + ) + assert_match(path, "/page/tender") + assert_match(path, "/page/love") + assert_no_match(path, "/page/loving") + end + + def test_optional_names + [ + ["/:foo(/:bar(/:baz))", %w{ bar baz }], + ["/:foo(/:bar)", %w{ bar }], + ["/:foo(/:bar)/:lol(/:baz)", %w{ bar baz }], + ].each do |pattern, list| + path = Pattern.from_string pattern + assert_equal list.sort, path.optional_names.sort + end + end + + def test_to_regexp_match_non_optional + path = Pattern.build( + "/:name", + { name: /\d+/ }, + SEPARATORS, + true + ) + assert_match(path, "/123") + assert_no_match(path, "/") + end + + def test_to_regexp_with_group + path = Pattern.build( + "/page/:name", + { name: /(tender|love)/ }, + SEPARATORS, + true + ) + assert_match(path, "/page/tender") + assert_match(path, "/page/love") + assert_no_match(path, "/page/loving") + end + + def test_ast_sets_regular_expressions + requirements = { name: /(tender|love)/, value: /./ } + path = Pattern.build( + "/page/:name/:value", + requirements, + SEPARATORS, + true + ) + + nodes = path.ast.grep(Nodes::Symbol) + assert_equal 2, nodes.length + nodes.each do |node| + assert_equal requirements[node.to_sym], node.regexp + end + end + + def test_match_data_with_group + path = Pattern.build( + "/page/:name", + { name: /(tender|love)/ }, + SEPARATORS, + true + ) + match = path.match "/page/tender" + assert_equal "tender", match[1] + assert_equal 2, match.length + end + + def test_match_data_with_multi_group + path = Pattern.build( + "/page/:name/:id", + { name: /t(((ender|love)))()/ }, + SEPARATORS, + true + ) + match = path.match "/page/tender/10" + assert_equal "tender", match[1] + assert_equal "10", match[2] + assert_equal 3, match.length + assert_equal %w{ tender 10 }, match.captures + end + + def test_star_with_custom_re + z = /\d+/ + path = Pattern.build( + "/page/*foo", + { foo: z }, + SEPARATORS, + true + ) + assert_equal(%r{\A/page/(#{z})\Z}, path.to_regexp) + end + + def test_insensitive_regexp_with_group + path = Pattern.build( + "/page/:name/aaron", + { name: /(tender|love)/i }, + SEPARATORS, + true + ) + assert_match(path, "/page/TENDER/aaron") + assert_match(path, "/page/loVE/aaron") + assert_no_match(path, "/page/loVE/AAron") + end + + def test_to_regexp_with_strexp + path = Pattern.build("/:controller", {}, SEPARATORS, true) + x = %r{\A/([^/.?]+)\Z} + + assert_equal(x.source, path.source) + end + + def test_to_regexp_defaults + path = Pattern.from_string "/:controller(/:action(/:id))" + expected = %r{\A/([^/.?]+)(?:/([^/.?]+)(?:/([^/.?]+))?)?\Z} + assert_equal expected, path.to_regexp + end + + def test_failed_match + path = Pattern.from_string "/:controller(/:action(/:id(.:format)))" + uri = "content" + + assert_not path =~ uri + end + + def test_match_controller + path = Pattern.from_string "/:controller(/:action(/:id(.:format)))" + uri = "/content" + + match = path =~ uri + assert_equal %w{ controller action id format }, match.names + assert_equal "content", match[1] + assert_nil match[2] + assert_nil match[3] + assert_nil match[4] + end + + def test_match_controller_action + path = Pattern.from_string "/:controller(/:action(/:id(.:format)))" + uri = "/content/list" + + match = path =~ uri + assert_equal %w{ controller action id format }, match.names + assert_equal "content", match[1] + assert_equal "list", match[2] + assert_nil match[3] + assert_nil match[4] + end + + def test_match_controller_action_id + path = Pattern.from_string "/:controller(/:action(/:id(.:format)))" + uri = "/content/list/10" + + match = path =~ uri + assert_equal %w{ controller action id format }, match.names + assert_equal "content", match[1] + assert_equal "list", match[2] + assert_equal "10", match[3] + assert_nil match[4] + end + + def test_match_literal + path = Path::Pattern.from_string "/books(/:action(.:format))" + + uri = "/books" + match = path =~ uri + assert_equal %w{ action format }, match.names + assert_nil match[1] + assert_nil match[2] + end + + def test_match_literal_with_action + path = Path::Pattern.from_string "/books(/:action(.:format))" + + uri = "/books/list" + match = path =~ uri + assert_equal %w{ action format }, match.names + assert_equal "list", match[1] + assert_nil match[2] + end + + def test_match_literal_with_action_and_format + path = Path::Pattern.from_string "/books(/:action(.:format))" + + uri = "/books/list.rss" + match = path =~ uri + assert_equal %w{ action format }, match.names + assert_equal "list", match[1] + assert_equal "rss", match[2] + end + end + end + end +end |