deas 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,203 @@
1
+ require 'assert'
2
+ require 'deas/logger'
3
+ require 'deas/route'
4
+ require 'deas/server'
5
+ require 'logger'
6
+
7
+ class Deas::Server
8
+
9
+ class BaseTests < Assert::Context
10
+ desc "Deas::Server"
11
+ setup do
12
+ @old_configuration = Deas::Server.configuration.dup
13
+ new_configuration = Deas::Server::Configuration.new
14
+ Deas::Server.instance.tap do |s|
15
+ s.instance_variable_set("@configuration", new_configuration)
16
+ end
17
+ end
18
+ teardown do
19
+ Deas::Server.instance.tap do |s|
20
+ s.instance_variable_set("@configuration", @old_configuration)
21
+ end
22
+ end
23
+ subject{ Deas::Server }
24
+
25
+ should have_instance_methods :configuration, :init, :view_handler_ns,
26
+ :get, :post, :put, :patch, :delete, :route
27
+
28
+ should "be a singleton" do
29
+ assert_includes Singleton, subject.included_modules
30
+ end
31
+
32
+ should "allow setting it's configuration options" do
33
+ config = subject.configuration
34
+
35
+ subject.env 'staging'
36
+ assert_equal 'staging', config.env
37
+
38
+ subject.root '/path/to/root'
39
+ assert_equal '/path/to/root', config.root.to_s
40
+
41
+ subject.public_folder '/path/to/public'
42
+ assert_equal '/path/to/public', config.public_folder.to_s
43
+
44
+ subject.views_folder '/path/to/views'
45
+ assert_equal '/path/to/views', config.views_folder.to_s
46
+
47
+ subject.dump_errors true
48
+ assert_equal true, config.dump_errors
49
+
50
+ subject.method_override false
51
+ assert_equal false, config.method_override
52
+
53
+ subject.sessions false
54
+ assert_equal false, config.sessions
55
+
56
+ subject.show_exceptions true
57
+ assert_equal true, config.show_exceptions
58
+
59
+ subject.static_files false
60
+ assert_equal false, config.static_files
61
+
62
+ stdout_logger = Logger.new(STDOUT)
63
+ subject.logger stdout_logger
64
+ assert_equal stdout_logger, config.logger
65
+
66
+ init_proc = proc{ }
67
+ subject.init(&init_proc)
68
+ assert_equal init_proc, config.init_proc
69
+ end
70
+
71
+ should "add a GET route using #get" do
72
+ subject.get('/assets', 'ListAssets')
73
+
74
+ route = subject.configuration.routes[0]
75
+ assert_instance_of Deas::Route, route
76
+ assert_equal :get, route.method
77
+ assert_equal '/assets', route.path
78
+ assert_equal 'ListAssets', route.handler_class_name
79
+ end
80
+
81
+ should "add a POST route using #post" do
82
+ subject.post('/assets', 'CreateAsset')
83
+
84
+ route = subject.configuration.routes[0]
85
+ assert_instance_of Deas::Route, route
86
+ assert_equal :post, route.method
87
+ assert_equal '/assets', route.path
88
+ assert_equal 'CreateAsset', route.handler_class_name
89
+ end
90
+
91
+ should "add a PUT route using #put" do
92
+ subject.put('/assets/:id', 'UpdateAsset')
93
+
94
+ route = subject.configuration.routes[0]
95
+ assert_instance_of Deas::Route, route
96
+ assert_equal :put, route.method
97
+ assert_equal '/assets/:id', route.path
98
+ assert_equal 'UpdateAsset', route.handler_class_name
99
+ end
100
+
101
+ should "add a PATCH route using #patch" do
102
+ subject.patch('/assets/:id', 'UpdateAsset')
103
+
104
+ route = subject.configuration.routes[0]
105
+ assert_instance_of Deas::Route, route
106
+ assert_equal :patch, route.method
107
+ assert_equal '/assets/:id', route.path
108
+ assert_equal 'UpdateAsset', route.handler_class_name
109
+ end
110
+
111
+ should "add a DELETE route using #delete" do
112
+ subject.delete('/assets/:id', 'DeleteAsset')
113
+
114
+ route = subject.configuration.routes[0]
115
+ assert_instance_of Deas::Route, route
116
+ assert_equal :delete, route.method
117
+ assert_equal '/assets/:id', route.path
118
+ assert_equal 'DeleteAsset', route.handler_class_name
119
+ end
120
+
121
+ should "allow defining any kind of route using #route" do
122
+ subject.route(:options, '/get_info', 'GetInfo')
123
+
124
+ route = subject.configuration.routes[0]
125
+ assert_instance_of Deas::Route, route
126
+ assert_equal :options, route.method
127
+ assert_equal '/get_info', route.path
128
+ assert_equal 'GetInfo', route.handler_class_name
129
+ end
130
+
131
+ should "set a namespace with #view_handler_ns and " \
132
+ "use it when defining routes" do
133
+ subject.view_handler_ns 'MyStuff'
134
+ assert_equal 'MyStuff', subject.configuration.view_handler_ns
135
+
136
+ # should use the ns
137
+ subject.route(:get, '/ns_test', 'NsTest')
138
+ route = subject.configuration.routes.last
139
+ assert_equal 'MyStuff::NsTest', route.handler_class_name
140
+
141
+ # should ignore the ns when the leading colons are present
142
+ subject.route(:post, '/no_ns_test', '::NoNsTest')
143
+ route = subject.configuration.routes.last
144
+ assert_equal '::NoNsTest', route.handler_class_name
145
+ end
146
+
147
+ end
148
+
149
+ class ConfigurationTests < BaseTests
150
+ desc "Configuration"
151
+ setup do
152
+ @configuration = Deas::Server::Configuration.new
153
+ end
154
+ subject{ @configuration }
155
+
156
+ should have_instance_methods :env, :root, :app_file, :public_folder,
157
+ :views_folder, :dump_errors, :method_override, :sessions, :static_files,
158
+ :init_proc, :logger, :routes, :view_handler_ns, :show_exceptions
159
+
160
+ should "default the env to 'development'" do
161
+ assert_equal 'development', subject.env
162
+ end
163
+
164
+ should "default the root to the routes file's folder" do
165
+ expected_root = File.expand_path('..', Deas.config.routes_file)
166
+ assert_equal expected_root, subject.root.to_s
167
+ end
168
+
169
+ should "default the app file to the routes file" do
170
+ assert_equal Deas.config.routes_file.to_s, subject.app_file.to_s
171
+ end
172
+
173
+ should "default the public folder based on the root" do
174
+ expected_root = File.expand_path('..', Deas.config.routes_file)
175
+ expected_public_folder = File.join(expected_root, 'public')
176
+ assert_equal expected_public_folder, subject.public_folder.to_s
177
+ end
178
+
179
+ should "default the views folder based on the root" do
180
+ expected_root = File.expand_path('..', Deas.config.routes_file)
181
+ expected_views_folder = File.join(expected_root, 'views')
182
+ assert_equal expected_views_folder, subject.views_folder.to_s
183
+ end
184
+
185
+ should "default the Sinatra flags" do
186
+ assert_equal false, subject.dump_errors
187
+ assert_equal true, subject.method_override
188
+ assert_equal false, subject.show_exceptions
189
+ assert_equal true, subject.sessions
190
+ assert_equal true, subject.static_files
191
+ end
192
+
193
+ should "default the logger to a NullLogger" do
194
+ assert_instance_of Deas::NullLogger, subject.logger
195
+ end
196
+
197
+ should "default routes to an empty array" do
198
+ assert_equal [], subject.routes
199
+ end
200
+
201
+ end
202
+
203
+ end
@@ -0,0 +1,70 @@
1
+ require 'assert'
2
+ require 'deas/route'
3
+ require 'deas/server'
4
+ require 'deas/sinatra_app'
5
+ require 'sinatra/base'
6
+ require 'test/support/view_handlers'
7
+
8
+ module Deas::SinatraApp
9
+
10
+ class BaseTests < Assert::Context
11
+ desc "Deas::SinatraApp"
12
+ setup do
13
+ @route = Deas::Route.new(:get, '/something', 'TestViewHandler')
14
+ @configuration = Deas::Server::Configuration.new.tap do |c|
15
+ c.env = 'staging'
16
+ c.root = 'path/to/somewhere'
17
+ c.dump_errors = true
18
+ c.method_override = false
19
+ c.sessions = false
20
+ c.show_exceptions = true
21
+ c.static = true
22
+ c.routes = [ @route ]
23
+ end
24
+ @sinatra_app = Deas::SinatraApp.new(@configuration)
25
+ end
26
+ subject{ @sinatra_app }
27
+
28
+ should "be a kind of Sinatra::Base" do
29
+ assert_equal Sinatra::Base, subject.superclass
30
+ end
31
+
32
+ should "call init procs when initialized" do
33
+ initialized = false
34
+ @configuration.init_proc = proc{ initialized = true }
35
+ @sinatra_app = Deas::SinatraApp.new(@configuration)
36
+
37
+ assert_equal true, initialized
38
+ end
39
+
40
+ should "call constantize! on all routes" do
41
+ assert_equal TestViewHandler, @route.handler_class
42
+ end
43
+
44
+ should "have it's configuration set based on the server configuration" do
45
+ subject.settings do |settings|
46
+ assert_equal 'staging', settings.env
47
+ assert_equal 'path/to/somewhere', settings.root
48
+ assert_equal @configuration.app_file, settings.app_file
49
+ assert_equal 'path/to/somewhere/public', settings.public_folder
50
+ assert_equal 'path/to/somewhere/views', settings.views
51
+ assert_equal true, settings.dump_errors
52
+ assert_equal false, settings.logging
53
+ assert_equal false, settings.method_override
54
+ assert_equal false, settings.sessions
55
+ assert_equal true, settings.show_exceptions
56
+ assert_equal true, settings.static_files
57
+ assert_equal @configuration.logger, settings.deas_logger
58
+ end
59
+ end
60
+
61
+ should "define Sinatra routes for every route in the configuration" do
62
+ get_routes = subject.routes[@route.method.to_s.upcase] || []
63
+ sinatra_route = get_routes.detect{|route| route[0].match(@route.path) }
64
+
65
+ assert_not_nil sinatra_route
66
+ end
67
+
68
+ end
69
+
70
+ end
@@ -0,0 +1,103 @@
1
+ require 'assert'
2
+ require 'deas/sinatra_runner'
3
+ require 'deas/template'
4
+ require 'test/support/fake_app'
5
+ require 'test/support/view_handlers'
6
+
7
+ class Deas::SinatraRunner
8
+
9
+ class BaseTests < Assert::Context
10
+ desc "Deas::SinatraRunner"
11
+ setup do
12
+ @fake_sinatra_call = FakeApp.new
13
+ @runner = Deas::SinatraRunner.new(FlagViewHandler, @fake_sinatra_call)
14
+ end
15
+ subject{ @runner }
16
+
17
+ should have_instance_methods :run, :request, :response, :params, :logger,
18
+ :halt, :render, :session, :redirect, :redirect_to
19
+
20
+ should "return the sinatra_call's request with #request" do
21
+ assert_equal @fake_sinatra_call.request, subject.request
22
+ end
23
+
24
+ should "return the sinatra_call's response with #response" do
25
+ assert_equal @fake_sinatra_call.response, subject.response
26
+ end
27
+
28
+ should "return the sinatra_call's params with #params" do
29
+ assert_equal @fake_sinatra_call.params, subject.params
30
+ end
31
+
32
+ should "return the sinatra_call's session with #session" do
33
+ assert_equal @fake_sinatra_call.session, subject.session
34
+ end
35
+
36
+ should "return the sinatra_call's settings logger with #logger" do
37
+ assert_equal @fake_sinatra_call.settings.deas_logger, subject.logger
38
+ end
39
+
40
+ should "call the sinatra_call's halt with #halt" do
41
+ return_value = catch(:halt){ subject.halt('test') }
42
+ assert_equal [ 'test' ], return_value
43
+ end
44
+
45
+ should "call the sinatra_call's erb method with #render" do
46
+ return_value = subject.render('index')
47
+
48
+ assert_equal :web, return_value[0]
49
+ assert_equal :index, return_value[2]
50
+
51
+ options = return_value[3]
52
+ assert_instance_of Deas::Template::RenderScope, options[:scope]
53
+
54
+ expected_locals = { :view => subject.instance_variable_get("@handler") }
55
+ assert_equal(expected_locals, options[:locals])
56
+ end
57
+
58
+ should "call the sinatra_call's redirect method with #redirect" do
59
+ return_value = catch(:halt){ subject.redirect('http://google.com') }
60
+ expected = [ 302, { 'Location' => 'http://google.com' } ]
61
+
62
+ assert_equal expected, return_value
63
+ end
64
+
65
+ should "call the sinatra_call's redirect and to methods with #redirect_to" do
66
+ return_value = catch(:halt){ subject.redirect_to('/somewhere') }
67
+ expected = [ 302, { 'Location' => "http://test.local/somewhere" } ]
68
+
69
+ assert_equal expected, return_value
70
+ end
71
+
72
+ should "not throw an exception with the setup or teardown methods" do
73
+ assert_nothing_raised{ subject.setup }
74
+ assert_nothing_raised{ subject.teardown }
75
+ end
76
+
77
+ end
78
+
79
+ class RunTests < BaseTests
80
+ desc "run"
81
+ setup do
82
+ @return_value = @runner.run
83
+ @handler = @runner.instance_variable_get("@handler")
84
+ end
85
+ subject{ @handler }
86
+
87
+ should "run the before and after hooks" do
88
+ assert_equal true, subject.before_hook_called
89
+ assert_equal true, subject.after_hook_called
90
+ end
91
+
92
+ should "run the handler's init and run" do
93
+ assert_equal true, subject.init_bang_called
94
+ assert_equal true, subject.run_bang_called
95
+ end
96
+
97
+ should "return the handler's run! return value" do
98
+ assert_equal true, @return_value
99
+ end
100
+
101
+ end
102
+
103
+ end
@@ -0,0 +1,150 @@
1
+ require 'assert'
2
+ require 'deas/template'
3
+ require 'test/support/fake_app'
4
+
5
+ class Deas::Template
6
+
7
+ class BaseTests < Assert::Context
8
+ desc "Deas::Template"
9
+ setup do
10
+ @fake_sinatra_call = FakeApp.new
11
+ @template = Deas::Template.new(@fake_sinatra_call, 'users/index')
12
+ end
13
+ subject{ @template }
14
+
15
+ should have_instance_methods :name, :options, :render
16
+ should have_class_methods :helpers
17
+
18
+ should "symbolize it's name" do
19
+ assert_equal :"users/index", subject.name
20
+ end
21
+
22
+ should "set it's scope option to a empty Module" do
23
+ assert_instance_of Deas::Template::RenderScope, subject.options[:scope]
24
+ end
25
+
26
+ should "call the sinatra_call's `erb` method with #render" do
27
+ return_value = subject.render
28
+
29
+ assert_equal subject.name, return_value[0]
30
+ assert_equal subject.options, return_value[1]
31
+ end
32
+
33
+ should "include modules on the RenderScope using helpers class method" do
34
+ helper_module = Module.new
35
+ Deas::Template.helpers(helper_module)
36
+
37
+ included_modules = Deas::Template::RenderScope.included_modules
38
+ assert_includes helper_module, included_modules
39
+ end
40
+
41
+ end
42
+
43
+ class WithLayoutsTests < BaseTests
44
+ desc "with layouts"
45
+ setup do
46
+ @template = Deas::Template.new(@fake_sinatra_call, 'users/index', {
47
+ :layout => [ 'layouts/web', 'layouts/search' ]
48
+ })
49
+ end
50
+
51
+ should "call the engine's `erb` method for each layout, " \
52
+ "in the `layout` option" do
53
+ return_value = subject.render
54
+
55
+ # the return_value is a one-dimensional array of all the render args
56
+ # used in order. Thus the, 0, 2, 4 nature of the indexes.
57
+ assert_equal :"layouts/web", return_value[0]
58
+ assert_equal :"layouts/search", return_value[2]
59
+ assert_equal :"users/index", return_value[4]
60
+ end
61
+
62
+ end
63
+
64
+ class RenderScopeTests < Assert::Context
65
+ desc "Deas::Template::RenderScope"
66
+ setup do
67
+ @fake_sinatra_call = FakeApp.new
68
+ @render_scope = Deas::Template::RenderScope.new(@fake_sinatra_call)
69
+ end
70
+ subject{ @render_scope }
71
+
72
+ should have_instance_methods :partial, :escape_html, :h, :escape_url, :u,
73
+ :render
74
+
75
+ should "call the sinatra_call's erb method with #partial" do
76
+ return_value = subject.partial('part', :something => true)
77
+
78
+ assert_equal :_part, return_value[0]
79
+
80
+ expected_options = return_value[1]
81
+ assert_instance_of Deas::Template::RenderScope, expected_options[:scope]
82
+
83
+ expected_locals = { :something => true }
84
+ assert_equal(expected_locals, expected_options[:locals])
85
+ end
86
+
87
+ should "call the sinatra_call's erb method with #render" do
88
+ return_value = subject.render('my_template', {
89
+ :views => '/path/to/templates',
90
+ :locals => {
91
+ :something => true
92
+ }
93
+ })
94
+
95
+ assert_equal :my_template, return_value[0]
96
+
97
+ expected_options = return_value[1]
98
+ assert_instance_of Deas::Template::RenderScope, expected_options[:scope]
99
+
100
+ expected_locals = { :something => true }
101
+ assert_equal(expected_locals, expected_options[:locals])
102
+ end
103
+
104
+ should "escape html with #h or #escape_html" do
105
+ return_value = subject.escape_html("<strong></strong>")
106
+ assert_equal "&lt;strong&gt;&lt;&#x2F;strong&gt;", return_value
107
+
108
+ return_value = subject.h("<strong></strong>")
109
+ assert_equal "&lt;strong&gt;&lt;&#x2F;strong&gt;", return_value
110
+ end
111
+
112
+ should "escape urls with #u or #escape_url" do
113
+ return_value = subject.escape_url("/path/to/somewhere")
114
+ assert_equal "%2Fpath%2Fto%2Fsomewhere", return_value
115
+
116
+ return_value = subject.u("/path/to/somewhere")
117
+ assert_equal "%2Fpath%2Fto%2Fsomewhere", return_value
118
+ end
119
+
120
+ end
121
+
122
+ end
123
+
124
+ class Deas::Partial
125
+
126
+ class BaseTests < Assert::Context
127
+ desc "Deas::Partial"
128
+ setup do
129
+ @fake_sinatra_call = FakeApp.new
130
+ @partial = Deas::Partial.new(@fake_sinatra_call, 'users/index/listing', {
131
+ :user => 'Joe Test'
132
+ })
133
+ end
134
+ subject{ @partial }
135
+
136
+ should "be a kind of Deas::Template" do
137
+ assert_kind_of Deas::Template, subject
138
+ end
139
+
140
+ should "add an underscore to it's template's basename" do
141
+ assert_equal :"users/index/_listing", subject.name
142
+ end
143
+
144
+ should "set it's locals option" do
145
+ assert_equal({ :user => 'Joe Test' }, subject.options[:locals])
146
+ end
147
+
148
+ end
149
+
150
+ end
@@ -0,0 +1,96 @@
1
+ require 'assert'
2
+ require 'deas/test_helpers'
3
+ require 'deas/view_handler'
4
+ require 'test/support/view_handlers'
5
+
6
+ module Deas::ViewHandler
7
+
8
+ class BaseTests < Assert::Context
9
+ include Deas::TestHelpers
10
+
11
+ desc "Deas::ViewHandler"
12
+ setup do
13
+ @handler = test_runner(TestViewHandler).handler
14
+ end
15
+ subject{ @handler }
16
+
17
+ should have_instance_methods :init, :init!, :run, :run!
18
+ should have_class_methods :before, :before_callbacks, :after,
19
+ :after_callbacks, :layout, :layouts
20
+
21
+ should "raise a NotImplementedError if run! is not overwritten" do
22
+ assert_raises(NotImplementedError){ subject.run! }
23
+ end
24
+
25
+ should "store procs in #before_callbacks with #before" do
26
+ before_proc = proc{ }
27
+ TestViewHandler.before(&before_proc)
28
+
29
+ assert_includes before_proc, TestViewHandler.before_callbacks
30
+ end
31
+
32
+ should "store procs in #after_callbacks with #after" do
33
+ after_proc = proc{ }
34
+ TestViewHandler.after(&after_proc)
35
+
36
+ assert_includes after_proc, TestViewHandler.after_callbacks
37
+ end
38
+
39
+ should "allow specifying the layouts using #layout or #layouts" do
40
+ handler_class = Class.new{ include Deas::ViewHandler }
41
+
42
+ handler_class.layout 'layouts/app'
43
+ assert_equal [ 'layouts/app' ], handler_class.layouts
44
+
45
+ handler_class.layouts 'layouts/web', 'layouts/search'
46
+ assert_equal [ 'layouts/web', 'layouts/search' ], handler_class.layouts
47
+ end
48
+
49
+ end
50
+
51
+ class WithMethodFlagsTests < BaseTests
52
+ setup do
53
+ @handler = test_runner(FlagViewHandler).handler
54
+ end
55
+
56
+ should "have called `init!` and it's callbacks" do
57
+ assert_equal true, subject.before_init_called
58
+ assert_equal true, subject.init_bang_called
59
+ assert_equal true, subject.after_init_called
60
+ end
61
+
62
+ should "not have called `run!` or it's callbacks when initialized" do
63
+ assert_nil subject.before_run_called
64
+ assert_nil subject.run_bang_called
65
+ assert_nil subject.after_run_called
66
+ end
67
+
68
+ should "call `run!` and it's callbacks when it's `run`" do
69
+ subject.run
70
+
71
+ assert_equal true, subject.before_run_called
72
+ assert_equal true, subject.run_bang_called
73
+ assert_equal true, subject.after_run_called
74
+ end
75
+
76
+ end
77
+
78
+ class HaltTests < BaseTests
79
+ desc "halt"
80
+
81
+ should "return a response with the status code and the passed data" do
82
+ runner = test_runner(HaltViewHandler, :params => {
83
+ 'code' => 200,
84
+ 'headers' => { 'Content-Type' => 'text/plain' },
85
+ 'body' => 'test halting'
86
+ })
87
+ runner.run
88
+
89
+ assert_equal 200, runner.return_value[0]
90
+ assert_equal({ 'Content-Type' => 'text/plain' }, runner.return_value[1])
91
+ assert_equal 'test halting', runner.return_value[2]
92
+ end
93
+
94
+ end
95
+
96
+ end