activity_notification 1.7.1 → 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 (97) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +3 -0
  3. data/.travis.yml +16 -2
  4. data/CHANGELOG.md +22 -2
  5. data/Gemfile +7 -0
  6. data/Procfile +2 -0
  7. data/README.md +366 -32
  8. data/Rakefile +19 -10
  9. data/activity_notification.gemspec +5 -3
  10. data/app/channels/activity_notification/notification_channel.rb +37 -0
  11. data/app/channels/activity_notification/notification_with_devise_channel.rb +51 -0
  12. data/app/controllers/activity_notification/notifications_controller.rb +1 -1
  13. data/app/controllers/activity_notification/subscriptions_controller.rb +1 -1
  14. data/app/jobs/activity_notification/notify_all_job.rb +16 -0
  15. data/app/jobs/activity_notification/notify_job.rb +17 -0
  16. data/app/jobs/activity_notification/notify_to_job.rb +16 -0
  17. data/app/views/activity_notification/notifications/default/_default_without_grouping.html.erb +1 -1
  18. data/app/views/activity_notification/notifications/default/index.html.erb +55 -2
  19. data/bin/_dynamodblocal +4 -0
  20. data/{scripts → bin}/bundle_update.sh +1 -0
  21. data/bin/deploy_on_heroku.sh +14 -0
  22. data/bin/install_dynamodblocal.sh +5 -0
  23. data/bin/start_dynamodblocal.sh +47 -0
  24. data/bin/stop_dynamodblocal.sh +34 -0
  25. data/gemfiles/Gemfile.rails-4.2 +1 -0
  26. data/gemfiles/Gemfile.rails-5.0 +2 -0
  27. data/gemfiles/Gemfile.rails-5.1 +1 -0
  28. data/gemfiles/Gemfile.rails-5.2 +1 -0
  29. data/gemfiles/Gemfile.rails-6.0.rc +21 -0
  30. data/lib/activity_notification.rb +1 -0
  31. data/lib/activity_notification/apis/notification_api.rb +289 -136
  32. data/lib/activity_notification/apis/subscription_api.rb +80 -53
  33. data/lib/activity_notification/common.rb +3 -3
  34. data/lib/activity_notification/config.rb +89 -33
  35. data/lib/activity_notification/controllers/common_controller.rb +19 -7
  36. data/lib/activity_notification/helpers/errors.rb +4 -0
  37. data/lib/activity_notification/helpers/view_helpers.rb +1 -1
  38. data/lib/activity_notification/models/concerns/notifiable.rb +61 -53
  39. data/lib/activity_notification/models/concerns/subscriber.rb +7 -6
  40. data/lib/activity_notification/models/concerns/target.rb +73 -28
  41. data/lib/activity_notification/optional_targets/base.rb +2 -2
  42. data/lib/activity_notification/orm/active_record/notification.rb +4 -23
  43. data/lib/activity_notification/orm/dynamoid.rb +495 -0
  44. data/lib/activity_notification/orm/dynamoid/extension.rb +184 -0
  45. data/lib/activity_notification/orm/dynamoid/notification.rb +189 -0
  46. data/lib/activity_notification/orm/dynamoid/subscription.rb +82 -0
  47. data/lib/activity_notification/orm/mongoid.rb +4 -1
  48. data/lib/activity_notification/orm/mongoid/notification.rb +8 -25
  49. data/lib/activity_notification/orm/mongoid/subscription.rb +1 -1
  50. data/lib/activity_notification/roles/acts_as_notifiable.rb +33 -5
  51. data/lib/activity_notification/roles/acts_as_target.rb +62 -9
  52. data/lib/activity_notification/version.rb +1 -1
  53. data/lib/generators/templates/activity_notification.rb +30 -7
  54. data/lib/tasks/activity_notification_tasks.rake +14 -4
  55. data/spec/channels/notification_channel_shared_examples.rb +59 -0
  56. data/spec/channels/notification_channel_spec.rb +50 -0
  57. data/spec/channels/notification_with_devise_channel_spec.rb +99 -0
  58. data/spec/concerns/apis/notification_api_spec.rb +2 -2
  59. data/spec/concerns/apis/subscription_api_spec.rb +2 -2
  60. data/spec/concerns/models/notifiable_spec.rb +72 -7
  61. data/spec/concerns/models/subscriber_spec.rb +53 -49
  62. data/spec/concerns/models/target_spec.rb +135 -13
  63. data/spec/config_spec.rb +41 -1
  64. data/spec/controllers/notifications_controller_shared_examples.rb +7 -3
  65. data/spec/controllers/subscriptions_controller_shared_examples.rb +7 -3
  66. data/spec/helpers/view_helpers_spec.rb +12 -10
  67. data/spec/models/dummy/dummy_group_spec.rb +4 -0
  68. data/spec/models/dummy/dummy_notifiable_spec.rb +4 -0
  69. data/spec/models/dummy/dummy_notifier_spec.rb +4 -0
  70. data/spec/models/dummy/dummy_subscriber_spec.rb +3 -0
  71. data/spec/models/dummy/dummy_target_spec.rb +4 -0
  72. data/spec/models/notification_spec.rb +164 -45
  73. data/spec/models/subscription_spec.rb +69 -14
  74. data/spec/orm/dynamoid_spec.rb +115 -0
  75. data/spec/rails_app/app/assets/javascripts/application.js +2 -1
  76. data/spec/rails_app/app/assets/javascripts/cable.js +12 -0
  77. data/spec/rails_app/app/controllers/comments_controller.rb +3 -4
  78. data/spec/rails_app/app/models/admin.rb +6 -4
  79. data/spec/rails_app/app/models/article.rb +2 -2
  80. data/spec/rails_app/app/models/comment.rb +17 -5
  81. data/spec/rails_app/app/models/user.rb +5 -3
  82. data/spec/rails_app/app/views/activity_notification/notifications/users/overridden/custom/_test.html.erb +1 -0
  83. data/spec/rails_app/config/application.rb +6 -1
  84. data/spec/rails_app/config/cable.yml +8 -0
  85. data/spec/rails_app/config/dynamoid.rb +5 -0
  86. data/spec/rails_app/config/environment.rb +4 -1
  87. data/spec/rails_app/config/environments/production.rb +1 -1
  88. data/spec/rails_app/config/initializers/activity_notification.rb +30 -7
  89. data/spec/rails_app/config/locales/activity_notification.en.yml +2 -0
  90. data/spec/rails_app/db/seeds.rb +21 -5
  91. data/spec/rails_app/lib/mailer_previews/mailer_preview.rb +12 -4
  92. data/spec/roles/acts_as_notifiable_spec.rb +2 -2
  93. data/spec/roles/acts_as_target_spec.rb +1 -1
  94. data/spec/spec_helper.rb +15 -8
  95. metadata +67 -20
  96. data/spec/rails_app/app/models/.keep +0 -0
  97. data/spec/rails_app/app/views/activity_notification/notifications/users/overriden/custom/_test.html.erb +0 -1
