activity_notification 1.3.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +41 -5
  3. data/CHANGELOG.md +20 -0
  4. data/Gemfile +4 -1
  5. data/Gemfile.lock +81 -70
  6. data/README.md +152 -12
  7. data/activity_notification.gemspec +6 -4
  8. data/gemfiles/Gemfile.rails-4.2.lock +27 -22
  9. data/gemfiles/Gemfile.rails-5.0.lock +26 -21
  10. data/gemfiles/Gemfile.rails-5.1 +15 -0
  11. data/gemfiles/Gemfile.rails-5.1.lock +229 -0
  12. data/lib/activity_notification/apis/notification_api.rb +2 -2
  13. data/lib/activity_notification/apis/subscription_api.rb +7 -7
  14. data/lib/activity_notification/controllers/common_controller.rb +2 -2
  15. data/lib/activity_notification/helpers/view_helpers.rb +1 -1
  16. data/lib/activity_notification/models/concerns/notifiable.rb +19 -1
  17. data/lib/activity_notification/models/concerns/target.rb +5 -3
  18. data/lib/activity_notification/orm/active_record/notification.rb +3 -1
  19. data/lib/activity_notification/orm/active_record/subscription.rb +3 -1
  20. data/lib/activity_notification/orm/mongoid.rb +2 -2
  21. data/lib/activity_notification/renderable.rb +1 -1
  22. data/lib/activity_notification/roles/acts_as_notifiable.rb +98 -17
  23. data/lib/activity_notification/version.rb +1 -1
  24. data/spec/concerns/apis/notification_api_spec.rb +9 -8
  25. data/spec/concerns/apis/subscription_api_spec.rb +28 -28
  26. data/spec/concerns/models/notifier_spec.rb +1 -1
  27. data/spec/concerns/models/subscriber_spec.rb +7 -7
  28. data/spec/concerns/models/target_spec.rb +20 -20
  29. data/spec/controllers/notifications_controller_shared_examples.rb +19 -8
  30. data/spec/controllers/subscriptions_controller_shared_examples.rb +16 -5
  31. data/spec/models/notification_spec.rb +4 -4
  32. data/spec/models/subscription_spec.rb +16 -12
  33. data/spec/rails_app/app/controllers/articles_controller.rb +1 -1
  34. data/spec/rails_app/app/controllers/comments_controller.rb +0 -1
  35. data/spec/rails_app/app/models/admin.rb +29 -8
  36. data/spec/rails_app/app/models/article.rb +45 -13
  37. data/spec/rails_app/app/models/comment.rb +107 -42
  38. data/spec/rails_app/app/models/user.rb +45 -12
  39. data/spec/rails_app/app/views/layouts/_header.html.erb +1 -0
  40. data/spec/rails_app/config/database.yml +26 -15
  41. data/spec/rails_app/config/initializers/devise.rb +5 -1
  42. data/spec/rails_app/db/migrate/20160715050420_create_activity_notification_tables.rb +1 -1
  43. data/spec/rails_app/db/migrate/20160715050433_create_test_tables.rb +1 -1
  44. data/spec/rails_app/db/seeds.rb +31 -8
  45. data/spec/roles/acts_as_notifiable_spec.rb +154 -1
  46. data/spec/spec_helper.rb +7 -2
  47. metadata +47 -17
@@ -125,11 +125,11 @@ module ActivityNotification
125
125
  }
126
126
 
127
127
  # Orders by latest (newest) first as created_at: :desc.
128
- # @return [Mongoid::Criteria<Notificaion>] Database query of notifications ordered by latest first
128
+ # @return [ActiveRecord_AssociationRelation<Notificaion>, Mongoid::Criteria<Notificaion>] Database query of notifications ordered by latest first
129
129
  scope :latest_order, -> { order(created_at: :desc) }
130
130
 
131
131
  # Orders by earliest (older) first as created_at: :asc.
132
- # @return [Mongoid::Criteria<Notificaion>] Database query of notifications ordered by earliest first
132
+ # @return [ActiveRecord_AssociationRelation<Notificaion>, Mongoid::Criteria<Notificaion>] Database query of notifications ordered by earliest first
133
133
  scope :earliest_order, -> { order(created_at: :asc) }
134
134
  end
135
135
 
@@ -9,7 +9,7 @@ module ActivityNotification
9
9
  # @subscriptions = @user.subscriptions.filtered_by_key('comment.reply')
10
10
  # @scope class
11
11
  # @param [String] key Key of the subscription for filter
