better_errors 0.9.0 → 1.0.0.rc1

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.

Potentially problematic release.


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

@@ -41,6 +41,14 @@
41
41
  background: #f0f0f5;
42
42
  }
43
43
 
44
+ .clearfix::after{
45
+ clear: both;
46
+ content: ".";
47
+ display: block;
48
+ height: 0;
49
+ visibility: hidden;
50
+ }
51
+
44
52
  /* ---------------------------------------------------------------------
45
53
  * Basic layout
46
54
  * --------------------------------------------------------------------- */
@@ -379,7 +387,7 @@
379
387
  * Monospace
380
388
  * --------------------------------------------------------------------- */
381
389
 
382
- pre, code, .repl input, .repl .prompt span, textarea {
390
+ pre, code, .repl input, .repl .prompt span, textarea, .code_linenums {
383
391
  font-family: menlo, lucida console, monospace;
384
392
  font-size: 8pt;
385
393
  }
@@ -396,6 +404,11 @@
396
404
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.03), 1px 1px 0 rgba(0, 0, 0, 0.05), -1px 1px 0 rgba(0, 0, 0, 0.05), 0 0 0 4px rgba(0, 0, 0, 0.04);
397
405
  }
398
406
 
407
+ .code_block{
408
+ background: #f1f1f1;
409
+ border-left: 1px solid #ccc;
410
+ }
411
+
399
412
  /* Titlebar */
400
413
  .trace_info .title {
401
414
  background: #f1f1f1;
@@ -447,15 +460,30 @@
447
460
  box-shadow: inset 3px 3px 3px rgba(0, 0, 0, 0.1), inset 0 0 0 1px rgba(0, 0, 0, 0.1);
448
461
  }
449
462
 
450
- .code {
451
- margin-bottom: -1px;
463
+ .code_linenums{
464
+ background:#f1f1f1;
465
+ padding-top:10px;
466
+ padding-bottom:9px;
467
+ float:left;
468
+ }
469
+
470
+ .code_linenums span{
471
+ display:block;
472
+ padding:0 12px;
452
473
  }
453
474
 
454
475
  .code {
476
+ margin-bottom: -1px;
477
+ border-top-left-radius:2px;
455
478
  padding: 10px 0;
456
479
  overflow: auto;
457
480
  }
458
481
 
482
+ .code pre{
483
+ padding-left:12px;
484
+ min-height:16px;
485
+ }
486
+
459
487
  /* Source unavailable */
460
488
  p.unavailable {
461
489
  padding: 20px 0 40px 0;
@@ -489,7 +517,7 @@
489
517
  100% { background: rgba(220, 30, 30, 0.1); }
490
518
  }
491
519
 
492
- .code .highlight {
520
+ .code .highlight, .code_linenums .highlight {
493
521
  background: rgba(220, 30, 30, 0.1);
494
522
  -webkit-animation: highlight 400ms linear 1;
495
523
  -moz-animation: highlight 400ms linear 1;
@@ -773,7 +801,10 @@
773
801
  this.inputElement = this.container.querySelector("input");
774
802
  this.outputElement = this.container.querySelector("pre");
775
803
 
776
- this.inputElement.onkeydown = this.onKeyDown.bind(this);
804
+ var self = this;
805
+ this.inputElement.onkeydown = function(ev) {
806
+ self.onKeyDown(ev);
807
+ };
777
808
 
778
809
  this.setPrompt(">>");
779
810
 
@@ -821,6 +852,7 @@
821
852
  self.writeRawOutput(response.highlighted_input + "\n");
822
853
  self.writeOutput(response.result);
823
854
  self.setPrompt(response.prompt);
855
+ self.setInput(response.prefilled_input);
824
856
  });
825
857
  };
826
858
 
@@ -1,10 +1,11 @@
1
- <header class="trace_info">
1
+ <header class="trace_info clearfix">
2
2
  <div class="title">
3
3
  <h2 class="name"><%= @frame.name %></h2>
4
4
  <div class="location"><span class="filename"><a href="<%= editor_url(@frame) %>"><%= @frame.pretty_path %></a></span></div>
5
5
  </div>
6
-
7
- <%== html_formatted_code_block @frame %>
6
+ <div class="code_block clearfix">
7
+ <%== html_formatted_code_block @frame %>
8
+ </div>
8
9
 
