lilypad 0.2.4 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,10 @@
1
+ Sinatra::Base.set :raise_errors, false
2
+
1
3
  class SinatraApp < Sinatra::Base
2
4
 
3
- use Rack::Lilypad, 'xxx'
5
+ use Rack::Lilypad, '' do
6
+ sinatra
7
+ end
4
8
  use TestExceptionMiddleware
5
9
 
6
10
  get "/nothing" do
@@ -0,0 +1,67 @@
1
+ require File.expand_path("#{File.dirname __FILE__}/../../spec_helper")
2
+
3
+ describe Lilypad::Rails do
4
+
5
+ include Rack::Test::Methods
6
+
7
+ def app
8
+ ActionController::Dispatcher.new
9
+ end
10
+
11
+ describe :post do
12
+
13
+ after(:each) do
14
+ ENV['RACK_ENV'] = 'production'
15
+ end
16
+
17
+ before(:each) do
18
+ stub_net_http
19
+ end
20
+
21
+ it "should post an error to Hoptoad" do
22
+ @http.should_receive(:post)
23
+ get "/test" rescue nil
24
+ end
25
+
26
+ it "should post middleware exceptions" do
27
+ @http.should_receive(:post)
28
+ get "/nothing?test_exception=1" rescue nil
29
+ end
30
+
31
+ it "should not post anything if non-production environment" do
32
+ ENV['RACK_ENV'] = 'development'
33
+ @http.should_not_receive(:post)
34
+ get "/test" rescue nil
35
+ end
36
+ end
37
+
38
+ describe :RACK_ENV do
39
+
40
+ before(:each) do
41
+ ENV['RACK_ENV'] = nil
42
+ ENV['RAILS_ENV'] = 'production'
43
+ ActionController::Base.send :include, Lilypad::Rails
44
+ end
45
+
46
+ it "should set ENV['RACK_ENV']" do
47
+ ENV['RACK_ENV'].should == 'production'
48
+ end
49
+ end
50
+
51
+ describe :rescue_action_without_handler do
52
+
53
+ it "should set Config::Request.action" do
54
+ Lilypad::Config::Request.should_receive(:action).with('test')
55
+ get "/test" rescue nil
56
+ end
57
+
58
+ it "should set Config::Request.component" do
59
+ Lilypad::Config::Request.should_receive(:component).with('application')
60
+ get "/test" rescue nil
61
+ end
62
+
63
+ it "should re-raise the exception (ActionController::Failsafe disabled)" do
64
+ lambda { get "/test" }.should raise_error(TestError)
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,49 @@
1
+ require File.expand_path("#{File.dirname __FILE__}/../../spec_helper")
2
+
3
+ describe Lilypad::Sinatra do
4
+
5
+ include Rack::Test::Methods
6
+
7
+ def app
8
+ SinatraApp.new
9
+ end
10
+
11
+ describe :post do
12
+
13
+ after(:each) do
14
+ ENV['RACK_ENV'] = 'production'
15
+ end
16
+
17
+ before(:each) do
18
+ stub_net_http
19
+ end
20
+
21
+ it "should post an error to Hoptoad" do
22
+ @http.should_receive(:post)
23
+ get "/test" rescue nil
24
+ end
25
+
26
+ it "should post middleware exceptions" do
27
+ @http.should_receive(:post)
28
+ get "/nothing?test_exception=1" rescue nil
29
+ end
30
+
31
+ it "should not post anything if non-production environment" do
32
+ ENV['RACK_ENV'] = 'development'
33
+ @http.should_not_receive(:post)
34
+ get "/test" rescue nil
35
+ end
36
+ end
37
+
38
+ describe :raise_errors do
39
+
40
+ it "should set raise_errors to true" do
41
+ get "/nothing"
42
+ Sinatra::Base.raise_errors?.should == true
43
+ end
44
+
45
+ it "should re-raise the exception" do
46
+ lambda { get "/test" }.should raise_error(TestError)
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,27 @@
1
+ require File.expand_path("#{File.dirname __FILE__}/../../spec_helper")
2
+
3
+ describe Lilypad::Config::Request do
4
+
5
+ before(:each) do
6
+ Lilypad::Config::Request.action 'action'
7
+ Lilypad::Config::Request.component 'component'
8
+ end
9
+
10
+ after(:each) do
11
+ Lilypad::Config::Request.class_eval do
12
+ @action = nil
13
+ @component = nil
14
+ end
15
+ end
16
+
17
+ it "should set options" do
18
+ Lilypad::Config::Request.action.should == 'action'
19
+ Lilypad::Config::Request.component.should == 'component'
20
+ end
21
+
22
+ it "should provide a method to reset all options" do
23
+ Lilypad::Config::Request.reset!
24
+ Lilypad::Config::Request.action.should == nil
25
+ Lilypad::Config::Request.component.should == nil
26
+ end
27
+ end
@@ -0,0 +1,59 @@
1
+ require File.expand_path("#{File.dirname __FILE__}/../spec_helper")
2
+
3
+ describe Lilypad::Config do
4
+
5
+ before(:each) do
6
+ Lilypad::Config.api_key 'api_key'
7
+ Lilypad::Config.deploy_url 'deploy_url'
8
+ Lilypad::Config.environments 'environments'
9
+ Lilypad::Config.filters 'filters'
10
+ Lilypad::Config.log 'log'
11
+ Lilypad::Config.notify_url 'notify_url'
12
+ end
13
+
14
+ after(:each) do
15
+ Lilypad::Config.class_eval do
16
+ @api_key = nil
17
+ @deploy_url = nil
18
+ @environments = nil
19
+ @filters = nil
20
+ @log = nil
21
+ @notify_url = nil
22
+ end
23
+ end
24
+
25
+ it "should set options" do
26
+ Lilypad::Config.api_key.should == 'api_key'
27
+ Lilypad::Config.deploy_url.should == 'deploy_url'
28
+ Lilypad::Config.environments.should == 'environments'
29
+ Lilypad::Config.filters.should == 'filters'
30
+ Lilypad::Config.log.should == 'log'
31
+ Lilypad::Config.notify_url.should == 'notify_url'
32
+ end
33
+
34
+ it "should require the rails adapter when the rails method is called" do
35
+ adapter = File.expand_path "#{SPEC}/../lib/lilypad/adapters/rails"
36
+ Lilypad::Config.should_receive(:require).with(adapter)
37
+ Lilypad::Config.rails
38
+ end
39
+
40
+ it "should require the rails adapter when the sinatra method is called" do
41
+ adapter = File.expand_path "#{SPEC}/../lib/lilypad/adapters/sinatra"
42
+ Lilypad::Config.should_receive(:require).with(adapter)
43
+ Lilypad::Config.sinatra
44
+ end
45
+
46
+ describe :Methods do
47
+
48
+ include Lilypad::Config::Methods
49
+
50
+ it "should provide an api_key method" do
51
+ Lilypad::Config.api_key 'api_key'
52
+ api_key.should == 'api_key'
53
+ Lilypad::Config.api_key { |env, e| [ env, e ].join '_' }
54
+ api_key.should == 'api_key' # api string takes precedence even when block configured
55
+ Lilypad::Config.class_eval { @api_key = nil }
56
+ api_key('api_key', 'block').should == 'api_key_block' # string is nil, now use the block
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,85 @@
1
+ require File.expand_path("#{File.dirname __FILE__}/../../spec_helper")
2
+
3
+ describe Lilypad::Hoptoad::Deploy do
4
+
5
+ before(:each) do
6
+ stub_net_http
7
+ @options = {
8
+ :username => 'username',
9
+ :environment => 'environment',
10
+ :revision => 'revision',
11
+ :repository => 'repository'
12
+ }
13
+ @instance = Lilypad::Hoptoad::Deploy.new(@options)
14
+ end
15
+
16
+ describe :initialize do
17
+
18
+ after(:each) do
19
+ @instance.send(:initialize, @options)
20
+ end
21
+
22
+ it "should call the post method" do
23
+ @instance.should_receive(:post)
24
+ end
25
+
26
+ it "should log the event" do
27
+ @instance.should_receive(:log).with(:deploy, @http_ok)
28
+ end
29
+
30
+ it "should return the success status" do
31
+ @instance.should_receive(:success?)
32
+ end
33
+ end
34
+
35
+ describe :params do
36
+
37
+ before(:each) do
38
+ Lilypad { api_key '' }
39
+ end
40
+
41
+ it "should return parameters for the Hoptoad request" do
42
+ @instance.send(:params).should == {
43
+ 'api_key' => '',
44
+ 'deploy[local_username]' => @options[:username],
45
+ 'deploy[rails_env]' => @options[:environment],
46
+ 'deploy[scm_revision]' => @options[:revision],
47
+ 'deploy[scm_repository]' => @options[:repository]
48
+ }
49
+ end
50
+ end
51
+
52
+ describe :post do
53
+
54
+ before(:each) do
55
+ URI.stub!(:parse).and_return('uri')
56
+ @instance.stub!(:params).and_return('params')
57
+ end
58
+
59
+ after(:each) do
60
+ @instance.send(:post)
61
+ end
62
+
63
+ it "should parse the URI" do
64
+ URI.should_receive(:parse).with(Lilypad::Config.deploy_url)
65
+ end
66
+
67
+ it "should post the form using the URI and params method" do
68
+ @instance.should_receive(:params)
69
+ Net::HTTP.should_receive(:post_form).with('uri', 'params')
70
+ end
71
+ end
72
+
73
+ describe :success? do
74
+
75
+ it "should make sure the response's superclass equals Net::HTTPSuccess" do
76
+ Net::HTTP.stub!(:post_form).and_return(nil)
77
+ @instance.send(:initialize, @options)
78
+ @instance.send(:success?).should == false
79
+
80
+ Net::HTTP.stub!(:post_form).and_return(@http_ok)
81
+ @instance.send(:initialize, @options)
82
+ @instance.send(:success?).should == true
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,138 @@
1
+ require File.expand_path("#{File.dirname __FILE__}/../../spec_helper")
2
+
3
+ describe Lilypad::Hoptoad::Notify do
4
+
5
+ before(:each) do
6
+ uri = mock(:uri)
7
+ uri.stub!(:host)
8
+ uri.stub!(:port)
9
+ uri.stub!(:path).and_return('uri')
10
+ URI.stub!(:parse).and_return(uri)
11
+ stub_net_http
12
+ begin; raise 'Test'; rescue Exception => e; @e = e; end
13
+ @instance = Lilypad::Hoptoad::Notify.new(nil, @e)
14
+ end
15
+
16
+ describe :initialize do
17
+
18
+ before(:each) do
19
+ Lilypad::Hoptoad::XML.stub!(:build).and_return('xml')
20
+ @instance.stub!(:headers).and_return 'headers'
21
+ @instance.stub!(:parse).and_return ['parse']
22
+ end
23
+
24
+ after(:each) do
25
+ @instance.send(:initialize, nil, @e)
26
+ end
27
+
28
+ it "should build XML from parse method" do
29
+ Lilypad::Hoptoad::XML.should_receive(:build).with('parse')
30
+ end
31
+
32
+ it "should post the XML" do
33
+ @http.should_receive(:post).with('uri', 'xml', 'headers')
34
+ end
35
+
36
+ it "should log the event" do
37
+ @instance.should_receive(:log).with(:notify, @http_ok)
38
+ end
39
+
40
+ it "should reset the request config" do
41
+ Lilypad::Config::Request.should_receive(:reset!)
42
+ end
43
+
44
+ it "should return the success status" do
45
+ @instance.should_receive(:success?)
46
+ end
47
+ end
48
+
49
+ describe :backtrace do
50
+
51
+ it "should return an array of backtrace information" do
52
+ backtrace = @instance.send(:backtrace)
53
+ backtrace.first.file.should =~ /notify_spec/
54
+ backtrace.first.respond_to?(:number).should == true
55
+ backtrace.first.respond_to?(:method).should == true
56
+ backtrace.length.should > 1
57
+ end
58
+ end
59
+
60
+ describe :filter do
61
+
62
+ after(:each) do
63
+ Lilypad { filters [] }
64
+ end
65
+
66
+ it "should remove elements of a hash for keys that match an element Config.filters" do
67
+ Lilypad { filters [ 't1' ] }
68
+ filtered = @instance.send(:filter, { :t1 => 't1', :t2 => 't2' })
69
+ filtered.should == { :t1 => '[FILTERED]', :t2 => 't2' }
70
+ end
71
+ end
72
+
73
+ describe :http_start do
74
+
75
+ after(:each) do
76
+ @instance.send(:http_start) {}
77
+ end
78
+
79
+ it "should get a URI instance for the notify URL" do
80
+ URI.should_receive(:parse).with(Lilypad::Config.notify_url)
81
+ end
82
+
83
+ it "should call start on Net::HTTP" do
84
+ Net::HTTP.should_receive(:start)
85
+ end
86
+
87
+ it "should yield to the block" do
88
+ yielded = false
89
+ @instance.send(:http_start) { yielded = true }
90
+ yielded.should == true
91
+ end
92
+ end
93
+
94
+ describe :parse do
95
+
96
+ before(:each) do
97
+ @env = mock(:env)
98
+ @env.stub!(:merge).and_return('env')
99
+ ENV.stub!(:to_hash).and_return(@env)
100
+ @instance.stub!(:filter).and_return('env')
101
+ @instance.stub!(:backtrace).and_return('backtrace')
102
+ end
103
+
104
+ it "should filter the environment" do
105
+ @instance.should_receive(:filter).with('env')
106
+ ENV.should_receive(:to_hash)
107
+ @env.should_receive(:merge)
108
+ @instance.send(:parse)
109
+ end
110
+
111
+ it "should return the correct parameters without an environment" do
112
+ @instance.send(:parse).should == [ "backtrace", "env", @e, {}, "Internal" ]
113
+ end
114
+
115
+ it "should return the correct parameters with an environment" do
116
+ request = mock(:request)
117
+ request.stub!(:params)
118
+ request.stub!(:script_name).and_return 'request_'
119
+ request.stub!(:path_info).and_return 'path'
120
+ Rack::Request.stub!(:new).and_return(request)
121
+ @instance.send(:initialize, {}, @e)
122
+ @instance.send(:parse).should == ["backtrace", "env", @e, "env", "request_path"]
123
+ end
124
+ end
125
+
126
+ describe :success? do
127
+
128
+ it "should make sure the response's superclass equals Net::HTTPSuccess" do
129
+ @http.stub!(:post).and_return(nil)
130
+ @instance.send(:initialize, nil, @e)
131
+ @instance.send(:success?).should == false
132
+
133
+ @http.stub!(:post).and_return(@http_ok)
134
+ @instance.send(:initialize, nil, @e)
135
+ @instance.send(:success?).should == true
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,76 @@
1
+ require "#{File.dirname(__FILE__)}/spec_helper"
2
+
3
+ describe Rack::Lilypad do
4
+
5
+ include Rack::Test::Methods
6
+
7
+ before(:each) do
8
+ @app = lambda { |env| raise TestError, 'Test' }
9
+ @env = Rack::MockRequest.env_for("/test")
10
+ stub_net_http
11
+ end
12
+
13
+ it "should yield a configuration object to the block when created" do
14
+ Rack::Lilypad.new(@app, '') do
15
+ filters %w(T1 T2)
16
+ log 'T3'
17
+ end
18
+ Lilypad::Config.filters.include?('T1').should == true
19
+ Lilypad::Config.filters.include?('T2').should == true
20
+ Lilypad::Config.log.should == 'T3'
21
+
22
+ Lilypad::Config.filters []
23
+ Lilypad::Config.log false
24
+ end
25
+
26
+ it "should write to a log file on success and failure" do
27
+ log_path = "#{SPEC}/fixtures/hoptoad.log"
28
+ notifier = Rack::Lilypad.new(@app, '') do |app|
29
+ log log_path
30
+ end
31
+
32
+ notifier.call(@env) rescue nil
33
+
34
+ File.exists?(log_path).should == true
35
+ File.read(log_path).should =~ /Notify Success/
36
+ File.delete(log_path)
37
+
38
+ @http.stub!(:post).and_return false
39
+ notifier.call(@env) rescue nil
40
+
41
+ File.exists?(log_path).should == true
42
+ File.read(log_path).should =~ /Notify Failure/
43
+ File.delete(log_path)
44
+
45
+ Lilypad::Config.log false
46
+ end
47
+
48
+ it "should transfer valid XML to Hoptoad" do
49
+ # Test complex environment variables
50
+ @env['rack.hash_test'] = { :test => true }
51
+ @env['rack.object_test'] = Object.new
52
+
53
+ notifier = Rack::Lilypad.new(@app, '')
54
+ notifier.call(@env) rescue nil
55
+ validate_xml
56
+ end
57
+
58
+ it "should provide a notify method" do
59
+ @http.should_receive(:post)
60
+ begin
61
+ raise TestError, 'Test'
62
+ rescue Exception => e
63
+ Lilypad.notify(e)
64
+ end
65
+ end
66
+
67
+ it "should provide a deploy method" do
68
+ Net::HTTP.should_receive(:post_form)
69
+ Lilypad.deploy(
70
+ :username => 't1',
71
+ :environment => 't2',
72
+ :revision => 't3',
73
+ :repository => 't4'
74
+ )
75
+ end
76
+ end