waves-edge 2009.03.10.13.14
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/waves +30 -0
- data/doc/HISTORY +1 -0
- data/doc/LICENSE +22 -0
- data/doc/README +1 -0
- data/doc/VERSION +1 -0
- data/lib/caches/file.rb +48 -0
- data/lib/caches/memcached.rb +40 -0
- data/lib/caches/simple.rb +25 -0
- data/lib/caches/synchronized.rb +25 -0
- data/lib/commands/console.rb +35 -0
- data/lib/commands/generate.rb +52 -0
- data/lib/commands/help.rb +5 -0
- data/lib/commands/server.rb +68 -0
- data/lib/dispatchers/base.rb +68 -0
- data/lib/dispatchers/default.rb +25 -0
- data/lib/ext/float.rb +13 -0
- data/lib/ext/hash.rb +31 -0
- data/lib/ext/integer.rb +27 -0
- data/lib/ext/kernel.rb +20 -0
- data/lib/ext/module.rb +20 -0
- data/lib/ext/object.rb +33 -0
- data/lib/ext/string.rb +20 -0
- data/lib/ext/symbol.rb +11 -0
- data/lib/ext/tempfile.rb +5 -0
- data/lib/foundations/classic.rb +59 -0
- data/lib/foundations/compact.rb +52 -0
- data/lib/helpers/basic.rb +11 -0
- data/lib/helpers/doc_type.rb +34 -0
- data/lib/helpers/extended.rb +21 -0
- data/lib/helpers/form.rb +42 -0
- data/lib/helpers/formatting.rb +30 -0
- data/lib/helpers/layouts.rb +37 -0
- data/lib/helpers/model.rb +37 -0
- data/lib/helpers/view.rb +22 -0
- data/lib/layers/inflect/english.rb +35 -0
- data/lib/layers/mvc.rb +41 -0
- data/lib/layers/mvc/controllers.rb +41 -0
- data/lib/layers/mvc/extensions.rb +52 -0
- data/lib/layers/orm/migration.rb +79 -0
- data/lib/layers/orm/providers/active_record.rb +84 -0
- data/lib/layers/orm/providers/active_record/migrations/empty.rb.erb +9 -0
- data/lib/layers/orm/providers/active_record/tasks/generate.rb +28 -0
- data/lib/layers/orm/providers/active_record/tasks/schema.rb +22 -0
- data/lib/layers/orm/providers/data_mapper.rb +37 -0
- data/lib/layers/orm/providers/filebase.rb +25 -0
- data/lib/layers/orm/providers/sequel.rb +87 -0
- data/lib/layers/orm/providers/sequel/migrations/empty.rb.erb +9 -0
- data/lib/layers/orm/providers/sequel/tasks/generate.rb +30 -0
- data/lib/layers/orm/providers/sequel/tasks/schema.rb +16 -0
- data/lib/layers/renderers/erubis.rb +52 -0
- data/lib/layers/renderers/haml.rb +67 -0
- data/lib/layers/renderers/markaby.rb +41 -0
- data/lib/matchers/accept.rb +21 -0
- data/lib/matchers/base.rb +30 -0
- data/lib/matchers/content_type.rb +17 -0
- data/lib/matchers/path.rb +67 -0
- data/lib/matchers/query.rb +21 -0
- data/lib/matchers/request.rb +27 -0
- data/lib/matchers/resource.rb +19 -0
- data/lib/matchers/traits.rb +19 -0
- data/lib/matchers/uri.rb +20 -0
- data/lib/renderers/mixin.rb +13 -0
- data/lib/resources/mixin.rb +136 -0
- data/lib/resources/paths.rb +132 -0
- data/lib/runtime/configuration.rb +100 -0
- data/lib/runtime/console.rb +23 -0
- data/lib/runtime/logger.rb +35 -0
- data/lib/runtime/mime_types.rb +536 -0
- data/lib/runtime/mocks.rb +14 -0
- data/lib/runtime/monitor.rb +32 -0
- data/lib/runtime/request.rb +152 -0
- data/lib/runtime/response.rb +43 -0
- data/lib/runtime/response_mixin.rb +54 -0
- data/lib/runtime/runtime.rb +69 -0
- data/lib/runtime/server.rb +20 -0
- data/lib/runtime/session.rb +27 -0
- data/lib/runtime/worker.rb +86 -0
- data/lib/servers/base.rb +42 -0
- data/lib/servers/mongrel.rb +13 -0
- data/lib/servers/webrick.rb +13 -0
- data/lib/tasks/gem.rb +32 -0
- data/lib/tasks/generate.rb +85 -0
- data/lib/views/errors.rb +49 -0
- data/lib/views/mixin.rb +64 -0
- data/lib/waves.rb +63 -0
- data/samples/blog/Rakefile +25 -0
- data/samples/blog/configurations/default.rb +11 -0
- data/samples/blog/configurations/development.rb +29 -0
- data/samples/blog/configurations/production.rb +26 -0
- data/samples/blog/models/comment.rb +23 -0
- data/samples/blog/models/entry.rb +31 -0
- data/samples/blog/public/css/site.css +13 -0
- data/samples/blog/public/javascript/jquery-1.2.6.min.js +32 -0
- data/samples/blog/public/javascript/site.js +13 -0
- data/samples/blog/resources/entry.rb +39 -0
- data/samples/blog/resources/map.rb +9 -0
- data/samples/blog/schema/migrations/001_initial_schema.rb +17 -0
- data/samples/blog/schema/migrations/002_add_comments.rb +18 -0
- data/samples/blog/schema/migrations/templates/empty.rb.erb +9 -0
- data/samples/blog/startup.rb +8 -0
- data/samples/blog/templates/comment/add.mab +12 -0
- data/samples/blog/templates/comment/list.mab +6 -0
- data/samples/blog/templates/entry/edit.mab +14 -0
- data/samples/blog/templates/entry/list.mab +16 -0
- data/samples/blog/templates/entry/show.mab +18 -0
- data/samples/blog/templates/entry/summary.mab +9 -0
- data/samples/blog/templates/errors/not_found_404.mab +7 -0
- data/samples/blog/templates/errors/server_error_500.mab +2 -0
- data/samples/blog/templates/layouts/default.mab +19 -0
- data/samples/blog/templates/waves/status.mab +85 -0
- data/templates/classic/Rakefile +90 -0
- data/templates/classic/configurations/default.rb.erb +9 -0
- data/templates/classic/configurations/development.rb.erb +26 -0
- data/templates/classic/configurations/production.rb.erb +29 -0
- data/templates/classic/controllers/.gitignore +0 -0
- data/templates/classic/helpers/.gitignore +0 -0
- data/templates/classic/lib/tasks/.gitignore +0 -0
- data/templates/classic/models/.gitignore +0 -0
- data/templates/classic/public/css/.gitignore +0 -0
- data/templates/classic/public/flash/.gitignore +0 -0
- data/templates/classic/public/images/.gitignore +0 -0
- data/templates/classic/public/javascript/.gitignore +0 -0
- data/templates/classic/resources/.gitignore +0 -0
- data/templates/classic/resources/map.rb.erb +8 -0
- data/templates/classic/schema/migrations/.gitignore +0 -0
- data/templates/classic/startup.rb.erb +11 -0
- data/templates/classic/templates/errors/not_found_404.mab +7 -0
- data/templates/classic/templates/errors/server_error_500.mab +7 -0
- data/templates/classic/templates/layouts/default.mab +14 -0
- data/templates/classic/tmp/sessions/.gitignore +0 -0
- data/templates/classic/views/.gitignore +0 -0
- data/templates/compact/startup.rb.erb +11 -0
- data/test/ext/object.rb +55 -0
- data/test/ext/shortcuts.rb +73 -0
- data/test/helpers.rb +17 -0
- data/test/match/accept.rb +34 -0
- data/test/match/methods.rb +22 -0
- data/test/match/params.rb +33 -0
- data/test/match/path.rb +106 -0
- data/test/match/query.rb +40 -0
- data/test/process/request.rb +75 -0
- data/test/process/resource.rb +53 -0
- data/test/resources/path.rb +166 -0
- data/test/runtime/configurations.rb +19 -0
- data/test/runtime/request.rb +63 -0
- data/test/runtime/response.rb +55 -0
- data/test/views/views.rb +34 -0
- metadata +394 -0
data/test/match/query.rb
ADDED
@@ -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
|