message_train 0.7.6 → 1.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.
- checksums.yaml +5 -5
- data/.gitattributes +1 -0
- data/.github/workflows/ci.yml +86 -0
- data/.gitignore +64 -0
- data/.rubocop.yml +9 -0
- data/.rubocop_todo.yml +854 -2
- data/.ruby-version +1 -1
- data/.simplecov +2 -4
- data/CHANGELOG.md +128 -0
- data/CLAUDE.md +5 -0
- data/Gemfile +29 -31
- data/LICENSE.txt +1 -1
- data/README.md +106 -35
- data/Rakefile +4 -18
- data/app/assets/stylesheets/message_train.scss +405 -67
- data/app/controllers/concerns/message_train_support.rb +2 -2
- data/app/controllers/message_train/boxes_controller.rb +4 -2
- data/app/controllers/message_train/conversations_controller.rb +1 -0
- data/app/helpers/message_train/application_helper.rb +68 -0
- data/app/helpers/message_train/attachments_helper.rb +7 -4
- data/app/helpers/message_train/conversations_helper.rb +16 -16
- data/app/helpers/message_train/messages_helper.rb +23 -10
- data/app/javascript/controllers/message_train/bulk_actions_controller.js +36 -0
- data/app/javascript/controllers/message_train/lightbox_controller.js +25 -0
- data/app/javascript/controllers/message_train/nested_form_controller.js +36 -0
- data/app/javascript/controllers/message_train/recipient_autocomplete_controller.js +31 -0
- data/app/mailers/message_train/previews/receipt_mailer_preview.rb +7 -5
- data/app/models/message_train/attachment.rb +54 -42
- data/app/models/message_train/box.rb +2 -2
- data/app/models/message_train/conversation.rb +28 -2
- data/app/models/message_train/ignore.rb +2 -2
- data/app/models/message_train/message.rb +10 -4
- data/app/models/message_train/receipt.rb +27 -4
- data/app/models/message_train/unsubscribe.rb +1 -1
- data/app/views/application/404.html.haml +1 -3
- data/app/views/kaminari/_first_page.html.haml +1 -1
- data/app/views/kaminari/_last_page.html.haml +1 -1
- data/app/views/kaminari/_next_page.html.haml +1 -1
- data/app/views/kaminari/_page.html.haml +3 -3
- data/app/views/kaminari/_paginator.html.haml +12 -11
- data/app/views/kaminari/_prev_page.html.haml +1 -1
- data/app/views/message_train/application/_attachment_fields.html.haml +10 -7
- data/app/views/message_train/application/_attachment_link.html.haml +2 -2
- data/app/views/message_train/application/_widget.html.haml +2 -4
- data/app/views/message_train/boxes/_widget.html.haml +5 -5
- data/app/views/message_train/boxes/show.html.haml +28 -45
- data/app/views/message_train/collectives/_widget.html.haml +4 -4
- data/app/views/message_train/conversations/_conversation.html.haml +11 -11
- data/app/views/message_train/conversations/_deleted_toggle.html.haml +1 -1
- data/app/views/message_train/conversations/_ignored_toggle.html.haml +2 -2
- data/app/views/message_train/conversations/_read_toggle.html.haml +2 -2
- data/app/views/message_train/conversations/_toggle.html.haml +6 -4
- data/app/views/message_train/conversations/_trashed_toggle.html.haml +2 -2
- data/app/views/message_train/conversations/show.html.haml +8 -6
- data/app/views/message_train/messages/_deleted_toggle.html.haml +1 -1
- data/app/views/message_train/messages/_form.html.haml +22 -30
- data/app/views/message_train/messages/_message.html.haml +27 -45
- data/app/views/message_train/messages/_read_toggle.html.haml +2 -2
- data/app/views/message_train/messages/_toggle.html.haml +5 -1
- data/app/views/message_train/messages/_trashed_toggle.html.haml +2 -2
- data/app/views/message_train/unsubscribes/index.html.haml +12 -15
- data/badges/coverage.json +1 -0
- data/config/importmap.rb +2 -0
- data/config/locales/en.yml +6 -3
- data/db/migrate/20150721145319_create_message_train_conversations.rb +1 -1
- data/db/migrate/20150721160322_create_message_train_messages.rb +1 -1
- data/db/migrate/20150721161144_create_message_train_attachments.rb +5 -2
- data/db/migrate/20150721161940_create_message_train_receipts.rb +1 -1
- data/db/migrate/20150721163838_create_message_train_ignores.rb +1 -1
- data/db/migrate/20150901183458_add_received_through_to_message_train_receipts.rb +1 -1
- data/db/migrate/20151004184347_add_unique_index_to_receipts.rb +1 -1
- data/db/migrate/20151124000820_create_message_train_unsubscribes.rb +1 -1
- data/db/migrate/20260827095938_remove_paperclip_columns_from_message_train_attachments.rb +8 -0
- data/db/migrate/20260827171549_remove_body_from_message_train_messages.rb +5 -0
- data/db/migrate/20260827180000_add_marking_indexes.rb +9 -0
- data/db/migrate/20260827200000_add_body_back_to_message_train_messages.rb +5 -0
- data/docs/screenshots/inbox-desktop.png +0 -0
- data/docs/screenshots/inbox-mobile.png +0 -0
- data/lib/generators/message_train/install/install_generator.rb +1 -1
- data/lib/message_train/engine.rb +11 -0
- data/lib/message_train/instance_methods.rb +13 -7
- data/lib/message_train/localization.rb +4 -3
- data/lib/message_train/version.rb +1 -1
- data/lib/message_train.rb +0 -2
- data/message_train.gemspec +57 -389
- data/spec/controllers/message_train/boxes_controller_spec.rb +13 -8
- data/spec/controllers/message_train/concerns_spec.rb +2 -2
- data/spec/controllers/message_train/conversations_controller_spec.rb +36 -7
- data/spec/controllers/message_train/messages_controller_spec.rb +4 -4
- data/spec/dummy/app/assets/stylesheets/application.scss +141 -12
- data/spec/dummy/app/controllers/application_controller.rb +1 -1
- data/spec/dummy/app/javascript/application.js +4 -0
- data/spec/dummy/app/javascript/controllers/application.js +9 -0
- data/spec/dummy/app/javascript/controllers/index.js +4 -0
- data/spec/dummy/app/models/role.rb +1 -1
- data/spec/dummy/app/views/active_storage/blobs/_blob.html.erb +14 -0
- data/spec/dummy/app/views/layouts/_top_navigation.html.haml +18 -7
- data/spec/dummy/app/views/layouts/application.html.haml +22 -26
- data/spec/dummy/bin/importmap +4 -0
- data/spec/dummy/config/application.rb +7 -20
- data/spec/dummy/config/environments/development.rb +17 -21
- data/spec/dummy/config/environments/production.rb +11 -63
- data/spec/dummy/config/environments/test.rb +21 -16
- data/spec/dummy/config/importmap.rb +7 -0
- data/spec/dummy/config/initializers/assets.rb +1 -6
- data/spec/dummy/config/routes.rb +1 -1
- data/spec/dummy/config/storage.yml +7 -0
- data/spec/dummy/db/migrate/20150721140013_devise_create_users.rb +1 -1
- data/spec/dummy/db/migrate/20150721141009_rolify_create_roles.rb +1 -1
- data/spec/dummy/db/migrate/20150721141128_create_groups.rb +1 -1
- data/spec/dummy/db/migrate/20150721150307_add_display_name_column_to_users.rb +1 -1
- data/spec/dummy/db/migrate/20160207190402_create_message_train_conversations.message_train.rb +1 -1
- data/spec/dummy/db/migrate/20160207190403_create_message_train_messages.message_train.rb +1 -1
- data/spec/dummy/db/migrate/20160207190404_create_message_train_attachments.message_train.rb +5 -2
- data/spec/dummy/db/migrate/20160207190405_create_message_train_receipts.message_train.rb +1 -1
- data/spec/dummy/db/migrate/20160207190406_create_message_train_ignores.message_train.rb +1 -1
- data/spec/dummy/db/migrate/20160207190407_add_received_through_to_message_train_receipts.message_train.rb +1 -1
- data/spec/dummy/db/migrate/20160207190408_add_unique_index_to_receipts.message_train.rb +1 -1
- data/spec/dummy/db/migrate/20160207190409_create_message_train_unsubscribes.message_train.rb +1 -1
- data/spec/dummy/db/migrate/20260827095939_remove_paperclip_columns_from_message_train_attachments.message_train.rb +9 -0
- data/spec/dummy/db/migrate/20260827161141_create_active_storage_tables.active_storage.rb +57 -0
- data/spec/dummy/db/migrate/20260827171550_remove_body_from_message_train_messages.message_train.rb +6 -0
- data/spec/dummy/db/migrate/20260827225116_add_marking_indexes.message_train.rb +10 -0
- data/spec/dummy/db/migrate/20260828034830_add_body_back_to_message_train_messages.message_train.rb +6 -0
- data/spec/dummy/db/migrate/20260828040000_drop_action_text_tables.rb +5 -0
- data/spec/dummy/db/schema.rb +106 -72
- data/spec/dummy/db/seeds/conversations.seeds.rb +22 -22
- data/spec/dummy/db/seeds/development/conversations.seeds.rb +2 -2
- data/spec/dummy/db/seeds/groups.seeds.rb +4 -4
- data/spec/dummy/db/seeds/test/attachments.seeds.rb +4 -4
- data/spec/dummy/db/seeds/test/conversations.seeds.rb +2 -2
- data/spec/dummy/db/seeds/users.seeds.rb +8 -8
- data/spec/dummy/vendor/javascript/.keep +0 -0
- data/spec/factories/attachment.rb +5 -6
- data/spec/factories/group.rb +2 -2
- data/spec/factories/message.rb +7 -7
- data/spec/factories/user.rb +3 -3
- data/spec/features/boxes_spec.rb +38 -34
- data/spec/features/conversations_spec.rb +13 -6
- data/spec/features/messages_spec.rb +20 -20
- data/spec/features/unsubscribes_spec.rb +9 -9
- data/spec/helpers/message_train/application_helper_spec.rb +16 -18
- data/spec/helpers/message_train/attachment_helper_spec.rb +8 -18
- data/spec/helpers/message_train/boxes_helper_spec.rb +6 -6
- data/spec/helpers/message_train/collectives_helper_spec.rb +10 -10
- data/spec/helpers/message_train/conversations_helper_spec.rb +43 -85
- data/spec/helpers/message_train/messages_helper_spec.rb +41 -61
- data/spec/models/message_train/attachment_spec.rb +26 -36
- data/spec/models/message_train/box_spec.rb +2 -2
- data/spec/models/message_train/conversation_spec.rb +15 -0
- data/spec/models/message_train/message_spec.rb +5 -1
- data/spec/models/message_train/receipt_spec.rb +1 -1
- data/spec/models/message_train/unsubscribe_spec.rb +1 -1
- data/spec/rails_helper.rb +14 -13
- data/spec/support/controller_behaviors.rb +13 -13
- data/spec/support/factory_bot.rb +3 -0
- data/spec/support/feature_behaviors.rb +14 -14
- data/spec/support/loaded_site/attachments.rb +6 -2
- data/spec/support/utilities.rb +49 -20
- metadata +260 -213
- data/.travis.yml +0 -12
- data/VERSION +0 -1
- data/app/assets/javascripts/ckeditor/config.js +0 -49
- data/app/assets/javascripts/message_train.js +0 -149
- data/spec/dummy/app/assets/javascripts/application.js +0 -17
- data/spec/dummy/app/assets/stylesheets/bootstrap-everything.scss +0 -54
- data/spec/dummy/config/initializers/bootstrap_leather.rb +0 -7
- data/spec/dummy/config/initializers/paperclip.rb +0 -5
- data/spec/dummy/config/secrets.yml +0 -22
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/support/factory_girl.rb +0 -3
|
@@ -8,21 +8,21 @@ after :users, :groups do
|
|
|
8
8
|
first_group = Group.find_by_slug('first-group')
|
|
9
9
|
membered_group = Group.find_by_slug('membered-group')
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
FactoryBot.create(
|
|
12
12
|
:simple_message,
|
|
13
13
|
sender: first_user,
|
|
14
14
|
recipients_to_save: { 'users' => second_user.slug },
|
|
15
15
|
subject: 'Sent Conversation'
|
|
16
16
|
)
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
FactoryBot.create(
|
|
19
19
|
:simple_message,
|
|
20
20
|
sender: second_user,
|
|
21
21
|
recipients_to_save: { 'users' => first_user.slug },
|
|
22
22
|
subject: 'Unread Conversation'
|
|
23
23
|
)
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
FactoryBot.create(
|
|
26
26
|
:simple_message,
|
|
27
27
|
sender: first_user,
|
|
28
28
|
recipients_to_save: {
|
|
@@ -35,28 +35,28 @@ after :users, :groups do
|
|
|
35
35
|
subject: 'To Many Conversation'
|
|
36
36
|
)
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
FactoryBot.create(
|
|
39
39
|
:simple_message,
|
|
40
40
|
sender: second_user,
|
|
41
41
|
recipients_to_save: { 'users' => first_user.slug },
|
|
42
42
|
subject: 'Ignored Conversation'
|
|
43
43
|
).conversation.participant_ignore(first_user)
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
FactoryBot.create(
|
|
46
46
|
:simple_message,
|
|
47
47
|
sender: second_user,
|
|
48
48
|
recipients_to_save: { 'users' => first_user.slug },
|
|
49
49
|
subject: 'Trashed Conversation'
|
|
50
50
|
).mark_trash_for(first_user)
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
FactoryBot.create(
|
|
53
53
|
:simple_message,
|
|
54
54
|
sender: second_user,
|
|
55
55
|
recipients_to_save: { 'users' => first_user.slug },
|
|
56
56
|
subject: 'Read Conversation'
|
|
57
57
|
).mark_read_for(first_user)
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
FactoryBot.create(
|
|
60
60
|
:simple_message,
|
|
61
61
|
sender: second_user,
|
|
62
62
|
recipients_to_save: { 'users' => first_user.slug },
|
|
@@ -64,56 +64,56 @@ after :users, :groups do
|
|
|
64
64
|
generate_attachment?: true
|
|
65
65
|
)
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
FactoryBot.create(
|
|
68
68
|
:simple_message,
|
|
69
69
|
sender: second_user,
|
|
70
70
|
recipients_to_save: { 'users' => first_user.slug },
|
|
71
71
|
subject: 'Deleted Conversation'
|
|
72
72
|
).mark_deleted_for(first_user)
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
FactoryBot.create(
|
|
75
75
|
:simple_message,
|
|
76
76
|
sender: first_user,
|
|
77
77
|
recipients_to_save: { 'groups' => first_group.slug },
|
|
78
78
|
subject: 'Group Announcement'
|
|
79
79
|
)
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
FactoryBot.create(
|
|
82
82
|
:simple_message,
|
|
83
83
|
sender: second_user,
|
|
84
84
|
recipients_to_save: { 'groups' => membered_group.slug },
|
|
85
85
|
subject: 'Membered Group Announcement'
|
|
86
86
|
)
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
FactoryBot.create(
|
|
89
89
|
:simple_message,
|
|
90
90
|
sender: second_user,
|
|
91
91
|
recipients_to_save: { 'groups' => membered_group.slug },
|
|
92
92
|
subject: 'Membered Group Trashed Conversation'
|
|
93
93
|
).mark(:trash, first_user)
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
FactoryBot.create(
|
|
96
96
|
:simple_message,
|
|
97
97
|
sender: second_user,
|
|
98
98
|
recipients_to_save: { 'groups' => membered_group.slug },
|
|
99
99
|
subject: 'Membered Group Read Conversation'
|
|
100
100
|
).mark(:read, first_user)
|
|
101
101
|
|
|
102
|
-
|
|
102
|
+
FactoryBot.create(
|
|
103
103
|
:simple_message,
|
|
104
104
|
sender: second_user,
|
|
105
105
|
recipients_to_save: { 'groups' => membered_group.slug },
|
|
106
106
|
subject: 'Membered Group Ignored Conversation'
|
|
107
107
|
).conversation.participant_ignore(first_user)
|
|
108
108
|
|
|
109
|
-
|
|
109
|
+
FactoryBot.create(
|
|
110
110
|
:simple_message,
|
|
111
111
|
sender: second_user,
|
|
112
112
|
recipients_to_save: { 'groups' => membered_group.slug },
|
|
113
113
|
subject: 'Membered Group Deleted Conversation'
|
|
114
114
|
).mark(:deleted, first_user)
|
|
115
115
|
|
|
116
|
-
|
|
116
|
+
FactoryBot.create(
|
|
117
117
|
:simple_message,
|
|
118
118
|
sender: second_user,
|
|
119
119
|
recipients_to_save: { 'groups' => membered_group.slug },
|
|
@@ -121,7 +121,7 @@ after :users, :groups do
|
|
|
121
121
|
draft: true
|
|
122
122
|
)
|
|
123
123
|
|
|
124
|
-
|
|
124
|
+
FactoryBot.create(
|
|
125
125
|
:simple_message,
|
|
126
126
|
sender: first_user,
|
|
127
127
|
recipients_to_save: { 'groups' => first_group.slug },
|
|
@@ -129,14 +129,14 @@ after :users, :groups do
|
|
|
129
129
|
draft: true
|
|
130
130
|
)
|
|
131
131
|
|
|
132
|
-
|
|
132
|
+
FactoryBot.create(
|
|
133
133
|
:simple_message,
|
|
134
134
|
sender: superadmin_user,
|
|
135
135
|
recipients_to_save: { 'roles' => 'admin' },
|
|
136
136
|
subject: 'Role Conversation'
|
|
137
137
|
)
|
|
138
138
|
|
|
139
|
-
|
|
139
|
+
FactoryBot.create(
|
|
140
140
|
:simple_message,
|
|
141
141
|
sender: superadmin_user,
|
|
142
142
|
recipients_to_save: { 'roles' => 'admin' },
|
|
@@ -144,28 +144,28 @@ after :users, :groups do
|
|
|
144
144
|
draft: true
|
|
145
145
|
)
|
|
146
146
|
|
|
147
|
-
|
|
147
|
+
FactoryBot.create(
|
|
148
148
|
:simple_message,
|
|
149
149
|
subject: 'This should turn into a draft',
|
|
150
150
|
sender: first_user,
|
|
151
151
|
recipients_to_save: {}
|
|
152
152
|
)
|
|
153
153
|
|
|
154
|
-
|
|
154
|
+
FactoryBot.create(
|
|
155
155
|
:simple_message,
|
|
156
156
|
subject: "Someone Else's Conversation",
|
|
157
157
|
sender: User.order(:id).last,
|
|
158
158
|
recipients_to_save: { 'users' => second_user.slug }
|
|
159
159
|
)
|
|
160
160
|
|
|
161
|
-
long_message =
|
|
161
|
+
long_message = FactoryBot.create(
|
|
162
162
|
:simple_message,
|
|
163
163
|
subject: 'Long Conversation',
|
|
164
164
|
sender: second_user,
|
|
165
165
|
recipients_to_save: { 'users' => first_user.slug }
|
|
166
166
|
)
|
|
167
167
|
|
|
168
|
-
|
|
168
|
+
FactoryBot.create_list(
|
|
169
169
|
:simple_message,
|
|
170
170
|
11,
|
|
171
171
|
conversation: long_message.conversation,
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
after :users, :groups do
|
|
2
2
|
User.find_each do |user|
|
|
3
3
|
# Create some conversations that this user has received
|
|
4
|
-
|
|
4
|
+
FactoryBot.create_list(
|
|
5
5
|
:message_from_random_sender,
|
|
6
6
|
[*5..10].sample,
|
|
7
7
|
recipients_to_save: { 'users' => user.slug }
|
|
8
8
|
)
|
|
9
9
|
|
|
10
10
|
# Create some conversations that this user has sent
|
|
11
|
-
|
|
11
|
+
FactoryBot.create_list(:message, [*5..10].sample, sender: user)
|
|
12
12
|
end
|
|
13
13
|
end
|
|
@@ -4,7 +4,7 @@ after :users do
|
|
|
4
4
|
fourth_user = User.friendly.find('fourth-user')
|
|
5
5
|
unsubscribed_user = User.friendly.find('unsubscribed-user')
|
|
6
6
|
|
|
7
|
-
first_group =
|
|
7
|
+
first_group = FactoryBot.create(
|
|
8
8
|
:group,
|
|
9
9
|
title: 'First Group',
|
|
10
10
|
owner: first_user
|
|
@@ -12,7 +12,7 @@ after :users do
|
|
|
12
12
|
fourth_user.add_role(:member, first_group)
|
|
13
13
|
unsubscribed_user.add_role(:member, first_group)
|
|
14
14
|
|
|
15
|
-
membered_group =
|
|
15
|
+
membered_group = FactoryBot.create(
|
|
16
16
|
:group,
|
|
17
17
|
title: 'Membered Group',
|
|
18
18
|
owner: second_user
|
|
@@ -20,13 +20,13 @@ after :users do
|
|
|
20
20
|
first_user.add_role(:member, membered_group)
|
|
21
21
|
unsubscribed_user.add_role(:member, membered_group)
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
FactoryBot.create(
|
|
24
24
|
:group,
|
|
25
25
|
title: 'Empty Group',
|
|
26
26
|
owner: first_user
|
|
27
27
|
)
|
|
28
28
|
|
|
29
|
-
unsubscribed_group =
|
|
29
|
+
unsubscribed_group = FactoryBot.create(
|
|
30
30
|
:group,
|
|
31
31
|
title: 'Unsubscribed Group',
|
|
32
32
|
owner: second_user
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
after 'test:conversations' do
|
|
2
|
-
|
|
2
|
+
FactoryBot.create(
|
|
3
3
|
:attachment,
|
|
4
|
-
attachment:
|
|
4
|
+
attachment: Rack::Test::UploadedFile.new(
|
|
5
5
|
'spec/dummy/app/assets/files/message_train/attachments/image-sample.jpg'
|
|
6
6
|
)
|
|
7
7
|
)
|
|
8
|
-
|
|
8
|
+
FactoryBot.create(
|
|
9
9
|
:attachment,
|
|
10
|
-
attachment:
|
|
10
|
+
attachment: Rack::Test::UploadedFile.new(
|
|
11
11
|
'spec/dummy/app/assets/files/message_train/attachments/pdf-sample.pdf'
|
|
12
12
|
)
|
|
13
13
|
)
|
|
@@ -2,12 +2,12 @@ after :users, :groups do
|
|
|
2
2
|
first_user = User.friendly.find('first-user')
|
|
3
3
|
|
|
4
4
|
# Create some conversations that first user has received
|
|
5
|
-
|
|
5
|
+
FactoryBot.create_list(
|
|
6
6
|
:message_from_random_sender,
|
|
7
7
|
10,
|
|
8
8
|
recipients_to_save: { 'users' => first_user.slug }
|
|
9
9
|
)
|
|
10
10
|
|
|
11
11
|
# Create some conversations that first user has sent
|
|
12
|
-
|
|
12
|
+
FactoryBot.create_list(:message, 10, sender: first_user)
|
|
13
13
|
end
|
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
|
|
1
|
+
FactoryBot.create(
|
|
2
2
|
:user,
|
|
3
3
|
display_name: 'First User',
|
|
4
4
|
email: 'first.user@example.com'
|
|
5
5
|
)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
FactoryBot.create(
|
|
8
8
|
:user,
|
|
9
9
|
display_name: 'Second User',
|
|
10
10
|
email: 'second.user@example.com'
|
|
11
11
|
)
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
FactoryBot.create(
|
|
14
14
|
:user,
|
|
15
15
|
display_name: 'Third User',
|
|
16
16
|
email: 'third.user@example.com'
|
|
17
17
|
)
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
FactoryBot.create(
|
|
20
20
|
:user,
|
|
21
21
|
display_name: 'Fourth User',
|
|
22
22
|
email: 'fourth.user@example.com'
|
|
23
23
|
)
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
FactoryBot.create(
|
|
26
26
|
:user,
|
|
27
27
|
display_name: 'Unsubscribed User',
|
|
28
28
|
email: 'unsubscribed.user@example.com'
|
|
29
29
|
)
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
FactoryBot.create(
|
|
32
32
|
:user,
|
|
33
33
|
display_name: 'Silent User',
|
|
34
34
|
email: 'silent.user@example.com'
|
|
35
35
|
)
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
FactoryBot.create(
|
|
38
38
|
:user,
|
|
39
39
|
display_name: 'Superadmin User',
|
|
40
40
|
email: 'superadmin.user@example.com'
|
|
41
41
|
).add_role(:superadmin)
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
FactoryBot.create(
|
|
44
44
|
:user,
|
|
45
45
|
display_name: 'Admin User',
|
|
46
46
|
email: 'admin.user@example.com'
|
|
File without changes
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
FactoryBot.define do
|
|
2
2
|
factory :attachment, class: 'MessageTrain::Attachment' do
|
|
3
3
|
message { MessageTrain::Message.order('RANDOM()').first }
|
|
4
4
|
attachment do
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
)
|
|
5
|
+
path = Dir[
|
|
6
|
+
Rails.root.join 'app/assets/files/message_train/attachments/*'
|
|
7
|
+
].sample
|
|
8
|
+
Rack::Test::UploadedFile.new(path)
|
|
10
9
|
end
|
|
11
10
|
end
|
|
12
11
|
end
|
data/spec/factories/group.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
FactoryBot.define do
|
|
2
2
|
factory :group do
|
|
3
3
|
title { Faker::Lorem.sentence }
|
|
4
|
-
description { Faker::Lorem.paragraphs([*1..5].sample).join("\n\n") }
|
|
4
|
+
description { Faker::Lorem.paragraphs(number: [*1..5].sample).join("\n\n") }
|
|
5
5
|
transient do
|
|
6
6
|
owner { User.order('RANDOM()').first }
|
|
7
7
|
# member_count 5
|
data/spec/factories/message.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
FactoryBot.define do
|
|
2
2
|
factory :message, class: 'MessageTrain::Message' do
|
|
3
3
|
sender do
|
|
4
4
|
User
|
|
@@ -18,7 +18,7 @@ FactoryGirl.define do
|
|
|
18
18
|
}
|
|
19
19
|
end
|
|
20
20
|
subject { Faker::Lorem.sentence }
|
|
21
|
-
body {
|
|
21
|
+
body { Faker::Lorem.paragraphs(number: [*1..5].sample).join("\n\n") }
|
|
22
22
|
|
|
23
23
|
transient do
|
|
24
24
|
generate_attachment? { [*1..100].sample >= 80 }
|
|
@@ -31,7 +31,7 @@ FactoryGirl.define do
|
|
|
31
31
|
# attributes
|
|
32
32
|
after(:create) do |message, evaluator|
|
|
33
33
|
if evaluator.generate_attachment?
|
|
34
|
-
|
|
34
|
+
FactoryBot.create(:attachment, message: message)
|
|
35
35
|
end
|
|
36
36
|
if message.recipients_to_save['users'].present?
|
|
37
37
|
participants = (
|
|
@@ -45,7 +45,7 @@ FactoryGirl.define do
|
|
|
45
45
|
if evaluator.generate_response? && participants.count > 1
|
|
46
46
|
response_sender = User.friendly.find(participants.sample)
|
|
47
47
|
response_recipients = participants - [response_sender.slug]
|
|
48
|
-
|
|
48
|
+
FactoryBot.create(
|
|
49
49
|
:message,
|
|
50
50
|
sender: response_sender,
|
|
51
51
|
recipients_to_save: { 'users' => response_recipients.join(', ') },
|
|
@@ -72,9 +72,9 @@ FactoryGirl.define do
|
|
|
72
72
|
end
|
|
73
73
|
|
|
74
74
|
factory :simple_message do
|
|
75
|
-
generate_ignore? false
|
|
76
|
-
generate_response? false
|
|
77
|
-
generate_attachment? false
|
|
75
|
+
generate_ignore? { false }
|
|
76
|
+
generate_response? { false }
|
|
77
|
+
generate_attachment? { false }
|
|
78
78
|
end
|
|
79
79
|
end
|
|
80
80
|
end
|
data/spec/factories/user.rb
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
FactoryBot.define do
|
|
2
2
|
factory :user do
|
|
3
3
|
display_name { Faker::Name.name }
|
|
4
4
|
sequence :email do |n|
|
|
5
5
|
"#{display_name.tr(' ', '.').downcase}#{n}@example.com"
|
|
6
6
|
end
|
|
7
|
-
password 'password'
|
|
8
|
-
password_confirmation 'password'
|
|
7
|
+
password { 'password' }
|
|
8
|
+
password_confirmation { 'password' }
|
|
9
9
|
end
|
|
10
10
|
end
|
data/spec/features/boxes_spec.rb
CHANGED
|
@@ -2,10 +2,10 @@ require 'rails_helper'
|
|
|
2
2
|
RSpec.feature 'Boxes' do
|
|
3
3
|
include_context 'loaded site'
|
|
4
4
|
|
|
5
|
-
it_behaves_like 'an authenticated section', '/box'
|
|
5
|
+
it_behaves_like 'an authenticated section', '/messages/box'
|
|
6
6
|
it_behaves_like(
|
|
7
7
|
'an authenticated section',
|
|
8
|
-
'/collectives/groups:membered-group'
|
|
8
|
+
'/messages/collectives/groups:membered-group'
|
|
9
9
|
)
|
|
10
10
|
|
|
11
11
|
describe 'When logged in as first-user' do
|
|
@@ -16,7 +16,7 @@ RSpec.feature 'Boxes' do
|
|
|
16
16
|
describe 'Showing' do
|
|
17
17
|
describe 'at /box/in' do
|
|
18
18
|
before do
|
|
19
|
-
visit '/box/in'
|
|
19
|
+
visit '/messages/box/in'
|
|
20
20
|
click_link 'Last'
|
|
21
21
|
end
|
|
22
22
|
it_behaves_like(
|
|
@@ -30,7 +30,7 @@ RSpec.feature 'Boxes' do
|
|
|
30
30
|
subject { page }
|
|
31
31
|
it do
|
|
32
32
|
should_not have_css(
|
|
33
|
-
'
|
|
33
|
+
'details.message-train-dropdown-nav-item summary',
|
|
34
34
|
text: 'Roles'
|
|
35
35
|
)
|
|
36
36
|
end
|
|
@@ -47,8 +47,8 @@ RSpec.feature 'Boxes' do
|
|
|
47
47
|
subject { page }
|
|
48
48
|
it do
|
|
49
49
|
should have_css(
|
|
50
|
-
"#message_train_conversation_#{attachment_conversation.id} "\
|
|
51
|
-
|
|
50
|
+
"#message_train_conversation_#{attachment_conversation.id} " \
|
|
51
|
+
'.message-train-icon'
|
|
52
52
|
)
|
|
53
53
|
end
|
|
54
54
|
end
|
|
@@ -68,7 +68,7 @@ RSpec.feature 'Boxes' do
|
|
|
68
68
|
describe 'at /box/in' do
|
|
69
69
|
describe 'using the buttons on each conversation' do
|
|
70
70
|
before do
|
|
71
|
-
visit '/box/in'
|
|
71
|
+
visit '/messages/box/in'
|
|
72
72
|
click_link 'Last'
|
|
73
73
|
within "#message_train_conversation_#{unread_conversation.id}" do
|
|
74
74
|
accept_confirm do
|
|
@@ -76,6 +76,7 @@ RSpec.feature 'Boxes' do
|
|
|
76
76
|
end
|
|
77
77
|
end
|
|
78
78
|
end
|
|
79
|
+
after { undo_leaked_mark(:untrash) }
|
|
79
80
|
it_behaves_like(
|
|
80
81
|
'a bootstrap page with an alert',
|
|
81
82
|
'info',
|
|
@@ -84,9 +85,8 @@ RSpec.feature 'Boxes' do
|
|
|
84
85
|
end
|
|
85
86
|
describe 'without checking anything' do
|
|
86
87
|
before do
|
|
87
|
-
visit '/box/in'
|
|
88
|
-
click_button '
|
|
89
|
-
click_link 'mark-read'
|
|
88
|
+
visit '/messages/box/in'
|
|
89
|
+
click_button 'mark-read'
|
|
90
90
|
end
|
|
91
91
|
it_behaves_like(
|
|
92
92
|
'a bootstrap page with an alert',
|
|
@@ -97,12 +97,16 @@ RSpec.feature 'Boxes' do
|
|
|
97
97
|
describe 'after checking a box' do
|
|
98
98
|
describe 'Marking Read' do
|
|
99
99
|
before do
|
|
100
|
-
visit '/box/in'
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
100
|
+
visit '/messages/box/in'
|
|
101
|
+
# Marking touches updated_at, which can move the
|
|
102
|
+
# conversation off the last page if an earlier example
|
|
103
|
+
# already marked it - only paginate there if needed.
|
|
104
|
+
checkbox = "objects_conversations_#{unread_conversation.id}"
|
|
105
|
+
click_link 'Last' unless page.has_field?(checkbox)
|
|
106
|
+
check checkbox
|
|
107
|
+
click_button 'mark-read'
|
|
105
108
|
end
|
|
109
|
+
after { undo_leaked_mark(:unread) }
|
|
106
110
|
it_behaves_like(
|
|
107
111
|
'a bootstrap page with an alert',
|
|
108
112
|
'info',
|
|
@@ -111,12 +115,13 @@ RSpec.feature 'Boxes' do
|
|
|
111
115
|
end
|
|
112
116
|
describe 'Marking Ignored' do
|
|
113
117
|
before do
|
|
114
|
-
visit '/box/in'
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
118
|
+
visit '/messages/box/in'
|
|
119
|
+
checkbox = "objects_conversations_#{unread_conversation.id}"
|
|
120
|
+
click_link 'Last' unless page.has_field?(checkbox)
|
|
121
|
+
check checkbox
|
|
122
|
+
click_button 'mark-ignored'
|
|
119
123
|
end
|
|
124
|
+
after { undo_leaked_mark(:unignore) }
|
|
120
125
|
it_behaves_like(
|
|
121
126
|
'a bootstrap page with an alert',
|
|
122
127
|
'info',
|
|
@@ -132,7 +137,7 @@ RSpec.feature 'Boxes' do
|
|
|
132
137
|
describe 'Showing' do
|
|
133
138
|
describe 'at /collectives/groups:membered-group/box/in' do
|
|
134
139
|
before do
|
|
135
|
-
visit '/collectives/groups:membered-group/box/in'
|
|
140
|
+
visit '/messages/collectives/groups:membered-group/box/in'
|
|
136
141
|
end
|
|
137
142
|
it_behaves_like(
|
|
138
143
|
'a bootstrap page listing a collection of items',
|
|
@@ -147,9 +152,8 @@ RSpec.feature 'Boxes' do
|
|
|
147
152
|
describe 'at /collectives/groups:membered-group/box/in' do
|
|
148
153
|
describe 'without checking anything' do
|
|
149
154
|
before do
|
|
150
|
-
visit '/collectives/groups:membered-group/box/in'
|
|
151
|
-
click_button '
|
|
152
|
-
click_link 'mark-read'
|
|
155
|
+
visit '/messages/collectives/groups:membered-group/box/in'
|
|
156
|
+
click_button 'mark-read'
|
|
153
157
|
end
|
|
154
158
|
it_behaves_like(
|
|
155
159
|
'a bootstrap page with an alert',
|
|
@@ -160,11 +164,11 @@ RSpec.feature 'Boxes' do
|
|
|
160
164
|
describe 'after checking a box' do
|
|
161
165
|
describe 'Marking Read' do
|
|
162
166
|
before do
|
|
163
|
-
visit '/collectives/groups:membered-group/box/in'
|
|
167
|
+
visit '/messages/collectives/groups:membered-group/box/in'
|
|
164
168
|
check "objects_conversations_#{membered_group_conversation.id}"
|
|
165
|
-
click_button '
|
|
166
|
-
click_link 'mark-read'
|
|
169
|
+
click_button 'mark-read'
|
|
167
170
|
end
|
|
171
|
+
after { undo_leaked_mark(:unread, conversation: membered_group_conversation) }
|
|
168
172
|
it_behaves_like(
|
|
169
173
|
'a bootstrap page with an alert',
|
|
170
174
|
'info',
|
|
@@ -173,11 +177,11 @@ RSpec.feature 'Boxes' do
|
|
|
173
177
|
end
|
|
174
178
|
describe 'Marking Ignored' do
|
|
175
179
|
before do
|
|
176
|
-
visit '/collectives/groups:membered-group/box/in'
|
|
180
|
+
visit '/messages/collectives/groups:membered-group/box/in'
|
|
177
181
|
check "objects_conversations_#{membered_group_conversation.id}"
|
|
178
|
-
click_button '
|
|
179
|
-
click_link 'mark-ignored'
|
|
182
|
+
click_button 'mark-ignored'
|
|
180
183
|
end
|
|
184
|
+
after { undo_leaked_mark(:unignore, conversation: membered_group_conversation) }
|
|
181
185
|
it_behaves_like(
|
|
182
186
|
'a bootstrap page with an alert',
|
|
183
187
|
'info',
|
|
@@ -198,12 +202,12 @@ RSpec.feature 'Boxes' do
|
|
|
198
202
|
describe 'Showing' do
|
|
199
203
|
describe 'at /box/in' do
|
|
200
204
|
before do
|
|
201
|
-
visit '/box/in'
|
|
205
|
+
visit '/messages/box/in'
|
|
202
206
|
end
|
|
203
207
|
|
|
204
208
|
describe 'lists Roles dropdown' do
|
|
205
209
|
subject { page }
|
|
206
|
-
it { should have_css('
|
|
210
|
+
it { should have_css('details.message-train-dropdown-nav-item summary', text: 'Roles') }
|
|
207
211
|
end
|
|
208
212
|
end
|
|
209
213
|
end
|
|
@@ -216,12 +220,12 @@ RSpec.feature 'Boxes' do
|
|
|
216
220
|
describe 'Showing' do
|
|
217
221
|
describe 'at /box/in' do
|
|
218
222
|
before do
|
|
219
|
-
visit '/box/in'
|
|
223
|
+
visit '/messages/box/in'
|
|
220
224
|
end
|
|
221
225
|
|
|
222
226
|
describe 'lists Roles dropdown' do
|
|
223
227
|
subject { page }
|
|
224
|
-
it { should have_css('
|
|
228
|
+
it { should have_css('details.message-train-dropdown-nav-item summary', text: 'Roles') }
|
|
225
229
|
end
|
|
226
230
|
end
|
|
227
231
|
end
|
|
@@ -2,7 +2,7 @@ require 'rails_helper'
|
|
|
2
2
|
RSpec.feature 'Conversations' do
|
|
3
3
|
include_context 'loaded site'
|
|
4
4
|
|
|
5
|
-
it_behaves_like 'an authenticated section', '/box/in/conversations/1'
|
|
5
|
+
it_behaves_like 'an authenticated section', '/messages/box/in/conversations/1'
|
|
6
6
|
|
|
7
7
|
describe 'When logged in' do
|
|
8
8
|
before do
|
|
@@ -11,7 +11,7 @@ RSpec.feature 'Conversations' do
|
|
|
11
11
|
describe 'Showing' do
|
|
12
12
|
describe 'at /box/in/conversations/:id' do
|
|
13
13
|
before do
|
|
14
|
-
visit "/box/in/conversations/#{unread_conversation.id}"
|
|
14
|
+
visit "/messages/box/in/conversations/#{unread_conversation.id}"
|
|
15
15
|
end
|
|
16
16
|
it_behaves_like(
|
|
17
17
|
'a bootstrap page showing an item',
|
|
@@ -31,9 +31,14 @@ RSpec.feature 'Conversations' do
|
|
|
31
31
|
describe 'at /box/in/conversations/:id' do
|
|
32
32
|
describe 'Marking Read' do
|
|
33
33
|
before do
|
|
34
|
-
visit "/box/in/conversations/#{unread_conversation.id}"
|
|
35
|
-
|
|
34
|
+
visit "/messages/box/in/conversations/#{unread_conversation.id}"
|
|
35
|
+
# An earlier example may have already marked this message read;
|
|
36
|
+
# toggle it back to unread first so this test always exercises
|
|
37
|
+
# (and can assert on) the read-marking action itself.
|
|
38
|
+
click_button "mark_unread_#{unread_message.id}" if page.has_button?("mark_unread_#{unread_message.id}")
|
|
39
|
+
click_button "mark_read_#{unread_message.id}"
|
|
36
40
|
end
|
|
41
|
+
after { undo_leaked_mark(:unread) }
|
|
37
42
|
it_behaves_like(
|
|
38
43
|
'a bootstrap page with an alert',
|
|
39
44
|
'info',
|
|
@@ -42,11 +47,13 @@ RSpec.feature 'Conversations' do
|
|
|
42
47
|
end
|
|
43
48
|
describe 'Marking Ignored' do
|
|
44
49
|
before do
|
|
45
|
-
visit "/box/in/conversations/#{unread_conversation.id}"
|
|
50
|
+
visit "/messages/box/in/conversations/#{unread_conversation.id}"
|
|
51
|
+
click_button 'Mark as Unignored' if page.has_button?('Mark as Unignored')
|
|
46
52
|
accept_confirm do
|
|
47
|
-
|
|
53
|
+
click_button 'Mark as Ignored'
|
|
48
54
|
end
|
|
49
55
|
end
|
|
56
|
+
after { undo_leaked_mark(:unignore) }
|
|
50
57
|
it_behaves_like(
|
|
51
58
|
'a bootstrap page with an alert',
|
|
52
59
|
'info',
|