waves 0.8.2 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (166) hide show
  1. data/bin/waves +4 -3
  2. data/doc/VERSION +1 -1
  3. data/lib/waves.rb +52 -40
  4. data/lib/{caches → waves/caches}/file.rb +3 -1
  5. data/lib/waves/caches/memcached.rb +56 -0
  6. data/lib/{caches → waves/caches}/simple.rb +6 -7
  7. data/lib/{caches → waves/caches}/synchronized.rb +15 -1
  8. data/lib/{commands → waves/commands}/console.rb +4 -4
  9. data/lib/{commands → waves/commands}/generate.rb +6 -5
  10. data/lib/{commands → waves/commands}/help.rb +0 -0
  11. data/lib/{commands → waves/commands}/server.rb +1 -1
  12. data/lib/{dispatchers → waves/dispatchers}/base.rb +17 -31
  13. data/lib/waves/dispatchers/default.rb +19 -0
  14. data/lib/{ext → waves/ext}/float.rb +0 -0
  15. data/lib/{ext → waves/ext}/hash.rb +0 -0
  16. data/lib/{ext → waves/ext}/integer.rb +16 -1
  17. data/lib/{ext → waves/ext}/kernel.rb +3 -7
  18. data/lib/{ext → waves/ext}/module.rb +3 -3
  19. data/lib/{ext → waves/ext}/object.rb +2 -0
  20. data/lib/waves/ext/string.rb +73 -0
  21. data/lib/{ext → waves/ext}/symbol.rb +0 -1
  22. data/lib/{ext → waves/ext}/tempfile.rb +0 -0
  23. data/lib/waves/ext/time.rb +5 -0
  24. data/lib/{foundations → waves/foundations}/classic.rb +9 -21
  25. data/lib/{foundations → waves/foundations}/compact.rb +15 -20
  26. data/lib/waves/foundations/rest.rb +311 -0
  27. data/lib/waves/helpers/basic.rb +13 -0
  28. data/lib/{helpers → waves/helpers}/doc_type.rb +3 -0
  29. data/lib/waves/helpers/form.rb +94 -0
  30. data/lib/waves/helpers/formatting.rb +14 -0
  31. data/lib/waves/layers/mvc.rb +65 -0
  32. data/lib/{layers → waves/layers}/mvc/controllers.rb +0 -0
  33. data/lib/{layers → waves/layers}/mvc/extensions.rb +23 -11
  34. data/lib/{layers → waves/layers}/orm/migration.rb +0 -0
  35. data/lib/{layers → waves/layers}/orm/providers/active_record.rb +2 -5
  36. data/lib/{layers → waves/layers}/orm/providers/active_record/migrations/empty.rb.erb +0 -0
  37. data/lib/{layers → waves/layers}/orm/providers/active_record/tasks/generate.rb +1 -1
  38. data/lib/{layers → waves/layers}/orm/providers/active_record/tasks/schema.rb +1 -1
  39. data/lib/{layers → waves/layers}/orm/providers/data_mapper.rb +0 -0
  40. data/lib/{layers → waves/layers}/orm/providers/filebase.rb +0 -0
  41. data/lib/{layers → waves/layers}/orm/providers/sequel.rb +28 -29
  42. data/lib/{layers → waves/layers}/orm/providers/sequel/migrations/empty.rb.erb +0 -0
  43. data/lib/{layers → waves/layers}/orm/providers/sequel/tasks/generate.rb +1 -1
  44. data/lib/{layers → waves/layers}/orm/providers/sequel/tasks/schema.rb +2 -0
  45. data/lib/waves/layers/rack/rack_cache.rb +32 -0
  46. data/lib/waves/layers/renderers/erubis.rb +52 -0
  47. data/lib/waves/layers/renderers/haml.rb +67 -0
  48. data/lib/waves/layers/renderers/markaby.rb +41 -0
  49. data/lib/waves/layers/text/inflect/english.rb +42 -0
  50. data/lib/waves/matchers/accept.rb +47 -0
  51. data/lib/waves/matchers/ext.rb +27 -0
  52. data/lib/waves/matchers/path.rb +72 -0
  53. data/lib/waves/matchers/query.rb +43 -0
  54. data/lib/waves/matchers/request.rb +86 -0
  55. data/lib/waves/matchers/requested.rb +31 -0
  56. data/lib/{matchers → waves/matchers}/resource.rb +8 -1
  57. data/lib/waves/matchers/traits.rb +30 -0
  58. data/lib/waves/matchers/uri.rb +69 -0
  59. data/lib/waves/media/mime_types.rb +542 -0
  60. data/lib/waves/renderers/mixin.rb +9 -0
  61. data/lib/waves/request/accept.rb +92 -0
  62. data/lib/{runtime → waves/request}/request.rb +77 -61
  63. data/lib/waves/resources/file_mixin.rb +11 -0
  64. data/lib/{resources → waves/resources}/mixin.rb +42 -44
  65. data/lib/waves/resources/paths.rb +132 -0
  66. data/lib/waves/response/client_errors.rb +10 -0
  67. data/lib/waves/response/packaged.rb +19 -0
  68. data/lib/waves/response/redirects.rb +35 -0
  69. data/lib/{runtime → waves/response}/response.rb +29 -11
  70. data/lib/{runtime → waves/response}/response_mixin.rb +30 -17
  71. data/lib/waves/runtime/applications.rb +18 -0
  72. data/lib/{runtime → waves/runtime}/configuration.rb +31 -25
  73. data/lib/waves/runtime/console.rb +24 -0
  74. data/lib/{runtime → waves/runtime}/logger.rb +3 -3
  75. data/lib/{runtime → waves/runtime}/mocks.rb +2 -2
  76. data/lib/waves/runtime/rackup.rb +37 -0
  77. data/lib/waves/runtime/runtime.rb +48 -0
  78. data/lib/waves/runtime/server.rb +33 -0
  79. data/lib/{servers → waves/servers}/base.rb +0 -0
  80. data/lib/{servers → waves/servers}/mongrel.rb +0 -0
  81. data/lib/{servers → waves/servers}/webrick.rb +0 -0
  82. data/lib/{tasks → waves/tasks}/gem.rb +0 -0
  83. data/lib/{tasks → waves/tasks}/generate.rb +0 -0
  84. data/lib/waves/views/cassy.rb +173 -0
  85. data/lib/{views → waves/views}/errors.rb +8 -7
  86. data/lib/waves/views/mixin.rb +23 -0
  87. data/lib/waves/views/templated.rb +40 -0
  88. data/samples/basic/basic_startup.rb +70 -0
  89. data/samples/basic/config.ru +9 -0
  90. data/samples/blog/configurations/development.rb +17 -16
  91. data/samples/blog/configurations/production.rb +0 -11
  92. data/samples/blog/resources/entry.rb +3 -3
  93. data/samples/blog/resources/map.rb +10 -3
  94. data/samples/blog/startup.rb +4 -3
  95. data/templates/classic/Rakefile +28 -29
  96. data/templates/classic/configurations/default.rb.erb +8 -3
  97. data/templates/classic/configurations/development.rb.erb +1 -20
  98. data/templates/classic/configurations/production.rb.erb +2 -16
  99. data/templates/classic/public/images/favicon.ico +0 -0
  100. data/templates/classic/resources/server.rb.erb +9 -0
  101. data/templates/classic/startup.rb.erb +3 -3
  102. data/templates/classic/views/css.rb.erb +14 -0
  103. data/templates/classic/views/default.rb.erb +17 -0
  104. data/templates/classic/views/errors.rb.erb +10 -0
  105. data/templates/classic/views/pages.rb.erb +14 -0
  106. data/templates/compact/startup.rb.erb +8 -3
  107. data/test/ext/object.rb +55 -0
  108. data/test/ext/shortcuts.rb +73 -0
  109. data/test/helpers.rb +17 -0
  110. data/test/match/accept.rb +78 -0
  111. data/test/match/ext.rb +156 -0
  112. data/test/match/methods.rb +22 -0
  113. data/test/match/params.rb +33 -0
  114. data/test/match/path.rb +106 -0
  115. data/test/match/query.rb +60 -0
  116. data/test/match/request.rb +91 -0
  117. data/test/match/requested.rb +149 -0
  118. data/test/match/uri.rb +136 -0
  119. data/test/process/request.rb +75 -0
  120. data/test/process/resource.rb +53 -0
  121. data/test/resources/path.rb +166 -0
  122. data/test/runtime/configurations.rb +19 -0
  123. data/test/runtime/request.rb +63 -0
  124. data/test/runtime/response.rb +85 -0
  125. data/test/views/views.rb +40 -0
  126. metadata +243 -157
  127. data/lib/caches/memcached.rb +0 -40
  128. data/lib/dispatchers/default.rb +0 -25
  129. data/lib/ext/string.rb +0 -20
  130. data/lib/helpers/basic.rb +0 -11
  131. data/lib/helpers/extended.rb +0 -21
  132. data/lib/helpers/form.rb +0 -42
  133. data/lib/helpers/formatting.rb +0 -30
  134. data/lib/helpers/layouts.rb +0 -37
  135. data/lib/helpers/model.rb +0 -37
  136. data/lib/helpers/view.rb +0 -22
  137. data/lib/layers/inflect/english.rb +0 -67
  138. data/lib/layers/mvc.rb +0 -54
  139. data/lib/layers/renderers/erubis.rb +0 -60
  140. data/lib/layers/renderers/haml.rb +0 -47
  141. data/lib/layers/renderers/markaby.rb +0 -29
  142. data/lib/matchers/accept.rb +0 -21
  143. data/lib/matchers/base.rb +0 -30
  144. data/lib/matchers/content_type.rb +0 -17
  145. data/lib/matchers/path.rb +0 -67
  146. data/lib/matchers/query.rb +0 -21
  147. data/lib/matchers/request.rb +0 -27
  148. data/lib/matchers/traits.rb +0 -19
  149. data/lib/matchers/uri.rb +0 -20
  150. data/lib/renderers/mixin.rb +0 -36
  151. data/lib/resources/paths.rb +0 -34
  152. data/lib/runtime/console.rb +0 -23
  153. data/lib/runtime/mime_types.rb +0 -536
  154. data/lib/runtime/monitor.rb +0 -32
  155. data/lib/runtime/runtime.rb +0 -67
  156. data/lib/runtime/server.rb +0 -20
  157. data/lib/runtime/session.rb +0 -27
  158. data/lib/runtime/worker.rb +0 -86
  159. data/lib/views/mixin.rb +0 -62
  160. data/samples/blog/blog.db +0 -0
  161. data/samples/blog/log/waves.production +0 -3
  162. data/templates/classic/resources/map.rb.erb +0 -8
  163. data/templates/classic/templates/errors/not_found_404.mab +0 -7
  164. data/templates/classic/templates/errors/server_error_500.mab +0 -7
  165. data/templates/classic/templates/layouts/default.mab +0 -14
  166. data/templates/classic/tmp/sessions/.gitignore +0 -0
