impressionist-cody 2.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.
Files changed (150) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/main.yml +25 -0
  3. data/.gitignore +17 -0
  4. data/.rspec +1 -0
  5. data/.rubocop.yml +27 -0
  6. data/.rubocop_todo.yml +660 -0
  7. data/CHANGELOG.rdoc +96 -0
  8. data/Gemfile +22 -0
  9. data/LICENSE.txt +20 -0
  10. data/README.md +265 -0
  11. data/Rakefile +20 -0
  12. data/UPGRADE_GUIDE.md +13 -0
  13. data/app/assets/config/manifest.js +3 -0
  14. data/app/controllers/impressionist_controller.rb +166 -0
  15. data/app/models/impression.rb +2 -0
  16. data/app/models/impressionist/bots.rb +1468 -0
  17. data/app/models/impressionist/impressionable.rb +62 -0
  18. data/impressionist.gemspec +30 -0
  19. data/lib/generators/active_record/impressionist_generator.rb +22 -0
  20. data/lib/generators/active_record/templates/create_impressions_table.rb.erb +32 -0
  21. data/lib/generators/impressionist_generator.rb +13 -0
  22. data/lib/generators/mongo_mapper/impressionist_generator.rb +8 -0
  23. data/lib/generators/mongoid/impressionist_generator.rb +8 -0
  24. data/lib/generators/templates/impression.rb.erb +8 -0
  25. data/lib/impressionist/bots.rb +21 -0
  26. data/lib/impressionist/controllers/mongoid/impressionist_controller.rb +10 -0
  27. data/lib/impressionist/counter_cache.rb +76 -0
  28. data/lib/impressionist/engine.rb +45 -0
  29. data/lib/impressionist/is_impressionable.rb +23 -0
  30. data/lib/impressionist/load.rb +11 -0
  31. data/lib/impressionist/models/active_record/impression.rb +14 -0
  32. data/lib/impressionist/models/active_record/impressionist/impressionable.rb +12 -0
  33. data/lib/impressionist/models/mongo_mapper/impression.rb +18 -0
  34. data/lib/impressionist/models/mongo_mapper/impressionist/impressionable.rb +21 -0
  35. data/lib/impressionist/models/mongoid/impression.rb +26 -0
  36. data/lib/impressionist/models/mongoid/impressionist/impressionable.rb +28 -0
  37. data/lib/impressionist/rails_toggle.rb +26 -0
  38. data/lib/impressionist/setup_association.rb +53 -0
  39. data/lib/impressionist/update_counters.rb +77 -0
  40. data/lib/impressionist/version.rb +3 -0
  41. data/lib/impressionist.rb +12 -0
  42. data/logo.png +0 -0
  43. data/spec/controllers/articles_controller_spec.rb +113 -0
  44. data/spec/controllers/dummy_controller_spec.rb +13 -0
  45. data/spec/controllers/impressionist_uniqueness_spec.rb +463 -0
  46. data/spec/controllers/posts_controller_spec.rb +36 -0
  47. data/spec/controllers/widgets_controller_spec.rb +103 -0
  48. data/spec/counter_caching_spec.rb +49 -0
  49. data/spec/dummy/.ruby-version +1 -0
  50. data/spec/dummy/Rakefile +6 -0
  51. data/spec/dummy/app/assets/config/manifest.js +1 -0
  52. data/spec/dummy/app/assets/images/.keep +0 -0
  53. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  54. data/spec/dummy/app/channels/application_cable/channel.rb +4 -0
  55. data/spec/dummy/app/channels/application_cable/connection.rb +4 -0
  56. data/spec/dummy/app/controllers/application_controller.rb +2 -0
  57. data/spec/dummy/app/controllers/articles_controller.rb +22 -0
  58. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  59. data/spec/dummy/app/controllers/dummy_controller.rb +6 -0
  60. data/spec/dummy/app/controllers/posts_controller.rb +23 -0
  61. data/spec/dummy/app/controllers/profiles_controller.rb +14 -0
  62. data/spec/dummy/app/controllers/widgets_controller.rb +12 -0
  63. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  64. data/spec/dummy/app/javascript/packs/application.js +15 -0
  65. data/spec/dummy/app/jobs/application_job.rb +7 -0
  66. data/spec/dummy/app/mailers/application_mailer.rb +4 -0
  67. data/spec/dummy/app/models/application_record.rb +3 -0
  68. data/spec/dummy/app/models/article.rb +3 -0
  69. data/spec/dummy/app/models/concerns/.keep +0 -0
  70. data/spec/dummy/app/models/dummy.rb +7 -0
  71. data/spec/dummy/app/models/post.rb +3 -0
  72. data/spec/dummy/app/models/profile.rb +6 -0
  73. data/spec/dummy/app/models/user.rb +3 -0
  74. data/spec/dummy/app/models/widget.rb +3 -0
  75. data/spec/dummy/app/views/articles/index.html.erb +1 -0
  76. data/spec/dummy/app/views/articles/show.html.erb +1 -0
  77. data/spec/dummy/app/views/dummy/index.html.erb +0 -0
  78. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  79. data/spec/dummy/app/views/layouts/mailer.html.erb +13 -0
  80. data/spec/dummy/app/views/layouts/mailer.text.erb +1 -0
  81. data/spec/dummy/app/views/posts/edit.html.erb +0 -0
  82. data/spec/dummy/app/views/posts/index.html.erb +0 -0
  83. data/spec/dummy/app/views/posts/show.html.erb +0 -0
  84. data/spec/dummy/app/views/profiles/show.html.erb +3 -0
  85. data/spec/dummy/app/views/widgets/index.html.erb +0 -0
  86. data/spec/dummy/app/views/widgets/new.html.erb +0 -0
  87. data/spec/dummy/app/views/widgets/show.html.erb +0 -0
  88. data/spec/dummy/bin/rails +4 -0
  89. data/spec/dummy/bin/rake +4 -0
  90. data/spec/dummy/bin/setup +33 -0
  91. data/spec/dummy/config/application.rb +20 -0
  92. data/spec/dummy/config/boot.rb +5 -0
  93. data/spec/dummy/config/cable.yml +10 -0
  94. data/spec/dummy/config/database.yml +25 -0
  95. data/spec/dummy/config/environment.rb +5 -0
  96. data/spec/dummy/config/environments/development.rb +62 -0
  97. data/spec/dummy/config/environments/production.rb +112 -0
  98. data/spec/dummy/config/environments/test.rb +49 -0
  99. data/spec/dummy/config/initializers/application_controller_renderer.rb +8 -0
  100. data/spec/dummy/config/initializers/assets.rb +12 -0
  101. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  102. data/spec/dummy/config/initializers/content_security_policy.rb +28 -0
  103. data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
  104. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  105. data/spec/dummy/config/initializers/impression.rb +8 -0
  106. data/spec/dummy/config/initializers/inflections.rb +16 -0
  107. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  108. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  109. data/spec/dummy/config/locales/en.yml +33 -0
  110. data/spec/dummy/config/puma.rb +38 -0
  111. data/spec/dummy/config/routes.rb +4 -0
  112. data/spec/dummy/config/spring.rb +6 -0
  113. data/spec/dummy/config/storage.yml +34 -0
  114. data/spec/dummy/config.ru +5 -0
  115. data/spec/dummy/config.ru2 +4 -0
  116. data/spec/dummy/db/development.sqlite3 +0 -0
  117. data/spec/dummy/db/migrate/20110201153144_create_articles.rb +13 -0
  118. data/spec/dummy/db/migrate/20110210205028_create_posts.rb +13 -0
  119. data/spec/dummy/db/migrate/20111127184039_create_widgets.rb +15 -0
  120. data/spec/dummy/db/migrate/20150207135825_create_profiles.rb +10 -0
  121. data/spec/dummy/db/migrate/20150207140310_create_friendly_id_slugs.rb +18 -0
  122. data/spec/dummy/db/migrate/20200720143817_create_impressions_table.rb +32 -0
  123. data/spec/dummy/db/schema.rb +77 -0
  124. data/spec/dummy/lib/assets/.keep +0 -0
  125. data/spec/dummy/log/.keep +0 -0
  126. data/spec/dummy/log/development.log +129 -0
  127. data/spec/dummy/public/404.html +67 -0
  128. data/spec/dummy/public/422.html +67 -0
  129. data/spec/dummy/public/500.html +66 -0
  130. data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
  131. data/spec/dummy/public/apple-touch-icon.png +0 -0
  132. data/spec/dummy/public/favicon.ico +0 -0
  133. data/spec/dummy/storage/.keep +0 -0
  134. data/spec/fixtures/articles.yml +3 -0
  135. data/spec/fixtures/impressions.yml +43 -0
  136. data/spec/fixtures/posts.yml +3 -0
  137. data/spec/fixtures/profiles.yml +4 -0
  138. data/spec/fixtures/widgets.yml +4 -0
  139. data/spec/initializers_spec.rb +21 -0
  140. data/spec/models/bots_spec.rb +25 -0
  141. data/spec/models/impression_spec.rb +66 -0
  142. data/spec/rails_generators/rails_generators_spec.rb +23 -0
  143. data/spec/rails_helper.rb +11 -0
  144. data/spec/rails_toggle_spec.rb +31 -0
  145. data/spec/setup_association_spec.rb +48 -0
  146. data/spec/spec_helper.rb +43 -0
  147. data/upgrade_migrations/version_0_3_0.rb +27 -0
  148. data/upgrade_migrations/version_0_4_0.rb +9 -0
  149. data/upgrade_migrations/version_1_5_2.rb +12 -0
  150. metadata +302 -0