@@ -10,7 +10,7 @@ shared_examples_for :target do
10
10
  expect(test_instance.notifications.count).to eq(2)
11
11
  expect(test_instance.notifications.earliest).to eq(notification_1)
12
12
  expect(test_instance.notifications.latest).to eq(notification_2)
13
- expect(test_instance.notifications).to eq(ActivityNotification::Notification.filtered_by_target(test_instance))
13
+ expect(test_instance.notifications.to_a).to eq(ActivityNotification::Notification.filtered_by_target(test_instance).to_a)
14
14
  end
15
15
  end
16
16
 
@@ -24,10 +24,15 @@ shared_examples_for :target do
24
24
  describe ".set_target_class_defaults" do
25
25
  it "set parameter fields as default" do
26
26
  described_class.set_target_class_defaults
27
- expect(described_class._notification_email).to eq(nil)
28
- expect(described_class._notification_email_allowed).to eq(ActivityNotification.config.email_enabled)
29
- expect(described_class._notification_devise_resource).to be_a_kind_of(Proc)
30
- expect(described_class._printable_notification_target_name).to eq(:printable_name)
27
+ expect(described_class._notification_email).to eq(nil)
28
+ expect(described_class._notification_email_allowed).to eq(ActivityNotification.config.email_enabled)
29
+ expect(described_class._batch_notification_email_allowed).to eq(ActivityNotification.config.email_enabled)
30
+ expect(described_class._notification_subscription_allowed).to eq(ActivityNotification.config.subscription_enabled)
31
+ expect(described_class._notification_action_cable_allowed).to eq(ActivityNotification.config.action_cable_enabled)
32
+ expect(described_class._notification_action_cable_with_devise).to eq(ActivityNotification.config.action_cable_with_devise)
33
+ expect(described_class._notification_devise_resource).to be_a_kind_of(Proc)
34
+ expect(described_class._notification_current_devise_target).to be_a_kind_of(Proc)
35
+ expect(described_class._printable_notification_target_name).to eq(:printable_name)
31
36
  end
32
37
  end
33
38
 
@@ -264,7 +269,8 @@ shared_examples_for :target do
264
269
  expect(test_instance.notification_email_allowed?(test_notifiable, 'dummy_key')).to eq(true)
265
270
  end
266
271
 
267
- it "returns specified symbol with target and key arguments" do
272
+ it "returns specified symbol with notifiable
273
+ and key arguments" do
268
274
  module AdditionalMethods
269
275
  def custom_notification_email_allowed?(notifiable, key)
270
276
  true
@@ -391,6 +397,117 @@ shared_examples_for :target do
391
397
  end
392
398
  end
393
399
 
