better_errors 2.1.1 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of better_errors might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5ae01bfc76b45f6af1df26c7268229088f8de251
4
- data.tar.gz: f95f617f84e01f1641bf193d735d45d85360b768
3
+ metadata.gz: d53ee50b3a870061cf9298e5225635771043d6d7
4
+ data.tar.gz: b4280966bd31d24f4f4cb12ea54c1eea11bccdaa
5
5
  SHA512:
6
- metadata.gz: 4881b5a147d85c9c7ed116a8838e45745bd95958df71dea8934e0b5601fd32cde2a016bbc419a855f9e29dd8e6bab322fcae8d676a78ede120d134809dac29b7
7
- data.tar.gz: 6fb75468216fc264250e8f6726d47689025352441701cb83b2c125b541ac389c491da6ba8b3eeded2759b99be47f5c0cd103b54315122d7a33905261d02d4cca
6
+ metadata.gz: e068142eaef86037e0cc6088672158a0a9d021e49e7fe9a823c888d1f319181e07b18a03852b46da4a6d9a0db49f6d420ac7359ceb6ec4a35549bb56b403bec5
7
+ data.tar.gz: 9c184752196c2cf65b7dba20f94cf3b47428c6fd067c880ffa452bca8ed2fa6d3e84e5cd64ae6e295199622fe4e1ff2d6d09979d2a35e0b9bf36d38c6ebfdd33
@@ -2,5 +2,8 @@ sudo: false
2
2
  language: ruby
3
3
  cache: bundler
4
4
  rvm:
5
- - 2.1.0
6
- - 2.0.0
5
+ - 2.0
6
+ - 2.1
7
+ - 2.2
8
+ - 2.3
9
+ - 2.4
data/Gemfile CHANGED
@@ -3,8 +3,9 @@ source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  gem "rake"
6
- gem "rack"
7
- gem "rspec", "2.14.1"
6
+ gem "rack", "1.6.4"
7
+ gem "rspec", "3.5.0"
8
+ gem "rspec-its"
8
9
  gem "binding_of_caller", platforms: :ruby
9
10
  gem "pry", "0.9.12"
10
11
  gem "yard"
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012-2015 Charlie Somerville
1
+ Copyright (c) 2012-2016 Charlie Somerville
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -6,10 +6,14 @@ Better Errors replaces the standard Rails error page with a much better and more
6
6
 
7
7
  ## Features
8
8
 
9
+ For screenshots of these features, [see the wiki](https://github.com/charliesome/better_errors/wiki).
10
+
9
11
  * Full stack trace
10
12
  * Source code inspection for all stack frames (with highlighting)
11
13
  * Local and instance variable inspection
12
- * Live REPL on every stack frame
14
+ * Live shell (REPL) on every stack frame
15
+ * Links directly to the source line in your editor
16
+ * Useful information in non-HTML requests
13
17
 
14
18
  ## Installation
15
19
 
@@ -95,6 +99,14 @@ in `development`. Another option would be to use Webrick, Mongrel, Thin,
95
99
  or another single-process server as your `rails server`, when you are trying
96
100
  to troubleshoot an issue in development.
97
101
 
102
+ ##Specify editor to open files in
103
+
104
+ ```ruby
105
+ # e.g. in config/initializers/better_errors.rb
106
+ # Other preset values are [:mvim, :macvim, :textmate, :txmt, :tm, :sublime, :subl, :st]
107
+ BetterErrors.editor = :mvim
108
+ ```
109
+
98
110
  ## Get in touch!
99
111
 
100
112
  If you're using better_errors, I'd love to hear from you. Drop me a line and tell me what you think!
@@ -58,6 +58,14 @@ module BetterErrors
58
58
  exception.backtrace
59
59
  end
60
60
 
61
+ def exception_type
62
+ exception.type
63
+ end
64
+
65
+ def exception_message
66
+ exception.message.lstrip
67
+ end
68
+
61
69
  def application_frames
62
70
  backtrace_frames.select(&:application?)
63
71
  end
@@ -100,7 +100,7 @@ module BetterErrors
100
100
  end
101
101
 
102
102
  status_code = 500
103
- if defined? ActionDispatch::ExceptionWrapper
103
+ if defined?(ActionDispatch::ExceptionWrapper) && exception
104
104
  status_code = ActionDispatch::ExceptionWrapper.new(env, exception).status_code
105
105
  end
106
106
 
@@ -115,7 +115,7 @@ module BetterErrors
115
115
  def log_exception
116
116
  return unless BetterErrors.logger
117
117
 
118
- message = "\n#{@error_page.exception.type} - #{@error_page.exception.message}:\n"
118
+ message = "\n#{@error_page.exception_type} - #{@error_page.exception_message}:\n"
119
119
  @error_page.backtrace_frames.each do |frame|
120
120
  message << " #{frame}\n"
121
121
  end
@@ -4,7 +4,9 @@ module BetterErrors
4
4
  attr_reader :exception, :message, :backtrace
5
5
 
6
6
  def initialize(exception)
7
- if exception.respond_to?(:original_exception) && exception.original_exception
7
+ if exception.respond_to?(:cause)
8
+ exception = exception.cause if exception.cause
9
+ elsif exception.respond_to?(:original_exception) && exception.original_exception
8
10
  exception = exception.original_exception
9
11
  end
10
12
 
@@ -1,7 +1,7 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
- <title><%= exception.type %> at <%= request_path %></title>
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. %>
@@ -731,8 +731,8 @@
731
731
 
732
732
  <div class='top'>
733
733
  <header class="exception">
734
- <h2><strong><%= exception.type %></strong> <span>at <%= request_path %></span></h2>
735
- <p><%= exception.message %></p>
734
+ <h2><strong><%= exception_type %></strong> <span>at <%= request_path %></span></h2>
735
+ <p><%= exception_message %></p>
736
736
  </header>
737
737
  </div>
738
738
 
@@ -1,6 +1,6 @@
1
- <%== text_heading("=", "%s at %s" % [exception.type, request_path]) %>
1
+ <%== text_heading("=", "%s at %s" % [exception_type, request_path]) %>
2
2
 
3
- > <%== exception.message %>
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]) %>
@@ -45,26 +45,28 @@
45
45
  </div>
