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.
- data/Rakefile +6 -5
- data/benchmarks/rack_mount.rb +16 -45
- data/benchmarks/rec2.rb +8 -8
- data/http_router.gemspec +5 -4
- data/lib/http_router/interface/sinatra.rb +7 -7
- data/lib/http_router/node.rb +106 -105
- data/lib/http_router/optional_compiler.rb +14 -5
- data/lib/http_router/path.rb +18 -28
- data/lib/http_router/root.rb +17 -29
- data/lib/http_router/route.rb +47 -16
- data/lib/http_router/static.rb +5 -0
- data/lib/http_router/variable.rb +2 -5
- data/lib/http_router/version.rb +1 -1
- data/lib/http_router.rb +38 -65
- data/test/helper.rb +74 -0
- data/test/rack/test_dispatch.rb +120 -0
- data/test/rack/test_route.rb +44 -0
- data/test/rack/test_urlmap.rb +12 -0
- data/{spec → test}/sinatra/recognize_spec.rb +0 -0
- data/test/sinatra/test_recognize.rb +150 -0
- data/test/test_arbitrary.rb +50 -0
- data/test/test_generate.rb +93 -0
- data/test/test_greedy.rb +24 -0
- data/test/test_interstitial.rb +47 -0
- data/test/test_misc.rb +30 -0
- data/test/test_mounting.rb +89 -0
- data/test/test_recognize.rb +56 -0
- data/test/test_request.rb +85 -0
- data/test/test_trailing_slash.rb +28 -0
- data/test/test_variable.rb +108 -0
- metadata +41 -32
- data/lib/http_router/response.rb +0 -46
- data/spec/generate_spec.rb +0 -234
- data/spec/misc_spec.rb +0 -65
- data/spec/mounting_spec.rb +0 -5
- data/spec/rack/dispatch_spec.rb +0 -119
- data/spec/rack/generate_spec.rb +0 -29
- data/spec/rack/middleware_spec.rb +0 -22
- data/spec/rack/route_spec.rb +0 -72
- data/spec/rack/urlmap_spec.rb +0 -13
- data/spec/recognize_spec.rb +0 -497
- 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
|
data/test/test_greedy.rb
ADDED
@@ -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
|