activity_notification 1.7.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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