added more tests for the poll federation + fixed broken rspec tests

This commit is contained in:
Jannik Streek 2014-03-21 18:51:40 +01:00
parent 5d560609e4
commit 8a4f833d1d
13 changed files with 121 additions and 30 deletions

View file

@ -6,7 +6,16 @@ class Poll < ActiveRecord::Base
has_many :poll_answers has_many :poll_answers
has_many :poll_participations 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 #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 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 end

View file

@ -7,4 +7,10 @@ class PollAnswer < ActiveRecord::Base
has_many :poll_participations has_many :poll_participations
xml_attr :answer xml_attr :answer
def update_vote_counter
self.vote_count = self.vote_count + 1
self.save!
end
end end

View file

@ -9,6 +9,13 @@ class PollParticipation < ActiveRecord::Base
belongs_to :author, :class_name => 'Person', :foreign_key => :author_id belongs_to :author, :class_name => 'Person', :foreign_key => :author_id
xml_attr :diaspora_handle xml_attr :diaspora_handle
xml_attr :poll_answer_guid 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 def parent_class
Poll Poll
@ -38,6 +45,18 @@ class PollParticipation < ActiveRecord::Base
self.author = Webfinger.new(nh).fetch self.author = Webfinger.new(nh).fetch
end 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 class Generator < Federated::Generator
def self.federated_class def self.federated_class
PollParticipation PollParticipation

View file

@ -77,6 +77,14 @@ en:
attributes: attributes:
root_guid: root_guid:
taken: "That good, huh? You've already reshared that post!" 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: error_messages:
helper: helper:
invalid_fields: "Invalid Fields" invalid_fields: "Invalid Fields"

View file

@ -13,6 +13,7 @@ class CreatePolls < ActiveRecord::Migration
t.string :answer, :null => false t.string :answer, :null => false
t.belongs_to :poll, :null => false t.belongs_to :poll, :null => false
t.string :guid t.string :guid
t.integer :vote_count, :default => 0
end end
add_index :poll_answers, :poll_id add_index :poll_answers, :poll_id

View file

@ -284,9 +284,10 @@ ActiveRecord::Schema.define(:version => 20140308154022) do
end end
create_table "poll_answers", :force => true do |t| create_table "poll_answers", :force => true do |t|
t.string "answer", :null => false t.string "answer", :null => false
t.integer "poll_id", :null => false t.integer "poll_id", :null => false
t.string "guid" t.string "guid"
t.integer "vote_count", :default => 0
end end
add_index "poll_answers", ["poll_id"], :name => "index_poll_answers_on_poll_id" add_index "poll_answers", ["poll_id"], :name => "index_poll_answers_on_poll_id"

View file

@ -5,7 +5,6 @@
module Diaspora module Diaspora
module Parser module Parser
def self.from_xml(xml) def self.from_xml(xml)
puts xml
doc = Nokogiri::XML(xml) { |cfg| cfg.noblanks } doc = Nokogiri::XML(xml) { |cfg| cfg.noblanks }
return unless body = doc.xpath("/XML/post").children.first return unless body = doc.xpath("/XML/post").children.first
class_name = body.name.gsub('-', '/') class_name = body.name.gsub('-', '/')

View file

@ -116,7 +116,8 @@ FactoryGirl.define do
factory(:poll) do factory(:poll) do
sequence(:question) { |n| "What do you think about #{n} ninjas?" } sequence(:question) { |n| "What do you think about #{n} ninjas?" }
after(:build) do |p| 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
end end

View file

@ -1,10 +1,21 @@
require 'spec_helper' require 'spec_helper'
describe PollAnswer do describe PollAnswer do
before :do before do
describe 'validation' do @status = FactoryGirl.create(:status_message_with_poll)
it 'should ...' do @user = alice
@answer = @status.poll.poll_answers.first
end
end 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 end

View file

@ -12,6 +12,23 @@ describe PollParticipation do
@status.poll = @poll @status.poll = @poll
end 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 describe 'xml' do
before do before do
@poll_participant = FactoryGirl.create(:user) @poll_participant = FactoryGirl.create(:user)
@ -61,18 +78,18 @@ describe PollParticipation do
before do before do
@local_luke, @local_leia, @remote_raphael = set_up_friends @local_luke, @local_leia, @remote_raphael = set_up_friends
@remote_parent = FactoryGirl.build(:status_message_with_poll, :author => @remote_raphael) @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 @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.new(:question => 'Who is now in charge?')
@poll2.poll_answers.build(:answer => "a") @poll2.poll_answers.build(:answer => "a")
@poll2.poll_answers.build(:answer => "b") @poll2.poll_answers.build(:answer => "b")
@local_parent.poll = @poll2 @local_parent.poll = @poll2
@object_by_parent_author = @local_luke.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, @poll.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 @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 end
let(:build_object) { PollParticipation::Generator.new(alice, @status, @poll.poll_answers.first).build } let(:build_object) { PollParticipation::Generator.new(alice, @status, @poll.poll_answers.first).build }

View file

@ -6,17 +6,15 @@ describe Poll do
end end
describe 'validation' do describe 'validation' do
it 'should create no poll when it has less than two answers' do it 'should not create a poll when it has less than two answers' do
@poll.poll_answers << PollAnswer.new(:answer => '1') @poll.poll_answers.build(:answer => '1')
@poll.should_not be_valid @poll.should_not be_valid
end end
it 'should create a poll when it has more than two answers' do it 'should create a poll when it has more than two answers' do
@poll.poll_answers << PollAnswer.new(:answer => '1') @poll.poll_answers.build(:answer => '1')
@poll.poll_answers << PollAnswer.new(:answer => '2') @poll.poll_answers.build(:answer => '2')
@poll.should be_valid @poll.should be_valid
end end
end end
#TODO test if delegation of subscribers works
end end

View file

@ -353,14 +353,14 @@ STR
context 'with a poll' do context 'with a poll' do
before 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 @xml = @message.to_xml.to_s
end end
it 'serializes the location' do it 'serializes the poll' do
@xml.should include "location" @xml.should include "poll"
@xml.should include "lat" @xml.should include "question"
@xml.should include "lng" @xml.should include "poll_answer"
end end
describe ".from_xml" do describe ".from_xml" do
@ -368,8 +368,12 @@ STR
@marshalled = StatusMessage.from_xml(@xml) @marshalled = StatusMessage.from_xml(@xml)
end end
it 'marshals the location' do it 'marshals the poll' do
@marshalled.location.should be_present @marshalled.poll.should be_present
end
it 'marshals the poll answers' do
@marshalled.poll.poll_answers.size.should == 2
end end
end end
end end

View file

@ -16,7 +16,7 @@ describe User::SocialActions do
alice.participations.last.target.should == @status alice.participations.last.target.should == @status
end end
it "creates the like" do it "creates the comment" do
lambda{ alice.comment!(@status, "bro") }.should change(Comment, :count).by(1) lambda{ alice.comment!(@status, "bro") }.should change(Comment, :count).by(1)
end end
@ -87,10 +87,27 @@ describe User::SocialActions do
describe 'User#participate_in_poll!' do describe 'User#participate_in_poll!' do
before do before do
@bobs_aspect = bob.aspects.where(:name => "generic").first @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)
@status = bob.post(:status_message, :text => "hello", :to => @bobs_aspect.id, :poll => poll) @poll = FactoryGirl.create(:poll, :status_message => @status)
@answer = @poll.poll_answers.first
end 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 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
end end