activity_notification 0.0.8 → 0.0.9

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