12
- # @return [ActiveRecord_AssociationRelation<Subscription>] Database query of filtered subscriptions
12
+ # @return [ActiveRecord_AssociationRelation<Subscription>, Mongoid::Criteria<Notificaion>] Database query of filtered subscriptions
13
13
  scope :filtered_by_key, ->(key) { where(key: key) }
14
14
 
15
15
  # Selects filtered subscriptions by key with filter options.
@@ -21,7 +21,7 @@ module ActivityNotification
21
21
  # @param [Hash] options Options for filter
22
22
  # @option options [String] :filtered_by_key (nil) Key of the subscription for filter
23
23
  # @option options [Array|Hash] :custom_filter (nil) Custom subscription filter (e.g. ["created_at >= ?", time.hour.ago])
24
- # @return [Mongoid::Criteria<Notificaion>] Database query of filtered subscriptions
24
+ # @return [ActiveRecord_AssociationRelation<Subscription>, Mongoid::Criteria<Notificaion>] Database query of filtered subscriptions
25
25
  scope :filtered_by_options, ->(options = {}) {
26
26
  options = ActivityNotification.cast_to_indifferent_hash(options)
27
27
  filtered_subscriptions = all
@@ -35,23 +35,23 @@ module ActivityNotification
35
35
  }
36
36
 
37
37
  # Orders by latest (newest) first as created_at: :desc.
38
- # @return [ActiveRecord_AssociationRelation<Subscription>] Database query of subscriptions ordered by latest first
38
+ # @return [ActiveRecord_AssociationRelation<Subscription>, Mongoid::Criteria<Notificaion>] Database query of subscriptions ordered by latest first
39
39
  scope :latest_order, -> { order(created_at: :desc) }
40
40
 
41
41
  # Orders by earliest (older) first as created_at: :asc.
42
- # @return [ActiveRecord_AssociationRelation<Subscription>] Database query of subscriptions ordered by earliest first
42
+ # @return [ActiveRecord_AssociationRelation<Subscription>, Mongoid::Criteria<Notificaion>] Database query of subscriptions ordered by earliest first
43
43
  scope :earliest_order, -> { order(created_at: :asc) }
44
44
 
45
45
  # Orders by latest (newest) first as subscribed_at: :desc.
46
- # @return [ActiveRecord_AssociationRelation<Subscription>] Database query of subscriptions ordered by latest subscribed_at first
46
+ # @return [ActiveRecord_AssociationRelation<Subscription>, Mongoid::Criteria<Notificaion>] Database query of subscriptions ordered by latest subscribed_at first
47
47
  scope :latest_subscribed_order, -> { order(subscribed_at: :desc) }
48
48
 
49
49
  # Orders by earliest (older) first as subscribed_at: :asc.
50
- # @return [ActiveRecord_AssociationRelation<Subscription>] Database query of subscriptions ordered by earliest subscribed_at first
50
+ # @return [ActiveRecord_AssociationRelation<Subscription>, Mongoid::Criteria<Notificaion>] Database query of subscriptions ordered by earliest subscribed_at first
51
51
  scope :earliest_subscribed_order, -> { order(subscribed_at: :asc) }
52
52
 
53
53
  # Orders by key name as key: :asc.
54
- # @return [ActiveRecord_AssociationRelation<Subscription>] Database query of subscriptions ordered by key name
54
+ # @return [ActiveRecord_AssociationRelation<Subscription>, Mongoid::Criteria<Notificaion>] Database query of subscriptions ordered by key name
55
55
  scope :key_order, -> { order(key: :asc) }
56
56
  end
57
57
 
@@ -24,8 +24,8 @@ module ActivityNotification
24
24
  if (target_type = params[:target_type]).present?
25
25
  target_class = target_type.to_model_class
26
26
  @target = params[:target_id].present? ?
27
- target_class.find_by_id!(params[:target_id]) :
28
- target_class.find_by_id!(params["#{target_type.to_resource_name}_id"])
27
+ target_class.find_by!(id: params[:target_id]) :
28
+ target_class.find_by!(id: params["#{target_type.to_resource_name}_id"])
29
29
  else
30
30
  render plain: "400 Bad Request: Missing parameter", status: 400
31
31
  end
@@ -58,7 +58,7 @@ module ActivityNotification
58
58
  notification_options = options.merge( target: target.to_resources_name,
59
59
  partial: options[:notification_partial],
60
60
  layout: options[:notification_layout] )