400
+ describe "#notification_action_cable_allowed?" do
401
+ context "without any configuration" do
402
+ it "returns ActivityNotification.config.action_cable_enabled without arguments" do
403
+ expect(test_instance.notification_action_cable_allowed?)
404
+ .to eq(ActivityNotification.config.action_cable_enabled)
405
+ end
406
+
407
+ it "returns ActivityNotification.config.action_cable_enabled with arguments" do
408
+ expect(test_instance.notification_action_cable_allowed?(test_notifiable, 'dummy_key'))
409
+ .to eq(ActivityNotification.config.action_cable_enabled)
410
+ end
411
+
412
+ it "returns false as default" do
413
+ expect(test_instance.notification_action_cable_allowed?).to be_falsey
414
+ end
415
+ end
416
+
417
+ context "configured with a field" do
418
+ it "returns specified value" do
419
+ described_class._notification_action_cable_allowed = true
420
+ expect(test_instance.notification_action_cable_allowed?).to eq(true)
421
+ end
422
+
423
+ it "returns specified symbol without argument" do
424
+ module AdditionalMethods
425
+ def custom_notification_action_cable_allowed?
426
+ true
427
+ end
428
+ end
429
+ test_instance.extend(AdditionalMethods)
430
+ described_class._notification_action_cable_allowed = :custom_notification_action_cable_allowed?
431
+ expect(test_instance.notification_action_cable_allowed?).to eq(true)
432
+ end
433
+
434
+ it "returns specified symbol with notifiable and key arguments" do
435
+ module AdditionalMethods
436
+ def custom_notification_action_cable_allowed?(notifiable, key)
437
+ true
438
+ end
439
+ end
440
+ test_instance.extend(AdditionalMethods)
441
+ described_class._notification_action_cable_allowed = :custom_notification_action_cable_allowed?
442
+ expect(test_instance.notification_action_cable_allowed?(test_notifiable, 'dummy_key')).to eq(true)
443
+ end
444
+
445
+ it "returns specified lambda with single target argument" do
446
+ described_class._notification_action_cable_allowed = ->(target){ true }
447
+ expect(test_instance.notification_action_cable_allowed?(test_notifiable, 'dummy_key')).to eq(true)
448
+ end
449
+
450
+ it "returns specified lambda with target, notifiable and key arguments" do
451
+ described_class._notification_action_cable_allowed = ->(target, notifiable, key){ true }
452
+ expect(test_instance.notification_action_cable_allowed?(test_notifiable, 'dummy_key')).to eq(true)
453
+ end
454
+ end
455
+ end
456
+
457
+ describe "#notification_action_cable_with_devise?" do
458
+ context "without any configuration" do
459
+ it "returns ActivityNotification.config.action_cable_with_devise without arguments" do
460
+ expect(test_instance.notification_action_cable_with_devise?)
461
+ .to eq(ActivityNotification.config.action_cable_with_devise)
462
+ end
463
+
464
+ it "returns false as default" do
465
+ expect(test_instance.notification_action_cable_with_devise?).to be_falsey
466
+ end
467
+ end
468
+
469
+ context "configured with a field" do
470
+ it "returns specified value" do
471
+ described_class._notification_action_cable_with_devise = true
472
+ expect(test_instance.notification_action_cable_with_devise?).to eq(true)
473
+ end
474
+
475
+ it "returns specified symbol without argument" do
476
+ module AdditionalMethods
477
+ def custom_notification_action_cable_with_devise?
478
+ true
479
+ end
480
+ end
481
+ test_instance.extend(AdditionalMethods)
482
+ described_class._notification_action_cable_with_devise = :custom_notification_action_cable_with_devise?
483
+ expect(test_instance.notification_action_cable_with_devise?).to eq(true)
484
+ end
485
+
486
+ it "returns specified lambda with single target argument" do
487
+ described_class._notification_action_cable_with_devise = ->(target){ true }
488
+ expect(test_instance.notification_action_cable_with_devise?).to eq(true)
489
+ end
490
+ end
491
+ end
492
+
493
+ if Rails::VERSION::MAJOR >= 5
494
+ describe "#notification_action_cable_channel_class_name" do
495
+ context "when custom_notification_action_cable_with_devise? returns true" do
496
+ it "returns ActivityNotification::NotificationWithDeviseChannel" do
497
+ described_class._notification_action_cable_with_devise = true
498
+ expect(test_instance.notification_action_cable_channel_class_name).to eq(ActivityNotification::NotificationWithDeviseChannel.name)
499
+ end
500
+ end
501
+
502
+ context "when custom_notification_action_cable_with_devise? returns false" do
503
+ it "returns ActivityNotification::NotificationChannel" do
504
+ described_class._notification_action_cable_with_devise = false
505
+ expect(test_instance.notification_action_cable_channel_class_name).to eq(ActivityNotification::NotificationChannel.name)
506
+ end
507
+ end
508
+ end
509
+ end
510
+
394
511
  describe "#authenticated_with_devise?" do
395
512
  context "without any configuration" do
396
513
  context "when the current devise resource and called target are different class instance" do
@@ -614,16 +731,21 @@ shared_examples_for :target do
614
731
 
615
732
  context 'with custom_filter options' do
616
733
  it "returns filtered notifications only" do
617
- if ActivityNotification.config.orm == :active_record
618
- options = { custom_filter: ["notifications.key = ?", @key] }
619
- expect(test_instance.notification_index(options)[0]).to eq(@notification3)
620
- expect(test_instance.notification_index(options).size).to eq(1)
621
- end
622
-
623
734
  options = { custom_filter: { key: @key } }
624
735
  expect(test_instance.notification_index(options)[0]).to eq(@notification3)
625
736
  expect(test_instance.notification_index(options).size).to eq(1)
626
737
  end
