# encoding: utf-8 #-- # Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . #++ require File.dirname(__FILE__) + '/../test_helper' class MessageTest < ActiveSupport::TestCase should_belong_to :sender should_belong_to :recipient should_require_attributes :subject, :body should_belong_to :notifiable should_have_many :replies context 'The state machine' do setup do @recipient = Factory.create(:user) @sender = Factory.create(:user) end context 'class level' do should 'have all the required states' do registered_state_names = Message.state_machines[:aasm_state].states.collect(&:name) [:unread, :read].each do |state| assert registered_state_names.include?(state) end end should 'have all the required events' do # Yeah, I know this is a bit brute, will refactor once all the models are migrated registered_event_names = Message.state_machines[:aasm_state].events.instance_variable_get("@nodes").collect(&:name) [:read].each {|e| assert registered_event_names.include?(e)} end end context 'instance level' do setup do @message = Factory.create(:message, :sender => @sender, :recipient => @recipient) @recipient = @message.recipient assert_not_nil(@recipient) end should 'transition to read when the user reads it' do unread_message_count = @recipient.received_messages.unread_count @message.read! assert_equal(unread_message_count - 1, @recipient.received_messages.unread_count) end end end context 'Replying to a message' do setup do @message = Factory.create(:message) @reply = @message.build_reply(:body => "Thanks. That's much appreciated") end should 'set the sender and recipient correctly' do assert_equal @message.recipient, @reply.sender assert_equal @message.sender, @reply.recipient end should 'be able to override the subject of a message' do @reply = @message.build_reply(:body => "Thanks. That's much appreciated", :subject => "WTF") assert_equal("WTF", @reply.subject) end should 'set a default subject when replying to a message' do assert_equal("Re: #{@message.subject}", @reply.subject) end should 'flag which message the reply relates to' do assert_equal @message, @reply.in_reply_to end should "add to its original messages's responses" do assert @reply.save assert @message.replies.include?(@reply) end should 'set the root message' do assert @reply.save assert_equal @message, @reply.root_message end should 'flag the root message as having unread messages when a new reply is created' do assert !@message.has_unread_replies? assert @reply.save assert @message.reload.has_unread_replies? @message.update_attribute(:has_unread_replies, false) reply_to_reply = @reply.build_reply(:body => 'All right!', :subject => 'Feeling chatty') assert reply_to_reply.save assert !@message.reload.has_unread_replies? end should "touch the root message's updated_at" do # hardwire the actual object here @reply.stubs(:root_message).returns(@message) @message.expects(:touch!) @reply.save end end context "Last updated on" do setup do @message = Message.new(:sender => users(:johan), :recipient => users(:moe), :subject => "Hey", :body => "thanks") @message.save end should "be set to current time on creation" do assert_not_nil @message.last_activity_at end should "set last_activity_on to now on touch!" do original_update_time = 1.hour.ago @message.last_activity_at = original_update_time @message.touch! assert @message.last_activity_at > original_update_time end end context 'Calculating the number of messages in a thread' do setup do @message = Factory.create(:message) end should 'calculate the number of unread messages' do assert_equal(1, @message.number_of_messages_in_thread) reply = @message.build_reply(:body => "Thanks so much") assert reply.save 10.times do new_reply = reply.build_reply(:body => "That's nothing") new_reply.save reply = new_reply end @message.replies.reload assert_equal(12, @message.number_of_messages_in_thread) end should 'know which messages are in the same thread' do reply = @message.build_reply(:body => 'Yeah') reply.save reply_to_reply = reply.build_reply(:body=>"Nope") reply_to_reply.save assert @message.messages_in_thread.include?(reply_to_reply) end should 'know whether there are any unread messages in the thread' do @message.read! assert !@message.unread_messages? reply = @message.build_reply(:body => "This isn't read yet") reply.save @message.replies.reload assert @message.unread_messages? reply.read! @message.replies.reload assert !@message.unread_messages? end end context 'Email notifications' do setup do @privacy_lover = Factory.create(:user, :wants_email_notifications => false) @email_lover = Factory.create(:user, :wants_email_notifications => true) # @moe = users(:moe) # @mike = users(:mike) @message = Message.new(:subject => "Hello", :body => "World") end should 'fire a notification event on message creation' do assert @email_lover.wants_email_notifications? @message.sender = @privacy_lover @message.recipient = @email_lover @message.expects(:schedule_email_delivery).once @message.save end should 'not fire a notification event for opt-out users' do assert !@privacy_lover.wants_email_notifications? @message.sender = @email_lover @message.recipient = @privacy_lover @message.expects(:schedule_email_delivery).never @message.save end should 'actually send the message to the queue' do p = proc{ @message.sender = @privacy_lover @message.recipient = @email_lover @message.save } message = find_message_with_queue_and_regexp('/queue/GitoriousEmailNotifications', /email_delivery/) {p.call} assert_equal(@privacy_lover.id, message['sender_id']) assert_equal(@email_lover.id, message['recipient_id']) assert_equal(@message.subject, message['subject']) end should 'not send a notification when the sender and recipient is the same person' do @message.sender = @message.recipient = @email_lover assert @message.recipient.wants_email_notifications? @message.expects(:schedule_email_delivery).never @message.save end end should "be readable by the sender" do message = Message.new(:subject => "Hello", :body => "World") message.sender = users(:johan) message.recipient = users(:mike) assert message.readable_by?(users(:johan)) assert message.readable_by?(users(:mike)) assert !message.readable_by?(users(:moe)) end should "be marked as read by the recipient" do message = Message.first message.sender = users(:johan) message.recipient = users(:mike) assert_equal "unread", message.aasm_state_for_user(users(:mike)) message.mark_as_read_by_user(users(:mike)) assert_equal "read", message.reload.aasm_state_for_user(users(:mike)) end context 'Rendering XML' do setup {@message = Factory.create(:message)} should 'include required attributes' do result = @message.to_xml assert_match /#{@message.recipient.title}<\/recipient_name>/, result end end context 'Mass email delivery' do should_eventually 'create n messages when supplying several recipients' end context "Thottling" do setup do Message.destroy_all @recipient = Factory.create(:user) @sender = Factory.create(:user) end should "not throttle system notifications" do assert_nothing_raised do 15.times{|i| @message = Message.new({:subject => "Hello#{i}", :body => "World"}) @message.sender = @sender @message.recipient = @recipient @message.notifiable = MergeRequest.first @message.save! } end end should "throttle on create" do assert_nothing_raised do 10.times{|i| @message = Message.new({:subject => "Hello#{i}", :body => "World"}) @message.sender = @sender @message.recipient = @recipient @message.save! } end assert_no_difference("Message.count") do assert_raises(RecordThrottling::LimitReachedError) do @message = Message.new({:subject => "spam much?", :body => "World"}) @message.sender = @sender @message.recipient = @recipient @message.save! end end # Should inflict with others assert_difference("Message.count") do assert_nothing_raised do @message = Message.new({:subject => "spam much?", :body => "World"}) @message.sender = @recipient @message.recipient = @sender @message.save! end end end end context 'Archive state' do setup do @sender = Factory.create(:user) @recipient = Factory.create(:user) @message = Factory.create(:message, :sender => @sender, :recipient => @recipient) end should 'be marked as archived by both sender and recipient when it is the same user' do @message = Factory.create(:message, :sender => @sender, :recipient => @sender) @message.archived_by(@sender) assert @message.archived_by_sender? assert @message.archived_by_recipient? end should 'initially be unread_by_both' do assert !@message.archived_by_sender? assert !@message.archived_by_recipient? end should 'be archived by sender' do @message.archived_by(@sender) assert @message.archived_by_sender? assert !@message.archived_by_recipient? end should 'be archived by recipient' do @message.archived_by(@recipient) assert @message.archived_by_recipient? assert !@message.archived_by_sender? end should 'be archived by both sender and recipient' do @message.archived_by(@sender) @message.archived_by(@recipient) assert @message.archived_by_sender? assert @message.archived_by_recipient? end should 'be reset when a reply is created' do @message.archived_by(@sender) @message.save reply = @message.build_reply(:body => "Foo") assert reply.save assert !@message.reload.archived_by_sender? @message.archived_by(@recipient) @message.save reply_to_reply = reply.build_reply(:body => "Kthxbye") assert reply_to_reply.save assert !@message.reload.archived_by_recipient? end end context "Sender display" do setup do @sender = Factory.create(:user) @recipient = Factory.create(:user) end should "be sender#title when no notifiable exists" do message = Message.create(:sender => @sender, :recipient => @recipient, :subject => "Hey", :body => "Hello earth") assert_equal @sender.title, message.sender_name assert message.replies_enabled? end should "be Gitorious when a notifiable exists" do group = Factory.create(:group, :creator => @sender) membership = Membership.build_invitation(@sender, :group => group, :user => @recipient, :role => Role.admin) assert membership.save assert_not_nil message = membership.messages.first assert_equal @sender, message.sender assert_equal "Gitorious", message.sender_name assert !message.replies_enabled? end end end