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,62 @@
1
+ $stderr.puts "loading"
2
+ require 'sinatra'
3
+
4
+ configure do
5
+ set :foo, :bar
6
+ end
7
+
8
+ get '/app_file' do
9
+ content_type :txt
10
+ settings.app_file
11
+ end
12
+
13
+ get '/ping' do
14
+ 'pong'
15
+ end
16
+
17
+ get '/stream' do
18
+ stream do |out|
19
+ sleep 0.1
20
+ out << "a"
21
+ sleep 1.2
22
+ out << "b"
23
+ end
24
+ end
25
+
26
+ get '/mainonly' do
27
+ object = Object.new
28
+ begin
29
+ object.send(:get, '/foo') { }
30
+ 'false'
31
+ rescue NameError
32
+ 'true'
33
+ end
34
+ end
35
+
36
+ set :out, nil
37
+ get '/async' do
38
+ stream(:keep_open) { |o| (settings.out = o) << "hi!" }
39
+ end
40
+
41
+ get '/send' do
42
+ settings.out << params[:msg] if params[:msg]
43
+ settings.out.close if params[:close]
44
+ "ok"
45
+ end
46
+
47
+ class Subclass < Sinatra::Base
48
+ set :out, nil
49
+ get '/subclass/async' do
50
+ stream(:keep_open) { |o| (settings.out = o) << "hi!" }
51
+ end
52
+
53
+ get '/subclass/send' do
54
+ settings.out << params[:msg] if params[:msg]
55
+ settings.out.close if params[:close]
56
+ "ok"
57
+ end
58
+ end
59
+
60
+ use Subclass
61
+
62
+ $stderr.puts "starting"
@@ -0,0 +1,222 @@
1
+ require 'sinatra/base'
2
+ require 'rbconfig'
3
+ require 'open-uri'
4
+ require 'net/http'
5
+ require 'timeout'
6
+
7
+ module IntegrationHelper
8
+ class BaseServer
9
+ extend Enumerable
10
+ attr_accessor :server, :port, :pipe
11
+ alias name server
12
+
13
+ def self.all
14
+ @all ||= []
15
+ end
16
+
17
+ def self.each(&block)
18
+ all.each(&block)
19
+ end
20
+
21
+ def self.run(server, port)
22
+ new(server, port).run
23
+ end
24
+
25
+ def app_file
26
+ File.expand_path('../integration/app.rb', __FILE__)
27
+ end
28
+
29
+ def environment
30
+ "development"
31
+ end
32
+
33
+ def initialize(server, port)
34
+ @installed, @pipe, @server, @port = nil, nil, server, port
35
+ Server.all << self
36
+ end
37
+
38
+ def run
39
+ return unless installed?
40
+ kill
41
+ @log = ""
42
+ @pipe = IO.popen(command)
43
+ @started = Time.now
44
+ warn "#{server} up and running on port #{port}" if ping
45
+ at_exit { kill }
46
+ end
47
+
48
+ def ping(timeout = 30)
49
+ loop do
50
+ return if alive?
51
+ if Time.now - @started > timeout
52
+ $stderr.puts command, log
53
+ fail "timeout"
54
+ else
55
+ sleep 0.1
56
+ end
57
+ end
58
+ end
59
+
60
+ def alive?
61
+ 3.times { get('/ping') }
62
+ true
63
+ rescue Errno::ECONNREFUSED, Errno::ECONNRESET, EOFError, SystemCallError, OpenURI::HTTPError, Timeout::Error => error
64
+ false
65
+ end
66
+
67
+ def get_stream(url = "/stream", &block)
68
+ Net::HTTP.start '127.0.0.1', port do |http|
69
+ request = Net::HTTP::Get.new url
70
+ http.request request do |response|
71
+ response.read_body(&block)
72
+ end
73
+ end
74
+ end
75
+
76
+ def get(url)
77
+ Timeout.timeout(1) { open("http://127.0.0.1:#{port}#{url}").read }
78
+ end
79
+
80
+ def log
81
+ @log ||= ""
82
+ loop { @log << @pipe.read_nonblock(1) }
83
+ rescue Exception
84
+ @log
85
+ end
86
+
87
+ def installed?
88
+ return @installed unless @installed.nil?
89
+ require server
90
+ @installed = true
91
+ rescue LoadError
92
+ warn "#{server} is not installed, skipping integration tests"
93
+ @installed = false
94
+ end
95
+
96
+ def command
97
+ @command ||= begin
98
+ cmd = ["RACK_ENV=#{environment}", "exec"]
99
+ if RbConfig.respond_to? :ruby
100
+ cmd << RbConfig.ruby.inspect
101
+ else
102
+ file, dir = RbConfig::CONFIG.values_at('ruby_install_name', 'bindir')
103
+ cmd << File.expand_path(file, dir).inspect
104
+ end
105
+ cmd << "-w" unless thin?
106
+ cmd << "-I" << File.expand_path('../../lib', __FILE__).inspect
107
+ cmd << app_file.inspect << '-s' << server << '-o' << '127.0.0.1' << '-p' << port
108
+ cmd << "-e" << environment.to_s << '2>&1'
109
+ cmd.join " "
110
+ end
111
+ end
112
+
113
+ def kill
114
+ return unless pipe
115
+ Process.kill("KILL", pipe.pid)
116
+ rescue NotImplementedError
117
+ system "kill -9 #{pipe.pid}"
118
+ rescue Errno::ESRCH
119
+ end
120
+
121
+ def webrick?
122
+ name.to_s == "webrick"
123
+ end
124
+
125
+ def thin?
126
+ name.to_s == "thin"
127
+ end
128
+
129
+ def puma?
130
+ name.to_s == "puma"
131
+ end
132
+
133
+ def trinidad?
134
+ name.to_s == "trinidad"
135
+ end
136
+
137
+ def warnings
138
+ log.scan(%r[(?:\(eval|lib/sinatra).*warning:.*$])
139
+ end
140
+
141
+ def run_test(target, &block)
142
+ retries ||= 3
143
+ target.server = self
144
+ run unless alive?
145
+ target.instance_eval(&block)
146
+ rescue Exception => error
147
+ retries -= 1
148
+ kill
149
+ retries < 0 ? retry : raise(error)
150
+ end
151
+ end
152
+
153
+ if RUBY_ENGINE == "jruby"
154
+ class JRubyServer < BaseServer
155
+ def start_vm
156
+ require 'java'
157
+ # Create a new container, set load paths and env
158
+ # SINGLETHREAD means create a new runtime
159
+ vm = org.jruby.embed.ScriptingContainer.new(org.jruby.embed.LocalContextScope::SINGLETHREAD)
160
+ vm.load_paths = [File.expand_path('../../lib', __FILE__)]
161
+ vm.environment = ENV.merge('RACK_ENV' => environment.to_s)
162
+
163
+ # This ensures processing of RUBYOPT which activates Bundler
164
+ vm.provider.ruby_instance_config.process_arguments []
165
+ vm.argv = ['-s', server.to_s, '-o', '127.0.0.1', '-p', port.to_s, '-e', environment.to_s]
166
+
167
+ # Set stdout/stderr so we can retrieve log
168
+ @pipe = java.io.ByteArrayOutputStream.new
169
+ vm.output = java.io.PrintStream.new(@pipe)
170
+ vm.error = java.io.PrintStream.new(@pipe)
171
+
172
+ Thread.new do
173
+ # Hack to ensure that Kernel#caller has the same info as
174
+ # when run from command-line, for Sintra::Application.app_file.
175
+ # Also, line numbers are zero-based in JRuby's parser
176
+ vm.provider.runtime.current_context.set_file_and_line(app_file, 0)
177
+ # Run the app
178
+ vm.run_scriptlet org.jruby.embed.PathType::ABSOLUTE, app_file
179
+ # terminate launches at_exit hooks which start server
180
+ vm.terminate
181
+ end
182
+ end
183
+
184
+ def run
185
+ return unless installed?
186
+ kill
187
+ @thread = start_vm
188
+ @started = Time.now
189
+ warn "#{server} up and running on port #{port}" if ping
190
+ at_exit { kill }
191
+ end
192
+
193
+ def log
194
+ String.from_java_bytes @pipe.to_byte_array
195
+ end
196
+
197
+ def kill
198
+ @thread.kill if @thread
199
+ @thread = nil
200
+ end
201
+ end
202
+ Server = JRubyServer
203
+ else
204
+ Server = BaseServer
205
+ end
206
+
207
+ def it(message, &block)
208
+ Server.each do |server|
209
+ next unless server.installed?
210
+ super("with #{server.name}: #{message}") { server.run_test(self, &block) }
211
+ end
212
+ end
213
+
214
+ def self.extend_object(obj)
215
+ super
216
+
217
+ base_port = 5000 + Process.pid % 100
218
+ Sinatra::Base.server.each_with_index do |server, index|
219
+ Server.run(server, 5000+index)
220
+ end
221
+ end
222
+ end
@@ -0,0 +1,87 @@
1
+ require File.expand_path('../helper', __FILE__)
2
+ require File.expand_path('../integration_helper', __FILE__)
3
+
4
+ # These tests start a real server and talk to it over TCP.
5
+ # Every test runs with every detected server.
6
+ #
7
+ # See test/integration/app.rb for the code of the app we test against.
8
+ class IntegrationTest < Test::Unit::TestCase
9
+ extend IntegrationHelper
10
+ attr_accessor :server
11
+
12
+ it('sets the app_file') { assert_equal server.app_file, server.get("/app_file") }
13
+ it('only extends main') { assert_equal "true", server.get("/mainonly") }
14
+
15
+ it 'logs once in development mode' do
16
+ next if server.puma? or RUBY_ENGINE == 'jruby'
17
+ random = "%064x" % Kernel.rand(2**256-1)
18
+ server.get "/ping?x=#{random}"
19
+ count = server.log.scan("GET /ping?x=#{random}").count
20
+ server.webrick? ? assert(count > 0) : assert_equal(1, count)
21
+ end
22
+
23
+ it 'streams' do
24
+ next if server.webrick? or server.trinidad?
25
+ times, chunks = [Time.now], []
26
+ server.get_stream do |chunk|
27
+ next if chunk.empty?
28
+ chunks << chunk
29
+ times << Time.now
30
+ end
31
+ assert_equal ["a", "b"], chunks
32
+ assert times[1] - times[0] < 1
33
+ assert times[2] - times[1] > 1
34
+ end
35
+
36
+ it 'streams async' do
37
+ next unless server.thin?
38
+
39
+ Timeout.timeout(3) do
40
+ chunks = []
41
+ server.get_stream '/async' do |chunk|
42
+ next if chunk.empty?
43
+ chunks << chunk
44
+ case chunk
45
+ when "hi!" then server.get "/send?msg=hello"
46
+ when "hello" then server.get "/send?close=1"
47
+ end
48
+ end
49
+
50
+ assert_equal ['hi!', 'hello'], chunks
51
+ end
52
+ end
53
+
54
+ it 'streams async from subclass' do
55
+ next unless server.thin?
56
+
57
+ Timeout.timeout(3) do
58
+ chunks = []
59
+ server.get_stream '/subclass/async' do |chunk|
60
+ next if chunk.empty?
61
+ chunks << chunk
62
+ case chunk
63
+ when "hi!" then server.get "/subclass/send?msg=hello"
64
+ when "hello" then server.get "/subclass/send?close=1"
65
+ end
66
+ end
67
+
68
+ assert_equal ['hi!', 'hello'], chunks
69
+ end
70
+ end
71
+
72
+ it 'starts the correct server' do
73
+ exp = %r{
74
+ ==\sSinatra/#{Sinatra::VERSION}\s
75
+ has\staken\sthe\sstage\son\s\d+\sfor\sdevelopment\s
76
+ with\sbackup\sfrom\s#{server}
77
+ }ix
78
+
79
+ assert_match exp, server.log
80
+ end
81
+
82
+ it 'does not generate warnings' do
83
+ assert_raise(OpenURI::HTTPError) { server.get '/' }
84
+ server.get '/app_file'
85
+ assert_equal [], server.warnings
86
+ end
87
+ end
@@ -0,0 +1,69 @@
1
+ require File.expand_path('../helper', __FILE__)
2
+
3
+ begin
4
+ require 'less'
5
+
6
+ class LessTest < Test::Unit::TestCase
7
+ def less_app(options = {}, &block)
8
+ mock_app do
9
+ set :views, File.dirname(__FILE__) + '/views'
10
+ set options
11
+ get('/', &block)
12
+ end
13
+ get '/'
14
+ end
15
+
16
+ it 'renders inline Less strings' do
17
+ less_app {
18
+ less "@white_color: #fff; #main { background-color: @white_color }"
19
+ }
20
+ assert ok?
21
+ assert_equal "#main{background-color:#ffffff;}", body.gsub(/\s/, "")
22
+ end
23
+
24
+ it 'defaults content type to css' do
25
+ less_app {
26
+ less "@white_color: #fff; #main { background-color: @white_color }"
27
+ }
28
+ assert ok?
29
+ assert_equal "text/css;charset=utf-8", response['Content-Type']
30
+ end
31
+
32
+ it 'defaults allows setting content type per route' do
33
+ less_app do
34
+ content_type :html
35
+ less "@white_color: #fff; #main { background-color: @white_color }"
36
+ end
37
+ assert ok?
38
+ assert_equal "text/html;charset=utf-8", response['Content-Type']
39
+ end
40
+
41
+ it 'defaults allows setting content type globally' do
42
+ less_app(:less => { :content_type => 'html' }) do
43
+ less "@white_color: #fff; #main { background-color: @white_color }"
44
+ end
45
+ assert ok?
46
+ assert_equal "text/html;charset=utf-8", response['Content-Type']
47
+ end
48
+
49
+ it 'renders .less files in views path' do
50
+ less_app { less :hello }
51
+ assert ok?
52
+ assert_equal "#main{background-color:#ffffff;}", body.gsub(/\s/, "")
53
+ end
54
+
55
+ it 'ignores the layout option' do
56
+ less_app { less :hello, :layout => :layout2 }
57
+ assert ok?
58
+ assert_equal "#main{background-color:#ffffff;}", body.gsub(/\s/, "")
59
+ end
60
+
61
+ it "raises error if template not found" do
62
+ mock_app { get('/') { less :no_such_template } }
63
+ assert_raise(Errno::ENOENT) { get('/') }
64
+ end
65
+ end
66
+
67
+ rescue LoadError
68
+ warn "#{$!.to_s}: skipping less tests"
69
+ end
@@ -0,0 +1,59 @@
1
+ require File.expand_path('../helper', __FILE__)
2
+
3
+ begin
4
+ require 'liquid'
5
+
6
+ class LiquidTest < Test::Unit::TestCase
7
+ def liquid_app(&block)
8
+ mock_app do
9
+ set :views, File.dirname(__FILE__) + '/views'
10
+ get('/', &block)
11
+ end
12
+ get '/'
13
+ end
14
+
15
+ it 'renders inline liquid strings' do
16
+ liquid_app { liquid '<h1>Hiya</h1>' }
17
+ assert ok?
18
+ assert_equal "<h1>Hiya</h1>", body
19
+ end
20
+
21
+ it 'renders .liquid files in views path' do
22
+ liquid_app { liquid :hello }
23
+ assert ok?
24
+ assert_equal "<h1>Hello From Liquid</h1>\n", body
25
+ end
26
+
27
+ it "renders with inline layouts" do
28
+ mock_app do
29
+ layout { "<h1>THIS. IS. {{ yield }}</h1>" }
30
+ get('/') { liquid '<EM>SPARTA</EM>' }
31
+ end
32
+ get '/'
33
+ assert ok?
34
+ assert_equal "<h1>THIS. IS. <EM>SPARTA</EM></h1>", body
35
+ end
36
+
37
+ it "renders with file layouts" do
38
+ liquid_app { liquid 'Hello World', :layout => :layout2 }
39
+ assert ok?
40
+ assert_equal "<h1>Liquid Layout!</h1>\n<p>Hello World</p>\n", body
41
+ end
42
+
43
+ it "raises error if template not found" do
44
+ mock_app { get('/') { liquid :no_such_template } }
45
+ assert_raise(Errno::ENOENT) { get('/') }
46
+ end
47
+
48
+ it "allows passing locals" do
49
+ liquid_app {
50
+ liquid '{{ value }}', :locals => { :value => 'foo' }
51
+ }
52
+ assert ok?
53
+ assert_equal 'foo', body
54
+ end
55
+ end
56
+
57
+ rescue LoadError
58
+ warn "#{$!.to_s}: skipping liquid tests"
59
+ end