61
- index_options = options.slice( :limit, :reverse, :with_group_members,
61
+ index_options = options.slice( :limit, :reverse, :with_group_members, :as_latest_group_member,
62
62
  :filtered_by_group, :filtered_by_group_type, :filtered_by_group_id,
63
63
  :filtered_by_type, :filtered_by_key, :custom_filter )
64
64
  notification_index = load_notification_index(target, options[:index_content], index_options)
@@ -285,11 +285,29 @@ module ActivityNotification
285
285
  # This method is able to be overriden.
286
286
  # "#{to_resource_name}.default" is defined as default key.
287
287
  #
288
- # @return [String] Default Key of the notification
288
+ # @return [String] Default key of the notification
289
289
  def default_notification_key
290
290
  "#{to_resource_name}.default"
291
291
  end
292
292
 
293
+ # Returns key of the notification for tracked notifiable creation.
294
+ # This method is able to be overriden.
295
+ # "#{to_resource_name}.create" is defined as default creation key.
296
+ #
297
+ # @return [String] Key of the notification for tracked notifiable creation
298
+ def notification_key_for_tracked_creation
299
+ "#{to_resource_name}.create"
300
+ end
301
+
302
+ # Returns key of the notification for tracked notifiable update.
303
+ # This method is able to be overriden.
304
+ # "#{to_resource_name}.update" is defined as default update key.
305
+ #
306
+ # @return [String] Key of the notification for tracked notifiable update
307
+ def notification_key_for_tracked_update
308
+ "#{to_resource_name}.update"
309
+ end
310
+
293
311
  private
294
312
 
295
313
  # Used to transform parameter value from configured field or defined method.
@@ -534,6 +534,7 @@ module ActivityNotification
534
534
  # @option options [Integer] :limit (nil) Limit to query for notifications
535
535
  # @option options [Boolean] :reverse (false) If notification index will be ordered as earliest first
536
536
  # @option options [Boolean] :with_group_members (false) If notification index will include group members
537
+ # @option options [Boolean] :as_latest_group_member (false) If grouped notification will be shown as the latest group member (default is shown as the earliest member)
537
538
  # @option options [String] :filtered_by_type (nil) Notifiable type for filter
538
539
  # @option options [Object] :filtered_by_group (nil) Group instance for filter
539
540
  # @option options [String] :filtered_by_group_type (nil) Group type for filter, valid with :filtered_by_group_id
@@ -560,6 +561,7 @@ module ActivityNotification
560
561
  # @option options [Integer] :limit (nil) Limit to query for notifications
561
562
  # @option options [Boolean] :reverse (false) If notification index will be ordered as earliest first
562
563
  # @option options [Boolean] :with_group_members (false) If notification index will include group members
564
+ # @option options [Boolean] :as_latest_group_member (false) If grouped notification will be shown as the latest group member (default is shown as the earliest member)
563
565
  # @option options [String] :filtered_by_type (nil) Notifiable type for filter
564
566
  # @option options [Object] :filtered_by_group (nil) Group instance for filter
565
567
  # @option options [String] :filtered_by_group_type (nil) Group type for filter, valid with :filtered_by_group_id
@@ -571,19 +573,19 @@ module ActivityNotification
571
573
  # When the target have unopened notifications
572
574
  if has_unopened_notifications?(options)
573
575
  # Return unopened notifications first
574
- target_unopened_index = loading_unopened_index_method.call(options).to_a
576
+ target_unopened_index = arrange_single_notification_index(loading_unopened_index_method, options)
575
577
  # Total limit if notification index
576
578
  total_limit = options[:limit] || ActivityNotification.config.opened_index_limit
577
579
  # Additionaly, return opened notifications unless unopened index size overs the limit
578
580
  if (opened_limit = total_limit - target_unopened_index.size) > 0
579
- target_opened_index = loading_opened_index_method.call(options.merge(limit: opened_limit))
581
+ target_opened_index = arrange_single_notification_index(loading_opened_index_method, options.merge(limit: opened_limit))
580
582
  target_unopened_index.concat(target_opened_index.to_a)
581
583
  else
582
584
  target_unopened_index
583
585
  end
584
586
  else
585
587
  # Otherwise, return opened notifications
586
- loading_opened_index_method.call(options).to_a
588
+ arrange_single_notification_index(loading_opened_index_method, options)
587
589
  end
588
590
  end
589
591
 
@@ -175,7 +175,9 @@ module ActivityNotification
175
175
  # Selects unique keys from query for notifications.
176
176
  # @return [Array<String>] Array of notification unique keys
177
177
  def self.uniq_keys
178
- select(:key).distinct.pluck(:key)
178
+ # select method cannot be chained with order by other columns like created_at
179
+ # select(:key).distinct.pluck(:key)
180
+ pluck(:key).uniq
179
181
  end
180
182
 
181
183
  protected
@@ -43,7 +43,9 @@ module ActivityNotification
43
43
  # Selects unique keys from query for subscriptions.
44
44
  # @return [Array<String>] Array of subscription unique keys
45
45
  def self.uniq_keys
46
- select(:key).distinct.pluck(:key)
46
+ # select method cannot be chained with order by other columns like created_at
47
+ # select(:key).distinct.pluck(:key)
48
+ pluck(:key).uniq
47
49
  end
48
50
 
49
51
  end
@@ -13,7 +13,7 @@ module ActivityNotification
13
13
  def belongs_to_polymorphic_xdb_record(name, _options = {})
14
14
  association_name = name.to_s.singularize.underscore
15
15
  id_field, type_field = "#{association_name}_id", "#{association_name}_type"
16
- field id_field, type: Integer
16
+ field id_field, type: String
17
17
  field type_field, type: String
18
18
 
19
19
  self.instance_eval do
@@ -22,7 +22,7 @@ module ActivityNotification
22
22
  if self.instance_variable_get("@#{name}").blank?
23
23
  if (class_name = self.send(type_field)).present?
24
24
  object_class = class_name.classify.constantize
25
- self.instance_variable_set("@#{name}", object_class.where(object_class.primary_key => self.send(id_field)).first)
25
+ self.instance_variable_set("@#{name}", object_class.where(id: self.send(id_field)).first)
26
26
  end
27
27
  end
28
28
  self.instance_variable_get("@#{name}")
@@ -152,7 +152,7 @@ module ActivityNotification
152
152
  context.render params.merge(partial: partial, layout: layout, locals: locals)
153
153
  rescue ActionView::MissingTemplate => e
154
154
  if params[:fallback] == :text
155
- context.render text: self.text(params)
155
+ context.render plain: self.text(params)
156
156
  elsif params[:fallback].present?
157
157
  partial = partial_path(*params.values_at(:fallback, :partial_root, :target))
158
158
  context.render params.merge(partial: partial, layout: layout, locals: locals)
@@ -105,6 +105,29 @@ module ActivityNotification
105
105
  # end
106
106
  # end
107
107
  #
108
+ # * :tracked
109
+ # * Adds required callbacks to generate notifications for creation and update of the notifiable model.
110
+ # Default callbacks are enabled for [:create, :update].
111
+ # You can use :only and :except options as hash for this option.
112
+ # @example Add all callbacks to generate notifications for creation and update
113
+ # # app/models/comment.rb
114
+ # class Comment < ActiveRecord::Base
115
+ # belongs_to :article
116
+ # acts_as_notifiable :users, targets: User.all, tracked: true
117
+ # end
118
+ # @example Add callbacks to generate notifications for creation only
119
+ # # app/models/comment.rb
120
+ # class Comment < ActiveRecord::Base
121
+ # belongs_to :article
122
+ # acts_as_notifiable :users, targets: User.all, tracked: { only: [:create] }
123
+ # end
124
+ # @example Add callbacks to generate notifications for creation (except update) only
125
+ # # app/models/comment.rb
126
+ # class Comment < ActiveRecord::Base
127
+ # belongs_to :article
128
+ # acts_as_notifiable :users, targets: User.all, tracked: { except: [:update] }
129
+ # end
130
+ #
108
131
  # * :printable_name or :printable_notifiable_name
109
132
  # * Printable notifiable name.
110
133
  # This parameter is a optional since `ActivityNotification::Common.printable_name` is used as default value.
@@ -168,26 +191,16 @@ module ActivityNotification
168
191
  include Notifiable
169
192
  configured_params = {}
170
193
 
171
- if [:delete_all, :destroy, :restrict_with_error, :restrict_with_exception, :update_group_and_delete_all, :update_group_and_destroy].include? options[:dependent_notifications]
172
- case options[:dependent_notifications]
173
- when :delete_all, :destroy, :restrict_with_error, :restrict_with_exception
174
- before_destroy -> { destroy_generated_notifications_with_dependency(options[:dependent_notifications], target_type) }
175
- when :update_group_and_delete_all
176
- before_destroy -> { destroy_generated_notifications_with_dependency(:delete_all, target_type, true) }
177
- when :update_group_and_destroy
178
- before_destroy -> { destroy_generated_notifications_with_dependency(:destroy, target_type, true) }
179
- end
180
- configured_params = { dependent_notifications: options[:dependent_notifications] }
194
+ if options[:tracked].present?
195
+ configured_params.update(add_tracked_callbacks(target_type, options[:tracked].is_a?(Hash) ? options[:tracked] : {}))
196
+ end
197
+
198
+ if available_dependent_notifications_options.include? options[:dependent_notifications]
199
+ configured_params.update(add_destroy_dependency(target_type, options[:dependent_notifications]))
181
200
  end
182
201
 
183
202
  if options[:optional_targets].is_a?(Hash)
184
- options[:optional_targets] = options[:optional_targets].map { |target_class, target_options|
185
- optional_target = target_class.new(target_options)
186
- unless optional_target.kind_of?(ActivityNotification::OptionalTarget::Base)
187
- raise TypeError, "#{optional_target.class.name} for an optional target is not a kind of ActivityNotification::OptionalTarget::Base"
188
- end
189
- optional_target
190
- }
203
+ options[:optional_targets] = arrange_optional_targets_option(options[:optional_targets])
191
204
  end
192
205
 
193
206
  options[:printable_notifiable_name] ||= options.delete(:printable_name)
@@ -212,6 +225,74 @@ module ActivityNotification
212
225
  ].freeze
