diff --git a/Gemfile b/Gemfile index 3ede96cce..4c37d5ea1 100644 --- a/Gemfile +++ b/Gemfile @@ -59,3 +59,7 @@ group :test do gem 'coveralls', require: false end +group :test do + gem 'email_spec' +end + diff --git a/Gemfile.lock b/Gemfile.lock index bdeda8b6e..62be9aa71 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -114,6 +114,9 @@ GEM json thread thread_safe + email_spec (1.6.0) + launchy (~> 2.1) + mail (~> 2.2) erubis (2.7.0) execjs (2.5.2) factory_girl (4.5.0) @@ -305,6 +308,7 @@ DEPENDENCIES coveralls database_cleaner devise + email_spec factory_girl_rails foundation-rails i18n-tasks diff --git a/app/controllers/account_controller.rb b/app/controllers/account_controller.rb index 494068476..e9b5b6c99 100644 --- a/app/controllers/account_controller.rb +++ b/app/controllers/account_controller.rb @@ -17,7 +17,7 @@ class AccountController < ApplicationController end def account_params - params.require(:account).permit(:first_name, :last_name, :nickname, :use_nickname) + params.require(:account).permit(:first_name, :last_name, :nickname, :use_nickname, :email_on_debate_comment, :email_on_comment_reply) end end diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb index 409bb7c9b..bbad3ca3b 100644 --- a/app/controllers/comments_controller.rb +++ b/app/controllers/comments_controller.rb @@ -7,6 +7,10 @@ class CommentsController < ApplicationController @comment = Comment.build(@debate, current_user, params[:comment][:body]) @comment.save! @comment.move_to_child_of(@parent) if reply? + + Mailer.comment(@comment).deliver_now if email_on_debate_comment? + Mailer.reply(@comment).deliver_now if email_on_comment_reply? + respond_with @comment end @@ -32,4 +36,12 @@ class CommentsController < ApplicationController def reply? @parent.class == Comment end + + def email_on_debate_comment? + @comment.debate.author.email_on_debate_comment? + end + + def email_on_comment_reply? + reply? && @parent.author.email_on_comment_reply? + end end \ No newline at end of file diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb new file mode 100644 index 000000000..e5d793e1e --- /dev/null +++ b/app/mailers/application_mailer.rb @@ -0,0 +1,4 @@ +class ApplicationMailer < ActionMailer::Base + default from: "participacion@madrid.es" + layout 'mailer' +end diff --git a/app/mailers/mailer.rb b/app/mailers/mailer.rb new file mode 100644 index 000000000..fa53c7c1a --- /dev/null +++ b/app/mailers/mailer.rb @@ -0,0 +1,16 @@ +class Mailer < ApplicationMailer + + def comment(comment) + @comment = comment + @debate = comment.debate + mail(to: @debate.author.email, subject: t('mailer.comment.subject')) + end + + def reply(reply) + @reply = reply + @debate = @reply.debate + parent = Comment.find(@reply.parent_id) + mail(to: parent.author.email, subject: t('mailer.reply.subject')) + end + +end diff --git a/app/models/comment.rb b/app/models/comment.rb index e99ef15e3..c2cf75292 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -17,4 +17,13 @@ class Comment < ActiveRecord::Base def self.find_parent(params) params[:commentable_type].constantize.find(params[:commentable_id]) end + + def debate + commentable if commentable.class == Debate + end + + def author + user + end + end diff --git a/app/views/account/show.html.erb b/app/views/account/show.html.erb index da568a9b9..d130121f3 100644 --- a/app/views/account/show.html.erb +++ b/app/views/account/show.html.erb @@ -15,6 +15,16 @@ <%= f.label :nickname, t("account.show.nickname_label") %> <%= f.text_field :nickname %> +
+ <%= f.check_box :email_on_debate_comment %> + <%= f.label :email_on_debate_comment, t("account.show.email_on_debate_comment_label") %> +
+ +
+ <%= f.check_box :email_on_comment_reply %> + <%= f.label :email_on_comment_reply, t("account.show.email_on_comment_reply_label") %> +
+ <%= f.submit t("account.show.save_changes_submit"), class: "button radius" %> <% end %> diff --git a/app/views/layouts/mailer.html.erb b/app/views/layouts/mailer.html.erb new file mode 100644 index 000000000..991cf0ffa --- /dev/null +++ b/app/views/layouts/mailer.html.erb @@ -0,0 +1,5 @@ + + + <%= yield %> + + diff --git a/app/views/mailer/comment.html.erb b/app/views/mailer/comment.html.erb new file mode 100644 index 000000000..f469d50b8 --- /dev/null +++ b/app/views/mailer/comment.html.erb @@ -0,0 +1,7 @@ +Hello, + +
<%= @comment.author.name %>
+ +
<%= @comment.body %>
+ +
<%= link_to @debate.title, debate_url(@debate) %>
\ No newline at end of file diff --git a/app/views/mailer/reply.html.erb b/app/views/mailer/reply.html.erb new file mode 100644 index 000000000..7714d7c28 --- /dev/null +++ b/app/views/mailer/reply.html.erb @@ -0,0 +1,7 @@ +Hello, + +
<%= @reply.author.name %>
+ +
<%= @reply.body %>
+ +
<%= link_to @debate.title, debate_url(@debate) %>
\ No newline at end of file diff --git a/config/locales/en.yml b/config/locales/en.yml index 7fdf7a214..5a7fa594e 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -62,6 +62,8 @@ en: show: title: "My account" save_changes_submit: "Save changes" + email_on_debate_comment_label: "Receive email when someone comments on my debates" + email_on_comment_reply_label: "Receive email when someone replies to my comments" change_credentials_link: "Change my credentials" first_name_label: "First Name" last_name_label: "Last Name" @@ -73,3 +75,8 @@ en: shared: tags_cloud: tags: Tags + mailer: + comment: + subject: Someone has commented on your debate + reply: + subject: Someone has replied to your comment diff --git a/config/locales/es.yml b/config/locales/es.yml index 9bbdde6b6..0576aecd7 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -62,6 +62,8 @@ es: show: title: "Mi cuenta" save_changes_submit: "Guardar cambios" + email_on_debate_comment_label: "Recibir un email cuando alguien commenta en mis debates" + email_on_comment_reply_label: "Recibir un email cuando alguien contesta a mis comentarios" change_credentials_link: "Cambiar mi contraseña" first_name_label: "Nombre" last_name_label: "Apellidos" @@ -73,4 +75,8 @@ es: shared: tags_cloud: tags: Etiquetas - + mailer: + comment: + subject: Alguien ha comentado en tu debate + reply: + subject: Alguien ha respondido a tu comentario diff --git a/db/migrate/20150806163142_add_preferences_to_users.rb b/db/migrate/20150806163142_add_preferences_to_users.rb new file mode 100644 index 000000000..8c3ae57cc --- /dev/null +++ b/db/migrate/20150806163142_add_preferences_to_users.rb @@ -0,0 +1,6 @@ +class AddPreferencesToUsers < ActiveRecord::Migration + def change + add_column :users, :email_on_debate_comment, :boolean, default: false + add_column :users, :email_on_comment_reply, :boolean, default: false + end +end diff --git a/db/schema.rb b/db/schema.rb index e5f6f9c0a..f6947e462 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20150806140048) do +ActiveRecord::Schema.define(version: 20150806163142) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -82,6 +82,8 @@ ActiveRecord::Schema.define(version: 20150806140048) do t.string "unconfirmed_email" t.string "nickname" t.boolean "use_nickname", default: false, null: false + t.boolean "email_on_debate_comment", default: false + t.boolean "email_on_comment_reply", default: false end add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree diff --git a/spec/features/account_spec.rb b/spec/features/account_spec.rb index 7179b6c6b..e622c83c1 100644 --- a/spec/features/account_spec.rb +++ b/spec/features/account_spec.rb @@ -21,6 +21,8 @@ feature 'Account' do fill_in 'account_first_name', with: 'Larry' fill_in 'account_last_name', with: 'Bird' + check 'account_email_on_debate_comment' + check 'account_email_on_comment_reply' click_button 'Save changes' expect(page).to have_content "Saved" @@ -29,5 +31,7 @@ feature 'Account' do expect(page).to have_selector("input[value='Larry']") expect(page).to have_selector("input[value='Bird']") + expect(page).to have_selector("input[id='account_email_on_debate_comment'][value='1']") + expect(page).to have_selector("input[id='account_email_on_comment_reply'][value='1']") end end \ No newline at end of file diff --git a/spec/features/comments_spec.rb b/spec/features/comments_spec.rb index 3d215ef00..1ec6a8c10 100644 --- a/spec/features/comments_spec.rb +++ b/spec/features/comments_spec.rb @@ -41,11 +41,11 @@ feature 'Comments' do login_as(user) visit debate_path(debate) - fill_in 'comment_body', with: '¿Has pensado en esto...?' + fill_in 'comment_body', with: 'Have you thought about...?' click_button 'Publish comment' within "#comments" do - expect(page).to have_content '¿Has pensado en esto...?' + expect(page).to have_content 'Have you thought about...?' end end @@ -60,12 +60,12 @@ feature 'Comments' do click_link "Reply" within "#js-comment-form-comment_#{comment.id}" do - fill_in 'comment_body', with: 'La semana que viene está hecho.' + fill_in 'comment_body', with: 'It will be done next week.' click_button 'Publish reply' end within "#comment-#{comment.id}" do - expect(page).to have_content 'La semana que viene está hecho.' + expect(page).to have_content 'It will be done next week.' end end diff --git a/spec/features/emails_spec.rb b/spec/features/emails_spec.rb new file mode 100644 index 000000000..86c794fac --- /dev/null +++ b/spec/features/emails_spec.rb @@ -0,0 +1,63 @@ +require 'rails_helper' + +feature 'Emails' do + + background do + reset_mailer + end + + scenario "Signup Email" do + sign_up + + email = open_last_email + expect(email).to have_subject('Confirmation instructions') + expect(email).to deliver_to('manuela@madrid.es') + expect(email).to have_body_text(user_confirmation_path) + end + + scenario "Reset password" do + reset_password + + email = open_last_email + expect(email).to have_subject('Reset password instructions') + expect(email).to deliver_to('manuela@madrid.es') + expect(email).to have_body_text(edit_user_password_path) + end + + scenario "Debate comment", :js do + user = create(:user, email_on_debate_comment: true) + debate = create(:debate, author: user) + comment_on(debate) + + email = open_last_email + expect(email).to have_subject('Someone has commented on your debate') + expect(email).to deliver_to(debate.author) + expect(email).to have_body_text(debate_path(debate)) + end + + scenario "Comment reply", :js do + user = create(:user, email_on_comment_reply: true) + reply_to(user) + + email = open_last_email + expect(email).to have_subject('Someone has replied to your comment') + expect(email).to deliver_to(user) + expect(email).to have_body_text(debate_path(Comment.first.debate)) + end + + scenario 'Do not send email about debate comment unless set in preferences', :js do + user = create(:user, email_on_debate_comment: false) + debate = create(:debate, author: user) + comment_on(debate) + + expect { open_last_email }.to raise_error "No email has been sent!" + end + + scenario "Do not send email about comment reply unless set in preferences", :js do + user = create(:user, email_on_comment_reply: false) + reply_to(user) + + expect { open_last_email }.to raise_error "No email has been sent!" + end + +end \ No newline at end of file diff --git a/spec/features/users_spec.rb b/spec/features/users_spec.rb index d2f01ec84..c15869bae 100644 --- a/spec/features/users_spec.rb +++ b/spec/features/users_spec.rb @@ -44,4 +44,26 @@ feature 'Users' do expect(page).to have_content 'Signed out successfully.' end + scenario 'Reset password' do + create(:user, email: 'manuela@madrid.es') + + visit '/' + click_link 'Log in' + click_link 'Forgot your password?' + + fill_in 'user_email', with: 'manuela@madrid.es' + click_button 'Send me reset password instructions' + + expect(page).to have_content "You will receive an email with instructions on how to reset your password in a few minutes." + + sent_token = /.*reset_password_token=(.*)".*/.match(ActionMailer::Base.deliveries.last.body.to_s)[1] + visit edit_user_password_path(reset_password_token: sent_token) + + fill_in 'user_password', with: 'new password' + fill_in 'user_password_confirmation', with: 'new password' + click_button 'Change my password' + + expect(page).to have_content "Your password has been changed successfully. You are now signed in." + end + end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 0a7665127..93cde956e 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -34,6 +34,20 @@ describe User do expect(subject).to be_valid end + describe 'preferences' do + describe 'email_on_debate_comment' do + it 'should be false by default' do + expect(subject.email_on_debate_comment).to eq(false) + end + end + + describe 'email_on_comment_reply' do + it 'should be false by default' do + expect(subject.email_on_comment_reply).to eq(false) + end + end + end + describe 'use_nickname' do describe 'when true' do before { subject.use_nickname = true } diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 156073f78..640f9e96c 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,5 +1,7 @@ require 'factory_girl_rails' require 'database_cleaner' +require "email_spec" +Dir["./spec/support/**/*.rb"].sort.each { |f| require f} RSpec.configure do |config| config.use_transactional_fixtures = false @@ -7,7 +9,9 @@ RSpec.configure do |config| config.filter_run :focus config.run_all_when_everything_filtered = true config.include FactoryGirl::Syntax::Methods - + config.include(EmailSpec::Helpers) + config.include(EmailSpec::Matchers) + config.include(CommonActions) config.before(:suite) do DatabaseCleaner.clean_with :truncation end diff --git a/spec/support/common_actions.rb b/spec/support/common_actions.rb new file mode 100644 index 000000000..d07f60261 --- /dev/null +++ b/spec/support/common_actions.rb @@ -0,0 +1,54 @@ +module CommonActions + + def sign_up + visit '/' + click_link 'Sign up' + + fill_in 'user_first_name', with: 'Manuela' + fill_in 'user_last_name', with: 'Carmena' + fill_in 'user_email', with: 'manuela@madrid.es' + fill_in 'user_password', with: 'judgementday' + fill_in 'user_password_confirmation', with: 'judgementday' + + click_button 'Sign up' + end + + def reset_password + create(:user, email: 'manuela@madrid.es') + + visit '/' + click_link 'Log in' + click_link 'Forgot your password?' + + fill_in 'user_email', with: 'manuela@madrid.es' + click_button 'Send me reset password instructions' + end + + def comment_on(debate) + user2 = create(:user) + + login_as(user2) + visit debate_path(debate) + + fill_in 'comment_body', with: 'Have you thought about...?' + click_button 'Publish comment' + expect(page).to have_content 'Have you thought about...?' + end + + def reply_to(user) + manuela = create(:user) + debate = create(:debate) + comment = create(:comment, commentable: debate, user: user) + + login_as(manuela) + visit debate_path(debate) + + click_link "Reply" + within "#js-comment-form-comment_#{comment.id}" do + fill_in 'comment_body', with: 'It will be done next week.' + click_button 'Publish reply' + end + expect(page).to have_content 'It will be done next week.' + end + +end \ No newline at end of file