pendragon 0.6.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,4 @@
1
1
 
2
2
  module Pendragon
3
- VERSION = '0.6.2'
3
+ VERSION = '1.0.0'
4
4
  end
@@ -11,10 +11,5 @@ Gem::Specification.new "pendragon", Pendragon::VERSION do |s|
11
11
  s.license = "MIT"
12
12
 
13
13
  s.add_dependency "rack", ">= 1.3.0"
14
- s.add_dependency "mustermann19", "~> 0.3.0"
15
- s.add_development_dependency "rake", ">= 0.8.7"
16
- s.add_development_dependency "rack-test", ">= 0.5.0"
17
- s.add_development_dependency "mocha", ">= 0.10.0"
18
- s.add_development_dependency "haml"
19
- s.add_development_dependency "padrino", "~> 0.12.2"
14
+ s.add_dependency "mustermann"
20
15
  end
@@ -1,92 +1,17 @@
1
1
  require 'bundler/setup'
2
- ENV['PADRINO_ENV'] = 'test'
3
- PADRINO_ROOT = File.dirname(__FILE__) unless defined?(PADRINO_ROOT)
4
- require File.expand_path('../../lib/pendragon', __FILE__)
2
+ require File.expand_path('../lib/pendragon', __dir__)
3
+ require File.expand_path('../lib/pendragon/realism', __dir__)
4
+ require File.expand_path('../lib/pendragon/linear', __dir__)
5
5
 
6
- require 'minitest/autorun'
7
- require 'minitest/spec'
6
+ Bundler.require(:default)
7
+
8
+ require 'test/unit'
8
9
  require 'mocha/setup'
9
- require 'padrino-core'
10
- require 'padrino/rendering'
11
10
  require 'rack'
12
11
  require 'rack/test'
13
12
 
14
- begin
15
- require 'ruby-debug'
16
- rescue LoadError; end
17
-
18
- class Sinatra::Base
19
- include MiniTest::Assertions
13
+ module Supports
20
14
  end
21
15
 