213
226
  end
214
227
 
228
+ # Returns array of available notifiable options in acts_as_notifiable.
229
+ # @return [Array<Symbol>] Array of available notifiable options
230
+ def available_dependent_notifications_options
231
+ [ :delete_all,
232
+ :destroy,
233
+ :restrict_with_error,
234
+ :restrict_with_exception,
235
+ :update_group_and_delete_all,
236
+ :update_group_and_destroy
237
+ ].freeze
238
+ end
239
+
240
+ # Adds tracked callbacks.
241
+ # @param [Symbol] target_type Type of notification target as symbol
242
+ # @param [Hash] tracked_option Specified :tracked option
243
+ # @return [Hash<Symbol, Symbol>] Configured tracked callbacks options
244
+ def add_tracked_callbacks(target_type, tracked_option = {})
245
+ tracked_callbacks = [:create, :update]
246
+ if tracked_option[:except]
247
+ tracked_callbacks -= tracked_option.delete(:except)
248
+ elsif tracked_option[:only]
249
+ tracked_callbacks &= tracked_option.delete(:only)
250
+ end
251
+ if tracked_callbacks.include? :create
252
+ if tracked_option.has_key?(:key)
253
+ after_create -> { notify target_type, tracked_option }
254
+ else
255
+ after_create -> { notify target_type, *tracked_option, key: notification_key_for_tracked_creation }
256
+ end
257
+ end
258
+ if tracked_callbacks.include? :update
259
+ if tracked_option.has_key?(:key)
260
+ after_update -> { notify target_type, tracked_option }
261
+ else
262
+ after_update -> { notify target_type, *tracked_option, key: notification_key_for_tracked_update }
263
+ end
264
+ end
265
+ { tracked: tracked_callbacks }
266
+ end
267
+
268
+ # Adds destroy dependency.
269
+ # @param [Symbol] target_type Type of notification target as symbol
270
+ # @param [Symbol] dependent_notifications_option Specified :dependent_notifications option
271
+ # @return [Hash<Symbol, Symbol>] Configured dependency options
272
+ def add_destroy_dependency(target_type, dependent_notifications_option)
273
+ case dependent_notifications_option
274
+ when :delete_all, :destroy, :restrict_with_error, :restrict_with_exception
275
+ before_destroy -> { destroy_generated_notifications_with_dependency(dependent_notifications_option, target_type) }
276
+ when :update_group_and_delete_all
277
+ before_destroy -> { destroy_generated_notifications_with_dependency(:delete_all, target_type, true) }
278
+ when :update_group_and_destroy
279
+ before_destroy -> { destroy_generated_notifications_with_dependency(:destroy, target_type, true) }
280
+ end
281
+ { dependent_notifications: dependent_notifications_option }
282
+ end
283
+
284
+ # Arrange optional targets option.
285
+ # @param [Symbol] optional_targets_option Specified :optional_targets option
286
+ # @return [Hash<ActivityNotification::OptionalTarget::Base, Hash>] Arranged optional targets options
287
+ def arrange_optional_targets_option(optional_targets_option)
288
+ optional_targets_option.map { |target_class, target_options|
289
+ optional_target = target_class.new(target_options)
290
+ unless optional_target.kind_of?(ActivityNotification::OptionalTarget::Base)
291
+ raise TypeError, "#{optional_target.class.name} for an optional target is not a kind of ActivityNotification::OptionalTarget::Base"
292
+ end
293
+ optional_target
294
+ }
295
+ end
215
296
  end
