web-console 2.0.0 → 2.1.0

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

Potentially problematic release.


This version of web-console might be problematic. Click here for more details.

Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/README.markdown +132 -85
  3. data/lib/web_console.rb +14 -13
  4. data/lib/web_console/errors.rb +7 -0
  5. data/lib/web_console/{repl.rb → evaluator.rb} +7 -10
  6. data/lib/web_console/helper.rb +22 -0
  7. data/lib/web_console/integration.rb +8 -0
  8. data/lib/web_console/{core_ext/exception → integration}/cruby.rb +0 -0
  9. data/lib/web_console/integration/jruby.rb +111 -0
  10. data/lib/web_console/integration/rubinius.rb +66 -0
  11. data/lib/web_console/middleware.rb +117 -0
  12. data/lib/web_console/railtie.rb +61 -0
  13. data/lib/web_console/request.rb +30 -0
  14. data/lib/web_console/session.rb +65 -0
  15. data/lib/web_console/template.rb +49 -0
  16. data/lib/web_console/templates/_inner_console_markup.html +3 -0
  17. data/lib/web_console/templates/_markup.html +4 -0
  18. data/lib/web_console/templates/_prompt_box_markup.html +2 -0
  19. data/lib/web_console/templates/console.js +373 -0
  20. data/lib/web_console/templates/error_page.js +83 -0
  21. data/lib/web_console/templates/index.html +8 -0
  22. data/lib/web_console/templates/layouts/inlined_string.erb +1 -0
  23. data/lib/web_console/templates/layouts/javascript.erb +5 -0
  24. data/lib/web_console/templates/main.js +24 -0
  25. data/lib/web_console/templates/style.css +9 -0
  26. data/lib/web_console/version.rb +1 -1
  27. data/lib/web_console/whiny_request.rb +38 -0
  28. data/lib/web_console/whitelist.rb +42 -0
  29. data/test/dummy/config/environments/test.rb +0 -4
  30. data/test/dummy/log/development.log +7075 -0
  31. data/test/dummy/log/test.log +66006 -0
  32. data/test/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  33. data/test/dummy/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  34. data/test/dummy/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  35. data/test/dummy/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  36. data/test/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  37. data/test/dummy/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  38. data/test/support/scenarios/bad_custom_error_scenario.rb +17 -0
  39. data/test/support/scenarios/basic_nested_scenario.rb +15 -0
  40. data/test/support/scenarios/custom_error_scenario.rb +11 -0
  41. data/test/support/scenarios/eval_nested_scenario.rb +15 -0
  42. data/test/support/scenarios/flat_scenario.rb +9 -0
  43. data/test/support/scenarios/reraised_scenario.rb +21 -0
  44. data/test/test_helper.rb +50 -3
  45. data/test/web_console/evaluator_test.rb +73 -0
  46. data/test/web_console/helper_test.rb +76 -0
  47. data/test/web_console/integration_test.rb +47 -0
  48. data/test/web_console/middleware_test.rb +116 -0
  49. data/test/web_console/railtie_test.rb +99 -0
  50. data/test/web_console/request_test.rb +52 -0
  51. data/test/web_console/session_test.rb +59 -0
  52. data/test/web_console/whiny_request_test.rb +33 -0
  53. data/test/web_console/whitelist_test.rb +43 -0
  54. metadata +66 -56
  55. data/lib/action_dispatch/debug_exceptions.rb +0 -105
  56. data/lib/action_dispatch/exception_wrapper.rb +0 -38
  57. data/lib/action_dispatch/templates/rescues/_request_and_response.html.erb +0 -34
  58. data/lib/action_dispatch/templates/rescues/_request_and_response.text.erb +0 -23
  59. data/lib/action_dispatch/templates/rescues/_source.erb +0 -29
  60. data/lib/action_dispatch/templates/rescues/_trace.html.erb +0 -72
  61. data/lib/action_dispatch/templates/rescues/_trace.text.erb +0 -9
  62. data/lib/action_dispatch/templates/rescues/_web_console.html.erb +0 -420
  63. data/lib/action_dispatch/templates/rescues/diagnostics.html.erb +0 -18
  64. data/lib/action_dispatch/templates/rescues/diagnostics.text.erb +0 -9
  65. data/lib/action_dispatch/templates/rescues/layout.erb +0 -160
  66. data/lib/action_dispatch/templates/rescues/missing_template.html.erb +0 -13
  67. data/lib/action_dispatch/templates/rescues/missing_template.text.erb +0 -3
  68. data/lib/action_dispatch/templates/rescues/routing_error.html.erb +0 -34
  69. data/lib/action_dispatch/templates/rescues/routing_error.text.erb +0 -11
  70. data/lib/action_dispatch/templates/rescues/template_error.html.erb +0 -22
  71. data/lib/action_dispatch/templates/rescues/template_error.text.erb +0 -7
  72. data/lib/action_dispatch/templates/rescues/unknown_action.html.erb +0 -6
  73. data/lib/action_dispatch/templates/rescues/unknown_action.text.erb +0 -3
  74. data/lib/action_dispatch/templates/routes/_route.html.erb +0 -16
  75. data/lib/action_dispatch/templates/routes/_table.html.erb +0 -200
  76. data/lib/assets/javascripts/web-console.js +0 -1
  77. data/lib/assets/javascripts/web_console.js +0 -41
  78. data/lib/web_console/controller_helpers.rb +0 -46
  79. data/lib/web_console/core_ext/exception.rb +0 -7
  80. data/lib/web_console/core_ext/exception/jruby.rb +0 -25
  81. data/lib/web_console/core_ext/exception/rubinius.rb +0 -32
  82. data/lib/web_console/engine.rb +0 -47
  83. data/lib/web_console/repl_session.rb +0 -89
  84. data/lib/web_console/unsupported_platforms.rb +0 -28
  85. data/lib/web_console/view_helpers.rb +0 -16
  86. data/test/action_pack/exception_wrapper_test.rb +0 -26
  87. data/test/controllers/tests_controller_test.rb +0 -41
  88. data/test/web_console/core_ext/exception_test.rb +0 -46
  89. data/test/web_console/engine_test.rb +0 -108
  90. data/test/web_console/repl_session_test.rb +0 -32
  91. data/test/web_console/repl_test.rb +0 -75