738
+
739
+ it "returns filtered notifications only with filter depending on ORM" do
740
+ options =
741
+ case ActivityNotification.config.orm
742
+ when :active_record then { custom_filter: ["notifications.key = ?", @key] }
743
+ when :mongoid then { custom_filter: { key: {'$eq': @key} } }
744
+ when :dynamoid then { custom_filter: {'key.begins_with': @key} }
745
+ end
746
+ expect(test_instance.notification_index(options)[0]).to eq(@notification3)
747
+ expect(test_instance.notification_index(options).size).to eq(1)
748
+ end
627
749
  end
628
750
  end
629
751
 
@@ -800,7 +922,7 @@ shared_examples_for :target do
800
922
  end
801
923
 
802
924
 
803
- # Methods to be overriden
925
+ # Methods to be overridden
804
926
 
805
927
  describe "#notification_index_with_attributes" do
806
928
  context "when the target has no notifications" do
@@ -7,7 +7,7 @@ describe ActivityNotification::Config do
7
7
  expect(ActivityNotification::Mailer).to receive(:send_notification_email).and_call_original
8
8
  notification.send_notification_email send_later: false
9
9
  end
10
-
10
+
11
11
  it "is not configured with CustomNotificationMailer" do
12
12
  expect(CustomNotificationMailer).not_to receive(:send_notification_email).and_call_original
13
13
  notification.send_notification_email send_later: false
@@ -31,4 +31,44 @@ describe ActivityNotification::Config do
31
31
  end
32
32
  end
33
33
  end
34
+
35
+ describe "config.store_with_associated_records" do
36
+ let(:target) { create(:confirmed_user) }
37
+
38
+ context "false as default" do
39
+ before do
40
+ @notification = create(:notification, target: target)
41
+ end
42
+
43
+ it "stores notification without associated records" do
44
+ expect(@notification.target).to eq(target)
45
+ expect { @notification.target_record }.to raise_error(NoMethodError)
46
+ end
47
+ end
48
+
49
+ context "when it is configured as true" do
50
+ if ActivityNotification.config.orm == :active_record
51
+ it "raises ActivityNotification::ConfigError when you use active_record ORM" do
52
+ expect { ActivityNotification.config.store_with_associated_records = true }.to raise_error(ActivityNotification::ConfigError)
53
+ end
54
+
55
+ else
56
+ before do
57
+ ActivityNotification.config.store_with_associated_records = true
58
+ load Rails.root.join("../../lib/activity_notification/orm/#{ActivityNotification.config.orm}/notification.rb").to_s
59
+ @notification = create(:notification, target: target)
60
+ end
61
+
62
+ after do
63
+ ActivityNotification.config.store_with_associated_records = false
64
+ load Rails.root.join("../../lib/activity_notification/orm/#{ActivityNotification.config.orm}/notification.rb").to_s
65
+ end
66
+
67
+ it "stores notification without associated records" do
68
+ expect(@notification.target).to eq(target)
69
+ expect(@notification.target_record).to eq(target.to_json)
70
+ end
71
+ end
72
+ end
73
+ end
34
74
  end
@@ -80,12 +80,16 @@ shared_examples_for :notification_controller do
80
80
  end
81
81
 
82
82
  it "returns json format" do
83
- if ActivityNotification.config.orm == :active_record
83
+ case ActivityNotification.config.orm
84
+ when :active_record
84
85
  expect(JSON.parse(response.body).first)
85
86
  .to include("target_id" => test_target.id, "target_type" => test_target.to_class_name)
86
- else
87
+ when :mongoid
87
88
  expect(JSON.parse(response.body).first)
88
89
  .to include("target_id" => test_target.id.to_s, "target_type" => test_target.to_class_name)
90
+ when :dynamoid
91
+ expect(JSON.parse(response.body).first)
92
+ .to include("target_key" => "#{test_target.to_class_name}#{ActivityNotification.config.composite_key_delimiter}#{test_target.id}")
89
93
  end
90
94
  end
91
95
  end
@@ -221,7 +225,7 @@ shared_examples_for :notification_controller do
221
225
  end
222
226
  end
223
227
 
224
- context 'with filtered_by_group_type and :filtered_by_group_id parameters' do
228
+ context 'with filtered_by_group_type and filtered_by_group_id parameters' do
225
229
  it "returns filtered notifications only" do
226
230
  get_with_compatibility :index, target_params.merge({ typed_target_param => test_target, filtered_by_group_type: 'Article', filtered_by_group_id: @group.id.to_s }), valid_session
227
231
  expect(assigns(:notifications)[0]).to eq(@notification1)
@@ -93,12 +93,16 @@ shared_examples_for :subscription_controller do
93
93
  end
94
94
 
95
95
  it "returns json format" do
96
- if ActivityNotification.config.orm == :active_record
96
+ case ActivityNotification.config.orm
97
+ when :active_record
97
98
  expect(JSON.parse(response.body)["subscriptions"].first)
98
99
  .to include("target_id" => test_target.id, "target_type" => test_target.to_class_name)
99
- else
100
+ when :mongoid
100
101
  expect(JSON.parse(response.body)["subscriptions"].first)
101
102
  .to include("target_id" => test_target.id.to_s, "target_type" => test_target.to_class_name)
