534 lines
17 KiB
Ruby
534 lines
17 KiB
Ruby
# Copyright (c) 2010-2011, Diaspora Inc. This file is
|
|
# licensed under the Affero General Public License version 3 or later. See
|
|
# the COPYRIGHT file.
|
|
|
|
require 'spec_helper'
|
|
|
|
describe Person do
|
|
|
|
before do
|
|
@user = bob
|
|
@person = Factory.create(:person)
|
|
end
|
|
|
|
it 'always has a profile' do
|
|
Person.new.profile.should_not be_nil
|
|
end
|
|
|
|
it 'does not save automatically' do
|
|
Person.new.persisted?.should be_false
|
|
Person.new.profile.persisted?.should be_false
|
|
end
|
|
|
|
context 'scopes' do
|
|
describe '.for_json' do
|
|
it 'does not select public keys' do
|
|
proc {
|
|
Person.for_json.first.serialized_public_key
|
|
}.should raise_error ActiveModel::MissingAttributeError
|
|
end
|
|
it 'eager loads profiles' do
|
|
Person.for_json.first.loaded_profile?.should be_true
|
|
end
|
|
it 'selects distinct people' do
|
|
aspect = bob.aspects.create(:name => 'hilarious people')
|
|
aspect.contacts << bob.contact_for(eve.person)
|
|
person_ids = Person.for_json.joins(:contacts => :aspect_memberships).
|
|
where(:contacts => {:user_id => bob.id},
|
|
:aspect_memberships => {:aspect_id => bob.aspect_ids}).map{|p| p.id}
|
|
|
|
person_ids.uniq.should == person_ids
|
|
end
|
|
end
|
|
|
|
describe '.local' do
|
|
it 'returns only local people' do
|
|
Person.local =~ [@person]
|
|
end
|
|
end
|
|
|
|
describe '.remote' do
|
|
it 'returns only local people' do
|
|
Person.remote =~ [@user.person]
|
|
end
|
|
end
|
|
|
|
describe '.find_person_from_id_or_username' do
|
|
it 'searchs for a person if id is passed' do
|
|
Person.find_from_id_or_username(:id => @person.id).id.should == @person.id
|
|
end
|
|
|
|
it 'searchs a person from a user if username is passed' do
|
|
Person.find_from_id_or_username(:username => @user.username).id.should == @user.person.id
|
|
end
|
|
|
|
it 'throws active record not found exceptions if no person is found via id' do
|
|
expect{
|
|
Person.find_from_id_or_username(:id => 213123)
|
|
}.to raise_error ActiveRecord::RecordNotFound
|
|
end
|
|
|
|
it 'throws active record not found exceptions if no person is found via username' do
|
|
expect{
|
|
Person.find_from_id_or_username(:username => 'michael_jackson')
|
|
}.to raise_error ActiveRecord::RecordNotFound
|
|
end
|
|
end
|
|
|
|
describe '.all_from_aspects' do
|
|
it "pulls back the right people given all a user's aspects" do
|
|
aspect_ids = bob.aspects.map(&:id)
|
|
Person.all_from_aspects(aspect_ids, bob).map(&:id).should =~ bob.contacts.includes(:person).map{|c| c.person.id}
|
|
end
|
|
|
|
it "pulls back the right people given a subset of aspects" do
|
|
aspect_ids = bob.aspects.first.id
|
|
Person.all_from_aspects(aspect_ids, bob).map(&:id).should =~ bob.aspects.first.contacts.includes(:person).map{|c| c.person.id}
|
|
end
|
|
|
|
it "respects aspects given a user" do
|
|
aspect_ids = alice.aspects.map(&:id)
|
|
Person.all_from_aspects(aspect_ids, bob).map(&:id).should == []
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "delegating" do
|
|
it "delegates last_name to the profile" do
|
|
@person.last_name.should == @person.profile.last_name
|
|
@person.profile.update_attributes(:last_name => "Heathers")
|
|
@person.reload.last_name.should == "Heathers"
|
|
end
|
|
end
|
|
|
|
describe "vaild url" do
|
|
it 'should allow for https urls' do
|
|
person = Factory.create(:person, :url => "https://example.com")
|
|
person.should be_valid
|
|
end
|
|
|
|
it 'should always return the correct receive url' do
|
|
person = Factory.create(:person, :url => "https://example.com/a/bit/messed/up")
|
|
person.receive_url.should == "https://example.com/receive/users/#{person.guid}/"
|
|
end
|
|
|
|
it 'should allow ports in the url' do
|
|
person = Factory.create(:person, :url => "https://example.com:3000/")
|
|
person.url.should == "https://example.com:3000/"
|
|
end
|
|
end
|
|
|
|
describe '#diaspora_handle' do
|
|
context 'local people' do
|
|
it 'uses the pod config url to set the diaspora_handle' do
|
|
new_person = User.build(:username => "foo123", :email => "foo123@example.com", :password => "password", :password_confirmation => "password").person
|
|
new_person.diaspora_handle.should == "foo123@#{AppConfig[:pod_uri].authority}"
|
|
end
|
|
end
|
|
|
|
context 'remote people' do
|
|
it 'stores the diaspora_handle in the database' do
|
|
@person.diaspora_handle.include?(AppConfig[:pod_uri].host).should be false
|
|
end
|
|
end
|
|
|
|
describe 'validation' do
|
|
it 'is unique' do
|
|
person_two = Factory.build(:person, :diaspora_handle => @person.diaspora_handle)
|
|
person_two.should_not be_valid
|
|
end
|
|
|
|
it 'is case insensitive' do
|
|
person_two = Factory.build(:person, :diaspora_handle => @person.diaspora_handle.upcase)
|
|
person_two.should_not be_valid
|
|
end
|
|
end
|
|
end
|
|
|
|
context '.name_from_attrs' do
|
|
before do
|
|
@person = alice.person
|
|
@profile = @person.profile
|
|
end
|
|
|
|
context 'with only first name' do
|
|
it 'should return their first name for name' do
|
|
Person.name_from_attrs(@profile.first_name, nil, @profile.diaspora_handle).should == @profile.first_name.strip
|
|
end
|
|
end
|
|
|
|
context 'with only last name' do
|
|
it 'should return their last name for name' do
|
|
Person.name_from_attrs(nil, @profile.last_name, @profile.diaspora_handle).should == @profile.last_name.strip
|
|
end
|
|
end
|
|
|
|
context 'with both first and last name' do
|
|
it 'should return their composed name for name' do
|
|
Person.name_from_attrs(@profile.first_name, @profile.last_name, @profile.diaspora_handle).should == "#{@profile.first_name.strip} #{@profile.last_name.strip}"
|
|
end
|
|
end
|
|
|
|
context 'without first nor last name' do
|
|
it 'should display their diaspora handle' do
|
|
Person.name_from_attrs(nil, nil, @profile.diaspora_handle).should == @profile.diaspora_handle
|
|
end
|
|
end
|
|
end
|
|
|
|
describe '#name' do
|
|
it 'calls Person.name_from_attrs' do
|
|
profile = alice.person.profile
|
|
Person.should_receive(:name_from_attrs).with(profile.first_name, profile.last_name, profile.person.diaspora_handle)
|
|
alice.name
|
|
end
|
|
|
|
it "strips endline whitespace" do
|
|
profile = alice.person.profile
|
|
profile.first_name = "maxwell "
|
|
profile.last_name = "salzberg "
|
|
alice.name.should == "maxwell salzberg"
|
|
end
|
|
end
|
|
|
|
describe 'XML' do
|
|
before do
|
|
@xml = @person.to_xml.to_s
|
|
end
|
|
|
|
it 'should serialize to xml' do
|
|
@xml.include?("person").should == true
|
|
end
|
|
|
|
it 'should have a profile in its xml' do
|
|
@xml.include?("first_name").should == true
|
|
|
|
end
|
|
end
|
|
|
|
it '#owns? posts' do
|
|
person_message = Factory.create(:status_message, :author => @person)
|
|
person_two = Factory.create(:person)
|
|
|
|
@person.owns?(person_message).should be true
|
|
person_two.owns?(person_message).should be false
|
|
end
|
|
|
|
describe '#remove_all_traces' do
|
|
before do
|
|
@deleter = Factory(:person)
|
|
@status = Factory.create(:status_message, :author => @deleter)
|
|
@other_status = Factory.create(:status_message, :author => @person)
|
|
end
|
|
|
|
it "deletes all notifications from a person's actions" do
|
|
note = Factory(:notification, :actors => [@deleter], :recipient => @user)
|
|
@deleter.destroy
|
|
Notification.where(:id => note.id).first.should be_nil
|
|
end
|
|
|
|
it "deletes all contacts pointing towards a person" do
|
|
@user.contacts.create(:person => @deleter, :aspects => [@user.aspects.first])
|
|
@deleter.destroy
|
|
@user.contact_for(@deleter).should be_nil
|
|
end
|
|
|
|
it "deletes all of a person's posts upon person deletion" do
|
|
lambda { @deleter.destroy }.should change(Post, :count).by(-1)
|
|
end
|
|
|
|
it "deletes a person's profile" do
|
|
lambda {
|
|
@deleter.destroy
|
|
}.should change(Profile, :count).by(-1)
|
|
end
|
|
|
|
it "deletes a person's comments on person deletion" do
|
|
Factory.create(:comment, :author_id => @deleter.id, :diaspora_handle => @deleter.diaspora_handle, :text => "i love you", :post => @other_status)
|
|
Factory.create(:comment, :author_id => @person.id, :diaspora_handle => @person.diaspora_handle, :text => "you are creepy", :post => @other_status)
|
|
|
|
lambda { @deleter.destroy }.should change(Comment, :count).by(-1)
|
|
end
|
|
end
|
|
|
|
describe "disconnecting" do
|
|
before do
|
|
@user2 = Factory(:user)
|
|
@aspect = @user.aspects.create(:name => "Dudes")
|
|
@aspect2 = @user2.aspects.create(:name => "Abscence of Babes")
|
|
end
|
|
it 'should not delete an orphaned contact' do
|
|
@user.contacts.create(:person => @person, :aspects => [@aspect])
|
|
|
|
lambda { @user.disconnect(@user.contact_for(@person)) }.should_not change(Person, :count)
|
|
end
|
|
|
|
it 'should not delete an un-orphaned contact' do
|
|
@user.contacts.create(:person => @person, :aspects => [@aspect])
|
|
@user2.contacts.create(:person => @person, :aspects => [@aspect2])
|
|
|
|
lambda { @user.disconnect(@user.contact_for(@person)) }.should_not change(Person, :count)
|
|
end
|
|
end
|
|
|
|
describe "#first_name" do
|
|
it 'returns username if first_name is not present in profile' do
|
|
alice.person.profile.update_attributes(:first_name => "")
|
|
alice.person.first_name.should == alice.username
|
|
end
|
|
|
|
it 'returns first word in first_name if first_name is present' do
|
|
alice.person.profile.update_attributes(:first_name => "Alice Smith")
|
|
alice.person.first_name.should == "Alice"
|
|
end
|
|
end
|
|
|
|
describe '.search' do
|
|
before do
|
|
Person.delete_all
|
|
@user = Factory.create(:user_with_aspect)
|
|
user_profile = @user.person.profile
|
|
user_profile.first_name = "aiofj"
|
|
user_profile.last_name = "asdji"
|
|
user_profile.save
|
|
|
|
@robert_grimm = Factory.create(:searchable_person)
|
|
@eugene_weinstein = Factory.create(:searchable_person)
|
|
@yevgeniy_dodis = Factory.create(:searchable_person)
|
|
@casey_grippi = Factory.create(:searchable_person)
|
|
|
|
@robert_grimm.profile.first_name = "Robert"
|
|
@robert_grimm.profile.last_name = "Grimm"
|
|
@robert_grimm.profile.save
|
|
@robert_grimm.reload
|
|
|
|
@eugene_weinstein.profile.first_name = "Eugene"
|
|
@eugene_weinstein.profile.last_name = "Weinstein"
|
|
@eugene_weinstein.profile.save
|
|
@eugene_weinstein.reload
|
|
|
|
@yevgeniy_dodis.profile.first_name = "Yevgeniy"
|
|
@yevgeniy_dodis.profile.last_name = "Dodis"
|
|
@yevgeniy_dodis.profile.save
|
|
@yevgeniy_dodis.reload
|
|
|
|
@casey_grippi.profile.first_name = "Casey"
|
|
@casey_grippi.profile.last_name = "Grippi"
|
|
@casey_grippi.profile.save
|
|
@casey_grippi.reload
|
|
end
|
|
it 'orders results by last name' do
|
|
@robert_grimm.profile.first_name = "AAA"
|
|
@robert_grimm.profile.save!
|
|
|
|
@eugene_weinstein.profile.first_name = "AAA"
|
|
@eugene_weinstein.profile.save!
|
|
|
|
@yevgeniy_dodis.profile.first_name = "AAA"
|
|
@yevgeniy_dodis.profile.save!
|
|
|
|
@casey_grippi.profile.first_name = "AAA"
|
|
@casey_grippi.profile.save!
|
|
|
|
people = Person.search("AAA", @user)
|
|
people.map { |p| p.name }.should == [@yevgeniy_dodis, @robert_grimm, @casey_grippi, @eugene_weinstein].map { |p| p.name }
|
|
end
|
|
|
|
it 'returns nothing on an empty query' do
|
|
people = Person.search("", @user)
|
|
people.should be_empty
|
|
end
|
|
|
|
it 'returns nothing on a one-character query' do
|
|
people = Person.search("i", @user)
|
|
people.should be_empty
|
|
end
|
|
|
|
it 'returns results for partial names' do
|
|
people = Person.search("Eug", @user)
|
|
people.count.should == 1
|
|
people.first.should == @eugene_weinstein
|
|
|
|
people = Person.search("wEi", @user)
|
|
people.count.should == 1
|
|
people.first.should == @eugene_weinstein
|
|
|
|
people = Person.search("gri", @user)
|
|
people.count.should == 2
|
|
people.first.should == @robert_grimm
|
|
people.second.should == @casey_grippi
|
|
end
|
|
|
|
it 'returns results for full names' do
|
|
people = Person.search("Casey Grippi", @user)
|
|
people.count.should == 1
|
|
people.first.should == @casey_grippi
|
|
end
|
|
|
|
it 'only displays searchable people' do
|
|
invisible_person = Factory(:person, :profile => Factory.build(:profile, :searchable => false, :first_name => "johnson"))
|
|
Person.search("johnson", @user).should_not include invisible_person
|
|
Person.search("", @user).should_not include invisible_person
|
|
end
|
|
|
|
it 'returns results for Diaspora handles' do
|
|
people = Person.search(@robert_grimm.diaspora_handle, @user)
|
|
people.should == [@robert_grimm]
|
|
end
|
|
|
|
it "puts the searching user's contacts first" do
|
|
@robert_grimm.profile.first_name = "AAA"
|
|
@robert_grimm.profile.save!
|
|
|
|
@eugene_weinstein.profile.first_name = "AAA"
|
|
@eugene_weinstein.profile.save!
|
|
|
|
@yevgeniy_dodis.profile.first_name = "AAA"
|
|
@yevgeniy_dodis.profile.save!
|
|
|
|
@casey_grippi.profile.first_name = "AAA"
|
|
@casey_grippi.profile.save!
|
|
|
|
@user.contacts.create(:person => @casey_grippi, :aspects => [@user.aspects.first])
|
|
|
|
people = Person.search("AAA", @user)
|
|
people.map { |p| p.name }.should == [@casey_grippi, @yevgeniy_dodis, @robert_grimm, @eugene_weinstein].map { |p| p.name }
|
|
end
|
|
end
|
|
|
|
context 'people finders for webfinger' do
|
|
let(:user) { Factory(:user) }
|
|
let(:person) { Factory(:person) }
|
|
|
|
describe '.by_account_identifier' do
|
|
it 'should find a local users person' do
|
|
p = Person.by_account_identifier(user.diaspora_handle)
|
|
p.should == user.person
|
|
end
|
|
|
|
it 'should find remote users person' do
|
|
p = Person.by_account_identifier(person.diaspora_handle)
|
|
p.should == person
|
|
end
|
|
|
|
it 'should downcase and strip the diaspora_handle' do
|
|
dh_upper = " " + user.diaspora_handle.upcase + " "
|
|
Person.by_account_identifier(dh_upper).should == user.person
|
|
end
|
|
|
|
it "finds a local person with a mixed-case username" do
|
|
user = Factory(:user, :username => "SaMaNtHa")
|
|
person = Person.by_account_identifier(user.person.diaspora_handle)
|
|
person.should == user.person
|
|
end
|
|
|
|
it "is case insensitive" do
|
|
user1 = Factory(:user, :username => "SaMaNtHa")
|
|
person = Person.by_account_identifier(user1.person.diaspora_handle.upcase)
|
|
person.should == user1.person
|
|
end
|
|
|
|
it 'should only find people who are exact matches (1/2)' do
|
|
user = Factory(:user, :username => "SaMaNtHa")
|
|
person = Factory(:person, :diaspora_handle => "tomtom@tom.joindiaspora.com")
|
|
user.person.diaspora_handle = "tom@tom.joindiaspora.com"
|
|
user.person.save
|
|
Person.by_account_identifier("tom@tom.joindiaspora.com").diaspora_handle.should == "tom@tom.joindiaspora.com"
|
|
end
|
|
|
|
it 'should only find people who are exact matches (2/2)' do
|
|
person = Factory(:person, :diaspora_handle => "tomtom@tom.joindiaspora.com")
|
|
person1 = Factory(:person, :diaspora_handle => "tom@tom.joindiaspora.comm")
|
|
f = Person.by_account_identifier("tom@tom.joindiaspora.com")
|
|
f.should be nil
|
|
end
|
|
|
|
|
|
end
|
|
|
|
describe '.local_by_account_identifier' do
|
|
it 'should find local users people' do
|
|
p = Person.local_by_account_identifier(user.diaspora_handle)
|
|
p.should == user.person
|
|
end
|
|
|
|
it 'should not find a remote person' do
|
|
p = Person.local_by_account_identifier(@person.diaspora_handle)
|
|
p.should be nil
|
|
end
|
|
|
|
it 'should call .by_account_identifier' do
|
|
Person.should_receive(:by_account_identifier)
|
|
Person.local_by_account_identifier(@person.diaspora_handle)
|
|
end
|
|
end
|
|
end
|
|
describe '#has_photos?' do
|
|
it 'returns false if the user has no photos' do
|
|
alice.person.has_photos?.should be_false
|
|
end
|
|
|
|
it 'returns true if the user has photos' do
|
|
alice.post(:photo, :user_file => uploaded_photo, :to => alice.aspects.first.id)
|
|
|
|
alice.person.has_photos?.should be_true
|
|
end
|
|
end
|
|
|
|
describe '#as_json' do
|
|
it 'returns a hash representation of a person' do
|
|
@person.as_json.should == {
|
|
:id => @person.id,
|
|
:name => @person.name,
|
|
:avatar => @person.profile.image_url(:thumb_medium),
|
|
:handle => @person.diaspora_handle,
|
|
:url => "/people/#{@person.id}",
|
|
}
|
|
end
|
|
it 'return tags if asked' do
|
|
@person.as_json(:includes => "tags").
|
|
should == @person.as_json.merge(:tags => @person.profile.tags.map { |t| "##{t.name}" })
|
|
end
|
|
end
|
|
|
|
describe '.community_spotlight' do
|
|
describe "when the pod owner hasn't set up any community spotlight members" do
|
|
before do
|
|
@existing_community_spotlight = AppConfig[:community_spotlight]
|
|
AppConfig[:community_spotlight] = nil
|
|
end
|
|
after do
|
|
AppConfig[:community_spotlight] = @existing_community_spotlight
|
|
end
|
|
it "returns an empty array" do
|
|
Person.community_spotlight.should == []
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'updating urls' do
|
|
before do
|
|
@url = "http://new-url.com/"
|
|
end
|
|
|
|
describe '.url_batch_update' do
|
|
it "calls #update_person_url given an array of users and a url" do
|
|
people = [stub.as_null_object, stub.as_null_object, stub.as_null_object]
|
|
people.each do |person|
|
|
person.should_receive(:update_url).with(@url)
|
|
end
|
|
Person.url_batch_update(people, @url)
|
|
end
|
|
end
|
|
|
|
describe '#update_url' do
|
|
it "updates a given person's url" do
|
|
expect {
|
|
alice.person.update_url(@url)
|
|
}.to change {
|
|
alice.person.reload.url
|
|
}.from(anything).to(@url)
|
|
end
|
|
end
|
|
end
|
|
end
|