22
- class MiniTest::Spec
23
- include Rack::Test::Methods
24
-
25
- def pendragon(&block)
26
- if !block_given? && defined?(ENABLE_COMPILER)
27
- block = Proc.new do |config|
28
- config.enable_compiler = true
29
- end
30
- end
31
- @app = Pendragon.new(&block)
32
- end
33
-
34
- def mock_app(base = nil, &block)
35
- @app = Sinatra.new(base || ::Padrino::Application, &block)
36
- @app.class_eval{ set :pendragon, :enable_compiler => defined?(ENABLE_COMPILER) }
37
- end
38
-
39
- def app
40
- Rack::Lint.new(@app)
41
- end
42
-
43
- def method_missing(name, *args, &block)
44
- if response && response.respond_to?(name)
45
- response.send(name, *args, &block)
46
- else
47
- super(name, *args, &block)
48
- end
49
- rescue Rack::Test::Error # no response yet
50
- super(name, *args, &block)
51
- end
52
- alias response last_response
53
-
54
- class << self
55
- alias :setup :before unless defined?(Rails)
56
- alias :teardown :after unless defined?(Rails)
57
- alias :should :it
58
- alias :context :describe
59
- def should_eventually(desc)
60
- it("should eventually #{desc}") { skip("Should eventually #{desc}") }
61
- end
62
- end
63
- alias :assert_no_match :refute_match
64
- alias :assert_not_nil :refute_nil
65
- alias :assert_not_equal :refute_equal
66
- end
67
-
68
-
69
- if defined?(MiniTest::Unit.output)
70
- class ColoredIO
71
- def initialize(io)
72
- @io = io
73
- end
74
-
75
- def print(o)
76
- case o
77
- when "." then @io.send(:print, o.colorize(:green))
78
- when "E" then @io.send(:print, o.colorize(:red))
79
- when "F" then @io.send(:print, o.colorize(:yellow))
80
- when "S" then @io.send(:print, o.colorize(:magenta))
81
- else @io.send(:print, o)
82
- end
83
- end
84
-
85
- def puts(*o)
86
- super
87
- end
88
- end
89
- MiniTest::Unit.output = ColoredIO.new($stdout)
90
- else
91
- require 'minitest/pride'
92
- end
16
+ $:.unshift(File.expand_path('..', __dir__))
17
+ Dir.glob('test/supports/*.rb').each(&method(:require))
@@ -0,0 +1,6 @@
1
+ require File.expand_path('../helper', __dir__)
2
+
3
+ class TestLinear < Test::Unit::TestCase
4
+ include Supports::SharedExamplesForRouting
5
+ router_class Pendragon::Linear
6
+ end
@@ -0,0 +1,6 @@
1
+ require File.expand_path('../helper', __dir__)
2
+
3
+ class TestRealism < Test::Unit::TestCase
4
+ include Supports::SharedExamplesForRouting
5
+ router_class Pendragon::Realism
6
+ end
@@ -0,0 +1,277 @@
1
+ require 'json'
2
+
3
+ module Supports::SharedExamplesForRouting
4
+ extend Modulla
5
+ include Rack::Test::Methods
6
+
7
+ module ClassMethods
8
+ def router_class(klass)
9
+ define_method(:router) { klass }
10
+ end
11
+
12
+ def disable(*features)
13
+ features.each do |feature|
14
+ define_method('%p disabled' % feature) {}
15
+ end
16
+ end
17
+ end
18
+
19
+ alias_method :response, :last_response
20
+
21
+ def disabled?(feature)
22
+ respond_to?('%p disabled' % feature)
23
+ end
24
+
25
+ def mock_env_for(path = ?/, **options)
26
+ Rack::MockRequest.env_for(path, **options)
27
+ end
28
+
29
+ def mock_app(base = nil, &block)
30
+ @app = router.new(&block)
31
+ end
32
+
33
+ def app
34
+ Rack::Lint.new(@app)
35
+ end
36
+
37
+ def assert_response(status, body, headers = {})
38
+ assert { last_response.status == status }
39
+ assert { last_response.body == body }
40
+ headers.each_pair do |key, val|
41
+ assert { last_response.headers[key] == val }
42
+ end
43
+ end
44
+
45
+ sub_test_case '#call' do
46
+ test 'return response conformed rack format' do
47
+ assert_nothing_raised do
48
+ Rack::Lint.new(router.new).call(mock_env_for)
49
+ end
50
+ end
51
+ end
52
+
53
+ sub_test_case 'default response' do
54
+ setup { mock_app { } }
55
+ test 'return default response if given request does not match with any routes' do
56
+ get ?/
57
+ assert_response 404, 'not found', 'Content-Type' => 'text/plain'
58
+ end
59
+ end
60
+
61
+ sub_test_case 'basic' do
62
+ setup do
63
+ mock_app do
64
+ get(?/) { [200, {}, ['hello']] }
65
+ end
66
+ end
67
+ test 'return response if given request matches with any routes' do
68
+ get ?/
69
+ assert_response 200, 'hello'
70
+ end
71
+ end
72
+
73
+ sub_test_case 'duck typing' do
74
+ setup do
75
+ _lambda = -> { [200, {}, ['lambda']] }
76
+ rack_app_class = Class.new {
77
+ def call(env)
78
+ [200, {}, ['rackapp']]
79
+ end
80
+ }
81
+ mock_app do
82
+ get '/lambda', to: _lambda
83
+ get '/rack_app', to: rack_app_class.new
84
+ end
85
+ end
86
+
87
+ test 'duck typing for lambda' do
88
+ get '/lambda'
89
+ assert_response 200, 'lambda'
90
+ end
91
+
92
+ test 'duck typing for rack app' do
93
+ get '/rack_app'
94
+ assert_response 200, 'rackapp'
95
+ end
96
+ end
97
+
98
+ sub_test_case 'namespacing' do
99
+ setup do
100
+ mock_app do
101
+ namespace :foo do
102
+ get('/123') { [200, {}, ['hey']] }
103
+ end
104
+ end
105
+ end
106
+
107
+ test 'append given namespace as a prefix' do
108
+ get '/foo/123'
109
+ assert_response 200, 'hey'
110
+ end
111
+ end
112
+
113
+ sub_test_case 'nested namespacing' do
114
+ setup do
115
+ mock_app do
116
+ namespace :foo do
117
+ get('/') { [200, {}, ['foo']] }
118
+ namespace :bar do
119
+ get('/') { [200, {}, ['bar']] }
120
+ namespace :baz do
121
+ get('/') { [200, {}, ['baz']] }
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
127
+
128
+ test 'append given namespace as a prefix' do
129
+ get '/foo/'
130
+ assert_response 200, 'foo'
131
+ get '/foo/bar/'
132
+ assert_response 200, 'bar'
133
+ get '/foo/bar/baz/'
134
+ assert_response 200, 'baz'
135
+ end
136
+ end
137
+
138
+ sub_test_case 'complex routing' do
139
+ setup do
140
+ mock_app do
141
+ 1000.times do |n|
142
+ [:get, :post, :put, :delete, :options].each do |verb|
143
+ public_send(verb, "/#{n}") { [200, {}, ["#{verb} #{n}"]] }
144
+ end
145
+ end
146
+ end
147
+ end
148
+
149
+ test 'recognize a route correctly' do
150
+ put '/376'
151
+ assert_response 200, 'put 376'
152
+ end
153
+
154
+ test 'recognize a route correctly (part 2)' do
155
+ delete '/999'
156
+ assert_response 200, 'delete 999'
157
+ end
158
+ end
159
+
160
+ sub_test_case 'method not allowed' do
161
+ setup do
162
+ mock_app do
163
+ get '/testing' do
164
+ [200, {}, ['hello testing']]
165
+ end
166
+ end
167
+ end
168
+
169
+ test 'returns 405 if given method is not allowed' do
170
+ post '/testing'
171
+ assert_response 405, 'method not allowed', { 'Allows' => 'GET' }
172
+ end
173
+ end
174
+
175
+ sub_test_case 'block arguments' do
176
+ setup do
177
+ mock_app do
178
+ get '/foo/:name/*/*' do |name, a, b|
179
+ body = "#{name}, #{a}, #{b}"
180
+ [200, {}, [body]]
181
+ end
182
+ end
183
+ end
184
+
185
+ test 'gets params as block parameters' do
186
+ omit_if disabled?(:multiple_splats)
187
+ get '/foo/yoman/1234/5678'
188
+ assert_response 200, 'yoman, 1234, 5678'
189
+ end
190
+ end
191
+
192
+ sub_test_case '#params' do
193
+ setup do
194
+ mock_app do
195
+ get '/foo/:name/*/*' do
196
+ body = params.to_json
197
+ [200, {}, [body]]
198
+ end
199
+ end
200
+ end
201
+
202
+ test 'gets params correctly' do
203
+ omit_if disabled?(:multiple_splats)
204
+ get '/foo/heyman/1234/5678'
205
+ assert_response 200, {name: 'heyman', splat: ['1234', '5678']}.to_json
206
+ end
207
+ end
208
+
209
+ sub_test_case 'capturing' do
210
+ setup do
211
+ mock_app do
212
+ get '/users/:name/articles/:article_id' do
213
+ [200, {}, [captures.join(' ')]]
214
+ end
215
+ end
216
+ end
217
+
218
+ test 'gets captures correctly' do
219
+ get '/users/namusyaka/articles/1234'
220
+ assert_response 200, 'namusyaka 1234'
221
+ end
222
+ end
223
+
224
+ sub_test_case 'splat' do
225
+ sub_test_case 'multiple splats' do
226
+ setup do
227
+ mock_app do
228
+ get '/splatting/*/*/*' do |a, b, c|
229
+ [200, {}, ["captures: #{captures.join(' ')}, block: #{a} #{b} #{c}"]]
230
+ end
231
+ end
232
+ end
233
+
234
+ test 'gets multiple splats correctly' do
235
+ omit_if disabled?(:multiple_splats)
236
+ get '/splatting/1234/5678/90'
237
+ assert_response 200, 'captures: 1234 5678 90, block: 1234 5678 90'
238
+ end
239
+ end
240
+ end
241
+
242
+ sub_test_case 'cascading' do
243
+ setup do
244
+ mock_app do
245
+ get '/cascading' do
246
+ [200, { 'X-Cascade' => 'pass' }, ['']]
247
+ end
248
+
249
+ get '/cascading' do
250
+ [200, {}, ['yay']]
251
+ end
252
+ end
253
+ end
254
+
255
+ test 'succeeds to cascading' do
256
+ omit_if disabled?(:cascading)
257
+ get '/cascading'
258
+ assert_response 200, 'yay'
259
+ end
260
+ end
261
+
262
+ sub_test_case 'halting' do
263
+ setup do
264
+ mock_app do
265
+ get ?/ do
266
+ throw :halt, [404, {}, ['not found']]
267
+ [200, {}, ['failed to halt']]
268
+ end
269
+ end
270
+ end
271
+
272
+ test 'succeeds to halting' do
273
+ get ?/
274
+ assert_response 404, 'not found'
275
+ end
276
+ end
277
+ end
@@ -0,0 +1,40 @@
1
+ require File.expand_path('helper', __dir__)
2
+
3
+ class TestRouter < Test::Unit::TestCase
4
+ attr_accessor :router
5
+
6
+ setup { self.router = Pendragon::Router.new }
7
+
8
+ sub_test_case '#call' do
9
+ setup do
10
+ @mock_request = Rack::MockRequest.env_for(?/)
11
+ router.get(?/) { 'hello' }
12
+ end
13
+
14
+ test 'should recognize a route inside #with_block' do
15
+ router.expects(:with_optimization)
16
+ router.call(@mock_request)
17
+ end
18
+
19
+ test 'raises NotImplementedError' do
20
+ assert_raise NotImplementedError do
21
+ router.call(@mock_request)
22
+ end
23
+ end
24
+
25
+ sub_test_case 'without matched route' do
26
+ end
27
+ end
28
+
29
+ %w[get post put delete head options].each do |request_method|
30
+ sub_test_case "##{request_method}" do
31
+ setup { @expected_block = Proc.new {} }
32
+ test "should append #{request_method} route correctly" do
33
+ router.public_send(request_method, ?/, &@expected_block)
34
+ actual = router.map[request_method.upcase].first
35
+ assert { actual.request_method == request_method.upcase }
36
+ assert { actual.path == ?/ }
37
+ end
38
+ end
39
+ end
40
+ end