activity_notification 0.0.8 → 0.0.9

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 (95) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +11 -1
  3. data/README.md +63 -28
  4. data/activity_notification.gemspec +4 -2
  5. data/app/controllers/activity_notification/notifications_controller.rb +1 -1
  6. data/app/controllers/activity_notification/notifications_with_devise_controller.rb +10 -10
  7. data/app/views/activity_notification/notifications/default/_index.html.erb +9 -4
  8. data/lib/activity_notification.rb +7 -6
  9. data/lib/activity_notification/apis/notification_api.rb +14 -15
  10. data/lib/activity_notification/common.rb +15 -7
  11. data/lib/activity_notification/config.rb +2 -0
  12. data/lib/activity_notification/helpers/view_helpers.rb +5 -4
  13. data/lib/activity_notification/mailers/helpers.rb +9 -9
  14. data/lib/activity_notification/models.rb +16 -0
  15. data/lib/activity_notification/models/{notifiable.rb → concerns/notifiable.rb} +15 -10
  16. data/lib/activity_notification/models/{notifier.rb → concerns/notifier.rb} +6 -0
  17. data/lib/activity_notification/models/{target.rb → concerns/target.rb} +34 -17
  18. data/lib/activity_notification/renderable.rb +2 -1
  19. data/lib/activity_notification/roles/acts_as_notifiable.rb +38 -23
  20. data/lib/activity_notification/roles/acts_as_notifier.rb +11 -0
  21. data/lib/activity_notification/roles/acts_as_target.rb +9 -18
  22. data/lib/activity_notification/version.rb +1 -1
  23. data/lib/generators/activity_notification/{migration → active_record}/migration_generator.rb +5 -4
  24. data/lib/generators/activity_notification/controllers_generator.rb +1 -1
  25. data/lib/generators/activity_notification/install_generator.rb +3 -6
  26. data/lib/generators/activity_notification/{notification → models}/notification_generator.rb +5 -4
  27. data/lib/generators/activity_notification/views_generator.rb +20 -22
  28. data/lib/generators/templates/active_record/migration.rb +1 -1
  29. data/lib/generators/templates/activity_notification.rb +13 -3
  30. data/{config → lib/generators/templates}/locales/en.yml +0 -0
  31. data/lib/generators/templates/notification/notification.rb +4 -1
  32. data/spec/concerns/{notification_api_spec.rb → apis/notification_api_spec.rb} +169 -45
  33. data/spec/concerns/common_spec.rb +150 -0
  34. data/spec/concerns/models/notifiable_spec.rb +435 -0
  35. data/spec/concerns/models/notifier_spec.rb +23 -0
  36. data/spec/concerns/models/target_spec.rb +579 -0
  37. data/spec/concerns/renderable_spec.rb +110 -0
  38. data/spec/controllers/notifications_controller_shared_examples.rb +457 -0
  39. data/spec/controllers/notifications_controller_spec.rb +12 -0
  40. data/spec/controllers/notifications_with_devise_controller_spec.rb +81 -0
  41. data/spec/factories/admins.rb +5 -0
  42. data/spec/factories/articles.rb +1 -1
  43. data/spec/factories/comments.rb +1 -1
  44. data/spec/factories/dummy/dummy_notifiable.rb +4 -0
  45. data/spec/factories/dummy/dummy_notifier.rb +4 -0
  46. data/spec/factories/dummy/dummy_target.rb +4 -0
  47. data/spec/factories/notifications.rb +1 -1
  48. data/spec/factories/users.rb +7 -1
  49. data/spec/generators/active_record/migration_generator_spec.rb +41 -0
  50. data/spec/generators/controllers_generator_spec.rb +62 -0
  51. data/spec/generators/install_generator_spec.rb +43 -0
  52. data/spec/generators/models/notification_generator_spec.rb +41 -0
  53. data/spec/generators/views_generator_spec.rb +111 -0
  54. data/spec/helpers/polymorphic_helpers_spec.rb +89 -0
  55. data/spec/helpers/view_helpers_spec.rb +258 -0
  56. data/spec/mailers/mailer_spec.rb +98 -0
  57. data/spec/models/dummy/dummy_notifiable_spec.rb +6 -0
  58. data/spec/models/dummy/dummy_notifier_spec.rb +6 -0
  59. data/spec/models/dummy/dummy_target_spec.rb +6 -0
  60. data/spec/models/notification_spec.rb +5 -4
  61. data/spec/rails_app/app/assets/javascripts/application.js +2 -0
  62. data/spec/rails_app/app/controllers/articles_controller.rb +62 -0
  63. data/spec/rails_app/app/controllers/comments_controller.rb +34 -0
  64. data/spec/rails_app/app/models/admin.rb +8 -0
  65. data/spec/rails_app/app/models/article.rb +6 -6
  66. data/spec/rails_app/app/models/comment.rb +2 -2
  67. data/spec/rails_app/app/models/dummy/dummy_base.rb +2 -0
  68. data/spec/rails_app/app/models/dummy/dummy_notifiable.rb +4 -0
  69. data/spec/rails_app/app/models/dummy/dummy_notifier.rb +4 -0
  70. data/spec/rails_app/app/models/dummy/dummy_target.rb +4 -0
  71. data/spec/rails_app/app/models/user.rb +5 -5
  72. data/spec/rails_app/app/views/activity_notification/notifications/default/custom/_path_test.html.erb +1 -0
  73. data/spec/rails_app/app/views/activity_notification/notifications/default/custom/_test.html.erb +1 -0
  74. data/spec/rails_app/app/views/activity_notification/notifications/users/_custom_index.html.erb +1 -0
  75. data/spec/rails_app/app/views/activity_notification/notifications/users/custom/_test.html.erb +1 -0
  76. data/spec/rails_app/app/views/articles/_form.html.erb +20 -0
  77. data/spec/rails_app/app/views/articles/edit.html.erb +6 -0
  78. data/spec/rails_app/app/views/articles/index.html.erb +67 -0
  79. data/spec/rails_app/app/views/articles/new.html.erb +5 -0
  80. data/spec/rails_app/app/views/articles/show.html.erb +38 -0
  81. data/spec/rails_app/app/views/layouts/_header.html.erb +8 -0
  82. data/spec/rails_app/app/views/layouts/application.html.erb +3 -4
  83. data/spec/rails_app/config/initializers/activity_notification.rb +13 -3
  84. data/spec/rails_app/config/initializers/devise.rb +274 -274
  85. data/spec/rails_app/config/locales/activity_notification.en.yml +20 -0
  86. data/spec/rails_app/config/locales/devise.en.yml +62 -0
  87. data/spec/rails_app/config/routes.rb +6 -2
  88. data/spec/rails_app/db/migrate/20160715050433_create_test_tables.rb +6 -2
  89. data/spec/rails_app/db/schema.rb +8 -0
  90. data/spec/rails_app/db/seeds.rb +43 -0
  91. data/spec/roles/acts_as_notifiable_spec.rb +32 -0
  92. data/spec/roles/acts_as_notifier_spec.rb +17 -0
  93. data/spec/roles/acts_as_target_spec.rb +40 -0
  94. data/spec/spec_helper.rb +18 -14
  95. metadata +136 -12
