devcenter 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.
Files changed (192) hide show
  1. data/.gitignore +18 -0
  2. data/Gemfile +8 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +39 -0
  5. data/Rakefile +2 -0
  6. data/bin/devcenter +7 -0
  7. data/devcenter.gemspec +30 -0
  8. data/lib/devcenter.rb +6 -0
  9. data/lib/devcenter/cli.rb +45 -0
  10. data/lib/devcenter/coderay_extensions.rb +70 -0
  11. data/lib/devcenter/commands.rb +4 -0
  12. data/lib/devcenter/commands/base.rb +47 -0
  13. data/lib/devcenter/commands/open.rb +34 -0
  14. data/lib/devcenter/commands/preview.rb +28 -0
  15. data/lib/devcenter/commands/pull.rb +37 -0
  16. data/lib/devcenter/helpers.rb +41 -0
  17. data/lib/devcenter/layout.html +299 -0
  18. data/lib/devcenter/md_parser.rb +87 -0
  19. data/lib/devcenter/previewer.rb +36 -0
  20. data/lib/devcenter/previewer/assets/images/public/article-icon-large.png +0 -0
  21. data/lib/devcenter/previewer/assets/images/public/article-icon.png +0 -0
  22. data/lib/devcenter/previewer/assets/images/public/aside_accordion_indicator_default.png +0 -0
  23. data/lib/devcenter/previewer/assets/images/public/aside_accordion_indicator_open.png +0 -0
  24. data/lib/devcenter/previewer/assets/images/public/body_bg.png +0 -0
  25. data/lib/devcenter/previewer/assets/images/public/callout_bg.png +0 -0
  26. data/lib/devcenter/previewer/assets/images/public/feed-icon-sprite.png +0 -0
  27. data/lib/devcenter/previewer/assets/images/public/heroku-header-logo-mobile.png +0 -0
  28. data/lib/devcenter/previewer/assets/images/public/heroku-header-logo.png +0 -0
  29. data/lib/devcenter/previewer/assets/images/public/heroku-logo.png +0 -0
  30. data/lib/devcenter/previewer/assets/images/public/icon_sprite_16.png +0 -0
  31. data/lib/devcenter/previewer/assets/images/public/index_li_bullet.png +0 -0
  32. data/lib/devcenter/previewer/assets/images/public/intro_bg.png +0 -0
  33. data/lib/devcenter/previewer/assets/images/public/jive_discussion_arrow.png +0 -0
  34. data/lib/devcenter/previewer/assets/images/public/jive_discussion_glyph.png +0 -0
  35. data/lib/devcenter/previewer/assets/images/public/line.png +0 -0
  36. data/lib/devcenter/previewer/assets/images/public/pre_code_background.png +0 -0
  37. data/lib/devcenter/previewer/assets/images/public/search-icon.png +0 -0
  38. data/lib/devcenter/previewer/assets/images/public/search_glyph.png +0 -0
  39. data/lib/devcenter/previewer/assets/images/public/search_return.png +0 -0
  40. data/lib/devcenter/previewer/assets/images/public/tag-icon-large.png +0 -0
  41. data/lib/devcenter/previewer/assets/images/public/toc-icon.png +0 -0
  42. data/lib/devcenter/previewer/assets/public.css +2125 -0
  43. data/lib/devcenter/previewer/assets/public/article-icon-large.png +0 -0
  44. data/lib/devcenter/previewer/assets/public/article-icon.png +0 -0
  45. data/lib/devcenter/previewer/assets/public/aside_accordion_indicator_default.png +0 -0
  46. data/lib/devcenter/previewer/assets/public/aside_accordion_indicator_open.png +0 -0
  47. data/lib/devcenter/previewer/assets/public/body_bg.png +0 -0
  48. data/lib/devcenter/previewer/assets/public/callout_bg.png +0 -0
  49. data/lib/devcenter/previewer/assets/public/feed-icon-sprite.png +0 -0
  50. data/lib/devcenter/previewer/assets/public/heroku-header-logo-mobile.png +0 -0
  51. data/lib/devcenter/previewer/assets/public/heroku-header-logo.png +0 -0
  52. data/lib/devcenter/previewer/assets/public/heroku-logo.png +0 -0
  53. data/lib/devcenter/previewer/assets/public/icon_sprite_16.png +0 -0
  54. data/lib/devcenter/previewer/assets/public/index_li_bullet.png +0 -0
  55. data/lib/devcenter/previewer/assets/public/intro_bg.png +0 -0
  56. data/lib/devcenter/previewer/assets/public/jive_discussion_arrow.png +0 -0
  57. data/lib/devcenter/previewer/assets/public/jive_discussion_glyph.png +0 -0
  58. data/lib/devcenter/previewer/assets/public/line.png +0 -0
  59. data/lib/devcenter/previewer/assets/public/pre_code_background.png +0 -0
  60. data/lib/devcenter/previewer/assets/public/public.css +2125 -0
  61. data/lib/devcenter/previewer/assets/public/search-icon.png +0 -0
  62. data/lib/devcenter/previewer/assets/public/search_glyph.png +0 -0
  63. data/lib/devcenter/previewer/assets/public/search_return.png +0 -0
  64. data/lib/devcenter/previewer/assets/public/tag-icon-large.png +0 -0
  65. data/lib/devcenter/previewer/assets/public/toc-icon.png +0 -0
  66. data/lib/devcenter/previewer/file_listener.rb +23 -0
  67. data/lib/devcenter/previewer/views/article.erb +345 -0
  68. data/lib/devcenter/previewer/web_app.rb +53 -0
  69. data/lib/devcenter/previewer/web_server.rb +29 -0
  70. data/lib/devcenter/version.rb +3 -0
  71. data/vendor/sinatra/.gitignore +6 -0
  72. data/vendor/sinatra/.travis.yml +16 -0
  73. data/vendor/sinatra/.yardopts +4 -0
  74. data/vendor/sinatra/AUTHORS +61 -0
  75. data/vendor/sinatra/Gemfile +91 -0
  76. data/vendor/sinatra/LICENSE +22 -0
  77. data/vendor/sinatra/README.de.rdoc +2116 -0
  78. data/vendor/sinatra/README.es.rdoc +2106 -0
  79. data/vendor/sinatra/README.fr.rdoc +2133 -0
  80. data/vendor/sinatra/README.hu.rdoc +608 -0
  81. data/vendor/sinatra/README.jp.rdoc +1056 -0
  82. data/vendor/sinatra/README.ko.rdoc +1932 -0
  83. data/vendor/sinatra/README.pt-br.rdoc +778 -0
  84. data/vendor/sinatra/README.pt-pt.rdoc +647 -0
  85. data/vendor/sinatra/README.rdoc +2049 -0
  86. data/vendor/sinatra/README.ru.rdoc +2033 -0
  87. data/vendor/sinatra/README.zh.rdoc +1816 -0
  88. data/vendor/sinatra/Rakefile +182 -0
  89. data/vendor/sinatra/examples/chat.rb +61 -0
  90. data/vendor/sinatra/examples/simple.rb +3 -0
  91. data/vendor/sinatra/examples/stream.ru +26 -0
  92. data/vendor/sinatra/lib/sinatra.rb +5 -0
  93. data/vendor/sinatra/lib/sinatra/base.rb +1820 -0
  94. data/vendor/sinatra/lib/sinatra/images/404.png +0 -0
  95. data/vendor/sinatra/lib/sinatra/images/500.png +0 -0
  96. data/vendor/sinatra/lib/sinatra/main.rb +30 -0
  97. data/vendor/sinatra/lib/sinatra/showexceptions.rb +345 -0
  98. data/vendor/sinatra/lib/sinatra/version.rb +3 -0
  99. data/vendor/sinatra/sinatra.gemspec +18 -0
  100. data/vendor/sinatra/test/base_test.rb +172 -0
  101. data/vendor/sinatra/test/builder_test.rb +91 -0
  102. data/vendor/sinatra/test/coffee_test.rb +90 -0
  103. data/vendor/sinatra/test/compile_test.rb +139 -0
  104. data/vendor/sinatra/test/contest.rb +98 -0
  105. data/vendor/sinatra/test/creole_test.rb +65 -0
  106. data/vendor/sinatra/test/delegator_test.rb +160 -0
  107. data/vendor/sinatra/test/encoding_test.rb +20 -0
  108. data/vendor/sinatra/test/erb_test.rb +98 -0
  109. data/vendor/sinatra/test/extensions_test.rb +98 -0
  110. data/vendor/sinatra/test/filter_test.rb +437 -0
  111. data/vendor/sinatra/test/haml_test.rb +91 -0
  112. data/vendor/sinatra/test/helper.rb +123 -0
  113. data/vendor/sinatra/test/helpers_test.rb +1768 -0
  114. data/vendor/sinatra/test/integration/app.rb +62 -0
  115. data/vendor/sinatra/test/integration_helper.rb +222 -0
  116. data/vendor/sinatra/test/integration_test.rb +87 -0
  117. data/vendor/sinatra/test/less_test.rb +69 -0
  118. data/vendor/sinatra/test/liquid_test.rb +59 -0
  119. data/vendor/sinatra/test/mapped_error_test.rb +305 -0
  120. data/vendor/sinatra/test/markaby_test.rb +80 -0
  121. data/vendor/sinatra/test/markdown_test.rb +82 -0
  122. data/vendor/sinatra/test/middleware_test.rb +68 -0
  123. data/vendor/sinatra/test/nokogiri_test.rb +67 -0
  124. data/vendor/sinatra/test/public/favicon.ico +0 -0
  125. data/vendor/sinatra/test/rabl_test.rb +89 -0
  126. data/vendor/sinatra/test/rack_test.rb +45 -0
  127. data/vendor/sinatra/test/radius_test.rb +59 -0
  128. data/vendor/sinatra/test/rdoc_test.rb +66 -0
  129. data/vendor/sinatra/test/readme_test.rb +120 -0
  130. data/vendor/sinatra/test/request_test.rb +45 -0
  131. data/vendor/sinatra/test/response_test.rb +64 -0
  132. data/vendor/sinatra/test/result_test.rb +76 -0
  133. data/vendor/sinatra/test/route_added_hook_test.rb +59 -0
  134. data/vendor/sinatra/test/routing_test.rb +1175 -0
  135. data/vendor/sinatra/test/sass_test.rb +116 -0
  136. data/vendor/sinatra/test/scss_test.rb +89 -0
  137. data/vendor/sinatra/test/server_test.rb +48 -0
  138. data/vendor/sinatra/test/settings_test.rb +561 -0
  139. data/vendor/sinatra/test/sinatra_test.rb +12 -0
  140. data/vendor/sinatra/test/slim_test.rb +84 -0
  141. data/vendor/sinatra/test/static_test.rb +219 -0
  142. data/vendor/sinatra/test/streaming_test.rb +149 -0
  143. data/vendor/sinatra/test/templates_test.rb +333 -0
  144. data/vendor/sinatra/test/textile_test.rb +65 -0
  145. data/vendor/sinatra/test/views/a/in_a.str +1 -0
  146. data/vendor/sinatra/test/views/ascii.erb +2 -0
  147. data/vendor/sinatra/test/views/b/in_b.str +1 -0
  148. data/vendor/sinatra/test/views/calc.html.erb +1 -0
  149. data/vendor/sinatra/test/views/error.builder +3 -0
  150. data/vendor/sinatra/test/views/error.erb +3 -0
  151. data/vendor/sinatra/test/views/error.haml +3 -0
  152. data/vendor/sinatra/test/views/error.sass +2 -0
  153. data/vendor/sinatra/test/views/explicitly_nested.str +1 -0
  154. data/vendor/sinatra/test/views/foo/hello.test +1 -0
  155. data/vendor/sinatra/test/views/hello.builder +1 -0
  156. data/vendor/sinatra/test/views/hello.coffee +1 -0
  157. data/vendor/sinatra/test/views/hello.creole +1 -0
  158. data/vendor/sinatra/test/views/hello.erb +1 -0
  159. data/vendor/sinatra/test/views/hello.haml +1 -0
  160. data/vendor/sinatra/test/views/hello.less +5 -0
  161. data/vendor/sinatra/test/views/hello.liquid +1 -0
  162. data/vendor/sinatra/test/views/hello.mab +1 -0
  163. data/vendor/sinatra/test/views/hello.md +1 -0
  164. data/vendor/sinatra/test/views/hello.nokogiri +1 -0
  165. data/vendor/sinatra/test/views/hello.rabl +2 -0
  166. data/vendor/sinatra/test/views/hello.radius +1 -0
  167. data/vendor/sinatra/test/views/hello.rdoc +1 -0
  168. data/vendor/sinatra/test/views/hello.sass +2 -0
  169. data/vendor/sinatra/test/views/hello.scss +3 -0
  170. data/vendor/sinatra/test/views/hello.slim +1 -0
  171. data/vendor/sinatra/test/views/hello.str +1 -0
  172. data/vendor/sinatra/test/views/hello.test +1 -0
  173. data/vendor/sinatra/test/views/hello.textile +1 -0
  174. data/vendor/sinatra/test/views/hello.wlang +1 -0
  175. data/vendor/sinatra/test/views/hello.yajl +1 -0
  176. data/vendor/sinatra/test/views/layout2.builder +3 -0
  177. data/vendor/sinatra/test/views/layout2.erb +2 -0
  178. data/vendor/sinatra/test/views/layout2.haml +2 -0
  179. data/vendor/sinatra/test/views/layout2.liquid +2 -0
  180. data/vendor/sinatra/test/views/layout2.mab +2 -0
  181. data/vendor/sinatra/test/views/layout2.nokogiri +3 -0
  182. data/vendor/sinatra/test/views/layout2.rabl +3 -0
  183. data/vendor/sinatra/test/views/layout2.radius +2 -0
  184. data/vendor/sinatra/test/views/layout2.slim +3 -0
  185. data/vendor/sinatra/test/views/layout2.str +2 -0
  186. data/vendor/sinatra/test/views/layout2.test +1 -0
  187. data/vendor/sinatra/test/views/layout2.wlang +2 -0
  188. data/vendor/sinatra/test/views/nested.str +1 -0
  189. data/vendor/sinatra/test/views/utf8.erb +2 -0
  190. data/vendor/sinatra/test/wlang_test.rb +70 -0
  191. data/vendor/sinatra/test/yajl_test.rb +86 -0
  192. metadata +414 -0