46
46
  </div>
47
47
 
48
- <div class="sub">
49
- <h3>Local Variables</h3>
50
- <div class='inset variables'>
51
- <table class="var_table">
52
- <% @frame.local_variables.each do |name, value| %>
53
- <tr><td class="name"><%= name %></td><td><pre><%== inspect_value value %></pre></td></tr>
54
- <% end %>
55
- </table>
48
+ <% if BetterErrors.binding_of_caller_available? && @frame.frame_binding %>
49
+ <div class="sub">
50
+ <h3>Local Variables</h3>
51
+ <div class='inset variables'>
52
+ <table class="var_table">
53
+ <% @frame.local_variables.each do |name, value| %>
54
+ <tr><td class="name"><%= name %></td><td><pre><%== inspect_value value %></pre></td></tr>
55
+ <% end %>
56
+ </table>
57
+ </div>
56
58
  </div>
57
- </div>
58
59
 
59
- <div class="sub">
60
- <h3>Instance Variables</h3>
61
- <div class="inset variables">
62
- <table class="var_table">
63
- <% @frame.instance_variables.each do |name, value| %>
64
- <tr><td class="name"><%= name %></td><td><pre><%== inspect_value value %></pre></td></tr>
65
- <% end %>
66
- </table>
60
+ <div class="sub">
61
+ <h3>Instance Variables</h3>
62
+ <div class="inset variables">
63
+ <table class="var_table">
64
+ <% @frame.instance_variables.each do |name, value| %>
65
+ <tr><td class="name"><%= name %></td><td><pre><%== inspect_value value %></pre></td></tr>
66
+ <% end %>
67
+ </table>
68
+ </div>
67
69
  </div>
68
- </div>
69
70
 
70
- <!-- <%= Time.now.to_f - @var_start_time %> seconds -->
71
+ <!-- <%= Time.now.to_f - @var_start_time %> seconds -->
72
+ <% end %>
@@ -1,3 +1,3 @@
1
1
  module BetterErrors
2
- VERSION = "2.1.1"
2
+ VERSION = "2.2.0"
3
3
  end
@@ -7,13 +7,13 @@ module BetterErrors
7
7
  let(:formatter) { CodeFormatter.new(filename, 8) }
8
8
 
9
9
  it "picks an appropriate scanner" do
10
- formatter.coderay_scanner.should == :ruby
10
+ expect(formatter.coderay_scanner).to eq(:ruby)
11
11
  end
12
12
 
13
13
  it "shows 5 lines of context" do
14
- formatter.line_range.should == (3..13)
14
+ expect(formatter.line_range).to eq(3..13)
15
15
 
16
- formatter.context_lines.should == [
16
+ expect(formatter.context_lines).to eq([
17
17
  "three\n",
18
18
  "four\n",
19
19
  "five\n",
@@ -25,40 +25,40 @@ module BetterErrors
25
25
  "eleven\n",
26
26
  "twelve\n",
27
27
  "thirteen\n"
28
- ]
28
+ ])
29
29
  end
30
30
 
31
31
  it "works when the line is right on the edge" do
32
32
  formatter = CodeFormatter.new(filename, 20)
33
- formatter.line_range.should == (15..20)
33
+ expect(formatter.line_range).to eq(15..20)
34
34
  end
35
35
 
36
36
  describe CodeFormatter::HTML do
37
37
  it "highlights the erroring line" do
38
38
  formatter = CodeFormatter::HTML.new(filename, 8)
39
- formatter.output.should =~ /highlight.*eight/
39
+ expect(formatter.output).to match(/highlight.*eight/)
40
40
  end
41
41
 
42
42
  it "works when the line is right on the edge" do
