require 'spec_helper' describe Invite do it { should belong_to :user } it { should have_many :topic_invites } it { should belong_to :invited_by } it { should have_many :topics } it { should validate_presence_of :email } it { should validate_presence_of :invited_by_id } context 'user validators' do let(:coding_horror) { Fabricate(:coding_horror) } let(:user) { Fabricate(:user) } let(:invite) { Invite.create(email: user.email, invited_by: coding_horror) } it "should not allow an invite with the same email as an existing user" do invite.should_not be_valid end it "should not allow a user to invite themselves" do invite.email_already_exists.should be_true end end context '#create' do context 'saved' do subject { Fabricate(:invite) } its(:invite_key) { should be_present } its(:email_already_exists) { should be_false } it 'should store a lower case version of the email' do subject.email.should == "iceking@adventuretime.ooo" end end context 'to a topic' do let!(:topic) { Fabricate(:topic) } let(:inviter) { topic.user } context 'email' do it 'enqueues a job to email the invite' do Jobs.expects(:enqueue).with(:invite_email, has_key(:invite_id)) topic.invite_by_email(inviter, 'iceking@adventuretime.ooo') end end context 'destroyed' do it "can invite the same user after their invite was destroyed" do invite = topic.invite_by_email(inviter, 'iceking@adventuretime.ooo') invite.destroy invite = topic.invite_by_email(inviter, 'iceking@adventuretime.ooo') invite.should be_present end end context 'after created' do before do @invite = topic.invite_by_email(inviter, 'iceking@adventuretime.ooo') end it 'belongs to the topic' do topic.invites.should == [@invite] end it 'has a topic' do @invite.topics.should == [topic] end it 'is pending in the invite list for the creator' do InvitedList.new(inviter).pending.should == [@invite] end context 'when added by another user' do let(:coding_horror) { Fabricate(:coding_horror) } let(:new_invite) { topic.invite_by_email(coding_horror, 'iceking@adventuretime.ooo') } it 'returns a different invite' do new_invite.should_not == @invite end it 'has a different key' do new_invite.invite_key.should_not == @invite.invite_key end it 'has the topic relationship' do new_invite.topics.should == [topic] end end context 'when adding a duplicate' do it 'returns the original invite' do topic.invite_by_email(inviter, 'iceking@adventuretime.ooo').should == @invite end it 'matches case insensitively' do topic.invite_by_email(inviter, 'ICEKING@adventuretime.ooo').should == @invite end end context 'when adding to another topic' do let!(:another_topic) { Fabricate(:topic, user: topic.user) } before do @new_invite = another_topic.invite_by_email(inviter, 'iceking@adventuretime.ooo') end it 'should be the same invite' do @new_invite.should == @invite end it 'belongs to the new topic' do another_topic.invites.should == [@invite] end it 'has references to both topics' do @invite.topics.should =~ [topic, another_topic] end end end end end context 'an existing user' do let(:topic) { Fabricate(:topic, archetype: Archetype.private_message) } let(:coding_horror) { Fabricate(:coding_horror) } let!(:invite) { topic.invite_by_email(topic.user, coding_horror.email) } it "doesn't create an invite" do invite.should be_blank end it "gives the user permission to access the topic" do topic.allowed_users.include?(coding_horror).should be_true end end context '.redeem' do let(:invite) { Fabricate(:invite) } it 'creates a notification for the invitee' do lambda { invite.redeem }.should change(Notification, :count) end it 'wont redeem an expired invite' do SiteSetting.expects(:invite_expiry_days).returns(10) invite.update_column(:created_at, 20.days.ago) invite.redeem.should be_blank end it 'wont redeem a deleted invite' do invite.destroy invite.redeem.should be_blank end context 'invite trust levels' do it "returns the trust level in default_invitee_trust_level" do SiteSetting.stubs(:default_invitee_trust_level).returns(TrustLevel.Levels[:experienced]) invite.redeem.trust_level.should == TrustLevel.Levels[:experienced] end end context 'simple invite' do let!(:user) { invite.redeem } it 'returns a user record' do user.is_a?(User).should be_true end it 'wants us to send a welcome message' do user.send_welcome_message.should be_true end it 'has the default_invitee_trust_level' do user.trust_level.should == SiteSetting.default_invitee_trust_level end context 'after redeeming' do before do invite.reload end it 'no longer in the pending list for that user' do InvitedList.new(invite.invited_by).pending.should be_blank end it 'is redeeemed in the invite list for the creator' do InvitedList.new(invite.invited_by).redeemed.should == [invite] end it 'has set the user_id attribute' do invite.user.should == user end it 'returns true for redeemed' do invite.should be_redeemed end context 'again' do it 'will not redeem twice' do invite.redeem.should == user end it "doesn't want us to send a welcome message" do invite.redeem.send_welcome_message.should be_false end end end end context 'invited to topics' do let!(:topic) { Fabricate(:private_message_topic) } let!(:invite) { topic.invite(topic.user, 'jake@adventuretime.ooo')} context 'redeem topic invite' do let!(:user) { invite.redeem } it 'adds the user to the topic_users' do topic.allowed_users.include?(user).should be_true end it 'can see the private topic' do Guardian.new(user).can_see?(topic).should be_true end end context 'invited by another user to the same topic' do let(:coding_horror) { User.where(username: 'CodingHorror').first } let!(:another_invite) { topic.invite(coding_horror, 'jake@adventuretime.ooo') } let!(:user) { invite.redeem } it 'adds the user to the topic_users' do topic.allowed_users.include?(user).should be_true end end context 'invited by another user to a different topic' do let(:coding_horror) { User.where(username: 'CodingHorror').first } let(:another_topic) { Fabricate(:topic, archetype: "private_message", user: coding_horror) } let!(:another_invite) { another_topic.invite(coding_horror, 'jake@adventuretime.ooo') } let!(:user) { invite.redeem } it 'adds the user to the topic_users of the first topic' do topic.allowed_users.include?(user).should be_true end it 'adds the user to the topic_users of the second topic' do another_topic.allowed_users.include?(user).should be_true end it 'does not redeem the second invite' do another_invite.reload another_invite.should_not be_redeemed end context 'if they redeem the other invite afterwards' do before do @result = another_invite.redeem end it 'returns the same user' do @result.should == user end it 'marks the second invite as redeemed' do another_invite.reload another_invite.should be_redeemed end end end end end end