@@ -0,0 +1,17 @@
1
+ module WebConsole
2
+ class BadCustomErrorScenario
3
+ class Error < StandardError
4
+ def initialize(*)
5
+ # Bad exceptions are exceptions that don't call super in there
6
+ # #initialize method.
7
+ end
8
+ end
9
+
10
+ def call
11
+ raise Error
12
+ rescue => exc
13
+ exc
14
+ end
15
+ end
16
+ end
17
+
@@ -0,0 +1,15 @@
1
+ module WebConsole
2
+ class BasicNestedScenario
3
+ def call
4
+ raise_an_error
5
+ rescue => exc
6
+ exc
7
+ end
8
+
9
+ private
10
+
11
+ def raise_an_error
12
+ raise
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ module WebConsole
2
+ class CustomErrorScenario
3
+ Error = Class.new(StandardError)
4
+
5
+ def call
6
+ raise Error
7
+ rescue => exc
8
+ exc
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ module WebConsole
2
+ class EvalNestedScenario
3
+ def call
4
+ tap { raise_an_error_in_eval }
5
+ rescue => exc
6
+ exc
7
+ end
8
+
9
+ private
10
+
11
+ def raise_an_error_in_eval
12
+ eval 'raise', binding, __FILE__, __LINE__
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ module WebConsole
2
+ class FlatScenario
3
+ def call
4
+ raise
5
+ rescue => exc
6
+ exc
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,21 @@
1
+ module WebConsole
2
+ class ReraisedScenario
3
+ def call
4
+ reraise_an_error
5
+ rescue => exc
6
+ exc
7
+ end
8
+
9
+ private
10
+
11
+ def raise_an_error_in_eval
12
+ method_that_raises
13
+ rescue => exc
14
+ raise exc
15
+ end
16
+
17
+ def method_that_raises
18
+ raise
19
+ end
20
+ end
21
+ end
@@ -1,5 +1,8 @@
1
- require 'simplecov'
2
- SimpleCov.start 'rails'
1
+ case RUBY_ENGINE
2
+ when 'ruby', 'rbx'
3
+ require 'simplecov'
4
+ SimpleCov.start 'rails'
5
+ end
3
6
 
4
7
  # Configure Rails Environment
5
8
  ENV["RAILS_ENV"] = "test"
@@ -19,10 +22,54 @@ module SilenceRailsDomTesting
19
22
  end