43
43
  formatter = CodeFormatter::HTML.new(filename, 20)
44
- formatter.output.should_not == formatter.source_unavailable
44
+ expect(formatter.output).not_to eq(formatter.source_unavailable)
45
45
  end
46
46
 
47
47
  it "doesn't barf when the lines don't make any sense" do
48
48
  formatter = CodeFormatter::HTML.new(filename, 999)
49
- formatter.output.should == formatter.source_unavailable
49
+ expect(formatter.output).to eq(formatter.source_unavailable)
50
50
  end
51
51
 
52
52
  it "doesn't barf when the file doesn't exist" do
53
53
  formatter = CodeFormatter::HTML.new("fkdguhskd7e l", 1)
54
- formatter.output.should == formatter.source_unavailable
54
+ expect(formatter.output).to eq(formatter.source_unavailable)
55
55
  end
56
56
  end
57
57
 
58
58
  describe CodeFormatter::Text do
59
59
  it "highlights the erroring line" do
60
60
  formatter = CodeFormatter::Text.new(filename, 8)
61
- formatter.output.should == <<-TEXT.gsub(/^ /, "")
61
+ expect(formatter.output).to eq <<-TEXT.gsub(/^ /, "")
62
62
  3 three
63
63
  4 four
64
64
  5 five
@@ -75,17 +75,17 @@ module BetterErrors
75
75
 
76
76
  it "works when the line is right on the edge" do
77
77
  formatter = CodeFormatter::Text.new(filename, 20)
78
- formatter.output.should_not == formatter.source_unavailable
78
+ expect(formatter.output).not_to eq(formatter.source_unavailable)
79
79
  end
80
80
 
81
81
  it "doesn't barf when the lines don't make any sense" do
82
82
  formatter = CodeFormatter::Text.new(filename, 999)
83
- formatter.output.should == formatter.source_unavailable
83
+ expect(formatter.output).to eq(formatter.source_unavailable)
84
84
  end
85
85
 
86
86
  it "doesn't barf when the file doesn't exist" do
87
87
  formatter = CodeFormatter::Text.new("fkdguhskd7e l", 1)
88
- formatter.output.should == formatter.source_unavailable
88
+ expect(formatter.output).to eq(formatter.source_unavailable)
89
89
  end
90
90
  end
91
91
  end
@@ -19,15 +19,15 @@ module BetterErrors
19
19
  }
20
20
 
21
21
  it "includes the error message" do
22
- response.should include("you divided by zero you silly goose!")
22
+ expect(response).to include("you divided by zero you silly goose!")
23
23
  end
24
24
 
25
25
  it "includes the request path" do
26
- response.should include("/some/path")
26
+ expect(response).to include("/some/path")
27
27
  end
28
28
 
29
29
  it "includes the exception class" do
30
- response.should include("ZeroDivisionError")
30
+ expect(response).to include("ZeroDivisionError")
31
31
  end
32
32
 
33
33
  context "variable inspection" do
@@ -36,41 +36,57 @@ module BetterErrors
36
36
  if BetterErrors.binding_of_caller_available?
37
37
  it "shows local variables" do
38
38
  html = error_page.do_variables("index" => 0)[:html]
39
- html.should include("local_a")
40
- html.should include(":value_for_local_a")
41
- html.should include("local_b")
42
- html.should include(":value_for_local_b")
39
+ expect(html).to include("local_a")
40
+ expect(html).to include(":value_for_local_a")
41
+ expect(html).to include("local_b")
42
+ expect(html).to include(":value_for_local_b")
43
43
  end
44
44
  else
45
45
  it "tells the user to add binding_of_caller to their gemfile to get fancy features" do
46
46
  html = error_page.do_variables("index" => 0)[:html]
47
- html.should include(%{gem "binding_of_caller"})
47
+ expect(html).to include(%{gem "binding_of_caller"})
48
48
  end
49
49
  end
50
50
 
51
51
  it "shows instance variables" do
52
52
  html = error_page.do_variables("index" => 0)[:html]
53
- html.should include("inst_c")
54
- html.should include(":value_for_inst_c")
55
- html.should include("inst_d")
56
- html.should include(":value_for_inst_d")
53
+ expect(html).to include("inst_c")
54
+ expect(html).to include(":value_for_inst_c")
55
+ expect(html).to include("inst_d")
56
+ expect(html).to include(":value_for_inst_d")
57
57
  end
58
58
 
59
59
  it "shows filter instance variables" do
60
- BetterErrors.stub(:ignored_instance_variables).and_return([ :@inst_d ])
60
+ allow(BetterErrors).to receive(:ignored_instance_variables).and_return([ :@inst_d ])
61
61
  html = error_page.do_variables("index" => 0)[:html]
62
- html.should include("inst_c")
63
- html.should include(":value_for_inst_c")
64
- html.should_not include('<td class="name">@inst_d</td>')
65
- html.should_not include("<pre>:value_for_inst_d</pre>")
62
+ expect(html).to include("inst_c")
63
+ expect(html).to include(":value_for_inst_c")
64
+ expect(html).not_to include('<td class="name">@inst_d</td>')
65
+ expect(html).not_to include("<pre>:value_for_inst_d</pre>")
66
66
  end
