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.
- checksums.yaml +4 -4
- data/README.markdown +132 -85
- data/lib/web_console.rb +14 -13
- data/lib/web_console/errors.rb +7 -0
- data/lib/web_console/{repl.rb → evaluator.rb} +7 -10
- data/lib/web_console/helper.rb +22 -0
- data/lib/web_console/integration.rb +8 -0
- data/lib/web_console/{core_ext/exception → integration}/cruby.rb +0 -0
- data/lib/web_console/integration/jruby.rb +111 -0
- data/lib/web_console/integration/rubinius.rb +66 -0
- data/lib/web_console/middleware.rb +117 -0
- data/lib/web_console/railtie.rb +61 -0
- data/lib/web_console/request.rb +30 -0
- data/lib/web_console/session.rb +65 -0
- data/lib/web_console/template.rb +49 -0
- data/lib/web_console/templates/_inner_console_markup.html +3 -0
- data/lib/web_console/templates/_markup.html +4 -0
- data/lib/web_console/templates/_prompt_box_markup.html +2 -0
- data/lib/web_console/templates/console.js +373 -0
- data/lib/web_console/templates/error_page.js +83 -0
- data/lib/web_console/templates/index.html +8 -0
- data/lib/web_console/templates/layouts/inlined_string.erb +1 -0
- data/lib/web_console/templates/layouts/javascript.erb +5 -0
- data/lib/web_console/templates/main.js +24 -0
- data/lib/web_console/templates/style.css +9 -0
- data/lib/web_console/version.rb +1 -1
- data/lib/web_console/whiny_request.rb +38 -0
- data/lib/web_console/whitelist.rb +42 -0
- data/test/dummy/config/environments/test.rb +0 -4
- data/test/dummy/log/development.log +7075 -0
- data/test/dummy/log/test.log +66006 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
- data/test/support/scenarios/bad_custom_error_scenario.rb +17 -0
- data/test/support/scenarios/basic_nested_scenario.rb +15 -0
- data/test/support/scenarios/custom_error_scenario.rb +11 -0
- data/test/support/scenarios/eval_nested_scenario.rb +15 -0
- data/test/support/scenarios/flat_scenario.rb +9 -0
- data/test/support/scenarios/reraised_scenario.rb +21 -0
- data/test/test_helper.rb +50 -3
- data/test/web_console/evaluator_test.rb +73 -0
- data/test/web_console/helper_test.rb +76 -0
- data/test/web_console/integration_test.rb +47 -0
- data/test/web_console/middleware_test.rb +116 -0
- data/test/web_console/railtie_test.rb +99 -0
- data/test/web_console/request_test.rb +52 -0
- data/test/web_console/session_test.rb +59 -0
- data/test/web_console/whiny_request_test.rb +33 -0
- data/test/web_console/whitelist_test.rb +43 -0
- metadata +66 -56
- data/lib/action_dispatch/debug_exceptions.rb +0 -105
- data/lib/action_dispatch/exception_wrapper.rb +0 -38
- data/lib/action_dispatch/templates/rescues/_request_and_response.html.erb +0 -34
- data/lib/action_dispatch/templates/rescues/_request_and_response.text.erb +0 -23
- data/lib/action_dispatch/templates/rescues/_source.erb +0 -29
- data/lib/action_dispatch/templates/rescues/_trace.html.erb +0 -72
- data/lib/action_dispatch/templates/rescues/_trace.text.erb +0 -9
- data/lib/action_dispatch/templates/rescues/_web_console.html.erb +0 -420
- data/lib/action_dispatch/templates/rescues/diagnostics.html.erb +0 -18
- data/lib/action_dispatch/templates/rescues/diagnostics.text.erb +0 -9
- data/lib/action_dispatch/templates/rescues/layout.erb +0 -160
- data/lib/action_dispatch/templates/rescues/missing_template.html.erb +0 -13
- data/lib/action_dispatch/templates/rescues/missing_template.text.erb +0 -3
- data/lib/action_dispatch/templates/rescues/routing_error.html.erb +0 -34
- data/lib/action_dispatch/templates/rescues/routing_error.text.erb +0 -11
- data/lib/action_dispatch/templates/rescues/template_error.html.erb +0 -22
- data/lib/action_dispatch/templates/rescues/template_error.text.erb +0 -7
- data/lib/action_dispatch/templates/rescues/unknown_action.html.erb +0 -6
- data/lib/action_dispatch/templates/rescues/unknown_action.text.erb +0 -3
- data/lib/action_dispatch/templates/routes/_route.html.erb +0 -16
- data/lib/action_dispatch/templates/routes/_table.html.erb +0 -200
- data/lib/assets/javascripts/web-console.js +0 -1
- data/lib/assets/javascripts/web_console.js +0 -41
- data/lib/web_console/controller_helpers.rb +0 -46
- data/lib/web_console/core_ext/exception.rb +0 -7
- data/lib/web_console/core_ext/exception/jruby.rb +0 -25
- data/lib/web_console/core_ext/exception/rubinius.rb +0 -32
- data/lib/web_console/engine.rb +0 -47
- data/lib/web_console/repl_session.rb +0 -89
- data/lib/web_console/unsupported_platforms.rb +0 -28
- data/lib/web_console/view_helpers.rb +0 -16
- data/test/action_pack/exception_wrapper_test.rb +0 -26
- data/test/controllers/tests_controller_test.rb +0 -41
- data/test/web_console/core_ext/exception_test.rb +0 -46
- data/test/web_console/engine_test.rb +0 -108
- data/test/web_console/repl_session_test.rb +0 -32
- data/test/web_console/repl_test.rb +0 -75
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -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,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
|
data/test/test_helper.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
|
-
|
2
|
-
|
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
|
-
|
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
|