103
+ when :dynamoid
104
+ expect(JSON.parse(response.body)["subscriptions"].first)
105
+ .to include("target_key" => "#{test_target.to_class_name}#{ActivityNotification.config.composite_key_delimiter}#{test_target.id}")
102
106
  end
103
107
  expect(JSON.parse(response.body)["unconfigured_notification_keys"].first)
104
108
  .to eq('test_notification_key')
@@ -227,7 +231,7 @@ shared_examples_for :subscription_controller do
227
231
 
228
232
  describe "POST #create" do
229
233
  before do
230
- expect(test_target.subscriptions.size).to eq(0)
234
+ expect(test_target.subscriptions.size).to eq(0)
231
235
  end
232
236
 
233
237
  context "http direct POST request without optional targets" do
@@ -46,12 +46,14 @@ describe ActivityNotification::ViewHelpers, type: :helper do
46
46
  )
47
47
  end
48
48
 
49
- if ActivityNotification.config.orm == :active_record
50
- it 'handles multiple notifications of active_record' do
51
- expect(notifications.to_a.first).to receive(:render).with(self, { fallback: :default })
52
- expect(notifications.to_a.last).to receive(:render).with(self, { fallback: :default })
53
- render_notification notifications, fallback: :default
54
- end
49
+ it 'handles multiple notifications of records' do
50
+ rendered_template = render_notification notifications, fallback: :default
51
+ expect(rendered_template).to start_with(
52
+ render partial: 'activity_notification/notifications/default/default',
53
+ locals: { notification: notifications.to_a.first, parameters: {} })
54
+ expect(rendered_template).to end_with(
55
+ render partial: 'activity_notification/notifications/default/default',
56
+ locals: { notification: notifications.to_a.last , parameters: {} })
55
57
  end
56
58
 
57
59
  it 'handles multiple notifications of array' do
@@ -117,17 +119,17 @@ describe ActivityNotification::ViewHelpers, type: :helper do
117
119
  end
118
120
 
119
121
  context "with defined overriding_notification_template_key in notifiable model" do
120
- it "renders overriden custom notification view" do
122
+ it "renders overridden custom notification view" do
121
123
  notification.key = 'custom.test'
122
124
  module AdditionalMethods
123
125
  def overriding_notification_template_key(target, key)
124
- 'overriden.custom.test'
126
+ 'overridden.custom.test'
125
127
  end
126
128
  end
127
129
  notification.notifiable.extend(AdditionalMethods)
128
- # render activity_notification/notifications/users/overriden/custom/test
130
+ # render activity_notification/notifications/users/overridden/custom/test
129
131
  expect(render_notification notification, target: :users)
130
- .to eq("Overriden custom template root for user target: #{notification.id}")
132
+ .to eq("Overridden custom template root for user target: #{notification.id}")
131
133
  end
132
134
  end
133
135
  end
@@ -1,3 +1,7 @@
1
+ # To run as single test for debugging
2
+ # require Rails.root.join('../../spec/concerns/models/group_spec.rb').to_s
3
+ # require Rails.root.join('../../spec/concerns/common_spec.rb').to_s
4
+
1
5
  describe Dummy::DummyGroup, type: :model do
2
6
 
3
7
  it_behaves_like :group
@@ -1,3 +1,7 @@
1
+ # To run as single test for debugging
2
+ # require Rails.root.join('../../spec/concerns/models/notifiable_spec.rb').to_s
3
+ # require Rails.root.join('../../spec/concerns/common_spec.rb').to_s
4
+
1
5
  describe Dummy::DummyNotifiable, type: :model do
2
6
 
3
7
  it_behaves_like :notifiable
@@ -1,3 +1,7 @@
1
+ # To run as single test for debugging
2
+ # require Rails.root.join('../../spec/concerns/models/notifier_spec.rb').to_s
3
+ # require Rails.root.join('../../spec/concerns/common_spec.rb').to_s
4
+
1
5
  describe Dummy::DummyNotifier, type: :model do
2
6
 
3
7
  it_behaves_like :notifier
@@ -1,3 +1,6 @@
1
+ # To run as single test for debugging
2
+ # require Rails.root.join('../../spec/concerns/models/subscriber_spec.rb').to_s
3
+
1
4
  describe Dummy::DummySubscriber, type: :model do
2
5
 
3
6
  it_behaves_like :subscriber
@@ -1,3 +1,7 @@
1
+ # To run as single test for debugging
2
+ # require Rails.root.join('../../spec/concerns/models/target_spec.rb').to_s
3
+ # require Rails.root.join('../../spec/concerns/common_spec.rb').to_s
4
+
1
5
  describe Dummy::DummyTarget, type: :model do
2
6
 
3
7
  it_behaves_like :target
@@ -1,13 +1,30 @@
1
+ # To run as single test for debugging
2
+ # require Rails.root.join('../../spec/concerns/apis/notification_api_spec.rb').to_s
3
+ # require Rails.root.join('../../spec/concerns/renderable_spec.rb').to_s
4
+
1
5
  describe ActivityNotification::Notification, type: :model do
2
6
 
3
7
  it_behaves_like :notification_api
4
8
  it_behaves_like :renderable
5
9
 
6
10
  describe "with association" do