67
67
  end
68
68
 
69
69
  it "doesn't die if the source file is not a real filename" do
70
- exception.stub(:backtrace).and_return([
70
+ allow(exception).to receive(:backtrace).and_return([
71
71
  "<internal:prelude>:10:in `spawn_rack_application'"
72
72
  ])
73
- response.should include("Source unavailable")
73
+ expect(response).to include("Source unavailable")
74
+ end
75
+
76
+ context 'with an exception with blank lines' do
77
+ class SpacedError < StandardError
78
+ def initialize(message = nil)
79
+ message = "\n\n#{message}" if message
80
+ super
81
+ end
82
+ end
83
+
84
+ let!(:exception) { raise SpacedError, "Danger Warning!" rescue $! }
85
+
86
+ it 'should not include leading blank lines from exception_message' do
87
+ expect(exception.message).to match(/\A\n\n/)
88
+ expect(error_page.exception_message).not_to match(/\A\n\n/)
89
+ end
74
90
  end
75
91
  end
76
92
  end
@@ -6,42 +6,42 @@ module BetterErrors
6
6
  let(:exception) { RuntimeError.new("oh no :(") }
7
7
 
8
8
  it "passes non-error responses through" do
9
- app.call({}).should == ":)"
9
+ expect(app.call({})).to eq(":)")
10
10
  end
11
11
 
12
12
  it "calls the internal methods" do
13
- app.should_receive :internal_call
13
+ expect(app).to receive :internal_call
14
14
  app.call("PATH_INFO" => "/__better_errors/1/preform_awesomness")
15
15
  end
16
16
 
17
17
  it "calls the internal methods on any subfolder path" do
18
- app.should_receive :internal_call
18
+ expect(app).to receive :internal_call
19
19
  app.call("PATH_INFO" => "/any_sub/folder/path/__better_errors/1/preform_awesomness")
20
20
  end
21
21
 
22
22
  it "shows the error page" do
23
- app.should_receive :show_error_page
23
+ expect(app).to receive :show_error_page
24
24
  app.call("PATH_INFO" => "/__better_errors/")
25
25
  end
26
26
 
27
27
  it "shows the error page on any subfolder path" do
28
- app.should_receive :show_error_page
28
+ expect(app).to receive :show_error_page
29
29
  app.call("PATH_INFO" => "/any_sub/folder/path/__better_errors/")
30
30
  end
31
31
 
32
32
  it "doesn't show the error page to a non-local address" do
33
- app.should_not_receive :better_errors_call
33
+ expect(app).not_to receive :better_errors_call
34
34
  app.call("REMOTE_ADDR" => "1.2.3.4")
35
35
  end
36
36
 
37
37
  it "shows to a whitelisted IP" do
38
38
  BetterErrors::Middleware.allow_ip! '77.55.33.11'
39
- app.should_receive :better_errors_call
39
+ expect(app).to receive :better_errors_call
40
40
  app.call("REMOTE_ADDR" => "77.55.33.11")
41
41
  end
42
42
 
43
43
  it "respects the X-Forwarded-For header" do
44
- app.should_not_receive :better_errors_call
44
+ expect(app).not_to receive :better_errors_call
45
45
  app.call(
46
46
  "REMOTE_ADDR" => "127.0.0.1",
47
47
  "HTTP_X_FORWARDED_FOR" => "1.2.3.4",
@@ -61,12 +61,20 @@ module BetterErrors
61
61
 
62
62
  it "shows that no errors have been recorded" do
63
63
  status, headers, body = app.call("PATH_INFO" => "/__better_errors")
64
- body.join.should match /No errors have been recorded yet./
64
+ expect(body.join).to match /No errors have been recorded yet./
65
+ end
66
+
67
+ it 'does not attempt to use ActionDispatch::ExceptionWrapper with a nil exception' do
68
+ ad_ew = double("ActionDispatch::ExceptionWrapper")
69
+ stub_const('ActionDispatch::ExceptionWrapper', ad_ew)
70
+ ad_ew.should_not_receive :new
71
+
72
+ status, headers, body = app.call("PATH_INFO" => "/__better_errors")
65
73
  end
66
74
 
67
75
  it "shows that no errors have been recorded on any subfolder path" do
68
76
  status, headers, body = app.call("PATH_INFO" => "/any_sub/folder/path/__better_errors")
69
- body.join.should match /No errors have been recorded yet./
77
+ expect(body.join).to match /No errors have been recorded yet./
70
78
  end
71
79
  end
72
80
 
@@ -76,76 +84,102 @@ module BetterErrors
76
84
  it "returns status 500" do
77
85
  status, headers, body = app.call({})
78
86
 
79
- status.should == 500
87
+ expect(status).to eq(500)
80
88
  end
81
89
 
82
- context "original_exception" do
83
- class OriginalExceptionException < Exception
84
- attr_reader :original_exception
90
+ if Exception.new.respond_to?(:cause)
91
+ context "cause" do
92
+ class OtherException < Exception
93
+ def initialize(message)
94
+ super(message)
95
+ end
96
+ end
85
97
 
86
- def initialize(message, original_exception = nil)
87
- super(message)
88
- @original_exception = original_exception
98
+ it "shows Original Exception if it responds_to and has an cause" do
99
+ app = Middleware.new(->env {
100
+ begin
101
+ raise "Original Exception"
102
+ rescue
103
+ raise OtherException.new("Other Exception")
104
+ end
105
+ })
106
+
107
+ status, _, body = app.call({})
108
+
109
+ expect(status).to eq(500)
110
+ expect(body.join).not_to match(/\n> Other Exception\n/)
111
+ expect(body.join).to match(/\n> Original Exception\n/)
89
112
  end
90
113
  end
114
+ else
115
+ context "original_exception" do
116
+ class OriginalExceptionException < Exception
117
+ attr_reader :original_exception
118
+
119
+ def initialize(message, original_exception = nil)
120
+ super(message)
121
+ @original_exception = original_exception
122
+ end
123
+ end
91
124
 
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
- })
125
+ it "shows Original Exception if it responds_to and has an original_exception" do
126
+ app = Middleware.new(->env {
127
+ raise OriginalExceptionException.new("Other Exception", Exception.new("Original Exception"))
128
+ })
96
129
 
97
- status, _, body = app.call({})
130
+ status, _, body = app.call({})
98
131
 
99
- status.should == 500
100
- body.join.should_not match(/Other Exception/)
101
- body.join.should match(/Original Exception/)
102
- end
132
+ expect(status).to eq(500)
133
+ expect(body.join).not_to match(/Other Exception/)
134
+ expect(body.join).to match(/Original Exception/)
135
+ end
103
136
 
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
- })
137
+ it "won't crash if the exception responds_to but doesn't have an original_exception" do
138
+ app = Middleware.new(->env {
139
+ raise OriginalExceptionException.new("Other Exception")
140
+ })
108
141
 