9
10
  <% if BetterErrors.binding_of_caller_available? && @frame.frame_binding %>
10
11
  <div class="repl">
@@ -1,3 +1,3 @@
1
1
  module BetterErrors
2
- VERSION = "0.9.0"
2
+ VERSION = "1.0.0.rc1"
3
3
  end
@@ -6,11 +6,11 @@ module BetterErrors
6
6
 
7
7
  let(:formatter) { CodeFormatter.new(filename, 8) }
8
8
 
9
- it "should pick an appropriate scanner" do
9
+ it "picks an appropriate scanner" do
10
10
  formatter.coderay_scanner.should == :ruby
11
11
  end
12
12
 
13
- it "should show 5 lines of context" do
13
+ it "shows 5 lines of context" do
14
14
  formatter.line_range.should == (3..13)
15
15
 
16
16
  formatter.context_lines.should == [
@@ -28,35 +28,35 @@ module BetterErrors
28
28
  ]
29
29
  end
30
30
 
31
- it "should work when the line is right on the edge" do
31
+ it "works when the line is right on the edge" do
32
32
  formatter = CodeFormatter.new(filename, 20)
33
33
  formatter.line_range.should == (15..20)
34
34
  end
35
35
 
36
36
  describe CodeFormatter::HTML do
37
- it "should highlight the erroring line" do
37
+ it "highlights the erroring line" do
38
38
  formatter = CodeFormatter::HTML.new(filename, 8)
39
39
  formatter.output.should =~ /highlight.*eight/
40
40
  end
41
41
 
42
- it "should work when the line is right on the edge" do
42
+ it "works when the line is right on the edge" do
43
43
  formatter = CodeFormatter::HTML.new(filename, 20)
44
44
  formatter.output.should_not == formatter.source_unavailable
45
45
  end
46
46
 
47
- it "should not barf when the lines don't make any sense" do
47
+ it "doesn't barf when the lines don't make any sense" do
48
48
  formatter = CodeFormatter::HTML.new(filename, 999)
49
49
  formatter.output.should == formatter.source_unavailable
50
50
  end
51
51
 
52
- it "should not barf when the file doesn't exist" do
52
+ it "doesn't barf when the file doesn't exist" do
53
53
  formatter = CodeFormatter::HTML.new("fkdguhskd7e l", 1)
54
54
  formatter.output.should == formatter.source_unavailable
55
55
  end
56
56
  end
57
57
 
58
58
  describe CodeFormatter::Text do
59
- it "should highlight the erroring line" do
59
+ it "highlights the erroring line" do
60
60
  formatter = CodeFormatter::Text.new(filename, 8)
61
61
  formatter.output.should == <<-TEXT.gsub(/^ /, "")
62
62
  3 three
@@ -73,17 +73,17 @@ module BetterErrors
73
73
  TEXT
74
74
  end
75
75
 
76
- it "should work when the line is right on the edge" do
76
+ it "works when the line is right on the edge" do
77
77
  formatter = CodeFormatter::Text.new(filename, 20)
78
78
  formatter.output.should_not == formatter.source_unavailable
79
79
  end
80
80
 
81
- it "should not barf when the lines don't make any sense" do
81
+ it "doesn't barf when the lines don't make any sense" do
82
82
  formatter = CodeFormatter::Text.new(filename, 999)
83
83
  formatter.output.should == formatter.source_unavailable
84
84
  end
85
85
 
86
- it "should not barf when the file doesn't exist" do
86
+ it "doesn't barf when the file doesn't exist" do
87
87
  formatter = CodeFormatter::Text.new("fkdguhskd7e l", 1)
88
88
  formatter.output.should == formatter.source_unavailable
89
89
  end
@@ -18,30 +18,37 @@ module BetterErrors
18
18
  binding
19
19
  }
20
20
 
21
- it "should include the error message" do
21
+ it "includes the error message" do
22
22
  response.should include("you divided by zero you silly goose!")
23
23
  end
24
24
 
25
- it "should include the request path" do
25
+ it "includes the request path" do
26
26
  response.should include("/some/path")
27
27
  end
28
28
 
29
- it "should include the exception class" do
29
+ it "includes the exception class" do
30
30
  response.should include("ZeroDivisionError")
31
31
  end
32
32
 
