waves-edge 2009.03.10.13.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (148) hide show
  1. data/bin/waves +30 -0
  2. data/doc/HISTORY +1 -0
  3. data/doc/LICENSE +22 -0
  4. data/doc/README +1 -0
  5. data/doc/VERSION +1 -0
  6. data/lib/caches/file.rb +48 -0
  7. data/lib/caches/memcached.rb +40 -0
  8. data/lib/caches/simple.rb +25 -0
  9. data/lib/caches/synchronized.rb +25 -0
  10. data/lib/commands/console.rb +35 -0
  11. data/lib/commands/generate.rb +52 -0
  12. data/lib/commands/help.rb +5 -0
  13. data/lib/commands/server.rb +68 -0
  14. data/lib/dispatchers/base.rb +68 -0
  15. data/lib/dispatchers/default.rb +25 -0
  16. data/lib/ext/float.rb +13 -0
  17. data/lib/ext/hash.rb +31 -0
  18. data/lib/ext/integer.rb +27 -0
  19. data/lib/ext/kernel.rb +20 -0
  20. data/lib/ext/module.rb +20 -0
  21. data/lib/ext/object.rb +33 -0
  22. data/lib/ext/string.rb +20 -0
  23. data/lib/ext/symbol.rb +11 -0
  24. data/lib/ext/tempfile.rb +5 -0
  25. data/lib/foundations/classic.rb +59 -0
  26. data/lib/foundations/compact.rb +52 -0
  27. data/lib/helpers/basic.rb +11 -0
  28. data/lib/helpers/doc_type.rb +34 -0
  29. data/lib/helpers/extended.rb +21 -0
  30. data/lib/helpers/form.rb +42 -0
  31. data/lib/helpers/formatting.rb +30 -0
  32. data/lib/helpers/layouts.rb +37 -0
  33. data/lib/helpers/model.rb +37 -0
  34. data/lib/helpers/view.rb +22 -0
  35. data/lib/layers/inflect/english.rb +35 -0
  36. data/lib/layers/mvc.rb +41 -0
  37. data/lib/layers/mvc/controllers.rb +41 -0
  38. data/lib/layers/mvc/extensions.rb +52 -0
  39. data/lib/layers/orm/migration.rb +79 -0
  40. data/lib/layers/orm/providers/active_record.rb +84 -0
  41. data/lib/layers/orm/providers/active_record/migrations/empty.rb.erb +9 -0
  42. data/lib/layers/orm/providers/active_record/tasks/generate.rb +28 -0
  43. data/lib/layers/orm/providers/active_record/tasks/schema.rb +22 -0
  44. data/lib/layers/orm/providers/data_mapper.rb +37 -0
  45. data/lib/layers/orm/providers/filebase.rb +25 -0
  46. data/lib/layers/orm/providers/sequel.rb +87 -0
  47. data/lib/layers/orm/providers/sequel/migrations/empty.rb.erb +9 -0
  48. data/lib/layers/orm/providers/sequel/tasks/generate.rb +30 -0
  49. data/lib/layers/orm/providers/sequel/tasks/schema.rb +16 -0
  50. data/lib/layers/renderers/erubis.rb +52 -0
  51. data/lib/layers/renderers/haml.rb +67 -0
  52. data/lib/layers/renderers/markaby.rb +41 -0
  53. data/lib/matchers/accept.rb +21 -0
  54. data/lib/matchers/base.rb +30 -0
  55. data/lib/matchers/content_type.rb +17 -0
  56. data/lib/matchers/path.rb +67 -0
  57. data/lib/matchers/query.rb +21 -0
  58. data/lib/matchers/request.rb +27 -0
  59. data/lib/matchers/resource.rb +19 -0
  60. data/lib/matchers/traits.rb +19 -0
  61. data/lib/matchers/uri.rb +20 -0
  62. data/lib/renderers/mixin.rb +13 -0
  63. data/lib/resources/mixin.rb +136 -0
  64. data/lib/resources/paths.rb +132 -0
  65. data/lib/runtime/configuration.rb +100 -0
  66. data/lib/runtime/console.rb +23 -0
  67. data/lib/runtime/logger.rb +35 -0
  68. data/lib/runtime/mime_types.rb +536 -0
  69. data/lib/runtime/mocks.rb +14 -0
  70. data/lib/runtime/monitor.rb +32 -0
  71. data/lib/runtime/request.rb +152 -0
  72. data/lib/runtime/response.rb +43 -0
  73. data/lib/runtime/response_mixin.rb +54 -0
  74. data/lib/runtime/runtime.rb +69 -0
  75. data/lib/runtime/server.rb +20 -0
  76. data/lib/runtime/session.rb +27 -0
  77. data/lib/runtime/worker.rb +86 -0
  78. data/lib/servers/base.rb +42 -0
  79. data/lib/servers/mongrel.rb +13 -0
  80. data/lib/servers/webrick.rb +13 -0
  81. data/lib/tasks/gem.rb +32 -0
  82. data/lib/tasks/generate.rb +85 -0
  83. data/lib/views/errors.rb +49 -0
  84. data/lib/views/mixin.rb +64 -0
  85. data/lib/waves.rb +63 -0
  86. data/samples/blog/Rakefile +25 -0
  87. data/samples/blog/configurations/default.rb +11 -0
  88. data/samples/blog/configurations/development.rb +29 -0
  89. data/samples/blog/configurations/production.rb +26 -0
  90. data/samples/blog/models/comment.rb +23 -0
  91. data/samples/blog/models/entry.rb +31 -0
  92. data/samples/blog/public/css/site.css +13 -0
  93. data/samples/blog/public/javascript/jquery-1.2.6.min.js +32 -0
  94. data/samples/blog/public/javascript/site.js +13 -0
  95. data/samples/blog/resources/entry.rb +39 -0
  96. data/samples/blog/resources/map.rb +9 -0
  97. data/samples/blog/schema/migrations/001_initial_schema.rb +17 -0
  98. data/samples/blog/schema/migrations/002_add_comments.rb +18 -0
  99. data/samples/blog/schema/migrations/templates/empty.rb.erb +9 -0
  100. data/samples/blog/startup.rb +8 -0
  101. data/samples/blog/templates/comment/add.mab +12 -0
  102. data/samples/blog/templates/comment/list.mab +6 -0
  103. data/samples/blog/templates/entry/edit.mab +14 -0
  104. data/samples/blog/templates/entry/list.mab +16 -0
  105. data/samples/blog/templates/entry/show.mab +18 -0
  106. data/samples/blog/templates/entry/summary.mab +9 -0
  107. data/samples/blog/templates/errors/not_found_404.mab +7 -0
  108. data/samples/blog/templates/errors/server_error_500.mab +2 -0
  109. data/samples/blog/templates/layouts/default.mab +19 -0
  110. data/samples/blog/templates/waves/status.mab +85 -0
  111. data/templates/classic/Rakefile +90 -0
  112. data/templates/classic/configurations/default.rb.erb +9 -0
  113. data/templates/classic/configurations/development.rb.erb +26 -0
  114. data/templates/classic/configurations/production.rb.erb +29 -0
  115. data/templates/classic/controllers/.gitignore +0 -0
  116. data/templates/classic/helpers/.gitignore +0 -0
  117. data/templates/classic/lib/tasks/.gitignore +0 -0
  118. data/templates/classic/models/.gitignore +0 -0
  119. data/templates/classic/public/css/.gitignore +0 -0
  120. data/templates/classic/public/flash/.gitignore +0 -0
  121. data/templates/classic/public/images/.gitignore +0 -0
  122. data/templates/classic/public/javascript/.gitignore +0 -0
  123. data/templates/classic/resources/.gitignore +0 -0
  124. data/templates/classic/resources/map.rb.erb +8 -0
  125. data/templates/classic/schema/migrations/.gitignore +0 -0
  126. data/templates/classic/startup.rb.erb +11 -0
  127. data/templates/classic/templates/errors/not_found_404.mab +7 -0
  128. data/templates/classic/templates/errors/server_error_500.mab +7 -0
  129. data/templates/classic/templates/layouts/default.mab +14 -0
  130. data/templates/classic/tmp/sessions/.gitignore +0 -0
  131. data/templates/classic/views/.gitignore +0 -0
  132. data/templates/compact/startup.rb.erb +11 -0
  133. data/test/ext/object.rb +55 -0
  134. data/test/ext/shortcuts.rb +73 -0
  135. data/test/helpers.rb +17 -0
  136. data/test/match/accept.rb +34 -0
  137. data/test/match/methods.rb +22 -0
  138. data/test/match/params.rb +33 -0
  139. data/test/match/path.rb +106 -0
  140. data/test/match/query.rb +40 -0
  141. data/test/process/request.rb +75 -0
  142. data/test/process/resource.rb +53 -0
  143. data/test/resources/path.rb +166 -0
  144. data/test/runtime/configurations.rb +19 -0
  145. data/test/runtime/request.rb +63 -0
  146. data/test/runtime/response.rb +55 -0
  147. data/test/views/views.rb +34 -0
  148. metadata +394 -0