109
- status, _, body = app.call({})
142
+ status, _, body = app.call({})
110
143
 
111
- status.should == 500
112
- body.join.should match(/Other Exception/)
144
+ expect(status).to eq(500)
145
+ expect(body.join).to match(/Other Exception/)
146
+ end
113
147
  end
114
148
  end
115
149
 
116
150
  it "returns ExceptionWrapper's status_code" do
117
151
  ad_ew = double("ActionDispatch::ExceptionWrapper")
118
- ad_ew.stub('new').with({}, exception ){ double("ExceptionWrapper", status_code: 404) }
152
+ allow(ad_ew).to receive('new').with({}, exception) { double("ExceptionWrapper", status_code: 404) }
119
153
  stub_const('ActionDispatch::ExceptionWrapper', ad_ew)
120
154
 
121
155
  status, headers, body = app.call({})
122
156
 
123
- status.should == 404
157
+ expect(status).to eq(404)
124
158
  end
125
159
 
126
160
  it "returns UTF-8 error pages" do
127
161
  status, headers, body = app.call({})
128
162
 
129
- headers["Content-Type"].should match /charset=utf-8/
163
+ expect(headers["Content-Type"]).to match /charset=utf-8/
130
164
  end
131
165
 
132
166
  it "returns text pages by default" do
133
167
  status, headers, body = app.call({})
134
168
 
135
- headers["Content-Type"].should match /text\/plain/
169
+ expect(headers["Content-Type"]).to match /text\/plain/
136
170
  end
137
171
 
138
172
  it "returns HTML pages by default" do
139
173
  # Chrome's 'Accept' header looks similar this.
140
174
  status, headers, body = app.call("HTTP_ACCEPT" => "text/html,application/xhtml+xml;q=0.9,*/*")
141
175
 
142
- headers["Content-Type"].should match /text\/html/
176
+ expect(headers["Content-Type"]).to match /text\/html/
143
177
  end
144
178
 
145
179
  it "logs the exception" do
146
180
  logger = Object.new
147
- logger.should_receive :fatal
148
- BetterErrors.stub(:logger).and_return(logger)
181
+ expect(logger).to receive :fatal
182
+ allow(BetterErrors).to receive(:logger).and_return(logger)
149
183
 
150
184
  app.call({})
151
185
  end
@@ -1,4 +1,5 @@
1
1
  require "spec_helper"
2
+ require "rspec/its"
2
3
 
3
4
  module BetterErrors
4
5
  describe RaisedException do
@@ -24,8 +25,8 @@ module BetterErrors
24
25
  its(:type) { should == SyntaxError }
25
26
 
26
27
  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
28
+ expect(subject.backtrace.first.filename).to eq("foo.rb")
29
+ expect(subject.backtrace.first.line).to eq(123)
29
30
  end
30
31
  end
31
32
 