20
23
  end
21
24
 
22
- ActionController::TestCase.class_eval do
25
+ # Allows you to specify test to run only on specific Ruby platforms.
26
+ #
27
+ # Example:
28
+ #
29
+ # test 'CRuby specific feature', only: :ruby
30
+ # test 'CRuby and JRuby specific feature', only: %w(ruby jruby)
31
+ #
32
+ # If the :only option isn't present, the test is defined for all the platforms.
33
+ module PlatformSpecificTestMacro
34
+ def test(name, options = {})
35
+ platforms = Array(options[:only]).map(&:to_s)
36
+
37
+ if platforms.blank? || RUBY_ENGINE.in?(platforms)
38
+ super(name)
39
+ end
40
+ end
41
+ end
42
+
43
+ ActiveSupport::TestCase.class_eval do
44
+ extend PlatformSpecificTestMacro
45
+ end
46
+
47
+ ActionDispatch::IntegrationTest.class_eval do
23
48
  include SilenceRailsDomTesting
24
49
  end
25
50
 
51
+ # A copy of Kernel#capture in active_support/core_ext/kernel/reporting.rb as
52
+ # its getting deprecated past 4.2. Its not thread safe, but I don't need it to
53
+ # be in the tests
54
+ def capture(stream)
55
+ stream = stream.to_s
56
+ captured_stream = Tempfile.new(stream)
57
+ stream_io = eval("$#{stream}")
58
+ origin_stream = stream_io.dup
59
+ stream_io.reopen(captured_stream)
60
+
61
+ yield
62
+
63
+ stream_io.rewind
64
+ return captured_stream.read
65
+ ensure
66
+ captured_stream.close
67
+ captured_stream.unlink
68
+ stream_io.reopen(origin_stream)
69
+ end
70
+
71
+ alias silence capture
72
+
26
73
  # Load fixtures from the engine
27
74
  if ActiveSupport::TestCase.method_defined?(:fixture_path=)
28
75
  ActiveSupport::TestCase.fixture_path = File.expand_path("../fixtures", __FILE__)