data/test/helpers.rb ADDED
@@ -0,0 +1,17 @@
1
+ require 'rubygems'; %w{ bacon facon }.each { |dep| require dep }
2
+
3
+ # Framework lib goes to the front of the loadpath
4
+ $:.unshift('lib')
5
+ require 'waves'
6
+ require 'waves/runtime/mocks'
7
+
8
+ Waves::Runtime.instance = Waves::Runtime.new
9
+
10
+ Bacon::Context.module_eval do
11
+ include Waves::Mocks
12
+ alias_method :specification, :describe
13
+ alias_method :feature, :it
14
+ end
15
+
16
+ Bacon.extend Bacon::TestUnitOutput
17
+ Bacon.summary_on_exit
@@ -0,0 +1,78 @@
1
+ require "#{File.dirname(__FILE__)}/../../test/helpers.rb"
2
+ require 'test/helpers.rb'
3
+
4
+ require 'waves/foundations/compact'
5
+ require "waves/runtime/mime_types"
6
+
7
+ describe "Accept header matching" do
8
+
9
+ Accept = Waves::Accept
10
+
11
+ before do
12
+ Test = Module.new { include Waves::Foundations::Compact }
13
+ Waves << Test
14
+ end
15
+
16
+ after do
17
+ Waves.applications.clear
18
+ Object.instance_eval { remove_const(:Test) if const_defined?(:Test) }
19
+ end
20
+
21
+ feature "matches correct accept header" do
22
+
23
+ Test::Resources::Map.on( :get, [ "foo" ], :accept => "text/javascript" ) { }
24
+
25
+ resp = get "/foo"
26
+ resp.status.should == 404
27
+
28
+ resp = get "/foo", "HTTP_ACCEPT" => "text/javascript"
29
+ resp.status.should == 200
30
+
31
+ end
32
+
33
+ feature 'Accept header is being parsed parses in the right way.' do
34
+ accept_header = "text/*, text/html ;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5"
35
+ terms = Accept.parse(accept_header)
36
+ terms.size.should == 6
37
+ terms.map{|term,params| term }.uniq[0] == %w( text html )
38
+
39
+ accept_header = "text/html,application/xhtml+xml;q=0.95,application/xml;q=0.9,*/*;q=0.8"
40
+ terms = Accept.parse(accept_header)
41
+ terms.size.should == 4
42
+ terms[0][0].should == %w( text html )
43
+ terms[1][0].should == %w( application xhtml+xml )
44
+ terms[2][0].should == %w( application xml )
45
+ terms[3][0].should == [ true, true ]
46
+
47
+ accept_header = "text/css,*/*;q=0.1"
48
+ terms = Accept.parse(accept_header)
49
+ terms.size.should == 2
50
+ terms[0][0].should == %w( text css )
51
+ terms[1][0].should == [ true, true ]
52
+
53
+ accept_header = "image/png,image/*;q=0.8,*/*;q=0.5"
54
+ terms = Accept.parse(accept_header)
55
+ terms.size.should == 3
56
+ terms[0][0].should == %w( image png )
57
+ terms[1][0].should == [ 'image', true ]
58
+ terms[2][0].should == [ true, true ]
59
+ end
60
+
61
+ feature 'Should return all the terms in a Accept-Charset header' do
62
+ accept_charset_header = "ISO-8859-1,utf-8;q=0.7,*;q=0.7"
63
+ terms = Accept.parse( accept_charset_header )
64
+ terms.size.should == 3
65
+ terms[0][0].should == [ 'ISO-8859-1' ]
66
+ terms[1][0].should == [ 'utf-8' ]
67
+ terms[2][0].should == [ true ]
68
+ end
69
+
70
+ feature 'Should return all the terms in a Accept-Language header' do
71
+ accept_language_header = "en-us,en;q=0.5"
72
+ terms = Accept.parse(accept_language_header)
73
+ terms.size.should == 2
74
+ terms[0][0][0] == 'en-us'
75
+ terms[1][0][0] == 'en'
76
+ end
77
+
78
+ end
data/test/match/ext.rb ADDED
@@ -0,0 +1,156 @@
1
+ require 'test/helpers.rb'
2
+
3
+ require 'waves/foundations/compact'
4
+ require "waves/runtime/mime_types"
5
+ require "waves/matchers/ext"
6
+
7
+ describe "File extension matching" do
8
+ before do
9
+ Test = Module.new { include Waves::Foundations::Compact }
10
+ Waves << Test
11
+ end
12
+
13
+ after do
14
+ Waves.applications.clear
15
+ Object.instance_eval { remove_const(:Test) if const_defined?(:Test) }
16
+ end
17
+
18
+ feature "returns falseish if single file extension Symbol is not matched" do
19
+ m = Waves::Matchers::Ext.new :js
20
+
21
+ request = Waves::Request.new env("http://example.com/moo",
22
+ :method => "GET",
23
+ "HTTP_ACCEPT" => "text/javascript")
24
+
25
+ (!!m.call(request)).should == false
26
+
27
+ request = Waves::Request.new env("http://example.com/moo.sj",
28
+ :method => "GET",
29
+ "HTTP_ACCEPT" => "text/javascript")
30
+
31
+ (!!m.call(request)).should == false
32
+ end
33
+
34
+ feature "returns falseish if none of Array of Symbol extensions match" do
35
+ m = Waves::Matchers::Ext.new [:js, :html]
36
+
37
+ request = Waves::Request.new env("http://example.com/moo",
38
+ :method => "GET",
39
+ "HTTP_ACCEPT" => "text/javascript")
40
+
41
+ (!!m.call(request)).should == false
42
+
43
+ request = Waves::Request.new env("http://example.com/moo.sj",
44
+ :method => "GET",
45
+ "HTTP_ACCEPT" => "text/javascript")
46
+
47
+ (!!m.call(request)).should == false
48
+ end
49
+
50
+ feature "returns trueish if single file extension Symbol does match" do
51
+ m = Waves::Matchers::Ext.new :js
52
+
53
+ request = Waves::Request.new env("http://example.com/moo.js",
54
+ :method => "GET",
55
+ "HTTP_ACCEPT" => "text/javascript")
56
+
57
+ m.call(request).should == true
58
+ end
59
+
60
+ feature "returns trueish if any in Array of Symbol extensions match" do
61
+ m = Waves::Matchers::Ext.new [:js, :html]
62
+
63
+ request = Waves::Request.new env("http://example.com/moo.js",
64
+ :method => "GET",
65
+ "HTTP_ACCEPT" => "text/javascript")
66
+
67
+ (!!m.call(request)).should == true
68
+
69
+ request = Waves::Request.new env("http://example.com/moo.html",
70
+ :method => "GET",
71
+ "HTTP_ACCEPT" => "text/javascript")
72
+
73
+ (!!m.call(request)).should == true
74
+ end
75
+
76
+ feature "fails to match a Symbol extension with a leading dot included" do
77
+ m = Waves::Matchers::Ext.new :".js"
78
+
79
+ request = Waves::Request.new env("http://example.com/moo.js",
80
+ :method => "GET",
81
+ "HTTP_ACCEPT" => "text/javascript")
82
+
83
+ (!!m.call(request)).should == false
84
+ end
85
+
86
+ feature "matches absence of extension, returning true, if Array contains false" do
87
+ m = Waves::Matchers::Ext.new [ :js, :html, false ]
88
+
89
+ request = Waves::Request.new env("http://example.com/moo",
90
+ :method => "GET",
91
+ "HTTP_ACCEPT" => "text/javascript")
92
+
93
+ (!!m.call(request)).should == true
94
+ end
95
+
96
+ feature "fails to match if extension provided but no extension specified with empty String" do
97
+ m = Waves::Matchers::Ext.new( false )
98
+
99
+ request = Waves::Request.new env("http://example.com/moo.js",
100
+ :method => "GET",
101
+ "HTTP_ACCEPT" => "text/javascript")
102
+
103
+ (!!m.call(request)).should == false
104
+ end
105
+
106
+ end
107
+
108
+ describe "File extension matching in conjunction with Accept matching" do
109
+ before do
110
+ Test = Module.new { include Waves::Foundations::Compact }
111
+ Waves << Test
112
+ end
113
+
114
+ after do
115
+ Waves.applications.clear
116
+ Object.instance_eval { remove_const(:Test) if const_defined?(:Test) }
117
+ end
118
+
119
+ feature "fails if the Accept match fails" do
120
+ m = Waves::Matchers::Request.new :requested => ["text/html"],
121
+ :ext => :js
122
+
123
+ request = Waves::Request.new env("http://example.com/moo.js",
124
+ :method => "GET",
125
+ "HTTP_ACCEPT" => "text/javascript")
126
+
127
+ (!!m.call(request)).should == false
128
+ end
129
+
130
+ feature "matches if the extension is Accept-matched with or without Accept header" do
131
+ m = Waves::Matchers::Request.new :requested => ["text/javascript"],
132
+ :ext => :js
133
+
134
+ request = Waves::Request.new env("http://example.com/moo.js",
135
+ :method => "GET",
136
+ "HTTP_ACCEPT" => "text/javascript")
137
+
138
+ (!!m.call(request)).should == true
139
+
140
+ request = Waves::Request.new env("http://example.com/moo.js", :method => "GET")
141
+
142
+ (!!m.call(request)).should == true
143
+ end
144
+
145
+ feature "causes Accept match to fail if there is a file extension, and absence is specified" do
146
+ m = Waves::Matchers::Request.new :requested => ["text/javascript"],
147
+ :ext => false
148
+
149
+ request = Waves::Request.new env("http://example.com/moo.js",
150
+ :method => "GET",
151
+ "HTTP_ACCEPT" => "text/javascript")
152
+ (!!m.call(request)).should == false
153
+ end
154
+
155
+ end
156
+
@@ -0,0 +1,22 @@
1
+ require "#{File.dirname(__FILE__)}/../../test/helpers.rb"
2
+ require 'waves/foundations/compact'
3
+
4
+ describe "Matching Request Methods" do
5
+
6
+ before do
7
+ Test = Module.new { include Waves::Foundations::Compact }
8
+ Test::Resources::Map.module_eval {
9
+ %w( get put post delete head ).each { |m| on( m ) { m } } }
10
+ Waves << Test
11
+ end
12
+
13
+ after do
14
+ Waves.applications.clear
15
+ Object.instance_eval { remove_const(:Test) if const_defined?(:Test) }
16
+ end
17
+
18
+ %w( get put post delete head ).each do |m|
19
+ feature( "Match the '#{m}' method" ) { send( m, '/' ).body.should == m }
20
+ end
21
+
22
+ end
@@ -0,0 +1,33 @@
1
+ require "#{File.dirname(__FILE__)}/../../test/helpers.rb"
2
+ require 'waves/foundations/compact'
3
+
4
+ describe "A resource that has matched a request" do
5
+
6
+ before do
7
+ Test = Module.new { include Waves::Foundations::Compact }
8
+ Waves << Test
9
+
10
+ @request = Waves::Request.new( env('http://localhost/baz?bar=7', :method => 'GET', "HTTP_ACCEPT" => "text/html" ) )
11
+ Test::Resources::Map.on(:get, [:foo], :accept => "text/html") { }
12
+ @resource = Test::Resources::Map.new( @request )
13
+ @resource.get
14
+ end
15
+
16
+ after do
17
+ Waves.applications.clear
18
+ Object.instance_eval { remove_const(:Test) if const_defined?(:Test) }
19
+ end
20
+
21
+ it "makes parameters captured from the path available as #captured" do
22
+ @resource.captured.to_h.should == { 'foo' => 'baz' }
23
+ end
24
+
25
+ it "makes http query parameters available as #query" do
26
+ @resource.query.to_h.should == { 'bar' => '7' }
27
+ end
28
+
29
+ it "provides access to all derived parameters using #params" do
30
+ @resource.params.to_h.should == { 'foo' => 'baz', 'bar' => '7' }
31
+ end
32
+
33
+ end
@@ -0,0 +1,106 @@
1
+ require "#{File.dirname(__FILE__)}/../../test/helpers.rb"
2
+ require 'waves/foundations/compact'
3
+
4
+ describe "Matching Request URIs" do
5
+
6
+ before do
7
+ Test = Module.new { include Waves::Foundations::Compact }
8
+ Waves << Test
9
+ end
10
+
11
+ after do
12
+ Waves.applications.clear
13
+ Object.instance_eval { remove_const(:Test) if const_defined?(:Test) }
14
+ end
15
+
16
+ feature "By default, we match an arbitrary path." do
17
+ Test::Resources::Map.on( :get ) {}
18
+ get("/foobar").status.should == 200
19
+ get("/foo/bar").status.should == 200
20
+ end
21
+
22
+ feature "A path of true matches an arbitrary path." do
23
+ Test::Resources::Map.on( :get, true ) { request.path }
24
+ get("/foobar").body.should == '/foobar'
25
+ get("/foo/bar").body.should == '/foo/bar'
26
+ end
27
+
28
+ feature "An empty path matches root." do
29
+ Test::Resources::Map.on( :get, [] ) { request.path }
30
+ get("/").body.should == '/'
31
+ end
32
+
33
+ feature "A string path component matches that string." do
34
+ Test::Resources::Map.on( :get, [ 'foo' ] ) { request.path }
35
+ get("/foo").body.should == '/foo'
36
+ get("/bar").status.should == 404
37
+ end
38
+
39
+ feature "A symbol path component captures that component using the symbol as a key." do
40
+ Test::Resources::Map.on( :get, [ :foo ] ) { captured[:foo] }
41
+ get("/foo").body.should == 'foo'
42
+ get("/bar").body.should == 'bar'
43
+ end
44
+
45
+ feature "A regexp path component matches the any component that matches the regexp." do
46
+ Test::Resources::Map.on( :get, [ /\d+/ ] ) { request.path }
47
+ get("/1234").body.should == '/1234'
48
+ get("/foo").status.should == 404
49
+ end
50
+
51
+ feature "A path component of true matches the remaining path." do
52
+ Test::Resources::Map.on( :get, [ 'foo', true ] ) { request.path }
53
+ get("/foo/bar/baz").body.should == '/foo/bar/baz'
54
+ get("/foo").status.should == 404
55
+ end
56
+
57
+ [["one or more", 1..-1, false, true, true],
58
+ ["zero or more", 0..-1, true, true, true],
59
+ ["one to N (N=2)", 1..2, false, true, true, false],
60
+ ["one to N (N=3)", 1..3, false, true, true, true, false]
61
+ ].each do |name, range, *tests|
62
+ feature "A Range path component can match #{name} components" do
63
+ Test::Resources::Map.on(:get, ['foo', range]) { request.path }
64
+ tests.size.times do |i|
65
+ get("/foo" * ( i + 1 ) ).status.should == (tests[i] ? 200 : 404)
66
+ end
67
+ end
68
+ end
69
+
70
+ feature "A path component can use a hash with a value of true to capture the remaining path." do
71
+ Test::Resources::Map.on( :get, [ 'foo', { :rest => true } ] ) { captured[:rest] * ' ' }
72
+ get("/foo/bar/baz").body.should == 'bar baz'
73
+ end
74
+
75
+ [["one or more", 1..-1, false, 'foo', 'foo foo'],
76
+ ["zero or more", 0..-1, '', 'foo', 'foo foo'],
77
+ ["one to N (N=2)", 1..2, false, 'foo', 'foo foo', false],
78
+ ["one to N (N=3)", 0..3, '', 'foo', 'foo foo', 'foo foo foo', false]
79
+ ].each do |name, range, *tests|
80
+ feature "A Range path component can match #{name} components" do
81
+ Test::Resources::Map.on(:get, ['foo', { :rest => range }]) { captured.rest * ' ' }
82
+ tests.size.times do |i|
83
+ response = get("/foo" * ( i + 1 ) )
84
+ tests[i] ? response.body.should == tests[i] : response.status.should == 404
85
+ end
86
+ end
87
+ end
88
+
89
+ feature "A path component can use a hash with a string value to provide a default." do
90
+ Test::Resources::Map.on( :get, [ 'foo', { :bar => 'bar' } ] ) { captured[:bar] }
91
+ get("/foo/baz").body.should == 'baz'
92
+ get("/foo").body.should == 'bar'
93
+ end
94
+
95
+ feature "A path component can use a hash with a regexp value to match and capture." do
96
+ Test::Resources::Map.on( :get, [ 'foo', { :bar => /\d+/ } ] ) { captured[:bar] }
97
+ get("/foo/123").body.should == '123'
98
+ get("/foo").status.should == 404
99
+ end
100
+
101
+ it "Path components match against unescaped values" do
102
+ Test::Resources::Map.on(:get, [ 'polar bear']) { 'bang' }
103
+ get("/polar%20bear").body.should == 'bang'
104
+ end
105
+
106
+ end
@@ -0,0 +1,60 @@
1
+ require "#{File.dirname(__FILE__)}/../../test/helpers.rb"
2
+ require 'waves/foundations/compact'
3
+
4
+ describe "Matching Query Parameters" do
5
+
6
+ before do
7
+ Test = Module.new { include Waves::Foundations::Compact }
8
+ Waves << Test
9
+ end
10
+
11
+ after do
12
+ Waves.applications.clear
13
+ Object.instance_eval { remove_const(:Test) if const_defined?(:Test) }
14
+ end
15
+
16
+ feature "Test for a query parameter using true" do
17
+ Test::Resources::Map.on(:get, ["foo"], :accept => "text/plain",
18
+ :query => {:bar => true}) { }
19
+
20
+ resp = get "/foo?bar=baz", "HTTP_ACCEPT" => "text/plain"
21
+ resp.status.should == 200
22
+
23
+ resp = get "/foo", "HTTP_ACCEPT" => "text/plain"
24
+ resp.status.should == 404
25
+ end
26
+
27
+ feature "Test that a query parameter matches a regexp" do
28
+ Test::Resources::Map.on(:get, ["foo"], :accept => "text/plain",
29
+ :query => {:bar => /\d+/}) { }
30
+
31
+ resp = get "/foo?bar=123", "HTTP_ACCEPT" => "text/plain"
32
+ resp.status.should == 200
33
+
34
+ resp = get "/foo?bar=baz", "HTTP_ACCEPT" => "text/plain"
35
+ resp.status.should == 404
36
+ end
37
+
38
+ feature "Test that a query parameter matches a string" do
39
+ Test::Resources::Map.on(:get, ["foo"], :accept => "text/plain",
40
+ :query => {:bar => "123"}) { }
41
+
42
+ resp = get "/foo?bar=123", "HTTP_ACCEPT" => "text/plain"
43
+ resp.status.should == 200
44
+
45
+ resp = get "/foo?bar=baz", "HTTP_ACCEPT" => "text/plain"
46
+ resp.status.should == 404
47
+ end
48
+
49
+ feature "Test that a query parameter satisfies a lambda condition" do
50
+ Test::Resources::Map.on(:get, ["foo"], :accept => "text/plain",
51
+ :query => {:bar => lambda {|x| x == "123" }}) { }
52
+
53
+ resp = get "/foo?bar=123", "HTTP_ACCEPT" => "text/plain"
54
+ resp.status.should == 200
55
+
56
+ resp = get "/foo?bar=baz", "HTTP_ACCEPT" => "text/plain"
57
+ resp.status.should == 404
58
+ end
59
+
60
+ end