33
33
  context "variable inspection" do
34
34
  let(:exception) { empty_binding.eval("raise") rescue $! }
35
35
 
36
- it "should show local variables" do
37
- html = error_page.do_variables("index" => 0)[:html]
38
- html.should include("local_a")
39
- html.should include(":value_for_local_a")
40
- html.should include("local_b")
41
- html.should include(":value_for_local_b")
36
+ if BetterErrors.binding_of_caller_available?
37
+ it "shows local variables" do
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")
43
+ end
44
+ else
45
+ it "tells the user to add binding_of_caller to their gemfile to get fancy features" do
46
+ html = error_page.do_variables("index" => 0)[:html]
47
+ html.should include(%{gem "binding_of_caller"})
48
+ end
42
49
  end
43
50
 
44
- it "should show instance variables" do
51
+ it "shows instance variables" do
45
52
  html = error_page.do_variables("index" => 0)[:html]
46
53
  html.should include("inst_c")
47
54
  html.should include(":value_for_inst_c")
@@ -49,7 +56,7 @@ module BetterErrors
49
56
  html.should include(":value_for_inst_d")
50
57
  end
51
58
 
52
- it "should show filter instance variables" do
59
+ it "shows filter instance variables" do
53
60
  BetterErrors.stub(:ignored_instance_variables).and_return([ :@inst_d ])
54
61
  html = error_page.do_variables("index" => 0)[:html]
55
62
  html.should include("inst_c")
@@ -59,8 +66,8 @@ module BetterErrors
59
66
  end
60
67
  end
61
68
 
