better_errors 0.9.0 → 1.0.0.rc1

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.

@@ -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