@@ -44,8 +45,8 @@ module BetterErrors
44
45
  its(:type) { should == Haml::SyntaxError }
45
46
 
46
47
  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
48
+ expect(subject.backtrace.first.filename).to eq("foo.rb")
49
+ expect(subject.backtrace.first.line).to eq(123)
49
50
  end
50
51
  end
51
52
 
@@ -64,8 +65,8 @@ module BetterErrors
64
65
  its(:type) { should == Sprockets::Coffeelint::Error }
65
66
 
66
67
  it "has the right filename and line number in the backtrace" do
67
- subject.backtrace.first.filename.should == "app/assets/javascripts/files/index.coffee"
68
- subject.backtrace.first.line.should == 11
68
+ expect(subject.backtrace.first.filename).to eq("app/assets/javascripts/files/index.coffee")
69
+ expect(subject.backtrace.first.line).to eq(11)
69
70
  end
70
71
  end
71
72
  end
@@ -15,23 +15,23 @@ module BetterErrors
15
15
 
16
16
  it "does line continuation" do
17
17
  output, prompt, filled = repl.send_input ""
18
- output.should == "=> nil\n"
19
- prompt.should == ">>"
20
- filled.should == ""
18
+ expect(output).to eq("=> nil\n")
19
+ expect(prompt).to eq(">>")
20
+ expect(filled).to eq("")
21
21
 
22
22
  output, prompt, filled = repl.send_input "def f(x)"
23
- output.should == ""
24
- prompt.should == ".."
25
- filled.should == " "
23
+ expect(output).to eq("")
24
+ expect(prompt).to eq("..")
25
+ expect(filled).to eq(" ")
26
26
 
27
27
  output, prompt, filled = repl.send_input "end"
28
28
  if RUBY_VERSION >= "2.1.0"
29
- output.should == "=> :f\n"
29
+ expect(output).to eq("=> :f\n")
30
30
  else
31
- output.should == "=> nil\n"
31
+ expect(output).to eq("=> nil\n")
32
32
  end
33
- prompt.should == ">>"
34
- filled.should == ""
33
+ expect(prompt).to eq(">>")
34
+ expect(filled).to eq("")
35
35
  end
36
36
 
37
37
  it_behaves_like "a REPL provider"
@@ -1,18 +1,18 @@
1
1
  shared_examples_for "a REPL provider" do
2
2
  it "evaluates ruby code in a given context" do
3
3
  repl.send_input("local_a = 456")
4
- fresh_binding.eval("local_a").should == 456
4
+ expect(fresh_binding.eval("local_a")).to eq(456)
5
5
  end
6
6
 
7
7
  it "returns a tuple of output and the new prompt" do
8
8
  output, prompt = repl.send_input("1 + 2")
9
- output.should == "=> 3\n"
10
- prompt.should == ">>"
9
+ expect(output).to eq("=> 3\n")
10
+ expect(prompt).to eq(">>")
11
11
  end
12
12
 
13
13
  it "doesn't barf if the code throws an exception" do
14
14
  output, prompt = repl.send_input("raise Exception")
15
- output.should include "Exception: Exception"
16
- prompt.should == ">>"
15
+ expect(output).to include "Exception: Exception"
16
+ expect(prompt).to eq(">>")
17
17
  end
18
18
  end
@@ -4,80 +4,80 @@ module BetterErrors
4
4
  describe StackFrame do
5
5
  context "#application?" do
6
6
  it "is true for application filenames" do
7
- BetterErrors.stub(:application_root).and_return("/abc/xyz")
7
+ allow(BetterErrors).to receive(:application_root).and_return("/abc/xyz")
8
8
  frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index")
9
9
 
10
- frame.should be_application
10
+ expect(frame).to be_application
11
11
  end
12
12
 
13
13
  it "is false for everything else" do
14
- BetterErrors.stub(:application_root).and_return("/abc/xyz")
14
+ allow(BetterErrors).to receive(:application_root).and_return("/abc/xyz")
15
15
  frame = StackFrame.new("/abc/nope", 123, "foo")
16
16
 
17
- frame.should_not be_application
17
+ expect(frame).not_to be_application
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
- frame.should_not be_application
23
+ expect(frame).not_to be_application
24
24
  end
25
25
  end
26
26
 
27
27
  context "#gem?" do
28
28
  it "is true for gem filenames" do
