http_router 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/Rakefile +6 -5
  2. data/benchmarks/rack_mount.rb +16 -45
  3. data/benchmarks/rec2.rb +8 -8
  4. data/http_router.gemspec +5 -4
  5. data/lib/http_router/interface/sinatra.rb +7 -7
  6. data/lib/http_router/node.rb +106 -105
  7. data/lib/http_router/optional_compiler.rb +14 -5
  8. data/lib/http_router/path.rb +18 -28
  9. data/lib/http_router/root.rb +17 -29
  10. data/lib/http_router/route.rb +47 -16
  11. data/lib/http_router/static.rb +5 -0
  12. data/lib/http_router/variable.rb +2 -5
  13. data/lib/http_router/version.rb +1 -1
  14. data/lib/http_router.rb +38 -65
  15. data/test/helper.rb +74 -0
  16. data/test/rack/test_dispatch.rb +120 -0
  17. data/test/rack/test_route.rb +44 -0
  18. data/test/rack/test_urlmap.rb +12 -0
  19. data/{spec → test}/sinatra/recognize_spec.rb +0 -0
  20. data/test/sinatra/test_recognize.rb +150 -0
  21. data/test/test_arbitrary.rb +50 -0
  22. data/test/test_generate.rb +93 -0
  23. data/test/test_greedy.rb +24 -0
  24. data/test/test_interstitial.rb +47 -0
  25. data/test/test_misc.rb +30 -0
  26. data/test/test_mounting.rb +89 -0
  27. data/test/test_recognize.rb +56 -0
  28. data/test/test_request.rb +85 -0
  29. data/test/test_trailing_slash.rb +28 -0
  30. data/test/test_variable.rb +108 -0
  31. metadata +41 -32
  32. data/lib/http_router/response.rb +0 -46
  33. data/spec/generate_spec.rb +0 -234
  34. data/spec/misc_spec.rb +0 -65
  35. data/spec/mounting_spec.rb +0 -5
  36. data/spec/rack/dispatch_spec.rb +0 -119
  37. data/spec/rack/generate_spec.rb +0 -29
  38. data/spec/rack/middleware_spec.rb +0 -22
  39. data/spec/rack/route_spec.rb +0 -72
  40. data/spec/rack/urlmap_spec.rb +0 -13
  41. data/spec/recognize_spec.rb +0 -497
  42. data/spec/spec_helper.rb +0 -25