216
297
  end
217
298
  end
@@ -1,3 +1,3 @@
1
1
  module ActivityNotification
2
- VERSION = "1.3.0"
2
+ VERSION = "1.4.0"
3
3
  end
@@ -313,10 +313,11 @@ shared_examples_for :notification_api do
313
313
 
314
314
  context "out of the group expiry period" do
315
315
  it "does not belong to single group" do
316
- owner_notification = described_class.notify_to(@user_1, @comment_1, group: @article, group_expiry_delay: 1.second)
317
- member_notification_1 = described_class.notify_to(@user_1, @comment_2, group: @article, group_expiry_delay: 1.second)
318
- sleep(1)
319
- member_notification_2 = described_class.notify_to(@user_1, @comment_2, group: @article, group_expiry_delay: 1.second)
316
+ Timecop.travel(90.seconds.ago)
317
+ owner_notification = described_class.notify_to(@user_1, @comment_1, group: @article, group_expiry_delay: 1.minute)
318
+ member_notification_1 = described_class.notify_to(@user_1, @comment_2, group: @article, group_expiry_delay: 1.minute)
319
+ Timecop.return
320
+ member_notification_2 = described_class.notify_to(@user_1, @comment_2, group: @article, group_expiry_delay: 1.minute)
320
321
  expect(member_notification_1.group_owner).to eq(owner_notification)