7
- it "belongs to target" do
8
- target = create(:confirmed_user)
9
- notification = create(:notification, target: target)
10
- expect(notification.reload.target).to eq(target)
11
+ context "belongs to target" do
12
+ before do
13
+ @target = create(:confirmed_user)
14
+ @notification = create(:notification, target: @target)
15
+ end
16
+
17
+ it "responds to target" do
18
+ expect(@notification.reload.target).to eq(@target)
19
+ end
20
+
21
+ it "responds to target_id" do
22
+ expect(@notification.reload.target_id.to_s).to eq(@target.id.to_s)
23
+ end
24
+
25
+ it "responds to target_type" do
26
+ expect(@notification.reload.target_type).to eq("User")
27
+ end
11
28
  end
12
29
 
13
30
  it "belongs to notifiable" do
@@ -42,18 +59,16 @@ describe ActivityNotification::Notification, type: :model do
42
59
  end
43
60
 
44
61
  describe "with serializable column" do
45
- if ActivityNotification.config.orm == :active_record
46
- it "has parameters for hash with symbol" do
47
- parameters = {a: 1, b: 2, c: 3}
48
- notification = create(:notification, parameters: parameters)
49
- expect(notification.reload.parameters).to eq(parameters)
50
- end
62
+ it "has parameters for hash with symbol" do
63
+ parameters = {a: 1, b: 2, c: 3}
64
+ notification = create(:notification, parameters: parameters)
65
+ expect(notification.reload.parameters.symbolize_keys).to eq(parameters)
51
66
  end
52
67
 
53
68
  it "has parameters for hash with string" do
54
69
  parameters = {'a' => 1, 'b' => 2, 'c' => 3}
55
70
  notification = create(:notification, parameters: parameters)
56
- expect(notification.reload.parameters).to eq(parameters)
71
+ expect(notification.reload.parameters.stringify_keys).to eq(parameters)
57
72
  end
58
73
  end
59
74
 
@@ -67,19 +82,19 @@ describe ActivityNotification::Notification, type: :model do
67
82
  it "is invalid with blank target" do
68
83
  @notification.target = nil
69
84
  expect(@notification).to be_invalid
70
- expect(@notification.errors[:target].size).to eq(1)
85
+ expect(@notification.errors[:target]).not_to be_empty
71
86
  end
72
87
 
73
88
  it "is invalid with blank notifiable" do
74
89
  @notification.notifiable = nil
75
90
  expect(@notification).to be_invalid
76
- expect(@notification.errors[:notifiable].size).to eq(1)
91
+ expect(@notification.errors[:notifiable]).not_to be_empty
77
92
  end
78
93
 
79
94
  it "is invalid with blank key" do
80
95
  @notification.key = nil
81
96
  expect(@notification).to be_invalid
82
- expect(@notification.errors[:key].size).to eq(1)
97
+ expect(@notification.errors[:key]).not_to be_empty
83
98
  end
84
99
  end
85
100
 
@@ -99,34 +114,34 @@ describe ActivityNotification::Notification, type: :model do
99
114
  expect(notifications.unopened_only.first).to eq(@unopened_group_owner)
100
115
  expect(notifications.opened_only!.first).to eq(@opened_group_owner)
101
116
  end
102
-
117
+
103
118
  it "works with group_members_only scope" do
104
119
  notifications = ActivityNotification::Notification.group_members_only
105
120
  expect(notifications.to_a.size).to eq(2)
106
121
  expect(notifications.unopened_only.first).to eq(@unopened_group_member)
107
122
  expect(notifications.opened_only!.first).to eq(@opened_group_member)
108
123
  end
109
-
124
+
110
125
  it "works with unopened_only scope" do
111
126
  notifications = ActivityNotification::Notification.unopened_only
112
127
  expect(notifications.to_a.size).to eq(2)
113
128
  expect(notifications.group_owners_only.first).to eq(@unopened_group_owner)
114
129
  expect(notifications.group_members_only.first).to eq(@unopened_group_member)
115
130
  end
116
-
131
+
117
132
  it "works with unopened_index scope" do
118
133
  notifications = ActivityNotification::Notification.unopened_index
119
134
  expect(notifications.to_a.size).to eq(1)
120
135
  expect(notifications.first).to eq(@unopened_group_owner)
121
136
  end
122
-
137
+
123
138
  it "works with opened_only! scope" do
124
139
  notifications = ActivityNotification::Notification.opened_only!
125
140
  expect(notifications.to_a.size).to eq(2)
126
141
  expect(notifications.group_owners_only.first).to eq(@opened_group_owner)
127
142
  expect(notifications.group_members_only.first).to eq(@opened_group_member)
128
143
  end
129
-
144
+
130
145
  context "with opened_only scope" do
131
146
  it "works" do
132
147
  notifications = ActivityNotification::Notification.opened_only(4)
@@ -134,39 +149,39 @@ describe ActivityNotification::Notification, type: :model do
134
149
  expect(notifications.group_owners_only.first).to eq(@opened_group_owner)
135
150
  expect(notifications.group_members_only.first).to eq(@opened_group_member)
136
151
  end
137
-
152
+
138
153
  it "works with limit" do
139
154
  notifications = ActivityNotification::Notification.opened_only(1)
140
155
  expect(notifications.to_a.size).to eq(1)