@@ -0,0 +1,12 @@
1
+ require 'impressionist/load'
2
+
3
+ module Impressionist
4
+ # Define default ORM
5
+ mattr_accessor :orm
6
+ @@orm = :active_record
7
+
8
+ # Load configuration from initializer
9
+ def self.setup
10
+ yield self
11
+ end
12
+ end
data/logo.png ADDED
Binary file
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: false
2
+
3
+ require 'spec_helper'
4
+
5
+ describe ArticlesController, type: :controller do
6
+ fixtures :articles, :impressions, :posts, :widgets
7
+
8
+ render_views
9
+
10
+ it 'makes the impressionable_hash available' do
11
+ get :index
12
+ expect(response.body).to include('false')
13
+ end
14
+
15
+ it 'logs an impression with a message' do
16
+ get 'index'
17
+
18
+ latest_impression = Article.first.impressions.last
19
+
20
+ expect(Impression.all.size).to eq 12
21
+
22
+ expect(latest_impression.message).to eq 'this is a test article impression'
23
+ expect(latest_impression.controller_name).to eq 'articles'
24
+ expect(latest_impression.action_name).to eq 'index'
25
+ end
26
+
27
+ it 'logs an impression without a message' do
28
+ get :show, params: { id: 1 }
29
+
30
+ latest_impression = Article.first.impressions.last
31
+
32
+ expect(Impression.all.size).to eq 12
33
+
34
+ expect(latest_impression.message).to eq nil
35
+ expect(latest_impression.controller_name).to eq 'articles'
36
+ expect(latest_impression.action_name).to eq 'show'
37
+ end
38
+
39
+ it 'logs the user_id if user is authenticated (@current_user before_action method)' do
40
+ session[:user_id] = 123
41
+ get :show, params: { id: 1 }
42
+
43
+ expect(Article.first.impressions.last.user_id).to eq 123
44
+ end
45
+
46
+ it 'does not log the user_id if user is authenticated' do
47
+ get :show, params: { id: 1 }
48
+
49
+ expect(Article.first.impressions.last.user_id).to eq nil
50
+ end
51
+
52
+ it 'logs the request_hash, ip_address, referrer and session_hash' do
53
+ get :show, params: { id: 1 }
54
+
55
+ impression = Impression.last
56
+
57
+ expect(impression.request_hash.size).to eq 64
58
+ expect(impression.ip_address).to eq '0.0.0.0'
59
+ expect(impression.session_hash.size).to eq 32
60
+ expect(impression.referrer).to eq nil
61
+ end
62
+
63
+ # Capybara has change the way it works
64
+ # We need to pass :type options in order to make include helper methods
65
+ # see https://github.com/jnicklas/capybara#using-capybara-with-rspec
66
+ it 'logs the referrer when you click a link', type: :feature do
67
+ default_url_options[:host] = "test.host"
68
+
69
+ visit article_url(Article.first)
70
+ click_link 'Same Page'
71
+ expect(Impression.last.referrer).to eq 'http://test.host/articles/1'
72
+ end
73
+
74
+ it 'logs request with params (checked = true)' do
75
+ get :show, params: { id: 1, checked: true }
76
+
77
+ impression = Impression.last
78
+
79
+ expect(impression.params).to eq({ 'checked' => "true" })
80
+ expect(impression.request_hash.size).to eq 64
81
+ expect(impression.ip_address).to eq '0.0.0.0'
82
+ expect(impression.session_hash.size).to eq 32
83
+ expect(impression.referrer).to eq nil
84
+ end
85
+
86
+ it 'logs request with params: {}' do
87
+ get 'index'
88
+
89
+ impression = Impression.last
90
+
91
+ expect(impression.params).to eq({})
92
+ expect(impression.request_hash.size).to eq 64
93
+ expect(impression.ip_address).to eq '0.0.0.0'
94
+ expect(impression.session_hash.size).to eq 32
95
+ expect(impression.referrer).to eq nil
96
+ end
97
+
98
+ describe 'when filtering params' do
99
+ before do
100
+ @_filtered_params = Rails.application.config.filter_parameters
101
+ Rails.application.config.filter_parameters = [:password]
102
+ end
103
+
104
+ after do
105
+ Rails.application.config.filter_parameters = @_filtered_params
106
+ end
107
+
108
+ it 'values should not be recorded' do
109
+ get 'index', params: { password: 'best-password-ever' }
110
+ expect(Impression.last.params).to eq('password' => '[FILTERED]')
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: false
2
+
3
+ require 'spec_helper'
4
+
5
+ describe DummyController, type: :controller do
6
+ fixtures :impressions
7
+ render_views
8
+
9
+ it 'logs impression at the per action level on non-restful controller' do
10
+ get 'index'
11
+ expect(Impression.all.size).to eq 12
12
+ end
13
+ end
@@ -0,0 +1,463 @@
1
+ require 'spec_helper'
2
+
3
+ # we use the posts controller as it uses the impressionsist module. any such controller would do.
4
+ describe DummyController do
5
+ before do
6
+ @impression_count = Impression.all.size
7
+ end
8
+
9
+ describe "impressionist filter uniqueness" do
10
+ it "ignore uniqueness if not requested" do
11
+ controller.impressionist_subapp_filter
12
+ controller.impressionist_subapp_filter
13
+
14
+ expect(Impression.count).to eq(@impression_count + 2)
15
+ end
16
+
17
+ it "recognize unique session" do
18
+ allow(controller).to receive(:session_hash).and_return(request.session_options[:id])
19
+
20
+ controller.impressionist_subapp_filter(unique: [:session_hash])
21
+ controller.impressionist_subapp_filter(unique: [:session_hash])
22
+
23
+ expect(Impression.count).to eq(@impression_count + 1)
24
+ end
25
+
26
+ it "recognize unique ip" do
27
+ allow(controller).to receive(:remote_ip).and_return("1.2.3.4")
28
+
29
+ controller.impressionist_subapp_filter(unique: [:ip_address])
30
+ controller.impressionist_subapp_filter(unique: [:ip_address])
31
+
32
+ expect(Impression.count).to equal(@impression_count + 1)
33
+ end
34
+
35
+ it "recognize unique request" do
36
+ controller.impressionist_subapp_filter(unique: [:request_hash])
37
+ controller.impressionist_subapp_filter(unique: [:request_hash])
38
+
39
+ expect(Impression.count).to equal(@impression_count + 1)
40
+ end
41
+
42
+ it "recognize unique action" do
43
+ allow(controller).to receive(:action_name).and_return("test_action")
44
+
45
+ controller.impressionist_subapp_filter(unique: [:action_name])
46
+ controller.impressionist_subapp_filter(unique: [:action_name])
47
+
48
+ expect(Impression.count).to equal(@impression_count + 1)
49
+ end
50
+
51
+ it "recognize unique controller" do
52
+ allow(controller).to receive(:controller_name).and_return("post")
53
+
54
+ controller.impressionist_subapp_filter(unique: [:controller_name])
55
+ controller.impressionist_subapp_filter(unique: [:controller_name])
56
+ expect(Impression.count).to equal(@impression_count + 1)
57
+ end
58
+
59
+ it "recognize unique user" do
60
+ allow(controller).to receive(:user_id).and_return(42)
61
+
62
+ controller.impressionist_subapp_filter(unique: [:user_id])
63
+ controller.impressionist_subapp_filter(unique: [:user_id])
64
+
65
+ expect(Impression.count).to equal(@impression_count + 1)
66
+ end
67
+
68
+ it "recognize unique referer" do
69
+ allow(controller.request).to receive(:referer).and_return("http://foo/bar")
70
+
71
+ controller.impressionist_subapp_filter(unique: [:referrer])
72
+ controller.impressionist_subapp_filter(unique: [:referrer])
73
+
74
+ expect(Impression.count).to equal(@impression_count + 1)
75
+ end
76
+
77
+ it "recognize unique id" do
78
+ allow(controller).to receive(:params).and_return({ :id => "666" }) # for correct impressionable id in filter
79
+
80
+ controller.impressionist_subapp_filter(unique: [:impressionable_id])
81
+ controller.impressionist_subapp_filter(unique: [:impressionable_id])
82
+ expect(Impression.count).to equal(@impression_count + 1)
83
+ end
84
+
85
+ # extra redundant test for important controller and action combination.
86
+ it "recognize different controller and action" do
87
+ allow(controller).to receive(:controller_name).and_return("post")
88
+ allow(controller).to receive(:action_name).and_return("test_action")
89
+
90
+ controller.impressionist_subapp_filter(unique: [:controller_name, :action_name])
91
+ controller.impressionist_subapp_filter(unique: [:controller_name, :action_name])
92
+
93
+ expect(Impression.count).to equal(@impression_count + 1)
94
+
95
+ allow(controller).to receive(:action_name).and_return("another_action")
96
+
97
+ controller.impressionist_subapp_filter(unique: [:controller_name, :action_name])
98
+ controller.impressionist_subapp_filter(unique: [:controller_name, :action_name])
99
+
100
+ expect(Impression.count).to equal(@impression_count + 2)
101
+
102
+ allow(controller).to receive(:controller_name).and_return("article")
103
+
104
+ controller.impressionist_subapp_filter(unique: [:controller_name, :action_name])
105
+ controller.impressionist_subapp_filter(unique: [:controller_name, :action_name])
106
+
107
+ expect(Impression.count).to equal(@impression_count + 3)
108
+ end
109
+
110
+ it "recognize different action" do
111
+ allow(controller).to receive(:action_name).and_return("test_action")
112
+ controller.impressionist_subapp_filter(unique: [:action_name])
113
+ controller.impressionist_subapp_filter(unique: [:action_name])
114
+ expect(Impression.count).to equal(@impression_count + 1)
115
+ allow(controller).to receive(:action_name).and_return("another_action")
116
+ controller.impressionist_subapp_filter(unique: [:action_name])
117
+ controller.impressionist_subapp_filter(unique: [:action_name])
118
+ expect(Impression.count).to equal(@impression_count + 2)
119
+ end
120
+
121
+ it "recognize different controller" do
122
+ allow(controller).to receive(:controller_name).and_return("post")
123
+ controller.impressionist_subapp_filter(unique: [:controller_name])
124
+ controller.impressionist_subapp_filter(unique: [:controller_name])
125
+ expect(Impression.count).to equal(@impression_count + 1)
126
+ allow(controller).to receive(:controller_name).and_return("article")
127
+ controller.impressionist_subapp_filter(unique: [:controller_name])
128
+ controller.impressionist_subapp_filter(unique: [:controller_name])
129
+ expect(Impression.count).to equal(@impression_count + 2)
130
+ end
131
+
132
+ it "recognize different session" do
133
+ allow(controller).to receive(:session_hash).and_return("foo")
134
+ controller.impressionist_subapp_filter(unique: [:session_hash])
135
+ controller.impressionist_subapp_filter(unique: [:session_hash])
136
+ expect(Impression.count).to equal(@impression_count + 1)
137
+ allow(controller).to receive(:session_hash).and_return("bar")
138
+ controller.impressionist_subapp_filter(unique: [:session_hash])
139
+ controller.impressionist_subapp_filter(unique: [:session_hash])
140
+ expect(Impression.count).to equal(@impression_count + 2)
141
+ end
142
+
143
+ it "recognize different ip" do
144
+ allow(controller.request).to receive(:remote_ip).and_return("1.2.3.4")
145
+
146
+ controller.impressionist_subapp_filter(unique: [:ip_address])
147
+ controller.impressionist_subapp_filter(unique: [:ip_address])
148
+
149
+ expect(Impression.count).to equal(@impression_count + 1)
150
+
151
+ allow(controller.request).to receive(:remote_ip).and_return("5.6.7.8")
152
+
153
+ controller.impressionist_subapp_filter(unique: [:ip_address])
154
+ controller.impressionist_subapp_filter(unique: [:ip_address])
155
+
156
+ expect(Impression.count).to equal(@impression_count + 2)
157
+ end
158
+
159
+ it "recognize different referer" do
160
+ allow(controller.request).to receive(:referer).and_return("http://foo/bar")
161
+
162
+ controller.impressionist_subapp_filter(unique: [:referrer])
163
+ controller.impressionist_subapp_filter(unique: [:referrer])
164
+
165
+ expect(Impression.count).to equal(@impression_count + 1)
166
+
167
+ allow(controller.request).to receive(:referer).and_return("http://bar/fo")
168
+
169
+ controller.impressionist_subapp_filter(unique: [:referrer])
170
+ controller.impressionist_subapp_filter(unique: [:referrer])
171
+ expect(Impression.count).to equal(@impression_count + 2)
172
+ end
173
+
174
+ it "recognize different id" do
175
+ allow(controller).to receive(:params).and_return({ :id => "666" }) # for correct impressionable id in filter
176
+
177
+ controller.impressionist_subapp_filter(unique: [:impressionable_type, :impressionable_id])
178
+ controller.impressionist_subapp_filter(unique: [:impressionable_type, :impressionable_id])
179
+
180
+ allow(controller).to receive(:params).and_return({ :id => "42" }) # for correct impressionable id in filter
181
+
182
+ controller.impressionist_subapp_filter(unique: [:impressionable_type, :impressionable_id])
183
+ controller.impressionist_subapp_filter(unique: [:impressionable_type, :impressionable_id])
184
+
185
+ expect(Impression.count).to equal(@impression_count + 2)
186
+ end
187
+
188
+ it "recognize combined uniqueness" do
189
+ allow(controller).to receive(:action_name).and_return("test_action")
190
+
191
+ controller.impressionist_subapp_filter(unique: [:ip_address, :request_hash, :action_name])
192
+ controller.impressionist_subapp_filter(unique: [:request_hash, :ip_address, :action_name])
193
+ controller.impressionist_subapp_filter(unique: [:request_hash, :action_name])
194
+ controller.impressionist_subapp_filter(unique: [:ip_address, :action_name])
195
+ controller.impressionist_subapp_filter(unique: [:ip_address, :request_hash])
196
+ controller.impressionist_subapp_filter(unique: [:action_name])
197
+ controller.impressionist_subapp_filter(unique: [:ip_address])
198
+ controller.impressionist_subapp_filter(unique: [:request_hash])
199
+
200
+ expect(Impression.count).to equal(@impression_count + 1)
201
+ end
202
+
203
+ it "recognize combined non-uniqueness" do
204
+ allow(controller).to receive(:action_name).and_return(nil)
205
+
206
+ controller.impressionist_subapp_filter(unique: [:ip_address, :action_name])
207
+
208
+ allow(controller).to receive(:action_name).and_return("test_action")
209
+
210
+ controller.impressionist_subapp_filter(unique: [:ip_address, :action_name])
211
+
212
+ allow(controller).to receive(:action_name).and_return("another_action")
213
+
214
+ controller.impressionist_subapp_filter(unique: [:ip_address, :action_name])
215
+
216
+ expect(Impression.count).to equal(@impression_count + 3)
217
+ end
218
+ end
219
+
220
+ describe "impressionist method uniqueness for impressionables" do
221
+ # in this test we reuse the post model. might break if model changes.
222
+
223
+ it "ignore uniqueness if not requested" do
224
+ impressionable = Post.create
225
+ controller.impressionist impressionable
226
+ controller.impressionist impressionable
227
+ expect(Impression.count).to equal(@impression_count + 2)
228
+ end
229
+
230
+ it "recognize unique session" do
231
+ allow(controller).to receive(:session_hash).and_return(request.session_options[:id])
232
+
233
+ impressionable = Post.create
234
+ controller.impressionist(impressionable, nil, :unique => [:session_hash])
235
+ controller.impressionist(impressionable, nil, :unique => [:session_hash])
236
+
237
+ expect(Impression.count).to equal(@impression_count + 1)
238
+ end
239
+
240
+ it "recognize unique ip" do
241
+ allow(controller.request).to receive(:remote_ip).and_return("1.2.3.4")
242
+
243
+ impressionable = Post.create
244
+ controller.impressionist(impressionable, nil, :unique => [:ip_address])
245
+ controller.impressionist(impressionable, nil, :unique => [:ip_address])
246
+
247
+ expect(Impression.count).to equal(@impression_count + 1)
248
+ end
249
+
250
+ it "recognize unique request" do
251
+ impressionable = Post.create
252
+ controller.impressionist(impressionable, nil, :unique => [:request_hash])
253
+ controller.impressionist(impressionable, nil, :unique => [:request_hash])
254
+
255
+ expect(Impression.count).to equal(@impression_count + 1)
256
+ end
257
+
258
+ it "recognize unique user" do
259
+ allow(controller).to receive(:user_id).and_return(666)
260
+
261
+ impressionable = Post.create
262
+ controller.impressionist(impressionable, nil, :unique => [:user_id])
263
+ controller.impressionist(impressionable, nil, :unique => [:user_id])
264
+
265
+ expect(Impression.count).to equal(@impression_count + 1)
266
+ end
267
+
268
+ it "recognize unique referer" do
269
+ allow(controller.request).to receive(:referer).and_return("http://foo/bar")
270
+
271
+ impressionable = Post.create
272
+ controller.impressionist(impressionable, nil, :unique => [:referrer])
273
+ controller.impressionist(impressionable, nil, :unique => [:referrer])
274
+
275
+ expect(Impression.count).to equal(@impression_count + 1)
276
+ end
277
+
278
+ it "recognize different session" do
279
+ impressionable = Post.create
280
+
281
+ allow(controller).to receive(:session_hash).and_return("foo")
282
+
283
+ controller.impressionist(impressionable, nil, :unique => [:session_hash])
284
+ controller.impressionist(impressionable, nil, :unique => [:session_hash])
285
+
286
+ expect(Impression.count).to equal(@impression_count + 1)
287
+
288
+ allow(controller).to receive(:session_hash).and_return("bar")
289
+
290
+ controller.impressionist(impressionable, nil, :unique => [:session_hash])
291
+ controller.impressionist(impressionable, nil, :unique => [:session_hash])
292
+
293
+ expect(Impression.count).to equal(@impression_count + 2)
294
+ end
295
+
296
+ it "recognize different ip" do
297
+ allow(controller.request).to receive(:remote_ip).and_return("1.2.3.4")
298
+
299
+ impressionable = Post.create
300
+ controller.impressionist(impressionable, nil, :unique => [:ip_address])
301
+ controller.impressionist(impressionable, nil, :unique => [:ip_address])
302
+
303
+ expect(Impression.count).to equal(@impression_count + 1)
304
+
305
+ allow(controller.request).to receive(:remote_ip).and_return("5.6.7.8")
306
+
307
+ controller.impressionist(impressionable, nil, :unique => [:ip_address])
308
+ controller.impressionist(impressionable, nil, :unique => [:ip_address])
309
+
310
+ expect(Impression.count).to equal(@impression_count + 2)
311
+ end
312
+
313
+ it "recognize different user" do
314
+ impressionable = Post.create
315
+
316
+ allow(controller).to receive(:user_id).and_return(666)
317
+
318
+ controller.impressionist(impressionable, nil, :unique => [:user_id])
319
+ controller.impressionist(impressionable, nil, :unique => [:user_id])
320
+
321
+ expect(Impression.count).to equal(@impression_count + 1)
322
+
323
+ allow(controller).to receive(:user_id).and_return(42)
324
+
325
+ controller.impressionist(impressionable, nil, :unique => [:user_id])
326
+ controller.impressionist(impressionable, nil, :unique => [:user_id])
327
+
328
+ expect(Impression.count).to equal(@impression_count + 2)
329
+ end
330
+
331
+ it "recognize combined uniqueness" do
332
+ impressionable = Post.create
333
+ allow(controller).to receive(:session_hash).and_return("foo")
334
+
335
+ controller.impressionist(impressionable, nil, :unique => [:ip_address, :request_hash, :session_hash])
336
+ controller.impressionist(impressionable, nil, :unique => [:request_hash, :ip_address, :session_hash])
337
+ controller.impressionist(impressionable, nil, :unique => [:request_hash, :session_hash])
338
+ controller.impressionist(impressionable, nil, :unique => [:ip_address, :session_hash])
339
+ controller.impressionist(impressionable, nil, :unique => [:ip_address, :request_hash])
340
+ controller.impressionist(impressionable, nil, :unique => [:session_hash])
341
+ controller.impressionist(impressionable, nil, :unique => [:ip_address])
342
+ controller.impressionist(impressionable, nil, :unique => [:request_hash])
343
+
344
+ expect(Impression.count).to equal(@impression_count + 1)
345
+ end
346
+
347
+ it "recognize combined non-uniqueness" do
348
+ impressionable = Post.create
349
+ allow(controller).to receive(:session_hash).and_return(nil)
350
+ controller.impressionist(impressionable, nil, :unique => [:ip_address, :session_hash])
351
+ allow(controller).to receive(:session_hash).and_return("foo")
352
+ controller.impressionist(impressionable, nil, :unique => [:ip_address, :session_hash])
353
+ allow(controller).to receive(:session_hash).and_return("bar")
354
+ controller.impressionist(impressionable, nil, :unique => [:ip_address, :session_hash])
355
+ expect(Impression.count).to equal(@impression_count + 3)
356
+ end
357
+ end
358
+
359
+ describe "impressionist filter and method uniqueness" do
360
+ it "recognize uniqueness" do
361
+ impressionable = Post.create
362
+ allow(controller).to receive(:controller_name).and_return("posts") # for correct impressionable type in filter
363
+ allow(controller).to receive(:params).and_return({ :id => impressionable.id.to_s }) # for correct impressionable id in filter
364
+ allow(controller).to receive(:session_hash).and_return("foo")
365
+ allow(controller.request).to receive(:remote_ip).and_return("1.2.3.4")
366
+ # order of the following methods is important for the test!
367
+ controller.impressionist_subapp_filter(unique: [:ip_address, :request_hash, :session_hash])
368
+ controller.impressionist(impressionable, nil, :unique => [:ip_address, :request_hash, :session_hash])
369
+ expect(Impression.count).to equal(@impression_count + 1)
370
+ end
371
+ end
372
+
373
+ describe 'impressionist with friendly id' do
374
+ it 'unique' do
375
+ impressionable = Profile.create({ username: 'test_profile', slug: 'test_profile' })
376
+
377
+ allow(controller).to receive(:controller_name).and_return('profile')
378
+ allow(controller).to receive(:action_name).and_return('show')
379
+ allow(controller).to receive(:params).and_return({ id: impressionable.slug })
380
+ allow(controller.request).to receive(:remote_ip).and_return('1.2.3.4')
381
+
382
+ controller.impressionist(impressionable, nil, :unique => [:impressionable_type, :impressionable_id])
383
+ controller.impressionist(impressionable, nil, :unique => [:impressionable_type, :impressionable_id])
384
+ expect(Impression.count).to equal(@impression_count + 1)
385
+ end
386
+ end
387
+
388
+ shared_examples_for 'an impressionable action' do
389
+ it 'record an impression' do
390
+ controller.impressionist_subapp_filter(condition)
391
+ expect(Impression.count).to equal(@impression_count + 1)
392
+ end
393
+ end
394
+
395
+ shared_examples_for 'an unimpressionable action' do
396
+ it 'record an impression' do
397
+ controller.impressionist_subapp_filter(condition)
398
+ expect(Impression.count).to equal(@impression_count)
399
+ end
400
+ end
401
+
402
+ describe "conditional impressions" do
403
+ describe ":if condition" do
404
+ context "true condition" do
405
+ before do
406
+ allow(controller).to receive(:true_condition).and_return(true)
407
+ end
408
+
409
+ it_behaves_like 'an impressionable action' do
410
+ let(:condition) { { if: :true_condition } }
411
+ end
412
+
413
+ it_behaves_like 'an impressionable action' do
414
+ let(:condition) { { if: -> { true } } }
415
+ end
416
+ end
417
+
418
+ context "false condition" do
419
+ before do
420
+ allow(controller).to receive(:false_condition).and_return(false)
421
+ end
422
+
423
+ it_behaves_like 'an unimpressionable action' do
424
+ let(:condition) { { if: :false_condition } }
425
+ end
426
+
427
+ it_behaves_like 'an unimpressionable action' do
428
+ let(:condition) { { if: -> { false } } }
429
+ end
430
+ end
431
+ end
432
+
433
+ describe ":unless condition" do
434
+ context "true condition" do
435
+ before do
436
+ allow(controller).to receive(:true_condition).and_return(true)
437
+ end
438
+
439
+ it_behaves_like 'an unimpressionable action' do
440
+ let(:condition) { { unless: :true_condition } }
441
+ end
442
+
443
+ it_behaves_like 'an unimpressionable action' do
444
+ let(:condition) { { unless: -> { true } } }
445
+ end
446
+ end
447
+
448
+ context "false condition" do
449
+ before do
450
+ allow(controller).to receive(:false_condition).and_return(false)
451
+ end
452
+
453
+ it_behaves_like 'an impressionable action' do
454
+ let(:condition) { { unless: :false_condition } }
455
+ end
456
+
457
+ it_behaves_like 'an impressionable action' do
458
+ let(:condition) { { unless: -> { false } } }
459
+ end
460
+ end
461
+ end
462
+ end
463
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe PostsController do
4
+ it "logs impression at the action level" do
5
+ get :show, params: { id: 1 }
6
+
7
+ expect(Impression.all.size).to eq 12
8
+
9
+ impression = Impression.last
10
+
11
+ expect(impression.controller_name).to eq "posts"
12
+ expect(impression.action_name).to eq "show"
13
+ expect(impression.impressionable_type).to eq "Post"
14
+ expect(impression.impressionable_id).to eq 1
15
+ end
16
+
17
+ it "logs the user_id if user is authenticated (current_user helper method)" do
18
+ session[:user_id] = 123
19
+ get :show, params: { id: 1 }
20
+ expect(Post.first.impressions.last.user_id).to eq 123
21
+ end
22
+
23
+ it "logs impression at the action level with params" do
24
+ get :show, params: { id: 1, checked: true }
25
+
26
+ expect(Impression.all.size).to eq 12
27
+
28
+ impression = Impression.last
29
+
30
+ expect(impression.params).to eq({ "checked" => "true" })
31
+ expect(impression.controller_name).to eq "posts"
32
+ expect(impression.action_name).to eq "show"
33
+ expect(impression.impressionable_type).to eq "Post"
34
+ expect(impression.impressionable_id).to eq 1
35
+ end
36
+ end