@@ -0,0 +1,150 @@
1
+ require "sinatra"
2
+ require "http_router/interface/sinatra"
3
+
4
+ module CallWithMockRequestMixin
5
+ def call_with_mock_request(url = "/sample", method = "GET", params = Hash.new)
6
+ params.merge!(:method => method)
7
+ request = Rack::MockRequest.new(self)
8
+ request.request(method, url, params)
9
+ end
10
+ end
11
+
12
+ class TestRecognize < MiniTest::Unit::TestCase
13
+
14
+ def setup
15
+ @app = Sinatra.new { register HttpRouter::Interface::Sinatra::Extension }
16
+ @app.extend(CallWithMockRequestMixin)
17
+ @app.reset!
18
+ end
19
+
20
+ def test_basic
21
+ response = @app.call_with_mock_request('/bar')
22
+ assert_equal 404, response.status
23
+ end
24
+
25
+ def test_map_index
26
+ @app.get("/") { "index" }
27
+ response = @app.call_with_mock_request('/')
28
+ assert_equal 200, response.status
29
+ assert_equal "index", response.body
30
+ end
31
+
32
+ def test_trailing_slash
33
+ @app.get("/foo") { "foo" }
34
+ response = @app.call_with_mock_request('/foo')
35
+ assert_equal 200, response.status
36
+ assert_equal "foo", response.body
37
+ response = @app.call_with_mock_request('/foo/')
38
+ assert_equal 200, response.status
39
+ assert_equal "foo", response.body
40
+ end
41
+
42
+ def test_trailing_slash2
43
+ @app.get("/foo") { "foo" }
44
+ @app.get("/foo/bar") { "bar" }
45
+ response = @app.call_with_mock_request('/foo')
46
+ assert_equal 200, response.status
47
+ assert_equal "foo", response.body
48
+ response = @app.call_with_mock_request('/foo/bar')
49
+ assert_equal 200, response.status
50
+ assert_equal "bar", response.body
51
+ response = @app.call_with_mock_request('/foo/')
52
+ assert_equal 200, response.status
53
+ assert_equal "foo", response.body
54
+ response = @app.call_with_mock_request('/foo/bar/')
55
+ assert_equal 200, response.status
56
+ assert_equal "bar", response.body
57
+ end
58
+
59
+ def test_trailing_slash_with_optional_param
60
+ @app.get("/foo/(:bar)") { params[:bar] }
61
+ @app.get("/bar(/:foo)") { params[:foo] }
62
+ response = @app.call_with_mock_request('/foo/bar')
63
+ assert_equal 200, response.status
64
+ assert_equal "bar", response.body
65
+ response = @app.call_with_mock_request('/bar/foo')
66
+ assert_equal 200, response.status
67
+ assert_equal "foo", response.body
68
+ response = @app.call_with_mock_request('/bar')
69
+ assert_equal 200, response.status
70
+ assert_equal "", response.body
71
+ response = @app.call_with_mock_request('/bar/')
72
+ assert_equal 200, response.status
73
+ assert_equal "", response.body
74
+ end
75
+
76
+ def test_trailing_question_mark
77
+ @app.get("/foo/?") { "foo" }
78
+ response = @app.call_with_mock_request('/foo')
79
+ assert_equal 200, response.status
80
+ assert_equal "foo", response.body
81
+ response = @app.call_with_mock_request('/foo/')
82
+ assert_equal 200, response.status
83
+ assert_equal "foo", response.body
84
+ end
85
+
86
+ def test_map_basic
87
+ @app.get('/hi', :name => :hi) { generate(:hi) }
88
+ response = @app.call_with_mock_request('/hi')
89
+ assert_equal 200, response.status
90
+ assert_equal "/hi", response.body
91
+ end
92
+
93
+ def test_map_basic2
94
+ @app.get('/hi', :name => :hi) { generate(:hi) }
95
+ response = @app.call_with_mock_request('/hi/')
96
+ assert_equal 200, response.status
97
+ assert_equal "/hi", response.body
98
+ end
99
+
100
+ def test_map_param
101
+ @app.get('/hi/:id', :name => :hi) { generate(:hi, :id => 18) }
102
+ response = @app.call_with_mock_request('/hi/1')
103
+ assert_equal 200, response.status
104
+ assert_equal "/hi/18", response.body
105
+ end
106
+
107
+ def test_map_param2
108
+ @app.get('/hi-:id', :name => :hi) { generate(:hi, :id => 18) }
109
+ response = @app.call_with_mock_request('/hi-1')
110
+ assert_equal 200, response.status
111
+ assert_equal "/hi-18", response.body
112
+ end
113
+
114
+ def test_map_complex
115
+ @app.get('/hi/:foo/:bar/:baz(.:format)') { "/#{params[:foo]}/#{params[:bar]}/#{params[:baz]}/#{params[:format]}" }
116
+ response = @app.call_with_mock_request('/hi/foo/bar/baz')
117
+ assert_equal 200, response.status
118
+ assert_equal "/foo/bar/baz/", response.body
119
+ response = @app.call_with_mock_request('/hi/foo/bar-bax/baz')
120
+ assert_equal 200, response.status
121
+ assert_equal "/foo/bar-bax/baz/", response.body
122
+ end
123
+
124
+ def test_map_regexp
125
+ @app.get('/numbers/:digits', :matching => { :digits => /\d+/ }) { params[:digits] }
126
+ response = @app.call_with_mock_request('/numbers/2010')
127
+ assert_equal 200, response.status
128
+ assert_equal "2010", response.body
129
+ end
130
+
131
+ def test_not_map_regex
132
+ @app.get('/numbers/:digits', :matching => { :digits => /\d+/ }) { params[:digits] }
133
+ response = @app.call_with_mock_request('/numbers/nan')
134
+ assert_equal 404, response.status
135
+ end
136
+
137
+ def test_404
138
+ response = @app.call_with_mock_request('/bar')
139
+ assert_equal 404, response.status
140
+ assert_match response.body, /Sinatra doesn't know this ditty/
141
+ end
142
+
143
+ def test_405
144
+ @app.post('/bar') { 'found' }
145
+ @app.put('/bar') { 'found' }
146
+ response = @app.call_with_mock_request('/bar')
147
+ assert_equal 405, response.status
148
+ assert_equal ['POST', 'PUT'], response.headers['Allow'].split(/\s*,\s*/).sort
149
+ end
150
+ end
@@ -0,0 +1,50 @@
1
+ class TestArbitrary < MiniTest::Unit::TestCase
2
+ def test_match
3
+ hello, love80, love8080 = router {
4
+ add('test').arbitrary(Proc.new{|req, params| req.host == 'hellodooly' })
5
+ add("test").arbitrary(Proc.new{|req, params| req.host == 'lovelove' }).arbitrary{|req, params, dest| req.port == 80}
6
+ add("test").arbitrary(Proc.new{|req, params| req.host == 'lovelove' }).arbitrary{|req, params, dest| req.port == 8080}
7
+ }
8
+ assert_route love8080, 'http://lovelove:8080/test'
9
+ end
10
+
11
+ def test_less_specific_node
12
+ general, hello, love80, love8080 = router {
13
+ add("/test")
14
+ add("/test").arbitrary(Proc.new{|req, params| req.host == 'hellodooly' })
15
+ add("/test").arbitrary(Proc.new{|req, params| req.host == 'lovelove' }).arbitrary{|req, params, dest| req.port == 80}
16
+ add("/test").arbitrary(Proc.new{|req, params| req.host == 'lovelove' }).arbitrary{|req, params, dest| req.port == 8080}
17
+ }
18
+ assert_route general, 'http://lovelove:8081/test'
19
+ assert_route hello, 'http://hellodooly:8081/test'
20
+ assert_route love80, 'http://lovelove:80/test'
21
+ assert_route love8080, 'http://lovelove:8080/test'
22
+ end
23
+
24
+ def test_match_request
25
+ love80, love8080 = router {
26
+ add("/test").get.arbitrary(Proc.new{|req, params| req.host == 'lovelove' }).arbitrary{|req, params, dest| req.port == 80}
27
+ add("/test").get.arbitrary(Proc.new{|req, params| req.host == 'lovelove' }).arbitrary{|req, params, dest| req.port == 8080}
28
+ }
29
+ assert_route love80, 'http://lovelove:80/test'
30
+ assert_route love8080, 'http://lovelove:8080/test'
31
+ end
32
+
33
+ def test_less_specific_with_request
34
+ love80, love8080, general = router {
35
+ add("test").post.arbitrary(Proc.new{|req, params| req.host == 'lovelove' }).arbitrary{|req, params, dest| req.port == 80}
36
+ add("test").post.arbitrary(Proc.new{|req, params| req.host == 'lovelove' }).arbitrary{|req, params, dest| req.port == 8080}
37
+ add("test").post
38
+ }
39
+ assert_route love8080, Rack::MockRequest.env_for('http://lovelove:8080/test', :method => :post)
40
+ assert_route love80, Rack::MockRequest.env_for('http://lovelove:80/test', :method => :post)
41
+ assert_route general, Rack::MockRequest.env_for('/test', :method => :post)
42
+ end
43
+
44
+ def test_pass_params
45
+ r = router {
46
+ add(":test").get.arbitrary(Proc.new{|req, params, dest| params[:test] == 'test' })
47
+ }
48
+ assert_route r, '/test', {:test => 'test'}
49
+ end
50
+ end
@@ -0,0 +1,93 @@
1
+ class TestGenerate < MiniTest::Unit::TestCase
2
+
3
+ def test_static
4
+ router {
5
+ add('/').name(:a)
6
+ add('/test').name(:b)
7
+ add('/test/time').name(:c)
8
+ add('/one/more/what').name(:d)
9
+ add('/test.html').name(:e)
10
+ }
11
+ assert_generate '/', :a
12
+ assert_generate '/test', :b
13
+ assert_generate '/test/time', :c
14
+ assert_generate '/one/more/what', :d
15
+ assert_generate '/test.html', :e
16
+ end
17
+
18
+ def test_dynamic
19
+ assert_generate '/test', '/:var', :var => 'test'
20
+ assert_generate '/test', '/:var', 'test'
21
+ end
22
+
23
+ def test_array_with_extras
24
+ assert_generate '/test?query=string', '/:var', :var => 'test', :query => 'string'
25
+ assert_generate '/test?query=string', '/:var', 'test', :query => 'string'
26
+ end
27
+
28
+ def test_multiple_dynamics
29
+ assert_generate '/one/two', "/:var/:baz", :var => 'one', :baz => 'two'
30
+ assert_generate '/one/two', "/:var/:baz", 'one', 'two'
31
+ end
32
+
33
+ def test_extension
34
+ assert_generate '/test.html', "/test.:format", :format => 'html'
35
+ assert_generate '/test.html', "/test.:format", 'html'
36
+ end
37
+
38
+ def test_optional_extension
39
+ assert_generate '/test.html', "/test(.:format)", :format => 'html'
40
+ assert_generate '/test.html', "/test(.:format)", 'html'
41
+ assert_generate '/test', "/test(.:format)"
42
+ end
43
+
44
+ def test_variable_with_extension
45
+ assert_generate '/test.html', "/:var.:format", :var => 'test', :format => 'html'
46
+ assert_generate '/test.html', "/:var.:format", 'test', 'html'
47
+ end
48
+
49
+ def test_variable_with_optional_extension
50
+ assert_generate '/test.html', "/:var(.:format)", :var => 'test', :format => 'html'
51
+ assert_generate '/test.html', "/:var(.:format)", 'test', 'html'
52
+ assert_generate '/test', "/:var(.:format)", :var => 'test'
53
+ assert_generate '/test', "/:var(.:format)", 'test'
54
+ end
55
+
56
+ def test_optionals
57
+ assert_generate '/var', "/:var1(/:var2)", 'var'
58
+ assert_generate '/var/fooz', "/:var1(/:var2)", 'var', 'fooz'
59
+ assert_generate '/var', "/:var1(/:var2)", :var1 => 'var'
60
+ assert_generate '/var/fooz', "/:var1(/:var2)", :var1 => 'var', :var2 => 'fooz'
61
+ assert_raises(HttpRouter::UngeneratableRouteException) { router.url(router.add("/:var1(/:var2)").to(:test), :var2 => 'fooz') }
62
+ end
63
+
64
+ def test_optionals_with_format
65
+ assert_generate '/var', "/:var1(/:var2.:format)", 'var'
66
+ assert_generate '/var/fooz.html', "/:var1(/:var2.:format)", 'var', 'fooz', 'html'
67
+ assert_generate '/var', "/:var1(/:var2.:format)", :var1 => 'var'
68
+ assert_generate '/var/fooz.html', "/:var1(/:var2.:format)", :var1 => 'var', :var2 => 'fooz', :format => 'html'
69
+ end
70
+
71
+ def test_nested_optionals
72
+ assert_generate '/var', "/:var1(/:var2(/:var3))", 'var'
73
+ assert_generate '/var/fooz', "/:var1(/:var2(/:var3))", 'var', 'fooz'
74
+ assert_generate '/var/fooz/baz', "/:var1(/:var2(/:var3))", 'var', 'fooz', 'baz'
75
+ assert_generate '/var', "/:var1(/:var2(/:var3))", :var1 => 'var'
76
+ assert_generate '/var/fooz', "/:var1(/:var2(/:var3))", :var1 => 'var', :var2 => 'fooz'
77
+ assert_generate '/var/fooz/baz', "/:var1(/:var2(/:var3))", :var1 => 'var', :var2 => 'fooz', :var3 => 'baz'
78
+ end
79
+
80
+ def test_default_value
81
+ assert_generate "/123?page=1", router.add("/:var").default(:page => 1), 123
82
+ assert_generate "/1/123", router.add("/:page/:entry").default(:page => 1), :entry => '123'
83
+ end
84
+
85
+ def test_nil_values
86
+ assert_generate '/url', "/url(/:var)", :var => nil
87
+ end
88
+
89
+ def test_raise
90
+ r = router { add(':var').matching(:var => /\d+/) }
91
+ assert_raises(HttpRouter::InvalidRouteException) { router.url(r, 'asd') }
92
+ end
93
+ end
@@ -0,0 +1,24 @@
1
+ class TestGreedy < MiniTest::Unit::TestCase
2
+ def test_mix_regex_with_greedy
3
+ regex, greedy = router {
4
+ add("/:test/number").matching(:test => /\d+/)
5
+ add("/:test/anything")
6
+ }
7
+ assert_route regex, '/123/number', {:test => '123'}
8
+ assert_route greedy, '/123/anything', {:test => '123'}
9
+ end
10
+
11
+ def test_trailing_slash
12
+ assert_route router.add("/:test").matching(:test => /.*/), '/test/', {:test => 'test/'}
13
+ end
14
+
15
+ def test_extension
16
+ assert_route router.add("/:test").matching(:test => /.*/), '/test.html', {:test => 'test.html'}
17
+ end
18
+
19
+ def test_match_at_beginning
20
+ r = router { add(':test', :test => /\d+/)}
21
+ assert_route r, '/123', {:test => '123'}
22
+ assert_route nil, '/a123'
23
+ end
24
+ end
@@ -0,0 +1,47 @@
1
+ class TestInterstitial < MiniTest::Unit::TestCase
2
+ def test_recognize
3
+ assert_route '/one-:variable-time', '/one-value-time', {:variable => 'value'}
4
+ end
5
+
6
+ def test_regex
7
+ r = router { add('/one-:variable-time').matching(:variable => /\d+/) }
8
+ assert_route r, '/one-123-time', {:variable => '123'}
9
+ assert_route nil, '/one-value-time'
10
+ end
11
+
12
+ def test_regex_as_options
13
+ r = router { add('/one-:variable-time', :variable => /\d+/) }
14
+ assert_route r, '/one-123-time', {:variable => '123'}
15
+ assert_route nil, '/one-value-time'
16
+ end
17
+
18
+ def test_extension
19
+ assert_route 'hey.:greed.html', '/hey.greedybody.html', {:greed => 'greedybody'}
20
+ end
21
+
22
+ def test_multi
23
+ r1, r2, r3, r4, r5, r6 = router {
24
+ add('/:var1')
25
+ add('/:var1-:var2')
26
+ add('/:var1-:var2-:var3')
27
+ add('/:var1-:var2-:var3-:var4')
28
+ add('/:var1-:var2-:var3-:var4-:var5')
29
+ add('/:var1-:var2-:var3-:var4-:var5-:var6')
30
+ }
31
+ assert_route r1, '/one', {:var1 => 'one'}
32
+ assert_route r2, '/one-value', {:var1 => 'one', :var2 => 'value'}
33
+ assert_route r3, '/one-value-time', {:var1 => 'one', :var2 => 'value', :var3 => 'time'}
34
+ assert_route r4, '/one-value-time-one', {:var1 => 'one', :var2 => 'value', :var3 => 'time', :var4 => 'one'}
35
+ assert_route r5, '/one-value-time-one-variable', {:var1 => 'one', :var2 => 'value', :var3 => 'time', :var4 => 'one', :var5 => 'variable'}
36
+ assert_route r6, '/one-value-time-one-value-time', {:var1 => 'one', :var2 => 'value', :var3 => 'time', :var4 => 'one', :var5 => 'value', :var6 => 'time'}
37
+ end
38
+
39
+ def test_regex_with_mutliple_variables
40
+ with_regex, without_regex = router {
41
+ add("/:common_variable.:matched").matching(:matched => /\d+/)
42
+ add("/:common_variable.:unmatched")
43
+ }
44
+ assert_route with_regex, '/common.123', {:common_variable => 'common', :matched => '123'}
45
+ assert_route without_regex, '/common.other', {:common_variable => 'common', :unmatched => 'other'}
46
+ end
47
+ end
data/test/test_misc.rb ADDED
@@ -0,0 +1,30 @@
1
+ class TestMisc < MiniTest::Unit::TestCase
2
+ def test_exceptions
3
+ assert_raises(HttpRouter::AmbiguousRouteException) {HttpRouter.new.add("/:var1(/:var2)(/:var3)").compile}
4
+ assert_raises(HttpRouter::AmbiguousVariableException) {HttpRouter.new.add("/:var1(/:var1)(/:var1)").compile}
5
+ assert_raises(HttpRouter::UnsupportedRequestConditionError) {HttpRouter.new.add("/").condition(:flibberty => 'gibet').compile}
6
+ end
7
+
8
+ def test_cloning
9
+ r1 = HttpRouter.new {
10
+ add('/test').name(:test_route).to :test
11
+ }
12
+ r2 = r1.clone
13
+
14
+ r2.add('/test2').name(:test).to(:test2)
15
+ assert_equal 2, r2.routes.size
16
+
17
+ assert r1.recognize(Rack::MockRequest.env_for('/test2')).nil?
18
+ assert !r2.recognize(Rack::MockRequest.env_for('/test2')).nil?
19
+ assert_equal r1.routes.first, r1.named_routes[:test_route]
20
+ assert_equal r2.routes.first, r2.named_routes[:test_route]
21
+
22
+ r1.add('/another').name(:test).to(:test2)
23
+
24
+ assert_equal r1.routes.size, r2.routes.size
25
+ assert_equal '/another', r1.url(:test)
26
+ assert_equal '/test2', r2.url(:test)
27
+ assert_equal :test, r1.routes.first.dest
28
+ assert_equal :test, r2.routes.first.dest
29
+ end
30
+ end
@@ -0,0 +1,89 @@
1
+ class TestMounting < MiniTest::Unit::TestCase
2
+ def setup
3
+ @r1 = HttpRouter.new
4
+ @r2 = HttpRouter.new
5
+ @r2.add("/bar").name(:test).compile
6
+ end
7
+
8
+ def test_url_mount_for_child_route
9
+ route = @r1.add("/foo").to(@r2)
10
+ assert_equal "/foo", @r2.url_mount.url
11
+ assert_equal "/foo/bar", @r2.url(:test)
12
+ end
13
+
14
+ def test_default_values
15
+ route = @r1.add("/foo/:bar").default(:bar => "baz").to(@r2)
16
+ assert_equal "/foo/baz/bar", @r2.url(:test)
17
+ assert_equal "/foo/haha/bar", @r2.url(:test, :bar => "haha")
18
+ end
19
+
20
+ def test_multiple_values
21
+ @r1.add("/foo/:bar/:baz").default(:bar => "bar").to(@r2)
22
+ assert_equal "/foo/bar/baz/bar", @r2.url(:test, :baz => "baz")
23
+ end
24
+
25
+ def test_bubble_params
26
+ route = @r1.add("/foo/:bar").default(:bar => "baz").to(@r2)
27
+ assert_equal "/foo/baz/bar?bang=ers", @r2.url(:test, :bang => "ers")
28
+ assert_equal "/foo/haha/bar?bang=ers", @r2.url(:test, :bar => "haha", :bang => "ers")
29
+ end
30
+
31
+ def test_path_with_optional
32
+ @r1.add("/foo(/:bar)").to(@r2)
33
+ @r2.add("/hey(/:there)").name(:test).compile
34
+ assert_equal "/foo/hey", @r2.url(:test)
35
+ assert_equal "/foo/bar/hey", @r2.url(:test, :bar => "bar")
36
+ assert_equal "/foo/bar/hey/there", @r2.url(:test, :bar => "bar", :there => "there")
37
+ end
38
+
39
+ def test_nest3
40
+ @r3 = HttpRouter.new
41
+ @r1.add("/foo(/:bar)").default(:bar => "barry").to(@r2)
42
+ @r2.add("/hi").name(:hi).compile
43
+ @r2.add("/mounted").to(@r3)
44
+ @r3.add("/endpoint").name(:endpoint).compile
45
+
46
+ assert_equal "/foo/barry/hi", @r2.url(:hi)
47
+ assert_equal "/foo/barry/mounted/endpoint", @r3.url(:endpoint)
48
+ assert_equal "/foo/flower/mounted/endpoint", @r3.url(:endpoint, :bar => "flower")
49
+ end
50
+
51
+ def test_with_default_host
52
+ @r1.add("/mounted").default(:host => "example.com").to(@r2)
53
+ assert_equal "http://example.com/mounted/bar", @r2.url(:test)
54
+ end
55
+
56
+ def test_with_host
57
+ @r1.add("/mounted").to(@r2)
58
+ assert_equal "/mounted/bar", @r2.url(:test)
59
+ assert_equal "http://example.com/mounted/bar", @r2.url(:test, :host => "example.com")
60
+ end
61
+
62
+ def test_with_scheme
63
+ @r1.add("/mounted").to(@r2)
64
+ assert_equal "/mounted/bar", @r2.url(:test)
65
+ assert_equal "https://example.com/mounted/bar", @r2.url(:test, :scheme => "https", :host => "example.com")
66
+ end
67
+
68
+ def test_clone
69
+ @r3 = HttpRouter.new
70
+ @r1.add("/first").to(@r2)
71
+ @r2.add("/second").to(@r3)
72
+ r1 = @r1.clone
73
+ assert @r1.routes.first
74
+ r2 = r1.routes.first.dest
75
+ assert r2
76
+ assert_equal @r1.routes.first.dest.object_id, @r2.object_id
77
+ assert r2.object_id != @r2.object_id
78
+ assert_equal 2, r2.routes.size
79
+ r3 = r2.routes.last.dest
80
+ assert_instance_of HttpRouter, r3
81
+ assert r3.object_id != @r3.object_id
82
+ end
83
+ end
84
+
85
+ # it "should clone my nested structure" do
86
+ # end
87
+ # end
88
+ # end
89
+ #end
@@ -0,0 +1,56 @@
1
+ class TestRecognition < MiniTest::Unit::TestCase
2
+ def test_simple
3
+ assert_route router.add(''), '/'
4
+ assert_route router.add('/'), '/'
5
+ assert_route router.add('/test'), '/test'
6
+ assert_route router.add('/test/one'), '/test/one'
7
+ assert_route router.add('/test/one/two'), '/test/one/two'
8
+ assert_route router.add('/test.html'), '/test.html'
9
+ assert_route router.add('/.html'), '/.html'
10
+ end
11
+
12
+ def test_optional
13
+ route = router {
14
+ add 'one(/two(/three(/four)(/five)))'
15
+ }
16
+ assert_route route, '/one'
17
+ assert_route route, '/one/two'
18
+ assert_route route, '/one/two/three'
19
+ assert_route route, '/one/two/three/four'
20
+ assert_route route, '/one/two/three/five'
21
+ end
22
+
23
+ def test_escape_paren
24
+ assert_route router.add('/test\(:variable\)'), '/test(hello)', {:variable => 'hello'}
25
+ end
26
+
27
+ def test_escape_colon
28
+ assert_route router.add('/test\:variable'), '/test:variable'
29
+ end
30
+
31
+ def test_escape_star
32
+ assert_route router.add('/test\*variable'), '/test*variable'
33
+ end
34
+
35
+ def test_partial
36
+ router.add("/test*").to { |env| Rack::Response.new(env['PATH_INFO']).finish }
37
+ assert_body '/optional', router.call(Rack::MockRequest.env_for('/test/optional'))
38
+ assert_body '/', router.call(Rack::MockRequest.env_for('/test'))
39
+ end
40
+
41
+ def test_partial_root
42
+ router.add("/*").to { |env| Rack::Response.new(env['PATH_INFO']).finish }
43
+ assert_body '/optional', router.call(Rack::MockRequest.env_for('/optional'))
44
+ assert_body '/', router.call(Rack::MockRequest.env_for('/'))
45
+ end
46
+
47
+ def test_multiple_partial
48
+ test, root = router {
49
+ add("/test").partial.to{|env| [200, {}, ['/test',env['PATH_INFO']]]}
50
+ add("/").partial.to{|env| [200, {}, ['/',env['PATH_INFO']]]}
51
+ }
52
+ assert_body ['/test', '/optional'], router.call(Rack::MockRequest.env_for('/test/optional'))
53
+ assert_body ['/test', '/optional/'], router.call(Rack::MockRequest.env_for('/test/optional/'))
54
+ assert_body ['/', '/testing/optional'], router.call(Rack::MockRequest.env_for('/testing/optional'))
55
+ end
56
+ end
@@ -0,0 +1,85 @@
1
+ class TestRequest < MiniTest::Unit::TestCase
2
+ def test_simple_case
3
+ r = router { add('test').post }
4
+ assert_route r, Rack::MockRequest.env_for('/test', :method => 'POST')
5
+ assert_header({'Allow' => 'POST'}, Rack::MockRequest.env_for('/test', :method => 'GET'))
6
+ assert_status(405, Rack::MockRequest.env_for('/test', :method => 'GET'))
7
+ end
8
+
9
+ def test_with_optional_parts_and_405
10
+ get, post, delete = router {
11
+ get('test(.:format)')
12
+ post('test(.:format)')
13
+ delete('test(.:format)')
14
+ }
15
+ assert_route get, Rack::MockRequest.env_for('/test', :method => 'GET')
16
+ assert_route post, Rack::MockRequest.env_for('/test', :method => 'POST')
17
+ assert_route delete, Rack::MockRequest.env_for('/test', :method => 'DELETE')
18
+ assert_route get, Rack::MockRequest.env_for('/test.html', :method => 'GET'), {:format => 'html'}
19
+ assert_route post, Rack::MockRequest.env_for('/test.html', :method => 'POST'), {:format => 'html'}
20
+ assert_route delete, Rack::MockRequest.env_for('/test.html', :method => 'DELETE'), {:format => 'html'}
21
+ put = router.call(Rack::MockRequest.env_for('/test', :method => 'PUT'))
22
+ assert_status 405, put
23
+ assert_equal %w{DELETE GET POST}, put[1]['Allow'].split(/\s*,\s*/).sort
24
+ end
25
+
26
+ def test_deeply
27
+ test_post, test_post_post, test_get, test_post_get, test_post_catchall, test_catchall = router {
28
+ post("/test")
29
+ post("/test/post")
30
+ get("/test")
31
+ get("/test/post")
32
+ add("/test/post")
33
+ add("/test")
34
+ }
35
+ assert_route test_post, Rack::MockRequest.env_for('/test', :method => 'POST')
36
+ assert_route test_get, Rack::MockRequest.env_for('/test', :method => 'GET')
37
+ assert_route test_catchall, Rack::MockRequest.env_for('/test', :method => 'PUT')
38
+ assert_route test_post_post, Rack::MockRequest.env_for('/test/post', :method => 'POST')
39
+ assert_route test_post_get, Rack::MockRequest.env_for('/test/post', :method => 'GET')
40
+ assert_route test_post_catchall, Rack::MockRequest.env_for('/test/post', :method => 'PUT')
41
+ end
42
+
43
+ def test_move_node
44
+ general, post = router {
45
+ add("/test").default_destination
46
+ post("/test").default_destination
47
+ }
48
+ assert_route post, Rack::MockRequest.env_for('/test', :method => 'POST')
49
+ assert_route general, Rack::MockRequest.env_for('/test', :method => 'PUT')
50
+ end
51
+
52
+ def test_complex_routing
53
+ host2, post, host2_get, host2_post = router {
54
+ add("/test").host('host2')
55
+ add("/test").post
56
+ add("/test").host('host2').get
57
+ add("/test").post.host('host2')
58
+ }
59
+ assert_route host2, Rack::MockRequest.env_for('http://host2/test', :method => 'PUT')
60
+ assert_route post, Rack::MockRequest.env_for('http://host1/test', :method => 'POST')
61
+ assert_route host2_get, Rack::MockRequest.env_for('http://host2/test', :method => 'GET')
62
+ assert_route host2_post, Rack::MockRequest.env_for('http://host2/test', :method => 'POST')
63
+ end
64
+
65
+ def test_regexp
66
+ with, without = router {
67
+ get("/test").host(/host1/)
68
+ get("/test")
69
+ }
70
+ assert_route without, 'http://host2/test'
71
+ assert_route with, 'http://host2.host1.com/test'
72
+ end
73
+
74
+ def test_all_routes
75
+ router {
76
+ post("/test").host('host1')
77
+ }
78
+ assert_route router.add("/test").host('host2'), Rack::MockRequest.env_for('http://host2/test', :method => 'POST')
79
+ end
80
+
81
+ def test_match_on_scheme
82
+ http, https = router { get("/test").scheme('http'); get("/test").scheme('https') }
83
+ assert_status 405, Rack::MockRequest.env_for('https://example.org/test', :method => 'POST')
84
+ end
85
+ end
@@ -0,0 +1,28 @@
1
+ class TestVariable < MiniTest::Unit::TestCase
2
+ def test_ignore_trailing_slash
3
+ assert_route router.add('/test'), '/test/'
4
+ end
5
+
6
+ def test_ignore_trailing_slash_disabled
7
+ assert_route router(:ignore_trailing_slash => false).add('/test/?'), '/test/'
8
+ end
9
+
10
+ def test_ignore_trailing_slash_enabled
11
+ router(:ignore_trailing_slash => false).add('/test/?')
12
+ assert_route nil, '/test/'
13
+ end
14
+
15
+ def test_capture_with_trailing_slash
16
+ assert_route router.add('/:test'), '/test/', {:test => 'test'}
17
+ end
18
+
19
+ def test_trailing_slash_confusion
20
+ more_general, more_specific = router {
21
+ add('foo')
22
+ add('foo/:bar/:id')
23
+ }
24
+ assert_route more_general, '/foo'
25
+ assert_route more_general, '/foo/'
26
+ assert_route more_specific, '/foo/5/10', {:bar => '5', :id => '10'}
27
+ end
28
+ end