Add Poll Voting Method to Interactions Endpoint

This commit is contained in:
Hank Grabowski 2018-12-10 17:13:13 -05:00
parent 32157036d3
commit ff6d0064d0
8 changed files with 198 additions and 6 deletions

View file

@ -51,11 +51,32 @@ module Api
render json: I18n.t("api.endpoint_errors.posts.cant_report"), status: :unprocessable_entity
end
def vote
begin
post = post_service.find!(params[:post_id])
rescue ActiveRecord::RecordNotFound
render json: I18n.t("api.endpoint_errors.posts.post_not_found"), status: :not_found
return
end
poll_vote = poll_service.vote(post.id, params[:poll_answer_id])
if poll_vote
head :no_content
else
render json: I18n.t("api.endpoint_errors.interactions.cant_vote"), status: :unprocessable_entity
end
rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotFound
render json: I18n.t("api.endpoint_errors.interactions.cant_vote"), status: :unprocessable_entity
end
private
def post_service
@post_service ||= PostService.new(current_user)
end
def poll_service
@poll_service ||= PollParticipationService.new(current_user)
end
end
end
end

View file

@ -4,8 +4,7 @@ class PollParticipationsController < ApplicationController
before_action :authenticate_user!
def create
answer = PollAnswer.find(params[:poll_answer_id])
poll_participation = current_user.participate_in_poll!(target, answer) if target
poll_participation = poll_service.vote(params[:post_id], params[:poll_answer_id])
respond_to do |format|
format.mobile { redirect_to stream_path }
format.json { render json: poll_participation, :status => 201 }
@ -19,9 +18,7 @@ class PollParticipationsController < ApplicationController
private
def target
@target ||= if params[:post_id]
current_user.find_visible_shareable_by_id(Post, params[:post_id]) || raise(ActiveRecord::RecordNotFound.new)
end
def poll_service
@poll_service ||= PollParticipationService.new(current_user)
end
end

View file

@ -0,0 +1,18 @@
# frozen_string_literal: true
class PollParticipationService
def initialize(user)
@user = user
end
def vote(post_id, answer_id)
answer = PollAnswer.find(answer_id)
@user.participate_in_poll!(target(post_id), answer) if target(post_id)
end
private
def target(post_id)
@target ||= @user.find_visible_shareable_by_id(Post, post_id) || raise(ActiveRecord::RecordNotFound.new)
end
end

View file

@ -974,6 +974,7 @@ en:
no_like: "Like doesnt exist"
interactions:
cant_subscribe: "Can't subscribe to this post"
cant_vote: "Can't vote on this post"
notifications:
not_found: "Notification with provided guid could not be found"
cant_process: "Couldn't process the notifications request"

View file

@ -236,6 +236,7 @@ Rails.application.routes.draw do
post "mute" => "post_interactions#mute"
post "hide" => "post_interactions#hide"
post "report" => "post_interactions#report"
post "vote" => "post_interactions#vote"
end
resources :conversations, only: %i[show index create destroy] do
resources :messages, only: %i[index create]

View file

@ -0,0 +1,38 @@
# frozen_string_literal: true
describe PollParticipationsController, type: :controller do
let(:poll_post) { FactoryGirl.create(:status_message_with_poll, public: true) }
let(:poll_answer) { poll_post.poll.poll_answers.first }
before do
sign_in alice, scope: :user
request.env["HTTP_ACCEPT"] = "application/json"
end
describe "voting on poll" do
it "succeeds" do
post :create, params: {post_id: poll_post.id, poll_answer_id: poll_answer.id}
expect(response.status).to eq(201)
poll_participation = JSON.parse(response.body)["poll_participation"]
expect(poll_participation["poll_answer_id"]).to eq(poll_answer.id)
end
it "fails to vote twice" do
post :create, params: {post_id: poll_post.id, poll_answer_id: poll_answer.id}
expect(response.status).to eq(201)
post :create, params: {post_id: poll_post.id, poll_answer_id: poll_answer.id}
expect(response.status).to eq(403)
end
it "fails with bad answer id" do
expect {
post :create, params: {post_id: poll_post.id, poll_answer_id: -1}
}.to raise_error(ActiveRecord::RecordNotFound)
end
it "fails with bad post id" do
expect { post :create, params: {post_id: -1, poll_answer_id: poll_answer.id} }
.to raise_error(ActiveRecord::RecordNotFound)
end
end
end

