cloudtrapper 0.0.2.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +823 -0
- data/Gemfile +12 -0
- data/Guardfile +6 -0
- data/INSTALL +20 -0
- data/MIT-LICENSE +22 -0
- data/README.md +465 -0
- data/README_FOR_HEROKU_ADDON.md +94 -0
- data/Rakefile +223 -0
- data/SUPPORTED_RAILS_VERSIONS +23 -0
- data/TESTING.md +33 -0
- data/cloudtrapper.gemspec +35 -0
- data/features/metal.feature +18 -0
- data/features/rack.feature +56 -0
- data/features/rails.feature +211 -0
- data/features/rails_with_js_notifier.feature +97 -0
- data/features/rake.feature +27 -0
- data/features/sinatra.feature +29 -0
- data/features/step_definitions/file_steps.rb +10 -0
- data/features/step_definitions/metal_steps.rb +23 -0
- data/features/step_definitions/rack_steps.rb +23 -0
- data/features/step_definitions/rails_application_steps.rb +433 -0
- data/features/step_definitions/rake_steps.rb +17 -0
- data/features/support/airbrake_shim.rb.template +11 -0
- data/features/support/env.rb +18 -0
- data/features/support/matchers.rb +35 -0
- data/features/support/rails.rb +201 -0
- data/features/support/rake/Rakefile +68 -0
- data/features/support/terminal.rb +107 -0
- data/features/user_informer.feature +63 -0
- data/generators/cloudtrapper/airbrake_generator.rb +94 -0
- data/generators/cloudtrapper/lib/insert_commands.rb +34 -0
- data/generators/cloudtrapper/lib/rake_commands.rb +24 -0
- data/generators/cloudtrapper/templates/capistrano_hook.rb +6 -0
- data/generators/cloudtrapper/templates/cloudtrapper_tasks.rake +25 -0
- data/generators/cloudtrapper/templates/initializer.rb +6 -0
- data/install.rb +1 -0
- data/lib/cloudtrapper/backtrace.rb +100 -0
- data/lib/cloudtrapper/capistrano.rb +44 -0
- data/lib/cloudtrapper/configuration.rb +281 -0
- data/lib/cloudtrapper/notice.rb +348 -0
- data/lib/cloudtrapper/rack.rb +55 -0
- data/lib/cloudtrapper/rails/action_controller_catcher.rb +30 -0
- data/lib/cloudtrapper/rails/controller_methods.rb +74 -0
- data/lib/cloudtrapper/rails/error_lookup.rb +33 -0
- data/lib/cloudtrapper/rails/javascript_notifier.rb +48 -0
- data/lib/cloudtrapper/rails/middleware/exceptions_catcher.rb +29 -0
- data/lib/cloudtrapper/rails.rb +40 -0
- data/lib/cloudtrapper/rails3_tasks.rb +85 -0
- data/lib/cloudtrapper/railtie.rb +48 -0
- data/lib/cloudtrapper/rake_handler.rb +66 -0
- data/lib/cloudtrapper/sender.rb +116 -0
- data/lib/cloudtrapper/shared_tasks.rb +36 -0
- data/lib/cloudtrapper/tasks.rb +83 -0
- data/lib/cloudtrapper/user_informer.rb +27 -0
- data/lib/cloudtrapper/version.rb +3 -0
- data/lib/cloudtrapper.rb +155 -0
- data/lib/cloudtrapper_tasks.rb +65 -0
- data/lib/rails/generators/cloudtrapper/cloudtrapper_generator.rb +100 -0
- data/lib/templates/javascript_notifier.erb +15 -0
- data/lib/templates/rescue.erb +91 -0
- data/rails/init.rb +1 -0
- data/resources/README.md +34 -0
- data/resources/ca-bundle.crt +3376 -0
- data/script/integration_test.rb +38 -0
- data/test/backtrace_test.rb +162 -0
- data/test/capistrano_test.rb +34 -0
- data/test/catcher_test.rb +333 -0
- data/test/cloudtrapper_2_2.xsd +78 -0
- data/test/cloudtrapper_tasks_test.rb +170 -0
- data/test/configuration_test.rb +221 -0
- data/test/helper.rb +263 -0
- data/test/javascript_notifier_test.rb +52 -0
- data/test/logger_test.rb +73 -0
- data/test/notice_test.rb +468 -0
- data/test/notifier_test.rb +246 -0
- data/test/rack_test.rb +58 -0
- data/test/rails_initializer_test.rb +36 -0
- data/test/recursion_test.rb +10 -0
- data/test/sender_test.rb +261 -0
- data/test/user_informer_test.rb +29 -0
- metadata +301 -0
@@ -0,0 +1,170 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper'
|
2
|
+
require 'rubygems'
|
3
|
+
|
4
|
+
require File.dirname(__FILE__) + '/../lib/cloudtrapper_tasks'
|
5
|
+
require 'fakeweb'
|
6
|
+
|
7
|
+
FakeWeb.allow_net_connect = false
|
8
|
+
|
9
|
+
class CloudtrapperTasksTest < Test::Unit::TestCase
|
10
|
+
def successful_response(body = "")
|
11
|
+
response = Net::HTTPSuccess.new('1.2', '200', 'OK')
|
12
|
+
response.stubs(:body).returns(body)
|
13
|
+
return response
|
14
|
+
end
|
15
|
+
|
16
|
+
def unsuccessful_response(body = "")
|
17
|
+
response = Net::HTTPClientError.new('1.2', '200', 'OK')
|
18
|
+
response.stubs(:body).returns(body)
|
19
|
+
return response
|
20
|
+
end
|
21
|
+
|
22
|
+
context "being quiet" do
|
23
|
+
setup { CloudtrapperTasks.stubs(:puts) }
|
24
|
+
|
25
|
+
context "in a configured project" do
|
26
|
+
setup { Cloudtrapper.configure { |config| config.api_key = "1234123412341234" } }
|
27
|
+
|
28
|
+
context "on deploy({})" do
|
29
|
+
setup { @output = CloudtrapperTasks.deploy({}) }
|
30
|
+
|
31
|
+
before_should "complain about missing rails env" do
|
32
|
+
CloudtrapperTasks.expects(:puts).with(regexp_matches(/rails environment/i))
|
33
|
+
end
|
34
|
+
|
35
|
+
should "return false" do
|
36
|
+
assert !@output
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "given an optional HTTP proxy and valid options" do
|
41
|
+
setup do
|
42
|
+
@response = stub("response", :body => "stub body")
|
43
|
+
@http_proxy = stub("proxy", :request => @response)
|
44
|
+
@http_proxy_class = stub("proxy_class", :new => @http_proxy)
|
45
|
+
@post = stub("post", :set_form_data => nil)
|
46
|
+
|
47
|
+
Net::HTTP.expects(:Proxy).
|
48
|
+
with(Cloudtrapper.configuration.proxy_host,
|
49
|
+
Cloudtrapper.configuration.proxy_port,
|
50
|
+
Cloudtrapper.configuration.proxy_user,
|
51
|
+
Cloudtrapper.configuration.proxy_pass).
|
52
|
+
returns(@http_proxy_class)
|
53
|
+
Net::HTTP::Post.expects(:new).with("/deploys.txt").returns(@post)
|
54
|
+
|
55
|
+
@options = { :rails_env => "staging", :dry_run => false }
|
56
|
+
end
|
57
|
+
|
58
|
+
context "performing a dry run" do
|
59
|
+
setup { @output = CloudtrapperTasks.deploy(@options.merge(:dry_run => true)) }
|
60
|
+
|
61
|
+
should "return true without performing any actual request" do
|
62
|
+
assert_equal true, @output
|
63
|
+
assert_received(@http_proxy, :request) do |expects|
|
64
|
+
expects.never
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context "on deploy(options)" do
|
70
|
+
setup do
|
71
|
+
@output = CloudtrapperTasks.deploy(@options)
|
72
|
+
end
|
73
|
+
|
74
|
+
before_should "post to http://api.cloudtrapper.io:80/deploys.txt" do
|
75
|
+
@http_proxy_class.expects(:new).with("api.cloudtrapper.io", 80).returns(@http_proxy)
|
76
|
+
@post.expects(:set_form_data).with(kind_of(Hash))
|
77
|
+
@http_proxy.expects(:request).with(any_parameters).returns(successful_response)
|
78
|
+
end
|
79
|
+
|
80
|
+
before_should "use the project api key" do
|
81
|
+
@post.expects(:set_form_data).
|
82
|
+
with(has_entries('api_key' => "1234123412341234"))
|
83
|
+
end
|
84
|
+
|
85
|
+
before_should "use send the rails_env param" do
|
86
|
+
@post.expects(:set_form_data).
|
87
|
+
with(has_entries("deploy[rails_env]" => "staging"))
|
88
|
+
end
|
89
|
+
|
90
|
+
[:local_username, :scm_repository, :scm_revision].each do |key|
|
91
|
+
before_should "use send the #{key} param if it's passed in." do
|
92
|
+
@options[key] = "value"
|
93
|
+
@post.expects(:set_form_data).
|
94
|
+
with(has_entries("deploy[#{key}]" => "value"))
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
before_should "use the :api_key param if it's passed in." do
|
99
|
+
@options[:api_key] = "value"
|
100
|
+
@post.expects(:set_form_data).
|
101
|
+
with(has_entries("api_key" => "value"))
|
102
|
+
end
|
103
|
+
|
104
|
+
before_should "puts the response body on success" do
|
105
|
+
CloudtrapperTasks.expects(:puts).with("body")
|
106
|
+
@http_proxy.expects(:request).with(any_parameters).returns(successful_response('body'))
|
107
|
+
end
|
108
|
+
|
109
|
+
before_should "puts the response body on failure" do
|
110
|
+
CloudtrapperTasks.expects(:puts).with("body")
|
111
|
+
@http_proxy.expects(:request).with(any_parameters).returns(unsuccessful_response('body'))
|
112
|
+
end
|
113
|
+
|
114
|
+
should "return false on failure", :before => lambda {
|
115
|
+
@http_proxy.expects(:request).with(any_parameters).returns(unsuccessful_response('body'))
|
116
|
+
} do
|
117
|
+
assert !@output
|
118
|
+
end
|
119
|
+
|
120
|
+
should "return true on success", :before => lambda {
|
121
|
+
@http_proxy.expects(:request).with(any_parameters).returns(successful_response('body'))
|
122
|
+
} do
|
123
|
+
assert @output
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context "in a configured project with custom host" do
|
130
|
+
setup do
|
131
|
+
Cloudtrapper.configure do |config|
|
132
|
+
config.api_key = "1234123412341234"
|
133
|
+
config.host = "custom.host"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
context "on deploy(:rails_env => 'staging')" do
|
138
|
+
setup { @output = CloudtrapperTasks.deploy(:rails_env => "staging") }
|
139
|
+
|
140
|
+
before_should "post to the custom host" do
|
141
|
+
@post = stub("post", :set_form_data => nil)
|
142
|
+
@http_proxy = stub("proxy", :request => @response)
|
143
|
+
|
144
|
+
@http_proxy_class = stub("proxy_class", :new => @http_proxy)
|
145
|
+
@http_proxy_class.expects(:new).with("custom.host", 80).returns(@http_proxy)
|
146
|
+
Net::HTTP.expects(:Proxy).with(any_parameters).returns(@http_proxy_class)
|
147
|
+
Net::HTTP::Post.expects(:new).with("/deploys.txt").returns(@post)
|
148
|
+
@post.expects(:set_form_data).with(kind_of(Hash))
|
149
|
+
@http_proxy.expects(:request).with(any_parameters).returns(successful_response)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
context "when not configured" do
|
155
|
+
setup { Cloudtrapper.configure { |config| config.api_key = "" } }
|
156
|
+
|
157
|
+
context "on deploy(:rails_env => 'staging')" do
|
158
|
+
setup { @output = CloudtrapperTasks.deploy(:rails_env => "staging") }
|
159
|
+
|
160
|
+
before_should "complain about missing api key" do
|
161
|
+
CloudtrapperTasks.expects(:puts).with(regexp_matches(/api key/i))
|
162
|
+
end
|
163
|
+
|
164
|
+
should "return false" do
|
165
|
+
assert !@output
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,221 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper'
|
2
|
+
|
3
|
+
class ConfigurationTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
include DefinesConstants
|
6
|
+
|
7
|
+
should "provide default values" do
|
8
|
+
assert_config_default :proxy_host, nil
|
9
|
+
assert_config_default :proxy_port, nil
|
10
|
+
assert_config_default :proxy_user, nil
|
11
|
+
assert_config_default :proxy_pass, nil
|
12
|
+
assert_config_default :project_root, nil
|
13
|
+
assert_config_default :environment_name, nil
|
14
|
+
assert_config_default :logger, nil
|
15
|
+
assert_config_default :notifier_version, Cloudtrapper::VERSION
|
16
|
+
assert_config_default :notifier_name, 'Cloudtrapper Notifier'
|
17
|
+
assert_config_default :notifier_url, 'https://github.com/cloudtrapper/cloudtrapper'
|
18
|
+
assert_config_default :secure, false
|
19
|
+
assert_config_default :host, 'api.cloudtrapper.io'
|
20
|
+
assert_config_default :http_open_timeout, 2
|
21
|
+
assert_config_default :http_read_timeout, 5
|
22
|
+
assert_config_default :ignore_by_filters, []
|
23
|
+
assert_config_default :ignore_user_agent, []
|
24
|
+
assert_config_default :params_filters,
|
25
|
+
Cloudtrapper::Configuration::DEFAULT_PARAMS_FILTERS
|
26
|
+
assert_config_default :backtrace_filters,
|
27
|
+
Cloudtrapper::Configuration::DEFAULT_BACKTRACE_FILTERS
|
28
|
+
assert_config_default :ignore,
|
29
|
+
Cloudtrapper::Configuration::IGNORE_DEFAULT
|
30
|
+
assert_config_default :development_lookup, true
|
31
|
+
assert_config_default :framework, 'Standalone'
|
32
|
+
end
|
33
|
+
|
34
|
+
should "provide default values for secure connections" do
|
35
|
+
config = Cloudtrapper::Configuration.new
|
36
|
+
config.secure = true
|
37
|
+
assert_equal 443, config.port
|
38
|
+
assert_equal 'https', config.protocol
|
39
|
+
end
|
40
|
+
|
41
|
+
should "provide default values for insecure connections" do
|
42
|
+
config = Cloudtrapper::Configuration.new
|
43
|
+
config.secure = false
|
44
|
+
assert_equal 80, config.port
|
45
|
+
assert_equal 'http', config.protocol
|
46
|
+
end
|
47
|
+
|
48
|
+
should "not cache inferred ports" do
|
49
|
+
config = Cloudtrapper::Configuration.new
|
50
|
+
config.secure = false
|
51
|
+
config.port
|
52
|
+
config.secure = true
|
53
|
+
assert_equal 443, config.port
|
54
|
+
end
|
55
|
+
|
56
|
+
should "allow values to be overwritten" do
|
57
|
+
assert_config_overridable :proxy_host
|
58
|
+
assert_config_overridable :proxy_port
|
59
|
+
assert_config_overridable :proxy_user
|
60
|
+
assert_config_overridable :proxy_pass
|
61
|
+
assert_config_overridable :secure
|
62
|
+
assert_config_overridable :host
|
63
|
+
assert_config_overridable :port
|
64
|
+
assert_config_overridable :http_open_timeout
|
65
|
+
assert_config_overridable :http_read_timeout
|
66
|
+
assert_config_overridable :project_root
|
67
|
+
assert_config_overridable :notifier_version
|
68
|
+
assert_config_overridable :notifier_name
|
69
|
+
assert_config_overridable :notifier_url
|
70
|
+
assert_config_overridable :environment_name
|
71
|
+
assert_config_overridable :development_lookup
|
72
|
+
assert_config_overridable :logger
|
73
|
+
end
|
74
|
+
|
75
|
+
should "have an api key" do
|
76
|
+
assert_config_overridable :api_key
|
77
|
+
end
|
78
|
+
|
79
|
+
should "act like a hash" do
|
80
|
+
config = Cloudtrapper::Configuration.new
|
81
|
+
hash = config.to_hash
|
82
|
+
[:api_key, :backtrace_filters, :development_environments,
|
83
|
+
:environment_name, :host, :http_open_timeout,
|
84
|
+
:http_read_timeout, :ignore, :ignore_by_filters, :ignore_user_agent,
|
85
|
+
:notifier_name, :notifier_url, :notifier_version, :params_filters,
|
86
|
+
:project_root, :port, :protocol, :proxy_host, :proxy_pass, :proxy_port,
|
87
|
+
:proxy_user, :secure, :development_lookup].each do |option|
|
88
|
+
assert_equal config[option], hash[option], "Wrong value for #{option}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
should "be mergable" do
|
93
|
+
config = Cloudtrapper::Configuration.new
|
94
|
+
hash = config.to_hash
|
95
|
+
assert_equal hash.merge(:key => 'value'), config.merge(:key => 'value')
|
96
|
+
end
|
97
|
+
|
98
|
+
should "allow param filters to be appended" do
|
99
|
+
assert_appends_value :params_filters
|
100
|
+
end
|
101
|
+
|
102
|
+
should "warn when attempting to read environment filters" do
|
103
|
+
config = Cloudtrapper::Configuration.new
|
104
|
+
config.
|
105
|
+
expects(:warn).
|
106
|
+
with(regexp_matches(/deprecated/i))
|
107
|
+
assert_equal [], config.environment_filters
|
108
|
+
end
|
109
|
+
|
110
|
+
should "warn when attempting to write js_notifier" do
|
111
|
+
config = Cloudtrapper::Configuration.new
|
112
|
+
config.
|
113
|
+
expects(:warn).
|
114
|
+
with(regexp_matches(/deprecated/i))
|
115
|
+
config.js_notifier = true
|
116
|
+
end
|
117
|
+
|
118
|
+
should "allow ignored user agents to be appended" do
|
119
|
+
assert_appends_value :ignore_user_agent
|
120
|
+
end
|
121
|
+
|
122
|
+
should "allow backtrace filters to be appended" do
|
123
|
+
assert_appends_value(:backtrace_filters) do |config|
|
124
|
+
new_filter = lambda {}
|
125
|
+
config.filter_backtrace(&new_filter)
|
126
|
+
new_filter
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
should "allow ignore by filters to be appended" do
|
131
|
+
assert_appends_value(:ignore_by_filters) do |config|
|
132
|
+
new_filter = lambda {}
|
133
|
+
config.ignore_by_filter(&new_filter)
|
134
|
+
new_filter
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
should "allow ignored exceptions to be appended" do
|
139
|
+
config = Cloudtrapper::Configuration.new
|
140
|
+
original_filters = config.ignore.dup
|
141
|
+
new_filter = 'hello'
|
142
|
+
config.ignore << new_filter
|
143
|
+
assert_same_elements original_filters + [new_filter], config.ignore
|
144
|
+
end
|
145
|
+
|
146
|
+
should "allow ignored exceptions to be replaced" do
|
147
|
+
assert_replaces(:ignore, :ignore_only=)
|
148
|
+
end
|
149
|
+
|
150
|
+
should "allow ignored user agents to be replaced" do
|
151
|
+
assert_replaces(:ignore_user_agent, :ignore_user_agent_only=)
|
152
|
+
end
|
153
|
+
|
154
|
+
should "use development and test as development environments by default" do
|
155
|
+
config = Cloudtrapper::Configuration.new
|
156
|
+
assert_same_elements %w(development test cucumber), config.development_environments
|
157
|
+
end
|
158
|
+
|
159
|
+
should "be public in a public environment" do
|
160
|
+
config = Cloudtrapper::Configuration.new
|
161
|
+
config.development_environments = %w(development)
|
162
|
+
config.environment_name = 'production'
|
163
|
+
assert config.public?
|
164
|
+
end
|
165
|
+
|
166
|
+
should "not be public in a development environment" do
|
167
|
+
config = Cloudtrapper::Configuration.new
|
168
|
+
config.development_environments = %w(staging)
|
169
|
+
config.environment_name = 'staging'
|
170
|
+
assert !config.public?
|
171
|
+
end
|
172
|
+
|
173
|
+
should "be public without an environment name" do
|
174
|
+
config = Cloudtrapper::Configuration.new
|
175
|
+
assert config.public?
|
176
|
+
end
|
177
|
+
|
178
|
+
should "use the assigned logger if set" do
|
179
|
+
config = Cloudtrapper::Configuration.new
|
180
|
+
config.logger = "CUSTOM LOGGER"
|
181
|
+
assert_equal "CUSTOM LOGGER", config.logger
|
182
|
+
end
|
183
|
+
|
184
|
+
should 'give a new instance if non defined' do
|
185
|
+
Cloudtrapper.configuration = nil
|
186
|
+
assert_kind_of Cloudtrapper::Configuration, Cloudtrapper.configuration
|
187
|
+
end
|
188
|
+
|
189
|
+
def assert_config_default(option, default_value, config = nil)
|
190
|
+
config ||= Cloudtrapper::Configuration.new
|
191
|
+
assert_equal default_value, config.send(option)
|
192
|
+
end
|
193
|
+
|
194
|
+
def assert_config_overridable(option, value = 'a value')
|
195
|
+
config = Cloudtrapper::Configuration.new
|
196
|
+
config.send(:"#{option}=", value)
|
197
|
+
assert_equal value, config.send(option)
|
198
|
+
end
|
199
|
+
|
200
|
+
def assert_appends_value(option, &block)
|
201
|
+
config = Cloudtrapper::Configuration.new
|
202
|
+
original_values = config.send(option).dup
|
203
|
+
block ||= lambda do |config|
|
204
|
+
new_value = 'hello'
|
205
|
+
config.send(option) << new_value
|
206
|
+
new_value
|
207
|
+
end
|
208
|
+
new_value = block.call(config)
|
209
|
+
assert_same_elements original_values + [new_value], config.send(option)
|
210
|
+
end
|
211
|
+
|
212
|
+
def assert_replaces(option, setter)
|
213
|
+
config = Cloudtrapper::Configuration.new
|
214
|
+
new_value = 'hello'
|
215
|
+
config.send(setter, [new_value])
|
216
|
+
assert_equal [new_value], config.send(option)
|
217
|
+
config.send(setter, new_value)
|
218
|
+
assert_equal [new_value], config.send(option)
|
219
|
+
end
|
220
|
+
|
221
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,263 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start
|
3
|
+
require 'test/unit'
|
4
|
+
require 'rubygems'
|
5
|
+
|
6
|
+
$LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
|
7
|
+
|
8
|
+
require 'thread'
|
9
|
+
|
10
|
+
require "bundler/setup"
|
11
|
+
|
12
|
+
require 'shoulda'
|
13
|
+
require 'mocha'
|
14
|
+
|
15
|
+
require 'action_controller'
|
16
|
+
require 'action_controller/test_process'
|
17
|
+
require 'active_record'
|
18
|
+
require 'active_support'
|
19
|
+
require 'nokogiri'
|
20
|
+
require 'rack'
|
21
|
+
require 'bourne'
|
22
|
+
require 'sham_rack'
|
23
|
+
|
24
|
+
require "cloudtrapper"
|
25
|
+
|
26
|
+
begin require 'redgreen'; rescue LoadError; end
|
27
|
+
|
28
|
+
module TestMethods
|
29
|
+
def rescue_action e
|
30
|
+
raise e
|
31
|
+
end
|
32
|
+
|
33
|
+
def do_raise
|
34
|
+
raise "Cloudtrapper"
|
35
|
+
end
|
36
|
+
|
37
|
+
def do_not_raise
|
38
|
+
render :text => "Success"
|
39
|
+
end
|
40
|
+
|
41
|
+
def do_raise_ignored
|
42
|
+
raise ActiveRecord::RecordNotFound.new("404")
|
43
|
+
end
|
44
|
+
|
45
|
+
def do_raise_not_ignored
|
46
|
+
raise ActiveRecord::StatementInvalid.new("Statement invalid")
|
47
|
+
end
|
48
|
+
|
49
|
+
def manual_notify
|
50
|
+
notify_cloudtrapper(Exception.new)
|
51
|
+
render :text => "Success"
|
52
|
+
end
|
53
|
+
|
54
|
+
def manual_notify_ignored
|
55
|
+
notify_cloudtrapper(ActiveRecord::RecordNotFound.new("404"))
|
56
|
+
render :text => "Success"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class Test::Unit::TestCase
|
61
|
+
def request(action = nil, method = :get, user_agent = nil, params = {})
|
62
|
+
@request = ActionController::TestRequest.new
|
63
|
+
@request.action = action ? action.to_s : ""
|
64
|
+
|
65
|
+
if user_agent
|
66
|
+
if @request.respond_to?(:user_agent=)
|
67
|
+
@request.user_agent = user_agent
|
68
|
+
else
|
69
|
+
@request.env["HTTP_USER_AGENT"] = user_agent
|
70
|
+
end
|
71
|
+
end
|
72
|
+
@request.query_parameters = @request.query_parameters.merge(params)
|
73
|
+
@response = ActionController::TestResponse.new
|
74
|
+
@controller.process(@request, @response)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Borrowed from ActiveSupport 2.3.2
|
78
|
+
def assert_difference(expression, difference = 1, message = nil, &block)
|
79
|
+
b = block.send(:binding)
|
80
|
+
exps = Array.wrap(expression)
|
81
|
+
before = exps.map { |e| eval(e, b) }
|
82
|
+
|
83
|
+
yield
|
84
|
+
|
85
|
+
exps.each_with_index do |e, i|
|
86
|
+
error = "#{e.inspect} didn't change by #{difference}"
|
87
|
+
error = "#{message}.\n#{error}" if message
|
88
|
+
assert_equal(before[i] + difference, eval(e, b), error)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def assert_no_difference(expression, message = nil, &block)
|
93
|
+
assert_difference expression, 0, message, &block
|
94
|
+
end
|
95
|
+
|
96
|
+
def stub_sender
|
97
|
+
stub('sender', :send_to_cloudtrapper => nil)
|
98
|
+
end
|
99
|
+
|
100
|
+
def stub_sender!
|
101
|
+
Cloudtrapper.sender = stub_sender
|
102
|
+
end
|
103
|
+
|
104
|
+
def stub_notice
|
105
|
+
stub('notice', :to_xml => 'some yaml', :ignore? => false)
|
106
|
+
end
|
107
|
+
|
108
|
+
def stub_notice!
|
109
|
+
stub_notice.tap do |notice|
|
110
|
+
Cloudtrapper::Notice.stubs(:new => notice)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def create_dummy
|
115
|
+
Cloudtrapper::DummySender.new
|
116
|
+
end
|
117
|
+
|
118
|
+
def reset_config
|
119
|
+
Cloudtrapper.configuration = nil
|
120
|
+
Cloudtrapper.configure do |config|
|
121
|
+
config.api_key = 'abc123'
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def clear_backtrace_filters
|
126
|
+
Cloudtrapper.configuration.backtrace_filters.clear
|
127
|
+
end
|
128
|
+
|
129
|
+
def build_exception(opts = {})
|
130
|
+
backtrace = ["cloudtrapper/test/helper.rb:132:in `build_exception'",
|
131
|
+
"cloudtrapper/test/backtrace.rb:4:in `build_notice_data'",
|
132
|
+
"/var/lib/gems/1.8/gems/cloudtrapper-2.4.5/rails/init.rb:2:in `send_exception'"]
|
133
|
+
opts = {:backtrace => backtrace}.merge(opts)
|
134
|
+
BacktracedException.new(opts)
|
135
|
+
end
|
136
|
+
|
137
|
+
class BacktracedException < Exception
|
138
|
+
attr_accessor :backtrace
|
139
|
+
def initialize(opts)
|
140
|
+
@backtrace = opts[:backtrace]
|
141
|
+
end
|
142
|
+
def set_backtrace(bt)
|
143
|
+
@backtrace = bt
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def build_notice_data(exception = nil)
|
148
|
+
exception ||= build_exception
|
149
|
+
{
|
150
|
+
:api_key => 'abc123',
|
151
|
+
:error_class => exception.class.name,
|
152
|
+
:error_message => "#{exception.class.name}: #{exception.message}",
|
153
|
+
:backtrace => exception.backtrace,
|
154
|
+
:environment => { 'PATH' => '/bin', 'REQUEST_URI' => '/users/1' },
|
155
|
+
:request => {
|
156
|
+
:params => { 'controller' => 'users', 'action' => 'show', 'id' => '1' },
|
157
|
+
:rails_root => '/path/to/application',
|
158
|
+
:url => "http://test.host/users/1"
|
159
|
+
},
|
160
|
+
:session => {
|
161
|
+
:key => '123abc',
|
162
|
+
:data => { 'user_id' => '5', 'flash' => { 'notice' => 'Logged in successfully' } }
|
163
|
+
}
|
164
|
+
}
|
165
|
+
end
|
166
|
+
|
167
|
+
def assert_caught_and_sent
|
168
|
+
assert !Cloudtrapper.sender.collected.empty?
|
169
|
+
end
|
170
|
+
|
171
|
+
def assert_caught_and_not_sent
|
172
|
+
assert Cloudtrapper.sender.collected.empty?
|
173
|
+
end
|
174
|
+
|
175
|
+
def assert_array_starts_with(expected, actual)
|
176
|
+
assert_respond_to actual, :to_ary
|
177
|
+
array = actual.to_ary.reverse
|
178
|
+
expected.reverse.each_with_index do |value, i|
|
179
|
+
assert_equal value, array[i]
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def assert_valid_node(document, xpath, content)
|
184
|
+
nodes = document.xpath(xpath)
|
185
|
+
assert nodes.any?{|node| node.content == content },
|
186
|
+
"Expected xpath #{xpath} to have content #{content}, " +
|
187
|
+
"but found #{nodes.map { |n| n.content }} in #{nodes.size} matching nodes." +
|
188
|
+
"Document:\n#{document.to_s}"
|
189
|
+
end
|
190
|
+
|
191
|
+
def assert_logged(expected)
|
192
|
+
assert_received(Cloudtrapper, :write_verbose_log) do |expect|
|
193
|
+
expect.with {|actual| actual =~ expected }
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def assert_not_logged(expected)
|
198
|
+
assert_received(Cloudtrapper, :write_verbose_log) do |expect|
|
199
|
+
expect.with {|actual| actual =~ expected }.never
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
|
204
|
+
end
|
205
|
+
|
206
|
+
module DefinesConstants
|
207
|
+
def setup
|
208
|
+
@defined_constants = []
|
209
|
+
end
|
210
|
+
|
211
|
+
def teardown
|
212
|
+
@defined_constants.each do |constant|
|
213
|
+
Object.__send__(:remove_const, constant)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def define_constant(name, value)
|
218
|
+
Object.const_set(name, value)
|
219
|
+
@defined_constants << name
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
# Also stolen from AS 2.3.2
|
224
|
+
class Array
|
225
|
+
# Wraps the object in an Array unless it's an Array. Converts the
|
226
|
+
# object to an Array using #to_ary if it implements that.
|
227
|
+
def self.wrap(object)
|
228
|
+
case object
|
229
|
+
when nil
|
230
|
+
[]
|
231
|
+
when self
|
232
|
+
object
|
233
|
+
else
|
234
|
+
if object.respond_to?(:to_ary)
|
235
|
+
object.to_ary
|
236
|
+
else
|
237
|
+
[object]
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
end
|
243
|
+
|
244
|
+
class CollectingSender
|
245
|
+
attr_reader :collected
|
246
|
+
|
247
|
+
def initialize
|
248
|
+
@collected = []
|
249
|
+
end
|
250
|
+
|
251
|
+
def send_to_cloudtrapper(data)
|
252
|
+
@collected << data
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
class FakeLogger
|
257
|
+
def info(*args); end
|
258
|
+
def debug(*args); end
|
259
|
+
def warn(*args); end
|
260
|
+
def error(*args); end
|
261
|
+
def fatal(*args); end
|
262
|
+
end
|
263
|
+
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper'
|
2
|
+
require 'cloudtrapper/rails/javascript_notifier'
|
3
|
+
require 'ostruct'
|
4
|
+
|
5
|
+
class JavascriptNotifierTest < Test::Unit::TestCase
|
6
|
+
module FakeRenderer
|
7
|
+
def javascript_tag(text)
|
8
|
+
"<script>#{text}</script>"
|
9
|
+
end
|
10
|
+
def escape_javascript(text)
|
11
|
+
"ESC#{text}ESC"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class FakeController
|
16
|
+
def self.helper_method(*args)
|
17
|
+
end
|
18
|
+
|
19
|
+
include Cloudtrapper::Rails::JavascriptNotifier
|
20
|
+
|
21
|
+
def action_name
|
22
|
+
"action"
|
23
|
+
end
|
24
|
+
|
25
|
+
def controller_name
|
26
|
+
"controller"
|
27
|
+
end
|
28
|
+
|
29
|
+
def request
|
30
|
+
@request ||= OpenStruct.new
|
31
|
+
end
|
32
|
+
|
33
|
+
def render_to_string(options)
|
34
|
+
context = OpenStruct.new(options[:locals])
|
35
|
+
context.extend(FakeRenderer)
|
36
|
+
context.instance_eval do
|
37
|
+
erb = ERB.new(IO.read(options[:file]))
|
38
|
+
erb.result(binding)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
should "make sure escape_javacript is called on the request.url" do
|
44
|
+
Cloudtrapper.configure do
|
45
|
+
end
|
46
|
+
controller = FakeController.new
|
47
|
+
controller.request.url = "bad_javascript"
|
48
|
+
assert controller.send(:cloudtrapper_javascript_notifier)['"ESCbad_javascriptESC"']
|
49
|
+
assert ! controller.send(:cloudtrapper_javascript_notifier)['"bad_javascript"']
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|