321
322
  expect(member_notification_2.group_owner).to be_nil
322
323
  end
@@ -568,7 +569,7 @@ shared_examples_for :notification_api do
568
569
  context "as default" do
569
570
  it "open notification with current time" do
570
571
  expect(test_instance.opened_at.blank?).to be_truthy
571
- Timecop.freeze(Time.current)
572
+ Timecop.freeze(Time.at(Time.now.to_i))
572
573
  test_instance.open!
573
574
  expect(test_instance.opened_at.blank?).to be_falsey
574
575
  expect(test_instance.opened_at).to eq(Time.current)
@@ -578,7 +579,7 @@ shared_examples_for :notification_api do
578
579
  it "open group member notifications with current time" do
579
580
  group_member = create(test_class_name, group_owner: test_instance)
580
581
  expect(group_member.opened_at.blank?).to be_truthy
581
- Timecop.freeze(Time.current)
582
+ Timecop.freeze(Time.at(Time.now.to_i))
582
583
  test_instance.open!
583
584
  group_member = group_member.reload
584
585
  expect(group_member.opened_at.blank?).to be_falsey
@@ -593,7 +594,7 @@ shared_examples_for :notification_api do
593
594
  opened_at = Time.current - 1.months
594
595
  test_instance.open!(opened_at: opened_at)
595
596
  expect(test_instance.opened_at.blank?).to be_falsey
596
- expect(test_instance.opened_at).to eq(opened_at)
597
+ expect(test_instance.opened_at.to_i).to eq(opened_at.to_i)
597
598
  end
598
599
 
599
600
  it "open group member notifications with specified time" do
@@ -1146,7 +1147,7 @@ shared_examples_for :notification_api do
1146
1147
  context "with group member" do
1147
1148
  it "returns latest group member" do
1148
1149
  member1 = create(test_class_name, target: test_instance.target, group_owner: test_instance)
1149
- member2 = create(test_class_name, target: test_instance.target, group_owner: test_instance)
1150
+ member2 = create(test_class_name, target: test_instance.target, group_owner: test_instance, created_at: member1.created_at + 10.second)
1150
1151
  expect(test_instance.latest_group_member.becomes(ActivityNotification::Notification)).to eq(member2)
1151
1152
  end
1152
1153
  end
@@ -37,12 +37,12 @@ shared_examples_for :subscription_api do
37
37
  it "subscribe with current time" do
38
38
  expect(test_instance.subscribing?).to eq(false)
39
39
  expect(test_instance.subscribing_to_email?).to eq(false)
40
- Timecop.freeze(Time.current)
40
+ Timecop.freeze(Time.at(Time.now.to_i))
41
41
  test_instance.subscribe
42
42
  expect(test_instance.subscribing?).to eq(true)
43
43
  expect(test_instance.subscribing_to_email?).to eq(true)
44
- expect(test_instance.subscribed_at).to eq(Time.current)
45
- expect(test_instance.subscribed_to_email_at).to eq(Time.current)
44
+ expect(test_instance.subscribed_at).to eq(Time.current)
45
+ expect(test_instance.subscribed_to_email_at).to eq(Time.current)
46
46
  Timecop.return
47
47
  end
48
48
  end
