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_#{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_#{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_#{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