pendragon 0.6.2 → 1.0.0

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.
@@ -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