@@ -55,8 +55,8 @@ shared_examples_for :subscription_api do
55
55
  test_instance.subscribe(subscribed_at: subscribed_at)
56
56
  expect(test_instance.subscribing?).to eq(true)
57
57
  expect(test_instance.subscribing_to_email?).to eq(true)
58
- expect(test_instance.subscribed_at).to eq(subscribed_at)
59
- expect(test_instance.subscribed_to_email_at).to eq(subscribed_at)
58
+ expect(test_instance.subscribed_at.to_i).to eq(subscribed_at.to_i)
59
+ expect(test_instance.subscribed_to_email_at.to_i).to eq(subscribed_at.to_i)
60
60
  end
61
61
  end
62
62
 
@@ -102,12 +102,12 @@ shared_examples_for :subscription_api do
102
102
  it "unsubscribe with current time" do
103
103
  expect(test_instance.subscribing?).to eq(true)
104
104
  expect(test_instance.subscribing_to_email?).to eq(true)
105
- Timecop.freeze(Time.current)
105
+ Timecop.freeze(Time.at(Time.now.to_i))
106
106
  test_instance.unsubscribe
107
107
  expect(test_instance.subscribing?).to eq(false)
108
108
  expect(test_instance.subscribing_to_email?).to eq(false)
109
- expect(test_instance.unsubscribed_at).to eq(Time.current)
110
- expect(test_instance.unsubscribed_to_email_at).to eq(Time.current)
109
+ expect(test_instance.unsubscribed_at).to eq(Time.current)
110
+ expect(test_instance.unsubscribed_to_email_at).to eq(Time.current)
111
111
  Timecop.return
112
112
  end
113
113
  end
@@ -120,8 +120,8 @@ shared_examples_for :subscription_api do
120
120
  test_instance.unsubscribe(unsubscribed_at: unsubscribed_at)
121
121
  expect(test_instance.subscribing?).to eq(false)
122
122
  expect(test_instance.subscribing_to_email?).to eq(false)
123
- expect(test_instance.unsubscribed_at).to eq(unsubscribed_at)
124
- expect(test_instance.unsubscribed_to_email_at).to eq(unsubscribed_at)
123
+ expect(test_instance.unsubscribed_at.to_i).to eq(unsubscribed_at.to_i)
124
+ expect(test_instance.unsubscribed_to_email_at.to_i).to eq(unsubscribed_at.to_i)
125
125
  end
126
126
  end
127
127
  end
@@ -152,11 +152,11 @@ shared_examples_for :subscription_api do
152
152
  it "subscribe_to_email with current time" do
153
153
  expect(test_instance.subscribing?).to eq(true)
154
154
  expect(test_instance.subscribing_to_email?).to eq(false)
155
- Timecop.freeze(Time.current)
155
+ Timecop.freeze(Time.at(Time.now.to_i))
156
156
  test_instance.subscribe_to_email
157
157
  expect(test_instance.subscribing?).to eq(true)
158
158
  expect(test_instance.subscribing_to_email?).to eq(true)
159
- expect(test_instance.subscribed_to_email_at).to eq(Time.current)
159
+ expect(test_instance.subscribed_to_email_at).to eq(Time.current)
160
160
  Timecop.return
161
161
  end
162
162
  end
@@ -169,7 +169,7 @@ shared_examples_for :subscription_api do
169
169
  test_instance.subscribe_to_email(subscribed_to_email_at: subscribed_to_email_at)
170
170
  expect(test_instance.subscribing?).to eq(true)
171
171
  expect(test_instance.subscribing_to_email?).to eq(true)
172
- expect(test_instance.subscribed_to_email_at).to eq(subscribed_to_email_at)
172
+ expect(test_instance.subscribed_to_email_at.to_i).to eq(subscribed_to_email_at.to_i)
173
173
  end
174
174
  end
175
175
  end
@@ -183,11 +183,11 @@ shared_examples_for :subscription_api do
183
183
  it "unsubscribe_to_email with current time" do
184
184
  expect(test_instance.subscribing?).to eq(true)
185
185
  expect(test_instance.subscribing_to_email?).to eq(true)
186
- Timecop.freeze(Time.current)
186
+ Timecop.freeze(Time.at(Time.now.to_i))
187
187
  test_instance.unsubscribe_to_email
188
188
  expect(test_instance.subscribing?).to eq(true)
189
189
  expect(test_instance.subscribing_to_email?).to eq(false)
190
- expect(test_instance.unsubscribed_to_email_at).to eq(Time.current)
190
+ expect(test_instance.unsubscribed_to_email_at).to eq(Time.current)
191
191
  Timecop.return
