diff --git a/Gemfile b/Gemfile index dd4fef9d..5605025c 100644 --- a/Gemfile +++ b/Gemfile @@ -90,6 +90,7 @@ group :development, :test do gem 'puma' gem 'rspec-rails', '~> 3.9' gem 'rspec-its', '~> 1.3' + gem "rspec-sidekiq", "~> 3.0" gem 'factory_bot_rails', require: false gem 'faker' gem 'capybara' diff --git a/Gemfile.lock b/Gemfile.lock index 3d759e07..77859523 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -406,6 +406,9 @@ GEM rspec-expectations (~> 3.9.0) rspec-mocks (~> 3.9.0) rspec-support (~> 3.9.0) + rspec-sidekiq (3.0.3) + rspec-core (~> 3.0, >= 3.0.0) + sidekiq (>= 2.4.0) rspec-support (3.9.2) ruby-progressbar (1.10.1) sanitize (5.1.0) @@ -563,6 +566,7 @@ DEPENDENCIES rolify (~> 5.2) rspec-its (~> 1.3) rspec-rails (~> 3.9) + rspec-sidekiq (~> 3.0) ruby-progressbar sanitize sass-rails (~> 5.0) diff --git a/app/controllers/ajax/answer_controller.rb b/app/controllers/ajax/answer_controller.rb index d35ff3e9..05a7ba7e 100644 --- a/app/controllers/ajax/answer_controller.rb +++ b/app/controllers/ajax/answer_controller.rb @@ -1,11 +1,4 @@ -class Ajax::AnswerController < ApplicationController - rescue_from(ActionController::ParameterMissing) do |titanic_param| - @status = :parameter_error - @message = I18n.t('messages.parameter_error', parameter: titanic_param.param.capitalize) - @success = false - render partial: "ajax/shared/status" - end - +class Ajax::AnswerController < AjaxController def create params.require :id params.require :answer @@ -18,27 +11,24 @@ class Ajax::AnswerController < ApplicationController inbox_entry = Inbox.find(params[:id]) unless current_user == inbox_entry.user - @status = :fail - @message = I18n.t('messages.answer.create.fail') - @success = false + @response[:status] = :fail + @response[:message] = I18n.t('messages.answer.create.fail') return end else question = Question.find(params[:id]) unless question.user.privacy_allow_stranger_answers - @status = :privacy_stronk - @message = I18n.t('messages.answer.create.privacy_stronk') - @success = false + @response[:status] = :privacy_stronk + @response[:message] = I18n.t('messages.answer.create.privacy_stronk') return end end # this should never trigger because empty params throw ParameterMissing unless params[:answer].length > 0 - @status = :peter_dinklage - @message = I18n.t('messages.answer.create.peter_dinklage') - @success = false + @response[:status] = :peter_dinklage + @response[:message] = I18n.t('messages.answer.create.peter_dinklage') return end @@ -50,10 +40,10 @@ class Ajax::AnswerController < ApplicationController else current_user.answer question, params[:answer] end - rescue - @status = :err - @message = I18n.t('messages.error') - @success = false + rescue => e + NewRelic::Agent.notice_error(e) + @response[:status] = :err + @response[:message] = I18n.t('messages.error') return end @@ -61,12 +51,13 @@ class Ajax::AnswerController < ApplicationController ShareWorker.perform_async(current_user.id, answer.id, services) - @status = :okay - @message = I18n.t('messages.answer.create.okay') - @success = true + @response[:status] = :okay + @response[:message] = I18n.t('messages.answer.create.okay') + @response[:success] = true unless inbox + # this assign is needed because shared/_answerbox relies on it, I think @question = 1 - @render = render_to_string(partial: 'shared/answerbox', locals: { a: answer, show_question: false }) + @response[:render] = render_to_string(partial: 'shared/answerbox', locals: { a: answer, show_question: false }) end end @@ -76,9 +67,8 @@ class Ajax::AnswerController < ApplicationController answer = Answer.find(params[:answer]) unless (current_user == answer.user) or (privileged? answer.user) - @status = :nopriv - @message = I18n.t('messages.answer.destroy.nopriv') - @success = false + @response[:status] = :nopriv + @response[:message] = I18n.t('messages.answer.destroy.nopriv') return end @@ -87,8 +77,8 @@ class Ajax::AnswerController < ApplicationController end # TODO: decide what happens with the question answer.destroy - @status = :okay - @message = I18n.t('messages.answer.destroy.okay') - @success = true + @response[:status] = :okay + @response[:message] = I18n.t('messages.answer.destroy.okay') + @response[:success] = true end end diff --git a/app/controllers/ajax/comment_controller.rb b/app/controllers/ajax/comment_controller.rb index c854ff9d..283da8d7 100644 --- a/app/controllers/ajax/comment_controller.rb +++ b/app/controllers/ajax/comment_controller.rb @@ -1,11 +1,4 @@ -class Ajax::CommentController < ApplicationController - rescue_from(ActionController::ParameterMissing) do |param_miss_ex| - @status = :parameter_error - @message = I18n.t('messages.parameter_error', parameter: param_miss_ex.param.capitalize) - @success = false - render partial: "ajax/shared/status" - end - +class Ajax::CommentController < AjaxController def create params.require :answer params.require :comment @@ -14,39 +7,37 @@ class Ajax::CommentController < ApplicationController begin current_user.comment(answer, params[:comment]) - rescue ActiveRecord::RecordInvalid - @status = :rec_inv - @message = I18n.t('messages.comment.create.rec_inv') - @success = false + rescue ActiveRecord::RecordInvalid => e + NewRelic::Agent.notice_error(e) + @response[:status] = :rec_inv + @response[:message] = I18n.t('messages.comment.create.rec_inv') return end - @status = :okay - @message = I18n.t('messages.comment.create.okay') - @success = true - @render = render_to_string(partial: 'shared/comments', locals: { a: answer }) - @count = answer.comment_count + @response[:status] = :okay + @response[:message] = I18n.t('messages.comment.create.okay') + @response[:success] = true + @response[:render] = render_to_string(partial: 'shared/comments', locals: { a: answer }) + @response[:count] = answer.comment_count end def destroy params.require :comment - @status = :err - @success = false + @response[:status] = :err comment = Comment.find(params[:comment]) unless (current_user == comment.user) or (current_user == comment.answer.user) or (privileged? comment.user) - @status = :nopriv - @message = I18n.t('messages.comment.destroy.nopriv') - @success = false + @response[:status] = :nopriv + @response[:message] = I18n.t('messages.comment.destroy.nopriv') return end - @count = comment.answer.comment_count - 1 + @response[:count] = comment.answer.comment_count - 1 comment.destroy - @status = :okay - @message = I18n.t('messages.comment.destroy.okay') - @success = true + @response[:status] = :okay + @response[:message] = I18n.t('messages.comment.destroy.okay') + @response[:success] = true end end diff --git a/app/controllers/ajax/friend_controller.rb b/app/controllers/ajax/friend_controller.rb index 965a7876..829ec769 100644 --- a/app/controllers/ajax/friend_controller.rb +++ b/app/controllers/ajax/friend_controller.rb @@ -1,11 +1,4 @@ -class Ajax::FriendController < ApplicationController - rescue_from(ActionController::ParameterMissing) do |param_miss_ex| - @status = :parameter_error - @message = I18n.t('messages.parameter_error', parameter: param_miss_ex.param.capitalize) - @success = false - render partial: "ajax/shared/status" - end - +class Ajax::FriendController < AjaxController def create params.require :screen_name @@ -13,16 +6,16 @@ class Ajax::FriendController < ApplicationController begin current_user.follow target_user - rescue - @status = :fail - @message = I18n.t('messages.friend.create.fail') - @success = false + rescue => e + NewRelic::Agent.notice_error(e) + @response[:status] = :fail + @response[:message] = I18n.t('messages.friend.create.fail') return end - @status = :okay - @message = I18n.t('messages.friend.create.okay') - @success = true + @response[:status] = :okay + @response[:message] = I18n.t('messages.friend.create.okay') + @response[:success] = true end def destroy @@ -32,15 +25,15 @@ class Ajax::FriendController < ApplicationController begin current_user.unfollow target_user - rescue - @status = :fail - @message = I18n.t('messages.friend.destroy.fail') - @success = false + rescue => e + NewRelic::Agent.notice_error(e) + @response[:status] = :fail + @response[:message] = I18n.t('messages.friend.destroy.fail') return end - @status = :okay - @message = I18n.t('messages.friend.destroy.okay') - @success = true + @response[:status] = :okay + @response[:message] = I18n.t('messages.friend.destroy.okay') + @response[:success] = true end end diff --git a/app/controllers/ajax/group_controller.rb b/app/controllers/ajax/group_controller.rb index b3102489..cb29f6f2 100644 --- a/app/controllers/ajax/group_controller.rb +++ b/app/controllers/ajax/group_controller.rb @@ -1,26 +1,19 @@ -class Ajax::GroupController < ApplicationController - rescue_from(ActionController::ParameterMissing) do |param_miss_ex| - @status = :parameter_error - @message = I18n.t('messages.parameter_error', parameter: param_miss_ex.param.capitalize) - @success = false - render partial: "ajax/shared/status" - end - +class Ajax::GroupController < AjaxController def create - @status = :err - @success = false + @response[:status] = :err unless user_signed_in? - @status = :noauth - @message = I18n.t('messages.noauth') + @response[:status] = :noauth + @response[:message] = I18n.t('messages.noauth') return end begin params.require :name - rescue ActionController::ParameterMissing - @status = :toolong - @message = I18n.t('messages.group.create.noname') + rescue ActionController::ParameterMissing => e + NewRelic::Agent.notice_error(e) + @response[:status] = :toolong + @response[:message] = I18n.t('messages.group.create.noname') return end params.require :user @@ -28,33 +21,35 @@ class Ajax::GroupController < ApplicationController begin target_user = User.find_by_screen_name(params[:user]) group = Group.create! user: current_user, display_name: params[:name] - rescue ActiveRecord::RecordInvalid - @status = :toolong - @message = I18n.t('messages.group.create.toolong') + rescue ActiveRecord::RecordInvalid => e + NewRelic::Agent.notice_error(e) + @response[:status] = :toolong + @response[:message] = I18n.t('messages.group.create.toolong') return - rescue ActiveRecord::RecordNotFound - @status = :notfound - @message = I18n.t('messages.group.create.notfound') + rescue ActiveRecord::RecordNotFound => e + NewRelic::Agent.notice_error(e) + @response[:status] = :notfound + @response[:message] = I18n.t('messages.group.create.notfound') return - rescue ActiveRecord::RecordNotUnique - @status = :exists - @message = I18n.t('messages.group.create.exists') + rescue ActiveRecord::RecordNotUnique => e + NewRelic::Agent.notice_error(e) + @response[:status] = :exists + @response[:message] = I18n.t('messages.group.create.exists') return end - @status = :okay - @success = true - @message = I18n.t('messages.group.create.okay') - @render = render_to_string(partial: 'modal/group/item', locals: { group: group, user: target_user }) + @response[:status] = :okay + @response[:success] = true + @response[:message] = I18n.t('messages.group.create.okay') + @response[:render] = render_to_string(partial: 'modal/group/item', locals: { group: group, user: target_user }) end def destroy - @status = :err - @success = false + @response[:status] = :err unless user_signed_in? - @status = :noauth - @message = I18n.t('messages.noauth') + @response[:status] = :noauth + @response[:message] = I18n.t('messages.noauth') return end @@ -62,24 +57,24 @@ class Ajax::GroupController < ApplicationController begin Group.where(user: current_user, name: params[:group]).first.destroy! - rescue ActiveRecord::RecordNotFound - @status = :notfound - @message = I18n.t('messages.group.destroy.notfound') + rescue ActiveRecord::RecordNotFound => e + NewRelic::Agent.notice_error(e) + @response[:status] = :notfound + @response[:message] = I18n.t('messages.group.destroy.notfound') return end - @status = :okay - @success = true - @message = I18n.t('messages.group.destroy.okay') + @response[:status] = :okay + @response[:success] = true + @response[:message] = I18n.t('messages.group.destroy.okay') end def membership - @status = :err - @success = false + @response[:status] = :err unless user_signed_in? - @status = :noauth - @message = I18n.t('messages.noauth') + @response[:status] = :noauth + @response[:message] = I18n.t('messages.noauth') return end @@ -91,9 +86,10 @@ class Ajax::GroupController < ApplicationController begin group = current_user.groups.find_by_name(params[:group]) - rescue ActiveRecord::RecordNotFound - @status = :notfound - @message = I18n.t('messages.group.membership.notfound') + rescue ActiveRecord::RecordNotFound => e + NewRelic::Agent.notice_error(e) + @response[:status] = :notfound + @response[:message] = I18n.t('messages.group.membership.notfound') return end @@ -101,15 +97,15 @@ class Ajax::GroupController < ApplicationController if add group.add_member target_user if group.members.find_by_user_id(target_user.id).nil? - @checked = true - @message = I18n.t('messages.group.membership.add') + @response[:checked] = true + @response[:message] = I18n.t('messages.group.membership.add') else group.remove_member target_user unless group.members.find_by_user_id(target_user.id).nil? - @checked = false - @message = I18n.t('messages.group.membership.remove') + @response[:checked] = false + @response[:message] = I18n.t('messages.group.membership.remove') end - @status = :okay - @success = true + @response[:status] = :okay + @response[:success] = true end end diff --git a/app/controllers/ajax/inbox_controller.rb b/app/controllers/ajax/inbox_controller.rb index 7f0fef26..0aa99cdc 100644 --- a/app/controllers/ajax/inbox_controller.rb +++ b/app/controllers/ajax/inbox_controller.rb @@ -1,16 +1,8 @@ -class Ajax::InboxController < ApplicationController - rescue_from(ActionController::ParameterMissing) do |param_miss_ex| - @status = :parameter_error - @message = I18n.t('messages.parameter_error', parameter: param_miss_ex.param.capitalize) - @success = false - render partial: "ajax/shared/status" - end - +class Ajax::InboxController < AjaxController def create unless user_signed_in? - @status = :noauth - @message = I18n.t('messages.noauth') - @success = false + @response[:status] = :noauth + @response[:message] = I18n.t('messages.noauth') return end @@ -21,10 +13,10 @@ class Ajax::InboxController < ApplicationController inbox = Inbox.create!(user: current_user, question_id: question.id, new: true) - @status = :okay - @message = I18n.t('messages.inbox.create.okay') - @success = true - @render = render_to_string(partial: 'inbox/entry', locals: { i: inbox }) + @response[:status] = :okay + @response[:message] = I18n.t('messages.inbox.create.okay') + @response[:success] = true + @response[:render] = render_to_string(partial: 'inbox/entry', locals: { i: inbox }) inbox.update(new: false) end @@ -34,40 +26,38 @@ class Ajax::InboxController < ApplicationController inbox = Inbox.find(params[:id]) unless current_user == inbox.user - @status = :fail - @message = I18n.t('messages.inbox.remove.fail') - @success = false + @response[:status] = :fail + @response[:message] = I18n.t('messages.inbox.remove.fail') return end begin inbox.remove - rescue - @status = :err - @message = I18n.t('messages.error') - @success = false + rescue => e + NewRelic::Agent.notice_error(e) + @response[:status] = :err + @response[:message] = I18n.t('messages.error') return end - @status = :okay - @message = I18n.t('messages.inbox.remove.okay') - @success = true + @response[:status] = :okay + @response[:message] = I18n.t('messages.inbox.remove.okay') + @response[:success] = true end def remove_all begin Inbox.where(user: current_user).each { |i| i.remove } - rescue - @status = :err - @message = I18n.t('messages.error') - @success = false + rescue => e + NewRelic::Agent.notice_error(e) + @response[:status] = :err + @response[:message] = I18n.t('messages.error') return end - @status = :okay - @message = I18n.t('messages.inbox.remove_all.okay') - @success = true - render 'ajax/inbox/remove' + @response[:status] = :okay + @response[:message] = I18n.t('messages.inbox.remove_all.okay') + @response[:success] = true end def remove_all_author @@ -76,16 +66,15 @@ class Ajax::InboxController < ApplicationController @inbox = current_user.inboxes.joins(:question) .where(questions: { user_id: @target_user.id, author_is_anonymous: false }) @inbox.each { |i| i.remove } - rescue - @status = :err - @message = I18n.t('messages.error') - @success = false + rescue => e + NewRelic::Agent.notice_error(e) + @response[:status] = :err + @response[:message] = I18n.t('messages.error') return end - @status = :okay - @message = I18n.t('messages.inbox.remove_all.okay') - @success = true - render 'ajax/inbox/remove' + @response[:status] = :okay + @response[:message] = I18n.t('messages.inbox.remove_all.okay') + @response[:success] = true end end diff --git a/app/controllers/ajax/moderation_controller.rb b/app/controllers/ajax/moderation_controller.rb index dda91f54..850c3564 100644 --- a/app/controllers/ajax/moderation_controller.rb +++ b/app/controllers/ajax/moderation_controller.rb @@ -1,11 +1,4 @@ -class Ajax::ModerationController < ApplicationController - rescue_from(ActionController::ParameterMissing) do |param_miss_ex| - @status = :parameter_error - @message = I18n.t('messages.parameter_error', parameter: param_miss_ex.param.capitalize) - @success = false - render partial: "ajax/shared/status" - end - +class Ajax::ModerationController < AjaxController def vote params.require :id params.require :upvote @@ -14,17 +7,17 @@ class Ajax::ModerationController < ApplicationController begin current_user.report_vote(report, params[:upvote]) - rescue - @status = :fail - @message = I18n.t('messages.moderation.vote.fail') - @success = false + rescue => e + NewRelic::Agent.notice_error(e) + @response[:status] = :fail + @response[:message] = I18n.t('messages.moderation.vote.fail') return end - @count = report.votes - @status = :okay - @message = I18n.t('messages.moderation.vote.okay') - @success = true + @response[:count] = report.votes + @response[:status] = :okay + @response[:message] = I18n.t('messages.moderation.vote.okay') + @response[:success] = true end def destroy_vote @@ -34,17 +27,17 @@ class Ajax::ModerationController < ApplicationController begin current_user.report_unvote report - rescue - @status = :fail - @message = I18n.t('messages.moderation.destroy_vote.fail') - @success = false + rescue => e + NewRelic::Agent.notice_error(e) + @response[:status] = :fail + @response[:message] = I18n.t('messages.moderation.destroy_vote.fail') return end - @count = report.votes - @status = :okay - @message = I18n.t('messages.moderation.destroy_vote.okay') - @success = true + @response[:count] = report.votes + @response[:status] = :okay + @response[:message] = I18n.t('messages.moderation.destroy_vote.okay') + @response[:success] = true end def destroy_report @@ -55,16 +48,16 @@ class Ajax::ModerationController < ApplicationController begin report.deleted = true report.save - rescue - @status = :fail - @message = I18n.t('messages.moderation.destroy_report.fail') - @success = false + rescue => e + NewRelic::Agent.notice_error(e) + @response[:status] = :fail + @response[:message] = I18n.t('messages.moderation.destroy_report.fail') return end - @status = :okay - @message = I18n.t('messages.moderation.destroy_report.okay') - @success = true + @response[:status] = :okay + @response[:message] = I18n.t('messages.moderation.destroy_report.okay') + @response[:success] = true end def create_comment @@ -73,48 +66,45 @@ class Ajax::ModerationController < ApplicationController report = Report.find(params[:id]) - @success = false begin current_user.report_comment(report, params[:comment]) - rescue ActiveRecord::RecordInvalid - @status = :rec_inv - @message = I18n.t('messages.moderation.create_comment.rec_inv') + rescue ActiveRecord::RecordInvalid => e + NewRelic::Agent.notice_error(e) + @response[:status] = :rec_inv + @response[:message] = I18n.t('messages.moderation.create_comment.rec_inv') return end - @status = :okay - @message = I18n.t('messages.moderation.create_comment.okay') - @success = true - @render = render_to_string(partial: 'moderation/discussion', locals: { report: report }) - @count = report.moderation_comments.all.count + @response[:status] = :okay + @response[:message] = I18n.t('messages.moderation.create_comment.okay') + @response[:success] = true + @response[:render] = render_to_string(partial: 'moderation/discussion', locals: { report: report }) + @response[:count] = report.moderation_comments.all.count end def destroy_comment params.require :comment - @status = :err - @success = false + @response[:status] = :err comment = ModerationComment.find(params[:comment]) unless current_user == comment.user - @status = :nopriv - @message = I18n.t('messages.moderation.destroy_comment.nopriv') - @success = false + @response[:status] = :nopriv + @response[:message] = I18n.t('messages.moderation.destroy_comment.nopriv') return end comment.destroy - @status = :okay - @message = I18n.t('messages.moderation.destroy_comment.okay') - @success = true + @response[:status] = :okay + @response[:message] = I18n.t('messages.moderation.destroy_comment.okay') + @response[:success] = true end def ban - @status = :err - @message = I18n.t('messages.moderation.ban.error') - @success = false + @response[:status] = :err + @response[:message] = I18n.t('messages.moderation.ban.error') params.require :user params.require :ban @@ -128,32 +118,30 @@ class Ajax::ModerationController < ApplicationController buntil = DateTime.strptime params[:until], "%m/%d/%Y %I:%M %p" unless unban || perma if !unban && target.has_role?(:administrator) - @status = :nopriv - @message = I18n.t('messages.moderation.ban.nopriv') - @success = false + @response[:status] = :nopriv + @response[:message] = I18n.t('messages.moderation.ban.nopriv') return end if unban target.unban - @message = I18n.t('messages.moderation.ban.unban') - @success = true + @response[:message] = I18n.t('messages.moderation.ban.unban') + @response[:success] = true elsif perma target.ban nil, reason - @message = I18n.t('messages.moderation.ban.perma') + @response[:message] = I18n.t('messages.moderation.ban.perma') else target.ban buntil, reason - @message = I18n.t('messages.moderation.ban.temp', date: buntil.to_s) + @response[:message] = I18n.t('messages.moderation.ban.temp', date: buntil.to_s) end target.save! - @status = :okay - @success = target.banned? == !unban + @response[:status] = :okay + @response[:success] = target.banned? == !unban end def privilege - @status = :err - @success = false + @response[:status] = :err params.require :user params.require :type @@ -163,17 +151,16 @@ class Ajax::ModerationController < ApplicationController target_user = User.find_by_screen_name(params[:user]) - @message = I18n.t('messages.moderation.privilege.nope') + @response[:message] = I18n.t('messages.moderation.privilege.nope') return unless %w(moderator admin).include? params[:type].downcase unless current_user.has_role?(:administrator) - @status = :nopriv - @message = I18n.t('messages.moderation.privilege.nopriv') - @success = false + @response[:status] = :nopriv + @response[:message] = I18n.t('messages.moderation.privilege.nopriv') return end - @checked = status + @response[:checked] = status type = params[:type].downcase target_role = {"admin" => "administrator"}.fetch(type, type).to_sym @@ -184,9 +171,9 @@ class Ajax::ModerationController < ApplicationController end target_user.save! - @message = I18n.t('messages.moderation.privilege.checked', privilege: params[:type]) + @response[:message] = I18n.t('messages.moderation.privilege.checked', privilege: params[:type]) - @status = :okay - @success = true + @response[:status] = :okay + @response[:success] = true end end diff --git a/app/controllers/ajax/question_controller.rb b/app/controllers/ajax/question_controller.rb index 17f61a53..acdc3109 100644 --- a/app/controllers/ajax/question_controller.rb +++ b/app/controllers/ajax/question_controller.rb @@ -1,36 +1,25 @@ -class Ajax::QuestionController < ApplicationController - include MarkdownHelper - - rescue_from(ActionController::ParameterMissing) do |param_miss_ex| - @status = :parameter_error - @message = I18n.t('messages.parameter_error', parameter: param_miss_ex.param.capitalize) - @success = false - render partial: "ajax/shared/status" - end - +class Ajax::QuestionController < AjaxController def destroy params.require :question question = Question.find params[:question] if question.nil? - @status = :not_found - @message = I18n.t('messages.question.destroy.not_found') - @success = false + @response[:status] = :not_found + @response[:message] = I18n.t('messages.question.destroy.not_found') return end if not (current_user.mod? or question.user == current_user) - @status = :not_authorized - @message = I18n.t('messages.question.destroy.not_authorized') - @success = false + @response[:status] = :not_authorized + @response[:message] = I18n.t('messages.question.destroy.not_authorized') return end question.destroy! - @status = :okay - @message = I18n.t('messages.question.destroy.okay') - @success = true + @response[:status] = :okay + @response[:message] = I18n.t('messages.question.destroy.okay') + @response[:success] = true end def create @@ -42,10 +31,10 @@ class Ajax::QuestionController < ApplicationController question = Question.create!(content: params[:question], author_is_anonymous: params[:anonymousQuestion], user: current_user) - rescue ActiveRecord::RecordInvalid - @status = :rec_inv - @message = I18n.t('messages.question.create.rec_inv') - @success = false + rescue ActiveRecord::RecordInvalid => e + NewRelic::Agent.notice_error(e) + @response[:status] = :rec_inv + @response[:message] = I18n.t('messages.question.create.rec_inv') return end @@ -62,42 +51,25 @@ class Ajax::QuestionController < ApplicationController begin current_user.groups.find_by_name!(params[:rcpt].sub 'grp:', '') QuestionWorker.perform_async params[:rcpt], current_user.id, question.id - rescue ActiveRecord::RecordNotFound - @status = :not_found - @message = I18n.t('messages.question.create.not_found') - @success = false + rescue ActiveRecord::RecordNotFound => e + NewRelic::Agent.notice_error(e) + @response[:status] = :not_found + @response[:message] = I18n.t('messages.question.create.not_found') return end end else if User.find(params[:rcpt]).nil? - @status = :not_found - @message = I18n.t('messages.question.create.not_found') - @success = false + @response[:status] = :not_found + @response[:message] = I18n.t('messages.question.create.not_found') return end Inbox.create!(user_id: params[:rcpt], question_id: question.id, new: true) end - @status = :okay - @message = I18n.t('messages.question.create.okay') - @success = true - end - - def preview - params.require :md - - @message = I18n.t('messages.question.preview.fail') - begin - @markdown = markdown params[:md] - @message = I18n.t('messages.question.preview.okay') - rescue - @status = :fail - @success = false - return - end - @status = :okay - @success = true + @response[:status] = :okay + @response[:message] = I18n.t('messages.question.create.okay') + @response[:success] = true end end diff --git a/app/controllers/ajax/report_controller.rb b/app/controllers/ajax/report_controller.rb index 05cca16c..c49ec9b4 100644 --- a/app/controllers/ajax/report_controller.rb +++ b/app/controllers/ajax/report_controller.rb @@ -1,25 +1,17 @@ -class Ajax::ReportController < ApplicationController - rescue_from(ActionController::ParameterMissing) do |param_miss_ex| - @status = :parameter_error - @message = I18n.t('messages.parameter_error', parameter: param_miss_ex.param.capitalize) - @success = false - render partial: "ajax/shared/status" - end - +class Ajax::ReportController < AjaxController def create params.require :id params.require :type - @status = :err - @success = false + @response[:status] = :err if current_user.nil? - @message = I18n.t('messages.report.create.login') + @response[:message] = I18n.t('messages.report.create.login') return end unless %w(answer comment question user).include? params[:type] - @message = I18n.t('messages.report.create.unknown') + @response[:message] = I18n.t('messages.report.create.unknown') return end @@ -39,14 +31,14 @@ class Ajax::ReportController < ApplicationController end if object.nil? - @message = I18n.t('messages.report.create.not_found', parameter: params[:type]) + @response[:message] = I18n.t('messages.report.create.not_found', parameter: params[:type]) return end current_user.report object, params[:reason] - @status = :okay - @message = I18n.t('messages.report.create.okay', parameter: params[:type]) - @success = true + @response[:status] = :okay + @response[:message] = I18n.t('messages.report.create.okay', parameter: params[:type]) + @response[:success] = true end end diff --git a/app/controllers/ajax/smile_controller.rb b/app/controllers/ajax/smile_controller.rb index 93aab9f4..0e7ae9e2 100644 --- a/app/controllers/ajax/smile_controller.rb +++ b/app/controllers/ajax/smile_controller.rb @@ -1,11 +1,4 @@ -class Ajax::SmileController < ApplicationController - rescue_from(ActionController::ParameterMissing) do |param_miss_ex| - @status = :parameter_error - @message = I18n.t('messages.parameter_error', parameter: param_miss_ex.param.capitalize) - @success = false - render partial: "ajax/shared/status" - end - +class Ajax::SmileController < AjaxController def create params.require :id @@ -13,16 +6,16 @@ class Ajax::SmileController < ApplicationController begin current_user.smile answer - rescue - @status = :fail - @message = I18n.t('messages.smile.create.fail') - @success = false + rescue => e + NewRelic::Agent.notice_error(e) + @response[:status] = :fail + @response[:message] = I18n.t('messages.smile.create.fail') return end - @status = :okay - @message = I18n.t('messages.smile.create.okay') - @success = true + @response[:status] = :okay + @response[:message] = I18n.t('messages.smile.create.okay') + @response[:success] = true end def destroy @@ -32,16 +25,16 @@ class Ajax::SmileController < ApplicationController begin current_user.unsmile answer - rescue - @status = :fail - @message = I18n.t('messages.smile.destroy.fail') - @success = false + rescue => e + NewRelic::Agent.notice_error(e) + @response[:status] = :fail + @response[:message] = I18n.t('messages.smile.destroy.fail') return end - @status = :okay - @message = I18n.t('messages.smile.destroy.okay') - @success = true + @response[:status] = :okay + @response[:message] = I18n.t('messages.smile.destroy.okay') + @response[:success] = true end def create_comment @@ -51,16 +44,16 @@ class Ajax::SmileController < ApplicationController begin current_user.smile_comment comment - rescue - @status = :fail - @message = I18n.t('messages.smile.create_comment.fail') - @success = false + rescue => e + NewRelic::Agent.notice_error(e) + @response[:status] = :fail + @response[:message] = I18n.t('messages.smile.create_comment.fail') return end - @status = :okay - @message = I18n.t('messages.smile.create_comment.okay') - @success = true + @response[:status] = :okay + @response[:message] = I18n.t('messages.smile.create_comment.okay') + @response[:success] = true end def destroy_comment @@ -70,15 +63,15 @@ class Ajax::SmileController < ApplicationController begin current_user.unsmile_comment comment - rescue - @status = :fail - @message = I18n.t('messages.smile.destroy_comment.fail') - @success = false + rescue => e + NewRelic::Agent.notice_error(e) + @response[:status] = :fail + @response[:message] = I18n.t('messages.smile.destroy_comment.fail') return end - @status = :okay - @message = I18n.t('messages.smile.destroy_comment.okay') - @success = true + @response[:status] = :okay + @response[:message] = I18n.t('messages.smile.destroy_comment.okay') + @response[:success] = true end end diff --git a/app/controllers/ajax/subscription_controller.rb b/app/controllers/ajax/subscription_controller.rb index 746bcf48..8d660713 100644 --- a/app/controllers/ajax/subscription_controller.rb +++ b/app/controllers/ajax/subscription_controller.rb @@ -1,25 +1,19 @@ -class Ajax::SubscriptionController < ApplicationController +class Ajax::SubscriptionController < AjaxController before_action :authenticate_user! - rescue_from(ActionController::ParameterMissing) do |param_miss_ex| - @status = :parameter_error - @message = I18n.t('messages.parameter_error', parameter: param_miss_ex.param.capitalize) - @success = false - render partial: "ajax/shared/status" - end def subscribe params.require :answer - @status = 418 - @message = I18n.t('messages.subscription.torpedo') + @response[:status] = 418 + @response[:message] = I18n.t('messages.subscription.torpedo') state = Subscription.subscribe(current_user, Answer.find(params[:answer])).nil? - @success = state == false + @response[:success] = state == false end def unsubscribe params.require :answer - @status = 418 - @message = I18n.t('messages.subscription.torpedo') + @response[:status] = 418 + @response[:message] = I18n.t('messages.subscription.torpedo') state = Subscription.unsubscribe(current_user, Answer.find(params[:answer])).nil? - @success = state == false + @response[:success] = state == false end end diff --git a/app/controllers/ajax_controller.rb b/app/controllers/ajax_controller.rb new file mode 100644 index 00000000..8331130d --- /dev/null +++ b/app/controllers/ajax_controller.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +class AjaxController < ApplicationController + before_action :build_response + after_action :return_response + + respond_to :json + + rescue_from(ActiveRecord::RecordNotFound) do |e| + NewRelic::Agent.notice_error(e) + + @response = { + success: false, + message: "Record not found", + status: :not_found + } + + return_response + end + + rescue_from(ActionController::ParameterMissing) do |e| + NewRelic::Agent.notice_error(e) + + @response = { + success: false, + message: I18n.t('messages.parameter_error', parameter: e.param.capitalize), + status: :parameter_error + } + + return_response + end + + def find_active_announcements + # We do not need announcements here + end + + private + + def build_response + @response = { + success: false, + message: '', + status: 'unknown' + } + end + + def return_response + # Q: Why don't we just use render(json:) here? + # A: Because otherwise Rails wants us to use views, which do not make much sense here. + # + # Q: Why do we always return 200? + # A: Because JQuery might not do things we want it to if we don't. + response.status = 200 + response.headers["Content-Type"] = "application/json" + response.body = @response.to_json + end +end diff --git a/app/views/ajax/answer/create.json.jbuilder b/app/views/ajax/answer/create.json.jbuilder deleted file mode 100644 index e63a494b..00000000 --- a/app/views/ajax/answer/create.json.jbuilder +++ /dev/null @@ -1,2 +0,0 @@ -json.partial! 'ajax/shared/status' -json.render @render if @render \ No newline at end of file diff --git a/app/views/ajax/answer/destroy.json.jbuilder b/app/views/ajax/answer/destroy.json.jbuilder deleted file mode 100644 index 2c193af4..00000000 --- a/app/views/ajax/answer/destroy.json.jbuilder +++ /dev/null @@ -1 +0,0 @@ -json.partial! 'ajax/shared/status' \ No newline at end of file diff --git a/app/views/ajax/comment/create.json.jbuilder b/app/views/ajax/comment/create.json.jbuilder deleted file mode 100644 index 46fa7695..00000000 --- a/app/views/ajax/comment/create.json.jbuilder +++ /dev/null @@ -1,3 +0,0 @@ -json.partial! 'ajax/shared/status' -json.render @render if @render -json.count @count if @count \ No newline at end of file diff --git a/app/views/ajax/comment/destroy.json.jbuilder b/app/views/ajax/comment/destroy.json.jbuilder deleted file mode 100644 index 46291e5d..00000000 --- a/app/views/ajax/comment/destroy.json.jbuilder +++ /dev/null @@ -1,2 +0,0 @@ -json.partial! 'ajax/shared/status' -json.count @count if @count \ No newline at end of file diff --git a/app/views/ajax/friend/create.json.jbuilder b/app/views/ajax/friend/create.json.jbuilder deleted file mode 100644 index 2c193af4..00000000 --- a/app/views/ajax/friend/create.json.jbuilder +++ /dev/null @@ -1 +0,0 @@ -json.partial! 'ajax/shared/status' \ No newline at end of file diff --git a/app/views/ajax/friend/destroy.json.jbuilder b/app/views/ajax/friend/destroy.json.jbuilder deleted file mode 100644 index 2c193af4..00000000 --- a/app/views/ajax/friend/destroy.json.jbuilder +++ /dev/null @@ -1 +0,0 @@ -json.partial! 'ajax/shared/status' \ No newline at end of file diff --git a/app/views/ajax/group/create.json.jbuilder b/app/views/ajax/group/create.json.jbuilder deleted file mode 100644 index e63a494b..00000000 --- a/app/views/ajax/group/create.json.jbuilder +++ /dev/null @@ -1,2 +0,0 @@ -json.partial! 'ajax/shared/status' -json.render @render if @render \ No newline at end of file diff --git a/app/views/ajax/group/destroy.json.jbuilder b/app/views/ajax/group/destroy.json.jbuilder deleted file mode 100644 index 2c193af4..00000000 --- a/app/views/ajax/group/destroy.json.jbuilder +++ /dev/null @@ -1 +0,0 @@ -json.partial! 'ajax/shared/status' \ No newline at end of file diff --git a/app/views/ajax/group/membership.json.jbuilder b/app/views/ajax/group/membership.json.jbuilder deleted file mode 100644 index 707cf362..00000000 --- a/app/views/ajax/group/membership.json.jbuilder +++ /dev/null @@ -1,2 +0,0 @@ -json.partial! 'ajax/shared/status' -json.checked @checked \ No newline at end of file diff --git a/app/views/ajax/inbox/create.json.jbuilder b/app/views/ajax/inbox/create.json.jbuilder deleted file mode 100644 index f2c8c8c4..00000000 --- a/app/views/ajax/inbox/create.json.jbuilder +++ /dev/null @@ -1,2 +0,0 @@ -json.partial! 'ajax/shared/status' -json.render @render \ No newline at end of file diff --git a/app/views/ajax/inbox/remove.json.jbuilder b/app/views/ajax/inbox/remove.json.jbuilder deleted file mode 100644 index 2c193af4..00000000 --- a/app/views/ajax/inbox/remove.json.jbuilder +++ /dev/null @@ -1 +0,0 @@ -json.partial! 'ajax/shared/status' \ No newline at end of file diff --git a/app/views/ajax/moderation/ban.json.jbuilder b/app/views/ajax/moderation/ban.json.jbuilder deleted file mode 100644 index f98b3c38..00000000 --- a/app/views/ajax/moderation/ban.json.jbuilder +++ /dev/null @@ -1 +0,0 @@ -json.partial! 'ajax/shared/status' diff --git a/app/views/ajax/moderation/create_comment.json.jbuilder b/app/views/ajax/moderation/create_comment.json.jbuilder deleted file mode 100644 index 46fa7695..00000000 --- a/app/views/ajax/moderation/create_comment.json.jbuilder +++ /dev/null @@ -1,3 +0,0 @@ -json.partial! 'ajax/shared/status' -json.render @render if @render -json.count @count if @count \ No newline at end of file diff --git a/app/views/ajax/moderation/destroy_comment.json.jbuilder b/app/views/ajax/moderation/destroy_comment.json.jbuilder deleted file mode 100644 index 46291e5d..00000000 --- a/app/views/ajax/moderation/destroy_comment.json.jbuilder +++ /dev/null @@ -1,2 +0,0 @@ -json.partial! 'ajax/shared/status' -json.count @count if @count \ No newline at end of file diff --git a/app/views/ajax/moderation/destroy_report.json.jbuilder b/app/views/ajax/moderation/destroy_report.json.jbuilder deleted file mode 100644 index 2c193af4..00000000 --- a/app/views/ajax/moderation/destroy_report.json.jbuilder +++ /dev/null @@ -1 +0,0 @@ -json.partial! 'ajax/shared/status' \ No newline at end of file diff --git a/app/views/ajax/moderation/destroy_vote.json.jbuilder b/app/views/ajax/moderation/destroy_vote.json.jbuilder deleted file mode 100644 index 46291e5d..00000000 --- a/app/views/ajax/moderation/destroy_vote.json.jbuilder +++ /dev/null @@ -1,2 +0,0 @@ -json.partial! 'ajax/shared/status' -json.count @count if @count \ No newline at end of file diff --git a/app/views/ajax/moderation/privilege.json.jbuilder b/app/views/ajax/moderation/privilege.json.jbuilder deleted file mode 100644 index 707cf362..00000000 --- a/app/views/ajax/moderation/privilege.json.jbuilder +++ /dev/null @@ -1,2 +0,0 @@ -json.partial! 'ajax/shared/status' -json.checked @checked \ No newline at end of file diff --git a/app/views/ajax/moderation/vote.json.jbuilder b/app/views/ajax/moderation/vote.json.jbuilder deleted file mode 100644 index 46291e5d..00000000 --- a/app/views/ajax/moderation/vote.json.jbuilder +++ /dev/null @@ -1,2 +0,0 @@ -json.partial! 'ajax/shared/status' -json.count @count if @count \ No newline at end of file diff --git a/app/views/ajax/question/create.json.jbuilder b/app/views/ajax/question/create.json.jbuilder deleted file mode 100644 index 2c193af4..00000000 --- a/app/views/ajax/question/create.json.jbuilder +++ /dev/null @@ -1 +0,0 @@ -json.partial! 'ajax/shared/status' \ No newline at end of file diff --git a/app/views/ajax/question/destroy.json.jbuilder b/app/views/ajax/question/destroy.json.jbuilder deleted file mode 100644 index f98b3c38..00000000 --- a/app/views/ajax/question/destroy.json.jbuilder +++ /dev/null @@ -1 +0,0 @@ -json.partial! 'ajax/shared/status' diff --git a/app/views/ajax/question/preview.json.jbuilder b/app/views/ajax/question/preview.json.jbuilder deleted file mode 100644 index 6bf01010..00000000 --- a/app/views/ajax/question/preview.json.jbuilder +++ /dev/null @@ -1,2 +0,0 @@ -json.partial! 'ajax/shared/status' -json.markdown @markdown if @markdown diff --git a/app/views/ajax/report/create.json.jbuilder b/app/views/ajax/report/create.json.jbuilder deleted file mode 100644 index f2c8c8c4..00000000 --- a/app/views/ajax/report/create.json.jbuilder +++ /dev/null @@ -1,2 +0,0 @@ -json.partial! 'ajax/shared/status' -json.render @render \ No newline at end of file diff --git a/app/views/ajax/shared/_status.json.jbuilder b/app/views/ajax/shared/_status.json.jbuilder deleted file mode 100644 index a027dbff..00000000 --- a/app/views/ajax/shared/_status.json.jbuilder +++ /dev/null @@ -1,3 +0,0 @@ -json.success @success -json.status @status -json.message @message \ No newline at end of file diff --git a/app/views/ajax/smile/create.json.jbuilder b/app/views/ajax/smile/create.json.jbuilder deleted file mode 100644 index 2c193af4..00000000 --- a/app/views/ajax/smile/create.json.jbuilder +++ /dev/null @@ -1 +0,0 @@ -json.partial! 'ajax/shared/status' \ No newline at end of file diff --git a/app/views/ajax/smile/create_comment.json.jbuilder b/app/views/ajax/smile/create_comment.json.jbuilder deleted file mode 100644 index f98b3c38..00000000 --- a/app/views/ajax/smile/create_comment.json.jbuilder +++ /dev/null @@ -1 +0,0 @@ -json.partial! 'ajax/shared/status' diff --git a/app/views/ajax/smile/destroy.json.jbuilder b/app/views/ajax/smile/destroy.json.jbuilder deleted file mode 100644 index 2c193af4..00000000 --- a/app/views/ajax/smile/destroy.json.jbuilder +++ /dev/null @@ -1 +0,0 @@ -json.partial! 'ajax/shared/status' \ No newline at end of file diff --git a/app/views/ajax/smile/destroy_comment.json.jbuilder b/app/views/ajax/smile/destroy_comment.json.jbuilder deleted file mode 100644 index f98b3c38..00000000 --- a/app/views/ajax/smile/destroy_comment.json.jbuilder +++ /dev/null @@ -1 +0,0 @@ -json.partial! 'ajax/shared/status' diff --git a/app/views/ajax/subscription/subscribe.json.jbuilder b/app/views/ajax/subscription/subscribe.json.jbuilder deleted file mode 100644 index f98b3c38..00000000 --- a/app/views/ajax/subscription/subscribe.json.jbuilder +++ /dev/null @@ -1 +0,0 @@ -json.partial! 'ajax/shared/status' diff --git a/app/views/ajax/subscription/unsubscribe.json.jbuilder b/app/views/ajax/subscription/unsubscribe.json.jbuilder deleted file mode 100644 index f98b3c38..00000000 --- a/app/views/ajax/subscription/unsubscribe.json.jbuilder +++ /dev/null @@ -1 +0,0 @@ -json.partial! 'ajax/shared/status' diff --git a/config/locales/cs.yml b/config/locales/cs.yml index bead41bc..3d82fbb2 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -152,9 +152,6 @@ cs: rec_inv: "Vaše otázka je příliš dlhá." not_found: "Skupina nebyla nalezena" okay: "Otázka úspěšně zeptána." - preview: - fail: "Renderování kódu selhalo." - okay: "Úspěšně renderováno kód." report: create: login: "přihlášení povinné" diff --git a/config/locales/de.yml b/config/locales/de.yml index de50b23e..177e96db 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -154,9 +154,6 @@ de: rec_inv: "Deine Frage ist zu lang." not_found: "Gruppe nicht gefunden" okay: "Frage erfolgreich gestellt." - preview: - fail: "Das Markdownrendern ist fehlgeschlagen." - okay: "Markdown erfolgreich gerendert." report: create: login: "Login benötigt" @@ -455,4 +452,4 @@ de: contributor: Contributor blogger: Blogger banned: Gebannt - translator: Übersetzer \ No newline at end of file + translator: Übersetzer diff --git a/config/locales/en.yml b/config/locales/en.yml index bf3b2a0d..03d56529 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -151,9 +151,6 @@ en: rec_inv: "Your question is too long." not_found: "Group not found" okay: "Question asked successfully." - preview: - fail: "Failed to render markdown." - okay: "Successfully rendered markdown." report: create: login: "login required" diff --git a/config/locales/en_dizzle.yml b/config/locales/en_dizzle.yml index c7699379..525105d3 100644 --- a/config/locales/en_dizzle.yml +++ b/config/locales/en_dizzle.yml @@ -151,9 +151,6 @@ en_dizzle: rec_inv: "Yo crazy-ass question is too long." not_found: "Group not found" okay: "Question asked successfully." - preview: - fail: "Failed ta render markdown." - okay: "Successfully rendered markdown." report: create: login: "login required" diff --git a/config/locales/en_pirate.yml b/config/locales/en_pirate.yml index 8ef80609..3e27d0df 100644 --- a/config/locales/en_pirate.yml +++ b/config/locales/en_pirate.yml @@ -151,9 +151,6 @@ en_pirate: rec_inv: "Your inquiry is too long." not_found: "Crew not found" okay: "Inquiry asked successfully." - preview: - fail: "Failed to render markdown." - okay: "Successfully rendered markdown." report: create: login: "login required" diff --git a/config/locales/fr.yml b/config/locales/fr.yml index c7a1e5af..f1f17579 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -154,9 +154,6 @@ fr: rec_inv: "Votre question est trop longue." not_found: "Le groupe est introuvable." okay: "La question a été posée avec succès." - preview: - fail: "Échec de rendu du markdown." - okay: "Markdown rendu avec succès." report: create: login: "connexion requise" diff --git a/config/locales/it.yml b/config/locales/it.yml index 220ecf5f..b155a5a4 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -151,9 +151,6 @@ it: rec_inv: "La tua domanda è troppo lunga." not_found: "Gruppo non trovato" okay: "Domanda chiesta." - preview: - fail: "Impossibile renderizzare markdown." - okay: "Markdown renderizzato." report: create: login: "devi prima fare il login" diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 1040763c..0d96e79c 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -153,9 +153,6 @@ ja: rec_inv: 質問が長過ぎます。 not_found: グループが見つかりません okay: 質問の投稿に成功しました。 - preview: - fail: 書式処理に失敗しました。 - okay: 書式処理に成功しました。 report: create: login: ログインが必要です diff --git a/config/routes.rb b/config/routes.rb index 5d3e2464..7ffc9036 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -106,7 +106,6 @@ Rails.application.routes.draw do match '/create_group', to: 'group#create', via: :post, as: :create_group match '/destroy_group', to: 'group#destroy', via: :post, as: :destroy_group match '/group_membership', to: 'group#membership', via: :post, as: :group_membership - match '/preview', to: "question#preview", via: :post, as: :preview match '/subscribe', to: 'subscription#subscribe', via: :post, as: :subscribe_answer match '/unsubscribe', to: 'subscription#unsubscribe', via: :post, as: :unsubscribe_answer end diff --git a/spec/controllers/ajax/answer_controller_spec.rb b/spec/controllers/ajax/answer_controller_spec.rb new file mode 100644 index 00000000..55aa7ad6 --- /dev/null +++ b/spec/controllers/ajax/answer_controller_spec.rb @@ -0,0 +1,290 @@ +# coding: utf-8 +# frozen_string_literal: true + +require "rails_helper" + +describe Ajax::AnswerController, type: :controller do + shared_examples "returns the expected response" do + it "returns the expected response" do + expect(JSON.parse(subject.body)).to match(expected_response) + end + end + + let(:user) { FactoryBot.create(:user) } + let(:question) { FactoryBot.create(:question, user: FactoryBot.build(:user, privacy_allow_stranger_answers: asker_allows_strangers)) } + let(:asker_allows_strangers) { true } + + describe "#create" do + let(:params) do + { + id: id, + answer: answer, + share: shared_services&.to_json, + inbox: inbox + }.compact + end + + subject { post(:create, params: params) } + + context "when user is signed in" do + shared_examples "creates the answer" do + it "creates an answer" do + expect { subject }.to(change { Answer.count }.by(1)) + end + + it "enqueues a job for sharing the answer to social networks" do + subject + expect(ShareWorker).to have_enqueued_sidekiq_job(user.id, Answer.last.id, shared_services) + end + + include_examples "returns the expected response" + end + + shared_examples "does not create the answer" do + it "does not create an answer" do + expect { subject }.not_to(change { Answer.count }) + end + + it "does not enqueue a job for sharing the answer to social networks" do + subject + expect(ShareWorker).not_to have_enqueued_sidekiq_job(anything, anything, anything) + end + + include_examples "returns the expected response" + end + + shared_examples "fails when answer content is empty" do + let(:expected_response) do + { + "success" => false, + # caught by rescue_from, so status is not peter_dinklage + "status" => "parameter_error", + "message" => anything + } + end + + ["", " ", "\r \n"].each do |a| + context "when answer is #{a.inspect}" do + let(:answer) { a } + include_examples "does not create the answer" + end + end + end + + before(:each) { sign_in(user) } + + context "when all parameters are given" do + let(:answer) { "Werfen Sie nicht länger das Fenster zum Geld hinaus!" } + let(:shared_services) { %w[twitter] } + + context "when inbox is true" do + let(:id) { FactoryBot.create(:inbox, user: inbox_user, question: question).id } + let(:inbox) { true } + + context "when the inbox entry belongs to the user" do + let(:inbox_user) { user } + let(:expected_response) do + { + "success" => true, + "status" => "okay", + "message" => anything + } + end + + include_examples "creates the answer" + + it_behaves_like "fails when answer content is empty" + end + + context "when the inbox entry does not belong to the user" do + let(:inbox_user) { FactoryBot.create(:user) } + let(:expected_response) do + { + "success" => false, + "status" => "fail", + "message" => anything + } + end + + include_examples "does not create the answer" + + it_behaves_like "fails when answer content is empty" + end + end + + context "when inbox is false" do + let(:id) { question.id } + let(:inbox) { false } + + context "when question asker allows strangers to answer (i.e. question was not in inbox)" do + let(:asker_allows_strangers) { true } + let(:expected_response) do + { + "success" => true, + "status" => "okay", + "message" => anything, + "render" => anything + } + end + + include_examples "creates the answer" + + it_behaves_like "fails when answer content is empty" + end + + context "when question asker does not allow strangers to answer (i.e. question was not in inbox)" do + let(:asker_allows_strangers) { false } + let(:expected_response) do + { + "success" => false, + "status" => "privacy_stronk", + "message" => anything + } + end + + include_examples "does not create the answer" + end + end + end + + context "when some parameters are missing" do + let(:id) { nil } + let(:answer) { "Trollolo" } + let(:inbox) { nil } + let(:shared_services) { [] } + + let(:expected_response) do + { + "success" => false, + # caught by rescue_from, so status is not peter_dinklage + "status" => "parameter_error", + "message" => anything + } + end + + include_examples "returns the expected response" + end + end + + context "when user is not signed in" do + let(:id) { question.id } + let(:inbox) { false } + let(:shared_services) { %w[twitter] } + let(:answer) { "HACKED" } + + let(:expected_response) do + { + "success" => false, + "status" => "err", + "message" => anything + } + end + + include_examples "returns the expected response" + end + end + + describe "#destroy" do + let(:answer_user) { user } + let(:question) { FactoryBot.create(:question, user: FactoryBot.create(:user)) } + let(:answer) { FactoryBot.create(:answer, user: answer_user, question: question) } + let(:answer_id) { answer.id } + + let(:params) do + { + answer: answer_id + } + end + + subject { delete(:destroy, params: params) } + + context "when user is signed in" do + shared_examples "deletes the answer" do + let(:expected_response) do + { + "success" => true, + "status" => "okay", + "message" => anything + } + end + + it "deletes the answer" do + answer # ensure we already have it in the db + expect { subject }.to(change { Answer.count }.by(-1)) + end + + include_examples "returns the expected response" + end + + shared_examples "does not delete the answer" do + let(:expected_response) do + { + "success" => false, + "status" => "nopriv", + "message" => anything + } + end + + it "does not delete the answer" do + answer # ensure we already have it in the db + expect { subject }.not_to(change { Answer.count }) + end + + include_examples "returns the expected response" + end + + before(:each) { sign_in(user) } + + context "when the answer exists and was made by the current user" do + include_examples "deletes the answer" + + it "returns the question back to the user's inbox" do + expect { subject }.to(change { Inbox.where(question_id: answer.question.id, user_id: user.id).count }.by(1)) + end + end + + context "when the answer exists and was not made by the current user" do + let(:answer_user) { FactoryBot.create(:user) } + include_examples "does not delete the answer" + + %i[moderator administrator].each do |privileged_role| + context "when the current user is a #{privileged_role}" do + around do |example| + user.add_role privileged_role + example.run + user.remove_role privileged_role + end + + include_examples "deletes the answer" + end + end + end + + context "when the answer does not exist" do + let(:answer_id) { "sonic_the_hedgehog" } + + let(:expected_response) do + { + "success" => false, + "status" => anything, + "message" => anything + } + end + + include_examples "returns the expected response" + end + end + + context "when user is not signed in" do + let(:expected_response) do + { + "success" => false, + "status" => "nopriv", + "message" => anything + } + end + + include_examples "returns the expected response" + end + end +end diff --git a/spec/factories/inbox.rb b/spec/factories/inbox.rb new file mode 100644 index 00000000..6345fa72 --- /dev/null +++ b/spec/factories/inbox.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :inbox do + question { FactoryBot.build(:question) } + new { true } + end +end