@@ -0,0 +1,89 @@
1
+ describe ActivityNotification::PolymorphicHelpers, type: :helper do
2
+
3
+ include ActivityNotification::PolymorphicHelpers
4
+
5
+ describe 'extended String class' do
6
+ describe "as public instance methods" do
7
+ describe '#to_model_name' do
8
+ it 'returns singularized and camelized string' do
9
+ expect('foo_bars'.to_model_name).to eq('FooBar')
10
+ expect('users'.to_model_name).to eq('User')
11
+ end
12
+ end
13
+
14
+ describe '#to_model_class' do
15
+ it 'returns class instance' do
16
+ expect('users'.to_model_class).to eq(User)
17
+ end
18
+ end
19
+
20
+ describe '#to_resource_name' do
21
+ it 'returns singularized underscore string' do
22
+ expect('FooBars'.to_resource_name).to eq('foo_bar')
23
+ end
24
+ end
25
+
26
+ describe '#to_resources_name' do
27
+ it 'returns pluralized underscore string' do
28
+ expect('FooBar'.to_resources_name).to eq('foo_bars')
29
+ end
30
+ end
31
+
32
+ describe '#to_boolean' do
33
+ context 'without default argument' do
34
+ it 'returns true for string true' do
35
+ expect('true'.to_boolean).to eq(true)
36
+ end
37
+
38
+ it 'returns true for string 1' do
39
+ expect('1'.to_boolean).to eq(true)
40
+ end
41
+
42
+ it 'returns true for string yes' do
43
+ expect('yes'.to_boolean).to eq(true)
44
+ end
45
+
46
+ it 'returns true for string on' do
47
+ expect('on'.to_boolean).to eq(true)
48
+ end
49
+
50
+ it 'returns true for string t' do
51
+ expect('t'.to_boolean).to eq(true)
52
+ end
53
+
54
+ it 'returns false for string false' do
55
+ expect('false'.to_boolean).to eq(false)
56
+ end
57
+
58
+ it 'returns false for string 0' do
59
+ expect('0'.to_boolean).to eq(false)
60
+ end
61
+
62
+ it 'returns false for string no' do
63
+ expect('no'.to_boolean).to eq(false)
64
+ end
65
+
66
+ it 'returns false for string off' do
67
+ expect('off'.to_boolean).to eq(false)
68
+ end
69
+
70
+ it 'returns false for string f' do
71
+ expect('f'.to_boolean).to eq(false)
72
+ end
73
+
74
+ it 'returns nil for other string' do
75
+ expect('hoge'.to_boolean).to be_nil
76
+ end
77
+ end
78
+
79
+ context 'with default argument' do
80
+ it 'returns default value for other string' do
81
+ expect('hoge'.to_boolean(true)).to eq(true)
82
+ expect('hoge'.to_boolean(false)).to eq(false)
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ end
@@ -0,0 +1,258 @@
1
+ describe ActivityNotification::ViewHelpers, type: :helper do
2
+ let(:view_context) { ActionView::Base.new }
3
+ let(:notification) {
4
+ create(:notification, target: create(:confirmed_user))
5
+ }
6
+ let(:target_user) { notification.target }
7
+ let(:notification_2) {
8
+ create(:notification, target: create(:confirmed_user))
9
+ }
10
+ let(:notifications) {
11
+ target = create(:confirmed_user)
12
+ create(:notification, target: target)
13
+ create(:notification, target: target)
14
+ target.notifications.group_owners_only
15
+ }
16
+ let(:simple_text_key) { 'article.create' }
17
+ let(:simple_text_original) { 'Article has been created' }
18
+
19
+ include ActivityNotification::ViewHelpers
20
+
21
+ describe 'ActionView::Base' do
22
+ it 'provides render_notification helper' do
23
+ expect(view_context.respond_to?(:render_notification)).to be_truthy
24
+ end
25
+ end
26
+
27
+ describe '#render_notification' do
28
+ context "without fallback" do
29
+ context "when the template is missing for the target type and key" do
30
+ it "raises ActionView::MissingTemplate" do
31
+ expect { render_notification notification }
32
+ .to raise_error(ActionView::MissingTemplate)
33
+ end
34
+ end
35
+ end
36
+
37
+ context "with default as fallback" do
38
+ it "renders default notification view" do
39
+ expect(render_notification notification, fallback: :default)
40
+ .to eq(
41
+ render partial: 'activity_notification/notifications/default/default',
42
+ locals: { notification: notification }
43
+ )
44
+ end
45
+
46
+ it 'handles multiple notifications of active_record' do
47
+ expect(notifications.to_a.first).to receive(:render).with(self, { fallback: :default })
48
+ expect(notifications.to_a.last).to receive(:render).with(self, { fallback: :default })
49
+ render_notification notifications, fallback: :default
50
+ end
51
+
52
+ it 'handles multiple notifications of array' do
53
+ expect(notification).to receive(:render).with(self, { fallback: :default })
54
+ expect(notification_2).to receive(:render).with(self, { fallback: :default })
55
+ render_notification [notification, notification_2], fallback: :default
56
+ end
57
+ end
58
+
59
+ context "with text as fallback" do
60
+ it "uses i18n text from key" do
61
+ notification.key = simple_text_key
62
+ expect(render_notification notification, fallback: :text)
63
+ .to eq(simple_text_original)
64
+ end
65
+ end
66
+
67
+ context "with custom view" do
68
+ it "renders custom notification view for default target" do
69
+ notification.key = 'custom.test'
70
+ # render activity_notification/notifications/default/custom/test
71
+ expect(render_notification notification)
72
+ .to eq("Custom template root for default target: #{notification.id}")
73
+ end
74
+
75
+ it "renders custom notification view for specified target" do
76
+ notification.key = 'custom.test'
77
+ # render activity_notification/notifications/users/custom/test
78
+ expect(render_notification notification, target: :users)
79
+ .to eq("Custom template root for user target: #{notification.id}")
80
+ end
81
+
82
+ it "renders custom notification view of partial parameter" do
83
+ notification.key = 'custom.test'
84
+ # render activity_notification/notifications/default/custom/path_test
85
+ expect(render_notification notification, partial: 'custom/path_test')
86
+ .to eq("Custom template root for path test: #{notification.id}")
87
+ end
88
+
89
+ it "uses layout of layout parameter" do
90
+ notification.key = 'custom.test'
91
+ expect(self).to receive(:render).with({
92
+ layout: 'layouts/test',
93
+ partial: 'activity_notification/notifications/default/custom/test',
94
+ locals: notification.prepare_locals({ layout: 'test' })
95
+ })
96
+ render_notification notification, layout: 'test'
97
+ end
98
+ end
99
+ end
100
+
101
+ describe '#render_notifications' do
102
+ it "is an alias of render_notification" do
103
+ expect(notification).to receive(:render).with(self, { fallback: :default })
104
+ render_notifications notification, fallback: :default
105
+ end
106
+ end
107
+
108
+ describe '#render_notification_of' do
109
+ context "without fallback" do
110
+ context "when the template is missing for the target type and key" do
111
+ it "raises ActionView::MissingTemplate" do
112
+ expect { render_notification_of target_user }
113
+ .to raise_error(ActionView::MissingTemplate)
114
+ end
115
+ end
116
+ end
117
+
118
+ context "with default as fallback" do
119
+ it "renders default notification view" do
120
+ allow(self).to receive(:content_for).with(:notification_index).and_return('foo')
121
+ @target = target_user
122
+ expect(render_notification_of target_user, fallback: :default)
123
+ .to eq(
124
+ render partial: 'activity_notification/notifications/default/index',
125
+ locals: { target: target_user }
126
+ )
127
+ end
128
+ end
129
+
130
+ context "with custom view" do
131
+ before do
132
+ allow(self).to receive(:content_for).with(:notification_index).and_return('foo')
133
+ @target = target_user
134
+ end
135
+
136
+ #TODO make better test using content_for
137
+ it "renders custom notification view for specified target" do
138
+ # notification_1 = target_user.notifications.first
139
+ # notification_2 = target_user.notifications.last
140
+ # notification_1.update(key: 'custom.test')
141
+ # notification_2.update(key: 'custom.test')
142
+ expect(render_notification_of target_user, partial: 'custom_index', fallback: :default)
143
+ .to eq("Custom index: ")
144
+ # .to eq("Custom index: Custom template root for user target: #{notification_1.id}"\
145
+ # "Custom template root for user target: #{notification_2.id}")
146
+ end
147
+
148
+ it "uses layout of layout parameter" do
149
+ expect(self).to receive(:render).with({
150
+ partial: 'activity_notification/notifications/users/index',
151
+ layout: 'layouts/test',
152
+ locals: { target: target_user }
153
+ })
154
+ render_notification_of target_user, layout: 'test'
155
+ end
156
+ end
157
+
158
+ context "with index_content option" do
159
+ before do
160
+ @target = target_user
161
+ end
162
+
163
+ context "as default" do
164
+ it "uses target.notification_index_with_attributes" do
165
+ expect(target_user).to receive(:notification_index_with_attributes)
166
+ render_notification_of target_user
167
+ end
168
+ end
169
+
170
+ context "with :simple" do
171
+ it "uses target.notification_index" do
172
+ expect(target_user).to receive(:notification_index)
173
+ render_notification_of target_user, index_content: :simple
174
+ end
175
+ end
176
+
177
+ context "with :with_attributes or any other key" do
178
+ it "uses target.notification_index_with_attributes" do
179
+ expect(target_user).to receive(:notification_index_with_attributes)
180
+ render_notification_of target_user, index_content: :with_attributes
181
+ end
182
+ end
183
+
184
+ context "with :none" do
185
+ it "uses neither target.notification_index nor notification_index_with_attributes" do
186
+ expect(target_user).not_to receive(:notification_index)
187
+ expect(target_user).not_to receive(:notification_index_with_attributes)
188
+ render_notification_of target_user, index_content: :none
189
+ end
190
+ end
191
+ end
192
+ end
193
+
194
+ describe '#render_notifications_of' do
195
+ it "is an alias of render_notification_of" do
196
+ expect(self).to receive(:render_notification)
197
+ render_notifications_of target_user, fallback: :default
198
+ end
199
+ end
200
+
201
+
202
+ describe '#notification_path_for' do
203
+ it "returns path for the notification target" do
204
+ expect(notification_path_for(notification))
205
+ .to eq(user_notification_path(target_user, notification))
206
+ end
207
+ end
208
+
209
+ describe '#move_notification_path_for' do
210
+ it "returns path for the notification target" do
211
+ expect(move_notification_path_for(notification))
212
+ .to eq(move_user_notification_path(target_user, notification))
213
+ end
214
+ end
215
+
216
+ describe '#open_notification_path_for' do
217
+ it "returns path for the notification target" do
218
+ expect(open_notification_path_for(notification))
219
+ .to eq(open_user_notification_path(target_user, notification))
220
+ end
221
+ end
222
+
223
+ describe '#open_all_notifications_path_for' do
224
+ it "returns path for the notification target" do
225
+ expect(open_all_notifications_path_for(target_user))
226
+ .to eq(open_all_user_notifications_path(target_user))
227
+ end
228
+ end
229
+
230
+ describe '#notification_url_for' do
231
+ it "returns url for the notification target" do
232
+ expect(notification_url_for(notification))
233
+ .to eq(user_notification_url(target_user, notification))
234
+ end
235
+ end
236
+
237
+ describe '#move_notification_url_for' do
238
+ it "returns url for the notification target" do
239
+ expect(move_notification_url_for(notification))
240
+ .to eq(move_user_notification_url(target_user, notification))
241
+ end
242
+ end
243
+
244
+ describe '#open_notification_url_for' do
245
+ it "returns url for the notification target" do
246
+ expect(open_notification_url_for(notification))
247
+ .to eq(open_user_notification_url(target_user, notification))
248
+ end
249
+ end
250
+
251
+ describe '#open_all_notifications_url_for' do
252
+ it "returns url for the notification target" do
253
+ expect(open_all_notifications_url_for(target_user))
254
+ .to eq(open_all_user_notifications_url(target_user))
255
+ end
256
+ end
257
+
258
+ end
@@ -0,0 +1,98 @@
1
+ describe ActivityNotification::Mailer do
2
+ include ActiveJob::TestHelper
3
+ let(:notification) { create(:notification) }
4
+
5
+ before do
6
+ ActivityNotification::Mailer.deliveries.clear
7
+ expect(ActivityNotification::Mailer.deliveries.size).to eq(0)
8
+ end
9
+
10
+ describe "#send_notification_email" do
11
+ context "with deliver_now" do
12
+ context "as default" do
13
+ before do
14
+ ActivityNotification::Mailer.send_notification_email(notification).deliver_now
15
+ end
16
+
17
+ it "sends notification email now" do
18
+ expect(ActivityNotification::Mailer.deliveries.size).to eq(1)
19
+ end
20
+
21
+ it "sends to target email" do
22
+ expect(ActivityNotification::Mailer.deliveries.last.to[0]).to eq(notification.target.email)
23
+ end
24
+
25
+ it "sends from configured email in initializer" do
26
+ expect(ActivityNotification::Mailer.deliveries.last.from[0])
27
+ .to eq("please-change-me-at-config-initializers-activity_notification@example.com")
28
+ end
29
+
30
+ it "sends with default notification subject" do
31
+ expect(ActivityNotification::Mailer.deliveries.last.subject)
32
+ .to eq("Notification of Article")
33
+ end
34
+ end
35
+
36
+ context "with default from parameter in mailer" do
37
+ it "sends from configured email as default parameter" do
38
+ class CustomMailer < ActivityNotification::Mailer
39
+ default from: "test01@example.com"
40
+ end
41
+ CustomMailer.send_notification_email(notification).deliver_now
42
+ expect(CustomMailer.deliveries.last.from[0])
43
+ .to eq("test01@example.com")
44
+ end
45
+ end
46
+
47
+ context "with email value as ActivityNotification.config.mailer_sender" do
48
+ it "sends from configured email as ActivityNotification.config.mailer_sender" do
49
+ ActivityNotification.config.mailer_sender = "test02@example.com"
50
+ ActivityNotification::Mailer.send_notification_email(notification).deliver_now
51
+ expect(ActivityNotification::Mailer.deliveries.last.from[0])
52
+ .to eq("test02@example.com")
53
+ end
54
+ end
55
+
56
+ context "with email proc as ActivityNotification.config.mailer_sender" do
57
+ it "sends from configured email as ActivityNotification.config.mailer_sender" do
58
+ ActivityNotification.config.mailer_sender =
59
+ ->(notification){ notification.target_type == 'User' ? "test03@example.com" : "test04@example.com" }
60
+ ActivityNotification::Mailer.send_notification_email(notification).deliver_now
61
+ expect(ActivityNotification::Mailer.deliveries.last.from[0])
62
+ .to eq("test03@example.com")
63
+ end
64
+ end
65
+
66
+ context "with defined overriding_notification_email_key in notifiable model" do
67
+ it "sends with configured notification subject in locale file as updated key" do
68
+ module AdditionalMethods
69
+ def overriding_notification_email_key(target, key)
70
+ 'comment.reply'
71
+ end
72
+ end
73
+ notification.notifiable.extend(AdditionalMethods)
74
+ ActivityNotification::Mailer.send_notification_email(notification).deliver_now
75
+ expect(ActivityNotification::Mailer.deliveries.last.subject)
76
+ .to eq("New comment to your article")
77
+ end
78
+ end
79
+ end
80
+
81
+ context "with deliver_later" do
82
+ it "sends notification email later" do
83
+ expect {
84
+ perform_enqueued_jobs do
85
+ ActivityNotification::Mailer.send_notification_email(notification).deliver_later
86
+ end
87
+ }.to change { ActivityNotification::Mailer.deliveries.size }.by(1)
88
+ expect(ActivityNotification::Mailer.deliveries.size).to eq(1)
89
+ end
90
+
91
+ it "sends notification email with active job queue" do
92
+ expect {
93
+ ActivityNotification::Mailer.send_notification_email(notification).deliver_later
94
+ }.to change(ActiveJob::Base.queue_adapter.enqueued_jobs, :size).by(1)
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,6 @@
1
+ describe Dummy::DummyNotifiable, type: :model do
2
+
3
+ it_behaves_like :notifiable
4
+ it_behaves_like :common
5
+
6
+ end