doze 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/README +6 -0
  2. data/lib/doze/application.rb +92 -0
  3. data/lib/doze/collection/object.rb +14 -0
  4. data/lib/doze/entity.rb +62 -0
  5. data/lib/doze/error.rb +75 -0
  6. data/lib/doze/media_type.rb +135 -0
  7. data/lib/doze/negotiator.rb +107 -0
  8. data/lib/doze/request.rb +119 -0
  9. data/lib/doze/resource/error.rb +21 -0
  10. data/lib/doze/resource/proxy.rb +81 -0
  11. data/lib/doze/resource.rb +193 -0
  12. data/lib/doze/responder/error.rb +34 -0
  13. data/lib/doze/responder/main.rb +41 -0
  14. data/lib/doze/responder/resource.rb +262 -0
  15. data/lib/doze/responder.rb +58 -0
  16. data/lib/doze/response.rb +78 -0
  17. data/lib/doze/router/anchored_route_set.rb +68 -0
  18. data/lib/doze/router/route.rb +88 -0
  19. data/lib/doze/router/route_set.rb +34 -0
  20. data/lib/doze/router.rb +100 -0
  21. data/lib/doze/serialization/entity.rb +34 -0
  22. data/lib/doze/serialization/form_data_helpers.rb +40 -0
  23. data/lib/doze/serialization/html.rb +116 -0
  24. data/lib/doze/serialization/json.rb +29 -0
  25. data/lib/doze/serialization/multipart_form_data.rb +162 -0
  26. data/lib/doze/serialization/resource.rb +30 -0
  27. data/lib/doze/serialization/resource_proxy.rb +14 -0
  28. data/lib/doze/serialization/www_form_encoded.rb +42 -0
  29. data/lib/doze/serialization/yaml.rb +25 -0
  30. data/lib/doze/uri_template.rb +220 -0
  31. data/lib/doze/utils.rb +53 -0
  32. data/lib/doze/version.rb +3 -0
  33. data/lib/doze.rb +5 -0
  34. data/test/functional/auth_test.rb +69 -0
  35. data/test/functional/base.rb +159 -0
  36. data/test/functional/cache_header_test.rb +76 -0
  37. data/test/functional/direct_response_test.rb +16 -0
  38. data/test/functional/error_handling_test.rb +131 -0
  39. data/test/functional/get_and_conneg_test.rb +182 -0
  40. data/test/functional/media_type_extensions_test.rb +102 -0
  41. data/test/functional/media_type_test.rb +40 -0
  42. data/test/functional/method_support_test.rb +49 -0
  43. data/test/functional/non_get_method_test.rb +173 -0
  44. data/test/functional/precondition_test.rb +84 -0
  45. data/test/functional/raw_path_info_test.rb +69 -0
  46. data/test/functional/resource_representation_test.rb +14 -0
  47. data/test/functional/router_test.rb +196 -0
  48. data/test/functional/serialization_test.rb +142 -0
  49. data/test/functional/uri_template_test.rb +51 -0
  50. metadata +221 -0