141
156
  end
142
157
  end
143
-
158
+
144
159
  context "with opened_index scope" do
145
160
  it "works" do
146
161
  notifications = ActivityNotification::Notification.opened_index(4)
147
162
  expect(notifications.to_a.size).to eq(1)
148
163
  expect(notifications.first).to eq(@opened_group_owner)
149
164
  end
150
-
165
+
151
166
  it "works with limit" do
152
167
  notifications = ActivityNotification::Notification.opened_index(0)
153
168
  expect(notifications.to_a.size).to eq(0)
154
169
  end
155
170
  end
156
-
171
+
157
172
  it "works with unopened_index_group_members_only scope" do
158
173
  notifications = ActivityNotification::Notification.unopened_index_group_members_only
159
174
  expect(notifications.to_a.size).to eq(1)
160
175
  expect(notifications.first).to eq(@unopened_group_member)
161
176
  end
162
-
177
+
163
178
  context "with opened_index_group_members_only scope" do
164
179
  it "works" do
165
180
  notifications = ActivityNotification::Notification.opened_index_group_members_only(4)
166
181
  expect(notifications.to_a.size).to eq(1)
167
182
  expect(notifications.first).to eq(@opened_group_member)
168
183
  end
169
-
184
+
170
185
  it "works with limit" do
171
186
  notifications = ActivityNotification::Notification.opened_index_group_members_only(0)
172
187
  expect(notifications.to_a.size).to eq(0)
@@ -239,7 +254,7 @@ describe ActivityNotification::Notification, type: :model do
239
254
  expect(notifications.first).to eq(@notification_2)
240
255
  end
241
256
  end
242
-
257
+
243
258
  context 'with filtered_by_group options' do
244
259
  it "works with filtered_by_options scope" do
245
260
  notifications = ActivityNotification::Notification.filtered_by_options({ filtered_by_group: @group_1 })
@@ -276,18 +291,24 @@ describe ActivityNotification::Notification, type: :model do
276
291
 
277
292
  context 'with custom_filter options' do
278
293
  it "works with filtered_by_options scope" do
279
- if ActivityNotification.config.orm == :active_record
280
- notifications = ActivityNotification::Notification.filtered_by_options({ custom_filter: ["notifications.key = ?", @key_1] })
281
- expect(notifications.to_a.size).to eq(1)
282
- expect(notifications.first).to eq(@notification_1)
283
- end
284
-
285
294
  notifications = ActivityNotification::Notification.filtered_by_options({ custom_filter: { key: @key_2 } })
286
295
  expect(notifications.to_a.size).to eq(1)
287
296
  expect(notifications.first).to eq(@notification_2)
288
297
  end
298
+
299
+ it "works with filtered_by_options scope with filter depending on ORM" do
300
+ options =
301
+ case ActivityNotification.config.orm
302
+ when :active_record then { custom_filter: ["notifications.key = ?", @key_1] }
303
+ when :mongoid then { custom_filter: { key: {'$eq': @key_1} } }
304
+ when :dynamoid then { custom_filter: {'key.begins_with': @key_1} }
305
+ end
306
+ notifications = ActivityNotification::Notification.filtered_by_options(options)
307
+ expect(notifications.to_a.size).to eq(1)
308
+ expect(notifications.first).to eq(@notification_1)
309
+ end
289
310
  end
290
-
311
+
291
312
  context 'with no options' do
292
313
  it "works with filtered_by_options scope" do
293
314
  notifications = ActivityNotification::Notification.filtered_by_options
@@ -300,37 +321,135 @@ describe ActivityNotification::Notification, type: :model do
300
321
  context "to make order by created_at" do
301
322
  before do
302
323
  ActivityNotification::Notification.delete_all
303
- unopened_group_owner = create(:notification, group_owner: nil)
304
- unopened_group_member = create(:notification, group_owner: unopened_group_owner, created_at: unopened_group_owner.created_at + 10.second)
305
- opened_group_owner = create(:notification, group_owner: nil, opened_at: Time.current, created_at: unopened_group_owner.created_at + 20.second)
306
- opened_group_member = create(:notification, group_owner: opened_group_owner, opened_at: Time.current, created_at: unopened_group_owner.created_at + 30.second)
324
+ @target = create(:confirmed_user)
325
+ unopened_group_owner = create(:notification, target: @target, group_owner: nil)
326
+ unopened_group_member = create(:notification, target: @target, group_owner: unopened_group_owner, created_at: unopened_group_owner.created_at + 10.second)
327
+ opened_group_owner = create(:notification, target: @target, group_owner: nil, opened_at: Time.current, created_at: unopened_group_owner.created_at + 20.second)
328
+ opened_group_member = create(:notification, target: @target, group_owner: opened_group_owner, opened_at: Time.current, created_at: unopened_group_owner.created_at + 30.second)
307
329
  @earliest_notification = unopened_group_owner
308
330
  @latest_notification = opened_group_member
309
331
  end
310
332
 
