lego-core 0.0.1

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.
@@ -0,0 +1,188 @@
1
+ require File.join('spec', '/spec_helper')
2
+
3
+ describe Lego::Controller::RouteHandler do
4
+
5
+ context '.match_all_routes with matching route' do
6
+ before do
7
+ @route_handler = empty_route_handler
8
+ @env = {}
9
+ @env["REQUEST_METHOD"] = 'GET'
10
+ @valid_route = {:path => '/myadmin'}
11
+ @other_route = {:path => '/foo'}
12
+ @fake_routes = {:get => [@other_route, @other_route, @valid_route], :post => [{}]}
13
+ end
14
+
15
+ it 'should return matching route if found' do
16
+ @route_handler.should_receive(:routes).and_return(@fake_routes)
17
+ @route_handler.should_receive(:run_matchers).with(@other_route, @env).exactly(2).times.and_return(false)
18
+ @route_handler.should_receive(:run_matchers).with(@valid_route, @env).and_return(true)
19
+ @route_handler.match_all_routes(@env).should eql(@valid_route)
20
+ end
21
+
22
+ it 'should return false when no matching route is found' do
23
+ @route_handler.should_receive(:routes).and_return({:get=> [{}]})
24
+ @route_handler.should_receive(:run_matchers).and_return(false)
25
+ @route_handler.match_all_routes(@env).should eql(nil)
26
+ end
27
+ end
28
+
29
+ context '.run_matchers' do
30
+ before do
31
+ @route_handler = empty_route_handler
32
+ @env = {}
33
+ @route = { :path => '/mypath' }
34
+ module Match1; end
35
+ module Match2; end
36
+ @matchers = [Match1, Match2]
37
+ end
38
+
39
+ it 'should return true when matching route found' do
40
+ Match1.should_receive(:match_route).with(@route, @env).and_return(false)
41
+ Match2.should_receive(:match_route).with(@route, @env).and_return(true)
42
+ @route_handler.should_receive(:matchers).and_return(@matchers)
43
+ @route_handler.run_matchers(@route, @env).should eql(true)
44
+ end
45
+
46
+ it 'should return false when no matching route found' do
47
+ Match1.should_receive(:match_route).with(@route, @env).and_return(false)
48
+ Match2.should_receive(:match_route).with(@route, @env).and_return(false)
49
+ @route_handler.should_receive(:matchers).and_return(@matchers)
50
+ @route_handler.run_matchers(@route, @env).should eql(false)
51
+ end
52
+ end
53
+
54
+ context '.routes' do
55
+ before do
56
+ @route_handler = empty_route_handler
57
+ end
58
+
59
+ it 'should return empty routes when new' do
60
+ @route_handler.routes.should eql({
61
+ :get => [],
62
+ :post => [],
63
+ :put => [],
64
+ :head => [],
65
+ :delete => [],
66
+ :not_found => nil
67
+ })
68
+ end
69
+ end
70
+
71
+ context '.add_route' do
72
+ before do
73
+ @route_handler = empty_route_handler
74
+ end
75
+
76
+ it 'should appen routes with their options' do
77
+ route_options1 = { :path => '/a_path1' }
78
+ route_options2 = { :path => '/a_path2' }
79
+ @route_handler.add_route(:get, route_options1)
80
+ @route_handler.add_route(:get, route_options2)
81
+ @route_handler.routes[:get].should eql([route_options1, route_options2])
82
+ end
83
+
84
+ it 'should set not_found route if method is :not_found' do
85
+ route_options = { :action_block => '{block}' }
86
+ @route_handler.add_route(:not_found, route_options)
87
+ @route_handler.routes[:not_found].should eql(route_options)
88
+ end
89
+ end
90
+
91
+ context '.matchers' do
92
+ before do
93
+ @route_handler = empty_route_handler
94
+ end
95
+
96
+ it 'should return an empty Array when new' do
97
+ @route_handler.matchers.should eql([])
98
+ end
99
+
100
+ end
101
+
102
+ context '.add_matcher' do
103
+ before do
104
+ @route_handler = empty_route_handler
105
+ module ValidMatcher; def self.match_route(route, env); end; end
106
+ module BrokenMatcher; end
107
+ end
108
+
109
+ it 'should store route matchers if valid' do
110
+ @route_handler.add_matcher(ValidMatcher)
111
+ @route_handler.matchers.should eql([ValidMatcher])
112
+ end
113
+
114
+ it 'should raise InvalidMatcher error if invalid' do
115
+ @route_handler.should_receive(:validate_matcher).and_return(false)
116
+ lambda { @route_handler.add_matcher(BrokenMatcher) }.should raise_error(Lego::Controller::RouteHandler::InvalidMatcher)
117
+ @route_handler.matchers.should == []
118
+ end
119
+ end
120
+
121
+ context '.validate_matcher' do
122
+ before do
123
+ @route_handler = empty_route_handler
124
+ module MyBrokenMatcher; end
125
+ module MyValidMatcher; def self.match_route(); end; end
126
+ end
127
+
128
+ it 'should return true if a valid Matcher module' do
129
+ @route_handler.validate_matcher(MyValidMatcher).should be_true
130
+ end
131
+
132
+ it 'should return false if not a valid Matcher module' do
133
+ @route_handler.validate_matcher(MyBrokenMatcher).should be_false
134
+ end
135
+ end
136
+
137
+ context 'when extended' do
138
+ before do
139
+ reset_lego_base
140
+ end
141
+ it 'plugins should be copied from base class' do
142
+
143
+ module GlobalPlug
144
+ def self.register(lego)
145
+ lego.add_plugin :router, self
146
+ end
147
+
148
+ def another_routehandler
149
+ add_route(:get, {})
150
+ end
151
+
152
+ def self.match_route(route, env); end
153
+ end
154
+
155
+ # Create two fake plugins
156
+ Object.const_set(:App1Plug, GlobalPlug.clone)
157
+ Object.const_set(:App2Plug, GlobalPlug.clone)
158
+
159
+ Lego.plugin GlobalPlug
160
+
161
+ create_new_app("MyApp1", Lego::Controller)
162
+ create_new_app("MyApp2", Lego::Controller)
163
+
164
+ MyApp1.plugin App1Plug
165
+ MyApp2.plugin App2Plug
166
+
167
+ Lego::Controller::RouteHandler.matchers.should eql([GlobalPlug])
168
+ MyApp1::RouteHandler.matchers.should eql([GlobalPlug, App1Plug])
169
+ MyApp2::RouteHandler.matchers.should eql([GlobalPlug, App2Plug])
170
+ end
171
+
172
+ after do
173
+ rm_const "GlobalPlug", "App1Plug", "App2Plug", "MyApp1", "MyApp2"
174
+ end
175
+ end
176
+
177
+ end
178
+
179
+ def empty_route_handler
180
+ route_handler = Lego::Controller::RouteHandler.clone
181
+ route_handler.class_eval "remove_instance_variable :@route_cache if @route_cache"
182
+ route_handler.class_eval "remove_instance_variable :@matcher_cache if @matcher_cache"
183
+ route_handler
184
+ end
185
+
186
+
187
+
188
+
@@ -0,0 +1,297 @@
1
+ require File.join('spec', '/spec_helper')
2
+
3
+ describe Lego::Controller do
4
+
5
+ it 'should contain an ActionContext Class' do
6
+ Lego::Controller::ActionContext.should be_kind_of(Class)
7
+ end
8
+
9
+ it 'should contain an RouteHandler Module' do
10
+ Lego::Controller::RouteHandler.should be_kind_of(Module)
11
+ end
12
+
13
+ it 'should load Lego::Plugin::Controller::NotFound by default' do
14
+ Lego::Controller.methods.should include('not_found')
15
+ end
16
+
17
+ context 'when inherited' do
18
+ before do
19
+ create_new_app("MyController", Lego::Controller)
20
+ end
21
+
22
+ it 'should create a new ActionContext for the inheriting class' do
23
+ MyController::ActionContext.object_id.should_not == Lego::Controller::ActionContext.object_id
24
+ end
25
+
26
+ it 'should setup a constant on ActionContext holding a reference to the application class' do
27
+ MyController::ActionContext::ApplicationClass.should eql(MyController)
28
+ end
29
+
30
+ it 'should create a new RouteHandler for the inheriting class' do
31
+ MyController::RouteHandler.object_id.should_not == Lego::Controller::RouteHandler.object_id
32
+ end
33
+
34
+ it 'should create a new Config for the inheriting class' do
35
+ MyController::Config.object_id.should_not == Lego::Controller::Config.object_id
36
+ end
37
+
38
+ it 'should create a new Config for every inheriting class' do
39
+ create_new_app "MyOtherController", Lego::Controller
40
+ MyController::Config.object_id.should_not == MyOtherController::Config.object_id
41
+ end
42
+ end
43
+
44
+ context '.plugin <plugin_module>' do
45
+ before do
46
+ create_new_app("MyApp", Lego::Controller)
47
+ module MyPlugin
48
+ def self.register(lego)
49
+ lego.register self
50
+ end
51
+ end
52
+ end
53
+
54
+ after do
55
+ rm_const "MyPlugin", "MyApp"
56
+ end
57
+
58
+ it 'should have a class method named plugin' do
59
+ MyApp.should respond_to(:plugin)
60
+ end
61
+
62
+ it 'should call self.register on <plugin_module>' do
63
+ MyPlugin.should_receive(:register).with(MyApp)
64
+ MyApp.plugin MyPlugin
65
+ end
66
+ end
67
+
68
+ context '.add_plugin :view, <plugin_module>' do
69
+ before do
70
+ create_new_app("MyApp", Lego::Controller)
71
+ module MyViewPlugin
72
+ def self.register(lego)
73
+ lego.add_plugin :view, self
74
+ end
75
+ def makebold(content)
76
+ "<b>#{content}</b>"
77
+ end
78
+ end
79
+ end
80
+
81
+ it 'should make plugin methods availibe to ActionContext' do
82
+ MyApp::ActionContext.instance_methods.should_not include('makebold')
83
+ MyApp.plugin MyViewPlugin
84
+ MyApp::ActionContext.instance_methods.should include('makebold')
85
+ end
86
+
87
+ after do
88
+ rm_const "MyViewPlugin", "MyApp"
89
+ end
90
+ end
91
+
92
+ context '.add_plugin :controller, <plugin_module>' do
93
+ before do
94
+ create_new_app("MyApp", Lego::Controller)
95
+ module MyPlugin2
96
+ def self.register(lego)
97
+ lego.add_plugin :controller, PluginMethods
98
+ end
99
+ module PluginMethods
100
+ def get_this;end
101
+ end
102
+ end
103
+ end
104
+
105
+ after do
106
+ rm_const "MyPlugin2", "MyApp"
107
+ end
108
+
109
+ it 'should extend controller with <plugin_module>' do
110
+ MyApp.should_not respond_to(:get_this)
111
+ MyApp.plugin MyPlugin2
112
+ MyApp.should respond_to(:get_this)
113
+ end
114
+ end
115
+
116
+ context '.add_route <method> <route>' do
117
+ before do
118
+ create_new_app("MyApp", Lego::Controller)
119
+ end
120
+
121
+ it 'should be defined' do
122
+ MyApp.should respond_to(:add_route)
123
+ end
124
+
125
+ it 'should add a route to RouteHandler' do
126
+ route = {:path => '/somewhere'}
127
+ method = :get
128
+ MyApp::RouteHandler.should_receive(:add_route).with(method, route)
129
+ MyApp.add_route(method, route)
130
+ end
131
+ after { rm_const 'MyApp' }
132
+ end
133
+
134
+ context '.add_plugin :router, <plugin_module>' do
135
+ before do
136
+ create_new_app("MyApp", Lego::Controller)
137
+ module MyRouter
138
+ def self.register(lego)
139
+ lego.add_plugin :router, RouterMethods
140
+ end
141
+ module RouterMethods
142
+ extend self
143
+ def match_route
144
+ end
145
+ end
146
+ end
147
+ end
148
+
149
+ after do
150
+ rm_const "MyRouter", "MyApp"
151
+ end
152
+
153
+ it 'should not extend controller with <plugin_module>' do
154
+ MyApp.plugin MyRouter
155
+ MyApp.should_not respond_to(:match_route)
156
+ end
157
+
158
+ it 'should call add_matcher on RouteHandler with <plugin_module>' do
159
+ MyApp::RouteHandler.should_receive(:add_matcher).with(MyRouter::RouterMethods)
160
+ MyApp.plugin MyRouter
161
+ end
162
+ end
163
+
164
+ context '.call <env>' do
165
+ context 'with a route that matches' do
166
+ before do
167
+ @env = ["Environment"]
168
+ create_new_app("MyApp", Lego::Controller)
169
+ MyApp::RouteHandler.should_receive(:match_all_routes).with(@env).and_return("route")
170
+ end
171
+
172
+ it 'should create a new instance of ActionContext' do
173
+ mock = mock("ActionContext instance")
174
+ mock.should_receive(:run).with("route", @env)
175
+ MyApp::ActionContext.should_receive(:new).and_return(mock)
176
+ end
177
+
178
+ after do
179
+ MyApp.call(@env)
180
+ rm_const "MyApp"
181
+ end
182
+ end
183
+
184
+ context 'with a route that don\'t matches' do
185
+ before do
186
+ @env = ["Environment"]
187
+ create_new_app("MyApp", Lego::Controller)
188
+ MyApp::RouteHandler.should_receive(:match_all_routes).with(@env).and_return(nil)
189
+ end
190
+
191
+ it 'should create a new instance of ActionContext' do
192
+ MyApp::ActionContext.should_not_receive(:new)
193
+ end
194
+
195
+ after do
196
+ MyApp.call(@env).should eql(
197
+ [404, {'Content-Type' => 'text/html'}, '404 - Not found']
198
+ )
199
+ rm_const "MyApp"
200
+ end
201
+ end
202
+
203
+ context 'without matching route and a :not_found route defined' do
204
+ before do
205
+ @env = ["Rack Env"]
206
+ @routes = { :not_found => {}}
207
+ create_new_app("MyApp", Lego::Controller)
208
+ MyApp::RouteHandler.should_receive(:match_all_routes).with(@env).and_return(nil)
209
+ MyApp::RouteHandler.should_receive(:routes).and_return( @routes )
210
+ end
211
+
212
+ it 'should create a new ActionContext with the :not_found route' do
213
+ action_context = mock("ActionContext instance")
214
+ MyApp::ActionContext.should_receive(:new).and_return(action_context)
215
+ action_context.should_receive(:run).with(@routes[:not_found], @env)
216
+ end
217
+
218
+ after do
219
+ MyApp.call(@env)
220
+ rm_const "MyApp"
221
+ end
222
+ end
223
+ end
224
+
225
+ context ".set" do
226
+ context 'on Lego::Controller' do
227
+
228
+ it "should proxy the method call to its own Config" do
229
+ Lego::Controller::Config.should_receive(:set).and_return(nil)
230
+ Lego::Controller.set :foo => "bar"
231
+ end
232
+ end
233
+
234
+ context "on subclasses" do
235
+
236
+ before do
237
+ create_new_app "MyApp", Lego::Controller
238
+ end
239
+
240
+ it "should proxy the method call to its own Confg" do
241
+ MyApp::Config.should_receive(:set).and_return(nil)
242
+ MyApp.set :foo => "bar"
243
+ end
244
+
245
+ after do
246
+ rm_const "MyApp"
247
+ end
248
+ end
249
+ end
250
+
251
+ context ".environment <env>" do
252
+
253
+ context 'on Lego::Controller' do
254
+
255
+ before do
256
+ @config_block = lambda {}
257
+ end
258
+
259
+ it 'should proxy the method call to its own config' do
260
+ Lego::Controller::Config.should_receive(:environment).with(nil, &@config_block).and_return(nil)
261
+ Lego::Controller.environment(&@config_block)
262
+ end
263
+
264
+ it 'take an optional <env> argument' do
265
+ Lego::Controller::Config.should_receive(:environment).
266
+ with('development', &@config_block).
267
+ and_return(nil)
268
+
269
+ Lego::Controller.environment('development', &@config_block)
270
+ end
271
+
272
+ it 'should raise an ArgumentError if no block is provided' do
273
+ lambda {
274
+ Lego::Controller.environment(:development)
275
+ }.should raise_error(ArgumentError, "No block provided")
276
+ end
277
+ end
278
+
279
+ context 'on subclasses' do
280
+
281
+ before do
282
+ create_new_app "MyApp", Lego::Controller
283
+ @config_block = lambda {}
284
+ end
285
+
286
+ it 'should proxy the method call to its own config' do
287
+ MyApp::Config.should_receive(:environment).with(nil, &@config_block).and_return(nil)
288
+ MyApp.environment(&@config_block)
289
+ end
290
+
291
+ after do
292
+ rm_const "MyApp"
293
+ end
294
+ end
295
+ end
296
+ end
297
+