192
192
  end
193
193
  end
@@ -200,7 +200,7 @@ shared_examples_for :subscription_api do
200
200
  test_instance.unsubscribe_to_email(unsubscribed_to_email_at: unsubscribed_to_email_at)
201
201
  expect(test_instance.subscribing?).to eq(true)
202
202
  expect(test_instance.subscribing_to_email?).to eq(false)
203
- expect(test_instance.unsubscribed_to_email_at).to eq(unsubscribed_to_email_at)
203
+ expect(test_instance.unsubscribed_to_email_at.to_i).to eq(unsubscribed_to_email_at.to_i)
204
204
  end
205
205
  end
206
206
  end
@@ -275,7 +275,7 @@ shared_examples_for :subscription_api do
275
275
  it "subscribe_to_optional_target with current time" do
276
276
  expect(test_instance.subscribing?).to eq(true)
277
277
  expect(test_instance.subscribing_to_optional_target?(:console_output)).to eq(false)
278
- Timecop.freeze(Time.current)
278
+ Timecop.freeze(Time.at(Time.now.to_i))
279
279
  test_instance.subscribe_to_optional_target(:console_output)
280
280
  expect(test_instance.subscribing?).to eq(true)
281
281
  expect(test_instance.subscribing_to_optional_target?(:console_output)).to eq(true)
@@ -286,13 +286,13 @@ shared_examples_for :subscription_api do
286
286
 
287
287
  context "with subscribed_at option" do
288
288
  it "subscribe with specified time" do
289
- expect(test_instance.subscribing?).to eq(true)
290
- expect(test_instance.subscribing_to_optional_target?(:console_output)).to eq(false)
289
+ expect(test_instance.subscribing?).to eq(true)
290
+ expect(test_instance.subscribing_to_optional_target?(:console_output)).to eq(false)
291
291
  subscribed_at = Time.current - 1.months
292
292
  test_instance.subscribe_to_optional_target(:console_output, subscribed_at: subscribed_at)
293
- expect(test_instance.subscribing?).to eq(true)
294
- expect(test_instance.subscribing_to_optional_target?(:console_output)).to eq(true)
295
- expect(test_instance.optional_targets[:subscribed_to_console_output_at]).to eq(subscribed_at)
293
+ expect(test_instance.subscribing?).to eq(true)
294
+ expect(test_instance.subscribing_to_optional_target?(:console_output)).to eq(true)
295
+ expect(test_instance.optional_targets[:subscribed_to_console_output_at].to_i).to eq(subscribed_at.to_i)
296
296
  end
297
297
  end
298
298
  end
@@ -306,7 +306,7 @@ shared_examples_for :subscription_api do
306
306
  it "unsubscribe_to_optional_target with current time" do
307
307
  expect(test_instance.subscribing?).to eq(true)
308
308
  expect(test_instance.subscribing_to_optional_target?(:console_output)).to eq(true)
309
- Timecop.freeze(Time.current)
309
+ Timecop.freeze(Time.at(Time.now.to_i))
310
310
  test_instance.unsubscribe_to_optional_target(:console_output)
311
311
  expect(test_instance.subscribing?).to eq(true)
312
312
  expect(test_instance.subscribing_to_optional_target?(:console_output)).to eq(false)
@@ -317,13 +317,13 @@ shared_examples_for :subscription_api do
317
317
 
318
318
  context "with unsubscribed_at option" do
319
319
  it "unsubscribe with specified time" do
320
- expect(test_instance.subscribing?).to eq(true)
321
- expect(test_instance.subscribing_to_optional_target?(:console_output)).to eq(true)
320
+ expect(test_instance.subscribing?).to eq(true)
321
+ expect(test_instance.subscribing_to_optional_target?(:console_output)).to eq(true)
322
322
  unsubscribed_at = Time.current - 1.months
323
323
  test_instance.unsubscribe_to_optional_target(:console_output, unsubscribed_at: unsubscribed_at)
324
- expect(test_instance.subscribing?).to eq(true)
325
- expect(test_instance.subscribing_to_optional_target?(:console_output)).to eq(false)
326
- expect(test_instance.optional_targets[:unsubscribed_to_console_output_at]).to eq(unsubscribed_at)
324
+ expect(test_instance.subscribing?).to eq(true)
325
+ expect(test_instance.subscribing_to_optional_target?(:console_output)).to eq(false)
326
+ expect(test_instance.optional_targets[:unsubscribed_to_console_output_at].to_i).to eq(unsubscribed_at.to_i)
327
327
  end
328
328
  end
329
329
  end