@@ -0,0 +1,40 @@
1
+ require "#{File.dirname(__FILE__)}/../../test/helpers.rb"
2
+ require '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, true, :query => { :bar => true }) {}
18
+ get("/foo?bar=baz").status.should == 200
19
+ get("/foo").status.should == 404
20
+ end
21
+
22
+ feature "Test that a query parameter matches a regexp" do
23
+ Test::Resources::Map.on( :get, true, :query => { :bar => /\d+/ }) {}
24
+ get("/foo?bar=123").status.should == 200
25
+ get("/foo?bar=baz").status.should == 404
26
+ end
27
+
28
+ feature "Test that a query parameter matches a string" do
29
+ Test::Resources::Map.on( :get, true, :query => { :bar => '123' }) {}
30
+ get("/foo?bar=123").status.should == 200
31
+ get("/foo?bar=baz").status.should == 404
32
+ end
33
+
34
+ feature "Test that a query parameter satisfies a lambda condition" do
35
+ Test::Resources::Map.on( :get, true, :query => { :bar => lambda { |x| x == '123' } }) {}
36
+ get("/foo?bar=123").status.should == 200
37
+ get("/foo?bar=baz").status.should == 404
38
+ end
39
+
40
+ end
@@ -0,0 +1,75 @@
1
+ require 'test/helpers.rb'
2
+ require 'foundations/compact'
3
+
4
+ describe "Request Object" do
5
+ before do
6
+ Test = Module.new { include Waves::Foundations::Compact }
7
+ Waves << Test
8
+ end
9
+
10
+ after do
11
+ Waves.applications.clear
12
+ Object.instance_eval { remove_const( :Test ) if const_defined?( :Test ) }
13
+ end
14
+
15
+ feature "Access the request method, scheme, url, host, port, path, referer, and query" do
16
+ r = Waves::Request.new( env( 'http://localhost/', :method => 'GET' ) )
17
+ { :scheme => 'http', :url => 'http://localhost/', :method => :get,
18
+ :path => '/', :host => 'localhost', :domain => 'localhost',
19
+ :query => {}, :params => {}, :port => 80, :referer => '/' }.
20
+ each { |k,v| r.send( k ).should == v }
21
+ end
22
+
23
+ feature "Access the request method as a boolean" do
24
+ Waves::Request.new( env( '/', :method => 'GET' ) ).get.should == true
25
+ end
26
+
27
+ feature "Access HTTP headers as accessor methods" do
28
+ Waves::Request.new( env( '/', :method => 'GET',
29
+ 'HTTP_CACHE_CONTROL' => 'no-cache' ) ).
30
+ cache_control.should == 'no-cache'
31
+ end
32
+
33
+ feature "Access accept headers as Waves::Request::Accept objects" do
34
+ Waves::Request.new( env( '/', :method => 'GET',
35
+ 'HTTP_ACCEPT_LANGUAGE' => 'en/us' ) ).
36
+ accept_language.class.should == Waves::Request::Accept
37
+ end
38
+
39
+ feature "Access custom headers as methods" do
40
+ Waves::Request.new( env( '/', :method => 'GET',
41
+ 'X_CUSTOM_HEADER' => 'foo' ) )[ :x_custom_header ].should == 'foo'
42
+ end
43
+
44
+ feature "Initiate redirect using #redirect" do
45
+ lambda {
46
+ Waves::Request.new( env( '/', :method => 'GET' ) ).redirect('/')
47
+ }.should.raise( Waves::Dispatchers::Redirect )
48
+ end
49
+
50
+ feature "Raise NotFoundError using #not_found" do
51
+ lambda {
52
+ Waves::Request.new( env( '/', :method => 'GET' ) ).not_found
53
+ }.should.raise( Waves::Dispatchers::NotFoundError )
54
+ end
55
+
56
+ feature "Access to content_type, media_type, and content_length" do
57
+ r = Waves::Request.new( env( '/', :method => 'GET',
58
+ 'CONTENT_TYPE' => 'text/plain;charset=utf-8', 'CONTENT_LENGTH' => 0 ) )
59
+ r.content_type.should == 'text/plain;charset=utf-8'
60
+ r.media_type.should == 'text/plain'
61
+ r.content_length.should == 0
62
+ end
63
+
64
+ feature "Read / write traits to the request" do
65
+ r = Waves::Request.new( env( '/', :method => 'GET' ))
66
+ r.traits[:foo] = 'bar'
67
+ r.traits.foo.should == 'bar'
68
+ end
69
+
70
+ feature "The Rack request is frozen and cannot be modified" do
71
+ r = Waves::Request.new( env( '/', :method => 'GET' ))
72
+ lambda { r.rack_request.instance_eval { @env = {} } }.should.raise( TypeError )
73
+ end
74
+
75
+ end
@@ -0,0 +1,53 @@
1
+ require 'test/helpers.rb'
2
+ require 'foundations/compact'
3
+
4
+ describe "Application Context" do
5
+ before do
6
+ Test = Module.new { include Waves::Foundations::Compact }
7
+ Waves << Test
8
+ end
9
+
10
+ after do
11
+ Waves.applications.clear
12
+ Object.instance_eval { remove_const( :Test ) if const_defined?( :Test ) }
13
+ end
14
+
15
+ feature "Provide acccess to request, response, and session objects" do
16
+ Test::Resources::Map.new( Waves::Request.new( env('/', :method => 'GET' ) ) ).
17
+ instance_eval do
18
+ { :request => Waves::Request, :response => Waves::Response,
19
+ :session => Waves::Session, :query => Waves::Request::Query }.
20
+ each { |k,v| send( k ).class.should == v }
21
+ end
22
+ end
23
+
24
+ feature "Shortcuts to the path, url, domain, and session" do
25
+ Test::Resources::Map.new( Waves::Request.new(
26
+ env('http://localhost/foo/bar.js', :method => 'GET' ) ) ).
27
+ instance_eval do
28
+ { :url => request.url, :path => request.path,
29
+ :domain => request.domain, :session => request.session }.
30
+ each { |k,v| send( k ).should == v }
31
+ end
32
+ end
33
+
34
+ feature "Access to path and associated helpers" do
35
+ Test::Resources::Map.new( Waves::Request.new(
36
+ env('http://localhost/foo/bar.js', :method => 'GET' ) ) ).
37
+ instance_eval do
38
+ { :url => 'http://localhost/foo/bar.js', :path => '/foo/bar.js',
39
+ :basename => '/foo/bar', :extension => 'js' }.
40
+ each { |k,v| send( k ).should == v }
41
+ end
42
+ end
43
+
44
+ feature "Access to the application object and name" do
45
+ Test::Resources::Map.new( Waves::Request.new(
46
+ env('http://localhost/foo/bar.js', :method => 'GET' ) ) ).
47
+ instance_eval do
48
+ { :app => Test, :app_name => :test }.
49
+ each { |k,v| send( k ).should == v }
50
+ end
51
+ end
52
+
53
+ end
@@ -0,0 +1,166 @@
1
+ require "#{File.dirname(__FILE__)}/../helpers.rb"
2
+ require "foundations/compact"
3
+
4
+ describe "A path generation method" do
5
+
6
+ before do
7
+ Test = Module.new { include Waves::Foundations::Compact }
8
+ @resource_class = Test::Resources::Map
9
+ @paths = @resource_class.new( Waves::Request.new( env( '/', :method => 'GET' ) ) ).paths
10
+ end
11
+
12
+ after do
13
+ Waves.applications.clear
14
+ Object.instance_eval { remove_const(:Test) if const_defined?(:Test) }
15
+ end
16
+
17
+ it "turns an empty template into '/'" do
18
+ @resource_class.on(:get, :list => [] ) { nil }
19
+ @paths.list.should == "/"
20
+ @paths.list("foo").should == "/"
21
+ end
22
+
23
+ it "reproduces strings from the path template" do
24
+ @resource_class.on(:get, :list => [ 'taller', 'ghost', 'walt' ] ) { nil }
25
+ @paths.list.should == "/taller/ghost/walt"
26
+ end
27
+
28
+ it "treats symbols as locations for arg interpolation" do
29
+ @resource_class.on(:get, :show => [ 'hi', 'there', :nickname ]) { nil }
30
+ @paths.show( 'freckles' ).should == "/hi/there/freckles"
31
+ end
32
+
33
+
34
+ it "treats a hash with string or symbol value as location for arg interpolations" do
35
+ @resource_class.on(:get, :edit => [ 'form', { :filter => 'textile' } ] ) { nil }
36
+ @paths.edit( 'markdown' ).should == "/form/markdown"
37
+ @paths.edit( 'markdown' ).should == "/form/markdown"
38
+ end
39
+
40
+ it "interpolates for a hash-with-regex only when the arg matches the regex" do
41
+ @resource_class.on(:get, :edit => [ 'form', { :filter => /^(textile|markdown|plain)$/ } ] ) { nil }
42
+ @paths.edit( 'markdown' ).should == "/form/markdown"
43
+
44
+ lambda { @paths.edit( 'html' ) }.should.raise ArgumentError
45
+ end
46
+
47
+ it "appends all arguments to the path when it encounters a true" do
48
+ @resource_class.on(:get, :count_1 => [ 'first', true ]) { nil }
49
+ @paths.count_1("second", "third", "fourth").should == "/first/second/third/fourth"
50
+
51
+ @resource_class.on(:get, :count_2 => [ 'first', { :whatever => true } ]) { nil }
52
+ @paths.count_2("second", "third", "fourth").should == "/first/second/third/fourth"
53
+ end
54
+
55
+ it "uses hash element value as default in absence of argument" do
56
+ @resource_class.on(:get, :edit => [ 'form', { :filter => 'textile' } ] ) { nil }
57
+ @paths.edit.should == "/form/textile"
58
+ end
59
+
60
+ it "uses regexes for argument interpolation if the arg matches" do
61
+ @resource_class.on(:get, :list => [ "episode", /\d+/ ] ) { nil }
62
+ @paths.list( 815 ).should == "/episode/815"
63
+
64
+ lambda { path = @paths.list( "boar" ) }.should.raise ArgumentError
65
+ end
66
+
67
+ describe "given an (implicit) array of args" do
68
+
69
+ it "interpolates its arguments in order" do
70
+ @resource_class.on(:get, :list => [ :one, :two, :three ] ) { nil }
71
+ @paths.list( 'one', 'two', 'three').should == '/one/two/three'
72
+ end
73
+
74
+ it "raises an ArgumentError if given more args than interpolables" do
75
+ @resource_class.on(:get, :list => [ :one ] ) { nil }
76
+ lambda { @paths.list( "x", "y") }.should.raise ArgumentError
77
+ end
78
+
79
+ end
80
+
81
+ describe "given an argument hash" do
82
+
83
+ it "interpolates arg pairs that match symbols in the template" do
84
+ @resource_class.on(:get, :list => [ :one, :two, :three ] ) { nil }
85
+ @paths.list( :three => 'three', :one => 'one', :two => 'two').should == '/one/two/three'
86
+ end
87
+
88
+ it "interpolates arg pairs that match the keys of hashes in the template" do
89
+ @resource_class.on(:get, :show => [ {:foo => 'bar'} ] ) { nil }
90
+ @paths.show( :foo => 'bear' ).should == "/bear"
91
+ end
92
+
93
+ it "interpolates an arg pair for a hash-with-regex only when the arg matches the regex" do
94
+ @resource_class.on(:get, :show => [ {:foo => /^ba(r|z|t)$/ } ] ) { nil }
95
+ @paths.show( :foo => 'baz' ).should == "/baz"
96
+ end
97
+
98
+ it "uses hash element value as default in absence of an arg pair" do
99
+ @resource_class.on(:get, :list => [ :one, { :two => 'two' }, :three ] ) { nil }
100
+ @paths.list( :three => 'three', :one => 'one').should == "/one/two/three"
101
+ end
102
+
103
+ it "raises when not all necessary interpolations can be performed" do
104
+ @resource_class.on(:get, :list => [ :one, :two, :three ] ) { nil }
105
+ lambda { @paths.list( :three => 'three', :one => 'one') }.should.raise ArgumentError
106
+ end
107
+
108
+ it "raises an ArgumentError if the template contains a regex" do
109
+ @resource_class.on(:get, :list => [ /anything/ ] ) { nil }
110
+ lambda { @paths.list( :one => 'one' ) }.should.raise ArgumentError
111
+ end
112
+
113
+ it "appends value/s of arg pair matching a template hash-with-true" do
114
+ @resource_class.on(:get, :list => [ :kind, { :parts => true } ]) { nil }
115
+ lambda { @paths.list( :kind => 'ghost') }.should.raise ArgumentError
116
+ @paths.list( :kind => 'ghost', :parts => "walt" ).should == "/ghost/walt"
117
+ @paths.list( :kind => 'ghost', :parts => ["walt", "boone"]).should == "/ghost/walt/boone"
118
+ end
119
+
120
+ it "raises an ArgumentError if the template contains a true" do
121
+ @resource_class.on(:get, :list => [ :kind, true ]) { nil }
122
+ lambda { @paths.list( :kind => 'whuh?' ) }.should.raise ArgumentError
123
+
124
+ end
125
+
126
+ end
127
+
128
+ describe "A path template" do
129
+
130
+ it "is compilable when it contains Strings, Symbols, and Hashes with Strings or Symbols" do
131
+ @resource_class.on(:get, :one => [ 'taller', 'ghost', 'walt' ] ) { nil }
132
+ @paths.one
133
+
134
+ @resource_class.on(:get, :two => [ 'hi', 'there', :nickname ]) { nil }
135
+ @paths.two( 'freckles' )
136
+
137
+ @resource_class.on(:get, :three => [ 'form', { :filter => 'textile' } ] ) { nil }
138
+ @paths.three( 'markdown' )
139
+
140
+ @resource_class.on(:get, :four => [ 'other_form', { :filter => :textile } ] ) { nil }
141
+ @paths.four( 'markdown' )
142
+
143
+ @paths.compiled_paths.values.sort.should == ["/taller/ghost/walt", "/hi/there/%s", "/form/%s", "/other_form/%s"].sort
144
+ end
145
+
146
+ it "is not compilable if it contains Regexps, true, or Hashes with Regexp or true" do
147
+ @resource_class.on(:get, :one => [ "episode", /\d+/ ] ) { nil }
148
+ @paths.one( 815 )
149
+
150
+ @resource_class.on(:get, :two => [ true ])
151
+ @paths.two( "foo" )
152
+
153
+ @resource_class.on(:get, :three => [ {:foo => /^ba(r|z|t)$/ } ] ) { nil }
154
+ @paths.three( :foo => 'baz' )
155
+
156
+ @resource_class.on(:get, :four => [ 'first', { :whatever => true } ]) { nil }
157
+ @paths.four
158
+
159
+ @paths.compiled_paths.values.should == []
160
+ end
161
+
162
+ end
163
+
164
+
165
+
166
+ end
@@ -0,0 +1,19 @@
1
+ require "#{File.dirname(__FILE__)}/../helpers.rb"
2
+
3
+ describe "Configuration attributes" do
4
+
5
+ class Basic < Waves::Configurations::Base; end
6
+
7
+ it "can be declared by developers" do
8
+ Basic.attribute :smurf
9
+ Basic.smurf("smurfy")
10
+ Basic.smurf.should == "smurfy"
11
+ end
12
+
13
+
14
+ it "must be declared before use" do
15
+ Basic.should.not.respond_to :gnome
16
+ end
17
+
18
+ end
19
+
@@ -0,0 +1,63 @@
1
+ require "#{File.dirname(__FILE__)}/../helpers.rb"
2
+
3
+ describe "A Waves request instance" do
4
+
5
+ before do
6
+ @request = Waves::Request.new(env( '/', :method => 'GET' ))
7
+ end
8
+
9
+ it "has session, response, and blackboard objects" do
10
+ @request.session.class.should == Waves::Session
11
+ @request.response.class.should == Waves::Response
12
+ end
13
+
14
+ it "provides an accessor to the Rack request" do
15
+ @request.rack_request.class.should == Rack::Request
16
+ end
17
+
18
+ it "wraps some useful Rack data in more elegant methods" do
19
+ @request.path.should == "/"
20
+
21
+ @request.domain.should == "example.org"
22
+
23
+ # @request.content_type.should == "text/html"
24
+ end
25
+
26
+ # it "delegates unknown methods to the Rack request" do
27
+ # @request.chitty_bang_bang
28
+ # end
29
+
30
+ end
31
+
32
+ describe "The HTTP request method" do
33
+
34
+
35
+ it "is determined in a straightforward manner for straightforward requests" do
36
+ @get = Waves::Request.new(env("/", :method => 'GET'))
37
+ @post = Waves::Request.new(env("/", :method => 'POST'))
38
+ @put = Waves::Request.new(env("/", :method => 'PUT'))
39
+ @delete = Waves::Request.new(env("/", :method => 'DELETE'))
40
+
41
+ @get.method.should == :get
42
+ @post.method.should == :post
43
+ @put.method.should == :put
44
+ @delete.method.should == :delete
45
+ end
46
+
47
+ it "can be set with the '_method' query param on a POST" do
48
+ @url_put = Waves::Request.new(env("/?_method=put", :method => 'POST'))
49
+ @url_delete = Waves::Request.new(env("/?_method=delete", :method => 'POST'))
50
+
51
+ @url_put.method.should == :put; @url_put.put.should.be.true
52
+ @url_delete.method.should == :delete; @url_delete.delete.should.be.true
53
+ end
54
+
55
+ it "can be set with the '_method' body param on a POST" do
56
+ @body_put = Waves::Request.new(env("/", :method => 'POST', :input => '_method=put'))
57
+ @body_delete = Waves::Request.new(env("/", :method => 'POST', :input => '_method=delete'))
58
+
59
+ @body_put.method.should == :put; @body_put.put.should.be.true
60
+ @body_delete.method.should == :delete
61
+ end
62
+
63
+ end
@@ -0,0 +1,55 @@
1
+ require "#{File.dirname(__FILE__)}/../helpers.rb"
2
+
3
+ describe "An instance of Waves::Response" do
4
+
5
+ before do
6
+ @request = Waves::Request.new(env( '/', :method => 'GET' ))
7
+ @response = Waves::Response.new(@request)
8
+ end
9
+
10
+ it "has a Rack::Response" do
11
+ @response.rack_response.class.should == Rack::Response
12
+ end
13
+
14
+ it "has a Waves::Request" do
15
+ @response.request.class.should == Waves::Request
16
+ end
17
+
18
+ it "can access the session for the current request" do
19
+ @response.session.class.should == Waves::Session
20
+ end
21
+
22
+ it "provides setter methods for commonly used headers" do
23
+ @response.rack_response.should.receive(:[]=).with('Content-Type', 'text/javascript')
24
+ @response.content_type = 'text/javascript'
25
+
26
+ @response.rack_response.should.receive(:[]=).with('Content-Length', '42')
27
+ @response.content_length = '42'
28
+
29
+ @response.rack_response.should.receive(:[]=).with('Location', '/here/')
30
+ @response.location = '/here/'
31
+
32
+ @response.rack_response.should.receive(:[]=).with('Expires', 'Thu, 09 Aug 2007 05:22:55 GMT')
33
+ @response.expires = 'Thu, 09 Aug 2007 05:22:55 GMT'
34
+ end
35
+
36
+ it "delegates unknown methods to the Rack response" do
37
+ @response.rack_response.should.receive(:mclintock!)
38
+ @response.mclintock!
39
+ end
40
+
41
+ end
42
+
43
+ describe "Waves::Response#finish" do
44
+
45
+ before do
46
+ @request = Waves::Request.new(env( '/', :method => 'GET' ))
47
+ @response = Waves::Response.new(@request)
48
+ end
49
+
50
+ it "saves the request session and calls Rack::Response#finish" do
51
+ @response.rack_response.should.receive(:finish)
52
+ @response.finish
53
+ end
54
+
55
+ end