bullet 7.0.6 → 7.1.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/CHANGELOG.md +13 -1
- data/README.md +3 -0
- data/lib/bullet/active_record4.rb +9 -0
- data/lib/bullet/active_record41.rb +9 -0
- data/lib/bullet/active_record42.rb +9 -0
- data/lib/bullet/active_record5.rb +11 -0
- data/lib/bullet/active_record52.rb +11 -0
- data/lib/bullet/active_record60.rb +11 -0
- data/lib/bullet/active_record61.rb +11 -0
- data/lib/bullet/active_record70.rb +19 -6
- data/lib/bullet/active_record71.rb +297 -0
- data/lib/bullet/dependency.rb +12 -0
- data/lib/bullet/detector/unused_eager_loading.rb +1 -1
- data/lib/bullet/mongoid8x.rb +59 -0
- data/lib/bullet/notification/counter_cache.rb +1 -1
- data/lib/bullet/rack.rb +1 -1
- data/lib/bullet/version.rb +1 -1
- data/lib/bullet.rb +6 -2
- metadata +7 -155
- data/.github/workflows/main.yml +0 -82
- data/.gitignore +0 -15
- data/.rspec +0 -2
- data/Gemfile +0 -24
- data/Gemfile.mongoid +0 -12
- data/Gemfile.mongoid-4.0 +0 -15
- data/Gemfile.mongoid-5.0 +0 -15
- data/Gemfile.mongoid-6.0 +0 -15
- data/Gemfile.mongoid-7.0 +0 -15
- data/Gemfile.rails-4.0 +0 -16
- data/Gemfile.rails-4.1 +0 -16
- data/Gemfile.rails-4.2 +0 -16
- data/Gemfile.rails-5.0 +0 -15
- data/Gemfile.rails-5.1 +0 -15
- data/Gemfile.rails-5.2 +0 -15
- data/Gemfile.rails-6.0 +0 -15
- data/Gemfile.rails-6.1 +0 -15
- data/Gemfile.rails-7.0 +0 -10
- data/Guardfile +0 -8
- data/Hacking.md +0 -75
- data/Rakefile +0 -51
- data/bullet.gemspec +0 -33
- data/perf/benchmark.rb +0 -118
- data/rails/init.rb +0 -3
- data/spec/bullet/detector/association_spec.rb +0 -28
- data/spec/bullet/detector/base_spec.rb +0 -10
- data/spec/bullet/detector/counter_cache_spec.rb +0 -58
- data/spec/bullet/detector/n_plus_one_query_spec.rb +0 -150
- data/spec/bullet/detector/unused_eager_loading_spec.rb +0 -126
- data/spec/bullet/ext/object_spec.rb +0 -44
- data/spec/bullet/ext/string_spec.rb +0 -15
- data/spec/bullet/notification/base_spec.rb +0 -94
- data/spec/bullet/notification/counter_cache_spec.rb +0 -14
- data/spec/bullet/notification/n_plus_one_query_spec.rb +0 -29
- data/spec/bullet/notification/unused_eager_loading_spec.rb +0 -18
- data/spec/bullet/notification_collector_spec.rb +0 -34
- data/spec/bullet/rack_spec.rb +0 -296
- data/spec/bullet/registry/association_spec.rb +0 -28
- data/spec/bullet/registry/base_spec.rb +0 -46
- data/spec/bullet/registry/object_spec.rb +0 -26
- data/spec/bullet/stack_trace_filter_spec.rb +0 -26
- data/spec/bullet_spec.rb +0 -136
- data/spec/integration/active_record/association_spec.rb +0 -822
- data/spec/integration/counter_cache_spec.rb +0 -68
- data/spec/integration/mongoid/association_spec.rb +0 -246
- data/spec/models/address.rb +0 -5
- data/spec/models/attachment.rb +0 -5
- data/spec/models/author.rb +0 -5
- data/spec/models/base_user.rb +0 -7
- data/spec/models/category.rb +0 -12
- data/spec/models/city.rb +0 -5
- data/spec/models/client.rb +0 -8
- data/spec/models/comment.rb +0 -8
- data/spec/models/company.rb +0 -5
- data/spec/models/country.rb +0 -5
- data/spec/models/deal.rb +0 -5
- data/spec/models/document.rb +0 -7
- data/spec/models/entry.rb +0 -5
- data/spec/models/firm.rb +0 -7
- data/spec/models/folder.rb +0 -4
- data/spec/models/group.rb +0 -4
- data/spec/models/mongoid/address.rb +0 -9
- data/spec/models/mongoid/category.rb +0 -10
- data/spec/models/mongoid/comment.rb +0 -9
- data/spec/models/mongoid/company.rb +0 -9
- data/spec/models/mongoid/entry.rb +0 -9
- data/spec/models/mongoid/post.rb +0 -14
- data/spec/models/mongoid/user.rb +0 -7
- data/spec/models/newspaper.rb +0 -5
- data/spec/models/page.rb +0 -4
- data/spec/models/person.rb +0 -5
- data/spec/models/pet.rb +0 -5
- data/spec/models/post.rb +0 -34
- data/spec/models/relationship.rb +0 -6
- data/spec/models/reply.rb +0 -5
- data/spec/models/role.rb +0 -7
- data/spec/models/student.rb +0 -5
- data/spec/models/submission.rb +0 -7
- data/spec/models/teacher.rb +0 -5
- data/spec/models/user.rb +0 -8
- data/spec/models/writer.rb +0 -4
- data/spec/spec_helper.rb +0 -97
- data/spec/support/bullet_ext.rb +0 -56
- data/spec/support/mongo_seed.rb +0 -59
- data/spec/support/rack_double.rb +0 -49
- data/spec/support/sqlite_seed.rb +0 -284
- data/test.sh +0 -15
- data/update.sh +0 -10
@@ -1,44 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
describe Object do
|
6
|
-
context 'bullet_key' do
|
7
|
-
it 'should return class and id composition' do
|
8
|
-
post = Post.first
|
9
|
-
expect(post.bullet_key).to eq("Post:#{post.id}")
|
10
|
-
end
|
11
|
-
|
12
|
-
if mongoid?
|
13
|
-
it 'should return class with namespace and id composition' do
|
14
|
-
post = Mongoid::Post.first
|
15
|
-
expect(post.bullet_key).to eq("Mongoid::Post:#{post.id}")
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
context 'bullet_primary_key_value' do
|
21
|
-
it 'should return id' do
|
22
|
-
post = Post.first
|
23
|
-
expect(post.bullet_primary_key_value).to eq(post.id)
|
24
|
-
end
|
25
|
-
|
26
|
-
it 'should return primary key value' do
|
27
|
-
post = Post.first
|
28
|
-
Post.primary_key = 'name'
|
29
|
-
expect(post.bullet_primary_key_value).to eq(post.name)
|
30
|
-
Post.primary_key = 'id'
|
31
|
-
end
|
32
|
-
|
33
|
-
it 'should return value for multiple primary keys' do
|
34
|
-
post = Post.first
|
35
|
-
allow(Post).to receive(:primary_keys).and_return(%i[category_id writer_id])
|
36
|
-
expect(post.bullet_primary_key_value).to eq("#{post.category_id},#{post.writer_id}")
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'it should return nil for unpersisted records' do
|
40
|
-
post = Post.new(id: 123)
|
41
|
-
expect(post.bullet_primary_key_value).to be_nil
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
describe String do
|
6
|
-
context 'bullet_class_name' do
|
7
|
-
it 'should only return class name' do
|
8
|
-
expect('Post:1'.bullet_class_name).to eq('Post')
|
9
|
-
end
|
10
|
-
|
11
|
-
it 'should return class name with namespace' do
|
12
|
-
expect('Mongoid::Post:1234567890'.bullet_class_name).to eq('Mongoid::Post')
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
@@ -1,94 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
module Bullet
|
6
|
-
module Notification
|
7
|
-
describe Base do
|
8
|
-
subject { Base.new(Post, %i[comments votes]) }
|
9
|
-
|
10
|
-
context '#title' do
|
11
|
-
it 'should raise NoMethodError' do
|
12
|
-
expect { subject.title }.to raise_error(NoMethodError)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
context '#body' do
|
17
|
-
it 'should raise NoMethodError' do
|
18
|
-
expect { subject.body }.to raise_error(NoMethodError)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
context '#whoami' do
|
23
|
-
it 'should display user name' do
|
24
|
-
user = `whoami`.chomp
|
25
|
-
expect(subject.whoami).to eq("user: #{user}")
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'should leverage ENV parameter' do
|
29
|
-
temp_env_variable('USER', 'bogus') { expect(subject.whoami).to eq('user: bogus') }
|
30
|
-
end
|
31
|
-
|
32
|
-
it 'should return blank if no user available' do
|
33
|
-
temp_env_variable('USER', '') do
|
34
|
-
expect(subject).to receive(:`).with('whoami').and_return('')
|
35
|
-
expect(subject.whoami).to eq('')
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'should return blank if whoami is not available' do
|
40
|
-
temp_env_variable('USER', '') do
|
41
|
-
expect(subject).to receive(:`).with('whoami').and_raise(Errno::ENOENT)
|
42
|
-
expect(subject.whoami).to eq('')
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def temp_env_variable(name, value)
|
47
|
-
old_value = ENV[name]
|
48
|
-
ENV[name] = value
|
49
|
-
yield
|
50
|
-
ensure
|
51
|
-
ENV[name] = old_value
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
context '#body_with_caller' do
|
56
|
-
it 'should return body' do
|
57
|
-
allow(subject).to receive(:body).and_return('body')
|
58
|
-
allow(subject).to receive(:call_stack_messages).and_return('call_stack_messages')
|
59
|
-
expect(subject.body_with_caller).to eq("body\ncall_stack_messages\n")
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
context '#notification_data' do
|
64
|
-
it 'should return notification data' do
|
65
|
-
allow(subject).to receive(:whoami).and_return('whoami')
|
66
|
-
allow(subject).to receive(:url).and_return('url')
|
67
|
-
allow(subject).to receive(:title).and_return('title')
|
68
|
-
allow(subject).to receive(:body_with_caller).and_return('body_with_caller')
|
69
|
-
expect(subject.notification_data).to eq(user: 'whoami', url: 'url', title: 'title', body: 'body_with_caller')
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
context '#notify_inline' do
|
74
|
-
it 'should send full_notice to notifier' do
|
75
|
-
notifier = double
|
76
|
-
allow(subject).to receive(:notifier).and_return(notifier)
|
77
|
-
allow(subject).to receive(:notification_data).and_return({ foo: :bar })
|
78
|
-
expect(notifier).to receive(:inline_notify).with({ foo: :bar })
|
79
|
-
subject.notify_inline
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
context '#notify_out_of_channel' do
|
84
|
-
it 'should send full_out_of_channel to notifier' do
|
85
|
-
notifier = double
|
86
|
-
allow(subject).to receive(:notifier).and_return(notifier)
|
87
|
-
allow(subject).to receive(:notification_data).and_return({ foo: :bar })
|
88
|
-
expect(notifier).to receive(:out_of_channel_notify).with({ foo: :bar })
|
89
|
-
subject.notify_out_of_channel
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
@@ -1,14 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
module Bullet
|
6
|
-
module Notification
|
7
|
-
describe CounterCache do
|
8
|
-
subject { CounterCache.new(Post, %i[comments votes]) }
|
9
|
-
|
10
|
-
it { expect(subject.body).to eq(' Post => [:comments, :votes]') }
|
11
|
-
it { expect(subject.title).to eq('Need Counter Cache') }
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
module Bullet
|
6
|
-
module Notification
|
7
|
-
describe NPlusOneQuery do
|
8
|
-
subject { NPlusOneQuery.new([%w[caller1 caller2]], Post, %i[comments votes], 'path') }
|
9
|
-
|
10
|
-
it do
|
11
|
-
expect(subject.body_with_caller).to eq(
|
12
|
-
" Post => [:comments, :votes]\n Add to your query: .includes([:comments, :votes])\nCall stack\n caller1\n caller2\n"
|
13
|
-
)
|
14
|
-
end
|
15
|
-
it do
|
16
|
-
expect([subject.body_with_caller, subject.body_with_caller]).to eq(
|
17
|
-
[
|
18
|
-
" Post => [:comments, :votes]\n Add to your query: .includes([:comments, :votes])\nCall stack\n caller1\n caller2\n",
|
19
|
-
" Post => [:comments, :votes]\n Add to your query: .includes([:comments, :votes])\nCall stack\n caller1\n caller2\n"
|
20
|
-
]
|
21
|
-
)
|
22
|
-
end
|
23
|
-
it do
|
24
|
-
expect(subject.body).to eq(" Post => [:comments, :votes]\n Add to your query: .includes([:comments, :votes])")
|
25
|
-
end
|
26
|
-
it { expect(subject.title).to eq('USE eager loading in path') }
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
module Bullet
|
6
|
-
module Notification
|
7
|
-
describe UnusedEagerLoading do
|
8
|
-
subject { UnusedEagerLoading.new([''], Post, %i[comments votes], 'path') }
|
9
|
-
|
10
|
-
it do
|
11
|
-
expect(subject.body).to eq(
|
12
|
-
" Post => [:comments, :votes]\n Remove from your query: .includes([:comments, :votes])"
|
13
|
-
)
|
14
|
-
end
|
15
|
-
it { expect(subject.title).to eq('AVOID eager loading in path') }
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
module Bullet
|
6
|
-
describe NotificationCollector do
|
7
|
-
subject { NotificationCollector.new.tap { |collector| collector.add('value') } }
|
8
|
-
|
9
|
-
context '#add' do
|
10
|
-
it 'should add a value' do
|
11
|
-
subject.add('value1')
|
12
|
-
expect(subject.collection).to be_include('value1')
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
context '#reset' do
|
17
|
-
it 'should reset collector' do
|
18
|
-
subject.reset
|
19
|
-
expect(subject.collection).to be_empty
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
context '#notifications_present?' do
|
24
|
-
it 'should be true if collection is not empty' do
|
25
|
-
expect(subject).to be_notifications_present
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'should be false if collection is empty' do
|
29
|
-
subject.reset
|
30
|
-
expect(subject).not_to be_notifications_present
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
data/spec/bullet/rack_spec.rb
DELETED
@@ -1,296 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
module Bullet
|
6
|
-
describe Rack do
|
7
|
-
let(:middleware) { Bullet::Rack.new app }
|
8
|
-
let(:app) { Support::AppDouble.new }
|
9
|
-
|
10
|
-
context '#html_request?' do
|
11
|
-
it 'should be true if Content-Type is text/html and http body contains html tag' do
|
12
|
-
headers = { 'Content-Type' => 'text/html' }
|
13
|
-
response = double(body: '<html><head></head><body></body></html>')
|
14
|
-
expect(middleware).to be_html_request(headers, response)
|
15
|
-
end
|
16
|
-
|
17
|
-
it 'should be true if Content-Type is text/html and http body contains html tag with attributes' do
|
18
|
-
headers = { 'Content-Type' => 'text/html' }
|
19
|
-
response = double(body: "<html attr='hello'><head></head><body></body></html>")
|
20
|
-
expect(middleware).to be_html_request(headers, response)
|
21
|
-
end
|
22
|
-
|
23
|
-
it 'should be false if there is no Content-Type header' do
|
24
|
-
headers = {}
|
25
|
-
response = double(body: '<html><head></head><body></body></html>')
|
26
|
-
expect(middleware).not_to be_html_request(headers, response)
|
27
|
-
end
|
28
|
-
|
29
|
-
it 'should be false if Content-Type is javascript' do
|
30
|
-
headers = { 'Content-Type' => 'text/javascript' }
|
31
|
-
response = double(body: '<html><head></head><body></body></html>')
|
32
|
-
expect(middleware).not_to be_html_request(headers, response)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
context 'empty?' do
|
37
|
-
it 'should be false if response is a string and not empty' do
|
38
|
-
response = double(body: '<html><head></head><body></body></html>')
|
39
|
-
expect(middleware).not_to be_empty(response)
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'should be false if response is not found' do
|
43
|
-
response = ['Not Found']
|
44
|
-
expect(middleware).not_to be_empty(response)
|
45
|
-
end
|
46
|
-
|
47
|
-
it 'should be true if response body is empty' do
|
48
|
-
response = double(body: '')
|
49
|
-
expect(middleware).to be_empty(response)
|
50
|
-
end
|
51
|
-
|
52
|
-
it 'should be true if no response body' do
|
53
|
-
response = double
|
54
|
-
expect(middleware).to be_empty(response)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
context '#call' do
|
59
|
-
context 'when Bullet is enabled' do
|
60
|
-
it 'should return original response body' do
|
61
|
-
expected_response = Support::ResponseDouble.new 'Actual body'
|
62
|
-
app.response = expected_response
|
63
|
-
_, _, response = middleware.call({})
|
64
|
-
expect(response).to eq(expected_response)
|
65
|
-
end
|
66
|
-
|
67
|
-
it 'should change response body if notification is active' do
|
68
|
-
expect(Bullet).to receive(:notification?).and_return(true)
|
69
|
-
expect(Bullet).to receive(:console_enabled?).and_return(true)
|
70
|
-
expect(Bullet).to receive(:gather_inline_notifications).and_return('<bullet></bullet>')
|
71
|
-
expect(Bullet).to receive(:perform_out_of_channel_notifications)
|
72
|
-
_, headers, response = middleware.call('Content-Type' => 'text/html')
|
73
|
-
expect(headers['Content-Length']).to eq('56')
|
74
|
-
expect(response).to eq(%w[<html><head></head><body><bullet></bullet></body></html>])
|
75
|
-
end
|
76
|
-
|
77
|
-
it 'should set the right Content-Length if response body contains accents' do
|
78
|
-
response = Support::ResponseDouble.new
|
79
|
-
response.body = '<html><head></head><body>é</body></html>'
|
80
|
-
app.response = response
|
81
|
-
expect(Bullet).to receive(:notification?).and_return(true)
|
82
|
-
allow(Bullet).to receive(:console_enabled?).and_return(true)
|
83
|
-
expect(Bullet).to receive(:gather_inline_notifications).and_return('<bullet></bullet>')
|
84
|
-
_, headers, response = middleware.call('Content-Type' => 'text/html')
|
85
|
-
expect(headers['Content-Length']).to eq('58')
|
86
|
-
end
|
87
|
-
|
88
|
-
context 'with injection notifiers' do
|
89
|
-
before do
|
90
|
-
expect(Bullet).to receive(:notification?).and_return(true)
|
91
|
-
allow(Bullet).to receive(:gather_inline_notifications).and_return('<bullet></bullet>')
|
92
|
-
allow(middleware).to receive(:xhr_script).and_return('<script></script>')
|
93
|
-
allow(middleware).to receive(:footer_note).and_return('footer')
|
94
|
-
expect(Bullet).to receive(:perform_out_of_channel_notifications)
|
95
|
-
end
|
96
|
-
|
97
|
-
it 'should change response body if add_footer is true' do
|
98
|
-
expect(Bullet).to receive(:add_footer).exactly(3).times.and_return(true)
|
99
|
-
_, headers, response = middleware.call('Content-Type' => 'text/html')
|
100
|
-
|
101
|
-
expect(headers['Content-Length']).to eq((73 + middleware.send(:footer_note).length).to_s)
|
102
|
-
expect(response).to eq(%w[<html><head></head><body>footer<bullet></bullet><script></script></body></html>])
|
103
|
-
end
|
104
|
-
|
105
|
-
it 'should change response body for html safe string if add_footer is true' do
|
106
|
-
expect(Bullet).to receive(:add_footer).exactly(3).times.and_return(true)
|
107
|
-
app.response =
|
108
|
-
Support::ResponseDouble.new.tap do |response|
|
109
|
-
response.body = ActiveSupport::SafeBuffer.new('<html><head></head><body></body></html>')
|
110
|
-
end
|
111
|
-
_, headers, response = middleware.call('Content-Type' => 'text/html')
|
112
|
-
|
113
|
-
expect(headers['Content-Length']).to eq((73 + middleware.send(:footer_note).length).to_s)
|
114
|
-
expect(response).to eq(%w[<html><head></head><body>footer<bullet></bullet><script></script></body></html>])
|
115
|
-
end
|
116
|
-
|
117
|
-
it 'should add the footer-text header for non-html requests when add_footer is true' do
|
118
|
-
allow(Bullet).to receive(:add_footer).at_least(:once).and_return(true)
|
119
|
-
allow(Bullet).to receive(:footer_info).and_return(['footer text'])
|
120
|
-
app.headers = { 'Content-Type' => 'application/json' }
|
121
|
-
_, headers, _response = middleware.call({})
|
122
|
-
expect(headers).to include('X-bullet-footer-text' => '["footer text"]')
|
123
|
-
end
|
124
|
-
|
125
|
-
it 'should change response body if console_enabled is true' do
|
126
|
-
expect(Bullet).to receive(:console_enabled?).and_return(true)
|
127
|
-
_, headers, response = middleware.call('Content-Type' => 'text/html')
|
128
|
-
expect(headers['Content-Length']).to eq('56')
|
129
|
-
expect(response).to eq(%w[<html><head></head><body><bullet></bullet></body></html>])
|
130
|
-
end
|
131
|
-
|
132
|
-
it 'should include CSP nonce in inline script if console_enabled and a CSP is applied' do
|
133
|
-
allow(Bullet).to receive(:add_footer).at_least(:once).and_return(true)
|
134
|
-
expect(Bullet).to receive(:console_enabled?).and_return(true)
|
135
|
-
allow(middleware).to receive(:xhr_script).and_call_original
|
136
|
-
|
137
|
-
nonce = '+t9/wTlgG6xbHxXYUaDNzQ=='
|
138
|
-
app.headers = {
|
139
|
-
'Content-Type' => 'text/html',
|
140
|
-
'Content-Security-Policy' => "default-src 'self' https:; script-src 'self' https: 'nonce-#{nonce}'"
|
141
|
-
}
|
142
|
-
|
143
|
-
_, headers, response = middleware.call('Content-Type' => 'text/html')
|
144
|
-
|
145
|
-
size = 56 + middleware.send(:footer_note).length + middleware.send(:xhr_script, nonce).length
|
146
|
-
expect(headers['Content-Length']).to eq(size.to_s)
|
147
|
-
end
|
148
|
-
|
149
|
-
it 'should change response body for html safe string if console_enabled is true' do
|
150
|
-
expect(Bullet).to receive(:console_enabled?).and_return(true)
|
151
|
-
app.response =
|
152
|
-
Support::ResponseDouble.new.tap do |response|
|
153
|
-
response.body = ActiveSupport::SafeBuffer.new('<html><head></head><body></body></html>')
|
154
|
-
end
|
155
|
-
_, headers, response = middleware.call('Content-Type' => 'text/html')
|
156
|
-
expect(headers['Content-Length']).to eq('56')
|
157
|
-
expect(response).to eq(%w[<html><head></head><body><bullet></bullet></body></html>])
|
158
|
-
end
|
159
|
-
|
160
|
-
it 'should add headers for non-html requests when console_enabled is true' do
|
161
|
-
allow(Bullet).to receive(:console_enabled?).at_least(:once).and_return(true)
|
162
|
-
allow(Bullet).to receive(:text_notifications).and_return(['text notifications'])
|
163
|
-
app.headers = { 'Content-Type' => 'application/json' }
|
164
|
-
_, headers, _response = middleware.call({})
|
165
|
-
expect(headers).to include('X-bullet-console-text' => '["text notifications"]')
|
166
|
-
end
|
167
|
-
|
168
|
-
it "shouldn't change response body unnecessarily" do
|
169
|
-
expected_response = Support::ResponseDouble.new 'Actual body'
|
170
|
-
app.response = expected_response
|
171
|
-
_, _, response = middleware.call({})
|
172
|
-
expect(response).to eq(expected_response)
|
173
|
-
end
|
174
|
-
|
175
|
-
it "shouldn't add headers unnecessarily" do
|
176
|
-
app.headers = { 'Content-Type' => 'application/json' }
|
177
|
-
_, headers, _response = middleware.call({})
|
178
|
-
expect(headers).not_to include('X-bullet-footer-text')
|
179
|
-
expect(headers).not_to include('X-bullet-console-text')
|
180
|
-
end
|
181
|
-
|
182
|
-
context 'when skip_http_headers is enabled' do
|
183
|
-
before do
|
184
|
-
allow(Bullet).to receive(:skip_http_headers).and_return(true)
|
185
|
-
end
|
186
|
-
|
187
|
-
it 'should include the footer but not the xhr script tag if add_footer is true' do
|
188
|
-
expect(Bullet).to receive(:add_footer).at_least(:once).and_return(true)
|
189
|
-
_, headers, response = middleware.call({})
|
190
|
-
|
191
|
-
expect(headers['Content-Length']).to eq((56 + middleware.send(:footer_note).length).to_s)
|
192
|
-
expect(response).to eq(%w[<html><head></head><body>footer<bullet></bullet></body></html>])
|
193
|
-
end
|
194
|
-
|
195
|
-
it 'should not include the xhr script tag if console_enabled is true' do
|
196
|
-
expect(Bullet).to receive(:console_enabled?).and_return(true)
|
197
|
-
_, headers, response = middleware.call({})
|
198
|
-
expect(headers['Content-Length']).to eq('56')
|
199
|
-
expect(response).to eq(%w[<html><head></head><body><bullet></bullet></body></html>])
|
200
|
-
end
|
201
|
-
|
202
|
-
it 'should not add the footer-text header for non-html requests when add_footer is true' do
|
203
|
-
allow(Bullet).to receive(:add_footer).at_least(:once).and_return(true)
|
204
|
-
app.headers = { 'Content-Type' => 'application/json' }
|
205
|
-
_, headers, _response = middleware.call({})
|
206
|
-
expect(headers).not_to include('X-bullet-footer-text')
|
207
|
-
end
|
208
|
-
|
209
|
-
it 'should not add headers for non-html requests when console_enabled is true' do
|
210
|
-
allow(Bullet).to receive(:console_enabled?).at_least(:once).and_return(true)
|
211
|
-
app.headers = { 'Content-Type' => 'application/json' }
|
212
|
-
_, headers, _response = middleware.call({})
|
213
|
-
expect(headers).not_to include('X-bullet-console-text')
|
214
|
-
end
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
|
-
context 'when skip_html_injection is enabled' do
|
219
|
-
it 'should not try to inject html' do
|
220
|
-
expected_response = Support::ResponseDouble.new 'Actual body'
|
221
|
-
app.response = expected_response
|
222
|
-
allow(Bullet).to receive(:notification?).and_return(true)
|
223
|
-
allow(Bullet).to receive(:skip_html_injection?).and_return(true)
|
224
|
-
expect(Bullet).to receive(:gather_inline_notifications).never
|
225
|
-
expect(middleware).to receive(:xhr_script).never
|
226
|
-
expect(Bullet).to receive(:perform_out_of_channel_notifications)
|
227
|
-
_, _, response = middleware.call('Content-Type' => 'text/html')
|
228
|
-
expect(response).to eq(expected_response)
|
229
|
-
end
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
|
-
context 'when Bullet is disabled' do
|
234
|
-
before(:each) { allow(Bullet).to receive(:enable?).and_return(false) }
|
235
|
-
|
236
|
-
it 'should not call Bullet.start_request' do
|
237
|
-
expect(Bullet).not_to receive(:start_request)
|
238
|
-
middleware.call({})
|
239
|
-
end
|
240
|
-
end
|
241
|
-
end
|
242
|
-
|
243
|
-
context '#set_header' do
|
244
|
-
it 'should truncate headers to under 8kb' do
|
245
|
-
long_header = ['a' * 1_024] * 10
|
246
|
-
expected_res = (['a' * 1_024] * 7).to_json
|
247
|
-
expect(middleware.set_header({}, 'Dummy-Header', long_header)).to eq(expected_res)
|
248
|
-
end
|
249
|
-
end
|
250
|
-
|
251
|
-
describe '#response_body' do
|
252
|
-
let(:response) { double }
|
253
|
-
let(:body_string) { '<html><body>My Body</body></html>' }
|
254
|
-
|
255
|
-
context 'when `response` responds to `body`' do
|
256
|
-
before { allow(response).to receive(:body).and_return(body) }
|
257
|
-
|
258
|
-
context 'when `body` returns an Array' do
|
259
|
-
let(:body) { [body_string, 'random string'] }
|
260
|
-
it 'should return the plain body string' do
|
261
|
-
expect(middleware.response_body(response)).to eq body_string
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
265
|
-
context 'when `body` does not return an Array' do
|
266
|
-
let(:body) { body_string }
|
267
|
-
it 'should return the plain body string' do
|
268
|
-
expect(middleware.response_body(response)).to eq body_string
|
269
|
-
end
|
270
|
-
end
|
271
|
-
end
|
272
|
-
|
273
|
-
context 'when `response` does not respond to `body`' do
|
274
|
-
before { allow(response).to receive(:first).and_return(body_string) }
|
275
|
-
|
276
|
-
it 'should return the plain body string' do
|
277
|
-
expect(middleware.response_body(response)).to eq body_string
|
278
|
-
end
|
279
|
-
end
|
280
|
-
|
281
|
-
begin
|
282
|
-
require 'rack/files'
|
283
|
-
|
284
|
-
context 'when `response` is a Rack::Files::Iterator' do
|
285
|
-
let(:response) { instance_double(::Rack::Files::Iterator) }
|
286
|
-
before { allow(response).to receive(:is_a?).with(::Rack::Files::Iterator) { true } }
|
287
|
-
|
288
|
-
it 'should return nil' do
|
289
|
-
expect(middleware.response_body(response)).to be_nil
|
290
|
-
end
|
291
|
-
end
|
292
|
-
rescue LoadError
|
293
|
-
end
|
294
|
-
end
|
295
|
-
end
|
296
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
module Bullet
|
6
|
-
module Registry
|
7
|
-
describe Association do
|
8
|
-
subject { Association.new.tap { |association| association.add(%w[key1 key2], 'value') } }
|
9
|
-
|
10
|
-
context '#merge' do
|
11
|
-
it 'should merge key/value' do
|
12
|
-
subject.merge('key0', 'value0')
|
13
|
-
expect(subject['key0']).to be_include('value0')
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
context '#similarly_associated' do
|
18
|
-
it 'should return similarly associated keys' do
|
19
|
-
expect(subject.similarly_associated('key1', Set.new(%w[value]))).to eq(%w[key1 key2])
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'should return empty if key does not exist' do
|
23
|
-
expect(subject.similarly_associated('key3', Set.new(%w[value]))).to be_empty
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
@@ -1,46 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
module Bullet
|
6
|
-
module Registry
|
7
|
-
describe Base do
|
8
|
-
subject { Base.new.tap { |base| base.add('key', 'value') } }
|
9
|
-
|
10
|
-
context '#[]' do
|
11
|
-
it 'should get value by key' do
|
12
|
-
expect(subject['key']).to eq(Set.new(%w[value]))
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
context '#delete' do
|
17
|
-
it 'should delete key' do
|
18
|
-
subject.delete('key')
|
19
|
-
expect(subject['key']).to be_nil
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
context '#add' do
|
24
|
-
it 'should add value with string' do
|
25
|
-
subject.add('key', 'new_value')
|
26
|
-
expect(subject['key']).to eq(Set.new(%w[value new_value]))
|
27
|
-
end
|
28
|
-
|
29
|
-
it 'should add value with array' do
|
30
|
-
subject.add('key', %w[value1 value2])
|
31
|
-
expect(subject['key']).to eq(Set.new(%w[value value1 value2]))
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
context '#include?' do
|
36
|
-
it 'should include key/value' do
|
37
|
-
expect(subject.include?('key', 'value')).to eq true
|
38
|
-
end
|
39
|
-
|
40
|
-
it 'should not include wrong key/value' do
|
41
|
-
expect(subject.include?('key', 'val')).to eq false
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
module Bullet
|
6
|
-
module Registry
|
7
|
-
describe Object do
|
8
|
-
let(:post) { Post.first }
|
9
|
-
let(:another_post) { Post.last }
|
10
|
-
subject { Object.new.tap { |object| object.add(post.bullet_key) } }
|
11
|
-
|
12
|
-
context '#include?' do
|
13
|
-
it 'should include the object' do
|
14
|
-
expect(subject).to be_include(post.bullet_key)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
context '#add' do
|
19
|
-
it 'should add an object' do
|
20
|
-
subject.add(another_post.bullet_key)
|
21
|
-
expect(subject).to be_include(another_post.bullet_key)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
module Bullet
|
6
|
-
RSpec.describe StackTraceFilter do
|
7
|
-
let(:dummy_class) { Class.new { extend StackTraceFilter } }
|
8
|
-
let(:root_path) { Dir.pwd }
|
9
|
-
let(:bundler_path) { Bundler.bundle_path }
|
10
|
-
|
11
|
-
describe '#caller_in_project' do
|
12
|
-
it 'gets the caller in the project' do
|
13
|
-
expect(dummy_class).to receive(:call_stacks).and_return({
|
14
|
-
'Post:1' => [
|
15
|
-
File.join(root_path, 'lib/bullet.rb'),
|
16
|
-
File.join(root_path, 'vendor/uniform_notifier.rb'),
|
17
|
-
File.join(bundler_path, 'rack.rb')
|
18
|
-
]
|
19
|
-
})
|
20
|
-
expect(dummy_class.caller_in_project('Post:1')).to eq([
|
21
|
-
File.join(root_path, 'lib/bullet.rb')
|
22
|
-
])
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|