View file

@ -291,4 +291,91 @@ describe Api::V1::PostInteractionsController do
end
end
end
describe "#vote" do
before do
base_params = {status_message: {text: "myText"}, public: true}
poll_params = {poll_question: "something?", poll_answers: %w[yes no maybe]}
merged_params = base_params.merge(poll_params)
@poll_post = StatusMessageCreationService.new(alice).create(merged_params)
@poll_answer = @poll_post.poll.poll_answers.first
end
it "succeeds" do
post(
api_v1_post_vote_path(@poll_post.guid),
params: {
poll_answer_id: @poll_answer.id,
access_token: access_token
}
)
expect(response.status).to eq(204)
expect(@poll_answer.reload.vote_count).to eq(1)
end
it "fails to vote twice" do
post(
api_v1_post_vote_path(@poll_post.guid),
params: {
poll_answer_id: @poll_answer.id,
access_token: access_token
}
)
expect(response.status).to eq(204)
post(
api_v1_post_vote_path(@poll_post.guid),
params: {
poll_answer_id: @poll_answer.id,
access_token: access_token
}
)
expect(response.status).to eq(422)
expect(response.body).to eq(I18n.t("api.endpoint_errors.interactions.cant_vote"))
end
it "fails with bad answer id" do
post(
api_v1_post_vote_path(@poll_post.guid),
params: {
poll_answer_id: -1,
access_token: access_token
}
)
expect(response.status).to eq(422)
expect(response.body).to eq(I18n.t("api.endpoint_errors.interactions.cant_vote"))
end
it "fails with bad post id" do
post(
api_v1_post_vote_path("999_999_999"),
params: {
poll_answer_id: @poll_answer.id,
access_token: access_token
}
)
expect(response.status).to eq(404)
expect(response.body).to eq(I18n.t("api.endpoint_errors.posts.post_not_found"))
end
it "with read only token" do
post(
api_v1_post_vote_path(@poll_post.guid),
params: {
poll_answer_id: @poll_answer.id,
access_token: access_token_read_only
}
)
expect(response.status).to eq(403)
end
it "with invalid token" do
post(
api_v1_post_vote_path(@poll_post.guid),
params: {
poll_answer_id: @poll_answer.id,
access_token: "999_999_999"
}
)
expect(response.status).to eq(401)
end
end
end

View file

@ -0,0 +1,29 @@
# frozen_string_literal: true
describe PollParticipationService do
let(:poll_post) { FactoryGirl.create(:status_message_with_poll, public: true) }
let(:poll_answer) { poll_post.poll.poll_answers.first }
describe "voting on poll" do
it "succeeds" do
expect(poll_service.vote(poll_post.id, poll_answer.id)).not_to be_nil
end
it "fails to vote twice" do
expect(poll_service.vote(poll_post.id, poll_answer.id)).not_to be_nil
expect { poll_service.vote(poll_post.id, poll_answer.id) }.to raise_error(ActiveRecord::RecordInvalid)
end
it "fails with bad answer id" do
expect { poll_service.vote(poll_post.id, -2) }.to raise_error(ActiveRecord::RecordNotFound)
end
it "fails with bad post id" do
expect { poll_service.vote(-1, poll_answer.id) }.to raise_error(ActiveRecord::RecordNotFound)
end
end
def poll_service(user=alice)
PollParticipationService.new(user)
end
end