gentooboontoo-rack-bug 0.3.0.edge
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.
- data/.gitignore +3 -0
- data/History.txt +46 -0
- data/MIT-LICENSE.txt +19 -0
- data/README.md +120 -0
- data/Rakefile +23 -0
- data/Thorfile +113 -0
- data/lib/rack/bug/autoloading.rb +25 -0
- data/lib/rack/bug/filtered_backtrace.rb +38 -0
- data/lib/rack/bug/options.rb +89 -0
- data/lib/rack/bug/panel.rb +50 -0
- data/lib/rack/bug/panel_app.rb +33 -0
- data/lib/rack/bug/panels/active_record_panel/activerecord_extensions.rb +18 -0
- data/lib/rack/bug/panels/active_record_panel.rb +45 -0
- data/lib/rack/bug/panels/cache_panel/dalli_extension.rb +16 -0
- data/lib/rack/bug/panels/cache_panel/memcache_extension.rb +129 -0
- data/lib/rack/bug/panels/cache_panel/panel_app.rb +48 -0
- data/lib/rack/bug/panels/cache_panel/stats.rb +97 -0
- data/lib/rack/bug/panels/cache_panel.rb +51 -0
- data/lib/rack/bug/panels/log_panel/logger_extension.rb +24 -0
- data/lib/rack/bug/panels/log_panel.rb +56 -0
- data/lib/rack/bug/panels/memory_panel.rb +27 -0
- data/lib/rack/bug/panels/mongo_panel/mongo_extension.rb +27 -0
- data/lib/rack/bug/panels/mongo_panel/stats.rb +48 -0
- data/lib/rack/bug/panels/mongo_panel.rb +44 -0
- data/lib/rack/bug/panels/rails_info_panel.rb +23 -0
- data/lib/rack/bug/panels/redis_panel/redis_extension.rb +28 -0
- data/lib/rack/bug/panels/redis_panel/stats.rb +52 -0
- data/lib/rack/bug/panels/redis_panel.rb +44 -0
- data/lib/rack/bug/panels/request_variables_panel.rb +52 -0
- data/lib/rack/bug/panels/sphinx_panel/sphinx_extension.rb +25 -0
- data/lib/rack/bug/panels/sphinx_panel/stats.rb +96 -0
- data/lib/rack/bug/panels/sphinx_panel.rb +44 -0
- data/lib/rack/bug/panels/sql_panel/panel_app.rb +37 -0
- data/lib/rack/bug/panels/sql_panel/query.rb +63 -0
- data/lib/rack/bug/panels/sql_panel/sql_extension.rb +11 -0
- data/lib/rack/bug/panels/sql_panel.rb +55 -0
- data/lib/rack/bug/panels/templates_panel/actionview_extension.rb +12 -0
- data/lib/rack/bug/panels/templates_panel/rendering.rb +67 -0
- data/lib/rack/bug/panels/templates_panel/trace.rb +34 -0
- data/lib/rack/bug/panels/templates_panel.rb +47 -0
- data/lib/rack/bug/panels/timer_panel.rb +40 -0
- data/lib/rack/bug/params_signature.rb +63 -0
- data/lib/rack/bug/public/__rack_bug__/bookmarklet.html +10 -0
- data/lib/rack/bug/public/__rack_bug__/bookmarklet.js +217 -0
- data/lib/rack/bug/public/__rack_bug__/bug.css +220 -0
- data/lib/rack/bug/public/__rack_bug__/bug.js +84 -0
- data/lib/rack/bug/public/__rack_bug__/jquery-1.3.2.js +4376 -0
- data/lib/rack/bug/public/__rack_bug__/jquery.tablesorter.min.js +1 -0
- data/lib/rack/bug/public/__rack_bug__/spinner.gif +0 -0
- data/lib/rack/bug/rack_static_bug_avoider.rb +16 -0
- data/lib/rack/bug/redirect_interceptor.rb +27 -0
- data/lib/rack/bug/render.rb +67 -0
- data/lib/rack/bug/toolbar.rb +64 -0
- data/lib/rack/bug/views/error.html.erb +16 -0
- data/lib/rack/bug/views/panels/active_record.html.erb +17 -0
- data/lib/rack/bug/views/panels/cache.html.erb +93 -0
- data/lib/rack/bug/views/panels/execute_sql.html.erb +38 -0
- data/lib/rack/bug/views/panels/explain_sql.html.erb +38 -0
- data/lib/rack/bug/views/panels/log.html.erb +21 -0
- data/lib/rack/bug/views/panels/mongo.html.erb +32 -0
- data/lib/rack/bug/views/panels/profile_sql.html.erb +38 -0
- data/lib/rack/bug/views/panels/rails_info.html.erb +19 -0
- data/lib/rack/bug/views/panels/redis.html.erb +46 -0
- data/lib/rack/bug/views/panels/request_variables.html.erb +29 -0
- data/lib/rack/bug/views/panels/sphinx.html.erb +32 -0
- data/lib/rack/bug/views/panels/sql.html.erb +41 -0
- data/lib/rack/bug/views/panels/templates.html.erb +7 -0
- data/lib/rack/bug/views/panels/timer.html.erb +19 -0
- data/lib/rack/bug/views/panels/view_cache.html.erb +19 -0
- data/lib/rack/bug/views/redirect.html.erb +16 -0
- data/lib/rack/bug/views/toolbar.html.erb +42 -0
- data/lib/rack/bug.rb +82 -0
- data/rack-bug.gemspec +155 -0
- data/spec/custom_matchers.rb +21 -0
- data/spec/fixtures/config.ru +8 -0
- data/spec/fixtures/dummy_panel.rb +2 -0
- data/spec/fixtures/sample_app.rb +46 -0
- data/spec/rack/bug/panels/active_record_panel_spec.rb +30 -0
- data/spec/rack/bug/panels/cache_panel_spec.rb +167 -0
- data/spec/rack/bug/panels/log_panel_spec.rb +43 -0
- data/spec/rack/bug/panels/memory_panel_spec.rb +22 -0
- data/spec/rack/bug/panels/mongo_panel_spec.rb +51 -0
- data/spec/rack/bug/panels/rails_info_panel_spec.rb +40 -0
- data/spec/rack/bug/panels/redis_panel_spec.rb +69 -0
- data/spec/rack/bug/panels/sql_panel_spec.rb +146 -0
- data/spec/rack/bug/panels/templates_panel_spec.rb +71 -0
- data/spec/rack/bug/panels/timer_panel_spec.rb +38 -0
- data/spec/rack/bug_spec.rb +137 -0
- data/spec/rcov.opts +1 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +44 -0
- metadata +245 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
|
2
|
+
|
3
|
+
class Rack::Bug
|
4
|
+
describe LogPanel do
|
5
|
+
before do
|
6
|
+
LogPanel.reset
|
7
|
+
rack_env "rack-bug.panel_classes", [LogPanel]
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "heading" do
|
11
|
+
it "displays 'Log'" do
|
12
|
+
response = get_via_rack "/"
|
13
|
+
response.should have_heading("Log")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "content" do
|
18
|
+
it "displays recorded log lines" do
|
19
|
+
LogPanel.record("This is a logged message", 0)
|
20
|
+
response = get_via_rack "/"
|
21
|
+
response.should contain("This is a logged message")
|
22
|
+
response.should contain("DEBUG")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "Extended Logger" do
|
27
|
+
it "does still return true/false for #add if class Logger" do
|
28
|
+
#AS::BufferedLogger returns the added string, Logger returns true/false
|
29
|
+
LOGGER.add(0, "foo").should == true
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
describe "With no logger defined" do
|
35
|
+
it "does not err out" do
|
36
|
+
logger = LOGGER
|
37
|
+
Object.send :remove_const, :LOGGER
|
38
|
+
lambda{ load("rack/bug/panels/log_panel/logger_extension.rb") }.should_not raise_error
|
39
|
+
::LOGGER = logger
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
|
3
|
+
|
4
|
+
class Rack::Bug
|
5
|
+
describe MemoryPanel do
|
6
|
+
before do
|
7
|
+
rack_env "rack-bug.panel_classes", [MemoryPanel]
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "heading" do
|
11
|
+
it "displays the total memory" do
|
12
|
+
response = get_via_rack "/"
|
13
|
+
response.should have_heading(/\d+ KB total/)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "displays the memory change during the request" do
|
17
|
+
response = get_via_rack "/"
|
18
|
+
response.should have_heading(/\d+ KB Δ/)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
|
2
|
+
$LOADED_FEATURES << "mongo.rb" #avoid dependency on mongo
|
3
|
+
|
4
|
+
class Rack::Bug
|
5
|
+
describe MongoPanel do
|
6
|
+
before do
|
7
|
+
MongoPanel.reset
|
8
|
+
rack_env "rack-bug.panel_classes", [MongoPanel]
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "heading" do
|
12
|
+
it "displays the total mongo time" do
|
13
|
+
response = get_via_rack "/"
|
14
|
+
response.should have_heading("Mongo: 0.00ms")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "content" do
|
19
|
+
describe "usage table" do
|
20
|
+
it "displays the total number of mongo calls" do
|
21
|
+
MongoPanel.record("db.user.user.find()") { }
|
22
|
+
response = get_via_rack "/"
|
23
|
+
|
24
|
+
# This causes a bus error:
|
25
|
+
# response.should have_selector("th:content('Total Calls') + td", :content => "1")
|
26
|
+
|
27
|
+
response.should have_row("#mongo_usage", "Total Calls", "1")
|
28
|
+
end
|
29
|
+
|
30
|
+
it "displays the total mongo time" do
|
31
|
+
response = get_via_rack "/"
|
32
|
+
response.should have_row("#mongo_usage", "Total Time", "0.00ms")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "breakdown" do
|
37
|
+
it "displays each mongo operation" do
|
38
|
+
MongoPanel.record("db.user.user.find()") { }
|
39
|
+
response = get_via_rack "/"
|
40
|
+
response.should have_row("#mongo_breakdown", "db.user.user.find()")
|
41
|
+
end
|
42
|
+
|
43
|
+
it "displays the time for mongo call" do
|
44
|
+
MongoPanel.record("db.user.user.find()") { }
|
45
|
+
response = get_via_rack "/"
|
46
|
+
response.should have_row("#mongo_breakdown", "db.user.user.find()", TIME_MS_REGEXP)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
|
2
|
+
|
3
|
+
class Rack::Bug
|
4
|
+
describe RailsInfoPanel do
|
5
|
+
before do
|
6
|
+
rack_env "rack-bug.panel_classes", [RailsInfoPanel]
|
7
|
+
|
8
|
+
unless defined?(Rails)
|
9
|
+
@added_rails = true
|
10
|
+
Object.const_set :Rails, Module.new
|
11
|
+
Rails::Info = Class.new do
|
12
|
+
def self.properties
|
13
|
+
[]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
after do
|
20
|
+
Object.send :remove_const, :Rails if @added_rails
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "heading" do
|
24
|
+
it "displays the Rails version" do
|
25
|
+
Rails.stub!(:version => "v2.3.0")
|
26
|
+
response = get_via_rack "/"
|
27
|
+
response.should have_heading("Rails v2.3.0")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "content" do
|
32
|
+
it "displays the Rails::Info properties" do
|
33
|
+
Rails.stub!(:version => "v2.3.0")
|
34
|
+
Rails::Info.stub!(:properties => [["Name", "Value"]])
|
35
|
+
response = get_via_rack "/"
|
36
|
+
response.should have_row("#rails_info", "Name", "Value")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
|
2
|
+
$LOADED_FEATURES << "redis.rb" #avoid dependency on redis
|
3
|
+
|
4
|
+
class Rack::Bug
|
5
|
+
describe RedisPanel do
|
6
|
+
before do
|
7
|
+
RedisPanel.reset
|
8
|
+
rack_env "rack-bug.panel_classes", [RedisPanel]
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "heading" do
|
12
|
+
it "displays the total redis time" do
|
13
|
+
response = get_via_rack "/"
|
14
|
+
response.should have_heading("Redis: 0.00ms")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "content" do
|
19
|
+
describe "usage table" do
|
20
|
+
it "displays the total number of redis calls" do
|
21
|
+
RedisPanel.record(["get, user:1"], Kernel.caller) { }
|
22
|
+
response = get_via_rack "/"
|
23
|
+
|
24
|
+
# This causes a bus error:
|
25
|
+
# response.should have_selector("th:content('Total Calls') + td", :content => "1")
|
26
|
+
|
27
|
+
response.should have_row("#redis_usage", "Total Calls", "1")
|
28
|
+
end
|
29
|
+
|
30
|
+
it "displays the total redis time" do
|
31
|
+
response = get_via_rack "/"
|
32
|
+
response.should have_row("#redis_usage", "Total Time", "0.00ms")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "breakdown" do
|
37
|
+
it "displays each redis operation" do
|
38
|
+
RedisPanel.record(["get, user:1"], Kernel.caller) { }
|
39
|
+
response = get_via_rack "/"
|
40
|
+
response.should have_row("#redis_breakdown", "get")
|
41
|
+
end
|
42
|
+
|
43
|
+
it "displays the time for redis call" do
|
44
|
+
RedisPanel.record(["get, user:1"], Kernel.caller) { }
|
45
|
+
response = get_via_rack "/"
|
46
|
+
response.should have_row("#redis_breakdown", "user:1", TIME_MS_REGEXP)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "displays the arguments for each redis call" do
|
50
|
+
RedisPanel.record(["get, user:1"], Kernel.caller) { }
|
51
|
+
response = get_via_rack "/"
|
52
|
+
response.should have_row("#redis_breakdown", "user:1", "get")
|
53
|
+
end
|
54
|
+
|
55
|
+
it "displays a link to show the backtrace when it's available" do
|
56
|
+
RedisPanel.record(["get, user:1"], Kernel.caller) { }
|
57
|
+
response = get_via_rack "/"
|
58
|
+
response.should have_row("#redis_breakdown", "user:1", "Show Backtrace")
|
59
|
+
end
|
60
|
+
|
61
|
+
it "does not display a link to show the backtrace when it's not available" do
|
62
|
+
RedisPanel.record(["get, user:1"], []) { }
|
63
|
+
response = get_via_rack "/"
|
64
|
+
response.should_not contain("Show Backtrace")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
|
2
|
+
|
3
|
+
class Rack::Bug
|
4
|
+
describe SQLPanel do
|
5
|
+
before do
|
6
|
+
SQLPanel.reset
|
7
|
+
rack_env "rack-bug.panel_classes", [SQLPanel]
|
8
|
+
|
9
|
+
unless defined?(ActiveRecord)
|
10
|
+
@added_rails = true
|
11
|
+
Object.const_set :ActiveRecord, Module.new
|
12
|
+
ActiveRecord.const_set :Base, Class.new
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
after do
|
17
|
+
Object.send :remove_const, :ActiveRecord if @added_active_record
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "heading" do
|
21
|
+
it "displays the total SQL query count" do
|
22
|
+
SQLPanel.record("SELECT NOW();") { }
|
23
|
+
response = get_via_rack "/"
|
24
|
+
response.should have_heading("1 Queries")
|
25
|
+
end
|
26
|
+
|
27
|
+
it "displays the total SQL time" do
|
28
|
+
SQLPanel.record("SELECT NOW();") { }
|
29
|
+
response = get_via_rack "/"
|
30
|
+
response.should have_heading(/Queries \(\d+\.\d{2}ms\)/)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "content" do
|
35
|
+
it "displays each executed SQL query" do
|
36
|
+
SQLPanel.record("SELECT NOW();") { }
|
37
|
+
response = get_via_rack "/"
|
38
|
+
response.should have_row("#sql", "SELECT NOW();")
|
39
|
+
end
|
40
|
+
|
41
|
+
it "displays the time of each executed SQL query" do
|
42
|
+
SQLPanel.record("SELECT NOW();") { }
|
43
|
+
response = get_via_rack "/"
|
44
|
+
response.should have_row("#sql", "SELECT NOW();", TIME_MS_REGEXP)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def stub_result(results = [[]])
|
49
|
+
columns = results.first
|
50
|
+
fields = columns.map { |c| stub("field", :name => c) }
|
51
|
+
rows = results[1..-1]
|
52
|
+
|
53
|
+
result = stub("result", :fetch_fields => fields)
|
54
|
+
result.stub!(:each).and_yield(*rows)
|
55
|
+
return result
|
56
|
+
end
|
57
|
+
|
58
|
+
def expect_query(sql, results)
|
59
|
+
conn = stub("connection")
|
60
|
+
ActiveRecord::Base.stub!(:connection => conn)
|
61
|
+
conn.should_receive(:execute).with(sql).and_return(stub_result(results))
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "execute_sql" do
|
65
|
+
it "displays the query results" do
|
66
|
+
rack_env "rack-bug.secret_key", "abc"
|
67
|
+
expect_query "SELECT username FROM users",
|
68
|
+
[["username"],
|
69
|
+
["bryan"]]
|
70
|
+
|
71
|
+
response = get_via_rack "/__rack_bug__/execute_sql", {:query => "SELECT username FROM users",
|
72
|
+
:hash => "6f286f55b75716e5c91f16d77d09fa73b353ebc1"}, {:xhr => true}
|
73
|
+
response.should contain("SELECT username FROM users")
|
74
|
+
response.should be_ok
|
75
|
+
end
|
76
|
+
|
77
|
+
it "is forbidden when the hash is missing or wrong" do
|
78
|
+
rack_env "rack-bug.secret_key", 'abc'
|
79
|
+
|
80
|
+
lambda {
|
81
|
+
get_via_rack "/__rack_bug__/execute_sql", {:query => "SELECT username FROM users",
|
82
|
+
:hash => "foobar"}, {:xhr => true}
|
83
|
+
}.should raise_error(SecurityError)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "is not available when the rack-bug.secret_key is nil" do
|
87
|
+
rack_env "rack-bug.secret_key", nil
|
88
|
+
|
89
|
+
lambda {
|
90
|
+
get_via_rack "/__rack_bug__/execute_sql", {:query => "SELECT username FROM users",
|
91
|
+
:hash => "6f286f55b75716e5c91f16d77d09fa73b353ebc1"}, {:xhr => true}
|
92
|
+
}.should raise_error(SecurityError)
|
93
|
+
end
|
94
|
+
|
95
|
+
it "is not available when the rack-bug.secret_key is an empty string" do
|
96
|
+
rack_env "rack-bug.secret_key", ""
|
97
|
+
|
98
|
+
lambda {
|
99
|
+
get_via_rack "/__rack_bug__/execute_sql", {:query => "SELECT username FROM users",
|
100
|
+
:hash => "6f286f55b75716e5c91f16d77d09fa73b353ebc1"}, {:xhr => true}
|
101
|
+
}.should raise_error(SecurityError)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe "explain_sql" do
|
106
|
+
it "displays the query explain plan" do
|
107
|
+
rack_env "rack-bug.secret_key", "abc"
|
108
|
+
expect_query "EXPLAIN SELECT username FROM users",
|
109
|
+
[["table"],
|
110
|
+
["users"]]
|
111
|
+
|
112
|
+
response = get_via_rack "/__rack_bug__/explain_sql", :query => "SELECT username FROM users",
|
113
|
+
:hash => "6f286f55b75716e5c91f16d77d09fa73b353ebc1"
|
114
|
+
response.should contain("SELECT username FROM users")
|
115
|
+
response.should be_ok
|
116
|
+
end
|
117
|
+
|
118
|
+
it "is forbidden when the hash is missing or wrong" do
|
119
|
+
rack_env "rack-bug.secret_key", 'abc'
|
120
|
+
|
121
|
+
lambda {
|
122
|
+
get_via_rack "/__rack_bug__/explain_sql", :query => "SELECT username FROM users",
|
123
|
+
:hash => "foobar"
|
124
|
+
}.should raise_error(SecurityError)
|
125
|
+
end
|
126
|
+
|
127
|
+
it "is not available when the rack-bug.secret_key is nil" do
|
128
|
+
rack_env "rack-bug.secret_key", nil
|
129
|
+
|
130
|
+
lambda {
|
131
|
+
get_via_rack "/__rack_bug__/explain_sql", :query => "SELECT username FROM users",
|
132
|
+
:hash => "6f286f55b75716e5c91f16d77d09fa73b353ebc1"
|
133
|
+
}.should raise_error(SecurityError)
|
134
|
+
end
|
135
|
+
|
136
|
+
it "is not available when the rack-bug.secret_key is an empty string" do
|
137
|
+
rack_env "rack-bug.secret_key", ""
|
138
|
+
|
139
|
+
lambda {
|
140
|
+
get_via_rack "/__rack_bug__/explain_sql", :query => "SELECT username FROM users",
|
141
|
+
:hash => "6f286f55b75716e5c91f16d77d09fa73b353ebc1"
|
142
|
+
}.should raise_error(SecurityError)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
|
2
|
+
|
3
|
+
class Rack::Bug
|
4
|
+
describe TemplatesPanel do
|
5
|
+
before do
|
6
|
+
TemplatesPanel.reset
|
7
|
+
rack_env "rack-bug.panel_classes", [TemplatesPanel]
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "heading" do
|
11
|
+
it "displays the total rendering time" do
|
12
|
+
response = get_via_rack "/"
|
13
|
+
response.should have_heading("Templates: 0.00ms")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "content" do
|
18
|
+
it "displays the template paths" do
|
19
|
+
TemplatesPanel.record("users/show") { }
|
20
|
+
response = get_via_rack "/"
|
21
|
+
response.should contain("users/show")
|
22
|
+
end
|
23
|
+
|
24
|
+
it "displays the template children" do
|
25
|
+
TemplatesPanel.record("users/show") do
|
26
|
+
TemplatesPanel.record("users/toolbar") { }
|
27
|
+
end
|
28
|
+
|
29
|
+
response = get_via_rack "/"
|
30
|
+
response.should have_selector("li", :content => "users/show") do |li|
|
31
|
+
li.should contain("users/toolbar")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "for templates that rendered templates" do
|
36
|
+
it "displays the total time" do
|
37
|
+
TemplatesPanel.record("users/show") do
|
38
|
+
TemplatesPanel.record("users/toolbar") { }
|
39
|
+
end
|
40
|
+
|
41
|
+
response = get_via_rack "/"
|
42
|
+
response.should have_selector("li", :content => "users/show") do |li|
|
43
|
+
li.should contain(TIME_MS_REGEXP)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it "displays the exclusive time" do
|
48
|
+
TemplatesPanel.record("users/show") do
|
49
|
+
TemplatesPanel.record("users/toolbar") { }
|
50
|
+
end
|
51
|
+
|
52
|
+
response = get_via_rack "/"
|
53
|
+
response.should have_selector("li", :content => "users/show") do |li|
|
54
|
+
li.should contain(/\d\.\d{2} exclusive/)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context "for leaf templates" do
|
60
|
+
it "does not display the exclusive time" do
|
61
|
+
TemplatesPanel.record("users/show") { }
|
62
|
+
|
63
|
+
response = get_via_rack "/"
|
64
|
+
response.should contain("users/show") do |li|
|
65
|
+
li.should_not contain("exclusive")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
|
2
|
+
|
3
|
+
class Rack::Bug
|
4
|
+
describe TimerPanel do
|
5
|
+
before do
|
6
|
+
rack_env "rack-bug.panel_classes", [TimerPanel]
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "heading" do
|
10
|
+
it "displays the elapsed time" do
|
11
|
+
response = get_via_rack "/"
|
12
|
+
response.should have_heading(TIME_MS_REGEXP)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "content" do
|
17
|
+
it "displays the user CPU time" do
|
18
|
+
response = get_via_rack "/"
|
19
|
+
response.should have_row("#timer", "User CPU time", TIME_MS_REGEXP)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "displays the system CPU time" do
|
23
|
+
response = get_via_rack "/"
|
24
|
+
response.should have_row("#timer", "System CPU time", TIME_MS_REGEXP)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "displays the total CPU time" do
|
28
|
+
response = get_via_rack "/"
|
29
|
+
response.should have_row("#timer", "Total CPU time", TIME_MS_REGEXP)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "displays the elapsed time" do
|
33
|
+
response = get_via_rack "/"
|
34
|
+
response.should have_row("#timer", "Elapsed time", TIME_MS_REGEXP)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Rack::Bug do
|
4
|
+
it "inserts the Rack::Bug toolbar" do
|
5
|
+
response = get "/"
|
6
|
+
response.should have_selector("div#rack_bug")
|
7
|
+
end
|
8
|
+
|
9
|
+
it "updates the Content-Length" do
|
10
|
+
response = get "/"
|
11
|
+
response["Content-Length"].should == response.body.size.to_s
|
12
|
+
end
|
13
|
+
|
14
|
+
it "serves the Rack::Bug assets under /__rack_bug__/" do
|
15
|
+
response = get "/__rack_bug__/bug.css"
|
16
|
+
response.should be_ok
|
17
|
+
end
|
18
|
+
|
19
|
+
it "modifies HTML responses with a charset" do
|
20
|
+
response = get "/", :content_type => "application/xhtml+xml; charset=utf-8"
|
21
|
+
response.should have_selector("div#rack_bug")
|
22
|
+
end
|
23
|
+
|
24
|
+
it "does not modify XMLHttpRequest responses" do
|
25
|
+
response = get "/", {}, { :xhr => true }
|
26
|
+
response.should_not have_selector("div#rack_bug")
|
27
|
+
end
|
28
|
+
|
29
|
+
it "modifies XHTML responses" do
|
30
|
+
response = get "/", :content_type => "application/xhtml+xml"
|
31
|
+
response.should have_selector("div#rack_bug")
|
32
|
+
end
|
33
|
+
|
34
|
+
it "does not modify non-HTML responses" do
|
35
|
+
response = get "/", :content_type => "text/csv"
|
36
|
+
response.should_not have_selector("div#rack_bug")
|
37
|
+
end
|
38
|
+
|
39
|
+
it "does not modify server errors" do
|
40
|
+
app.disable :raise_errors
|
41
|
+
response = get "/error"
|
42
|
+
app.enable :raise_errors
|
43
|
+
response.should_not have_selector("div#rack_bug")
|
44
|
+
end
|
45
|
+
|
46
|
+
context "redirected when not configured to intercept redirects" do
|
47
|
+
it "passes the redirect unmodified" do
|
48
|
+
response = get "/redirect"
|
49
|
+
response.status.should == 302
|
50
|
+
end
|
51
|
+
|
52
|
+
it "does not show the interception page" do
|
53
|
+
response = get "/redirect"
|
54
|
+
response.body.should_not contain("Location: /")
|
55
|
+
end
|
56
|
+
|
57
|
+
it "does not insert the toolbar" do
|
58
|
+
header 'cookie', ""
|
59
|
+
response = get "/redirect"
|
60
|
+
response.should_not have_selector("div#rack_bug")
|
61
|
+
end
|
62
|
+
|
63
|
+
it "does not insert the toolbar if even toolbar requested" do
|
64
|
+
response = get "/redirect"
|
65
|
+
response.should_not have_selector("div#rack_bug")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context "redirected when configured to intercept redirects" do
|
70
|
+
it "shows the interception page" do
|
71
|
+
response = get "/redirect", {}, "rack-bug.intercept_redirects" => true
|
72
|
+
response.should have_selector("div#rack_bug")
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should provide a link to the target URL" do
|
76
|
+
response = get "/redirect", {}, "rack-bug.intercept_redirects" => true
|
77
|
+
response.should have_selector("a[href='/']")
|
78
|
+
end
|
79
|
+
|
80
|
+
it "inserts the toolbar if requested" do
|
81
|
+
response = get "/redirect", {}, "rack-bug.intercept_redirects" => true
|
82
|
+
response.should have_selector("div#rack_bug")
|
83
|
+
end
|
84
|
+
|
85
|
+
it "does not inserts the toolbar if not requested" do
|
86
|
+
header 'cookie', ""
|
87
|
+
response = get "/redirect", {}, "rack-bug.intercept_redirects" => true
|
88
|
+
response.should_not have_selector("div#rack_bug")
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context "configured with an IP address restriction" do
|
93
|
+
before do
|
94
|
+
rack_env "rack-bug.ip_masks", [IPAddr.new("127.0.0.1/255.255.255.0")]
|
95
|
+
end
|
96
|
+
|
97
|
+
it "inserts the Rack::Bug toolbar when the IP matches" do
|
98
|
+
response = get_via_rack "/", {}, "REMOTE_ADDR" => "127.0.0.2"
|
99
|
+
response.should have_selector("div#rack_bug")
|
100
|
+
end
|
101
|
+
|
102
|
+
it "is disabled when the IP doesn't match" do
|
103
|
+
response = get_via_rack "/", {}, "REMOTE_ADDR" => "128.0.0.1"
|
104
|
+
response.should_not have_selector("div#rack_bug")
|
105
|
+
end
|
106
|
+
|
107
|
+
it "doesn't use any panels" do
|
108
|
+
DummyPanel.should_not_receive(:new)
|
109
|
+
rack_env "rack-bug.panel_classes", [DummyPanel]
|
110
|
+
get_via_rack "/", {}, "REMOTE_ADDR" => "128.0.0.1"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
context "configured with a password" do
|
115
|
+
before do
|
116
|
+
rack_env "rack-bug.password", "secret"
|
117
|
+
end
|
118
|
+
|
119
|
+
it "inserts the Rack::Bug toolbar when the password matches" do
|
120
|
+
sha = "545049d1c5e2a6e0dfefd37f9a9e0beb95241935"
|
121
|
+
set_cookie ["rack_bug_enabled=1", "rack_bug_password=#{sha}"]
|
122
|
+
response = get_via_rack "/"
|
123
|
+
response.should have_selector("div#rack_bug")
|
124
|
+
end
|
125
|
+
|
126
|
+
it "is disabled when the password doesn't match" do
|
127
|
+
response = get_via_rack "/"
|
128
|
+
response.should_not have_selector("div#rack_bug")
|
129
|
+
end
|
130
|
+
|
131
|
+
it "doesn't use any panels" do
|
132
|
+
DummyPanel.should_not_receive(:new)
|
133
|
+
rack_env "rack-bug.panel_classes", [DummyPanel]
|
134
|
+
get_via_rack "/"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
data/spec/rcov.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
-x gems,spec\/
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "spec"
|
3
|
+
require "webrat"
|
4
|
+
require "rack/test"
|
5
|
+
|
6
|
+
RAILS_ENV = "test"
|
7
|
+
|
8
|
+
$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__)) + '/lib'
|
9
|
+
$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__))
|
10
|
+
|
11
|
+
require "rack/bug"
|
12
|
+
require "spec/fixtures/sample_app"
|
13
|
+
require "spec/fixtures/dummy_panel"
|
14
|
+
require "spec/custom_matchers"
|
15
|
+
|
16
|
+
Spec::Runner.configure do |config|
|
17
|
+
TIME_MS_REGEXP = /\d+\.\d{2}ms/
|
18
|
+
|
19
|
+
config.include Rack::Test::Methods
|
20
|
+
config.include Webrat::Matchers
|
21
|
+
config.include CustomMatchers
|
22
|
+
|
23
|
+
config.before do
|
24
|
+
# This allows specs to record data outside the request
|
25
|
+
Rack::Bug.enable
|
26
|
+
|
27
|
+
# Set the cookie that triggers Rack::Bug under normal conditions
|
28
|
+
set_cookie "rack_bug_enabled=1"
|
29
|
+
end
|
30
|
+
|
31
|
+
def app
|
32
|
+
SampleApp
|
33
|
+
end
|
34
|
+
|
35
|
+
def rack_env(key, value)
|
36
|
+
@rack_env ||= {}
|
37
|
+
@rack_env[key] = value
|
38
|
+
end
|
39
|
+
|
40
|
+
def get_via_rack(uri, params = {}, env = {}, &block)
|
41
|
+
env = env.merge(@rack_env) if @rack_env
|
42
|
+
get(uri, params, env, &block)
|
43
|
+
end
|
44
|
+
end
|