62
- it "should not die if the source file is not a real filename" do
63
- exception.stub!(:backtrace).and_return([
69
+ it "doesn't die if the source file is not a real filename" do
70
+ exception.stub(:backtrace).and_return([
64
71
  "<internal:prelude>:10:in `spawn_rack_application'"
65
72
  ])
66
73
  response.should include("Source unavailable")
@@ -3,88 +3,107 @@ require "spec_helper"
3
3
  module BetterErrors
4
4
  describe Middleware do
5
5
  let(:app) { Middleware.new(->env { ":)" }) }
6
+ let(:exception) { RuntimeError.new("oh no :(") }
6
7
 
7
- it "should pass non-error responses through" do
8
+ it "passes non-error responses through" do
8
9
  app.call({}).should == ":)"
9
10
  end
10
11
 
11
- it "should call the internal methods" do
12
+ it "calls the internal methods" do
12
13
  app.should_receive :internal_call
13
14
  app.call("PATH_INFO" => "/__better_errors/1/preform_awesomness")
14
15
  end
15
16
 
16
- it "should call the internal methods on any subfolder path" do
17
+ it "calls the internal methods on any subfolder path" do
17
18
  app.should_receive :internal_call
18
19
  app.call("PATH_INFO" => "/any_sub/folder/path/__better_errors/1/preform_awesomness")
19
20
  end
20
21
 
21
- it "should show the error page" do
22
+ it "shows the error page" do
22
23
  app.should_receive :show_error_page
23
24
  app.call("PATH_INFO" => "/__better_errors/")
24
25
  end
25
26
 
26
- it "should show the error page on any subfolder path" do
27
+ it "shows the error page on any subfolder path" do
27
28
  app.should_receive :show_error_page
28
29
  app.call("PATH_INFO" => "/any_sub/folder/path/__better_errors/")
29
30
  end
30
31
 
31
- it "should not show the error page to a non-local address" do
32
+ it "doesn't show the error page to a non-local address" do
32
33
  app.should_not_receive :better_errors_call
33
34
  app.call("REMOTE_ADDR" => "1.2.3.4")
34
35
  end
35
36
 
36
- it "should show to a whitelisted IP" do
37
+ it "shows to a whitelisted IP" do
37
38
  BetterErrors::Middleware.allow_ip! '77.55.33.11'
38
39
  app.should_receive :better_errors_call
39
40
  app.call("REMOTE_ADDR" => "77.55.33.11")
40
41
  end
41
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
+
42
51
  context "when requesting the /__better_errors manually" do
43
52
  let(:app) { Middleware.new(->env { ":)" }) }
44
53
 
45
- it "should show that no errors have been recorded" do
54
+ it "shows that no errors have been recorded" do
46
55
  status, headers, body = app.call("PATH_INFO" => "/__better_errors")
47
56
  body.join.should match /No errors have been recorded yet./
48
57
  end
49
58
 
50
- it "should show that no errors have been recorded on any subfolder path" do
59
+ it "shows that no errors have been recorded on any subfolder path" do
51
60
  status, headers, body = app.call("PATH_INFO" => "/any_sub/folder/path/__better_errors")
52
61
  body.join.should match /No errors have been recorded yet./
53
62
  end
54
63
  end
55
64
 
56
65
  context "when handling an error" do
57
- let(:app) { Middleware.new(->env { raise "oh no :(" }) }
66
+ let(:app) { Middleware.new(->env { raise exception }) }
58
67
 
59
- it "should return status 500" do
68
+ it "returns status 500" do
60
69
  status, headers, body = app.call({})
61
70
 
62
71
  status.should == 500
63
72
  end
64
73
 
65
- it "should return UTF-8 error pages" do
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
66
85
  status, headers, body = app.call({})
67
86
 
68
87
  headers["Content-Type"].should match /charset=utf-8/
69
88
  end
70
89
 
71
- it "should return text pages by default" do
90
+ it "returns text pages by default" do
72
91
  status, headers, body = app.call({})
73
92
 
74
93
  headers["Content-Type"].should match /text\/plain/
75
94
  end
76
95
 
77
- it "should return HTML pages by default" do
96
+ it "returns HTML pages by default" do
78
97
  # Chrome's 'Accept' header looks similar this.
79
98
  status, headers, body = app.call("HTTP_ACCEPT" => "text/html,application/xhtml+xml;q=0.9,*/*")
80
99
 
81
100
  headers["Content-Type"].should match /text\/html/
82
101
  end
83
102
 
84
- it "should log the exception" do
103
+ it "logs the exception" do
85
104
  logger = Object.new
86
105
  logger.should_receive :fatal
87
- BetterErrors.stub!(:logger).and_return(logger)
106
+ BetterErrors.stub(:logger).and_return(logger)
88
107
 
89
108
  app.call({})
90
109
  end
@@ -12,7 +12,7 @@ module BetterErrors
12
12
 
13
13
  let(:repl) { Basic.new fresh_binding }
14
14
 
15
- it_behaves_like "a good repl should"
15
+ it_behaves_like "a REPL provider"
16
16
  end
17
17
  end
18
18
  end
@@ -13,21 +13,24 @@ module BetterErrors
13
13
 
14
14
  let(:repl) { Pry.new fresh_binding }
15
15
 
16
- it_behaves_like "a good repl should"
17
-
18
- it "should do line continuation" do
19
- output, prompt = repl.send_input ""
16
+ it "does line continuation" do
17
+ output, prompt, filled = repl.send_input ""
20
18
  output.should == "=> nil\n"
21
19
  prompt.should == ">>"
20
+ filled.should == ""
22
21
 
23
- output, prompt = repl.send_input "def f(x)"
22
+ output, prompt, filled = repl.send_input "def f(x)"
24
23
  output.should == ""
25
24
  prompt.should == ".."
25
+ filled.should == " "
26
26
 
27
- output, prompt = repl.send_input "end"
27
+ output, prompt, filled = repl.send_input "end"
28
28
  output.should == "=> nil\n"
29
29
  prompt.should == ">>"
30
+ filled.should == ""
30
31
  end
32
+
33
+ it_behaves_like "a REPL provider"
31
34
  end
32
35
  end
33
36
  end
@@ -1,22 +1,18 @@
1
- module BetterErrors
2
- module REPL
3
- shared_examples "a good repl should" do
4
- it "should evaluate ruby code in a given context" do
5
- repl.send_input("local_a = 456")
6
- fresh_binding.eval("local_a").should == 456
7
- end
8
-
9
- it "should return a tuple of output and the new prompt" do
10
- output, prompt = repl.send_input("1 + 2")
11
- output.should == "=> 3\n"
12
- prompt.should == ">>"
13
- end
14
-
15
- it "should not barf if the code throws an exception" do
16
- output, prompt = repl.send_input("raise Exception")
17
- output.should include "Exception: Exception"
18
- prompt.should == ">>"
19
- end
20
- end
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 == ">>"
21
17
  end
22
18
  end