message_train 0.1.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 +7 -0
- data/.document +5 -0
- data/.rspec +1 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -0
- data/Gemfile +51 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +83 -0
- data/Rakefile +71 -0
- data/VERSION +1 -0
- data/app/assets/javascripts/message_train.js +138 -0
- data/app/assets/stylesheets/message_train.scss +107 -0
- data/app/controllers/message_train/application_controller.rb +64 -0
- data/app/controllers/message_train/boxes_controller.rb +37 -0
- data/app/controllers/message_train/conversations_controller.rb +38 -0
- data/app/controllers/message_train/messages_controller.rb +74 -0
- data/app/controllers/message_train/participants_controller.rb +36 -0
- data/app/helpers/message_train/application_helper.rb +4 -0
- data/app/helpers/message_train/boxes_helper.rb +30 -0
- data/app/helpers/message_train/conversations_helper.rb +73 -0
- data/app/helpers/message_train/messages_helper.rb +58 -0
- data/app/models/message_train/attachment.rb +17 -0
- data/app/models/message_train/box.rb +268 -0
- data/app/models/message_train/conversation.rb +101 -0
- data/app/models/message_train/ignore.rb +18 -0
- data/app/models/message_train/message.rb +146 -0
- data/app/models/message_train/receipt.rb +70 -0
- data/app/views/application/404.html.haml +3 -0
- data/app/views/message_train/application/results.json.jbuilder +8 -0
- data/app/views/message_train/boxes/_dropdown_list.html.haml +5 -0
- data/app/views/message_train/boxes/_list_item.html.haml +5 -0
- data/app/views/message_train/boxes/_widget.html.haml +6 -0
- data/app/views/message_train/boxes/show.html.haml +47 -0
- data/app/views/message_train/conversations/_conversation.html.haml +9 -0
- data/app/views/message_train/conversations/_deleted_toggle.html.haml +1 -0
- data/app/views/message_train/conversations/_ignored_toggle.html.haml +4 -0
- data/app/views/message_train/conversations/_read_toggle.html.haml +4 -0
- data/app/views/message_train/conversations/_toggle.html.haml +1 -0
- data/app/views/message_train/conversations/_trashed_toggle.html.haml +4 -0
- data/app/views/message_train/conversations/show.html.haml +11 -0
- data/app/views/message_train/conversations/show.json.jbuilder +2 -0
- data/app/views/message_train/messages/_deleted_toggle.html.haml +1 -0
- data/app/views/message_train/messages/_form.html.haml +8 -0
- data/app/views/message_train/messages/_message.html.haml +35 -0
- data/app/views/message_train/messages/_read_toggle.html.haml +4 -0
- data/app/views/message_train/messages/_toggle.html.haml +1 -0
- data/app/views/message_train/messages/_trashed_toggle.html.haml +4 -0
- data/app/views/message_train/messages/edit.html.haml +2 -0
- data/app/views/message_train/messages/new.html.haml +2 -0
- data/app/views/message_train/messages/show.json.jbuilder +2 -0
- data/app/views/message_train/participants/_field.html.haml +4 -0
- data/app/views/message_train/participants/_participant.json.jbuilder +5 -0
- data/app/views/message_train/participants/index.json.jbuilder +3 -0
- data/app/views/message_train/participants/show.json.jbuilder +1 -0
- data/bin/rails +12 -0
- data/config/initializers/bootstrap_pager_config.rb +10 -0
- data/config/initializers/date_time.rb +5 -0
- data/config/locales/en.yml +50 -0
- data/config/routes.rb +11 -0
- data/db/migrate/20150721145319_create_message_train_conversations.rb +9 -0
- data/db/migrate/20150721160322_create_message_train_messages.rb +14 -0
- data/db/migrate/20150721161144_create_message_train_attachments.rb +10 -0
- data/db/migrate/20150721161940_create_message_train_receipts.rb +16 -0
- data/db/migrate/20150721163838_create_message_train_ignores.rb +11 -0
- data/lib/generators/message_train/install/install_generator.rb +30 -0
- data/lib/generators/message_train/install/templates/initializer.rb +10 -0
- data/lib/generators/message_train/utils.rb +16 -0
- data/lib/message_train/configuration.rb +35 -0
- data/lib/message_train/engine.rb +19 -0
- data/lib/message_train/localization.rb +31 -0
- data/lib/message_train/mixin.rb +83 -0
- data/lib/message_train/version.rb +7 -0
- data/lib/message_train.rb +20 -0
- data/lib/tasks/message_train_tasks.rake +0 -0
- data/message_train.gemspec +325 -0
- data/night_train.gemspec +274 -0
- data/spec/controllers/message_train/boxes_controller_spec.rb +82 -0
- data/spec/controllers/message_train/conversations_controller_spec.rb +86 -0
- data/spec/controllers/message_train/messages_controller_spec.rb +210 -0
- data/spec/controllers/message_train/participants_controller_spec.rb +35 -0
- data/spec/dummy/.rspec +2 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/files/message_train/attachments/1917-Boys_Race_Above-Wiki.jpg +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/ACD_Silverbarn's_Mayumi.jpg +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/ACD_obedience.jpg +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/A_Man_and_His_Dog.jpg +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/Alaskan_Malamute_agility_a-frame.jpg +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/American_water_spaniel_02.jpg +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/Aport_konkurs_rybnik.jpg +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/Askerhytta.jpg +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/Bambisj.jpg +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/Cattle_dog_skating.jpg +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/Dog's_Olympics_training_ground_-_geograph.org.uk_-_660324.jpg +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/DogShowHierarchy.png +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/Dog_weight_pull.jpg +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/Draghuntpostcard.jpg +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/Esham_51.JPG +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/FastCourseExample.jpg +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/Fotos_joel_141.JPG +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/Galgo_Spanish_male_brindle.jpg +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/Golden-retriever-carlos-bei-der-dummyarbeit.jpg +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/Habavk.jpg +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/Haie_rci.svg +1714 -0
- data/spec/dummy/app/assets/files/message_train/attachments/Hanging_18.jpg +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/Hundewa.jpg +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/K9ProSports_AttackOnHandler.jpg +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/K9ProSports_heel.jpg +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/K9Pro_Civil_agitation.JPG +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/TrainingSchutzhundRetrieveOverWall.jpg +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/example.pdf +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/letterlegal5.doc +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/pdf-sample.pdf +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/sample.pdf +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/tips.doc +0 -0
- data/spec/dummy/app/assets/files/message_train/attachments/wd-spectools-word-sample-04.doc +0 -0
- data/spec/dummy/app/assets/images/logo.svg +140 -0
- data/spec/dummy/app/assets/javascripts/application.js +17 -0
- data/spec/dummy/app/assets/stylesheets/application.css.scss +35 -0
- data/spec/dummy/app/controllers/application_controller.rb +14 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.keep +0 -0
- data/spec/dummy/app/models/.keep +0 -0
- data/spec/dummy/app/models/group.rb +19 -0
- data/spec/dummy/app/models/role.rb +10 -0
- data/spec/dummy/app/models/user.rb +23 -0
- data/spec/dummy/app/views/layouts/_top_navigation.html.haml +5 -0
- data/spec/dummy/app/views/layouts/application.html.haml +29 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/bin/setup +29 -0
- data/spec/dummy/config/application.rb +40 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +41 -0
- data/spec/dummy/config/environments/production.rb +79 -0
- data/spec/dummy/config/environments/test.rb +42 -0
- data/spec/dummy/config/initializers/assets.rb +11 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/bootstrap_leather.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/devise.rb +265 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/message_train.rb +10 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/paperclip.rb +2 -0
- data/spec/dummy/config/initializers/rolify.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/devise.en.yml +60 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +5 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/config/unused/temporary_i18n_debugging.rb +12 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/migrate/20150721140013_devise_create_users.rb +42 -0
- data/spec/dummy/db/migrate/20150721141009_rolify_create_roles.rb +19 -0
- data/spec/dummy/db/migrate/20150721141128_create_groups.rb +11 -0
- data/spec/dummy/db/migrate/20150721150307_add_display_name_column_to_users.rb +6 -0
- data/spec/dummy/db/migrate/20150724142846_create_message_train_conversations.night_train.rb +10 -0
- data/spec/dummy/db/migrate/20150724142847_create_message_train_messages.night_train.rb +15 -0
- data/spec/dummy/db/migrate/20150724142848_create_message_train_attachments.night_train.rb +11 -0
- data/spec/dummy/db/migrate/20150724142849_create_message_train_receipts.night_train.rb +17 -0
- data/spec/dummy/db/migrate/20150724142850_create_message_train_ignores.night_train.rb +12 -0
- data/spec/dummy/db/schema.rb +121 -0
- data/spec/dummy/db/seeds/conversations.seeds.rb +86 -0
- data/spec/dummy/db/seeds/development/conversations.seeds.rb +9 -0
- data/spec/dummy/db/seeds/groups.seeds.rb +9 -0
- data/spec/dummy/db/seeds/test/conversations.seeds.rb +9 -0
- data/spec/dummy/db/seeds/users.seeds.rb +15 -0
- data/spec/dummy/db/seeds.rb +0 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/lib/assets/.keep +0 -0
- data/spec/dummy/log/.keep +0 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/capybara.html +193 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/factories/attachment.rb +6 -0
- data/spec/factories/group.rb +20 -0
- data/spec/factories/message.rb +68 -0
- data/spec/factories/user.rb +8 -0
- data/spec/features/boxes_spec.rb +50 -0
- data/spec/features/conversations_spec.rb +36 -0
- data/spec/features/messages_spec.rb +53 -0
- data/spec/helpers/message_train/boxes_helper_spec.rb +44 -0
- data/spec/message_train_spec.rb +7 -0
- data/spec/models/group_spec.rb +23 -0
- data/spec/models/message_train/attachment_spec.rb +12 -0
- data/spec/models/message_train/box_spec.rb +195 -0
- data/spec/models/message_train/conversation_spec.rb +98 -0
- data/spec/models/message_train/ignore_spec.rb +27 -0
- data/spec/models/message_train/message_spec.rb +83 -0
- data/spec/models/message_train/receipt_spec.rb +73 -0
- data/spec/models/user_spec.rb +68 -0
- data/spec/rails_helper.rb +83 -0
- data/spec/spec_helper.rb +92 -0
- data/spec/support/controller_behaviors.rb +88 -0
- data/spec/support/controller_macros.rb +13 -0
- data/spec/support/conversations.rb +10 -0
- data/spec/support/factory_girl.rb +3 -0
- data/spec/support/feature_behaviors.rb +62 -0
- data/spec/support/groups.rb +3 -0
- data/spec/support/loaded_site.rb +5 -0
- data/spec/support/shared_connection.rb +13 -0
- data/spec/support/users.rb +6 -0
- data/spec/support/utilities.rb +8 -0
- data/vendor/assets/javascripts/bootstrap-tags.js +623 -0
- data/vendor/assets/stylesheets/bootstrap-tags.css +78 -0
- metadata +608 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
FactoryGirl.define do
|
|
2
|
+
factory :group do
|
|
3
|
+
title { Faker::Lorem.sentence }
|
|
4
|
+
description { Faker::Lorem.paragraphs([*1..5].sample).join("\n\n") }
|
|
5
|
+
transient do
|
|
6
|
+
owner { User.order("RANDOM()").first }
|
|
7
|
+
member_count 5
|
|
8
|
+
end
|
|
9
|
+
# the after(:create) yields two values; the user instance itself and the
|
|
10
|
+
# evaluator, which stores all values from the factory, including transient
|
|
11
|
+
# attributes; `create_list`'s second argument is the number of records
|
|
12
|
+
# to create and we make sure the user is associated properly to the post
|
|
13
|
+
after(:create) do |group, evaluator|
|
|
14
|
+
evaluator.owner.add_role(:owner, group)
|
|
15
|
+
User.where('id != ?', evaluator.owner.id).order("RANDOM()").limit(evaluator.member_count).find_each do |user|
|
|
16
|
+
user.add_role(:member, group)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
FactoryGirl.define do
|
|
2
|
+
factory :message, class: 'MessageTrain::Message' do
|
|
3
|
+
sender {
|
|
4
|
+
User
|
|
5
|
+
.order('RANDOM()')
|
|
6
|
+
.first
|
|
7
|
+
}
|
|
8
|
+
recipients_to_save { { 'users' =>
|
|
9
|
+
User
|
|
10
|
+
.where('id != ?', sender.id)
|
|
11
|
+
.order('RANDOM()')
|
|
12
|
+
.limit([*1..5].sample)
|
|
13
|
+
.collect { |x| x.slug }
|
|
14
|
+
.join(', ')
|
|
15
|
+
} }
|
|
16
|
+
subject { Faker::Lorem.sentence }
|
|
17
|
+
body { Faker::Lorem.paragraphs([*1..5].sample).join("\n\n") }
|
|
18
|
+
transient do
|
|
19
|
+
generate_attachment? { [*1..100].sample >= 80 }
|
|
20
|
+
generate_response? { [*1..100].sample >= 50 }
|
|
21
|
+
generate_ignore? { [*1..100].sample >= 80 }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# the after(:create) yields two values; the user instance itself and the
|
|
25
|
+
# evaluator, which stores all values from the factory, including transient
|
|
26
|
+
# attributes; `create_list`'s second argument is the number of records
|
|
27
|
+
# to create and we make sure the user is associated properly to the post
|
|
28
|
+
after(:create) do |message, evaluator|
|
|
29
|
+
if evaluator.generate_attachment?
|
|
30
|
+
FactoryGirl.create(:attachment, message: message)
|
|
31
|
+
end
|
|
32
|
+
if message.recipients_to_save['users'].present?
|
|
33
|
+
participants = (message.recipients_to_save['users'].split(',') + [message.sender.slug]).collect{ |x| x.strip }
|
|
34
|
+
if evaluator.generate_ignore?
|
|
35
|
+
ignorer = User.friendly.find(participants.sample)
|
|
36
|
+
participants = participants - [ignorer.slug]
|
|
37
|
+
message.conversation.set_ignored(ignorer)
|
|
38
|
+
end
|
|
39
|
+
if evaluator.generate_response? && participants.count > 1
|
|
40
|
+
response_sender = User.friendly.find(participants.sample)
|
|
41
|
+
response_recipients = participants - [response_sender.slug]
|
|
42
|
+
FactoryGirl.create(
|
|
43
|
+
:message,
|
|
44
|
+
sender: response_sender,
|
|
45
|
+
recipients_to_save: { 'users' => response_recipients.join(', ') },
|
|
46
|
+
conversation: message.conversation
|
|
47
|
+
)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
factory :message_from_random_sender do
|
|
53
|
+
sender {
|
|
54
|
+
recipient_user_ids = recipients_to_save['users'].split(',').collect{ |x| User.friendly.find(x.strip).id }
|
|
55
|
+
User
|
|
56
|
+
.where('NOT (id IN (?))', recipient_user_ids )
|
|
57
|
+
.order('RANDOM()')
|
|
58
|
+
.first
|
|
59
|
+
}
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
factory :simple_message do
|
|
63
|
+
generate_ignore? false
|
|
64
|
+
generate_response? false
|
|
65
|
+
generate_attachment? false
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require 'rails_helper'
|
|
2
|
+
RSpec.feature 'Boxes' do
|
|
3
|
+
include_context 'loaded site'
|
|
4
|
+
|
|
5
|
+
before do
|
|
6
|
+
login_as first_user
|
|
7
|
+
end
|
|
8
|
+
describe 'Showing' do
|
|
9
|
+
describe 'at /box/in' do
|
|
10
|
+
before do
|
|
11
|
+
visit '/box/in'
|
|
12
|
+
end
|
|
13
|
+
it_behaves_like 'a bootstrap page listing a collection of items', MessageTrain::Conversation, plural_title: 'Inbox', minimum: 2
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
describe 'Marking', js: true do
|
|
17
|
+
describe 'at /box/in' do
|
|
18
|
+
describe 'without checking anything' do
|
|
19
|
+
before do
|
|
20
|
+
visit '/box/in'
|
|
21
|
+
click_button 'Mark'
|
|
22
|
+
click_link 'mark-read'
|
|
23
|
+
end
|
|
24
|
+
it_behaves_like 'a bootstrap page with an alert', 'warning', 'Nothing to do'
|
|
25
|
+
end
|
|
26
|
+
describe 'after checking a box' do
|
|
27
|
+
describe 'Marking Read' do
|
|
28
|
+
before do
|
|
29
|
+
visit '/box/in'
|
|
30
|
+
click_link 'Last'
|
|
31
|
+
check "objects_conversations_#{unread_conversation.id.to_s}"
|
|
32
|
+
click_button 'Mark'
|
|
33
|
+
click_link 'mark-read'
|
|
34
|
+
end
|
|
35
|
+
it_behaves_like 'a bootstrap page with an alert', 'info', 'Update successful'
|
|
36
|
+
end
|
|
37
|
+
describe 'Marking Ignored' do
|
|
38
|
+
before do
|
|
39
|
+
visit '/box/in'
|
|
40
|
+
click_link 'Last'
|
|
41
|
+
check "objects_conversations_#{unread_conversation.id.to_s}"
|
|
42
|
+
click_button 'Mark'
|
|
43
|
+
click_link 'mark-ignored'
|
|
44
|
+
end
|
|
45
|
+
it_behaves_like 'a bootstrap page with an alert', 'info', 'Update successful'
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require 'rails_helper'
|
|
2
|
+
RSpec.feature 'Conversations' do
|
|
3
|
+
include_context 'loaded site'
|
|
4
|
+
|
|
5
|
+
before do
|
|
6
|
+
login_as first_user
|
|
7
|
+
end
|
|
8
|
+
describe 'Showing' do
|
|
9
|
+
describe 'at /box/in/conversations/:id' do
|
|
10
|
+
before do
|
|
11
|
+
visit '/box/in/conversations/'+unread_conversation.id.to_s
|
|
12
|
+
end
|
|
13
|
+
it_behaves_like 'a bootstrap page showing an item', MessageTrain::Conversation, 'Unread Conversation'
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
describe 'Marking', js: true do
|
|
17
|
+
describe 'at /box/in/conversations/:id' do
|
|
18
|
+
describe 'Marking Read' do
|
|
19
|
+
before do
|
|
20
|
+
visit '/box/in/conversations/'+unread_conversation.id.to_s
|
|
21
|
+
click_link "mark_read_#{unread_conversation.messages.first.id.to_s}"
|
|
22
|
+
end
|
|
23
|
+
it_behaves_like 'a bootstrap page with an alert', 'info', 'Update successful'
|
|
24
|
+
end
|
|
25
|
+
describe 'Marking Ignored' do
|
|
26
|
+
before do
|
|
27
|
+
visit '/box/in/conversations/'+unread_conversation.id.to_s
|
|
28
|
+
accept_confirm do
|
|
29
|
+
click_link 'Mark as Ignored'
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
it_behaves_like 'a bootstrap page with an alert', 'info', 'Update successful'
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
require 'rails_helper'
|
|
2
|
+
RSpec.feature 'Messages' do
|
|
3
|
+
include_context 'loaded site'
|
|
4
|
+
|
|
5
|
+
before do
|
|
6
|
+
login_as first_user
|
|
7
|
+
end
|
|
8
|
+
describe 'Drafting', js: true do
|
|
9
|
+
describe 'at /box/in/messages' do
|
|
10
|
+
before do
|
|
11
|
+
visit '/box/in/messages/new/'
|
|
12
|
+
recipient_input = find(:css, "#message_recipients_to_save_users .tags-input")
|
|
13
|
+
recipient_input.set("")
|
|
14
|
+
fill_in 'Subject', with: 'This is a draft.'
|
|
15
|
+
fill_in 'Body', with: 'This is the body.'
|
|
16
|
+
click_button 'Send'
|
|
17
|
+
end
|
|
18
|
+
it_behaves_like 'a bootstrap page with an alert', 'warning', 'Message saved as draft.'
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
describe 'Composing', js: true do
|
|
22
|
+
describe 'at /box/in/messages' do
|
|
23
|
+
before do
|
|
24
|
+
visit '/box/in/messages/new/'
|
|
25
|
+
recipient_input = find(:css, "#message_recipients_to_save_users .tags-input")
|
|
26
|
+
recipient_input.set("sec")
|
|
27
|
+
recipient_input.native.send_keys :arrow_down
|
|
28
|
+
recipient_input.native.send_keys :return
|
|
29
|
+
fill_in 'Subject', with: 'This is the subject.'
|
|
30
|
+
fill_in 'Body', with: 'This is the body.'
|
|
31
|
+
click_button 'Send'
|
|
32
|
+
end
|
|
33
|
+
it_behaves_like 'a bootstrap page with an alert', 'info', 'Message sent.'
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
describe 'Editing a Draft', js: true do
|
|
37
|
+
describe 'at /box/in/messages' do
|
|
38
|
+
before do
|
|
39
|
+
visit "/box/in/conversations/#{draft_conversation.id}"
|
|
40
|
+
recipient_input = find(:css, "#message_recipients_to_save_users .tags-input")
|
|
41
|
+
recipient_input.set("sec")
|
|
42
|
+
recipient_input.native.send_keys :arrow_down
|
|
43
|
+
recipient_input.native.send_keys :return
|
|
44
|
+
fill_in 'Subject', with: 'This is the subject.'
|
|
45
|
+
fill_in 'Body', with: 'This is the body.'
|
|
46
|
+
find(:css, "#message_draft").set(false)
|
|
47
|
+
click_button 'Send'
|
|
48
|
+
end
|
|
49
|
+
it_behaves_like 'a bootstrap page with an alert', 'info', 'Message sent.'
|
|
50
|
+
it_behaves_like 'a bootstrap page without an alert', 'warning'
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
require 'rails_helper'
|
|
2
|
+
|
|
3
|
+
describe MessageTrain::BoxesHelper do
|
|
4
|
+
include_context 'loaded site'
|
|
5
|
+
include ControllerMacros
|
|
6
|
+
|
|
7
|
+
before do
|
|
8
|
+
login_user first_user
|
|
9
|
+
end
|
|
10
|
+
context '#box_nav_item' do
|
|
11
|
+
subject { helper.box_nav_item(first_user.box(:in)) }
|
|
12
|
+
it { should have_tag 'li', text: /Inbox/ }
|
|
13
|
+
it { should have_tag 'span', text: /[0-9]+/, with: { class: 'badge' } }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
context '#box_list_item' do
|
|
17
|
+
subject { helper.box_list_item(first_user.box(:in), class: 'foo') }
|
|
18
|
+
it { should have_tag 'li', text: /Inbox/, with: { class: 'foo' } }
|
|
19
|
+
it { should have_tag 'span', text: /[0-9]+/, with: { class: 'badge' } }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
context '#boxes_widget' do
|
|
23
|
+
subject { helper.boxes_widget }
|
|
24
|
+
it { should have_tag 'h3', text: /Messages/ }
|
|
25
|
+
it { should have_tag 'ul', with: { class: 'list-group' } }
|
|
26
|
+
it { should have_tag 'li', with: { class: 'list-group-item' }, count: 6 }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
context '#boxes_dropdown_list' do
|
|
30
|
+
subject { helper.boxes_dropdown_list }
|
|
31
|
+
it { should have_tag 'ul', with: { class: 'dropdown-menu' } }
|
|
32
|
+
it { should have_tag 'li', minimum: 5 }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
context '#box_participant_slug' do
|
|
36
|
+
subject { helper.box_participant_slug(first_user) }
|
|
37
|
+
it { should eq 'first-user' }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
context '#box_participant_name' do
|
|
41
|
+
subject { helper.box_participant_name(first_user) }
|
|
42
|
+
it { should eq 'First User' }
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'rails_helper'
|
|
2
|
+
|
|
3
|
+
RSpec.describe Group do
|
|
4
|
+
describe 'Model' do
|
|
5
|
+
# MessageTrain Gem, and Rolify Gem by extension
|
|
6
|
+
it { should have_many(:roles) }
|
|
7
|
+
|
|
8
|
+
# MessageTrain Gem
|
|
9
|
+
it { should have_many(:receipts) }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe 'Scopes and Methods from Message Train' do
|
|
13
|
+
include_context 'loaded site'
|
|
14
|
+
|
|
15
|
+
describe '#conversations' do
|
|
16
|
+
subject { first_group.conversations(:in) }
|
|
17
|
+
its(:first) { should be_a MessageTrain::Conversation }
|
|
18
|
+
its(:count) { should eq 1 }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
require 'rails_helper'
|
|
2
|
+
|
|
3
|
+
module MessageTrain
|
|
4
|
+
RSpec.describe Box do
|
|
5
|
+
describe 'Model' do
|
|
6
|
+
|
|
7
|
+
end
|
|
8
|
+
describe 'Scopes and Methods' do
|
|
9
|
+
include_context 'loaded site'
|
|
10
|
+
|
|
11
|
+
describe '#unread_count' do
|
|
12
|
+
subject { first_user.box.unread_count }
|
|
13
|
+
it { should be >= 2 }
|
|
14
|
+
end
|
|
15
|
+
describe '#conversations' do
|
|
16
|
+
context 'with division as :in' do
|
|
17
|
+
subject { first_user.box.conversations }
|
|
18
|
+
it { should_not include sent_conversation }
|
|
19
|
+
it { should include unread_conversation }
|
|
20
|
+
it { should include read_conversation }
|
|
21
|
+
it { should_not include ignored_conversation }
|
|
22
|
+
it { should_not include trashed_conversation }
|
|
23
|
+
it { should_not include deleted_conversation }
|
|
24
|
+
it { should_not include draft_conversation }
|
|
25
|
+
end
|
|
26
|
+
context 'with division as :sent' do
|
|
27
|
+
subject { first_user.box(:sent).conversations }
|
|
28
|
+
it { should include sent_conversation }
|
|
29
|
+
it { should_not include unread_conversation }
|
|
30
|
+
it { should_not include read_conversation }
|
|
31
|
+
it { should_not include ignored_conversation }
|
|
32
|
+
it { should_not include trashed_conversation }
|
|
33
|
+
it { should_not include deleted_conversation }
|
|
34
|
+
it { should_not include draft_conversation }
|
|
35
|
+
end
|
|
36
|
+
context 'with division as :trash' do
|
|
37
|
+
subject { first_user.box(:trash).conversations }
|
|
38
|
+
it { should_not include sent_conversation }
|
|
39
|
+
it { should_not include unread_conversation }
|
|
40
|
+
it { should_not include read_conversation }
|
|
41
|
+
it { should_not include ignored_conversation }
|
|
42
|
+
it { should include trashed_conversation }
|
|
43
|
+
it { should_not include deleted_conversation }
|
|
44
|
+
it { should_not include draft_conversation }
|
|
45
|
+
end
|
|
46
|
+
context 'with division as :drafts' do
|
|
47
|
+
subject { first_user.box(:drafts).conversations }
|
|
48
|
+
it { should_not include sent_conversation }
|
|
49
|
+
it { should_not include trashed_conversation }
|
|
50
|
+
it { should_not include read_conversation }
|
|
51
|
+
it { should_not include unread_conversation }
|
|
52
|
+
it { should_not include deleted_conversation }
|
|
53
|
+
it { should_not include ignored_conversation }
|
|
54
|
+
it { should include draft_conversation }
|
|
55
|
+
end
|
|
56
|
+
context 'with unread set to true' do
|
|
57
|
+
subject { first_user.box.conversations(unread: true) }
|
|
58
|
+
it { should_not include sent_conversation }
|
|
59
|
+
it { should include unread_conversation }
|
|
60
|
+
it { should_not include read_conversation }
|
|
61
|
+
it { should_not include ignored_conversation }
|
|
62
|
+
it { should_not include trashed_conversation }
|
|
63
|
+
it { should_not include deleted_conversation }
|
|
64
|
+
it { should_not include draft_conversation }
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
describe '#ignore' do
|
|
68
|
+
context 'when authorized' do
|
|
69
|
+
before do
|
|
70
|
+
first_user.box.ignore(read_conversation)
|
|
71
|
+
end
|
|
72
|
+
subject { read_conversation.is_ignored?(first_user) }
|
|
73
|
+
it { should be true}
|
|
74
|
+
end
|
|
75
|
+
context 'when not authorized' do
|
|
76
|
+
before do
|
|
77
|
+
last_user.box.ignore(read_conversation)
|
|
78
|
+
end
|
|
79
|
+
subject { last_user.box.errors.all.first[:message] }
|
|
80
|
+
it { should match /Access to Conversation ([0-9]+) denied/ }
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
describe '#unignore' do
|
|
84
|
+
context 'when authorized' do
|
|
85
|
+
before do
|
|
86
|
+
first_user.box.unignore(ignored_conversation)
|
|
87
|
+
end
|
|
88
|
+
subject { ignored_conversation.is_ignored?(first_user) }
|
|
89
|
+
it { should be false }
|
|
90
|
+
end
|
|
91
|
+
context 'when not authorized' do
|
|
92
|
+
before do
|
|
93
|
+
last_user.box.unignore(read_conversation)
|
|
94
|
+
end
|
|
95
|
+
subject { last_user.box.errors.all.first[:message] }
|
|
96
|
+
it { should match /Access to Conversation ([0-9]+) denied/ }
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
describe '#title' do
|
|
100
|
+
context 'with division set to :in' do
|
|
101
|
+
subject { first_user.box.title }
|
|
102
|
+
it { should eq 'Inbox' }
|
|
103
|
+
end
|
|
104
|
+
context 'with division set to :sent' do
|
|
105
|
+
subject { first_user.box(:sent).title }
|
|
106
|
+
it { should eq 'Sent Messages' }
|
|
107
|
+
end
|
|
108
|
+
context 'with division set to :all' do
|
|
109
|
+
subject { first_user.box(:all).title }
|
|
110
|
+
it { should eq 'All Messages' }
|
|
111
|
+
end
|
|
112
|
+
context 'with division set to :drafts' do
|
|
113
|
+
subject { first_user.box(:drafts).title }
|
|
114
|
+
it { should eq 'Drafts' }
|
|
115
|
+
end
|
|
116
|
+
context 'with division set to :trash' do
|
|
117
|
+
subject { first_user.box(:trash).title }
|
|
118
|
+
it { should eq 'Trash' }
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
describe '#mark' do
|
|
122
|
+
before do
|
|
123
|
+
first_user.box.mark('unread', conversations: [read_conversation.id.to_s])
|
|
124
|
+
end
|
|
125
|
+
subject { read_conversation.includes_read_for?(first_user) }
|
|
126
|
+
it { should be false }
|
|
127
|
+
end
|
|
128
|
+
describe '.send_message' do
|
|
129
|
+
context 'when message is valid' do
|
|
130
|
+
let(:valid_attributes) { { recipients_to_save: {'users' => 'second-user, third-user'}, subject: 'Test Message', body: 'This is the content.' } }
|
|
131
|
+
subject { first_user.box.send_message(valid_attributes) }
|
|
132
|
+
it { should be_a MessageTrain::Message }
|
|
133
|
+
its(:new_record?) { should be false }
|
|
134
|
+
its('errors.full_messages.to_sentence') { should eq '' }
|
|
135
|
+
its(:recipients) { should include second_user }
|
|
136
|
+
its(:recipients) { should include third_user }
|
|
137
|
+
its(:draft) { should be false }
|
|
138
|
+
end
|
|
139
|
+
context 'when message is invalid' do
|
|
140
|
+
let(:invalid_attributes) { { recipients_to_save: {'users' => 'second-user, third-user'}, subject: nil, body: 'This is the content.' } }
|
|
141
|
+
subject { first_user.box.send_message(invalid_attributes) }
|
|
142
|
+
it { should be_a_new MessageTrain::Message }
|
|
143
|
+
its('errors.full_messages.to_sentence') { should eq "Subject can't be blank" }
|
|
144
|
+
its(:recipients) { should be_empty }
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
describe '.update_message' do
|
|
148
|
+
let(:draft_message) { draft_conversation.messages.first }
|
|
149
|
+
context 'when message is valid' do
|
|
150
|
+
let(:valid_attributes) { {
|
|
151
|
+
recipients_to_save: {'users' => 'second-user, third-user'},
|
|
152
|
+
subject: 'Test Message',
|
|
153
|
+
body: 'This is the content.',
|
|
154
|
+
draft: false
|
|
155
|
+
} }
|
|
156
|
+
subject { first_user.box.update_message(draft_message, valid_attributes) }
|
|
157
|
+
it { should be_a MessageTrain::Message }
|
|
158
|
+
its('errors.full_messages.to_sentence') { should eq '' }
|
|
159
|
+
its(:recipients) { should include second_user }
|
|
160
|
+
its(:recipients) { should include third_user }
|
|
161
|
+
its(:subject) { should eq 'Test Message' }
|
|
162
|
+
its(:draft) { should be false }
|
|
163
|
+
end
|
|
164
|
+
context 'when message is invalid' do
|
|
165
|
+
let(:invalid_attributes) { {
|
|
166
|
+
recipients_to_save: {'users' => 'second-user, third-user'},
|
|
167
|
+
subject: '',
|
|
168
|
+
body: 'This is the content.',
|
|
169
|
+
draft: false
|
|
170
|
+
} }
|
|
171
|
+
subject { first_user.box.update_message(draft_message, invalid_attributes) }
|
|
172
|
+
it { should be_a MessageTrain::Message }
|
|
173
|
+
its('errors.full_messages.to_sentence') { should eq "Subject can't be blank" }
|
|
174
|
+
its(:recipients) { should be_empty }
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
describe '.new_message' do
|
|
179
|
+
context 'when conversation is set' do
|
|
180
|
+
let(:expected_recipients) { { 'users' => 'second-user' } }
|
|
181
|
+
subject { first_user.box.new_message(conversation_id: unread_conversation.id) }
|
|
182
|
+
it { should be_a_new MessageTrain::Message }
|
|
183
|
+
its(:subject) { should eq 'Re: Unread Conversation' }
|
|
184
|
+
its(:recipients_to_save) { should eq expected_recipients }
|
|
185
|
+
end
|
|
186
|
+
context 'when conversation is not set' do
|
|
187
|
+
subject { first_user.box.new_message }
|
|
188
|
+
it { should be_a_new MessageTrain::Message }
|
|
189
|
+
its(:subject) { should eq nil }
|
|
190
|
+
its(:recipients_to_save) { should be_empty }
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
end
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
require 'rails_helper'
|
|
2
|
+
|
|
3
|
+
module MessageTrain
|
|
4
|
+
RSpec.describe Conversation do
|
|
5
|
+
describe 'Model' do
|
|
6
|
+
it { should have_many :messages }
|
|
7
|
+
it { should have_many :ignores }
|
|
8
|
+
it { should have_many(:receipts).through(:messages) }
|
|
9
|
+
end
|
|
10
|
+
describe 'Scopes and Methods' do
|
|
11
|
+
include_context 'loaded site'
|
|
12
|
+
describe '#default_recipients_for' do
|
|
13
|
+
subject { sent_conversation.default_recipients_for(first_user) }
|
|
14
|
+
it { should include second_user }
|
|
15
|
+
it { should_not include first_user }
|
|
16
|
+
it { should_not include third_user }
|
|
17
|
+
end
|
|
18
|
+
describe '#set_ignored and #is_ignored?' do
|
|
19
|
+
subject { ignored_conversation.is_ignored?(first_user) }
|
|
20
|
+
it { should be true }
|
|
21
|
+
end
|
|
22
|
+
describe '#set_unignored' do
|
|
23
|
+
before do
|
|
24
|
+
ignored_conversation.set_unignored(first_user)
|
|
25
|
+
end
|
|
26
|
+
subject { ignored_conversation.is_ignored?(first_user) }
|
|
27
|
+
it { should be false }
|
|
28
|
+
end
|
|
29
|
+
describe '#mark and #includes_read_for?' do
|
|
30
|
+
before do
|
|
31
|
+
unread_conversation.mark(:read, first_user)
|
|
32
|
+
end
|
|
33
|
+
subject { unread_conversation.includes_read_for?(first_user) }
|
|
34
|
+
it { should be true }
|
|
35
|
+
end
|
|
36
|
+
describe '#includes_drafts_by?' do
|
|
37
|
+
subject { draft_conversation.includes_drafts_by?(first_user) }
|
|
38
|
+
it { should be true }
|
|
39
|
+
end
|
|
40
|
+
describe '.with_drafts_by' do
|
|
41
|
+
subject { MessageTrain::Conversation.with_drafts_by(first_user) }
|
|
42
|
+
its(:first) { should be_a MessageTrain::Conversation }
|
|
43
|
+
its(:count) { should eq 1 }
|
|
44
|
+
end
|
|
45
|
+
describe 'Dynamic Methods' do
|
|
46
|
+
describe '.trashed_for' do
|
|
47
|
+
subject { MessageTrain::Conversation.with_trashed_for(first_user) }
|
|
48
|
+
it { should include trashed_conversation }
|
|
49
|
+
end
|
|
50
|
+
describe '.untrashed_for' do
|
|
51
|
+
subject { MessageTrain::Conversation.with_untrashed_for(first_user) }
|
|
52
|
+
it { should_not include trashed_conversation }
|
|
53
|
+
end
|
|
54
|
+
describe '.deleted_for' do
|
|
55
|
+
subject { MessageTrain::Conversation.with_deleted_for(first_user) }
|
|
56
|
+
it { should include deleted_conversation }
|
|
57
|
+
end
|
|
58
|
+
describe '.undeleted_for' do
|
|
59
|
+
subject { MessageTrain::Conversation.with_undeleted_for(first_user) }
|
|
60
|
+
it { should_not include deleted_conversation }
|
|
61
|
+
end
|
|
62
|
+
describe '.read_for' do
|
|
63
|
+
subject { MessageTrain::Conversation.with_read_for(first_user) }
|
|
64
|
+
it { should include read_conversation }
|
|
65
|
+
end
|
|
66
|
+
describe '.unread_for' do
|
|
67
|
+
subject { MessageTrain::Conversation.with_unread_for(first_user) }
|
|
68
|
+
it { should include sent_conversation }
|
|
69
|
+
it { should include unread_conversation }
|
|
70
|
+
end
|
|
71
|
+
describe '#includes_trashed_to?' do
|
|
72
|
+
subject { trashed_conversation.includes_trashed_to?(first_user) }
|
|
73
|
+
it { should be true }
|
|
74
|
+
end
|
|
75
|
+
describe '#includes_read_to?' do
|
|
76
|
+
subject { read_conversation.includes_read_to?(first_user) }
|
|
77
|
+
it { should be true }
|
|
78
|
+
end
|
|
79
|
+
describe '#includes_deleted_to?' do
|
|
80
|
+
subject { deleted_conversation.includes_deleted_to?(first_user) }
|
|
81
|
+
it { should be true }
|
|
82
|
+
end
|
|
83
|
+
describe '#includes_receipts_to?' do
|
|
84
|
+
subject { unread_conversation.includes_receipts_to?(first_user) }
|
|
85
|
+
it { should be true }
|
|
86
|
+
end
|
|
87
|
+
describe '#includes_receipts_by?' do
|
|
88
|
+
subject { sent_conversation.includes_receipts_by?(first_user) }
|
|
89
|
+
it { should be true }
|
|
90
|
+
end
|
|
91
|
+
describe '#includes_receipts_for?' do
|
|
92
|
+
subject { sent_conversation.includes_receipts_for?(first_user) }
|
|
93
|
+
it { should be true }
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'rails_helper'
|
|
2
|
+
|
|
3
|
+
module MessageTrain
|
|
4
|
+
RSpec.describe Ignore do
|
|
5
|
+
describe 'Model' do
|
|
6
|
+
it { should belong_to :conversation }
|
|
7
|
+
it { should belong_to :participant }
|
|
8
|
+
it { should validate_presence_of :conversation }
|
|
9
|
+
it { should validate_presence_of :participant }
|
|
10
|
+
end
|
|
11
|
+
describe 'Scopes and Methods' do
|
|
12
|
+
include_context 'loaded site'
|
|
13
|
+
describe '.find_all_by_participant' do
|
|
14
|
+
subject { ignored_conversation.ignores.find_all_by_participant(first_user) }
|
|
15
|
+
its(:first) { should be_a MessageTrain::Ignore }
|
|
16
|
+
end
|
|
17
|
+
describe '.conversation_ids' do
|
|
18
|
+
subject { MessageTrain::Ignore.conversation_ids }
|
|
19
|
+
it { should include ignored_conversation.id }
|
|
20
|
+
end
|
|
21
|
+
describe '.conversations' do
|
|
22
|
+
subject { MessageTrain::Ignore.conversations }
|
|
23
|
+
it { should include ignored_conversation }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|