@@ -0,0 +1,160 @@
1
+ require File.expand_path('../helper', __FILE__)
2
+
3
+ class DelegatorTest < Test::Unit::TestCase
4
+ class Mirror
5
+ attr_reader :last_call
6
+ def method_missing(*a, &b)
7
+ @last_call = [*a.map(&:to_s)]
8
+ @last_call << b if b
9
+ end
10
+ end
11
+
12
+ def self.delegates(name)
13
+ it "delegates #{name}" do
14
+ m = mirror { send name }
15
+ assert_equal [name.to_s], m.last_call
16
+ end
17
+
18
+ it "delegates #{name} with arguments" do
19
+ m = mirror { send name, "foo", "bar" }
20
+ assert_equal [name.to_s, "foo", "bar"], m.last_call
21
+ end
22
+
23
+ it "delegates #{name} with block" do
24
+ block = proc { }
25
+ m = mirror { send(name, &block) }
26
+ assert_equal [name.to_s, block], m.last_call
27
+ end
28
+ end
29
+
30
+ setup do
31
+ @target_was = Sinatra::Delegator.target
32
+ end
33
+
34
+ def teardown
35
+ Sinatra::Delegator.target = @target_was
36
+ end
37
+
38
+ def delegation_app(&block)
39
+ mock_app { Sinatra::Delegator.target = self }
40
+ delegate(&block)
41
+ end
42
+
43
+ def mirror(&block)
44
+ mirror = Mirror.new
45
+ Sinatra::Delegator.target = mirror
46
+ delegate(&block)
47
+ end
48
+
49
+ def delegate(&block)
50
+ assert Sinatra::Delegator.target != Sinatra::Application
51
+ Object.new.extend(Sinatra::Delegator).instance_eval(&block) if block
52
+ Sinatra::Delegator.target
53
+ end
54
+
55
+ def target
56
+ Sinatra::Delegator.target
57
+ end
58
+
59
+ it 'defaults to Sinatra::Application as target' do
60
+ assert_equal Sinatra::Application, Sinatra::Delegator.target
61
+ end
62
+
63
+ %w[get put post delete options patch].each do |verb|
64
+ it "delegates #{verb} correctly" do
65
+ delegation_app do
66
+ send(verb, '/hello') { 'Hello World' }
67
+ end
68
+
69
+ request = Rack::MockRequest.new(@app)
70
+ response = request.request(verb.upcase, '/hello', {})
71
+ assert response.ok?
72
+ assert_equal 'Hello World', response.body
73
+ end
74
+ end
75
+
76
+ it "delegates head correctly" do
77
+ delegation_app do
78
+ head '/hello' do
79
+ response['X-Hello'] = 'World!'
80
+ 'remove me'
81
+ end
82
+ end
83
+
84
+ request = Rack::MockRequest.new(@app)
85
+ response = request.request('HEAD', '/hello', {})
86
+ assert response.ok?
87
+ assert_equal 'World!', response['X-Hello']
88
+ assert_equal '', response.body
89
+ end
90
+
91
+ it "registers extensions with the delegation target" do
92
+ app, mixin = mirror, Module.new
93
+ Sinatra.register mixin
94
+ assert_equal ["register", mixin.to_s], app.last_call
95
+ end
96
+
97
+ it "registers helpers with the delegation target" do
98
+ app, mixin = mirror, Module.new
99
+ Sinatra.helpers mixin
100
+ assert_equal ["helpers", mixin.to_s], app.last_call
101
+ end
102
+
103
+ it "registers middleware with the delegation target" do
104
+ app, mixin = mirror, Module.new
105
+ Sinatra.use mixin
106
+ assert_equal ["use", mixin.to_s], app.last_call
107
+ end
108
+
109
+ it "should work with method_missing proxies for options" do
110
+ mixin = Module.new do
111
+ def respond_to?(method, *)
112
+ method.to_sym == :options or super
113
+ end
114
+
115
+ def method_missing(method, *args, &block)
116
+ return super unless method.to_sym == :options
117
+ {:some => :option}
118
+ end
119
+ end
120
+
121
+ value = nil
122
+ mirror do
123
+ extend mixin
124
+ value = options
125
+ end
126
+
127
+ assert_equal({:some => :option}, value)
128
+ end
129
+
130
+ it "delegates crazy method names" do
131
+ Sinatra::Delegator.delegate "foo:bar:"
132
+ method = mirror { send "foo:bar:" }.last_call.first
133
+ assert_equal "foo:bar:", method
134
+ end
135
+
136
+ delegates 'get'
137
+ delegates 'patch'
138
+ delegates 'put'
139
+ delegates 'post'
140
+ delegates 'delete'
141
+ delegates 'head'
142
+ delegates 'options'
143
+ delegates 'template'
144
+ delegates 'layout'
145
+ delegates 'before'
146
+ delegates 'after'
147
+ delegates 'error'
148
+ delegates 'not_found'
149
+ delegates 'configure'
150
+ delegates 'set'
151
+ delegates 'mime_type'
152
+ delegates 'enable'
153
+ delegates 'disable'
154
+ delegates 'use'
155
+ delegates 'development?'
156
+ delegates 'test?'
157
+ delegates 'production?'
158
+ delegates 'helpers'
159
+ delegates 'settings'
160
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: UTF-8
2
+ require File.expand_path('../helper', __FILE__)
3
+ require 'erb'
4
+
5
+ class BaseTest < Test::Unit::TestCase
6
+ setup do
7
+ @base = Sinatra.new(Sinatra::Base)
8
+ @base.set :views, File.dirname(__FILE__) + "/views"
9
+ end
10
+
11
+ it 'allows unicode strings in ascii templates per default (1.9)' do
12
+ next unless defined? Encoding
13
+ @base.new!.erb(File.read(@base.views + "/ascii.erb").encode("ASCII"), {}, :value => "åkej")
14
+ end
15
+
16
+ it 'allows ascii strings in unicode templates per default (1.9)' do
17
+ next unless defined? Encoding
18
+ @base.new!.erb(:utf8, {}, :value => "Some Lyrics".encode("ASCII"))
19
+ end
20
+ end
@@ -0,0 +1,98 @@
1
+ require File.expand_path('../helper', __FILE__)
2
+
3
+ class ERBTest < Test::Unit::TestCase
4
+ def engine
5
+ Tilt::ERBTemplate
6
+ end
7
+
8
+ def setup
9
+ Tilt.prefer engine, :erb
10
+ super
11
+ end
12
+
13
+ def erb_app(&block)
14
+ mock_app do
15
+ set :views, File.dirname(__FILE__) + '/views'
16
+ get('/', &block)
17
+ end
18
+ get '/'
19
+ end
20
+
21
+ it 'uses the correct engine' do
22
+ assert_equal engine, Tilt[:erb]
23
+ end
24
+
25
+ it 'renders inline ERB strings' do
26
+ erb_app { erb '<%= 1 + 1 %>' }
27
+ assert ok?
28
+ assert_equal '2', body
29
+ end
30
+
31
+ it 'renders .erb files in views path' do
32
+ erb_app { erb :hello }
33
+ assert ok?
34
+ assert_equal "Hello World\n", body
35
+ end
36
+
37
+ it 'takes a :locals option' do
38
+ erb_app do
39
+ locals = {:foo => 'Bar'}
40
+ erb '<%= foo %>', :locals => locals
41
+ end
42
+ assert ok?
43
+ assert_equal 'Bar', body
44
+ end
45
+
46
+ it "renders with inline layouts" do
47
+ mock_app do
48
+ layout { 'THIS. IS. <%= yield.upcase %>!' }
49
+ get('/') { erb 'Sparta' }
50
+ end
51
+ get '/'
52
+ assert ok?
53
+ assert_equal 'THIS. IS. SPARTA!', body
54
+ end
55
+
56
+ it "renders with file layouts" do
57
+ erb_app { erb 'Hello World', :layout => :layout2 }
58
+ assert ok?
59
+ assert_body "ERB Layout!\nHello World"
60
+ end
61
+
62
+ it "renders erb with blocks" do
63
+ mock_app do
64
+ def container
65
+ @_out_buf << "THIS."
66
+ yield
67
+ @_out_buf << "SPARTA!"
68
+ end
69
+ def is; "IS." end
70
+ get('/') { erb '<% container do %> <%= is %> <% end %>' }
71
+ end
72
+ get '/'
73
+ assert ok?
74
+ assert_equal 'THIS. IS. SPARTA!', body
75
+ end
76
+
77
+ it "can be used in a nested fashion for partials and whatnot" do
78
+ mock_app do
79
+ template(:inner) { "<inner><%= 'hi' %></inner>" }
80
+ template(:outer) { "<outer><%= erb :inner %></outer>" }
81
+ get('/') { erb :outer }
82
+ end
83
+
84
+ get '/'
85
+ assert ok?
86
+ assert_equal '<outer><inner>hi</inner></outer>', body
87
+ end
88
+ end
89
+
90
+
91
+ begin
92
+ require 'erubis'
93
+ class ErubisTest < ERBTest
94
+ def engine; Tilt::ErubisTemplate end
95
+ end
96
+ rescue LoadError
97
+ warn "#{$!.to_s}: skipping erubis tests"
98
+ end
@@ -0,0 +1,98 @@
1
+ require File.expand_path('../helper', __FILE__)
2
+
3
+ class ExtensionsTest < Test::Unit::TestCase
4
+ module FooExtensions
5
+ def foo
6
+ end
7
+
8
+ private
9
+ def im_hiding_in_ur_foos
10
+ end
11
+ end
12
+
13
+ module BarExtensions
14
+ def bar
15
+ end
16
+ end
17
+
18
+ module BazExtensions
19
+ def baz
20
+ end
21
+ end
22
+
23
+ module QuuxExtensions
24
+ def quux
25
+ end
26
+ end
27
+
28
+ module PainExtensions
29
+ def foo=(name); end
30
+ def bar?(name); end
31
+ def fizz!(name); end
32
+ end
33
+
34
+ it 'will add the methods to the DSL for the class in which you register them and its subclasses' do
35
+ Sinatra::Base.register FooExtensions
36
+ assert Sinatra::Base.respond_to?(:foo)
37
+
38
+ Sinatra::Application.register BarExtensions
39
+ assert Sinatra::Application.respond_to?(:bar)
40
+ assert Sinatra::Application.respond_to?(:foo)
41
+ assert !Sinatra::Base.respond_to?(:bar)
42
+ end
43
+
44
+ it 'allows extending by passing a block' do
45
+ Sinatra::Base.register { def im_in_ur_anonymous_module; end }
46
+ assert Sinatra::Base.respond_to?(:im_in_ur_anonymous_module)
47
+ end
48
+
49
+ it 'will make sure any public methods added via Application#register are delegated to Sinatra::Delegator' do
50
+ Sinatra::Application.register FooExtensions
51
+ assert Sinatra::Delegator.private_instance_methods.
52
+ map { |m| m.to_sym }.include?(:foo)
53
+ assert !Sinatra::Delegator.private_instance_methods.
54
+ map { |m| m.to_sym }.include?(:im_hiding_in_ur_foos)
55
+ end
56
+
57
+ it 'will handle special method names' do
58
+ Sinatra::Application.register PainExtensions
59
+ assert Sinatra::Delegator.private_instance_methods.
60
+ map { |m| m.to_sym }.include?(:foo=)
61
+ assert Sinatra::Delegator.private_instance_methods.
62
+ map { |m| m.to_sym }.include?(:bar?)
63
+ assert Sinatra::Delegator.private_instance_methods.
64
+ map { |m| m.to_sym }.include?(:fizz!)
65
+ end
66
+
67
+ it 'will not delegate methods on Base#register' do
68
+ Sinatra::Base.register QuuxExtensions
69
+ assert !Sinatra::Delegator.private_instance_methods.include?("quux")
70
+ end
71
+
72
+ it 'will extend the Sinatra::Application application by default' do
73
+ Sinatra.register BazExtensions
74
+ assert !Sinatra::Base.respond_to?(:baz)
75
+ assert Sinatra::Application.respond_to?(:baz)
76
+ end
77
+
78
+ module BizzleExtension
79
+ def bizzle
80
+ bizzle_option
81
+ end
82
+
83
+ def self.registered(base)
84
+ fail "base should be BizzleApp" unless base == BizzleApp
85
+ fail "base should have already extended BizzleExtension" unless base.respond_to?(:bizzle)
86
+ base.set :bizzle_option, 'bizzle!'
87
+ end
88
+ end
89
+
90
+ class BizzleApp < Sinatra::Base
91
+ end
92
+
93
+ it 'sends .registered to the extension module after extending the class' do
94
+ BizzleApp.register BizzleExtension
95
+ assert_equal 'bizzle!', BizzleApp.bizzle_option
96
+ assert_equal 'bizzle!', BizzleApp.bizzle
97
+ end
98
+ end
@@ -0,0 +1,437 @@
1
+ require File.expand_path('../helper', __FILE__)
2
+
3
+ class BeforeFilterTest < Test::Unit::TestCase
4
+ it "executes filters in the order defined" do
5
+ count = 0
6
+ mock_app do
7
+ get('/') { 'Hello World' }
8
+ before do
9
+ assert_equal 0, count
10
+ count = 1
11
+ end
12
+ before do
13
+ assert_equal 1, count
14
+ count = 2
15
+ end
16
+ end
17
+
18
+ get '/'
19
+ assert ok?
20
+ assert_equal 2, count
21
+ assert_equal 'Hello World', body
22
+ end
23
+
24
+ it "can modify the request" do
25
+ mock_app do
26
+ get('/foo') { 'foo' }
27
+ get('/bar') { 'bar' }
28
+ before { request.path_info = '/bar' }
29
+ end
30
+
31
+ get '/foo'
32
+ assert ok?
33
+ assert_equal 'bar', body
34
+ end
35
+
36
+ it "can modify instance variables available to routes" do
37
+ mock_app do
38
+ before { @foo = 'bar' }
39
+ get('/foo') { @foo }
40
+ end
41
+
42
+ get '/foo'
43
+ assert ok?
44
+ assert_equal 'bar', body
45
+ end
46
+
47
+ it "allows redirects" do
48
+ mock_app do
49
+ before { redirect '/bar' }
50
+ get('/foo') do
51
+ fail 'before block should have halted processing'
52
+ 'ORLY?!'
53
+ end
54
+ end
55
+
56
+ get '/foo'
57
+ assert redirect?
58
+ assert_equal 'http://example.org/bar', response['Location']
59
+ assert_equal '', body
60
+ end
61
+
62
+ it "does not modify the response with its return value" do
63
+ mock_app do
64
+ before { 'Hello World!' }
65
+ get('/foo') do
66
+ assert_equal [], response.body
67
+ 'cool'
68
+ end
69
+ end
70
+
71
+ get '/foo'
72
+ assert ok?
73
+ assert_equal 'cool', body
74
+ end
75
+
76
+ it "does modify the response with halt" do
77
+ mock_app do
78
+ before { halt 302, 'Hi' }
79
+ get '/foo' do
80
+ "should not happen"
81
+ end
82
+ end
83
+
84
+ get '/foo'
85
+ assert_equal 302, response.status
86
+ assert_equal 'Hi', body
87
+ end
88
+
89
+ it "gives you access to params" do
90
+ mock_app do
91
+ before { @foo = params['foo'] }
92
+ get('/foo') { @foo }
93
+ end
94
+
95
+ get '/foo?foo=cool'
96
+ assert ok?
97
+ assert_equal 'cool', body
98
+ end
99
+
100
+ it "properly unescapes parameters" do
101
+ mock_app do
102
+ before { @foo = params['foo'] }
103
+ get('/foo') { @foo }
104
+ end
105
+
106
+ get '/foo?foo=bar%3Abaz%2Fbend'
107
+ assert ok?
108
+ assert_equal 'bar:baz/bend', body
109
+ end
110
+
111
+ it "runs filters defined in superclasses" do
112
+ base = Class.new(Sinatra::Base)
113
+ base.before { @foo = 'hello from superclass' }
114
+
115
+ mock_app(base) { get('/foo') { @foo } }
116
+
117
+ get '/foo'
118
+ assert_equal 'hello from superclass', body
119
+ end
120
+
121
+ it 'does not run before filter when serving static files' do
122
+ ran_filter = false
123
+ mock_app do
124
+ before { ran_filter = true }
125
+ set :static, true
126
+ set :public_folder, File.dirname(__FILE__)
127
+ end
128
+ get "/#{File.basename(__FILE__)}"
129
+ assert ok?
130
+ assert_equal File.read(__FILE__), body
131
+ assert !ran_filter
132
+ end
133
+
134
+ it 'takes an optional route pattern' do
135
+ ran_filter = false
136
+ mock_app do
137
+ before("/b*") { ran_filter = true }
138
+ get('/foo') { }
139
+ get('/bar') { }
140
+ end
141
+ get '/foo'
142
+ assert !ran_filter
143
+ get '/bar'
144
+ assert ran_filter
145
+ end
146
+
147
+ it 'generates block arguments from route pattern' do
148
+ subpath = nil
149
+ mock_app do
150
+ before("/foo/:sub") { |s| subpath = s }
151
+ get('/foo/*') { }
152
+ end
153
+ get '/foo/bar'
154
+ assert_equal subpath, 'bar'
155
+ end
156
+ end
157
+
158
+ class AfterFilterTest < Test::Unit::TestCase
159
+ it "executes before and after filters in correct order" do
160
+ invoked = 0
161
+ mock_app do
162
+ before { invoked = 2 }
163
+ get('/') { invoked += 2; 'hello' }
164
+ after { invoked *= 2 }
165
+ end
166
+
167
+ get '/'
168
+ assert ok?
169
+
170
+ assert_equal 8, invoked
171
+ end
172
+
173
+ it "executes filters in the order defined" do
174
+ count = 0
175
+ mock_app do
176
+ get('/') { 'Hello World' }
177
+ after do
178
+ assert_equal 0, count
179
+ count = 1
180
+ end
181
+ after do
182
+ assert_equal 1, count
183
+ count = 2
184
+ end
185
+ end
186
+
187
+ get '/'
188
+ assert ok?
189
+ assert_equal 2, count
190
+ assert_equal 'Hello World', body
191
+ end
192
+
193
+ it "allows redirects" do
194
+ mock_app do
195
+ get('/foo') { 'ORLY' }
196
+ after { redirect '/bar' }
197
+ end
198
+
199
+ get '/foo'
200
+ assert redirect?
201
+ assert_equal 'http://example.org/bar', response['Location']
202
+ assert_equal '', body
203
+ end
204
+
205
+ it "does not modify the response with its return value" do
206
+ mock_app do
207
+ get('/foo') { 'cool' }
208
+ after { 'Hello World!' }
209
+ end
210
+
211
+ get '/foo'
212
+ assert ok?
213
+ assert_equal 'cool', body
214
+ end
215
+
216
+ it "does modify the response with halt" do
217
+ mock_app do
218
+ get '/foo' do
219
+ "should not be returned"
220
+ end
221
+ after { halt 302, 'Hi' }
222
+ end
223
+
224
+ get '/foo'
225
+ assert_equal 302, response.status
226
+ assert_equal 'Hi', body
227
+ end
228
+
229
+ it "runs filters defined in superclasses" do
230
+ count = 2
231
+ base = Class.new(Sinatra::Base)
232
+ base.after { count *= 2 }
233
+ mock_app(base) do
234
+ get('/foo') do
235
+ count += 2
236
+ "ok"
237
+ end
238
+ end
239
+
240
+ get '/foo'
241
+ assert_equal 8, count
242
+ end
243
+
244
+ it 'does not run after filter when serving static files' do
245
+ ran_filter = false
246
+ mock_app do
247
+ after { ran_filter = true }
248
+ set :static, true
249
+ set :public_folder, File.dirname(__FILE__)
250
+ end
251
+ get "/#{File.basename(__FILE__)}"
252
+ assert ok?
253
+ assert_equal File.read(__FILE__), body
254
+ assert !ran_filter
255
+ end
256
+
257
+ it 'takes an optional route pattern' do
258
+ ran_filter = false
259
+ mock_app do
260
+ after("/b*") { ran_filter = true }
261
+ get('/foo') { }
262
+ get('/bar') { }
263
+ end
264
+ get '/foo'
265
+ assert !ran_filter
266
+ get '/bar'
267
+ assert ran_filter
268
+ end
269
+
270
+ it 'changes to path_info from a pattern matching before filter are respoected when routing' do
271
+ mock_app do
272
+ before('/foo') { request.path_info = '/bar' }
273
+ get('/bar') { 'blah' }
274
+ end
275
+ get '/foo'
276
+ assert ok?
277
+ assert_equal 'blah', body
278
+ end
279
+
280
+ it 'generates block arguments from route pattern' do
281
+ subpath = nil
282
+ mock_app do
283
+ after("/foo/:sub") { |s| subpath = s }
284
+ get('/foo/*') { }
285
+ end
286
+ get '/foo/bar'
287
+ assert_equal subpath, 'bar'
288
+ end
289
+
290
+ it 'is possible to access url params from the route param' do
291
+ ran = false
292
+ mock_app do
293
+ get('/foo/*') { }
294
+ before('/foo/:sub') do
295
+ assert_equal params[:sub], 'bar'
296
+ ran = true
297
+ end
298
+ end
299
+ get '/foo/bar'
300
+ assert ran
301
+ end
302
+
303
+ it 'is possible to apply host_name conditions to before filters with no path' do
304
+ ran = false
305
+ mock_app do
306
+ before(:host_name => 'example.com') { ran = true }
307
+ get('/') { 'welcome' }
308
+ end
309
+ get('/', {}, { 'HTTP_HOST' => 'example.org' })
310
+ assert !ran
311
+ get('/', {}, { 'HTTP_HOST' => 'example.com' })
312
+ assert ran
313
+ end
314
+
315
+ it 'is possible to apply host_name conditions to before filters with a path' do
316
+ ran = false
317
+ mock_app do
318
+ before('/foo', :host_name => 'example.com') { ran = true }
319
+ get('/') { 'welcome' }
320
+ end
321
+ get('/', {}, { 'HTTP_HOST' => 'example.com' })
322
+ assert !ran
323
+ get('/foo', {}, { 'HTTP_HOST' => 'example.org' })
324
+ assert !ran
325
+ get('/foo', {}, { 'HTTP_HOST' => 'example.com' })
326
+ assert ran
327
+ end
328
+
329
+ it 'is possible to apply host_name conditions to after filters with no path' do
330
+ ran = false
331
+ mock_app do
332
+ after(:host_name => 'example.com') { ran = true }
333
+ get('/') { 'welcome' }
334
+ end
335
+ get('/', {}, { 'HTTP_HOST' => 'example.org' })
336
+ assert !ran
337
+ get('/', {}, { 'HTTP_HOST' => 'example.com' })
338
+ assert ran
339
+ end
340
+
341
+ it 'is possible to apply host_name conditions to after filters with a path' do
342
+ ran = false
343
+ mock_app do
344
+ after('/foo', :host_name => 'example.com') { ran = true }
345
+ get('/') { 'welcome' }
346
+ end
347
+ get('/', {}, { 'HTTP_HOST' => 'example.com' })
348
+ assert !ran
349
+ get('/foo', {}, { 'HTTP_HOST' => 'example.org' })
350
+ assert !ran
351
+ get('/foo', {}, { 'HTTP_HOST' => 'example.com' })
352
+ assert ran
353
+ end
354
+
355
+ it 'is possible to apply user_agent conditions to before filters with no path' do
356
+ ran = false
357
+ mock_app do
358
+ before(:user_agent => /foo/) { ran = true }
359
+ get('/') { 'welcome' }
360
+ end
361
+ get('/', {}, { 'HTTP_USER_AGENT' => 'bar' })
362
+ assert !ran
363
+ get('/', {}, { 'HTTP_USER_AGENT' => 'foo' })
364
+ assert ran
365
+ end
366
+
367
+ it 'is possible to apply user_agent conditions to before filters with a path' do
368
+ ran = false
369
+ mock_app do
370
+ before('/foo', :user_agent => /foo/) { ran = true }
371
+ get('/') { 'welcome' }
372
+ end
373
+ get('/', {}, { 'HTTP_USER_AGENT' => 'foo' })
374
+ assert !ran
375
+ get('/foo', {}, { 'HTTP_USER_AGENT' => 'bar' })
376
+ assert !ran
377
+ get('/foo', {}, { 'HTTP_USER_AGENT' => 'foo' })
378
+ assert ran
379
+ end
380
+
381
+ it 'can add params' do
382
+ mock_app do
383
+ before { params['foo'] = 'bar' }
384
+ get('/') { params['foo'] }
385
+ end
386
+
387
+ get '/'
388
+ assert_body 'bar'
389
+ end
390
+
391
+ it 'can remove params' do
392
+ mock_app do
393
+ before { params.delete('foo') }
394
+ get('/') { params['foo'].to_s }
395
+ end
396
+
397
+ get '/?foo=bar'
398
+ assert_body ''
399
+ end
400
+
401
+ it 'is possible to apply user_agent conditions to after filters with no path' do
402
+ ran = false
403
+ mock_app do
404
+ after(:user_agent => /foo/) { ran = true }
405
+ get('/') { 'welcome' }
406
+ end
407
+ get('/', {}, { 'HTTP_USER_AGENT' => 'bar' })
408
+ assert !ran
409
+ get('/', {}, { 'HTTP_USER_AGENT' => 'foo' })
410
+ assert ran
411
+ end
412
+
413
+ it 'is possible to apply user_agent conditions to after filters with a path' do
414
+ ran = false
415
+ mock_app do
416
+ after('/foo', :user_agent => /foo/) { ran = true }
417
+ get('/') { 'welcome' }
418
+ end
419
+ get('/', {}, { 'HTTP_USER_AGENT' => 'foo' })
420
+ assert !ran
421
+ get('/foo', {}, { 'HTTP_USER_AGENT' => 'bar' })
422
+ assert !ran
423
+ get('/foo', {}, { 'HTTP_USER_AGENT' => 'foo' })
424
+ assert ran
425
+ end
426
+
427
+ it 'only triggeres provides condition if conforms with current Content-Type' do
428
+ mock_app do
429
+ before(:provides => :txt) { @type = 'txt' }
430
+ before(:provides => :html) { @type = 'html' }
431
+ get('/') { @type }
432
+ end
433
+
434
+ get('/', {}, { 'HTTP_ACCEPT' => '*' })
435
+ assert_body 'txt'
436
+ end
437
+ end