tobias-rack-webconsole 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,56 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ class AssetClass
5
+ include Rack::Webconsole::AssetHelpers
6
+ end
7
+
8
+ module Rack
9
+ describe Webconsole::AssetHelpers do
10
+
11
+ describe '#html_code' do
12
+ it 'loads the html code' do
13
+ asset_class = AssetClass.new
14
+ html = asset_class.html_code
15
+
16
+ html.must_match /console/
17
+ html.must_match /results/
18
+ html.must_match /form/
19
+ end
20
+ end
21
+
22
+ describe '#css_code' do
23
+ it 'loads the css code' do
24
+ asset_class = AssetClass.new
25
+ css = asset_class.css_code
26
+
27
+ css.must_match /<style/
28
+ css.must_match /text\/css/
29
+ css.must_match /#console/
30
+ end
31
+ end
32
+
33
+ describe '#js_code' do
34
+ it 'loads the js code' do
35
+ asset_class = AssetClass.new
36
+ js = asset_class.js_code
37
+
38
+ js.must_match /\$\("#rack-webconsole"\)/
39
+ js.must_match /escapeHTML/
40
+ end
41
+ end
42
+
43
+ describe '#render' do
44
+ it 'knows how to replace $ vars' do
45
+ asset_class = AssetClass.new
46
+
47
+ text = "test $test test $test"
48
+ asset_class.render(text, :test => "123").must_equal("test 123 test 123")
49
+
50
+ text = "test $var1 test $var2"
51
+ asset_class.render(text, :var1 => "123", :var2 => "321").must_equal("test 123 test 321")
52
+ end
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,101 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+ require 'ostruct'
4
+
5
+ module Rack
6
+ describe Webconsole::Assets do
7
+
8
+ it 'initializes with an app' do
9
+ @app = stub
10
+ @assets = Webconsole::Assets.new(@app)
11
+ @assets.instance_variable_get(:@app).must_equal @app
12
+ end
13
+
14
+ describe "#code" do
15
+ it 'injects the token, key_code, and context path' do
16
+ Webconsole::Repl.stubs(:token).returns('fake_generated_token')
17
+ Webconsole.key_code = "96"
18
+
19
+ @assets = Webconsole::Assets.new(nil)
20
+ assets_code = @assets.code('SCRIPT_NAME' => '/hambiscuit')
21
+
22
+ assets_code.must_match /fake_generated_token/
23
+ assets_code.must_match /event\.which == 96/
24
+ assets_code.must_match %r{/hambiscuit/webconsole}
25
+ end
26
+
27
+ end
28
+
29
+ describe "#call" do
30
+
31
+ describe 'when the call is not appropriate to inject the view code' do
32
+ # Different invalid cases
33
+ [
34
+ [200, {'Content-Type' => 'text/html'}, ['Whatever']],
35
+ [200, {'Content-Type' => 'text/plain'}, ['Hello World']],
36
+ [404, {'Content-Type' => 'text/html'}, ['Hello World']],
37
+ [404, {'Content-Type' => 'text/html'}, ['Hello, World']],
38
+
39
+ ].each do |invalid_response|
40
+ it 'passes the call untouched' do
41
+ @app = lambda { |env| invalid_response }
42
+
43
+ assets = Webconsole::Assets.new(@app)
44
+ assets.expects(:inject_code).never
45
+
46
+ assets.call({}).last.first.must_equal invalid_response.last.first
47
+ end
48
+ end
49
+ end
50
+
51
+ describe 'otherwise' do
52
+
53
+ it 'injects the view code before the body ending' do
54
+
55
+ valid_html = "<!DOCTYPE html>\n<html>\n<head>\n <title>Testapp</title>\n <link href=\"/assets/application.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n <script src=\"/assets/application.js\" type=\"text/javascript\"></script>\n <meta content=\"authenticity_token\" name=\"csrf-param\" />\n<meta content=\"26Ls63zdKBiCXoqU5CuG6KqVbeMYydRqOuovP+DXx8g=\" name=\"csrf-token\" />\n</head>\n<body>\n\n<h1> Hello bitches </h1>\n\n<p> Lorem ipsum dolor sit amet. </p>\n\n\n</body>\n</html>\n"
56
+
57
+ html = [valid_html]
58
+
59
+ @app = lambda { |env| [200, {'Content-Type' => 'text/html'}, html] }
60
+
61
+ assets = Webconsole::Assets.new(@app)
62
+ response = assets.call({}).last.first
63
+
64
+ response.must_match /input name/m # html
65
+ response.must_match /text\/css/m # css
66
+ response.must_match /escapeHTML/m # js
67
+ end
68
+
69
+ it "works with Rails' particular conception of what a response is" do
70
+
71
+ valid_html = "<!DOCTYPE html>\n<html>\n<head>\n <title>Testapp</title>\n <link href=\"/assets/application.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n <script src=\"/assets/application.js\" type=\"text/javascript\"></script>\n <meta content=\"authenticity_token\" name=\"csrf-param\" />\n<meta content=\"26Ls63zdKBiCXoqU5CuG6KqVbeMYydRqOuovP+DXx8g=\" name=\"csrf-token\" />\n</head>\n<body>\n\n<h1> Hello bitches </h1>\n\n<p> Lorem ipsum dolor sit amet. </p>\n\n\n</body>\n</html>\n"
72
+
73
+ @app = lambda { |env| [200, {'Content-Type' => 'text/html'}, OpenStruct.new({:body => valid_html})] }
74
+
75
+ assets = Webconsole::Assets.new(@app)
76
+
77
+ response = assets.call({}).last.first
78
+
79
+ response.must_match /input name/m # html
80
+ response.must_match /text\/css/m # css
81
+ response.must_match /escapeHTML/m # js
82
+ end
83
+
84
+ it 'exposes the request object to the console' do
85
+ valid_html = "<!DOCTYPE html>\n<html>\n<head>\n <title>Testapp</title>\n <link href=\"/assets/application.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n <script src=\"/assets/application.js\" type=\"text/javascript\"></script>\n <meta content=\"authenticity_token\" name=\"csrf-param\" />\n<meta content=\"26Ls63zdKBiCXoqU5CuG6KqVbeMYydRqOuovP+DXx8g=\" name=\"csrf-token\" />\n</head>\n<body>\n\n<h1> Hello bitches </h1>\n\n<p> Lorem ipsum dolor sit amet. </p>\n\n\n</body>\n</html>\n"
86
+
87
+ @app = lambda { |env| [200, {'Content-Type' => 'text/html'}, OpenStruct.new({:body => valid_html})] }
88
+
89
+ env = {'PATH_INFO' => '/some_path'}
90
+ assets = Webconsole::Assets.new(@app)
91
+
92
+ assets.call(env)
93
+
94
+ Webconsole::Repl.request.env['PATH_INFO'].must_equal '/some_path'
95
+ end
96
+
97
+ end
98
+ end
99
+
100
+ end
101
+ end
@@ -0,0 +1,106 @@
1
+ require 'spec_helper'
2
+ require 'ostruct'
3
+
4
+ module Rack
5
+ describe Webconsole::Repl do
6
+
7
+ it 'initializes with an app' do
8
+ @app = stub
9
+ @repl = Webconsole::Repl.new(@app)
10
+
11
+ @repl.instance_variable_get(:@app).must_equal @app
12
+ end
13
+
14
+ describe "#call" do
15
+ it 'evaluates the :query param in a sandbox and returns the result' do
16
+ @app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ['hello world']] }
17
+ env = {}
18
+ Webconsole::Repl.stubs(:token).returns('abc')
19
+ request = OpenStruct.new(:params => {'query' => 'a = 4; a * 2', 'token' => 'abc'}, :post? => true)
20
+ Rack::Request.stubs(:new).returns request
21
+
22
+ @repl = Webconsole::Repl.new(@app)
23
+
24
+ response = @repl.call(env).last.first
25
+
26
+ MultiJson.decode(response)['result'].must_equal "8"
27
+ end
28
+
29
+ it 'maintains local state in subsequent calls thanks to an evil global variable' do
30
+ @app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ['hello world']] }
31
+ env = {}
32
+ Webconsole::Repl.stubs(:token).returns('abc')
33
+ request = OpenStruct.new(:params => {'query' => 'a = 4', 'token' => 'abc'}, :post? => true)
34
+ Rack::Request.stubs(:new).returns request
35
+ @repl = Webconsole::Repl.new(@app)
36
+
37
+ @repl.call(env) # call 1 sets a to 4
38
+
39
+ request = OpenStruct.new(:params => {'query' => 'a * 8', 'token' => 'abc'}, :post? => true)
40
+ Rack::Request.stubs(:new).returns request
41
+
42
+ response = @repl.call(env).last.first # call 2 retrieves a and multiplies it by 8
43
+
44
+ MultiJson.decode(response)['result'].must_equal "32"
45
+ $sandbox.instance_variable_get(:@locals)[:a].must_equal 4
46
+ $sandbox.instance_variable_get(:@locals).size.must_equal 1
47
+ end
48
+
49
+ it "returns any found errors prepended with 'Error:'" do
50
+ @app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ['hello world']] }
51
+ env = {}
52
+ Webconsole::Repl.stubs(:token).returns('abc')
53
+ request = OpenStruct.new(:params => {'query' => 'unknown_method', 'token' => 'abc'}, :post? => true)
54
+ Rack::Request.stubs(:new).returns request
55
+ @repl = Webconsole::Repl.new(@app)
56
+
57
+ response = @repl.call(env).last.first
58
+
59
+ MultiJson.decode(response)['result'].must_match /Error:/
60
+ end
61
+
62
+ it 'rejects non-post requests' do
63
+ @app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ['hello world']] }
64
+ env = {}
65
+ Webconsole::Repl.stubs(:token).returns('abc')
66
+ request = OpenStruct.new(:params => {'query' => 'unknown_method', 'token' => 'abc'}, :post? => false)
67
+ Rack::Request.stubs(:new).returns request
68
+ @repl = Webconsole::Repl.new(@app)
69
+
70
+ $sandbox.expects(:instance_eval).never
71
+
72
+ @repl.call(env).must_equal @app.call(env)
73
+ end
74
+
75
+ it 'rejects requests with invalid token' do
76
+ @app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ['hello world']] }
77
+ env = {}
78
+ Webconsole::Repl.stubs(:token).returns('abc')
79
+ request = OpenStruct.new(:params => {'query' => 'unknown_method', 'token' => 'cba'}, :post? => true)
80
+ Rack::Request.stubs(:new).returns request
81
+ @repl = Webconsole::Repl.new(@app)
82
+
83
+ $sandbox.expects(:instance_eval).never
84
+
85
+ @repl.call(env).must_equal @app.call(env)
86
+ end
87
+ end
88
+
89
+ describe 'class methods' do
90
+ describe '#reset_token and #token' do
91
+ it 'returns the security token' do
92
+ Webconsole::Repl.reset_token
93
+ Webconsole::Repl.token.must_be_kind_of String
94
+ end
95
+ end
96
+ describe '#request= and #request' do
97
+ it 'returns the request object' do
98
+ request = stub
99
+ Webconsole::Repl.request = request
100
+ Webconsole::Repl.request.must_equal request
101
+ end
102
+ end
103
+ end
104
+
105
+ end
106
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ module Rack
4
+ describe Webconsole::Sandbox do
5
+
6
+ describe "#method_missing" do
7
+ describe 'when the method exists in @locals' do
8
+ it 'retrieves it' do
9
+ @sandbox = Webconsole::Sandbox.new
10
+ @sandbox.instance_variable_set(:@locals, {:a => 123})
11
+
12
+ @sandbox.a.must_equal 123
13
+ end
14
+ end
15
+ describe 'otherwise' do
16
+ it 'raises a NoMethodError' do
17
+ @sandbox = Webconsole::Sandbox.new
18
+
19
+ lambda {
20
+ @sandbox.a
21
+ }.must_raise NoMethodError
22
+ end
23
+ end
24
+ end
25
+
26
+ describe "#reload!" do
27
+ it 'assigns a new, fresh Sandbox to the global variable' do
28
+ old_sandbox = $sandbox = Webconsole::Sandbox.new
29
+
30
+ $sandbox.reload!
31
+
32
+ $sandbox.wont_equal old_sandbox
33
+ end
34
+ it 'returns a feedback string' do
35
+ Webconsole::Sandbox.new.reload!.must_equal 'ok'
36
+ end
37
+ end
38
+
39
+ describe "request" do
40
+ it 'returns the request object' do
41
+ @sandbox = Webconsole::Sandbox.new
42
+ request = Rack::Request.new({'PATH_INFO' => '/some_path'})
43
+ Webconsole::Repl.request = request
44
+
45
+ @sandbox.request.must_equal request
46
+ end
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ module Rack
4
+ describe Webconsole::Shell do
5
+ before do
6
+ Ripl.instance_variable_set(:@shell, nil)
7
+ end
8
+
9
+ describe ".eval_query" do
10
+ describe "sets Ripl::Shell" do
11
+ before { Webconsole::Shell.eval_query('2 + 2') }
12
+
13
+ it "#input" do
14
+ Ripl.shell.input.must_equal '2 + 2'
15
+ end
16
+
17
+ it "#result" do
18
+ Ripl.shell.result.must_equal 4
19
+ end
20
+
21
+ it "#history" do
22
+ Ripl.shell.history.must_equal ['2 + 2']
23
+ end
24
+ end
25
+
26
+ describe "for one line input" do
27
+ def response
28
+ Webconsole::Shell.eval_query("'input'")
29
+ end
30
+
31
+ it ":result returns inspected result" do
32
+ response[:result].must_equal '"input"'
33
+ end
34
+
35
+ it ":prompt returns normal prompt" do
36
+ response[:prompt] = '>> '
37
+ end
38
+
39
+ it "returns false for multi_line keys" do
40
+ response[:multi_line].must_equal false
41
+ response[:previous_multi_line].must_equal false
42
+ end
43
+
44
+ it "with an error :result returns error raised" do
45
+ Webconsole::Shell.eval_query("blah")[:result].must_match /^Error:/
46
+ end
47
+ end
48
+
49
+ describe "for multi line input" do
50
+ def response
51
+ [
52
+ Webconsole::Shell.eval_query("[1,2,3].map do |num|"),
53
+ Webconsole::Shell.eval_query("num ** 2"),
54
+ Webconsole::Shell.eval_query("end")
55
+ ]
56
+ end
57
+
58
+ it "returns correct results" do
59
+ response.map {|e| e[:result] }.must_equal [nil, nil, "[1, 4, 9]"]
60
+ end
61
+
62
+ it "returns correct prompts" do
63
+ response.map {|e| e[:prompt] }.must_equal ['>> ', '|| ', '|| ']
64
+ end
65
+
66
+ it "returns correct multi_line keys" do
67
+ response.map {|e| e[:multi_line] }.must_equal [true, true, false]
68
+ response.map {|e| e[:previous_multi_line] }.must_equal [false, true, true]
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,56 @@
1
+ require 'spec_helper'
2
+
3
+ module Rack
4
+ describe Webconsole do
5
+
6
+ it 'initializes with an app' do
7
+ @app = stub
8
+ @webconsole = Webconsole.new(@app)
9
+
10
+ @webconsole.instance_variable_get(:@app).must_equal @app
11
+ end
12
+
13
+ describe "#call" do
14
+ it 'delegates the call to the Repl middleware when the path is /webconsole' do
15
+ @app = stub
16
+ @webconsole = Webconsole.new(@app)
17
+ @env = {'PATH_INFO' => '/webconsole'}
18
+
19
+ repl = stub
20
+ Webconsole::Repl.expects(:new).with(@app).returns repl
21
+ repl.expects(:call).with @env
22
+
23
+ @webconsole.call(@env)
24
+ end
25
+
26
+ it 'passes the call to the Assets middleware otherwise' do
27
+ @app = stub
28
+ @webconsole = Webconsole.new(@app)
29
+ @env = {'PATH_INFO' => '/whatever'}
30
+
31
+ assets = stub
32
+ Webconsole::Assets.expects(:new).with(@app).returns assets
33
+ assets.expects(:call).with @env
34
+
35
+ @webconsole.call(@env)
36
+ end
37
+ end
38
+
39
+ describe 'class methods' do
40
+ it '#inject_jquery accessors' do
41
+ Webconsole.inject_jquery.must_equal false
42
+ Webconsole.inject_jquery = true
43
+ Webconsole.inject_jquery.must_equal true
44
+ end
45
+ it '#key_code accessors' do
46
+ Webconsole.key_code.must_equal "96"
47
+ Webconsole.key_code = "97"
48
+ Webconsole.key_code.must_equal "97"
49
+ end
50
+ it '#key_code setter cast parameter type' do
51
+ Webconsole.key_code = 96
52
+ Webconsole.key_code.must_equal "96"
53
+ end
54
+ end
55
+ end
56
+ end