better_errors 1.0.0 → 2.9.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 (64) hide show
  1. checksums.yaml +5 -5
  2. data/.coveralls.yml +1 -0
  3. data/.github/workflows/ci.yml +130 -0
  4. data/.github/workflows/release.yml +64 -0
  5. data/.gitignore +10 -5
  6. data/.ruby-version +1 -0
  7. data/CHANGELOG.md +3 -0
  8. data/Gemfile +7 -7
  9. data/LICENSE.txt +1 -1
  10. data/README.md +103 -33
  11. data/better_errors.gemspec +26 -8
  12. data/gemfiles/pry010.gemfile +10 -0
  13. data/gemfiles/pry011.gemfile +9 -0
  14. data/gemfiles/pry09.gemfile +9 -0
  15. data/gemfiles/rack.gemfile +8 -0
  16. data/gemfiles/rack_boc.gemfile +9 -0
  17. data/gemfiles/rails42.gemfile +10 -0
  18. data/gemfiles/rails42_boc.gemfile +11 -0
  19. data/gemfiles/rails42_haml.gemfile +11 -0
  20. data/gemfiles/rails50.gemfile +9 -0
  21. data/gemfiles/rails50_boc.gemfile +10 -0
  22. data/gemfiles/rails50_haml.gemfile +10 -0
  23. data/gemfiles/rails51.gemfile +9 -0
  24. data/gemfiles/rails51_boc.gemfile +10 -0
  25. data/gemfiles/rails51_haml.gemfile +10 -0
  26. data/gemfiles/rails52.gemfile +9 -0
  27. data/gemfiles/rails52_boc.gemfile +10 -0
  28. data/gemfiles/rails52_haml.gemfile +10 -0
  29. data/gemfiles/rails60.gemfile +8 -0
  30. data/gemfiles/rails60_boc.gemfile +9 -0
  31. data/gemfiles/rails60_haml.gemfile +9 -0
  32. data/lib/better_errors/code_formatter/html.rb +1 -1
  33. data/lib/better_errors/code_formatter.rb +7 -7
  34. data/lib/better_errors/editor.rb +99 -0
  35. data/lib/better_errors/error_page.rb +83 -49
  36. data/lib/better_errors/exception_extension.rb +17 -0
  37. data/lib/better_errors/exception_hint.rb +29 -0
  38. data/lib/better_errors/inspectable_value.rb +45 -0
  39. data/lib/better_errors/middleware.rb +101 -21
  40. data/lib/better_errors/raised_exception.rb +89 -0
  41. data/lib/better_errors/repl/basic.rb +3 -3
  42. data/lib/better_errors/repl/pry.rb +20 -10
  43. data/lib/better_errors/repl.rb +6 -4
  44. data/lib/better_errors/stack_frame.rb +48 -71
  45. data/lib/better_errors/templates/main.erb +167 -94
  46. data/lib/better_errors/templates/text.erb +6 -3
  47. data/lib/better_errors/templates/variable_info.erb +33 -24
  48. data/lib/better_errors/version.rb +1 -1
  49. data/lib/better_errors.rb +35 -37
  50. metadata +150 -46
  51. data/.travis.yml +0 -6
  52. data/Rakefile +0 -4
  53. data/ext/mkrf_conf.rb +0 -11
  54. data/lib/better_errors/core_ext/exception.rb +0 -21
  55. data/spec/better_errors/code_formatter_spec.rb +0 -92
  56. data/spec/better_errors/error_page_spec.rb +0 -76
  57. data/spec/better_errors/middleware_spec.rb +0 -112
  58. data/spec/better_errors/repl/basic_spec.rb +0 -18
  59. data/spec/better_errors/repl/pry_spec.rb +0 -36
  60. data/spec/better_errors/repl/shared_examples.rb +0 -18
  61. data/spec/better_errors/stack_frame_spec.rb +0 -161
  62. data/spec/better_errors/support/my_source.rb +0 -20
  63. data/spec/better_errors_spec.rb +0 -73
  64. data/spec/spec_helper.rb +0 -7
