123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- require 'rack/builder'
- require 'rack/lint'
- require 'rack/mock'
- require 'rack/showexceptions'
- require 'rack/urlmap'
- class NothingMiddleware
- def initialize(app)
- @app = app
- end
- def call(env)
- @@env = env
- response = @app.call(env)
- response
- end
- def self.env
- @@env
- end
- end
- describe Rack::Builder do
- def builder(&block)
- Rack::Lint.new Rack::Builder.new(&block)
- end
-
- def builder_to_app(&block)
- Rack::Lint.new Rack::Builder.new(&block).to_app
- end
-
- it "supports mapping" do
- app = builder_to_app do
- map '/' do |outer_env|
- run lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, ['root']] }
- end
- map '/sub' do
- run lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, ['sub']] }
- end
- end
- Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'root'
- Rack::MockRequest.new(app).get("/sub").body.to_s.should.equal 'sub'
- end
- it "doesn't dupe env even when mapping" do
- app = builder_to_app do
- use NothingMiddleware
- map '/' do |outer_env|
- run lambda { |inner_env|
- inner_env['new_key'] = 'new_value'
- [200, {"Content-Type" => "text/plain"}, ['root']]
- }
- end
- end
- Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'root'
- NothingMiddleware.env['new_key'].should.equal 'new_value'
- end
- it "chains apps by default" do
- app = builder_to_app do
- use Rack::ShowExceptions
- run lambda { |env| raise "bzzzt" }
- end
- Rack::MockRequest.new(app).get("/").should.be.server_error
- Rack::MockRequest.new(app).get("/").should.be.server_error
- Rack::MockRequest.new(app).get("/").should.be.server_error
- end
- it "has implicit #to_app" do
- app = builder do
- use Rack::ShowExceptions
- run lambda { |env| raise "bzzzt" }
- end
- Rack::MockRequest.new(app).get("/").should.be.server_error
- Rack::MockRequest.new(app).get("/").should.be.server_error
- Rack::MockRequest.new(app).get("/").should.be.server_error
- end
- it "supports blocks on use" do
- app = builder do
- use Rack::ShowExceptions
- use Rack::Auth::Basic do |username, password|
- 'secret' == password
- end
- run lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hi Boss']] }
- end
- response = Rack::MockRequest.new(app).get("/")
- response.should.be.client_error
- response.status.should.equal 401
- # with auth...
- response = Rack::MockRequest.new(app).get("/",
- 'HTTP_AUTHORIZATION' => 'Basic ' + ["joe:secret"].pack("m*"))
- response.status.should.equal 200
- response.body.to_s.should.equal 'Hi Boss'
- end
- it "has explicit #to_app" do
- app = builder do
- use Rack::ShowExceptions
- run lambda { |env| raise "bzzzt" }
- end
- Rack::MockRequest.new(app).get("/").should.be.server_error
- Rack::MockRequest.new(app).get("/").should.be.server_error
- Rack::MockRequest.new(app).get("/").should.be.server_error
- end
- it "can mix map and run for endpoints" do
- app = builder do
- map '/sub' do
- run lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, ['sub']] }
- end
- run lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, ['root']] }
- end
- Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'root'
- Rack::MockRequest.new(app).get("/sub").body.to_s.should.equal 'sub'
- end
- it "accepts middleware-only map blocks" do
- app = builder do
- map('/foo') { use Rack::ShowExceptions }
- run lambda { |env| raise "bzzzt" }
- end
- proc { Rack::MockRequest.new(app).get("/") }.should.raise(RuntimeError)
- Rack::MockRequest.new(app).get("/foo").should.be.server_error
- end
- should "initialize apps once" do
- app = builder do
- class AppClass
- def initialize
- @called = 0
- end
- def call(env)
- raise "bzzzt" if @called > 0
- @called += 1
- [200, {'Content-Type' => 'text/plain'}, ['OK']]
- end
- end
- use Rack::ShowExceptions
- run AppClass.new
- end
- Rack::MockRequest.new(app).get("/").status.should.equal 200
- Rack::MockRequest.new(app).get("/").should.be.server_error
- end
- it "allows use after run" do
- app = builder do
- run lambda { |env| raise "bzzzt" }
- use Rack::ShowExceptions
- end
- Rack::MockRequest.new(app).get("/").should.be.server_error
- Rack::MockRequest.new(app).get("/").should.be.server_error
- Rack::MockRequest.new(app).get("/").should.be.server_error
- end
- it 'complains about a missing run' do
- proc do
- Rack::Lint.new Rack::Builder.app { use Rack::ShowExceptions }
- end.should.raise(RuntimeError)
- end
- describe "parse_file" do
- def config_file(name)
- File.join(File.dirname(__FILE__), 'builder', name)
- end
- it "parses commented options" do
- app, options = Rack::Builder.parse_file config_file('options.ru')
- options[:debug].should.be.true
- Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'OK'
- end
- it "removes __END__ before evaluating app" do
- app, options = Rack::Builder.parse_file config_file('end.ru')
- options = nil # ignored, prevents warning
- Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'OK'
- end
- it "supports multi-line comments" do
- lambda {
- Rack::Builder.parse_file config_file('comment.ru')
- }.should.not.raise(SyntaxError)
- end
- it "requires anything not ending in .ru" do
- $: << File.dirname(__FILE__)
- app, options = Rack::Builder.parse_file 'builder/anything'
- Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'OK'
- $:.pop
- end
- end
- end
|