311
- it "works with latest_order scope" do
312
- notifications = ActivityNotification::Notification.latest_order
333
+ unless ActivityNotification.config.orm == :dynamoid
334
+ context "using ORM other than dynamoid, you can directly call latest/earliest order method from class objects" do
335
+
336
+ it "works with latest_order scope" do
337
+ notifications = ActivityNotification::Notification.latest_order
338
+ expect(notifications.to_a.size).to eq(4)
339
+ expect(notifications.first).to eq(@latest_notification)
340
+ expect(notifications.last).to eq(@earliest_notification)
341
+ end
342
+
343
+ it "works with earliest_order scope" do
344
+ notifications = ActivityNotification::Notification.earliest_order
345
+ expect(notifications.to_a.size).to eq(4)
346
+ expect(notifications.first).to eq(@earliest_notification)
347
+ expect(notifications.last).to eq(@latest_notification)
348
+ end
349
+
350
+ it "returns the latest notification with latest scope" do
351
+ notification = ActivityNotification::Notification.latest
352
+ expect(notification).to eq(@latest_notification)
353
+ end
354
+
355
+ it "returns the earliest notification with earliest scope" do
356
+ notification = ActivityNotification::Notification.earliest
357
+ expect(notification).to eq(@earliest_notification)
358
+ end
359
+
360
+ end
361
+ else
362
+ context "using dynamoid, you can call latest/earliest order method only with query using partition key of Global Secondary Index" do
363
+
364
+ it "works with latest_order scope" do
365
+ notifications = ActivityNotification::Notification.filtered_by_target(@target).latest_order
366
+ expect(notifications.to_a.size).to eq(4)
367
+ expect(notifications.first).to eq(@latest_notification)
368
+ expect(notifications.last).to eq(@earliest_notification)
369
+ end
370
+
371
+ it "works with earliest_order scope" do
372
+ notifications = ActivityNotification::Notification.filtered_by_target(@target).earliest_order
373
+ expect(notifications.to_a.size).to eq(4)
374
+ expect(notifications.first).to eq(@earliest_notification)
375
+ expect(notifications.last).to eq(@latest_notification)
376
+ end
377
+
378
+ it "returns the latest notification with latest scope" do
379
+ notification = ActivityNotification::Notification.filtered_by_target(@target).latest
380
+ expect(notification).to eq(@latest_notification)
381
+ end
382
+
383
+ it "returns the earliest notification with earliest scope" do
384
+ notification = ActivityNotification::Notification.filtered_by_target(@target).earliest
385
+ expect(notification).to eq(@earliest_notification)
386
+ end
387
+
388
+ end
389
+ end
390
+
391
+ it "works with latest_order! scope" do
392
+ notifications = ActivityNotification::Notification.latest_order!
313
393
  expect(notifications.to_a.size).to eq(4)
314
394
  expect(notifications.first).to eq(@latest_notification)
315
395
  expect(notifications.last).to eq(@earliest_notification)
316
396
  end
317
397
 
318
- it "works with earliest_order scope" do
319
- notifications = ActivityNotification::Notification.earliest_order
398
+ it "works with latest_order!(reverse=true) scope" do
399
+ notifications = ActivityNotification::Notification.latest_order!(true)
400
+ expect(notifications.to_a.size).to eq(4)
401
+ expect(notifications.first).to eq(@earliest_notification)
402
+ expect(notifications.last).to eq(@latest_notification)
403
+ end
404
+
405
+ it "works with earliest_order! scope" do
406
+ notifications = ActivityNotification::Notification.earliest_order!
320
407
  expect(notifications.to_a.size).to eq(4)
321
408
  expect(notifications.first).to eq(@earliest_notification)
322
409
  expect(notifications.last).to eq(@latest_notification)
323
410
  end
324
411
 
325
- it "returns the latest notification with latest scope" do
326
- notification = ActivityNotification::Notification.latest
412
+ it "returns the latest notification with latest! scope" do
413
+ notification = ActivityNotification::Notification.latest!
327
414
  expect(notification).to eq(@latest_notification)
328
415
  end
329
416
 
330
- it "returns the earliest notification with earliest scope" do
331
- notification = ActivityNotification::Notification.earliest
417
+ it "returns the earliest notification with earliest! scope" do
418
+ notification = ActivityNotification::Notification.earliest!
332
419
  expect(notification).to eq(@earliest_notification)
333
420
  end
334
421
  end
422
+
423
+ context "to include with associated records" do
424
+ before do
425
+ ActivityNotification::Notification.delete_all
426
+ create(:notification)
427
+ @notifications = ActivityNotification::Notification.filtered_by_key("default.default")
428
+ end
429
+
430
+ it "works with_target" do
431
+ expect(@notifications.with_target.count).to eq(1)
432
+ end
433
+
434
+ it "works with_notifiable" do
435
+ expect(@notifications.with_notifiable.count).to eq(1)
436
+ end
437
+
438
+ it "works with_group" do
439
+ expect(@notifications.with_group.count).to eq(1)
440
+ end
441
+
442
+ it "works with_group_owner" do
443
+ expect(@notifications.with_group_owner.count).to eq(1)
444
+ end
445
+
446
+ it "works with_group_members" do
447
+ expect(@notifications.with_group_members.count).to eq(1)
448
+ end
449
+
450
+ it "works with_notifier" do
451
+ expect(@notifications.with_notifier.count).to eq(1)
452
+ end
453
+ end
335
454
  end
336
455
  end