@@ -1,112 +0,0 @@
1
- require "spec_helper"
2
-
3
- module BetterErrors
4
- describe Middleware do
5
- let(:app) { Middleware.new(->env { ":)" }) }
6
- let(:exception) { RuntimeError.new("oh no :(") }
7
-
8
- it "passes non-error responses through" do
9
- app.call({}).should == ":)"
10
- end
11
-
12
- it "calls the internal methods" do
13
- app.should_receive :internal_call
14
- app.call("PATH_INFO" => "/__better_errors/1/preform_awesomness")
15
- end
16
-
17
- it "calls the internal methods on any subfolder path" do
18
- app.should_receive :internal_call
19
- app.call("PATH_INFO" => "/any_sub/folder/path/__better_errors/1/preform_awesomness")
20
- end
21
-
22
- it "shows the error page" do
23
- app.should_receive :show_error_page
24
- app.call("PATH_INFO" => "/__better_errors/")
25
- end
26
-
27
- it "shows the error page on any subfolder path" do
28
- app.should_receive :show_error_page
29
- app.call("PATH_INFO" => "/any_sub/folder/path/__better_errors/")
30
- end
31
-
32
- it "doesn't show the error page to a non-local address" do
33
- app.should_not_receive :better_errors_call
34
- app.call("REMOTE_ADDR" => "1.2.3.4")
35
- end
36
-
37
- it "shows to a whitelisted IP" do
38
- BetterErrors::Middleware.allow_ip! '77.55.33.11'
39
- app.should_receive :better_errors_call
40
- app.call("REMOTE_ADDR" => "77.55.33.11")
41
- end
42
-
43
- it "doesn't blow up when given a blank REMOTE_ADDR" do
44
- expect { app.call("REMOTE_ADDR" => " ") }.to_not raise_error
45
- end
46
-
47
- it "doesn't blow up when given an IP address with a zone index" do
48
- expect { app.call("REMOTE_ADDR" => "0:0:0:0:0:0:0:1%0" ) }.to_not raise_error
49
- end
50
-
51
- context "when requesting the /__better_errors manually" do
52
- let(:app) { Middleware.new(->env { ":)" }) }
53
-
54
- it "shows that no errors have been recorded" do
55
- status, headers, body = app.call("PATH_INFO" => "/__better_errors")
56
- body.join.should match /No errors have been recorded yet./
57
- end
58
-
59
- it "shows that no errors have been recorded on any subfolder path" do
60
- status, headers, body = app.call("PATH_INFO" => "/any_sub/folder/path/__better_errors")
61
- body.join.should match /No errors have been recorded yet./
62
- end
63
- end
64
-
65
- context "when handling an error" do
66
- let(:app) { Middleware.new(->env { raise exception }) }
67
-
68
- it "returns status 500" do
69
- status, headers, body = app.call({})
70
-
71
- status.should == 500
72
- end
73
-
74
- it "returns ExceptionWrapper's status_code" do
75
- ad_ew = double("ActionDispatch::ExceptionWrapper")
76
- ad_ew.stub('new').with({}, exception ){ double("ExceptionWrapper", status_code: 404) }
77
- stub_const('ActionDispatch::ExceptionWrapper', ad_ew)
78
-
79
- status, headers, body = app.call({})
80
-
81
- status.should == 404
82
- end
83
-
84
- it "returns UTF-8 error pages" do
85
- status, headers, body = app.call({})
86
-
87
- headers["Content-Type"].should match /charset=utf-8/
88
- end
89
-
90
- it "returns text pages by default" do
91
- status, headers, body = app.call({})
92
-
93
- headers["Content-Type"].should match /text\/plain/
94
- end
95
-
96
- it "returns HTML pages by default" do
97
- # Chrome's 'Accept' header looks similar this.
98
- status, headers, body = app.call("HTTP_ACCEPT" => "text/html,application/xhtml+xml;q=0.9,*/*")
99
-
100
- headers["Content-Type"].should match /text\/html/
101
- end
102
-
103
- it "logs the exception" do
104
- logger = Object.new
105
- logger.should_receive :fatal
106
- BetterErrors.stub(:logger).and_return(logger)
107
-
108
- app.call({})
109
- end
110
- end
111
- end
112
- end
@@ -1,18 +0,0 @@
1
- require "spec_helper"
2
- require "better_errors/repl/basic"
3
- require "better_errors/repl/shared_examples"
4
-
5
- module BetterErrors
6
- module REPL
7
- describe Basic do
8
- let(:fresh_binding) {
9
- local_a = 123
10
- binding
11
- }
12
-
13
- let(:repl) { Basic.new fresh_binding }
14
-
15
- it_behaves_like "a REPL provider"
16
- end
17
- end
18
- end
@@ -1,36 +0,0 @@
1
- require "spec_helper"
2
- require "pry"
3
- require "better_errors/repl/pry"
4
- require "better_errors/repl/shared_examples"
5
-
6
- module BetterErrors
7
- module REPL
8
- describe Pry do
9
- let(:fresh_binding) {
10
- local_a = 123
11
- binding
12
- }
13
-
14
- let(:repl) { Pry.new fresh_binding }
15
-
16
- it "does line continuation" do
17
- output, prompt, filled = repl.send_input ""
18
- output.should == "=> nil\n"
19
- prompt.should == ">>"
20
- filled.should == ""
21
-
22
- output, prompt, filled = repl.send_input "def f(x)"
23
- output.should == ""
24
- prompt.should == ".."
25
- filled.should == " "
26
-
27
- output, prompt, filled = repl.send_input "end"
28
- output.should == "=> nil\n"
29
- prompt.should == ">>"
30
- filled.should == ""
31
- end
32
-
33
- it_behaves_like "a REPL provider"
34
- end
35
- end
36
- end
@@ -1,18 +0,0 @@
1
- shared_examples_for "a REPL provider" do
2
- it "evaluates ruby code in a given context" do
3
- repl.send_input("local_a = 456")
4
- fresh_binding.eval("local_a").should == 456
5
- end
6
-
7
- it "returns a tuple of output and the new prompt" do
8
- output, prompt = repl.send_input("1 + 2")
9
- output.should == "=> 3\n"
10
- prompt.should == ">>"
11
- end
12
-
13
- it "doesn't barf if the code throws an exception" do
14
- output, prompt = repl.send_input("raise Exception")
15
- output.should include "Exception: Exception"
16
- prompt.should == ">>"
17
- end
18
- end
@@ -1,161 +0,0 @@
1
- require "spec_helper"
2
-
3
- module BetterErrors
4
- describe StackFrame do
5
- context "#application?" do
6
- it "is true for application filenames" do
7
- BetterErrors.stub(:application_root).and_return("/abc/xyz")
8
- frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index")
9
-
10
- frame.application?.should be_true
11
- end
12
-
13
- it "is false for everything else" do
14
- BetterErrors.stub(:application_root).and_return("/abc/xyz")
15
- frame = StackFrame.new("/abc/nope", 123, "foo")
16
-
17
- frame.application?.should be_false
18
- end
19
-
20
- it "doesn't care if no application_root is set" do
21
- frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index")
22
-
23
- frame.application?.should be_false
24
- end
25
- end
26
-
27
- context "#gem?" do
28
- it "is true for gem filenames" do
29
- Gem.stub(:path).and_return(["/abc/xyz"])
30
- frame = StackFrame.new("/abc/xyz/gems/whatever-1.2.3/lib/whatever.rb", 123, "foo")
31
-
32
- frame.gem?.should be_true
33
- end
34
-
35
- it "is false for everything else" do
36
- Gem.stub(:path).and_return(["/abc/xyz"])
37
- frame = StackFrame.new("/abc/nope", 123, "foo")
38
-
39
- frame.gem?.should be_false
40
- end
41
- end
42
-
43
- context "#application_path" do
44
- it "chops off the application root" do
45
- BetterErrors.stub(:application_root).and_return("/abc/xyz")
46
- frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index")
47
-
48
- frame.application_path.should == "app/controllers/crap_controller.rb"
49
- end
50
- end
51
-
52
- context "#gem_path" do
53
- it "chops of the gem path and stick (gem) there" do
54
- Gem.stub(:path).and_return(["/abc/xyz"])
55
- frame = StackFrame.new("/abc/xyz/gems/whatever-1.2.3/lib/whatever.rb", 123, "foo")
56
-
57
- frame.gem_path.should == "whatever (1.2.3) lib/whatever.rb"
58
- end
59
-
60
- it "prioritizes gem path over application path" do
61
- BetterErrors.stub(:application_root).and_return("/abc/xyz")
62
- Gem.stub(:path).and_return(["/abc/xyz/vendor"])
63
- frame = StackFrame.new("/abc/xyz/vendor/gems/whatever-1.2.3/lib/whatever.rb", 123, "foo")
64
-
65
- frame.gem_path.should == "whatever (1.2.3) lib/whatever.rb"
66
- end
67
- end
68
-
69
- context "#pretty_path" do
70
- it "returns #application_path for application paths" do
71
- BetterErrors.stub(:application_root).and_return("/abc/xyz")
72
- frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index")
73
- frame.pretty_path.should == frame.application_path
74
- end
75
-
76
- it "returns #gem_path for gem paths" do
77
- Gem.stub(:path).and_return(["/abc/xyz"])
78
- frame = StackFrame.new("/abc/xyz/gems/whatever-1.2.3/lib/whatever.rb", 123, "foo")
79
-
80
- frame.pretty_path.should == frame.gem_path
81
- end
82
- end
83
-
84
- it "special cases SyntaxErrors" do
85
- begin
86
- eval(%{ raise SyntaxError, "you wrote bad ruby!" }, nil, "my_file.rb", 123)
87
- rescue SyntaxError => syntax_error
88
- end
89
- frames = StackFrame.from_exception(syntax_error)
90
- frames.first.filename.should == "my_file.rb"
91
- frames.first.line.should == 123
92
- end
93
-
94
- it "doesn't blow up if no method name is given" do
95
- error = StandardError.allocate
96
-
97
- error.stub(:backtrace).and_return(["foo.rb:123"])
98
- frames = StackFrame.from_exception(error)
99
- frames.first.filename.should == "foo.rb"
100
- frames.first.line.should == 123
101
-
102
- error.stub(:backtrace).and_return(["foo.rb:123: this is an error message"])
103
- frames = StackFrame.from_exception(error)
104
- frames.first.filename.should == "foo.rb"
105
- frames.first.line.should == 123
106
- end
107
-
108
- it "ignores a backtrace line if its format doesn't make any sense at all" do
109
- error = StandardError.allocate
110
- error.stub(:backtrace).and_return(["foo.rb:123:in `foo'", "C:in `find'", "bar.rb:123:in `bar'"])
111
- frames = StackFrame.from_exception(error)
112
- frames.count.should == 2
113
- end
114
-
115
- it "doesn't blow up if a filename contains a colon" do
116
- error = StandardError.allocate
117
- error.stub(:backtrace).and_return(["crap:filename.rb:123"])
118
- frames = StackFrame.from_exception(error)
119
- frames.first.filename.should == "crap:filename.rb"
120
- end
121
-
122
- it "doesn't blow up with a BasicObject as frame binding" do
123
- obj = BasicObject.new
124
- def obj.my_binding
125
- ::Kernel.binding
126
- end
127
- frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index", obj.my_binding)
128
- if RUBY_VERSION >= "2.0.0"
129
- frame.class_name.should == 'BasicObject'
130
- else
131
- frame.class_name.should be_nil
132
- end
133
- end
134
-
135
- it "sets method names properly" do
136
- obj = "string"
137
- def obj.my_method
138
- begin
139
- raise "foo"
140
- rescue => err
141
- err
142
- end
143
- end
144
-
145
- frame = StackFrame.from_exception(obj.my_method).first
146
- if RUBY_VERSION >= "2.0.0"
147
- frame.method_name.should == "#my_method"
148
- frame.class_name.should == "String"
149
- else
150
- frame.method_name.should == "my_method"
151
- frame.class_name.should be_nil
152
- end
153
- end
154
-
155
- if RUBY_ENGINE == "java"
156
- it "doesn't blow up on a native Java exception" do
157
- expect { StackFrame.from_exception(java.lang.Exception.new) }.to_not raise_error
158
- end
159
- end
160
- end
161
- end
@@ -1,20 +0,0 @@
1
- one
2
- two
3
- three
4
- four
5
- five
6
- six
7
- seven
8
- eight
9
- nine
10
- ten
11
- eleven
12
- twelve
13
- thirteen
14
- fourteen
15
- fifteen
16
- sixteen
17
- seventeen
18
- eighteen
19
- nineteen
20
- twenty
@@ -1,73 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe BetterErrors do
4
- context ".editor" do
5
- it "defaults to textmate" do
6
- subject.editor["foo.rb", 123].should == "txmt://open?url=file://foo.rb&line=123"
7
- end
8
-
9
- it "url escapes the filename" do
10
- subject.editor["&.rb", 0].should == "txmt://open?url=file://%26.rb&line=0"
11
- end
12
-
13
- [:emacs, :emacsclient].each do |editor|
14
- it "uses emacs:// scheme when set to #{editor.inspect}" do
15
- subject.editor = editor
16
- subject.editor[].should start_with "emacs://"
17
- end
18
- end
19
-
20
- [:macvim, :mvim].each do |editor|
21
- it "uses mvim:// scheme when set to #{editor.inspect}" do
22
- subject.editor = editor
23
- subject.editor[].should start_with "mvim://"
24
- end
25
- end
26
-
27
- [:sublime, :subl, :st].each do |editor|
28
- it "uses subl:// scheme when set to #{editor.inspect}" do
29
- subject.editor = editor
30
- subject.editor[].should start_with "subl://"
31
- end
32
- end
33
-
34
- [:textmate, :txmt, :tm].each do |editor|
35
- it "uses txmt:// scheme when set to #{editor.inspect}" do
36
- subject.editor = editor
37
- subject.editor[].should start_with "txmt://"
38
- end
39
- end
40
-
41
- ["emacsclient", "/usr/local/bin/emacsclient"].each do |editor|
42
- it "uses emacs:// scheme when EDITOR=#{editor}" do
43
- ENV["EDITOR"] = editor
44
- subject.editor = subject.default_editor
45
- subject.editor[].should start_with "emacs://"
46
- end
47
- end
48
-
49
- ["mvim -f", "/usr/local/bin/mvim -f"].each do |editor|
50
- it "uses mvim:// scheme when EDITOR=#{editor}" do
51
- ENV["EDITOR"] = editor
52
- subject.editor = subject.default_editor
53
- subject.editor[].should start_with "mvim://"
54
- end
55
- end
56
-
57
- ["subl -w", "/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl"].each do |editor|
58
- it "uses mvim:// scheme when EDITOR=#{editor}" do
59
- ENV["EDITOR"] = editor
60
- subject.editor = subject.default_editor
61
- subject.editor[].should start_with "subl://"
62
- end
63
- end
64
-
65
- ["mate -w", "/usr/bin/mate -w"].each do |editor|
66
- it "uses txmt:// scheme when EDITOR=#{editor}" do
67
- ENV["EDITOR"] = editor
68
- subject.editor = subject.default_editor
69
- subject.editor[].should start_with "txmt://"
70
- end
71
- end
72
- end
73
- end
data/spec/spec_helper.rb DELETED
@@ -1,7 +0,0 @@
1
- require "simplecov"
2
- SimpleCov.start
3
-
4
- $: << File.expand_path("../../lib", __FILE__)
5
- ENV["EDITOR"] = nil
6
- require "better_errors"
7
- require "ostruct"