29
- Gem.stub(:path).and_return(["/abc/xyz"])
29
+ allow(Gem).to receive(: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
- frame.should be_gem
32
+ expect(frame).to be_gem
33
33
  end
34
34
 
35
35
  it "is false for everything else" do
36
- Gem.stub(:path).and_return(["/abc/xyz"])
36
+ allow(Gem).to receive(:path).and_return(["/abc/xyz"])
37
37
  frame = StackFrame.new("/abc/nope", 123, "foo")
38
38
 
39
- frame.should_not be_gem
39
+ expect(frame).not_to be_gem
40
40
  end
41
41
  end
42
42
 
43
43
  context "#application_path" do
44
44
  it "chops off the application root" do
45
- BetterErrors.stub(:application_root).and_return("/abc/xyz")
45
+ allow(BetterErrors).to receive(:application_root).and_return("/abc/xyz")
46
46
  frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index")
47
47
 
48
- frame.application_path.should == "app/controllers/crap_controller.rb"
48
+ expect(frame.application_path).to eq("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
- Gem.stub(:path).and_return(["/abc/xyz"])
54
+ allow(Gem).to receive(: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
- frame.gem_path.should == "whatever (1.2.3) lib/whatever.rb"
57
+ expect(frame.gem_path).to eq("whatever (1.2.3) lib/whatever.rb")
58
58
  end
59
59
 
60
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"])
61
+ allow(BetterErrors).to receive(:application_root).and_return("/abc/xyz")
62
+ allow(Gem).to receive(: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
- frame.gem_path.should == "whatever (1.2.3) lib/whatever.rb"
65
+ expect(frame.gem_path).to eq("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
- BetterErrors.stub(:application_root).and_return("/abc/xyz")
71
+ allow(BetterErrors).to receive(:application_root).and_return("/abc/xyz")
72
72
  frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index")
73
- frame.pretty_path.should == frame.application_path
73
+ expect(frame.pretty_path).to eq(frame.application_path)
74
74
  end
75
75
 
76
76
  it "returns #gem_path for gem paths" do
77
- Gem.stub(:path).and_return(["/abc/xyz"])
77
+ allow(Gem).to receive(: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
- frame.pretty_path.should == frame.gem_path
80
+ expect(frame.pretty_path).to eq(frame.gem_path)
81
81
  end
82
82
  end
83
83
 
@@ -87,36 +87,36 @@ module BetterErrors
87
87
  rescue SyntaxError => syntax_error
88
88
  end
89
89
  frames = StackFrame.from_exception(syntax_error)
90
- frames.first.filename.should == "my_file.rb"
91
- frames.first.line.should == 123
90
+ expect(frames.first.filename).to eq("my_file.rb")
91
+ expect(frames.first.line).to eq(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
- error.stub(:backtrace).and_return(["foo.rb:123"])
97
+ allow(error).to receive(:backtrace).and_return(["foo.rb:123"])
98
98
  frames = StackFrame.from_exception(error)
99
- frames.first.filename.should == "foo.rb"
100
- frames.first.line.should == 123
99
+ expect(frames.first.filename).to eq("foo.rb")
100
+ expect(frames.first.line).to eq(123)
101
101
 
102
- error.stub(:backtrace).and_return(["foo.rb:123: this is an error message"])
102
+ allow(error).to receive(:backtrace).and_return(["foo.rb:123: this is an error message"])
103
103
  frames = StackFrame.from_exception(error)
104
- frames.first.filename.should == "foo.rb"
105
- frames.first.line.should == 123
104
+ expect(frames.first.filename).to eq("foo.rb")
105
+ expect(frames.first.line).to eq(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
- error.stub(:backtrace).and_return(["foo.rb:123:in `foo'", "C:in `find'", "bar.rb:123:in `bar'"])
110
+ allow(error).to receive(:backtrace).and_return(["foo.rb:123:in `foo'", "C:in `find'", "bar.rb:123:in `bar'"])
111
111
  frames = StackFrame.from_exception(error)
112
- frames.count.should == 2
112
+ expect(frames.count).to eq(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
- error.stub(:backtrace).and_return(["crap:filename.rb:123"])
117
+ allow(error).to receive(:backtrace).and_return(["crap:filename.rb:123"])
118
118
  frames = StackFrame.from_exception(error)
119
- frames.first.filename.should == "crap:filename.rb"
119
+ expect(frames.first.filename).to eq("crap:filename.rb")
120
120
  end
121
121
 
122
122
  it "doesn't blow up with a BasicObject as frame binding" do
@@ -125,7 +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
- frame.class_name.should == 'BasicObject'
128
+ expect(frame.class_name).to eq('BasicObject')
129
129
  end
130
130
 
131
131
  it "sets method names properly" do
@@ -140,11 +140,11 @@ module BetterErrors
140
140
 
141
141
  frame = StackFrame.from_exception(obj.my_method).first
142
142
  if BetterErrors.binding_of_caller_available?
143
- frame.method_name.should == "#my_method"
144
- frame.class_name.should == "String"
143
+ expect(frame.method_name).to eq("#my_method")
144
+ expect(frame.class_name).to eq("String")
145
145
  else
146
- frame.method_name.should == "my_method"
147
- frame.class_name.should == nil
146
+ expect(frame.method_name).to eq("my_method")
147
+ expect(frame.class_name).to eq(nil)
148
148
  end
149
149
  end
150
150
 
@@ -3,38 +3,38 @@ require "spec_helper"
3
3
  describe BetterErrors do
4
4
  context ".editor" do
5
5
  it "defaults to textmate" do
6
- subject.editor["foo.rb", 123].should == "txmt://open?url=file://foo.rb&line=123"
6
+ expect(subject.editor["foo.rb", 123]).to eq("txmt://open?url=file://foo.rb&line=123")
7
7
  end
8
8
 
9
9
  it "url escapes the filename" do
10
- subject.editor["&.rb", 0].should == "txmt://open?url=file://%26.rb&line=0"
10
+ expect(subject.editor["&.rb", 0]).to eq("txmt://open?url=file://%26.rb&line=0")
11
11
  end
12
12
 
13
13
  [:emacs, :emacsclient].each do |editor|
14
14
  it "uses emacs:// scheme when set to #{editor.inspect}" do
15
15
  subject.editor = editor
16
- subject.editor[].should start_with "emacs://"
16
+ expect(subject.editor[]).to start_with "emacs://"
17
17
  end
18
18
  end
19
19
 
20
20
  [:macvim, :mvim].each do |editor|
21
21
  it "uses mvim:// scheme when set to #{editor.inspect}" do
22
22
  subject.editor = editor
23
- subject.editor[].should start_with "mvim://"
23
+ expect(subject.editor[]).to start_with "mvim://"
24
24
  end
25
25
  end
26
26
 
27
27
  [:sublime, :subl, :st].each do |editor|
28
28
  it "uses subl:// scheme when set to #{editor.inspect}" do
29
29
  subject.editor = editor
30
- subject.editor[].should start_with "subl://"
30
+ expect(subject.editor[]).to start_with "subl://"
31
31
  end
32
32
  end
33
33
 
34
34
  [:textmate, :txmt, :tm].each do |editor|
35
35
  it "uses txmt:// scheme when set to #{editor.inspect}" do
36
36
  subject.editor = editor
37
- subject.editor[].should start_with "txmt://"
37
+ expect(subject.editor[]).to start_with "txmt://"
38
38
  end
39
39
  end
40
40
 
@@ -42,7 +42,7 @@ describe BetterErrors do
42
42
  it "uses emacs:// scheme when EDITOR=#{editor}" do
43
43
  ENV["EDITOR"] = editor
44
44
  subject.editor = subject.default_editor
45
- subject.editor[].should start_with "emacs://"
45
+ expect(subject.editor[]).to start_with "emacs://"
46
46
  end
47
47
  end
48
48
 
@@ -50,15 +50,15 @@ describe BetterErrors do
50
50
  it "uses mvim:// scheme when EDITOR=#{editor}" do
51
51
  ENV["EDITOR"] = editor
52
52
  subject.editor = subject.default_editor
53
- subject.editor[].should start_with "mvim://"
53
+ expect(subject.editor[]).to start_with "mvim://"
54
54
  end
55
55
  end
56
56
 
57
57
  ["subl -w", "/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl"].each do |editor|
58
- it "uses mvim:// scheme when EDITOR=#{editor}" do
58
+ it "uses subl:// scheme when EDITOR=#{editor}" do
59
59
  ENV["EDITOR"] = editor
60
60
  subject.editor = subject.default_editor
61
- subject.editor[].should start_with "subl://"
61
+ expect(subject.editor[]).to start_with "subl://"
62
62
  end
63
63
  end
64
64
 
@@ -66,7 +66,7 @@ describe BetterErrors do
66
66
  it "uses txmt:// scheme when EDITOR=#{editor}" do
67
67
  ENV["EDITOR"] = editor
68
68
  subject.editor = subject.default_editor
69
- subject.editor[].should start_with "txmt://"
69
+ expect(subject.editor[]).to start_with "txmt://"
70
70
  end
71
71
  end
72
72
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: better_errors
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Charlie Somerville
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-09 00:00:00.000000000 Z
11
+ date: 2017-07-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: erubis
@@ -70,6 +70,15 @@ files:
70
70
  - README.md
71
71
  - Rakefile
72
72
  - better_errors.gemspec
73
+ - feature-screenshots/1-application-error.jpg
74
+ - feature-screenshots/2-other-application-frame.jpg
75
+ - feature-screenshots/3-live-shell.jpg
76
+ - feature-screenshots/4-other-frames.jpg
77
+ - feature-screenshots/5-open-editor.jpg
78
+ - feature-screenshots/6-local-variables.jpg
79
+ - feature-screenshots/7-non-html-requests.jpg
80
+ - feature-screenshots/8-xhr-shows-text-error.jpg
81
+ - feature-screenshots/9-xhr-error-in-manual-console.jpg
73
82
  - lib/better_errors.rb
74
83
  - lib/better_errors/code_formatter.rb
75
84
  - lib/better_errors/code_formatter/html.rb
@@ -119,7 +128,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
119
128
  version: '0'
120
129
  requirements: []
121
130
  rubyforge_project:
122
- rubygems_version: 2.2.2
131
+ rubygems_version: 2.6.8
123
132
  signing_key:
124
133
  specification_version: 4
125
134
  summary: Better error page for Rails and other Rack apps