@@ -0,0 +1,73 @@
1
+ require 'test_helper'
2
+
3
+ module WebConsole
4
+ class EvaluatorTest < ActiveSupport::TestCase
5
+ class TestError < StandardError
6
+ def backtrace
7
+ [
8
+ "/web-console/lib/web_console/repl.rb:16:in `eval'",
9
+ "/web-console/lib/web_console/repl.rb:16:in `eval'"
10
+ ]
11
+ end
12
+ end
13
+
14
+ class BadlyDefinedError < StandardError
15
+ def backtrace
16
+ nil
17
+ end
18
+ end
19
+
20
+ setup do
21
+ @repl1 = @repl = Evaluator.new
22
+ @repl2 = Evaluator.new
23
+ end
24
+
25
+ test 'sending input returns the result as output' do
26
+ assert_equal "=> 42\n", @repl.eval('foo = 42')
27
+ end
28
+
29
+ test 'preserves the session in the binding' do
30
+ assert_equal "=> 42\n", @repl.eval('foo = 42')
31
+ assert_equal "=> 50\n", @repl.eval('foo + 8')
32
+ end
33
+
34
+ test 'session preservation requires same bindings' do
35
+ assert_equal "=> 42\n", @repl1.eval('foo = 42')
36
+ assert_equal "=> 42\n", @repl2.eval('foo')
37
+ end
38
+
39
+ test 'formats exceptions similarly to IRB' do
40
+ repl = Evaluator.new(binding)
41
+
42
+ assert_equal <<-END.strip_heredoc, repl.eval("raise TestError, 'panic'")
43
+ #{TestError.name}: panic
44
+ \tfrom /web-console/lib/web_console/repl.rb:16:in `eval'
45
+ \tfrom /web-console/lib/web_console/repl.rb:16:in `eval'
46
+ END
47
+ end
48
+
49
+ test 'no backtrace is shown if exception backtrace is blank' do
50
+ repl = Evaluator.new(binding)
51
+
52
+ assert_equal <<-END.strip_heredoc, repl.eval("raise BadlyDefinedError")
53
+ #{BadlyDefinedError.name}: #{BadlyDefinedError.name}
54
+ END
55
+ end
56
+
57
+ test 'Evaluator callers are cleaned up of unneeded backtraces', only: :ruby do
58
+ # Those have to be on the same line to get the same trace.
59
+ repl, trace = Evaluator.new(binding), current_trace
60
+
61
+ assert_equal <<-END.strip_heredoc, repl.eval("raise")
62
+ RuntimeError:
63
+ \tfrom #{trace}
64
+ END
65
+ end
66
+
67
+ private
68
+
69
+ def current_trace
70
+ caller.first
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,76 @@
1
+ require 'test_helper'
2
+
3
+ module WebConsole
4
+ class HelperTest < ActionDispatch::IntegrationTest
5
+ class BaseApplication
6
+ include Helper
7
+
8
+ def call(env)
9
+ Rack::Response.new(<<-HTML.strip_heredoc).finish
10
+ <html>
11
+ <head>
12
+ <title>Hello world</title>
13
+ </head>
14
+ <body>
15
+ <p id="hello-world">Hello world</p>
16
+ </body>
17
+ </html>
18
+ HTML
19
+ end
20
+
21
+ private
22
+
23
+ def request
24
+ Request.new(@env)
25
+ end
26
+ end
27
+
28
+ class SingleConsoleApplication < BaseApplication
29
+ def call(env)
30
+ @env = env
31
+
32
+ console
33
+
34
+ super
35
+ end
36
+ end
37
+
38
+ class MultipleConsolesApplication < BaseApplication
39
+ def call(env)
40
+ @env = env
41
+
42
+ console
43
+ console
44
+
45
+ super
46
+ end
47
+ end
48
+
49
+ setup do
50
+ Request.stubs(:whitelisted_ips).returns(IPAddr.new('0.0.0.0/0'))
51
+
52
+ @app = Middleware.new(SingleConsoleApplication.new)
53
+ end
54
+
55
+ test 'renders a console into a view' do
56
+ get '/', nil, 'CONTENT_TYPE' => 'text/html'
57
+
58
+ assert_select '#console'
59
+ end
60
+
61
+ test 'raises an error when trying to spawn a console more than once' do
62
+ @app = Middleware.new(MultipleConsolesApplication.new)
63
+
64
+ assert_raises(DoubleRenderError) do
65
+ get '/', nil, 'CONTENT_TYPE' => 'text/html'
66
+ end
67
+ end
68
+
69
+ test "doesn't hijack current view" do
70
+ get '/', nil, 'CONTENT_TYPE' => 'text/html'
71
+
72
+ assert_select '#hello-world'
73
+ assert_select '#console'
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,47 @@
1
+ require 'test_helper'
2
+
3
+ module WebConsole
4
+ class IntegrationTest < ActiveSupport::TestCase
5
+ test 'Exception#bindings returns all the bindings of where the error originated' do
6
+ exc = FlatScenario.new.call
7
+
8
+ assert_equal 4, exc.bindings.first.eval('__LINE__')
9
+ end
10
+
11
+ test 'Exception#bindings returns all the bindings for a custom error' do
12
+ exc = CustomErrorScenario.new.call
13
+
14
+ assert_equal 6, exc.bindings.first.eval('__LINE__')
15
+ end
16
+
17
+ test 'Exception#bindings returns all the bindings for a bad custom error' do
18
+ exc = BadCustomErrorScenario.new.call
19
+
20
+ assert_equal 11, exc.bindings.first.eval('__LINE__')
21
+ end
22
+
23
+ test 'Exception#bindings goes down the stack' do
24
+ exc = BasicNestedScenario.new.call
25
+
26
+ assert_equal 12, exc.bindings.first.eval('__LINE__')
27
+ end
28
+
29
+ test 'Exception#bindings inside of an eval' do
30
+ exc = EvalNestedScenario.new.call
31
+
32
+ assert_equal 12, exc.bindings.first.eval('__LINE__')
33
+ end
34
+
35
+ test "re-raising doesn't lose Exception#bindings information" do
36
+ exc = ReraisedScenario.new.call
37
+
38
+ assert_equal 4, exc.bindings.first.eval('__LINE__')
39
+ end
40
+
41
+ test 'Exception#bindings is empty when exception is still not raised' do
42
+ exc = RuntimeError.new
43
+
44
+ assert_equal [], exc.bindings
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,116 @@
1
+ require 'test_helper'
2
+
3
+ module WebConsole
4
+ class MiddlewareTest < ActionDispatch::IntegrationTest
5
+ class Application
6
+ def call(env)
7
+ Rack::Response.new(<<-HTML.strip_heredoc).finish
8
+ <html>
9
+ <head>
10
+ <title>Hello world</title>
11
+ </head>
12
+ <body>
13
+ <p id="hello-world">Hello world</p>
14
+ </body>
15
+ </html>
16
+ HTML
17
+ end
18
+ end
19
+
20
+ setup do
21
+ Request.stubs(:whitelisted_ips).returns(IPAddr.new('0.0.0.0/0'))
22
+
23
+ @app = Middleware.new(Application.new)
24
+ end
25
+
26
+ test 'render console in an html application from web_console.binding' do
27
+ get '/', nil, 'CONTENT_TYPE' => 'text/html', 'web_console.binding' => binding
28
+
29
+ assert_select '#console'
30
+ end
31
+
32
+ test 'render console in an html application from web_console.exception' do
33
+ get '/', nil, 'CONTENT_TYPE' => 'text/html', 'web_console.exception' => raise_exception
34
+
35
+ assert_select '#console'
36
+ end
37
+
38
+ test 'prioritizes web_console.exception over web_console.binding' do
39
+ exception = raise_exception
40
+
41
+ Session.expects(:from_exception).with(exception)
42
+
43
+ get '/', nil, 'CONTENT_TYPE' => 'text/html', 'web_console.binding' => binding, 'web_console.exception' => exception
44
+ end
45
+
46
+ test 'render console in an html application with non text/html' do
47
+ get '/', nil, 'CONTENT_TYPE' => 'application/xhtml+xml', 'web_console.binding' => binding
48
+
49
+ assert_select '#console'
50
+ end
51
+
52
+ test "doesn't render console in non html application" do
53
+ get '/', nil, 'CONTENT_TYPE' => 'application/json', 'web-console.binding' => binding
54
+
55
+ assert_select '#console', 0
56
+ end
57
+
58
+ test "doesn't render console from non whitelisted IP" do
59
+ Request.stubs(:whitelisted_ips).returns(IPAddr.new('127.0.0.1'))
60
+
61
+ silence(:stderr) do
62
+ get '/', nil, 'CONTENT_TYPE' => 'text/html', 'REMOTE_ADDR' => '1.1.1.1', 'web-console.binding' => binding
63
+ end
64
+
65
+ assert_select '#console', 0
66
+ end
67
+
68
+ test "doesn't render console without a web_console.binding or web_console.exception" do
69
+ get '/', nil, 'CONTENT_TYPE' => 'text/html'
70
+
71
+ assert_select '#console', 0
72
+ end
73
+
74
+ test 'can evaluate code and return it as a JSON' do
75
+ session, line = Session.new(binding), __LINE__
76
+
77
+ Session.stubs(:from_binding).returns(session)
78
+
79
+ get '/', nil, 'CONTENT_TYPE' => 'text/html', 'web-console.binding' => binding
80
+ xhr :put, "/repl_sessions/#{session.id}", { input: '__LINE__' }
81
+
82
+ assert_equal({ output: "=> #{line}\n" }.to_json, response.body)
83
+ end
84
+
85
+ test 'can switch bindings on error pages' do
86
+ session = Session.new(exception = raise_exception)
87
+
88
+ Session.stubs(:from_exception).returns(session)
89
+
90
+ get '/', nil, 'CONTENT_TYPE' => 'text/html', 'web-console.exception' => exception
91
+ xhr :post, "/repl_sessions/#{session.id}/trace", { frame_id: 1 }
92
+
93
+ assert_equal({ ok: true }.to_json, response.body)
94
+ end
95
+
96
+ test 'unavailable sessions respond to the user with a message' do
97
+ xhr :put, '/repl_sessions/no_such_session', { input: '__LINE__' }
98
+
99
+ assert_equal(404, response.status)
100
+ end
101
+
102
+ test 'unavailable sessions can occur on binding switch' do
103
+ xhr :post, "/repl_sessions/no_such_session/trace", { frame_id: 1 }
104
+
105
+ assert_equal(404, response.status)
106
+ end
107
+
108
+ private
109
+
110
+ def raise_exception
111
+ raise
112
+ rescue => exc
113
+ exc
114
+ end
115
+ end
116
+ end