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.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -1
  3. data/README.md +3 -0
  4. data/lib/bullet/active_record4.rb +9 -0
  5. data/lib/bullet/active_record41.rb +9 -0
  6. data/lib/bullet/active_record42.rb +9 -0
  7. data/lib/bullet/active_record5.rb +11 -0
  8. data/lib/bullet/active_record52.rb +11 -0
  9. data/lib/bullet/active_record60.rb +11 -0
  10. data/lib/bullet/active_record61.rb +11 -0
  11. data/lib/bullet/active_record70.rb +19 -6
  12. data/lib/bullet/active_record71.rb +297 -0
  13. data/lib/bullet/dependency.rb +12 -0
  14. data/lib/bullet/detector/unused_eager_loading.rb +1 -1
  15. data/lib/bullet/mongoid8x.rb +59 -0
  16. data/lib/bullet/notification/counter_cache.rb +1 -1
  17. data/lib/bullet/rack.rb +1 -1
  18. data/lib/bullet/version.rb +1 -1
  19. data/lib/bullet.rb +6 -2
  20. metadata +7 -155
  21. data/.github/workflows/main.yml +0 -82
  22. data/.gitignore +0 -15
  23. data/.rspec +0 -2
  24. data/Gemfile +0 -24
  25. data/Gemfile.mongoid +0 -12
  26. data/Gemfile.mongoid-4.0 +0 -15
  27. data/Gemfile.mongoid-5.0 +0 -15
  28. data/Gemfile.mongoid-6.0 +0 -15
  29. data/Gemfile.mongoid-7.0 +0 -15
  30. data/Gemfile.rails-4.0 +0 -16
  31. data/Gemfile.rails-4.1 +0 -16
  32. data/Gemfile.rails-4.2 +0 -16
  33. data/Gemfile.rails-5.0 +0 -15
  34. data/Gemfile.rails-5.1 +0 -15
  35. data/Gemfile.rails-5.2 +0 -15
  36. data/Gemfile.rails-6.0 +0 -15
  37. data/Gemfile.rails-6.1 +0 -15
  38. data/Gemfile.rails-7.0 +0 -10
  39. data/Guardfile +0 -8
  40. data/Hacking.md +0 -75
  41. data/Rakefile +0 -51
  42. data/bullet.gemspec +0 -33
  43. data/perf/benchmark.rb +0 -118
  44. data/rails/init.rb +0 -3
  45. data/spec/bullet/detector/association_spec.rb +0 -28
  46. data/spec/bullet/detector/base_spec.rb +0 -10
  47. data/spec/bullet/detector/counter_cache_spec.rb +0 -58
  48. data/spec/bullet/detector/n_plus_one_query_spec.rb +0 -150
  49. data/spec/bullet/detector/unused_eager_loading_spec.rb +0 -126
  50. data/spec/bullet/ext/object_spec.rb +0 -44
  51. data/spec/bullet/ext/string_spec.rb +0 -15
  52. data/spec/bullet/notification/base_spec.rb +0 -94
  53. data/spec/bullet/notification/counter_cache_spec.rb +0 -14
  54. data/spec/bullet/notification/n_plus_one_query_spec.rb +0 -29
  55. data/spec/bullet/notification/unused_eager_loading_spec.rb +0 -18
  56. data/spec/bullet/notification_collector_spec.rb +0 -34
  57. data/spec/bullet/rack_spec.rb +0 -296
  58. data/spec/bullet/registry/association_spec.rb +0 -28
  59. data/spec/bullet/registry/base_spec.rb +0 -46
  60. data/spec/bullet/registry/object_spec.rb +0 -26
  61. data/spec/bullet/stack_trace_filter_spec.rb +0 -26
  62. data/spec/bullet_spec.rb +0 -136
  63. data/spec/integration/active_record/association_spec.rb +0 -822
  64. data/spec/integration/counter_cache_spec.rb +0 -68
  65. data/spec/integration/mongoid/association_spec.rb +0 -246
  66. data/spec/models/address.rb +0 -5
  67. data/spec/models/attachment.rb +0 -5
  68. data/spec/models/author.rb +0 -5
  69. data/spec/models/base_user.rb +0 -7
  70. data/spec/models/category.rb +0 -12
  71. data/spec/models/city.rb +0 -5
  72. data/spec/models/client.rb +0 -8
  73. data/spec/models/comment.rb +0 -8
  74. data/spec/models/company.rb +0 -5
  75. data/spec/models/country.rb +0 -5
  76. data/spec/models/deal.rb +0 -5
  77. data/spec/models/document.rb +0 -7
  78. data/spec/models/entry.rb +0 -5
  79. data/spec/models/firm.rb +0 -7
  80. data/spec/models/folder.rb +0 -4
  81. data/spec/models/group.rb +0 -4
  82. data/spec/models/mongoid/address.rb +0 -9
  83. data/spec/models/mongoid/category.rb +0 -10
  84. data/spec/models/mongoid/comment.rb +0 -9
  85. data/spec/models/mongoid/company.rb +0 -9
  86. data/spec/models/mongoid/entry.rb +0 -9
  87. data/spec/models/mongoid/post.rb +0 -14
  88. data/spec/models/mongoid/user.rb +0 -7
  89. data/spec/models/newspaper.rb +0 -5
  90. data/spec/models/page.rb +0 -4
  91. data/spec/models/person.rb +0 -5
  92. data/spec/models/pet.rb +0 -5
  93. data/spec/models/post.rb +0 -34
  94. data/spec/models/relationship.rb +0 -6
  95. data/spec/models/reply.rb +0 -5
  96. data/spec/models/role.rb +0 -7
  97. data/spec/models/student.rb +0 -5
  98. data/spec/models/submission.rb +0 -7
  99. data/spec/models/teacher.rb +0 -5
  100. data/spec/models/user.rb +0 -8
  101. data/spec/models/writer.rb +0 -4
  102. data/spec/spec_helper.rb +0 -97
  103. data/spec/support/bullet_ext.rb +0 -56
  104. data/spec/support/mongo_seed.rb +0 -59
  105. data/spec/support/rack_double.rb +0 -49
  106. data/spec/support/sqlite_seed.rb +0 -284
  107. data/test.sh +0 -15
  108. 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
@@ -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