airbrake 4.3.8 → 5.0.0
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.
- checksums.yaml +4 -4
- data/lib/airbrake/capistrano/tasks.rb +64 -0
- data/lib/airbrake/delayed_job/plugin.rb +48 -0
- data/lib/airbrake/rack/middleware.rb +45 -0
- data/lib/airbrake/rack/notice_builder.rb +80 -0
- data/lib/airbrake/rack/user.rb +51 -0
- data/lib/airbrake/rails/action_controller.rb +35 -0
- data/lib/airbrake/rails/active_job.rb +23 -0
- data/lib/airbrake/rails/active_record.rb +40 -0
- data/lib/airbrake/rails/railtie.rb +61 -0
- data/lib/airbrake/rake/task_ext.rb +61 -0
- data/lib/airbrake/rake/tasks.rb +93 -0
- data/lib/airbrake/resque/failure.rb +19 -0
- data/lib/airbrake/sidekiq/error_handler.rb +35 -0
- data/lib/airbrake/version.rb +4 -1
- data/lib/airbrake.rb +16 -185
- data/lib/generators/airbrake_generator.rb +25 -0
- data/lib/generators/airbrake_initializer.rb.erb +55 -0
- data/spec/airbrake_spec.rb +0 -0
- data/spec/apps/rack/dummy_app.rb +17 -0
- data/spec/apps/rails/dummy_app.rb +150 -0
- data/spec/apps/rails/dummy_task.rake +20 -0
- data/spec/apps/rails/logs/32.log +13358 -0
- data/spec/apps/rails/logs/40.log +6854 -0
- data/spec/apps/rails/logs/41.log +3170 -0
- data/spec/apps/rails/logs/42.log +23919 -0
- data/spec/apps/rails/logs/50.log +10976 -0
- data/spec/apps/sinatra/dummy_app.rb +12 -0
- data/spec/integration/rack/rack_spec.rb +17 -0
- data/spec/integration/rails/rails_spec.rb +135 -0
- data/spec/integration/rails/rake_spec.rb +160 -0
- data/spec/integration/shared_examples/rack_examples.rb +106 -0
- data/spec/integration/sinatra/sinatra_spec.rb +15 -0
- data/spec/spec_helper.rb +127 -0
- data/spec/unit/rack/middleware_spec.rb +80 -0
- data/spec/unit/rack/notice_builder_spec.rb +35 -0
- data/spec/unit/rack/user_spec.rb +78 -0
- data/spec/unit/rake/tasks_spec.rb +40 -0
- data/spec/unit/sidekiq/error_handler_spec.rb +29 -0
- metadata +108 -323
- data/CHANGELOG +0 -1716
- data/Gemfile +0 -3
- data/Guardfile +0 -6
- data/INSTALL +0 -20
- data/LICENSE +0 -61
- data/README.md +0 -148
- data/README_FOR_HEROKU_ADDON.md +0 -102
- data/Rakefile +0 -179
- data/TESTED_AGAINST +0 -7
- data/airbrake.gemspec +0 -41
- data/bin/airbrake +0 -12
- data/features/metal.feature +0 -34
- data/features/rack.feature +0 -60
- data/features/rails.feature +0 -324
- data/features/rake.feature +0 -33
- data/features/sinatra.feature +0 -126
- data/features/step_definitions/file_steps.rb +0 -14
- data/features/step_definitions/rack_steps.rb +0 -27
- data/features/step_definitions/rails_application_steps.rb +0 -267
- data/features/step_definitions/rake_steps.rb +0 -22
- data/features/support/airbrake_shim.rb.template +0 -11
- data/features/support/aruba.rb +0 -5
- data/features/support/env.rb +0 -39
- data/features/support/matchers.rb +0 -35
- data/features/support/rails.rb +0 -156
- data/features/support/rake/Rakefile +0 -77
- data/features/user_informer.feature +0 -57
- data/generators/airbrake/airbrake_generator.rb +0 -94
- data/generators/airbrake/lib/insert_commands.rb +0 -34
- data/generators/airbrake/lib/rake_commands.rb +0 -24
- data/generators/airbrake/templates/airbrake_tasks.rake +0 -25
- data/generators/airbrake/templates/capistrano_hook.rb +0 -6
- data/generators/airbrake/templates/initializer.rb +0 -4
- data/install.rb +0 -1
- data/lib/airbrake/backtrace.rb +0 -103
- data/lib/airbrake/capistrano.rb +0 -103
- data/lib/airbrake/capistrano3.rb +0 -3
- data/lib/airbrake/cli/client.rb +0 -76
- data/lib/airbrake/cli/options.rb +0 -45
- data/lib/airbrake/cli/printer.rb +0 -33
- data/lib/airbrake/cli/project.rb +0 -17
- data/lib/airbrake/cli/project_factory.rb +0 -33
- data/lib/airbrake/cli/runner.rb +0 -49
- data/lib/airbrake/cli/validator.rb +0 -8
- data/lib/airbrake/configuration.rb +0 -366
- data/lib/airbrake/jobs/send_job.rb +0 -7
- data/lib/airbrake/notice.rb +0 -411
- data/lib/airbrake/rack.rb +0 -64
- data/lib/airbrake/rails/action_controller_catcher.rb +0 -32
- data/lib/airbrake/rails/controller_methods.rb +0 -146
- data/lib/airbrake/rails/error_lookup.rb +0 -35
- data/lib/airbrake/rails/middleware.rb +0 -63
- data/lib/airbrake/rails.rb +0 -45
- data/lib/airbrake/rails3_tasks.rb +0 -126
- data/lib/airbrake/railtie.rb +0 -46
- data/lib/airbrake/rake_handler.rb +0 -75
- data/lib/airbrake/response.rb +0 -29
- data/lib/airbrake/sender.rb +0 -213
- data/lib/airbrake/shared_tasks.rb +0 -59
- data/lib/airbrake/sidekiq.rb +0 -8
- data/lib/airbrake/sinatra.rb +0 -40
- data/lib/airbrake/tasks/airbrake.cap +0 -28
- data/lib/airbrake/tasks.rb +0 -81
- data/lib/airbrake/user_informer.rb +0 -36
- data/lib/airbrake/utils/params_cleaner.rb +0 -141
- data/lib/airbrake/utils/rack_filters.rb +0 -45
- data/lib/airbrake_tasks.rb +0 -62
- data/lib/rails/generators/airbrake/airbrake_generator.rb +0 -155
- data/lib/templates/rescue.erb +0 -91
- data/rails/init.rb +0 -1
- data/resources/README.md +0 -34
- data/resources/airbrake_2_4.xsd +0 -89
- data/resources/airbrake_3_0.json +0 -52
- data/resources/ca-bundle.crt +0 -3376
- data/script/integration_test.rb +0 -35
- data/test/airbrake_tasks_test.rb +0 -161
- data/test/backtrace_test.rb +0 -215
- data/test/capistrano_test.rb +0 -44
- data/test/configuration_test.rb +0 -303
- data/test/controller_methods_test.rb +0 -230
- data/test/helper.rb +0 -233
- data/test/integration/catcher_test.rb +0 -371
- data/test/integration.rb +0 -13
- data/test/logger_test.rb +0 -79
- data/test/notice_test.rb +0 -494
- data/test/notifier_test.rb +0 -288
- data/test/params_cleaner_test.rb +0 -204
- data/test/rack_test.rb +0 -62
- data/test/rails_initializer_test.rb +0 -36
- data/test/recursion_test.rb +0 -10
- data/test/response_test.rb +0 -18
- data/test/sender_test.rb +0 -335
- data/test/support/response_shim.xml +0 -4
- data/test/user_informer_test.rb +0 -29
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'integration/shared_examples/rack_examples'
|
3
|
+
|
4
|
+
RSpec.describe "Rack integration specs" do
|
5
|
+
let(:app) { DummyApp }
|
6
|
+
|
7
|
+
include_examples 'rack examples'
|
8
|
+
|
9
|
+
describe "context payload" do
|
10
|
+
it "includes version" do
|
11
|
+
get '/crash'
|
12
|
+
wait_for_a_request_with_body(
|
13
|
+
/"context":{.*"version":"1.2.3 Rack\.version.+Rack\.release/
|
14
|
+
)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'integration/shared_examples/rack_examples'
|
3
|
+
|
4
|
+
RSpec.describe "Rails integration specs" do
|
5
|
+
include Warden::Test::Helpers
|
6
|
+
|
7
|
+
let(:app) { Rails.application }
|
8
|
+
|
9
|
+
include_examples 'rack examples'
|
10
|
+
|
11
|
+
it "inserts the Airbrake Rack middleware after DebugExceptions" do
|
12
|
+
middlewares = Rails.configuration.middleware.middlewares.map(&:inspect)
|
13
|
+
own_idx = middlewares.index('Airbrake::Rack::Middleware')
|
14
|
+
|
15
|
+
expect(middlewares[own_idx - 1]).to eq('ActionDispatch::DebugExceptions')
|
16
|
+
end
|
17
|
+
|
18
|
+
shared_examples 'context payload content' do |route|
|
19
|
+
before do
|
20
|
+
login_as(OpenStruct.new(id: 1, email: 'qa@example.com', username: 'qa-dept'))
|
21
|
+
get(route, foo: :bar)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "includes component information" do
|
25
|
+
wait_for_a_request_with_body(/"context":{.*"component":"dummy".*}/)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "includes action information" do
|
29
|
+
case route
|
30
|
+
when '/crash'
|
31
|
+
wait_for_a_request_with_body(/"context":{.*"action":"crash".*}/)
|
32
|
+
when '/notify_airbrake_helper'
|
33
|
+
wait_for_a_request_with_body(
|
34
|
+
/"context":{.*"action":"notify_airbrake_helper".*}/
|
35
|
+
)
|
36
|
+
when '/notify_airbrake_sync_helper'
|
37
|
+
wait_for_a_request_with_body(
|
38
|
+
/"context":{.*"action":"notify_airbrake_sync_helper".*}/
|
39
|
+
)
|
40
|
+
else
|
41
|
+
raise 'Unknown route'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
it "includes version" do
|
46
|
+
wait_for_a_request_with_body(/"context":{.*"version":"1.2.3 Rails/)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "includes session" do
|
50
|
+
wait_for_a_request_with_body(
|
51
|
+
/"context":{.*"session":{.*"session_id":"\w+".*}/
|
52
|
+
)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "includes params" do
|
56
|
+
action = route[1..-1]
|
57
|
+
wait_for_a_request_with_body(
|
58
|
+
/"context":{.*"params":{.*"controller":"dummy","action":"#{action}".*}/
|
59
|
+
)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "context payload" do
|
64
|
+
context "when exception reported through middleware" do
|
65
|
+
include_examples('context payload content', '/crash')
|
66
|
+
end
|
67
|
+
|
68
|
+
context "when exception reported through the notify_airbrake helper" do
|
69
|
+
include_examples('context payload content', '/notify_airbrake_helper')
|
70
|
+
end
|
71
|
+
|
72
|
+
context "when exception reported through the notify_airbrake_sync helper" do
|
73
|
+
include_examples('context payload content', '/notify_airbrake_sync_helper')
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "Active Record callbacks" do
|
78
|
+
it "reports exceptions in after_commit callbacks" do
|
79
|
+
get '/active_record_after_commit'
|
80
|
+
wait_for_a_request_with_body(
|
81
|
+
/"type":"AirbrakeTestError","message":"after_commit"/
|
82
|
+
)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "reports exceptions in after_rollback callbacks" do
|
86
|
+
get '/active_record_after_rollback'
|
87
|
+
wait_for_a_request_with_body(
|
88
|
+
/"type":"AirbrakeTestError","message":"after_rollback"/
|
89
|
+
)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
if Gem::Version.new(Rails.version) >= Gem::Version.new('4.2')
|
94
|
+
describe "ActiveJob jobs" do
|
95
|
+
it "reports exceptions occurring in ActiveJob workers" do
|
96
|
+
get '/active_job'
|
97
|
+
sleep 2
|
98
|
+
|
99
|
+
wait_for(
|
100
|
+
a_request(:post, endpoint).
|
101
|
+
with(body: /"message":"active_job error"/)
|
102
|
+
).to have_been_made.twice
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "Resque workers" do
|
108
|
+
it "reports exceptions occurring in Resque workers" do
|
109
|
+
with_resque { get '/resque' }
|
110
|
+
|
111
|
+
wait_for_a_request_with_body(
|
112
|
+
/"message":"resque\serror".*"params":{.*
|
113
|
+
"class":"BingoWorker","args":\["bango","bongo"\].*}/x
|
114
|
+
)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe "DelayedJob jobs" do
|
119
|
+
it "reports exceptions occurring in DelayedJob jobs" do
|
120
|
+
get '/delayed_job'
|
121
|
+
sleep 2
|
122
|
+
|
123
|
+
wait_for_a_request_with_body(
|
124
|
+
%r("message":"delayed_job\serror".*"params":{.*
|
125
|
+
"handler":"---\s!ruby/struct:BangoJob\\nbingo:\s
|
126
|
+
bingo\\nbongo:\sbongo\\n".*})x
|
127
|
+
)
|
128
|
+
|
129
|
+
# Two requests are performed during this example. We care only about one.
|
130
|
+
# Sleep guarantees that we let the unimportant request occur here and not
|
131
|
+
# elsewhere.
|
132
|
+
sleep 2
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe "Rake integration" do
|
4
|
+
let(:endpoint) do
|
5
|
+
'https://airbrake.io/api/v3/projects/113743/notices?key=fd04e13d806a90f96614ad8e529b2822'
|
6
|
+
end
|
7
|
+
|
8
|
+
def wait_for_a_request_with_body(body)
|
9
|
+
wait_for(a_request(:post, endpoint).with(body: body)).to have_been_made.once
|
10
|
+
end
|
11
|
+
|
12
|
+
def expect_no_requests_with_body(body)
|
13
|
+
sleep 1
|
14
|
+
expect(a_request(:post, endpoint).with(body: body)).not_to have_been_made
|
15
|
+
end
|
16
|
+
|
17
|
+
before do
|
18
|
+
Rails.application.load_tasks
|
19
|
+
stub_request(:post, endpoint).to_return(status: 201, body: '{}')
|
20
|
+
expect { faulty_task.invoke }.to raise_error(AirbrakeTestError)
|
21
|
+
end
|
22
|
+
|
23
|
+
after do
|
24
|
+
# Rake ensures that each task is executed only once per session. For testing
|
25
|
+
# purposes, we run the task multiple times.
|
26
|
+
faulty_task.reenable
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "a task with maximum information, which raises an exception" do
|
30
|
+
let(:faulty_task) { Rake::Task['bingo:bango'] }
|
31
|
+
|
32
|
+
it "sends the exception to Airbrake" do
|
33
|
+
wait_for_a_request_with_body(/"errors":\[{"type":"AirbrakeTestError"/)
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "contains the context payload, which" do
|
37
|
+
it "includes correct component" do
|
38
|
+
wait_for_a_request_with_body(/"context":{.*"component":"rake".*}/)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "includes correct action" do
|
42
|
+
wait_for_a_request_with_body(
|
43
|
+
/"context":{.*"action":"bingo:bango".*/
|
44
|
+
)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "contains the params payload, which" do
|
49
|
+
it "includes a task name" do
|
50
|
+
wait_for_a_request_with_body(
|
51
|
+
/"params":{.*"rake_task":{.*"name":"bingo:bango".*}.*}/
|
52
|
+
)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "includes a timestamp" do
|
56
|
+
wait_for_a_request_with_body(
|
57
|
+
/"params":{.*"rake_task":{.*"timestamp":"201\d\-\d\d-\d\d.+".*}.*}/
|
58
|
+
)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "includes investigation" do
|
62
|
+
# rubocop:disable Metrics/LineLength
|
63
|
+
wait_for_a_request_with_body(
|
64
|
+
/"params":{.*"rake_task":{.*"investigation":".+Investigating bingo:bango.+".*}.*}/
|
65
|
+
)
|
66
|
+
# rubocop:enable Metrics/LineLength
|
67
|
+
end
|
68
|
+
|
69
|
+
it "includes full comment" do
|
70
|
+
wait_for_a_request_with_body(
|
71
|
+
/"params":{.*"rake_task":{.*"full_comment":"Dummy description".*}.*}/
|
72
|
+
)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "includes arg names" do
|
76
|
+
wait_for_a_request_with_body(
|
77
|
+
/"params":{.*"rake_task":{.*"arg_names":\["dummy_arg"\].*}.*}/
|
78
|
+
)
|
79
|
+
end
|
80
|
+
|
81
|
+
it "includes arg description" do
|
82
|
+
wait_for_a_request_with_body(
|
83
|
+
/"params":{.*"rake_task":{.*"arg_description":"\[dummy_arg\]".*}.*}/
|
84
|
+
)
|
85
|
+
end
|
86
|
+
|
87
|
+
it "includes locations" do
|
88
|
+
# rubocop:disable Metrics/LineLength
|
89
|
+
wait_for_a_request_with_body(
|
90
|
+
%r("params":{.*"rake_task":{.*"locations":\[".+spec/apps/rails/dummy_task.rake:\d+:in.+"\].*}.*})
|
91
|
+
)
|
92
|
+
# rubocop:enable Metrics/LineLength
|
93
|
+
end
|
94
|
+
|
95
|
+
it "includes sources" do
|
96
|
+
wait_for_a_request_with_body(
|
97
|
+
/"params":{.*"rake_task":{.*"sources":\["environment"\].*}.*}/
|
98
|
+
)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "includes prerequisite tasks" do
|
102
|
+
# rubocop:disable Metrics/LineLength
|
103
|
+
wait_for_a_request_with_body(
|
104
|
+
/"params":{.*"rake_task":{.*"prerequisite_tasks":\[{"name":"bingo:environment".+\].*}.*}/
|
105
|
+
)
|
106
|
+
# rubocop:enable Metrics/LineLength
|
107
|
+
end
|
108
|
+
|
109
|
+
it "includes argv info" do
|
110
|
+
wait_for_a_request_with_body(
|
111
|
+
%r("params":{.*"argv":"--pattern spec/integration/rails/\*_spec.rb".*})
|
112
|
+
)
|
113
|
+
end
|
114
|
+
|
115
|
+
it "includes #execute args" do
|
116
|
+
wait_for_a_request_with_body(
|
117
|
+
/"params":{.*"execute_args":\[\].*}/
|
118
|
+
)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe "a task with minimum information, which raises an exception" do
|
124
|
+
let(:faulty_task) { Rake::Task['bingo:bongo'] }
|
125
|
+
|
126
|
+
describe "doesn't contain in the params payload" do
|
127
|
+
it "full comment" do
|
128
|
+
expect_no_requests_with_body(
|
129
|
+
/"params":{.*"rake_task":{.*"full_comment":"Dummy description".*}.*}/
|
130
|
+
)
|
131
|
+
end
|
132
|
+
|
133
|
+
it "arg names" do
|
134
|
+
expect_no_requests_with_body(
|
135
|
+
/"params":{.*"rake_task":{.*"arg_names":\["dummy_arg"\].*}.*}/
|
136
|
+
)
|
137
|
+
end
|
138
|
+
|
139
|
+
it "arg description" do
|
140
|
+
expect_no_requests_with_body(
|
141
|
+
/"params":{.*"rake_task":{.*"arg_description":"\[dummy_arg\]".*}.*}/
|
142
|
+
)
|
143
|
+
end
|
144
|
+
|
145
|
+
it "sources" do
|
146
|
+
expect_no_requests_with_body(
|
147
|
+
/"params":{.*"rake_task":{.*"sources":\["environment"\].*}.*}/
|
148
|
+
)
|
149
|
+
end
|
150
|
+
|
151
|
+
it "prerequisite tasks" do
|
152
|
+
# rubocop:disable Metrics/LineLength
|
153
|
+
expect_no_requests_with_body(
|
154
|
+
/"params":{.*"rake_task":{.*"prerequisite_tasks":\[{"name":"bingo:environment".+\].*}.*}/
|
155
|
+
)
|
156
|
+
# rubocop:enable Metrics/LineLength
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
RSpec.shared_examples 'rack examples' do
|
2
|
+
include Warden::Test::Helpers
|
3
|
+
|
4
|
+
after { Warden.test_reset! }
|
5
|
+
|
6
|
+
let(:endpoint) do
|
7
|
+
'https://airbrake.io/api/v3/projects/113743/notices?key=fd04e13d806a90f96614ad8e529b2822'
|
8
|
+
end
|
9
|
+
|
10
|
+
def wait_for_a_request_with_body(body)
|
11
|
+
wait_for(a_request(:post, endpoint).with(body: body)).to have_been_made.once
|
12
|
+
end
|
13
|
+
|
14
|
+
before do
|
15
|
+
stub_request(:post, endpoint).to_return(status: 201, body: '{}')
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "application routes" do
|
19
|
+
describe "/index" do
|
20
|
+
it "successfully returns 200 and body" do
|
21
|
+
get '/'
|
22
|
+
|
23
|
+
expect(last_response.status).to eq(200)
|
24
|
+
expect(last_response.body).to eq('Hello from index')
|
25
|
+
|
26
|
+
wait_for(a_request(:post, endpoint)).not_to have_been_made
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "/crash" do
|
31
|
+
it "returns 500 and sends a notice to Airbrake" do
|
32
|
+
get '/crash'
|
33
|
+
|
34
|
+
expect(last_response.status).to eq(500)
|
35
|
+
wait_for_a_request_with_body(/"errors":\[{"type":"AirbrakeTestError"/)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "context payload" do
|
41
|
+
context "when the user is present" do
|
42
|
+
let(:common_user_params) do
|
43
|
+
{ id: 1, email: 'qa@example.com', username: 'qa-dept' }
|
44
|
+
end
|
45
|
+
|
46
|
+
before do
|
47
|
+
login_as(OpenStruct.new(user_params))
|
48
|
+
get '/crash'
|
49
|
+
end
|
50
|
+
|
51
|
+
context "when the user has first and last names" do
|
52
|
+
let(:user_params) do
|
53
|
+
common_user_params.merge(first_name: 'Bingo', last_name: 'Bongo')
|
54
|
+
end
|
55
|
+
|
56
|
+
it "reports the user's first and last names" do
|
57
|
+
wait_for_a_request_with_body(/
|
58
|
+
"context":{.*
|
59
|
+
"user":{
|
60
|
+
"id":"1",
|
61
|
+
"name":"Bingo\sBongo",
|
62
|
+
"username":"qa-dept",
|
63
|
+
"email":"qa@example.com"}
|
64
|
+
/x)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context "when the user has only name" do
|
69
|
+
let(:user_params) do
|
70
|
+
common_user_params.merge(name: 'Bingo')
|
71
|
+
end
|
72
|
+
|
73
|
+
it "reports the user's name" do
|
74
|
+
wait_for_a_request_with_body(/
|
75
|
+
"context":{.*
|
76
|
+
"user":{
|
77
|
+
"id":"1",
|
78
|
+
"name":"Bingo",
|
79
|
+
"username":"qa-dept",
|
80
|
+
"email":"qa@example.com"}
|
81
|
+
/x)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context "when additional parameters present" do
|
87
|
+
before do
|
88
|
+
get '/crash', nil, 'HTTP_USER_AGENT' => 'Bot'
|
89
|
+
end
|
90
|
+
|
91
|
+
it "features url" do
|
92
|
+
wait_for_a_request_with_body(
|
93
|
+
%r("context":{.*"url":"http://example\.org/crash".*})
|
94
|
+
)
|
95
|
+
end
|
96
|
+
|
97
|
+
it "features hostname" do
|
98
|
+
wait_for_a_request_with_body(/"context":{.*"hostname":".+".*}/)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "features userAgent" do
|
102
|
+
wait_for_a_request_with_body(/"context":{.*"userAgent":"Bot".*}/)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'integration/shared_examples/rack_examples'
|
3
|
+
|
4
|
+
RSpec.describe "Sinatra integration specs" do
|
5
|
+
let(:app) { DummyApp }
|
6
|
+
|
7
|
+
include_examples 'rack examples'
|
8
|
+
|
9
|
+
describe "context payload" do
|
10
|
+
it "includes version" do
|
11
|
+
get '/crash'
|
12
|
+
wait_for_a_request_with_body(/"context":{.*"version":"1.2.3 Sinatra/)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
# Gems from the gemspec.
|
2
|
+
require 'webmock'
|
3
|
+
require 'webmock/rspec'
|
4
|
+
require 'rspec/wait'
|
5
|
+
require 'pry'
|
6
|
+
require 'rack'
|
7
|
+
require 'rack/test'
|
8
|
+
require 'rake'
|
9
|
+
|
10
|
+
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.0')
|
11
|
+
require 'sidekiq'
|
12
|
+
require 'sidekiq/cli'
|
13
|
+
end
|
14
|
+
|
15
|
+
require 'airbrake'
|
16
|
+
require 'airbrake/rake/tasks'
|
17
|
+
|
18
|
+
# Load integration tests only when they're run through appraisals.
|
19
|
+
if ENV['APPRAISAL_INITIALIZED']
|
20
|
+
# Gems from appraisals that every application uses.
|
21
|
+
require 'warden'
|
22
|
+
|
23
|
+
# Load a Rails app or skip.
|
24
|
+
begin
|
25
|
+
ENV['RAILS_ENV'] = 'test'
|
26
|
+
|
27
|
+
if RUBY_ENGINE == 'jruby'
|
28
|
+
require 'activerecord-jdbcsqlite3-adapter'
|
29
|
+
else
|
30
|
+
require 'sqlite3'
|
31
|
+
end
|
32
|
+
|
33
|
+
require 'rails'
|
34
|
+
|
35
|
+
rails_vsn = Gem::Version.new(Rails.version)
|
36
|
+
|
37
|
+
if rails_vsn <= Gem::Version.new('4.2')
|
38
|
+
ENV['DATABASE_URL'] = 'sqlite3:///:memory:'
|
39
|
+
else
|
40
|
+
ENV['DATABASE_URL'] = 'sqlite3::memory:'
|
41
|
+
end
|
42
|
+
|
43
|
+
require 'action_controller'
|
44
|
+
require 'action_view'
|
45
|
+
require 'action_view/testing/resolvers'
|
46
|
+
require 'active_record/railtie'
|
47
|
+
if rails_vsn >= Gem::Version.new('4.2')
|
48
|
+
require 'active_job'
|
49
|
+
|
50
|
+
# Silence logger.
|
51
|
+
ActiveJob::Base.logger.level = 99
|
52
|
+
end
|
53
|
+
|
54
|
+
require 'resque'
|
55
|
+
require 'resque_spec'
|
56
|
+
require 'airbrake/resque/failure'
|
57
|
+
Resque::Failure.backend = Resque::Failure::Airbrake
|
58
|
+
|
59
|
+
require 'delayed_job'
|
60
|
+
require 'delayed_job_active_record'
|
61
|
+
require 'airbrake/delayed_job/plugin'
|
62
|
+
Delayed::Worker.delay_jobs = false
|
63
|
+
|
64
|
+
require 'airbrake/rails/railtie'
|
65
|
+
|
66
|
+
load 'apps/rails/dummy_task.rake'
|
67
|
+
require 'apps/rails/dummy_app'
|
68
|
+
rescue LoadError
|
69
|
+
puts '** Skipped Rails specs'
|
70
|
+
end
|
71
|
+
|
72
|
+
# Load a Sinatra app or skip.
|
73
|
+
begin
|
74
|
+
# Resque depends on Sinatra, so when we launch Rails specs, we also
|
75
|
+
# accidentally load Sinatra.
|
76
|
+
raise LoadError if defined?(Resque)
|
77
|
+
|
78
|
+
require 'sinatra'
|
79
|
+
require 'apps/sinatra/dummy_app'
|
80
|
+
rescue LoadError
|
81
|
+
puts '** Skipped Sinatra specs'
|
82
|
+
end
|
83
|
+
|
84
|
+
# Load a Rack app or skip.
|
85
|
+
begin
|
86
|
+
require 'apps/rack/dummy_app'
|
87
|
+
rescue LoadError
|
88
|
+
puts '** Skipped Rack specs'
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
RSpec.configure do |c|
|
93
|
+
c.order = 'random'
|
94
|
+
c.color = true
|
95
|
+
c.disable_monkey_patching!
|
96
|
+
c.wait_timeout = 3
|
97
|
+
|
98
|
+
c.include Rack::Test::Methods
|
99
|
+
end
|
100
|
+
|
101
|
+
Airbrake.configure do |c|
|
102
|
+
c.project_id = 113743
|
103
|
+
c.project_key = 'fd04e13d806a90f96614ad8e529b2822'
|
104
|
+
c.logger = Logger.new('/dev/null')
|
105
|
+
c.app_version = '1.2.3'
|
106
|
+
c.workers = 5
|
107
|
+
end
|
108
|
+
|
109
|
+
# Make sure tests that use async requests fail.
|
110
|
+
Thread.abort_on_exception = true
|
111
|
+
|
112
|
+
AirbrakeTestError = Class.new(StandardError)
|
113
|
+
|
114
|
+
# Print header with versions information. This simplifies debugging of build
|
115
|
+
# failures on CircleCI.
|
116
|
+
versions = <<EOS
|
117
|
+
#{'#' * 80}
|
118
|
+
# RUBY_VERSION: #{RUBY_VERSION}
|
119
|
+
# RUBY_ENGINE: #{RUBY_ENGINE}
|
120
|
+
EOS
|
121
|
+
versions << "# JRUBY_VERSION #{JRUBY_VERSION}\n" if defined?(JRUBY_VERSION)
|
122
|
+
versions << "# Rails version: #{Rails.version}\n" if defined?(Rails)
|
123
|
+
versions << "# Sinatra version: #{Sinatra::VERSION}\n" if defined?(Sinatra)
|
124
|
+
versions << "# Rack release: #{Rack.release}\n"
|
125
|
+
versions << '#' * 80
|
126
|
+
|
127
|
+
puts versions
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Airbrake::Rack::Middleware do
|
4
|
+
let(:app) do
|
5
|
+
proc { |env| [200, env, 'Bingo bango content'] }
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:faulty_app) do
|
9
|
+
proc { raise AirbrakeTestError }
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:endpoint) do
|
13
|
+
'https://airbrake.io/api/v3/projects/113743/notices?key=fd04e13d806a90f96614ad8e529b2822'
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:middleware) { described_class.new(app) }
|
17
|
+
|
18
|
+
def env_for(url, opts = {})
|
19
|
+
Rack::MockRequest.env_for(url, opts)
|
20
|
+
end
|
21
|
+
|
22
|
+
def wait_for_a_request_with_body(body)
|
23
|
+
wait_for(a_request(:post, endpoint).with(body: body)).to have_been_made.once
|
24
|
+
end
|
25
|
+
|
26
|
+
before do
|
27
|
+
stub_request(:post, endpoint).to_return(status: 201, body: '{}')
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#call" do
|
31
|
+
context "when app raises an exception" do
|
32
|
+
it "rescues the exception, notifies Airbrake & re-raises it" do
|
33
|
+
expect { described_class.new(faulty_app).call(env_for('/')) }.
|
34
|
+
to raise_error(AirbrakeTestError)
|
35
|
+
|
36
|
+
wait_for_a_request_with_body(/"errors":\[{"type":"AirbrakeTestError"/)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "sends framework version and name" do
|
40
|
+
expect { described_class.new(faulty_app).call(env_for('/bingo/bango')) }.
|
41
|
+
to raise_error(AirbrakeTestError)
|
42
|
+
|
43
|
+
wait_for_a_request_with_body(
|
44
|
+
%r("context":{.*"version":"1.2.3 (Rails|Sinatra|Rack\.version)/.+".+})
|
45
|
+
)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "when app doesn't raise" do
|
50
|
+
context "and previous middleware stored an exception in env" do
|
51
|
+
shared_examples 'stored exception' do |type|
|
52
|
+
it "notifies on #{type}, but doesn't raise" do
|
53
|
+
env = env_for('/').merge(type => AirbrakeTestError.new)
|
54
|
+
described_class.new(app).call(env)
|
55
|
+
|
56
|
+
wait_for_a_request_with_body(/"errors":\[{"type":"AirbrakeTestError"/)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
['action_dispatch.exception', 'sinatra.error'].each do |type|
|
61
|
+
include_examples 'stored exception', type
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
it "doesn't notify Airbrake" do
|
66
|
+
described_class.new(app).call(env_for('/'))
|
67
|
+
sleep 1
|
68
|
+
expect(a_request(:post, endpoint)).not_to have_been_made
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
it "returns a response" do
|
73
|
+
response = described_class.new(app).call(env_for('/'))
|
74
|
+
|
75
|
+
expect(response[0]).to eq(200)
|
76
|
+
expect(response[1]).to be_a(Hash)
|
77
|
+
expect(response[2]).to eq('Bingo bango content')
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Airbrake::Rack::NoticeBuilder do
|
4
|
+
describe "#build_notice" do
|
5
|
+
it "doesn't overwrite session with nil" do
|
6
|
+
notice_builder = described_class.new('rack.session' => nil)
|
7
|
+
notice = notice_builder.build_notice(AirbrakeTestError.new)
|
8
|
+
|
9
|
+
expect(notice[:session]).to eq({})
|
10
|
+
end
|
11
|
+
|
12
|
+
it "sets session if it is present" do
|
13
|
+
session = { a: 1, b: 2 }
|
14
|
+
notice_builder = described_class.new('rack.session' => session)
|
15
|
+
notice = notice_builder.build_notice(AirbrakeTestError.new)
|
16
|
+
|
17
|
+
expect(notice[:session]).to eq(session)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "doesn't overwrite params with nil" do
|
21
|
+
notice_builder = described_class.new('action_dispatch.request.parameters' => nil)
|
22
|
+
notice = notice_builder.build_notice(AirbrakeTestError.new)
|
23
|
+
|
24
|
+
expect(notice[:session]).to eq({})
|
25
|
+
end
|
26
|
+
|
27
|
+
it "sets params if they're present" do
|
28
|
+
params = { a: 1, b: 2 }
|
29
|
+
notice_builder = described_class.new('action_dispatch.request.parameters' => params)
|
30
|
+
notice = notice_builder.build_notice(AirbrakeTestError.new)
|
31
|
+
|
32
|
+
expect(notice[:params]).to eq(params)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|