From 8a4f833d1def9ee780f958bee584c3a54c13c009 Mon Sep 17 00:00:00 2001 From: Jannik Streek Date: Fri, 21 Mar 2014 18:51:40 +0100 Subject: [PATCH] added more tests for the poll federation + fixed broken rspec tests --- app/models/poll.rb | 9 ++++++++ app/models/poll_answer.rb | 6 ++++++ app/models/poll_participation.rb | 19 +++++++++++++++++ config/locales/diaspora/en.yml | 8 ++++++++ db/migrate/20140308154022_create_polls.rb | 1 + db/schema.rb | 5 +++-- lib/diaspora/parser.rb | 1 - spec/factories.rb | 3 ++- spec/models/poll_answer_spec.rb | 21 ++++++++++++++----- spec/models/poll_participation_spec.rb | 25 +++++++++++++++++++---- spec/models/poll_spec.rb | 10 ++++----- spec/models/status_message_spec.rb | 18 +++++++++------- spec/models/user/social_actions_spec.rb | 25 +++++++++++++++++++---- 13 files changed, 121 insertions(+), 30 deletions(-) diff --git a/app/models/poll.rb b/app/models/poll.rb index 586e18154..778f654ca 100644 --- a/app/models/poll.rb +++ b/app/models/poll.rb @@ -6,7 +6,16 @@ class Poll < ActiveRecord::Base has_many :poll_answers has_many :poll_participations + xml_attr :question + xml_attr :poll_answers, :as => [PollAnswer] + #forward some requests to status message, because a poll is just attached to a status message and is not sharable itself delegate :author, :author_id, :public?, :subscribers, to: :status_message + validate :enough_poll_answers + + def enough_poll_answers + errors.add(:poll_answers, I18n.t("activerecord.errors.models.poll.attributes.poll_answers.not_enough_poll_answers")) if poll_answers.size < 2 + end + end diff --git a/app/models/poll_answer.rb b/app/models/poll_answer.rb index 7893a8b25..14ee658cf 100644 --- a/app/models/poll_answer.rb +++ b/app/models/poll_answer.rb @@ -7,4 +7,10 @@ class PollAnswer < ActiveRecord::Base has_many :poll_participations xml_attr :answer + + def update_vote_counter + self.vote_count = self.vote_count + 1 + self.save! + end + end diff --git a/app/models/poll_participation.rb b/app/models/poll_participation.rb index a5990f12e..c6c2ee85c 100644 --- a/app/models/poll_participation.rb +++ b/app/models/poll_participation.rb @@ -9,6 +9,13 @@ class PollParticipation < ActiveRecord::Base belongs_to :author, :class_name => 'Person', :foreign_key => :author_id xml_attr :diaspora_handle xml_attr :poll_answer_guid + validate :not_already_participated + + after_commit :update_vote_counter, :on => :create + + def update_vote_counter + self.poll_answer.update_vote_counter + end def parent_class Poll @@ -38,6 +45,18 @@ class PollParticipation < ActiveRecord::Base self.author = Webfinger.new(nh).fetch end + def not_already_participated + if self.poll == nil + return + end + + existing = PollParticipation.where(author_id: self.author.id, poll_id: self.poll.id) + if existing.first != self and existing.count != 0 + self.errors.add(:poll, I18n.t("errors.models.poll_participations.attributes.poll.already_participated")) + end + end + + class Generator < Federated::Generator def self.federated_class PollParticipation diff --git a/config/locales/diaspora/en.yml b/config/locales/diaspora/en.yml index 5e9fa2e9d..2f36c7c38 100644 --- a/config/locales/diaspora/en.yml +++ b/config/locales/diaspora/en.yml @@ -77,6 +77,14 @@ en: attributes: root_guid: taken: "That good, huh? You've already reshared that post!" + poll: + attributes: + poll_answers: + not_enough_poll_answers: "Not enough poll options provided." + poll_participation: + attributes: + poll: + already_participated: "You've already participated in this poll!" error_messages: helper: invalid_fields: "Invalid Fields" diff --git a/db/migrate/20140308154022_create_polls.rb b/db/migrate/20140308154022_create_polls.rb index 52188cdc6..f2d84ba6a 100644 --- a/db/migrate/20140308154022_create_polls.rb +++ b/db/migrate/20140308154022_create_polls.rb @@ -13,6 +13,7 @@ class CreatePolls < ActiveRecord::Migration t.string :answer, :null => false t.belongs_to :poll, :null => false t.string :guid + t.integer :vote_count, :default => 0 end add_index :poll_answers, :poll_id diff --git a/db/schema.rb b/db/schema.rb index 91253852f..97f7cb6c2 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -284,9 +284,10 @@ ActiveRecord::Schema.define(:version => 20140308154022) do end create_table "poll_answers", :force => true do |t| - t.string "answer", :null => false - t.integer "poll_id", :null => false + t.string "answer", :null => false + t.integer "poll_id", :null => false t.string "guid" + t.integer "vote_count", :default => 0 end add_index "poll_answers", ["poll_id"], :name => "index_poll_answers_on_poll_id" diff --git a/lib/diaspora/parser.rb b/lib/diaspora/parser.rb index 5665d74af..1d2c50092 100644 --- a/lib/diaspora/parser.rb +++ b/lib/diaspora/parser.rb @@ -5,7 +5,6 @@ module Diaspora module Parser def self.from_xml(xml) - puts xml doc = Nokogiri::XML(xml) { |cfg| cfg.noblanks } return unless body = doc.xpath("/XML/post").children.first class_name = body.name.gsub('-', '/') diff --git a/spec/factories.rb b/spec/factories.rb index 232e3a15b..ac040e185 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -116,7 +116,8 @@ FactoryGirl.define do factory(:poll) do sequence(:question) { |n| "What do you think about #{n} ninjas?" } after(:build) do |p| - FactoryGirl.create(:poll_answer, :poll => p) + p.poll_answers << FactoryGirl.build(:poll_answer) + p.poll_answers << FactoryGirl.build(:poll_answer) end end diff --git a/spec/models/poll_answer_spec.rb b/spec/models/poll_answer_spec.rb index b49465034..aa53d5261 100644 --- a/spec/models/poll_answer_spec.rb +++ b/spec/models/poll_answer_spec.rb @@ -1,10 +1,21 @@ require 'spec_helper' describe PollAnswer do -before :do - describe 'validation' do - it 'should ...' do - - end + before do + @status = FactoryGirl.create(:status_message_with_poll) + @user = alice + @answer = @status.poll.poll_answers.first end + + describe 'counter cache' do + it 'increments the counter cache on the answer' do + lambda { + alice.participate_in_poll!(@status, @answer) + }.should change{ + @answer.reload.vote_count + }.by(1) + end + + end + end \ No newline at end of file diff --git a/spec/models/poll_participation_spec.rb b/spec/models/poll_participation_spec.rb index 68c3fcfdf..26fbd10fc 100644 --- a/spec/models/poll_participation_spec.rb +++ b/spec/models/poll_participation_spec.rb @@ -12,6 +12,23 @@ describe PollParticipation do @status.poll = @poll end + describe 'validation' do + it 'does forbid multiple participations in the same poll' do + expect { + 2.times do |run| + bob.participate_in_poll!(@status, @poll.poll_answers.first) + end + }.to raise_error + end + + it 'does allow a one time participation in a poll' do + expect { + bob.participate_in_poll!(@status, @poll.poll_answers.first) + }.to_not raise_error + end + + end + describe 'xml' do before do @poll_participant = FactoryGirl.create(:user) @@ -61,18 +78,18 @@ describe PollParticipation do before do @local_luke, @local_leia, @remote_raphael = set_up_friends @remote_parent = FactoryGirl.build(:status_message_with_poll, :author => @remote_raphael) - + @local_parent = @local_luke.post :status_message, :text => "hi", :to => @local_luke.aspects.first @poll2 = Poll.new(:question => 'Who is now in charge?') @poll2.poll_answers.build(:answer => "a") @poll2.poll_answers.build(:answer => "b") @local_parent.poll = @poll2 - @object_by_parent_author = @local_luke.participate_in_poll!(@local_parent, @poll.poll_answers.first) - @object_by_recipient = @local_leia.participate_in_poll!(@local_parent, @poll.poll_answers.first) + @object_by_parent_author = @local_luke.participate_in_poll!(@local_parent, @poll2.poll_answers.first) + @object_by_recipient = @local_leia.participate_in_poll!(@local_parent, @poll2.poll_answers.first) @dup_object_by_parent_author = @object_by_parent_author.dup - @object_on_remote_parent = @local_luke.participate_in_poll!(@remote_parent, @poll.poll_answers.first) + @object_on_remote_parent = @local_luke.participate_in_poll!(@remote_parent, @remote_parent.poll.poll_answers.first) end let(:build_object) { PollParticipation::Generator.new(alice, @status, @poll.poll_answers.first).build } diff --git a/spec/models/poll_spec.rb b/spec/models/poll_spec.rb index ab5641fc7..c94c08e33 100644 --- a/spec/models/poll_spec.rb +++ b/spec/models/poll_spec.rb @@ -6,17 +6,15 @@ describe Poll do end describe 'validation' do - it 'should create no poll when it has less than two answers' do - @poll.poll_answers << PollAnswer.new(:answer => '1') + it 'should not create a poll when it has less than two answers' do + @poll.poll_answers.build(:answer => '1') @poll.should_not be_valid end it 'should create a poll when it has more than two answers' do - @poll.poll_answers << PollAnswer.new(:answer => '1') - @poll.poll_answers << PollAnswer.new(:answer => '2') + @poll.poll_answers.build(:answer => '1') + @poll.poll_answers.build(:answer => '2') @poll.should be_valid end end - - #TODO test if delegation of subscribers works end \ No newline at end of file diff --git a/spec/models/status_message_spec.rb b/spec/models/status_message_spec.rb index c68a82147..297a3f269 100644 --- a/spec/models/status_message_spec.rb +++ b/spec/models/status_message_spec.rb @@ -353,14 +353,14 @@ STR context 'with a poll' do before do - @message.poll = Poll.new(coordinates: "1, 2").tap(&:save) + @message.poll = FactoryGirl.create(:poll, :status_message => @message) @xml = @message.to_xml.to_s end - it 'serializes the location' do - @xml.should include "location" - @xml.should include "lat" - @xml.should include "lng" + it 'serializes the poll' do + @xml.should include "poll" + @xml.should include "question" + @xml.should include "poll_answer" end describe ".from_xml" do @@ -368,8 +368,12 @@ STR @marshalled = StatusMessage.from_xml(@xml) end - it 'marshals the location' do - @marshalled.location.should be_present + it 'marshals the poll' do + @marshalled.poll.should be_present + end + + it 'marshals the poll answers' do + @marshalled.poll.poll_answers.size.should == 2 end end end diff --git a/spec/models/user/social_actions_spec.rb b/spec/models/user/social_actions_spec.rb index 6ab83e4c5..de486010d 100644 --- a/spec/models/user/social_actions_spec.rb +++ b/spec/models/user/social_actions_spec.rb @@ -16,7 +16,7 @@ describe User::SocialActions do alice.participations.last.target.should == @status end - it "creates the like" do + it "creates the comment" do lambda{ alice.comment!(@status, "bro") }.should change(Comment, :count).by(1) end @@ -87,10 +87,27 @@ describe User::SocialActions do describe 'User#participate_in_poll!' do before do @bobs_aspect = bob.aspects.where(:name => "generic").first - poll = Poll.new(:poll_answers => [PollAnswer.new(:answer => "1"), PollAnswer.new(:answer => "2")]) - @status = bob.post(:status_message, :text => "hello", :to => @bobs_aspect.id, :poll => poll) + @status = bob.post(:status_message, :text => "hello", :to => @bobs_aspect.id) + @poll = FactoryGirl.create(:poll, :status_message => @status) + @answer = @poll.poll_answers.first end + + it "federates" do + Participation::Generator.any_instance.stub(:create!) + Postzord::Dispatcher.should_receive(:defer_build_and_post) + alice.participate_in_poll!(@status, @answer) + end + + it "creates a partcipation" do + lambda{ alice.participate_in_poll!(@status, @answer) }.should change(Participation, :count).by(1) + end + + it "creates the poll participation" do + lambda{ alice.participate_in_poll!(@status, @answer) }.should change(PollParticipation, :count).by(1) + end + it "sets the poll answer id" do - alice.participate_in_poll!(@status, 1).poll_answer.answer.should == "1" + alice.participate_in_poll!(@status, @answer).poll_answer.should == @answer end + end end \ No newline at end of file