@@ -0,0 +1,40 @@
1
+ require 'functional/base'
2
+
3
+ require 'doze/media_type'
4
+
5
+ class MediaTypeTest < Test::Unit::TestCase
6
+ include Doze::Utils
7
+ include Doze::TestCase
8
+ include Doze::MediaTypeTestCase
9
+
10
+ def test_put_registered_media_type_same_instance
11
+ foobar = Doze::MediaType.register('application/x-foo-bar')
12
+ root.expects(:supports_put?).returns(true)
13
+ root.expects(:accepts_put_with_media_type?).returns(true)
14
+ root.expects(:put).with {|entity| entity.media_type.equal?(foobar)}.returns(nil).once
15
+ put('CONTENT_TYPE' => 'application/x-foo-bar', :input => 'foo')
16
+ assert_equal STATUS_NO_CONTENT, last_response.status
17
+ end
18
+
19
+ def test_put_unregistered_media_type_equal
20
+ boo = Doze::MediaType.new('application/x-boo')
21
+ root.expects(:supports_put?).returns(true)
22
+ root.expects(:accepts_put_with_media_type?).returns(true)
23
+ root.expects(:put).with {|entity| entity && entity.media_type == boo}.returns(nil).once
24
+ put('CONTENT_TYPE' => 'application/x-boo', :input => 'foo')
25
+ assert_equal STATUS_NO_CONTENT, last_response.status
26
+ end
27
+
28
+
29
+
30
+ def test_lookup_name
31
+ mt = Doze::MediaType.register("application/foo")
32
+ assert Doze::MediaType["application/foo"].equal?(mt)
33
+ end
34
+
35
+ def test_lookup_alias
36
+ mt = Doze::MediaType.register("application/foo", :aliases => ['bar/foo'])
37
+ assert_equal Doze::MediaType["bar/foo"], mt
38
+ assert_equal ['application/foo', 'bar/foo'], mt.names
39
+ end
40
+ end
@@ -0,0 +1,49 @@
1
+ require 'functional/base'
2
+
3
+ class MethodSupportTest < Test::Unit::TestCase
4
+ include Doze::Utils
5
+ include Doze::TestCase
6
+
7
+ def test_unrecognized_method
8
+ app(:recognized_methods => [:get,:put,:post,:delete])
9
+ root.expects(:supports_method?).never
10
+ assert_equal STATUS_NOT_IMPLEMENTED, other_request_method('FOO').status
11
+ end
12
+
13
+ def test_recognized_but_not_supported_method
14
+ app(:recognized_methods => [:foo,:bar])
15
+
16
+ seq = sequence('support_calls')
17
+ root.expects(:supports_method?).with(:foo).returns(false).at_least_once.in_sequence(seq)
18
+ root.expects(:supports_method?).with(:bar).returns(true).at_least_once.in_sequence(seq)
19
+
20
+ assert_equal STATUS_METHOD_NOT_ALLOWED, other_request_method('FOO').status
21
+ allow = last_response.headers['Allow'] and allow = allow.split(', ')
22
+ assert_equal ['BAR','OPTIONS'], allow.sort
23
+ end
24
+
25
+ def test_recognized_and_supported_method_via_supports_foo
26
+ app(:recognized_methods => [:foo,:bar])
27
+
28
+ root.expects(:supports_foo?).returns(true).at_least_once
29
+ root.expects(:accepts_method_with_media_type?).with(:foo, anything).returns(true).at_least_once
30
+ root.expects(:supports_bar?).never
31
+ root.expects(:other_method).with(:foo, anything).returns(nil).once
32
+ assert_equal STATUS_NO_CONTENT, other_request_method('FOO').status
33
+ end
34
+
35
+ def test_options_with_get_supported_with_head_and_options_handled_automatically
36
+ root.expects(:supports_get?).returns(true).once
37
+ assert_equal STATUS_NO_CONTENT, other_request_method('OPTIONS').status
38
+
39
+ allow = last_response.headers['Allow'] and allow = allow.split(', ')
40
+ assert_not_nil allow
41
+ assert_equal ['GET','HEAD','OPTIONS'], allow.sort
42
+ end
43
+
44
+ def test_options_on_missing_resource
45
+ assert_equal STATUS_NO_CONTENT, other_request_method('OPTIONS', '/blah').status
46
+ allow = last_response.headers['Allow'] and allow = allow.split(', ')
47
+ assert_equal ['OPTIONS'], allow
48
+ end
49
+ end
@@ -0,0 +1,173 @@
1
+ require 'functional/base'
2
+
3
+ class NonGetMethodTest < Test::Unit::TestCase
4
+ include Doze::Utils
5
+ include Doze::TestCase
6
+ include Doze::MediaTypeTestCase
7
+
8
+ def setup
9
+ super
10
+ @foo = Doze::MediaType.new('text/foo')
11
+ @bar = Doze::MediaType.new('text/bar')
12
+ end
13
+
14
+ def test_put_with_unacceptable_media_type
15
+ root.expects(:supports_put?).returns(true)
16
+ root.expects(:accepts_put_with_media_type?).with do |a|
17
+ a.is_a?(Doze::Entity) && a.media_type == @foo &&
18
+ a.binary_data_stream.respond_to?(:read) && a.binary_data_stream.read == 'foo' &&
19
+ a.binary_data == 'foo'
20
+ end.returns(false)
21
+ root.expects(:put).never
22
+ put('CONTENT_TYPE' => 'text/foo', :input => 'foo')
23
+ assert_equal STATUS_UNSUPPORTED_MEDIA_TYPE, last_response.status
24
+ end
25
+
26
+ def test_put
27
+ root.expects(:supports_put?).returns(true)
28
+ root.expects(:accepts_put_with_media_type?).with {|a| a.is_a?(Doze::Entity) && a.media_type == @foo}.returns(true)
29
+ root.expects(:put).with do |value|
30
+ value.is_a?(Doze::Entity) and
31
+ value.binary_data == 'foo' and value.media_type == @foo and value.encoding == 'foobar'
32
+ end.returns(nil).once
33
+
34
+ put('CONTENT_TYPE' => 'text/foo; charset=foobar', :input => 'foo')
35
+ assert_equal STATUS_NO_CONTENT, last_response.status
36
+ end
37
+
38
+ def test_put_where_not_exists
39
+ root.expects(:exists?).returns(false)
40
+ root.expects(:supports_put?).returns(true)
41
+ root.expects(:accepts_put_with_media_type?).with {|a| a.is_a?(Doze::Entity) && a.media_type == @foo}.returns(true)
42
+ root.expects(:put).returns(nil).once
43
+
44
+ put('CONTENT_TYPE' => 'text/foo; charset=foobar', :input => 'foo')
45
+ assert_equal STATUS_CREATED, last_response.status
46
+ end
47
+
48
+ def test_post_with_unacceptable_media_type
49
+ root.expects(:supports_post?).returns(true)
50
+ root.expects(:accepts_post_with_media_type?).with {|a| a.is_a?(Doze::Entity) && a.media_type == @foo}.returns(false)
51
+ root.expects(:post).never
52
+ post('CONTENT_TYPE' => 'text/foo', :input => 'foo')
53
+ assert_equal STATUS_UNSUPPORTED_MEDIA_TYPE, last_response.status
54
+ end
55
+
56
+ def test_post_returning_created_resource
57
+ root.expects(:supports_post?).returns(true)
58
+ root.expects(:accepts_post_with_media_type?).with {|a| a.is_a?(Doze::Entity) && a.media_type == @foo}.returns(true)
59
+ created = mock_resource('/uri', 'foo')
60
+ root.expects(:post).with do |value|
61
+ value.is_a?(Doze::Entity) and
62
+ value.binary_data == 'foob' and value.media_type == @foo and value.encoding == 'foobar'
63
+ end.returns(created).once
64
+
65
+ post('CONTENT_TYPE' => 'text/foo; charset=foobar', :input => 'foob')
66
+ assert_equal STATUS_CREATED, last_response.status
67
+ assert_response_header 'Location', 'http://example.org/uri'
68
+ assert_equal 'foo', last_response.body
69
+ end
70
+
71
+ def test_post_returning_nothing
72
+ root.expects(:supports_post?).returns(true)
73
+ root.expects(:accepts_post_with_media_type?).with {|a| a.is_a?(Doze::Entity) && a.media_type == @foo}.returns(true)
74
+ root.expects(:post).returns(nil).once
75
+
76
+ post('CONTENT_TYPE' => 'text/foo; charset=foobar', :input => 'foob')
77
+ assert_equal STATUS_NO_CONTENT, last_response.status
78
+ end
79
+
80
+ def test_post_with_extra_arity_gets_session
81
+ root.expects(:supports_post?).returns(true)
82
+ root.expects(:accepts_post_with_media_type?).with {|a| a.is_a?(Doze::Entity) && a.media_type == @foo}.returns(true)
83
+
84
+ # Because mocha doesn't set the arity right
85
+ def root.post(a, b)
86
+ post_actually_called(a, b)
87
+ end
88
+ root.expects(:post_actually_called).with(instance_of(Doze::Entity), "user").once
89
+
90
+ post('REMOTE_USER' => 'user', 'CONTENT_TYPE' => 'text/foo; charset=foobar', :input => 'foob')
91
+ assert_equal STATUS_NO_CONTENT, last_response.status
92
+ end
93
+
94
+ def test_post_returning_entity
95
+ root.expects(:supports_post?).returns(true)
96
+ root.expects(:accepts_post_with_media_type?).with {|a| a.is_a?(Doze::Entity) && a.media_type == @foo}.returns(true)
97
+ root.expects(:post).returns(mock_entity('bar', @bar)).once
98
+
99
+ post('CONTENT_TYPE' => 'text/foo; charset=foobar', :input => 'foob')
100
+ assert_equal STATUS_OK, last_response.status
101
+ assert_equal 'bar', last_response.body
102
+ assert_equal 'text/bar', last_response.media_type
103
+ end
104
+
105
+ def test_post_returning_anonymous_resource
106
+ root.expects(:supports_post?).returns(true)
107
+ root.expects(:accepts_post_with_media_type?).with {|a| a.is_a?(Doze::Entity) && a.media_type == @foo}.returns(true)
108
+ resource = mock_resource(nil)
109
+ resource.expects(:get).returns(mock_entity('bar', @bar))
110
+ root.expects(:post).returns(resource).once
111
+
112
+ post('CONTENT_TYPE' => 'text/foo; charset=foobar', :input => 'foob')
113
+ assert_equal STATUS_OK, last_response.status
114
+ assert_equal 'bar', last_response.body
115
+ assert_equal 'text/bar', last_response.media_type
116
+ end
117
+
118
+ def test_delete
119
+ root.expects(:supports_delete?).returns(true)
120
+ root.expects(:accepts_delete_with_media_type?).never
121
+ root.expects(:delete_resource).returns(nil).once
122
+
123
+ delete
124
+ assert_equal STATUS_NO_CONTENT, last_response.status
125
+ assert last_response.body.empty?
126
+ end
127
+
128
+ def test_other_method_with_no_response
129
+ # PATCH used as an example here
130
+ app(:recognized_methods => [:get,:post,:put,:delete,:patch])
131
+
132
+ root.expects(:supports_patch?).returns(true)
133
+ root.expects(:accepts_method_with_media_type?).with {|m,a| m == :patch && a.is_a?(Doze::Entity) && a.media_type == @foo}.returns(true)
134
+ root.expects(:patch).with do |value|
135
+ value.is_a?(Doze::Entity) and
136
+ value.binary_data == 'foob' and value.media_type == @foo and value.encoding == 'foobar'
137
+ end.returns(nil).once
138
+
139
+ other_request_method('PATCH', {'CONTENT_TYPE' => 'text/foo; charset=foobar', :input => 'foob'})
140
+ assert_equal STATUS_NO_CONTENT, last_response.status
141
+ end
142
+
143
+ def test_other_method_with_anonymous_resource_response
144
+ # PATCH used as an example here
145
+ app(:recognized_methods => [:get,:post,:put,:delete,:patch])
146
+
147
+ root.expects(:supports_patch?).returns(true)
148
+ root.expects(:accepts_method_with_media_type?).with {|m,a| m == :patch && a.is_a?(Doze::Entity) && a.media_type == @foo}.returns(true)
149
+ resource = mock_resource(nil)
150
+ resource.expects(:get).returns(mock_entity('bar', @bar))
151
+ root.expects(:patch).returns(resource).once
152
+
153
+ other_request_method('PATCH', {'CONTENT_TYPE' => 'text/foo; charset=foobar', :input => 'foob'})
154
+ assert_equal STATUS_OK, last_response.status
155
+ assert_equal 'bar', last_response.body
156
+ assert_equal 'text/bar', last_response.media_type
157
+ end
158
+
159
+ def test_other_method_with_resource_response
160
+ # PATCH used as an example here
161
+ app(:recognized_methods => [:get,:post,:put,:delete,:patch])
162
+
163
+ root.expects(:supports_patch?).returns(true)
164
+ root.expects(:accepts_method_with_media_type?).with {|m,a| m == :patch && a.is_a?(Doze::Entity) && a.media_type == @foo}.returns(true)
165
+ resource = mock_resource('/foo', 'bar')
166
+ root.expects(:patch).returns(resource).once
167
+
168
+ other_request_method('PATCH', {'CONTENT_TYPE' => 'text/foo; charset=foobar', :input => 'foob'})
169
+ assert_equal STATUS_CREATED, last_response.status
170
+ assert_response_header 'Location', 'http://example.org/foo'
171
+ assert_equal 'bar', last_response.body
172
+ end
173
+ end
@@ -0,0 +1,84 @@
1
+ require 'functional/base'
2
+
3
+ class PreconditionTest < Test::Unit::TestCase
4
+ include Doze::Utils
5
+ include Doze::TestCase
6
+
7
+ def setup
8
+ @last_modified = Time.now - 30
9
+ root.expects(:last_modified).returns(@last_modified).at_least_once
10
+ end
11
+
12
+ def test_if_modified_since
13
+ get('HTTP_IF_MODIFIED_SINCE' => (@last_modified-10).httpdate)
14
+ assert_equal STATUS_OK, last_response.status
15
+ get('HTTP_IF_MODIFIED_SINCE' => (@last_modified+10).httpdate)
16
+ assert_equal STATUS_NOT_MODIFIED, last_response.status
17
+ end
18
+
19
+ def test_if_unmodified_since
20
+ get('HTTP_IF_UNMODIFIED_SINCE' => (@last_modified+10).httpdate)
21
+ assert_equal STATUS_OK, last_response.status
22
+ get('HTTP_IF_UNMODIFIED_SINCE' => (@last_modified-10).httpdate)
23
+ assert_equal STATUS_PRECONDITION_FAILED, last_response.status
24
+ end
25
+
26
+ def test_status_for_non_get
27
+ root.expects(:supports_post?).returns(true).at_least_once
28
+ root.expects(:supports_put?).returns(true).at_least_once
29
+ root.expects(:supports_delete?).returns(true).at_least_once
30
+ root.expects(:accepts_method_with_media_type?).returns(true).at_least_once
31
+ root.expects(:post).never
32
+ root.expects(:put).never
33
+ root.expects(:delete).never
34
+
35
+ assert_equal STATUS_PRECONDITION_FAILED, post('HTTP_IF_UNMODIFIED_SINCE' => (@last_modified-10).httpdate).status
36
+ assert_equal STATUS_PRECONDITION_FAILED, put('HTTP_IF_UNMODIFIED_SINCE' => (@last_modified-10).httpdate).status
37
+ assert_equal STATUS_PRECONDITION_FAILED, delete('HTTP_IF_UNMODIFIED_SINCE' => (@last_modified-10).httpdate).status
38
+ assert_equal STATUS_PRECONDITION_FAILED, post('HTTP_IF_MODIFIED_SINCE' => (@last_modified+10).httpdate).status
39
+ assert_equal STATUS_PRECONDITION_FAILED, put('HTTP_IF_MODIFIED_SINCE' => (@last_modified+10).httpdate).status
40
+ assert_equal STATUS_PRECONDITION_FAILED, delete('HTTP_IF_MODIFIED_SINCE' => (@last_modified+10).httpdate).status
41
+ end
42
+ end
43
+
44
+ class EntityPreconditionTest < Test::Unit::TestCase
45
+ include Doze::Utils
46
+ include Doze::TestCase
47
+
48
+ def setup
49
+ @last_modified = Time.now - 30
50
+ root.expects(:last_modified).returns(@last_modified).at_least_once
51
+
52
+ @entity = mock_entity('foo')
53
+ @etag = '123abc'
54
+ @entity.expects(:etag).returns(@etag).at_least_once
55
+ root.expects(:get).returns(@entity).at_least_once
56
+ end
57
+
58
+ def test_if_match
59
+ get('HTTP_IF_MATCH' => quote(@etag))
60
+ assert_equal STATUS_OK, last_response.status
61
+ get('HTTP_IF_MATCH' => quote("not-the-etag"))
62
+ assert_equal STATUS_PRECONDITION_FAILED, last_response.status
63
+ end
64
+
65
+ def test_if_none_match
66
+ get('HTTP_IF_NONE_MATCH' => quote(@etag))
67
+ assert_equal STATUS_NOT_MODIFIED, last_response.status
68
+ get('HTTP_IF_NONE_MATCH' => quote("not-the-etag"))
69
+ assert_equal STATUS_OK, last_response.status
70
+ end
71
+
72
+ def test_non_get_method_not_called_when_precondition_fails
73
+ root.expects(:supports_post?).returns(true).once
74
+ root.expects(:supports_put?).returns(true).once
75
+ root.expects(:supports_delete?).returns(true).once
76
+ root.expects(:accepts_method_with_media_type?).returns(true).at_least_once
77
+ root.expects(:post).never
78
+ root.expects(:put).never
79
+ root.expects(:delete).never
80
+ assert_equal STATUS_PRECONDITION_FAILED, post('HTTP_IF_MATCH' => quote('not-the-etag')).status
81
+ assert_equal STATUS_PRECONDITION_FAILED, put('HTTP_IF_MATCH' => quote('not-the-etag')).status
82
+ assert_equal STATUS_PRECONDITION_FAILED, delete('HTTP_IF_MATCH' => quote('not-the-etag')).status
83
+ end
84
+ end
@@ -0,0 +1,69 @@
1
+ require "test/unit"
2
+ require 'mocha/setup'
3
+ require 'doze/request'
4
+
5
+ class RawPathInfoTest < Test::Unit::TestCase
6
+ include Doze::Utils
7
+ include Doze::TestCase
8
+
9
+ def mock_request(path, host="localhost", scheme="http", port=-1, context="")
10
+
11
+ port_str = if port == -1 then "" ; else ":#{port}" ; end
12
+
13
+ path_parts = ["/", context, path].join("")
14
+ if path_parts[0...2] == "//" then path_parts = path_parts[1..-1] end
15
+
16
+ url = stub()
17
+ url.stubs(:toString).returns("#{scheme}://#{host}#{port_str}#{path_parts}")
18
+
19
+ s_request = stub("")
20
+ s_request.stubs(:getRequestURL).returns(url)
21
+ s_request.stubs(:getContextPath).returns(context)
22
+
23
+ app = stub()
24
+ env = stub()
25
+ env.stubs(:[]).with('java.servlet_request').returns(s_request)
26
+ Doze::Request.new(app, env)
27
+ end
28
+
29
+ def test_bland_path
30
+ dr = mock_request("/path/is/good")
31
+ assert_equal dr.raw_path_info, "/path/is/good"
32
+ end
33
+
34
+ def test_path_with_host_and_port
35
+ dr = mock_request("/how/do", "x23.awesome-server.playlouder---com.com", 5432)
36
+ assert_equal dr.raw_path_info, "/how/do"
37
+ end
38
+
39
+ def test_path_with_naughty_chars
40
+ dr = mock_request("/how/do%20", "awesome-server", 5432)
41
+ assert_equal dr.raw_path_info, "/how/do%20"
42
+ end
43
+
44
+ def test_context_is_chomped
45
+ ['bob', 'bob-y', 'the%20bobster'].each do |context|
46
+ dr = mock_request('/path-s/of/life', 'www.awesome.com', 'https', 8080, context)
47
+ assert_equal dr.raw_path_info, "/path-s/of/life"
48
+ end
49
+ end
50
+
51
+ def test_searchpart_excluded
52
+ {
53
+ '/path' => '/path', '?false=true' => '/', '/path?you=suck&bob&nick=awesome' => '/path'
54
+ }.each do |raw, exp_raw_path_info|
55
+ dr = mock_request(raw, 'some.host-rocks', 'http', 1234)
56
+ assert_equal dr.raw_path_info, exp_raw_path_info
57
+ end
58
+ end
59
+
60
+ def test_servlet_is_missing
61
+ app = stub()
62
+ env = stub()
63
+ env.stubs(:[]).with('java.servlet_request').returns(nil)
64
+ dr = Doze::Request.new(app, env)
65
+ dr.expects(:path_info).twice.returns("/omg/im/a/path")
66
+ assert_equal dr.raw_path_info, dr.path_info
67
+ end
68
+
69
+ end
@@ -0,0 +1,14 @@
1
+ require 'functional/base'
2
+
3
+ class ResourceRepresentationTest < Test::Unit::TestCase
4
+ include Doze::Utils
5
+ include Doze::TestCase
6
+
7
+ def test_get_with_resource_representation
8
+ resource = mock_resource('/foo/bar')
9
+ root.expects(:get).returns(resource)
10
+ get
11
+ assert_equal STATUS_SEE_OTHER, last_response.status
12
+ assert_response_header 'Location', 'http://example.org/foo/bar'
13
+ end
14
+ end
@@ -0,0 +1,196 @@
1
+ require 'functional/base'
2
+
3
+ class RouterInterfaceTest < Test::Unit::TestCase
4
+ include Doze::Utils
5
+ include Doze::TestCase
6
+
7
+ # tests how the basic Router interface is exposed by the framework
8
+
9
+ def test_router_no_match
10
+ root_router.expects(:perform_routing).with('/foo', nil, '').returns(nil).once
11
+ assert_equal STATUS_NOT_FOUND, get('/foo').status
12
+ end
13
+
14
+ def test_router_match_resource_with_no_trailing_path
15
+ resource = mock_resource('/foo')
16
+ root_router.expects(:perform_routing).with('/foo', nil, '').returns([resource, '/foo', nil]).once
17
+ resource.expects(:get).returns(mock_entity('foo', 'text/html')).once
18
+ assert_equal STATUS_OK, get('/foo').status
19
+ end
20
+
21
+ def test_router_match_resource_but_with_trailing
22
+ # here we route to a resource, but there is some trailing path which can't be routed any further
23
+ resource = mock_resource('/foo')
24
+ root_router.expects(:perform_routing).with('/foo/bar', nil, '').returns([resource, '/foo', '/bar']).once
25
+ resource.expects(:get).never
26
+ assert_equal STATUS_NOT_FOUND, get('/foo/bar').status
27
+ end
28
+
29
+ def test_router_match_router_with_trailing_then_resource
30
+ # here we route to another router which is matched but with some trailing path that's passed on to it.
31
+
32
+ second_router = mock_router
33
+ resource = mock_resource('/foo/bar')
34
+
35
+ root_router.expects(:perform_routing).with('/foo/bar', nil, '').returns([second_router, '/foo', '/bar']).once
36
+ second_router.expects(:perform_routing).with('/bar', nil, '/foo').returns([resource, '/foo/bar', nil]).once
37
+
38
+ resource.expects(:get).returns(mock_entity('foo', 'text/html')).once
39
+ assert_equal STATUS_OK, get('/foo/bar').status
40
+ end
41
+
42
+ def test_router_match_router_resource_with_trailing_then_resource
43
+ # as above but this time our second router is also a resource - check that it does actually act as a router
44
+
45
+ second_router = mock_router(Doze::MockResource)
46
+ resource = mock_resource('/foo/bar')
47
+
48
+ root_router.expects(:perform_routing).with('/foo/bar', nil, '').returns([second_router, '/foo', '/bar']).once
49
+ second_router.expects(:perform_routing).with('/bar', nil, '/foo').returns([resource, '/foo/bar', nil]).once
50
+
51
+ second_router.expects(:get).never
52
+ resource.expects(:get).returns(mock_entity('foo', 'text/html')).once
53
+ assert_equal STATUS_OK, get('/foo/bar').status
54
+ end
55
+
56
+ def test_router_match_router_resource_with_no_trailing
57
+ resource = mock_router(Doze::MockResource)
58
+
59
+ root_router.expects(:perform_routing).with('/foo', nil, '').returns([resource, '/foo', nil]).once
60
+ resource.expects(:perform_routing).never
61
+ resource.expects(:get).returns(mock_entity('foo', 'text/html')).once
62
+
63
+ assert_equal STATUS_OK, get('/foo').status
64
+ end
65
+
66
+ def test_router_gets_passed_user
67
+ root_router.expects(:perform_routing).with('/foo', 'Mack', '').returns(nil).once
68
+ assert_equal STATUS_NOT_FOUND, get('/foo', 'REMOTE_USER' => 'Mack').status
69
+ end
70
+ end
71
+
72
+
73
+ class RouterDefaultImplementationTest < Test::Unit::TestCase
74
+ include Doze::Utils
75
+ include Doze::TestCase
76
+
77
+ # tests the default implementation of Router based on routes defined in class method helpers
78
+
79
+ def test_route_fixed_uri_to_resource_class
80
+ resource = mock_resource('/foo')
81
+ resource.expects(:get).returns(mock_entity('foo', 'text/html')).once
82
+ klass = Class.new
83
+ klass.expects(:new).with("/foo").returns(resource)
84
+
85
+ root_router do
86
+ route '/foo', :to => klass
87
+ end
88
+
89
+ assert_equal STATUS_OK, get('/foo').status
90
+ end
91
+
92
+ def test_route_fixed_uri_to_resource_instance
93
+ resource = mock_resource('/foo')
94
+ resource.expects(:get).returns(mock_entity('foo', 'text/html')).once
95
+
96
+ root_router do
97
+ route '/foo', :to => resource
98
+ end
99
+
100
+ assert_equal STATUS_OK, get('/foo').status
101
+ end
102
+
103
+ def test_route_with_params_to_block_returning_resource
104
+ root_router do
105
+ route('/foo/{x}/{y}') do |router, uri, params|
106
+ Doze::MockResource.new(uri, [uri, params].inspect)
107
+ end
108
+ end
109
+
110
+ get('/foo/abc/123')
111
+
112
+ assert_equal STATUS_OK, last_response.status
113
+ assert_equal(['/foo/abc/123', {:x => 'abc', :y => '123'}].inspect, last_response.body)
114
+ end
115
+
116
+ # More complex two-level routing scenario with params at both levels
117
+ def test_route_with_params_to_block_returning_router_routing_to_resource_with_more_params
118
+ root_router do
119
+ route('/foo/{x}') do |router1, uri1, params1|
120
+
121
+ Class.new do
122
+ include Doze::Router
123
+ route("/{y}") do |router2, uri2, params2|
124
+ Doze::MockResource.new(uri2, [uri1, params1, uri2, params2].inspect)
125
+ end
126
+ end.new
127
+ end
128
+ end
129
+
130
+ get('/foo/abc/123')
131
+
132
+ assert_equal STATUS_OK, last_response.status
133
+ # bit of a messy way to test it but this was getting fiddly to mock nicely
134
+ # expecting [uri1, params1, uri2, params2].inspect from above
135
+ assert_equal(['/foo/abc', {:x => 'abc'}, '/foo/abc/123', {:y => '123'}].inspect, last_response.body)
136
+ end
137
+
138
+ def test_route_with_special_param_regexp
139
+ root_router do
140
+ route('/foo/{x}', :regexps => {:x => /\d+/}) do |router, uri, params|
141
+ Doze::MockResource.new(uri, params[:x])
142
+ end
143
+ end
144
+
145
+ assert_equal STATUS_NOT_FOUND, get('/foo/abc').status
146
+ assert_equal STATUS_OK, get('/foo/123').status
147
+ assert_equal "123", last_response.body
148
+ end
149
+
150
+ def test_route_with_uri_template_passed_directly
151
+ root_router do
152
+ route(Doze::URITemplate.compile('/foo/{x}', :x => /\d+/)) do |router, uri, params|
153
+ Doze::MockResource.new(uri, params[:x])
154
+ end
155
+ end
156
+
157
+ assert_equal STATUS_NOT_FOUND, get('/foo/abc').status
158
+ assert_equal STATUS_OK, get('/foo/123').status
159
+ assert_equal "123", last_response.body
160
+ end
161
+
162
+ def test_user_specific_route
163
+ root_router do
164
+ route('/foo/{x}/{y}', :session_specific => true) do |router, uri, params, user|
165
+ Doze::MockResource.new(uri, [uri, params, user].inspect)
166
+ end
167
+ end
168
+
169
+ get('/foo/abc/123', 'REMOTE_USER' => 'Mo')
170
+
171
+ assert_equal STATUS_OK, last_response.status
172
+ assert_equal(['/foo/abc/123', {:x => 'abc', :y => '123'}, 'Mo'].inspect, last_response.body)
173
+ end
174
+
175
+ def test_propagate_static_routes
176
+ klass = Class.new
177
+ klass.send(:include, Doze::Router)
178
+ router = mock_router
179
+ router2 = mock_router
180
+
181
+ root_router do
182
+ route "/bar", :uniquely_to => klass
183
+ route "/baz", :uniquely_to => router
184
+ route "/baz", :to => router2
185
+ end
186
+
187
+ root_router.propagate_static_routes("/foo")
188
+
189
+ assert_equal "/foo", root_router.router_uri_prefix
190
+
191
+ assert_equal "/foo/bar", klass.router_uri_prefix
192
+ assert_equal "/foo/bar", klass.new.router_uri_prefix
193
+ assert_equal "/foo/baz", router.router_uri_prefix
194
+ assert_equal nil, router2.router_uri_prefix
195
+ end
196
+ end