better_errors 1.0.0 → 2.0.0
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.
- checksums.yaml +4 -4
- data/.gitignore +7 -5
- data/.travis.yml +1 -3
- data/CHANGELOG.md +3 -0
- data/Gemfile +1 -1
- data/LICENSE.txt +1 -1
- data/README.md +12 -2
- data/Rakefile +12 -3
- data/better_errors.gemspec +3 -4
- data/lib/better_errors/error_page.rb +22 -33
- data/lib/better_errors/exception_extension.rb +17 -0
- data/lib/better_errors/middleware.rb +7 -7
- data/lib/better_errors/raised_exception.rb +66 -0
- data/lib/better_errors/repl/pry.rb +2 -2
- data/lib/better_errors/stack_frame.rb +19 -67
- data/lib/better_errors/templates/main.erb +63 -49
- data/lib/better_errors/templates/text.erb +2 -2
- data/lib/better_errors/version.rb +1 -1
- data/lib/better_errors.rb +7 -8
- data/spec/better_errors/middleware_spec.rb +42 -0
- data/spec/better_errors/raised_exception_spec.rb +52 -0
- data/spec/better_errors/repl/pry_spec.rb +5 -1
- data/spec/better_errors/stack_frame_spec.rb +26 -30
- data/spec/spec_helper.rb +2 -4
- data/spec/without_binding_of_caller.rb +9 -0
- metadata +35 -18
- data/ext/mkrf_conf.rb +0 -11
- data/lib/better_errors/core_ext/exception.rb +0 -21
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html>
|
|
3
3
|
<head>
|
|
4
|
-
<title><%= exception.
|
|
4
|
+
<title><%= exception.type %> at <%= request_path %></title>
|
|
5
5
|
</head>
|
|
6
6
|
<body>
|
|
7
7
|
<%# Stylesheets are placed in the <body> for Turbolinks compatibility. %>
|
|
@@ -180,6 +180,7 @@
|
|
|
180
180
|
padding-right: 20px;
|
|
181
181
|
overflow-y: auto;
|
|
182
182
|
word-wrap: break-word;
|
|
183
|
+
white-space: pre-wrap;
|
|
183
184
|
height: auto;
|
|
184
185
|
max-height: 7em;
|
|
185
186
|
}
|
|
@@ -443,13 +444,13 @@
|
|
|
443
444
|
font-weight: bold;
|
|
444
445
|
font-size: 10pt;
|
|
445
446
|
}
|
|
446
|
-
|
|
447
|
+
|
|
447
448
|
.trace_info .title .location a {
|
|
448
449
|
color:inherit;
|
|
449
450
|
text-decoration:none;
|
|
450
451
|
border-bottom:1px solid #aaaaaa;
|
|
451
452
|
}
|
|
452
|
-
|
|
453
|
+
|
|
453
454
|
.trace_info .title .location a:hover {
|
|
454
455
|
border-color:#666666;
|
|
455
456
|
}
|
|
@@ -472,7 +473,7 @@
|
|
|
472
473
|
padding-bottom:9px;
|
|
473
474
|
float:left;
|
|
474
475
|
}
|
|
475
|
-
|
|
476
|
+
|
|
476
477
|
.code_linenums span{
|
|
477
478
|
display:block;
|
|
478
479
|
padding:0 12px;
|
|
@@ -730,8 +731,8 @@
|
|
|
730
731
|
|
|
731
732
|
<div class='top'>
|
|
732
733
|
<header class="exception">
|
|
733
|
-
<h2><strong><%= exception.
|
|
734
|
-
<p><%=
|
|
734
|
+
<h2><strong><%= exception.type %></strong> <span>at <%= request_path %></span></h2>
|
|
735
|
+
<p><%= exception.message %></p>
|
|
735
736
|
</header>
|
|
736
737
|
</div>
|
|
737
738
|
|
|
@@ -767,8 +768,8 @@
|
|
|
767
768
|
<script>
|
|
768
769
|
(function() {
|
|
769
770
|
|
|
770
|
-
var OID =
|
|
771
|
-
|
|
771
|
+
var OID = "<%= id %>";
|
|
772
|
+
|
|
772
773
|
var previousFrame = null;
|
|
773
774
|
var previousFrameInfo = null;
|
|
774
775
|
var allFrames = document.querySelectorAll("ul.frames li");
|
|
@@ -786,68 +787,73 @@
|
|
|
786
787
|
}
|
|
787
788
|
};
|
|
788
789
|
}
|
|
789
|
-
|
|
790
|
+
|
|
790
791
|
function escapeHTML(html) {
|
|
791
792
|
return html.replace(/&/, "&").replace(/</g, "<");
|
|
792
793
|
}
|
|
793
|
-
|
|
794
|
+
|
|
794
795
|
function REPL(index) {
|
|
795
796
|
this.index = index;
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
797
|
+
|
|
798
|
+
var previousCommands = JSON.parse(localStorage.getItem("better_errors_previous_commands"));
|
|
799
|
+
if(previousCommands === null) {
|
|
800
|
+
localStorage.setItem("better_errors_previous_commands", JSON.stringify([]));
|
|
801
|
+
previousCommands = [];
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
this.previousCommandOffset = previousCommands.length;
|
|
799
805
|
}
|
|
800
|
-
|
|
806
|
+
|
|
801
807
|
REPL.all = [];
|
|
802
|
-
|
|
808
|
+
|
|
803
809
|
REPL.prototype.install = function(containerElement) {
|
|
804
810
|
this.container = containerElement;
|
|
805
|
-
|
|
811
|
+
|
|
806
812
|
this.promptElement = this.container.querySelector(".prompt span");
|
|
807
813
|
this.inputElement = this.container.querySelector("input");
|
|
808
814
|
this.outputElement = this.container.querySelector("pre");
|
|
809
|
-
|
|
815
|
+
|
|
810
816
|
var self = this;
|
|
811
817
|
this.inputElement.onkeydown = function(ev) {
|
|
812
818
|
self.onKeyDown(ev);
|
|
813
819
|
};
|
|
814
|
-
|
|
820
|
+
|
|
815
821
|
this.setPrompt(">>");
|
|
816
|
-
|
|
822
|
+
|
|
817
823
|
REPL.all[this.index] = this;
|
|
818
824
|
}
|
|
819
|
-
|
|
825
|
+
|
|
820
826
|
REPL.prototype.focus = function() {
|
|
821
827
|
this.inputElement.focus();
|
|
822
828
|
};
|
|
823
|
-
|
|
829
|
+
|
|
824
830
|
REPL.prototype.setPrompt = function(prompt) {
|
|
825
831
|
this._prompt = prompt;
|
|
826
832
|
this.promptElement.innerHTML = escapeHTML(prompt);
|
|
827
833
|
};
|
|
828
|
-
|
|
834
|
+
|
|
829
835
|
REPL.prototype.getInput = function() {
|
|
830
836
|
return this.inputElement.value;
|
|
831
837
|
};
|
|
832
|
-
|
|
838
|
+
|
|
833
839
|
REPL.prototype.setInput = function(text) {
|
|
834
840
|
this.inputElement.value = text;
|
|
835
|
-
|
|
841
|
+
|
|
836
842
|
if(this.inputElement.setSelectionRange) {
|
|
837
843
|
// set cursor to end of input
|
|
838
844
|
this.inputElement.setSelectionRange(text.length, text.length);
|
|
839
845
|
}
|
|
840
846
|
};
|
|
841
|
-
|
|
847
|
+
|
|
842
848
|
REPL.prototype.writeRawOutput = function(output) {
|
|
843
849
|
this.outputElement.innerHTML += output;
|
|
844
850
|
this.outputElement.scrollTop = this.outputElement.scrollHeight;
|
|
845
851
|
};
|
|
846
|
-
|
|
852
|
+
|
|
847
853
|
REPL.prototype.writeOutput = function(output) {
|
|
848
854
|
this.writeRawOutput(escapeHTML(output));
|
|
849
855
|
};
|
|
850
|
-
|
|
856
|
+
|
|
851
857
|
REPL.prototype.sendInput = function(line) {
|
|
852
858
|
var self = this;
|
|
853
859
|
apiCall("eval", { "index": this.index, source: line }, function(response) {
|
|
@@ -861,48 +867,56 @@
|
|
|
861
867
|
self.setInput(response.prefilled_input);
|
|
862
868
|
});
|
|
863
869
|
};
|
|
864
|
-
|
|
870
|
+
|
|
865
871
|
REPL.prototype.onEnterKey = function() {
|
|
866
872
|
var text = this.getInput();
|
|
867
873
|
if(text != "" && text !== undefined) {
|
|
868
|
-
|
|
874
|
+
var previousCommands = JSON.parse(localStorage.getItem("better_errors_previous_commands"));
|
|
875
|
+
this.previousCommandOffset = previousCommands.push(text);
|
|
876
|
+
if(previousCommands.length > 100) {
|
|
877
|
+
previousCommands.splice(0, 1);
|
|
878
|
+
}
|
|
879
|
+
localStorage.setItem("better_errors_previous_commands", JSON.stringify(previousCommands));
|
|
869
880
|
}
|
|
870
881
|
this.setInput("");
|
|
871
882
|
this.sendInput(text);
|
|
872
883
|
};
|
|
873
|
-
|
|
884
|
+
|
|
874
885
|
REPL.prototype.onNavigateHistory = function(direction) {
|
|
875
886
|
this.previousCommandOffset += direction;
|
|
876
|
-
|
|
887
|
+
var previousCommands = JSON.parse(localStorage.getItem("better_errors_previous_commands"));
|
|
888
|
+
|
|
877
889
|
if(this.previousCommandOffset < 0) {
|
|
878
890
|
this.previousCommandOffset = -1;
|
|
879
891
|
this.setInput("");
|
|
880
892
|
return;
|
|
881
893
|
}
|
|
882
|
-
|
|
883
|
-
if(this.previousCommandOffset >=
|
|
884
|
-
this.previousCommandOffset =
|
|
894
|
+
|
|
895
|
+
if(this.previousCommandOffset >= previousCommands.length) {
|
|
896
|
+
this.previousCommandOffset = previousCommands.length;
|
|
885
897
|
this.setInput("");
|
|
886
898
|
return;
|
|
887
899
|
}
|
|
888
|
-
|
|
889
|
-
this.setInput(
|
|
900
|
+
|
|
901
|
+
this.setInput(previousCommands[this.previousCommandOffset]);
|
|
890
902
|
};
|
|
891
|
-
|
|
903
|
+
|
|
892
904
|
REPL.prototype.onKeyDown = function(ev) {
|
|
893
905
|
if(ev.keyCode == 13) {
|
|
894
906
|
this.onEnterKey();
|
|
895
|
-
} else if(ev.keyCode == 38) {
|
|
896
|
-
// the user pressed the up arrow
|
|
907
|
+
} else if(ev.keyCode == 38 || (ev.ctrlKey && ev.keyCode == 80)) {
|
|
908
|
+
// the user pressed the up arrow or Ctrl-P
|
|
897
909
|
this.onNavigateHistory(-1);
|
|
910
|
+
ev.preventDefault();
|
|
898
911
|
return false;
|
|
899
|
-
} else if(ev.keyCode == 40) {
|
|
900
|
-
// the user pressed the down arrow
|
|
912
|
+
} else if(ev.keyCode == 40 || (ev.ctrlKey && ev.keyCode == 78)) {
|
|
913
|
+
// the user pressed the down arrow or Ctrl-N
|
|
901
914
|
this.onNavigateHistory(1);
|
|
915
|
+
ev.preventDefault();
|
|
902
916
|
return false;
|
|
903
917
|
}
|
|
904
918
|
};
|
|
905
|
-
|
|
919
|
+
|
|
906
920
|
function switchTo(el) {
|
|
907
921
|
if(previousFrameInfo) previousFrameInfo.style.display = "none";
|
|
908
922
|
previousFrameInfo = el;
|
|
@@ -937,7 +951,7 @@
|
|
|
937
951
|
});
|
|
938
952
|
}
|
|
939
953
|
}
|
|
940
|
-
|
|
954
|
+
|
|
941
955
|
for(var i = 0; i < allFrames.length; i++) {
|
|
942
956
|
(function(i, el) {
|
|
943
957
|
var el = allFrames[i];
|
|
@@ -947,12 +961,12 @@
|
|
|
947
961
|
}
|
|
948
962
|
el.className = "selected";
|
|
949
963
|
previousFrame = el;
|
|
950
|
-
|
|
964
|
+
|
|
951
965
|
selectFrameInfo(el.attributes["data-index"].value);
|
|
952
966
|
};
|
|
953
967
|
})(i);
|
|
954
968
|
}
|
|
955
|
-
|
|
969
|
+
|
|
956
970
|
// Click the first application frame
|
|
957
971
|
(
|
|
958
972
|
document.querySelector(".frames li.application") ||
|
|
@@ -968,7 +982,7 @@
|
|
|
968
982
|
var applicationFramesButtonIsInstalled = false;
|
|
969
983
|
var applicationFramesButton = document.getElementById("application_frames");
|
|
970
984
|
var allFramesButton = document.getElementById("all_frames");
|
|
971
|
-
|
|
985
|
+
|
|
972
986
|
// The application frames button only needs to be bound if
|
|
973
987
|
// there are actually any application frames to look at.
|
|
974
988
|
var installApplicationFramesButton = function() {
|
|
@@ -984,10 +998,10 @@
|
|
|
984
998
|
}
|
|
985
999
|
return false;
|
|
986
1000
|
};
|
|
987
|
-
|
|
1001
|
+
|
|
988
1002
|
applicationFramesButtonIsInstalled = true;
|
|
989
1003
|
}
|
|
990
|
-
|
|
1004
|
+
|
|
991
1005
|
allFramesButton.onclick = function() {
|
|
992
1006
|
if(applicationFramesButtonIsInstalled) {
|
|
993
1007
|
applicationFramesButton.className = "";
|
|
@@ -999,7 +1013,7 @@
|
|
|
999
1013
|
}
|
|
1000
1014
|
return false;
|
|
1001
1015
|
};
|
|
1002
|
-
|
|
1016
|
+
|
|
1003
1017
|
// If there are no application frames, select the 'All Frames'
|
|
1004
1018
|
// tab by default.
|
|
1005
1019
|
if(applicationFramesCount > 0) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
<%== text_heading("=", "%s at %s" % [exception.
|
|
1
|
+
<%== text_heading("=", "%s at %s" % [exception.type, request_path]) %>
|
|
2
2
|
|
|
3
|
-
> <%==
|
|
3
|
+
> <%== exception.message %>
|
|
4
4
|
<% if backtrace_frames.any? %>
|
|
5
5
|
|
|
6
6
|
<%== text_heading("-", "%s, line %i" % [first_frame.pretty_path, first_frame.line]) %>
|
data/lib/better_errors.rb
CHANGED
|
@@ -3,12 +3,13 @@ require "erubis"
|
|
|
3
3
|
require "coderay"
|
|
4
4
|
require "uri"
|
|
5
5
|
|
|
6
|
-
require "better_errors/
|
|
6
|
+
require "better_errors/code_formatter"
|
|
7
7
|
require "better_errors/error_page"
|
|
8
|
-
require "better_errors/stack_frame"
|
|
9
8
|
require "better_errors/middleware"
|
|
10
|
-
require "better_errors/
|
|
9
|
+
require "better_errors/raised_exception"
|
|
11
10
|
require "better_errors/repl"
|
|
11
|
+
require "better_errors/stack_frame"
|
|
12
|
+
require "better_errors/version"
|
|
12
13
|
|
|
13
14
|
module BetterErrors
|
|
14
15
|
POSSIBLE_EDITOR_PRESETS = [
|
|
@@ -134,14 +135,12 @@ module BetterErrors
|
|
|
134
135
|
BetterErrors.editor = default_editor
|
|
135
136
|
end
|
|
136
137
|
|
|
137
|
-
|
|
138
|
-
gem "binding_of_caller", "0.7.2"
|
|
138
|
+
begin
|
|
139
139
|
require "binding_of_caller"
|
|
140
|
+
require "better_errors/exception_extension"
|
|
140
141
|
BetterErrors.binding_of_caller_available = true
|
|
141
|
-
|
|
142
|
+
rescue LoadError => e
|
|
142
143
|
BetterErrors.binding_of_caller_available = false
|
|
143
144
|
end
|
|
144
145
|
|
|
145
|
-
require "better_errors/core_ext/exception"
|
|
146
|
-
|
|
147
146
|
require "better_errors/rails" if defined? Rails::Railtie
|
|
@@ -40,6 +40,14 @@ module BetterErrors
|
|
|
40
40
|
app.call("REMOTE_ADDR" => "77.55.33.11")
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
+
it "respects the X-Forwarded-For header" do
|
|
44
|
+
app.should_not_receive :better_errors_call
|
|
45
|
+
app.call(
|
|
46
|
+
"REMOTE_ADDR" => "127.0.0.1",
|
|
47
|
+
"HTTP_X_FORWARDED_FOR" => "1.2.3.4",
|
|
48
|
+
)
|
|
49
|
+
end
|
|
50
|
+
|
|
43
51
|
it "doesn't blow up when given a blank REMOTE_ADDR" do
|
|
44
52
|
expect { app.call("REMOTE_ADDR" => " ") }.to_not raise_error
|
|
45
53
|
end
|
|
@@ -71,6 +79,40 @@ module BetterErrors
|
|
|
71
79
|
status.should == 500
|
|
72
80
|
end
|
|
73
81
|
|
|
82
|
+
context "original_exception" do
|
|
83
|
+
class OriginalExceptionException < Exception
|
|
84
|
+
attr_reader :original_exception
|
|
85
|
+
|
|
86
|
+
def initialize(message, original_exception = nil)
|
|
87
|
+
super(message)
|
|
88
|
+
@original_exception = original_exception
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it "shows Original Exception if it responds_to and has an original_exception" do
|
|
93
|
+
app = Middleware.new(->env {
|
|
94
|
+
raise OriginalExceptionException.new("Other Exception", Exception.new("Original Exception"))
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
status, _, body = app.call({})
|
|
98
|
+
|
|
99
|
+
status.should == 500
|
|
100
|
+
body.join.should_not match(/Other Exception/)
|
|
101
|
+
body.join.should match(/Original Exception/)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it "won't crash if the exception responds_to but doesn't have an original_exception" do
|
|
105
|
+
app = Middleware.new(->env {
|
|
106
|
+
raise OriginalExceptionException.new("Other Exception")
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
status, _, body = app.call({})
|
|
110
|
+
|
|
111
|
+
status.should == 500
|
|
112
|
+
body.join.should match(/Other Exception/)
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
74
116
|
it "returns ExceptionWrapper's status_code" do
|
|
75
117
|
ad_ew = double("ActionDispatch::ExceptionWrapper")
|
|
76
118
|
ad_ew.stub('new').with({}, exception ){ double("ExceptionWrapper", status_code: 404) }
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
module BetterErrors
|
|
4
|
+
describe RaisedException do
|
|
5
|
+
let(:exception) { RuntimeError.new("whoops") }
|
|
6
|
+
subject { RaisedException.new(exception) }
|
|
7
|
+
|
|
8
|
+
its(:exception) { should == exception }
|
|
9
|
+
its(:message) { should == "whoops" }
|
|
10
|
+
its(:type) { should == RuntimeError }
|
|
11
|
+
|
|
12
|
+
context "when the exception wraps another exception" do
|
|
13
|
+
let(:original_exception) { RuntimeError.new("something went wrong!") }
|
|
14
|
+
let(:exception) { double(:original_exception => original_exception) }
|
|
15
|
+
|
|
16
|
+
its(:exception) { should == original_exception }
|
|
17
|
+
its(:message) { should == "something went wrong!" }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context "when the exception is a syntax error" do
|
|
21
|
+
let(:exception) { SyntaxError.new("foo.rb:123: you made a typo!") }
|
|
22
|
+
|
|
23
|
+
its(:message) { should == "you made a typo!" }
|
|
24
|
+
its(:type) { should == SyntaxError }
|
|
25
|
+
|
|
26
|
+
it "has the right filename and line number in the backtrace" do
|
|
27
|
+
subject.backtrace.first.filename.should == "foo.rb"
|
|
28
|
+
subject.backtrace.first.line.should == 123
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
context "when the exception is a HAML syntax error" do
|
|
33
|
+
before do
|
|
34
|
+
stub_const("Haml::SyntaxError", Class.new(SyntaxError))
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
let(:exception) {
|
|
38
|
+
Haml::SyntaxError.new("you made a typo!").tap do |ex|
|
|
39
|
+
ex.set_backtrace(["foo.rb:123", "haml/internals/blah.rb:123456"])
|
|
40
|
+
end
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
its(:message) { should == "you made a typo!" }
|
|
44
|
+
its(:type) { should == Haml::SyntaxError }
|
|
45
|
+
|
|
46
|
+
it "has the right filename and line number in the backtrace" do
|
|
47
|
+
subject.backtrace.first.filename.should == "foo.rb"
|
|
48
|
+
subject.backtrace.first.line.should == 123
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -25,7 +25,11 @@ module BetterErrors
|
|
|
25
25
|
filled.should == " "
|
|
26
26
|
|
|
27
27
|
output, prompt, filled = repl.send_input "end"
|
|
28
|
-
|
|
28
|
+
if RUBY_VERSION >= "2.1.0"
|
|
29
|
+
output.should == "=> :f\n"
|
|
30
|
+
else
|
|
31
|
+
output.should == "=> nil\n"
|
|
32
|
+
end
|
|
29
33
|
prompt.should == ">>"
|
|
30
34
|
filled.should == ""
|
|
31
35
|
end
|
|
@@ -6,77 +6,77 @@ module BetterErrors
|
|
|
6
6
|
it "is true for application filenames" do
|
|
7
7
|
BetterErrors.stub(:application_root).and_return("/abc/xyz")
|
|
8
8
|
frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index")
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
frame.application?.should be_true
|
|
11
11
|
end
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
it "is false for everything else" do
|
|
14
14
|
BetterErrors.stub(:application_root).and_return("/abc/xyz")
|
|
15
15
|
frame = StackFrame.new("/abc/nope", 123, "foo")
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
frame.application?.should be_false
|
|
18
18
|
end
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
it "doesn't care if no application_root is set" do
|
|
21
21
|
frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index")
|
|
22
|
-
|
|
22
|
+
|
|
23
23
|
frame.application?.should be_false
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
|
-
|
|
26
|
+
|
|
27
27
|
context "#gem?" do
|
|
28
28
|
it "is true for gem filenames" do
|
|
29
29
|
Gem.stub(:path).and_return(["/abc/xyz"])
|
|
30
30
|
frame = StackFrame.new("/abc/xyz/gems/whatever-1.2.3/lib/whatever.rb", 123, "foo")
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
frame.gem?.should be_true
|
|
33
33
|
end
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
it "is false for everything else" do
|
|
36
36
|
Gem.stub(:path).and_return(["/abc/xyz"])
|
|
37
37
|
frame = StackFrame.new("/abc/nope", 123, "foo")
|
|
38
|
-
|
|
38
|
+
|
|
39
39
|
frame.gem?.should be_false
|
|
40
40
|
end
|
|
41
41
|
end
|
|
42
|
-
|
|
42
|
+
|
|
43
43
|
context "#application_path" do
|
|
44
44
|
it "chops off the application root" do
|
|
45
45
|
BetterErrors.stub(:application_root).and_return("/abc/xyz")
|
|
46
46
|
frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index")
|
|
47
|
-
|
|
47
|
+
|
|
48
48
|
frame.application_path.should == "app/controllers/crap_controller.rb"
|
|
49
49
|
end
|
|
50
50
|
end
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
context "#gem_path" do
|
|
53
53
|
it "chops of the gem path and stick (gem) there" do
|
|
54
54
|
Gem.stub(:path).and_return(["/abc/xyz"])
|
|
55
55
|
frame = StackFrame.new("/abc/xyz/gems/whatever-1.2.3/lib/whatever.rb", 123, "foo")
|
|
56
|
-
|
|
56
|
+
|
|
57
57
|
frame.gem_path.should == "whatever (1.2.3) lib/whatever.rb"
|
|
58
58
|
end
|
|
59
|
-
|
|
59
|
+
|
|
60
60
|
it "prioritizes gem path over application path" do
|
|
61
61
|
BetterErrors.stub(:application_root).and_return("/abc/xyz")
|
|
62
62
|
Gem.stub(:path).and_return(["/abc/xyz/vendor"])
|
|
63
63
|
frame = StackFrame.new("/abc/xyz/vendor/gems/whatever-1.2.3/lib/whatever.rb", 123, "foo")
|
|
64
|
-
|
|
64
|
+
|
|
65
65
|
frame.gem_path.should == "whatever (1.2.3) lib/whatever.rb"
|
|
66
66
|
end
|
|
67
67
|
end
|
|
68
|
-
|
|
68
|
+
|
|
69
69
|
context "#pretty_path" do
|
|
70
70
|
it "returns #application_path for application paths" do
|
|
71
71
|
BetterErrors.stub(:application_root).and_return("/abc/xyz")
|
|
72
72
|
frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index")
|
|
73
73
|
frame.pretty_path.should == frame.application_path
|
|
74
74
|
end
|
|
75
|
-
|
|
75
|
+
|
|
76
76
|
it "returns #gem_path for gem paths" do
|
|
77
77
|
Gem.stub(:path).and_return(["/abc/xyz"])
|
|
78
78
|
frame = StackFrame.new("/abc/xyz/gems/whatever-1.2.3/lib/whatever.rb", 123, "foo")
|
|
79
|
-
|
|
79
|
+
|
|
80
80
|
frame.pretty_path.should == frame.gem_path
|
|
81
81
|
end
|
|
82
82
|
end
|
|
@@ -90,28 +90,28 @@ module BetterErrors
|
|
|
90
90
|
frames.first.filename.should == "my_file.rb"
|
|
91
91
|
frames.first.line.should == 123
|
|
92
92
|
end
|
|
93
|
-
|
|
93
|
+
|
|
94
94
|
it "doesn't blow up if no method name is given" do
|
|
95
95
|
error = StandardError.allocate
|
|
96
|
-
|
|
96
|
+
|
|
97
97
|
error.stub(:backtrace).and_return(["foo.rb:123"])
|
|
98
98
|
frames = StackFrame.from_exception(error)
|
|
99
99
|
frames.first.filename.should == "foo.rb"
|
|
100
100
|
frames.first.line.should == 123
|
|
101
|
-
|
|
101
|
+
|
|
102
102
|
error.stub(:backtrace).and_return(["foo.rb:123: this is an error message"])
|
|
103
103
|
frames = StackFrame.from_exception(error)
|
|
104
104
|
frames.first.filename.should == "foo.rb"
|
|
105
105
|
frames.first.line.should == 123
|
|
106
106
|
end
|
|
107
|
-
|
|
107
|
+
|
|
108
108
|
it "ignores a backtrace line if its format doesn't make any sense at all" do
|
|
109
109
|
error = StandardError.allocate
|
|
110
110
|
error.stub(:backtrace).and_return(["foo.rb:123:in `foo'", "C:in `find'", "bar.rb:123:in `bar'"])
|
|
111
111
|
frames = StackFrame.from_exception(error)
|
|
112
112
|
frames.count.should == 2
|
|
113
113
|
end
|
|
114
|
-
|
|
114
|
+
|
|
115
115
|
it "doesn't blow up if a filename contains a colon" do
|
|
116
116
|
error = StandardError.allocate
|
|
117
117
|
error.stub(:backtrace).and_return(["crap:filename.rb:123"])
|
|
@@ -125,11 +125,7 @@ module BetterErrors
|
|
|
125
125
|
::Kernel.binding
|
|
126
126
|
end
|
|
127
127
|
frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index", obj.my_binding)
|
|
128
|
-
|
|
129
|
-
frame.class_name.should == 'BasicObject'
|
|
130
|
-
else
|
|
131
|
-
frame.class_name.should be_nil
|
|
132
|
-
end
|
|
128
|
+
frame.class_name.should == 'BasicObject'
|
|
133
129
|
end
|
|
134
130
|
|
|
135
131
|
it "sets method names properly" do
|
|
@@ -143,12 +139,12 @@ module BetterErrors
|
|
|
143
139
|
end
|
|
144
140
|
|
|
145
141
|
frame = StackFrame.from_exception(obj.my_method).first
|
|
146
|
-
if
|
|
142
|
+
if BetterErrors.binding_of_caller_available?
|
|
147
143
|
frame.method_name.should == "#my_method"
|
|
148
144
|
frame.class_name.should == "String"
|
|
149
145
|
else
|
|
150
146
|
frame.method_name.should == "my_method"
|
|
151
|
-
frame.class_name.should
|
|
147
|
+
frame.class_name.should == nil
|
|
152
148
|
end
|
|
153
149
|
end
|
|
154
150
|
|
data/spec/spec_helper.rb
CHANGED