activity_notification 1.0.0 → 1.0.1
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/Gemfile.lock +3 -3
- data/README.md +49 -9
- data/activity_notification.gemspec +1 -1
- data/app/controllers/activity_notification/notifications_controller.rb +75 -31
- data/app/mailers/activity_notification/mailer.rb +19 -4
- data/app/views/activity_notification/mailer/default/batch_default.html.erb +79 -0
- data/app/views/activity_notification/mailer/default/batch_default.text.erb +13 -0
- data/app/views/activity_notification/mailer/default/default.html.erb +75 -10
- data/app/views/activity_notification/mailer/default/default.text.erb +2 -2
- data/app/views/activity_notification/notifications/default/_default.html.erb +15 -14
- data/app/views/activity_notification/notifications/default/_default_without_grouping.html.erb +165 -0
- data/app/views/activity_notification/notifications/default/_index.html.erb +8 -4
- data/app/views/activity_notification/notifications/default/destroy.js.erb +2 -2
- data/app/views/activity_notification/notifications/default/index.html.erb +9 -5
- data/app/views/activity_notification/notifications/default/open.js.erb +6 -2
- data/app/views/activity_notification/notifications/default/open_all.js.erb +6 -2
- data/lib/activity_notification/apis/notification_api.rb +42 -9
- data/lib/activity_notification/helpers/view_helpers.rb +48 -19
- data/lib/activity_notification/mailers/helpers.rb +74 -37
- data/lib/activity_notification/models/concerns/target.rb +290 -26
- data/lib/activity_notification/models/notification.rb +85 -29
- data/lib/activity_notification/roles/acts_as_target.rb +4 -2
- data/lib/activity_notification/version.rb +1 -1
- data/spec/concerns/apis/notification_api_spec.rb +46 -0
- data/spec/concerns/models/target_spec.rb +281 -22
- data/spec/controllers/notifications_controller_shared_examples.rb +77 -0
- data/spec/helpers/view_helpers_spec.rb +39 -3
- data/spec/mailers/mailer_spec.rb +54 -1
- data/spec/models/notification_spec.rb +11 -0
- data/spec/rails_app/app/models/user.rb +1 -1
- data/spec/rails_app/app/views/layouts/_header.html.erb +2 -0
- data/spec/rails_app/lib/mailer_previews/mailer_preview.rb +6 -0
- data/spec/roles/acts_as_target_spec.rb +1 -1
- metadata +7 -4
@@ -50,31 +50,55 @@ module ActivityNotification
|
|
50
50
|
# Selects group owner notifications only.
|
51
51
|
# @scope class
|
52
52
|
# @return [ActiveRecord_AssociationRelation<Notificaion>] Array or database query of filtered notifications
|
53
|
-
scope :group_owners_only, ->
|
53
|
+
scope :group_owners_only, -> { where(group_owner_id: nil) }
|
54
54
|
|
55
55
|
# Selects group member notifications only.
|
56
56
|
# @scope class
|
57
57
|
# @return [ActiveRecord_AssociationRelation<Notificaion>] Array or database query of filtered notifications
|
58
|
-
scope :group_members_only, ->
|
58
|
+
scope :group_members_only, -> { where.not(group_owner_id: nil) }
|
59
|
+
|
60
|
+
# Selects all notification index.
|
61
|
+
# ActivityNotification::Notification.all_index!
|
62
|
+
# is defined same as
|
63
|
+
# ActivityNotification::Notification.group_owners_only.latest_order
|
64
|
+
# @example Get all notification index of the @user
|
65
|
+
# @notifications = @user.notifications.all_index!
|
66
|
+
# @notifications = @user.notifications.group_owners_only.latest_order
|
67
|
+
# @scope class
|
68
|
+
# @param [Boolean] reverse If notification index will be ordered as earliest first
|
69
|
+
# @param [Boolean] with_group_members If notification index will include group members
|
70
|
+
# @return [ActiveRecord_AssociationRelation<Notificaion>] Array or database query of filtered notifications
|
71
|
+
scope :all_index!, ->(reverse = false, with_group_members = false) {
|
72
|
+
target_index = with_group_members ? self : group_owners_only
|
73
|
+
reverse ? target_index.earliest_order : target_index.latest_order
|
74
|
+
}
|
59
75
|
|
60
76
|
# Selects unopened notifications only.
|
61
77
|
# @scope class
|
62
78
|
# @return [ActiveRecord_AssociationRelation<Notificaion>] Array or database query of filtered notifications
|
63
|
-
scope :unopened_only, ->
|
79
|
+
scope :unopened_only, -> { where(opened_at: nil) }
|
64
80
|
|
65
81
|
# Selects unopened notification index.
|
66
|
-
#
|
82
|
+
# ActivityNotification::Notification.unopened_index
|
83
|
+
# is defined same as
|
84
|
+
# ActivityNotification::Notification.unopened_only.group_owners_only.latest_order
|
67
85
|
# @example Get unopened notificaton index of the @user
|
68
|
-
# @notifications = @user.unopened_index
|
86
|
+
# @notifications = @user.notifications.unopened_index
|
87
|
+
# @notifications = @user.notifications.unopened_only.group_owners_only.latest_order
|
69
88
|
# @scope class
|
89
|
+
# @param [Boolean] reverse If notification index will be ordered as earliest first
|
90
|
+
# @param [Boolean] with_group_members If notification index will include group members
|
70
91
|
# @return [ActiveRecord_AssociationRelation<Notificaion>] Array or database query of filtered notifications
|
71
|
-
scope :unopened_index, ->
|
92
|
+
scope :unopened_index, ->(reverse = false, with_group_members = false) {
|
93
|
+
target_index = with_group_members ? unopened_only : unopened_only.group_owners_only
|
94
|
+
reverse ? target_index.earliest_order : target_index.latest_order
|
95
|
+
}
|
72
96
|
|
73
97
|
# Selects opened notifications only without limit.
|
74
98
|
# Be careful to get too many records with this method.
|
75
99
|
# @scope class
|
76
100
|
# @return [ActiveRecord_AssociationRelation<Notificaion>] Array or database query of filtered notifications
|
77
|
-
scope :opened_only!, ->
|
101
|
+
scope :opened_only!, -> { where.not(opened_at: nil) }
|
78
102
|
|
79
103
|
# Selects opened notifications only with limit.
|
80
104
|
# @scope class
|
@@ -83,16 +107,26 @@ module ActivityNotification
|
|
83
107
|
scope :opened_only, ->(limit) { opened_only!.limit(limit) }
|
84
108
|
|
85
109
|
# Selects unopened notification index.
|
86
|
-
#
|
110
|
+
# ActivityNotification::Notification.opened_index(limit)
|
111
|
+
# is defined same as
|
112
|
+
# ActivityNotification::Notification.opened_only(limit).group_owners_only.latest_order
|
113
|
+
# @example Get unopened notificaton index of the @user with limit 10
|
114
|
+
# @notifications = @user.notifications.opened_index(10)
|
115
|
+
# @notifications = @user.notifications.opened_only(10).group_owners_only.latest_order
|
87
116
|
# @scope class
|
88
117
|
# @param [Integer] limit Limit to query for opened notifications
|
118
|
+
# @param [Boolean] reverse If notification index will be ordered as earliest first
|
119
|
+
# @param [Boolean] with_group_members If notification index will include group members
|
89
120
|
# @return [ActiveRecord_AssociationRelation<Notificaion>] Array or database query of filtered notifications
|
90
|
-
scope :opened_index, ->(limit
|
121
|
+
scope :opened_index, ->(limit, reverse = false, with_group_members = false) {
|
122
|
+
target_index = with_group_members ? opened_only(limit) : opened_only(limit).group_owners_only
|
123
|
+
reverse ? target_index.earliest_order : target_index.latest_order
|
124
|
+
}
|
91
125
|
|
92
126
|
# Selects group member notifications in unopened_index.
|
93
127
|
# @scope class
|
94
128
|
# @return [ActiveRecord_AssociationRelation<Notificaion>] Array or database query of filtered notifications
|
95
|
-
scope :unopened_index_group_members_only, ->
|
129
|
+
scope :unopened_index_group_members_only, -> { where(group_owner_id: unopened_index.map(&:id)) }
|
96
130
|
|
97
131
|
# Selects group member notifications in opened_index.
|
98
132
|
# @scope class
|
@@ -107,7 +141,15 @@ module ActivityNotification
|
|
107
141
|
# @scope class
|
108
142
|
# @param [Object] target Target instance for filter
|
109
143
|
# @return [ActiveRecord_AssociationRelation<Notificaion>] Array or database query of filtered notifications
|
110
|
-
scope :filtered_by_target,
|
144
|
+
scope :filtered_by_target, ->(target) { where(target: target) }
|
145
|
+
|
146
|
+
# Selects filtered notifications by target_type.
|
147
|
+
# @example Get filtered unopened notificatons of User as target type
|
148
|
+
# @notifications = ActivityNotification.Notification.unopened_only.filtered_by_target_type('User')
|
149
|
+
# @scope class
|
150
|
+
# @param [String] target_type Target type for filter
|
151
|
+
# @return [ActiveRecord_AssociationRelation<Notificaion>] Array or database query of filtered notifications
|
152
|
+
scope :filtered_by_target_type, ->(target_type) { where(target_type: target_type) }
|
111
153
|
|
112
154
|
# Selects filtered notifications by notifiable instance.
|
113
155
|
# @example Get filtered unopened notificatons of the @user for @comment as notifiable
|
@@ -115,7 +157,7 @@ module ActivityNotification
|
|
115
157
|
# @scope class
|
116
158
|
# @param [Object] notifiable Notifiable instance for filter
|
117
159
|
# @return [ActiveRecord_AssociationRelation<Notificaion>] Array or database query of filtered notifications
|
118
|
-
scope :filtered_by_instance,
|
160
|
+
scope :filtered_by_instance, ->(notifiable) { where(notifiable: notifiable) }
|
119
161
|
|
120
162
|
# Selects filtered notifications by notifiable_type.
|
121
163
|
# @example Get filtered unopened notificatons of the @user for Comment notifiable class
|
@@ -123,7 +165,7 @@ module ActivityNotification
|
|
123
165
|
# @scope class
|
124
166
|
# @param [String] notifiable_type Notifiable type for filter
|
125
167
|
# @return [ActiveRecord_AssociationRelation<Notificaion>] Array or database query of filtered notifications
|
126
|
-
scope :filtered_by_type,
|
168
|
+
scope :filtered_by_type, ->(notifiable_type) { where(notifiable_type: notifiable_type) }
|
127
169
|
|
128
170
|
# Selects filtered notifications by group instance.
|
129
171
|
# @example Get filtered unopened notificatons of the @user for @article as group
|
@@ -131,7 +173,7 @@ module ActivityNotification
|
|
131
173
|
# @scope class
|
132
174
|
# @param [Object] group Group instance for filter
|
133
175
|
# @return [ActiveRecord_AssociationRelation<Notificaion>] Array or database query of filtered notifications
|
134
|
-
scope :filtered_by_group,
|
176
|
+
scope :filtered_by_group, ->(group) { where(group: group) }
|
135
177
|
|
136
178
|
# Selects filtered notifications by key.
|
137
179
|
# @example Get filtered unopened notificatons of the @user with key 'comment.reply'
|
@@ -139,7 +181,7 @@ module ActivityNotification
|
|
139
181
|
# @scope class
|
140
182
|
# @param [String] key Key of the notification for filter
|
141
183
|
# @return [ActiveRecord_AssociationRelation<Notificaion>] Array or database query of filtered notifications
|
142
|
-
scope :filtered_by_key,
|
184
|
+
scope :filtered_by_key, ->(key) { where(key: key) }
|
143
185
|
|
144
186
|
# Selects filtered notifications by notifiable_type, group or key with filter options.
|
145
187
|
# @example Get filtered unopened notificatons of the @user for Comment notifiable class
|
@@ -152,15 +194,18 @@ module ActivityNotification
|
|
152
194
|
# @notifications = @user.notifications.unopened_only.filtered_by_options({ filtered_by_key: 'comment.reply' })
|
153
195
|
# @example Get filtered unopened notificatons of the @user for Comment notifiable class with key 'comment.reply'
|
154
196
|
# @notifications = @user.notifications.unopened_only.filtered_by_options({ filtered_by_type: 'Comment', filtered_by_key: 'comment.reply' })
|
197
|
+
# @example Get custom filtered notificatons of the @user
|
198
|
+
# @notifications = @user.notifications.unopened_only.filtered_by_options({ custom_filter: ["created_at >= ?", time.hour.ago] })
|
155
199
|
# @scope class
|
156
200
|
# @param [Hash] options Options for filter
|
157
|
-
# @option options [String]
|
158
|
-
# @option options [Object]
|
159
|
-
# @option options [String]
|
160
|
-
# @option options [String]
|
161
|
-
# @option options [String]
|
201
|
+
# @option options [String] :filtered_by_type (nil) Notifiable type for filter
|
202
|
+
# @option options [Object] :filtered_by_group (nil) Group instance for filter
|
203
|
+
# @option options [String] :filtered_by_group_type (nil) Group type for filter, valid with :filtered_by_group_id
|
204
|
+
# @option options [String] :filtered_by_group_id (nil) Group instance id for filter, valid with :filtered_by_group_type
|
205
|
+
# @option options [String] :filtered_by_key (nil) Key of the notification for filter
|
206
|
+
# @option options [Array|Hash] :custom_filter (nil) Custom notification filter (e.g. ["created_at >= ?", time.hour.ago])
|
162
207
|
# @return [ActiveRecord_AssociationRelation<Notificaion>] Array or database query of filtered notifications
|
163
|
-
scope :filtered_by_options,
|
208
|
+
scope :filtered_by_options, ->(options = {}) {
|
164
209
|
options = ActivityNotification.cast_to_indifferent_hash(options)
|
165
210
|
filtered_notifications = all
|
166
211
|
if options.has_key?(:filtered_by_type)
|
@@ -176,40 +221,51 @@ module ActivityNotification
|
|
176
221
|
if options.has_key?(:filtered_by_key)
|
177
222
|
filtered_notifications = filtered_notifications.filtered_by_key(options[:filtered_by_key])
|
178
223
|
end
|
224
|
+
if options.has_key?(:custom_filter)
|
225
|
+
filtered_notifications = filtered_notifications.where(options[:custom_filter])
|
226
|
+
end
|
179
227
|
filtered_notifications
|
180
228
|
}
|
181
229
|
|
182
230
|
# Includes target instance with query for notifications.
|
183
231
|
# @return [ActiveRecord_AssociationRelation<Notificaion>] Database query of notifications with target
|
184
|
-
scope :with_target, ->
|
232
|
+
scope :with_target, -> { includes(:target) }
|
185
233
|
|
186
234
|
# Includes notifiable instance with query for notifications.
|
187
235
|
# @return [ActiveRecord_AssociationRelation<Notificaion>] Database query of notifications with notifiable
|
188
|
-
scope :with_notifiable, ->
|
236
|
+
scope :with_notifiable, -> { includes(:notifiable) }
|
189
237
|
|
190
238
|
# Includes group instance with query for notifications.
|
191
239
|
# @return [ActiveRecord_AssociationRelation<Notificaion>] Database query of notifications with group
|
192
|
-
scope :with_group, ->
|
240
|
+
scope :with_group, -> { includes(:group) }
|
241
|
+
|
242
|
+
# Includes group owner instances with query for notifications.
|
243
|
+
# @return [ActiveRecord_AssociationRelation<Notificaion>] Database query of notifications with group owner
|
244
|
+
scope :with_group_owner, -> { includes(:group_owner) }
|
245
|
+
|
246
|
+
# Includes group member instances with query for notifications.
|
247
|
+
# @return [ActiveRecord_AssociationRelation<Notificaion>] Database query of notifications with group members
|
248
|
+
scope :with_group_members, -> { includes(:group_members) }
|
193
249
|
|
194
250
|
# Includes notifier instance with query for notifications.
|
195
251
|
# @return [ActiveRecord_AssociationRelation<Notificaion>] Database query of notifications with notifier
|
196
|
-
scope :with_notifier, ->
|
252
|
+
scope :with_notifier, -> { includes(:notifier) }
|
197
253
|
|
198
254
|
# Orders by latest (newest) first as created_at: :desc.
|
199
255
|
# @return [ActiveRecord_AssociationRelation<Notificaion>] Database query of notifications ordered by latest first
|
200
|
-
scope :latest_order, ->
|
256
|
+
scope :latest_order, -> { order(created_at: :desc) }
|
201
257
|
|
202
258
|
# Orders by earliest (older) first as created_at: :asc.
|
203
259
|
# @return [ActiveRecord_AssociationRelation<Notificaion>] Database query of notifications ordered by earliest first
|
204
|
-
scope :earliest_order, ->
|
260
|
+
scope :earliest_order, -> { order(created_at: :asc) }
|
205
261
|
|
206
262
|
# Returns latest notification instance.
|
207
263
|
# @return [Notification] Latest notification instance
|
208
|
-
scope :latest, ->
|
264
|
+
scope :latest, -> { latest_order.first }
|
209
265
|
|
210
266
|
# Returns earliest notification instance.
|
211
267
|
# @return [Notification] Earliest notification instance
|
212
|
-
scope :earliest, ->
|
268
|
+
scope :earliest, -> { earliest_order.first }
|
213
269
|
|
214
270
|
end
|
215
271
|
end
|
@@ -87,6 +87,7 @@ module ActivityNotification
|
|
87
87
|
# @param [Hash] options Options for notifiable model configuration
|
88
88
|
# @option options [Symbol, Proc, String] :email (nil) Email address to send notification email
|
89
89
|
# @option options [Symbol, Proc, Boolean] :email_allowed (ActivityNotification.config.email_enabled) Whether activity_notification sends notification email to this target
|
90
|
+
# @option options [Symbol, Proc, Boolean] :email_allowed (ActivityNotification.config.email_enabled) Whether activity_notification sends batch notification email to this target
|
90
91
|
# @option options [Symbol, Proc, Object] :devise_resource (nil) Integrated resource with devise authentication
|
91
92
|
# @option options [Symbol, Proc, String] :printable_name (ActivityNotification::Common.printable_name) Printable notification target name
|
92
93
|
# @return [Hash] Configured parameters as target model
|
@@ -94,15 +95,16 @@ module ActivityNotification
|
|
94
95
|
include Target
|
95
96
|
|
96
97
|
options[:printable_notification_target_name] ||= options.delete(:printable_name)
|
98
|
+
options[:batch_notification_email_allowed] ||= options.delete(:batch_email_allowed)
|
97
99
|
set_acts_as_parameters([:email, :email_allowed, :devise_resource], options, "notification_")
|
98
|
-
.merge set_acts_as_parameters([:printable_notification_target_name], options)
|
100
|
+
.merge set_acts_as_parameters([:batch_notification_email_allowed, :printable_notification_target_name], options)
|
99
101
|
end
|
100
102
|
alias_method :acts_as_notification_target, :acts_as_target
|
101
103
|
|
102
104
|
# Returns array of available target options in acts_as_target.
|
103
105
|
# @return [Array<Symbol>] Array of available target options
|
104
106
|
def available_target_options
|
105
|
-
[:email, :email_allowed, :devise_resource, :printable_notification_target_name, :printable_name].freeze
|
107
|
+
[:email, :email_allowed, :batch_email_allowed, :devise_resource, :printable_notification_target_name, :printable_name].freeze
|
106
108
|
end
|
107
109
|
end
|
108
110
|
end
|
@@ -412,6 +412,36 @@ shared_examples_for :notification_api do
|
|
412
412
|
end
|
413
413
|
end
|
414
414
|
|
415
|
+
describe ".send_batch_notification_email" do
|
416
|
+
context "as default" do
|
417
|
+
it "sends batch notification email later" do
|
418
|
+
expect(ActivityNotification::Mailer.deliveries.size).to eq(0)
|
419
|
+
expect {
|
420
|
+
perform_enqueued_jobs do
|
421
|
+
described_class.send_batch_notification_email(test_instance.target, [test_instance])
|
422
|
+
end
|
423
|
+
}.to change { ActivityNotification::Mailer.deliveries.size }.by(1)
|
424
|
+
expect(ActivityNotification::Mailer.deliveries.size).to eq(1)
|
425
|
+
expect(ActivityNotification::Mailer.deliveries.first.to[0]).to eq(test_instance.target.email)
|
426
|
+
end
|
427
|
+
|
428
|
+
it "sends batch notification email with active job queue" do
|
429
|
+
expect {
|
430
|
+
described_class.send_batch_notification_email(test_instance.target, [test_instance])
|
431
|
+
}.to change(ActiveJob::Base.queue_adapter.enqueued_jobs, :size).by(1)
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
435
|
+
context "with send_later false" do
|
436
|
+
it "sends notification email now" do
|
437
|
+
expect(ActivityNotification::Mailer.deliveries.size).to eq(0)
|
438
|
+
described_class.send_batch_notification_email(test_instance.target, [test_instance], send_later: false)
|
439
|
+
expect(ActivityNotification::Mailer.deliveries.size).to eq(1)
|
440
|
+
expect(ActivityNotification::Mailer.deliveries.first.to[0]).to eq(test_instance.target.email)
|
441
|
+
end
|
442
|
+
end
|
443
|
+
end
|
444
|
+
|
415
445
|
describe ".available_options" do
|
416
446
|
it "returns list of available options in notify api" do
|
417
447
|
expect(described_class.available_options)
|
@@ -1035,6 +1065,22 @@ shared_examples_for :notification_api do
|
|
1035
1065
|
end
|
1036
1066
|
end
|
1037
1067
|
|
1068
|
+
describe "#latest_group_member" do
|
1069
|
+
context "with group member" do
|
1070
|
+
it "returns latest group member" do
|
1071
|
+
member1 = create(test_class_name, target: test_instance.target, group_owner: test_instance)
|
1072
|
+
member2 = create(test_class_name, target: test_instance.target, group_owner: test_instance)
|
1073
|
+
expect(test_instance.latest_group_member).to eq(member2)
|
1074
|
+
end
|
1075
|
+
end
|
1076
|
+
|
1077
|
+
context "without group members" do
|
1078
|
+
it "returns group owner self" do
|
1079
|
+
expect(test_instance.latest_group_member).to eq(test_instance)
|
1080
|
+
end
|
1081
|
+
end
|
1082
|
+
end
|
1083
|
+
|
1038
1084
|
describe "#notifiable_path" do
|
1039
1085
|
it "returns notifiable.notifiable_path" do
|
1040
1086
|
expect(test_instance.notifiable_path)
|
@@ -30,6 +30,75 @@ shared_examples_for :target do
|
|
30
30
|
expect(described_class._printable_notification_target_name).to eq(:printable_name)
|
31
31
|
end
|
32
32
|
end
|
33
|
+
|
34
|
+
describe ".notification_index_map" do
|
35
|
+
it "returns notifications of this target type group by target" do
|
36
|
+
ActivityNotification::Notification.delete_all
|
37
|
+
target_1 = create(test_class_name)
|
38
|
+
target_2 = create(test_class_name)
|
39
|
+
notification_1 = create(:notification, target: target_1)
|
40
|
+
notification_2 = create(:notification, target: target_1)
|
41
|
+
notification_3 = create(:notification, target: target_1)
|
42
|
+
notification_4 = create(:notification, target: target_2)
|
43
|
+
notification_5 = create(:notification, target: target_2)
|
44
|
+
notification_6 = create(:notification, target: test_notifiable)
|
45
|
+
|
46
|
+
expect(described_class.notification_index_map.size).to eq(2)
|
47
|
+
expect(described_class.notification_index_map[target_1].size).to eq(3)
|
48
|
+
expect(described_class.notification_index_map[target_2].size).to eq(2)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe ".unopened_notification_index_map" do
|
53
|
+
it "returns unopened notifications of this target type group by target" do
|
54
|
+
ActivityNotification::Notification.delete_all
|
55
|
+
target_1 = create(test_class_name)
|
56
|
+
target_2 = create(test_class_name)
|
57
|
+
target_3 = create(test_class_name)
|
58
|
+
notification_1 = create(:notification, target: target_1)
|
59
|
+
notification_2 = create(:notification, target: target_1)
|
60
|
+
notification_3 = create(:notification, target: target_1)
|
61
|
+
notification_3.open!
|
62
|
+
notification_4 = create(:notification, target: target_2)
|
63
|
+
notification_5 = create(:notification, target: target_2)
|
64
|
+
notification_5.open!
|
65
|
+
notification_6 = create(:notification, target: target_3)
|
66
|
+
notification_6.open!
|
67
|
+
notification_7 = create(:notification, target: test_notifiable)
|
68
|
+
|
69
|
+
index_map = described_class.unopened_notification_index_map
|
70
|
+
expect(index_map.size).to eq(2)
|
71
|
+
expect(index_map[target_1].size).to eq(2)
|
72
|
+
expect(index_map[target_2].size).to eq(1)
|
73
|
+
expect(index_map.has_key?(target_3)).to be_falsey
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe ".send_batch_unopened_notification_email" do
|
78
|
+
it "sends batch notification email to this type targets with unopened notifications" do
|
79
|
+
ActivityNotification::Notification.delete_all
|
80
|
+
target_1 = create(test_class_name)
|
81
|
+
target_2 = create(test_class_name)
|
82
|
+
target_3 = create(test_class_name)
|
83
|
+
notification_1 = create(:notification, target: target_1)
|
84
|
+
notification_2 = create(:notification, target: target_1)
|
85
|
+
notification_3 = create(:notification, target: target_1)
|
86
|
+
notification_3.open!
|
87
|
+
notification_4 = create(:notification, target: target_2)
|
88
|
+
notification_5 = create(:notification, target: target_2)
|
89
|
+
notification_5.open!
|
90
|
+
notification_6 = create(:notification, target: target_3)
|
91
|
+
notification_6.open!
|
92
|
+
notification_7 = create(:notification, target: test_notifiable)
|
93
|
+
|
94
|
+
expect(ActivityNotification::Notification).to receive(:send_batch_notification_email).at_least(:once)
|
95
|
+
sent_email_map = described_class.send_batch_unopened_notification_email
|
96
|
+
expect(sent_email_map.size).to eq(2)
|
97
|
+
expect(sent_email_map.has_key?(target_1)).to be_truthy
|
98
|
+
expect(sent_email_map.has_key?(target_2)).to be_truthy
|
99
|
+
expect(sent_email_map.has_key?(target_3)).to be_falsey
|
100
|
+
end
|
101
|
+
end
|
33
102
|
end
|
34
103
|
|
35
104
|
describe "as public instance methods" do
|
@@ -248,9 +317,14 @@ shared_examples_for :target do
|
|
248
317
|
|
249
318
|
context "when the target has unopened notifications" do
|
250
319
|
before do
|
251
|
-
create(:
|
252
|
-
create(:
|
253
|
-
|
320
|
+
@notifiable = create(:article)
|
321
|
+
@group = create(:article)
|
322
|
+
@key = 'test.key.1'
|
323
|
+
@notification2 = create(:notification, target: test_instance, notifiable: @notifiable)
|
324
|
+
@notification1 = create(:notification, target: test_instance, notifiable: create(:comment), group: @group)
|
325
|
+
@member1 = create(:notification, target: test_instance, notifiable: create(:comment), group_owner: @notification1)
|
326
|
+
@notification3 = create(:notification, target: test_instance, notifiable: create(:article), key: @key)
|
327
|
+
@notification3.open!
|
254
328
|
end
|
255
329
|
|
256
330
|
it "calls unopened_notification_index" do
|
@@ -258,11 +332,11 @@ shared_examples_for :target do
|
|
258
332
|
test_instance.notification_index
|
259
333
|
end
|
260
334
|
|
261
|
-
context "without
|
335
|
+
context "without any options" do
|
262
336
|
it "returns the combined array of unopened_notification_index and opened_notification_index" do
|
263
|
-
expect(test_instance.notification_index[0]).to eq(
|
264
|
-
expect(test_instance.notification_index[1]).to eq(
|
265
|
-
expect(test_instance.notification_index[2]).to eq(
|
337
|
+
expect(test_instance.notification_index[0]).to eq(@notification1)
|
338
|
+
expect(test_instance.notification_index[1]).to eq(@notification2)
|
339
|
+
expect(test_instance.notification_index[2]).to eq(@notification3)
|
266
340
|
expect(test_instance.notification_index.size).to eq(3)
|
267
341
|
end
|
268
342
|
end
|
@@ -270,7 +344,86 @@ shared_examples_for :target do
|
|
270
344
|
context "with limit" do
|
271
345
|
it "returns the same as unopened_notification_index with limit" do
|
272
346
|
options = { limit: 1 }
|
273
|
-
expect(test_instance.notification_index(options)).to eq(
|
347
|
+
expect(test_instance.notification_index(options)[0]).to eq(@notification1)
|
348
|
+
expect(test_instance.notification_index(options).size).to eq(1)
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
context "with reverse" do
|
353
|
+
it "returns the earliest order" do
|
354
|
+
options = { reverse: true }
|
355
|
+
expect(test_instance.notification_index(options)[0]).to eq(@notification2)
|
356
|
+
expect(test_instance.notification_index(options)[1]).to eq(@notification1)
|
357
|
+
expect(test_instance.notification_index(options)[2]).to eq(@notification3)
|
358
|
+
expect(test_instance.notification_index(options).size).to eq(3)
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
context "with with_group_members" do
|
363
|
+
it "returns the index with group members" do
|
364
|
+
options = { with_group_members: true }
|
365
|
+
expect(test_instance.notification_index(options)[0]).to eq(@member1)
|
366
|
+
expect(test_instance.notification_index(options)[1]).to eq(@notification1)
|
367
|
+
expect(test_instance.notification_index(options)[2]).to eq(@notification2)
|
368
|
+
expect(test_instance.notification_index(options)[3]).to eq(@notification3)
|
369
|
+
expect(test_instance.notification_index(options).size).to eq(4)
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
context "with as_latest_group_member" do
|
374
|
+
it "returns the index as latest group member" do
|
375
|
+
options = { as_latest_group_member: true }
|
376
|
+
expect(test_instance.notification_index(options)[0]).to eq(@member1)
|
377
|
+
expect(test_instance.notification_index(options)[1]).to eq(@notification2)
|
378
|
+
expect(test_instance.notification_index(options)[2]).to eq(@notification3)
|
379
|
+
expect(test_instance.notification_index(options).size).to eq(3)
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
context 'with filtered_by_type options' do
|
384
|
+
it "returns filtered notifications only" do
|
385
|
+
options = { filtered_by_type: 'Article' }
|
386
|
+
expect(test_instance.notification_index(options)[0]).to eq(@notification2)
|
387
|
+
expect(test_instance.notification_index(options)[1]).to eq(@notification3)
|
388
|
+
expect(test_instance.notification_index(options).size).to eq(2)
|
389
|
+
options = { filtered_by_type: 'Comment' }
|
390
|
+
expect(test_instance.notification_index(options)[0]).to eq(@notification1)
|
391
|
+
expect(test_instance.notification_index(options).size).to eq(1)
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
395
|
+
context 'with filtered_by_group options' do
|
396
|
+
it "returns filtered notifications only" do
|
397
|
+
options = { filtered_by_group: @group }
|
398
|
+
expect(test_instance.notification_index(options)[0]).to eq(@notification1)
|
399
|
+
expect(test_instance.notification_index(options).size).to eq(1)
|
400
|
+
end
|
401
|
+
end
|
402
|
+
|
403
|
+
context 'with filtered_by_group_type and :filtered_by_group_id options' do
|
404
|
+
it "returns filtered notifications only" do
|
405
|
+
options = { filtered_by_group_type: 'Article', filtered_by_group_id: @group.id.to_s }
|
406
|
+
expect(test_instance.notification_index(options)[0]).to eq(@notification1)
|
407
|
+
expect(test_instance.notification_index(options).size).to eq(1)
|
408
|
+
end
|
409
|
+
end
|
410
|
+
|
411
|
+
context 'with filtered_by_key options' do
|
412
|
+
it "returns filtered notifications only" do
|
413
|
+
options = { filtered_by_key: @key }
|
414
|
+
expect(test_instance.notification_index(options)[0]).to eq(@notification3)
|
415
|
+
expect(test_instance.notification_index(options).size).to eq(1)
|
416
|
+
end
|
417
|
+
end
|
418
|
+
|
419
|
+
context 'with custom_filter options' do
|
420
|
+
it "returns filtered notifications only" do
|
421
|
+
options = { custom_filter: ["key = ?", @key] }
|
422
|
+
expect(test_instance.notification_index(options)[0]).to eq(@notification3)
|
423
|
+
expect(test_instance.notification_index(options).size).to eq(1)
|
424
|
+
|
425
|
+
options = { custom_filter: { key: @key } }
|
426
|
+
expect(test_instance.notification_index(options)[0]).to eq(@notification3)
|
274
427
|
expect(test_instance.notification_index(options).size).to eq(1)
|
275
428
|
end
|
276
429
|
end
|
@@ -453,9 +606,13 @@ shared_examples_for :target do
|
|
453
606
|
|
454
607
|
context "when the target has unopened notifications" do
|
455
608
|
before do
|
456
|
-
create(:
|
457
|
-
create(:
|
458
|
-
|
609
|
+
@notifiable = create(:article)
|
610
|
+
@group = create(:article)
|
611
|
+
@key = 'test.key.1'
|
612
|
+
@notification2 = create(:notification, target: test_instance, notifiable: @notifiable)
|
613
|
+
@notification1 = create(:notification, target: test_instance, notifiable: create(:comment), group: @group)
|
614
|
+
@notification3 = create(:notification, target: test_instance, notifiable: create(:article), key: @key)
|
615
|
+
@notification3.open!
|
459
616
|
end
|
460
617
|
|
461
618
|
it "calls unopened_notification_index_with_attributes" do
|
@@ -463,19 +620,65 @@ shared_examples_for :target do
|
|
463
620
|
test_instance.notification_index_with_attributes
|
464
621
|
end
|
465
622
|
|
466
|
-
context "without
|
467
|
-
it "returns the combined array of
|
468
|
-
expect(test_instance.notification_index_with_attributes[0]).to eq(
|
469
|
-
expect(test_instance.notification_index_with_attributes[1]).to eq(
|
470
|
-
expect(test_instance.notification_index_with_attributes[2]).to eq(
|
471
|
-
expect(test_instance.
|
623
|
+
context "without any options" do
|
624
|
+
it "returns the combined array of unopened_notification_index_with_attributes and opened_notification_index_with_attributes" do
|
625
|
+
expect(test_instance.notification_index_with_attributes[0]).to eq(@notification1)
|
626
|
+
expect(test_instance.notification_index_with_attributes[1]).to eq(@notification2)
|
627
|
+
expect(test_instance.notification_index_with_attributes[2]).to eq(@notification3)
|
628
|
+
expect(test_instance.notification_index_with_attributes.size).to eq(3)
|
472
629
|
end
|
473
630
|
end
|
474
631
|
|
475
632
|
context "with limit" do
|
476
633
|
it "returns the same as unopened_notification_index_with_attributes with limit" do
|
477
634
|
options = { limit: 1 }
|
478
|
-
expect(test_instance.notification_index_with_attributes(options)).to eq(
|
635
|
+
expect(test_instance.notification_index_with_attributes(options)[0]).to eq(@notification1)
|
636
|
+
expect(test_instance.notification_index_with_attributes(options).size).to eq(1)
|
637
|
+
end
|
638
|
+
end
|
639
|
+
|
640
|
+
context "with reverse" do
|
641
|
+
it "returns the earliest order" do
|
642
|
+
options = { reverse: true }
|
643
|
+
expect(test_instance.notification_index_with_attributes(options)[0]).to eq(@notification2)
|
644
|
+
expect(test_instance.notification_index_with_attributes(options)[1]).to eq(@notification1)
|
645
|
+
expect(test_instance.notification_index_with_attributes(options)[2]).to eq(@notification3)
|
646
|
+
expect(test_instance.notification_index_with_attributes(options).size).to eq(3)
|
647
|
+
end
|
648
|
+
end
|
649
|
+
|
650
|
+
context 'with filtered_by_type options' do
|
651
|
+
it "returns filtered notifications only" do
|
652
|
+
options = { filtered_by_type: 'Article' }
|
653
|
+
expect(test_instance.notification_index_with_attributes(options)[0]).to eq(@notification2)
|
654
|
+
expect(test_instance.notification_index_with_attributes(options)[1]).to eq(@notification3)
|
655
|
+
expect(test_instance.notification_index_with_attributes(options).size).to eq(2)
|
656
|
+
options = { filtered_by_type: 'Comment' }
|
657
|
+
expect(test_instance.notification_index_with_attributes(options)[0]).to eq(@notification1)
|
658
|
+
expect(test_instance.notification_index_with_attributes(options).size).to eq(1)
|
659
|
+
end
|
660
|
+
end
|
661
|
+
|
662
|
+
context 'with filtered_by_group options' do
|
663
|
+
it "returns filtered notifications only" do
|
664
|
+
options = { filtered_by_group: @group }
|
665
|
+
expect(test_instance.notification_index_with_attributes(options)[0]).to eq(@notification1)
|
666
|
+
expect(test_instance.notification_index_with_attributes(options).size).to eq(1)
|
667
|
+
end
|
668
|
+
end
|
669
|
+
|
670
|
+
context 'with filtered_by_group_type and :filtered_by_group_id options' do
|
671
|
+
it "returns filtered notifications only" do
|
672
|
+
options = { filtered_by_group_type: 'Article', filtered_by_group_id: @group.id.to_s }
|
673
|
+
expect(test_instance.notification_index_with_attributes(options)[0]).to eq(@notification1)
|
674
|
+
expect(test_instance.notification_index_with_attributes(options).size).to eq(1)
|
675
|
+
end
|
676
|
+
end
|
677
|
+
|
678
|
+
context 'with filtered_by_key options' do
|
679
|
+
it "returns filtered notifications only" do
|
680
|
+
options = { filtered_by_key: @key }
|
681
|
+
expect(test_instance.notification_index_with_attributes(options)[0]).to eq(@notification3)
|
479
682
|
expect(test_instance.notification_index_with_attributes(options).size).to eq(1)
|
480
683
|
end
|
481
684
|
end
|
@@ -510,8 +713,8 @@ shared_examples_for :target do
|
|
510
713
|
end
|
511
714
|
|
512
715
|
describe "#unopened_notification_index_with_attributes" do
|
513
|
-
it "calls
|
514
|
-
expect(test_instance).to receive(:
|
716
|
+
it "calls _unopened_notification_index" do
|
717
|
+
expect(test_instance).to receive(:_unopened_notification_index)
|
515
718
|
test_instance.unopened_notification_index_with_attributes
|
516
719
|
end
|
517
720
|
|
@@ -568,8 +771,8 @@ shared_examples_for :target do
|
|
568
771
|
end
|
569
772
|
|
570
773
|
describe "#opened_notification_index_with_attributes" do
|
571
|
-
it "calls
|
572
|
-
expect(test_instance).to receive(:
|
774
|
+
it "calls _opened_notification_index" do
|
775
|
+
expect(test_instance).to receive(:_opened_notification_index)
|
573
776
|
test_instance.opened_notification_index_with_attributes
|
574
777
|
end
|
575
778
|
|
@@ -625,6 +828,62 @@ shared_examples_for :target do
|
|
625
828
|
end
|
626
829
|
end
|
627
830
|
|
831
|
+
describe "#send_notification_email" do
|
832
|
+
context "with right target of notification" do
|
833
|
+
before do
|
834
|
+
@notification = create(:notification, target: test_instance)
|
835
|
+
end
|
836
|
+
|
837
|
+
it "calls notification.send_notification_email" do
|
838
|
+
expect(@notification).to receive(:send_notification_email).at_least(:once)
|
839
|
+
test_instance.send_notification_email(@notification)
|
840
|
+
end
|
841
|
+
end
|
842
|
+
|
843
|
+
context "with wrong target of notification" do
|
844
|
+
before do
|
845
|
+
@notification = create(:notification, target: create(:user))
|
846
|
+
end
|
847
|
+
|
848
|
+
it "does not call notification.send_notification_email" do
|
849
|
+
expect(@notification).not_to receive(:send_notification_email)
|
850
|
+
test_instance.send_notification_email(@notification)
|
851
|
+
end
|
852
|
+
|
853
|
+
it "returns nil" do
|
854
|
+
expect(test_instance.send_notification_email(@notification)).to be_nil
|
855
|
+
end
|
856
|
+
end
|
857
|
+
end
|
858
|
+
|
859
|
+
describe "#send_batch_notification_email" do
|
860
|
+
context "with right target of notification" do
|
861
|
+
before do
|
862
|
+
@notifications = [create(:notification, target: test_instance), create(:notification, target: test_instance)]
|
863
|
+
end
|
864
|
+
|
865
|
+
it "calls ActivityNotification::Notification.send_batch_notification_email" do
|
866
|
+
expect(ActivityNotification::Notification).to receive(:send_batch_notification_email).at_least(:once)
|
867
|
+
test_instance.send_batch_notification_email(@notifications)
|
868
|
+
end
|
869
|
+
end
|
870
|
+
|
871
|
+
context "with wrong target of notification" do
|
872
|
+
before do
|
873
|
+
notifications = [create(:notification, target: test_instance), create(:notification, target: create(:user))]
|
874
|
+
end
|
875
|
+
|
876
|
+
it "does not call ActivityNotification::Notification.send_batch_notification_email" do
|
877
|
+
expect(ActivityNotification::Notification).not_to receive(:send_batch_notification_email)
|
878
|
+
test_instance.send_batch_notification_email(@notifications)
|
879
|
+
end
|
880
|
+
|
881
|
+
it "returns nil" do
|
882
|
+
expect(test_instance.send_batch_notification_email(@notifications)).to be_nil
|
883
|
+
end
|
884
|
+
end
|
885
|
+
end
|
886
|
+
|
628
887
|
end
|
629
888
|
|
630
889
|
end
|