waves 0.8.2 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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