262 lines
7.4 KiB
Ruby
262 lines
7.4 KiB
Ruby
|
require 'spec_helper'
|
||
|
require 'rack-mini-profiler'
|
||
|
require 'rack/test'
|
||
|
|
||
|
describe Rack::MiniProfiler do
|
||
|
include Rack::Test::Methods
|
||
|
|
||
|
def app
|
||
|
@app ||= Rack::Builder.new {
|
||
|
use Rack::MiniProfiler
|
||
|
map '/path2/a' do
|
||
|
run lambda { |env| [200, {'Content-Type' => 'text/html'}, '<h1>path1</h1>'] }
|
||
|
end
|
||
|
map '/path1/a' do
|
||
|
run lambda { |env| [200, {'Content-Type' => 'text/html'}, '<h1>path2</h1>'] }
|
||
|
end
|
||
|
map '/post' do
|
||
|
run lambda { |env| [302, {'Content-Type' => 'text/html'}, '<h1>POST</h1>'] }
|
||
|
end
|
||
|
map '/html' do
|
||
|
run lambda { |env| [200, {'Content-Type' => 'text/html'}, "<html><BODY><h1>Hi</h1></BODY>\n \t</html>"] }
|
||
|
end
|
||
|
map '/implicitbody' do
|
||
|
run lambda { |env| [200, {'Content-Type' => 'text/html'}, "<html><h1>Hi</h1></html>"] }
|
||
|
end
|
||
|
map '/implicitbodyhtml' do
|
||
|
run lambda { |env| [200, {'Content-Type' => 'text/html'}, "<h1>Hi</h1>"] }
|
||
|
end
|
||
|
map '/db' do
|
||
|
run lambda { |env|
|
||
|
::Rack::MiniProfiler.record_sql("I want to be, in a db", 10)
|
||
|
[200, {'Content-Type' => 'text/html'}, '<h1>Hi+db</h1>']
|
||
|
}
|
||
|
end
|
||
|
map '/3ms' do
|
||
|
run lambda { |env|
|
||
|
sleep(0.003)
|
||
|
[200, {'Content-Type' => 'text/html'}, '<h1>Hi</h1>']
|
||
|
}
|
||
|
end
|
||
|
map '/whitelisted' do
|
||
|
run lambda { |env|
|
||
|
Rack::MiniProfiler.authorize_request
|
||
|
[200, {'Content-Type' => 'text/html'}, '<h1>path1</h1>']
|
||
|
}
|
||
|
end
|
||
|
}.to_app
|
||
|
end
|
||
|
|
||
|
before do
|
||
|
Rack::MiniProfiler.reset_config
|
||
|
end
|
||
|
|
||
|
describe 'with a valid request' do
|
||
|
|
||
|
before do
|
||
|
get '/html'
|
||
|
end
|
||
|
|
||
|
it 'returns 200' do
|
||
|
last_response.should be_ok
|
||
|
end
|
||
|
|
||
|
it 'has the X-MiniProfiler-Ids header' do
|
||
|
last_response.headers.has_key?('X-MiniProfiler-Ids').should be_true
|
||
|
end
|
||
|
|
||
|
it 'has only one X-MiniProfiler-Ids header' do
|
||
|
h = last_response.headers['X-MiniProfiler-Ids']
|
||
|
ids = ::JSON.parse(h)
|
||
|
ids.count.should == 1
|
||
|
end
|
||
|
|
||
|
it 'has the JS in the body' do
|
||
|
last_response.body.include?('/mini-profiler-resources/includes.js').should be_true
|
||
|
end
|
||
|
|
||
|
it 'has a functioning share link' do
|
||
|
h = last_response.headers['X-MiniProfiler-Ids']
|
||
|
id = ::JSON.parse(h)[0]
|
||
|
get "/mini-profiler-resources/results?id=#{id}"
|
||
|
last_response.should be_ok
|
||
|
end
|
||
|
|
||
|
it 'avoids xss attacks' do
|
||
|
h = last_response.headers['X-MiniProfiler-Ids']
|
||
|
id = ::JSON.parse(h)[0]
|
||
|
get "/mini-profiler-resources/results?id=%22%3E%3Cqss%3E"
|
||
|
last_response.should_not be_ok
|
||
|
last_response.body.should_not =~ /<qss>/
|
||
|
last_response.body.should =~ /<qss>/
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
describe 'with an implicit body tag' do
|
||
|
|
||
|
before do
|
||
|
get '/implicitbody'
|
||
|
end
|
||
|
|
||
|
it 'has the JS in the body' do
|
||
|
last_response.body.include?('/mini-profiler-resources/includes.js').should be_true
|
||
|
end
|
||
|
|
||
|
end
|
||
|
|
||
|
|
||
|
describe 'with implicit body and html tags' do
|
||
|
|
||
|
before do
|
||
|
get '/implicitbodyhtml'
|
||
|
end
|
||
|
|
||
|
it 'does not include the JS in the body' do
|
||
|
last_response.body.include?('/mini-profiler-resources/includes.js').should be_false
|
||
|
end
|
||
|
|
||
|
end
|
||
|
|
||
|
|
||
|
describe 'with a SCRIPT_NAME' do
|
||
|
|
||
|
before do
|
||
|
get '/html', nil, 'SCRIPT_NAME' => '/test'
|
||
|
end
|
||
|
|
||
|
it 'has the JS in the body with the correct path' do
|
||
|
last_response.body.include?('/test/mini-profiler-resources/includes.js').should be_true
|
||
|
end
|
||
|
|
||
|
end
|
||
|
|
||
|
describe 'configuration' do
|
||
|
it "doesn't add MiniProfiler if the callback fails" do
|
||
|
Rack::MiniProfiler.config.pre_authorize_cb = lambda {|env| false }
|
||
|
get '/html'
|
||
|
last_response.headers.has_key?('X-MiniProfiler-Ids').should be_false
|
||
|
end
|
||
|
|
||
|
it "skips paths listed" do
|
||
|
Rack::MiniProfiler.config.skip_paths = ['/path/', '/path2/']
|
||
|
get '/path2/a'
|
||
|
last_response.headers.has_key?('X-MiniProfiler-Ids').should be_false
|
||
|
get '/path1/a'
|
||
|
last_response.headers.has_key?('X-MiniProfiler-Ids').should be_true
|
||
|
end
|
||
|
|
||
|
it 'disables default functionality' do
|
||
|
Rack::MiniProfiler.config.enabled = false
|
||
|
get '/html'
|
||
|
last_response.headers.has_key?('X-MiniProfiler-Ids').should be_false
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def load_prof(response)
|
||
|
id = response.headers['X-MiniProfiler-Ids']
|
||
|
id = ::JSON.parse(id)[0]
|
||
|
Rack::MiniProfiler.config.storage_instance.load(id)
|
||
|
end
|
||
|
|
||
|
describe 'special options' do
|
||
|
it "omits db backtrace if requested" do
|
||
|
get '/db?pp=no-backtrace'
|
||
|
prof = load_prof(last_response)
|
||
|
stack = prof["Root"]["SqlTimings"][0]["StackTraceSnippet"]
|
||
|
stack.should be_nil
|
||
|
end
|
||
|
|
||
|
it 'disables functionality if requested' do
|
||
|
get '/html?pp=disable'
|
||
|
last_response.body.should_not include('/mini-profiler-resources/includes.js')
|
||
|
end
|
||
|
|
||
|
context 'when disabled' do
|
||
|
before(:each) do
|
||
|
get '/html?pp=disable'
|
||
|
get '/html'
|
||
|
last_response.body.should_not include('/mini-profiler-resources/includes.js')
|
||
|
end
|
||
|
|
||
|
it 're-enables functionality if requested' do
|
||
|
get '/html?pp=enable'
|
||
|
last_response.body.should include('/mini-profiler-resources/includes.js')
|
||
|
end
|
||
|
|
||
|
it "does not re-enable functionality if not whitelisted" do
|
||
|
Rack::MiniProfiler.config.authorization_mode = :whitelist
|
||
|
get '/html?pp=enable'
|
||
|
last_response.body.should_not include('/mini-profiler-resources/includes.js')
|
||
|
end
|
||
|
|
||
|
it "re-enabled functionality if whitelisted" do
|
||
|
Rack::MiniProfiler.config.authorization_mode = :whitelist
|
||
|
expect(Rack::MiniProfiler).to receive(:request_authorized?) { true }.twice
|
||
|
get '/html?pp=enable'
|
||
|
last_response.body.should include('/mini-profiler-resources/includes.js')
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
describe 'POST followed by GET' do
|
||
|
it "should end up with 2 ids" do
|
||
|
post '/post'
|
||
|
get '/html'
|
||
|
|
||
|
ids = last_response.headers['X-MiniProfiler-Ids']
|
||
|
::JSON.parse(ids).length.should == 2
|
||
|
end
|
||
|
end
|
||
|
|
||
|
describe 'authorization mode whitelist' do
|
||
|
before do
|
||
|
Rack::MiniProfiler.config.authorization_mode = :whitelist
|
||
|
end
|
||
|
|
||
|
it "should ban requests that are not whitelisted" do
|
||
|
get '/html'
|
||
|
last_response.headers['X-MiniProfiler-Ids'].should be_nil
|
||
|
end
|
||
|
|
||
|
it "should allow requests that are whitelisted" do
|
||
|
set_cookie("__profilin=stylin")
|
||
|
get '/whitelisted'
|
||
|
last_response.headers['X-MiniProfiler-Ids'].should_not be_nil
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
describe 'gc profiler' do
|
||
|
it "should return a report" do
|
||
|
get '/html?pp=profile-gc'
|
||
|
last_response.header['Content-Type'].should == 'text/plain'
|
||
|
end
|
||
|
end
|
||
|
|
||
|
describe 'error handling when storage_instance fails to save' do
|
||
|
it "should recover gracefully" do
|
||
|
Rack::MiniProfiler.config.pre_authorize_cb = lambda {|env| true }
|
||
|
Rack::MiniProfiler::MemoryStore.any_instance.stub(:save) { raise "This error" }
|
||
|
Rack::MiniProfiler.config.storage_failure.should_receive(:call)
|
||
|
get '/html'
|
||
|
end
|
||
|
end
|
||
|
|
||
|
describe 'when profiler is disabled by default' do
|
||
|
before(:each) do
|
||
|
Rack::MiniProfiler.config.enabled = false
|
||
|
get '/html'
|
||
|
last_response.headers.has_key?('X-MiniProfiler-Ids').should be_false
|
||
|
end
|
||
|
|
||
|
it 'functionality can be re-enabled' do
|
||
|
get '/html?pp=enable'
|
||
|
last_response.headers.has_key?('X-MiniProfiler-Ids').should be_true
|
||
|
get '/html'
|
||
|
last_response.headers.has_key?('X-MiniProfiler-Ids').should be_true
|
||
|
end
|
||
|
end
|
||
|
|
||
|
end
|