+ <%= labelled_check_box _("Allow other users to follow me"), 'profile_data[allow_followers]', true, @profile.allow_followers?, :class => "person-can-be-followed" %>
+
<% if profile.person? %>
-
+
<%= labelled_radio_button _('Public — show my contents to all internet users').html_safe, 'profile_data[public_profile]', true, @profile.public_profile? %>
diff --git a/app/views/profile_editor/index.html.erb b/app/views/profile_editor/index.html.erb
index 9c99687..17378f9 100644
--- a/app/views/profile_editor/index.html.erb
+++ b/app/views/profile_editor/index.html.erb
@@ -72,6 +72,11 @@
<%= control_panel_button(_('Email Templates'), 'email-templates', :controller => :profile_email_templates) if profile.organization? %>
+ <% if profile.person? %>
+ <%= control_panel_button(_('Manage followed profiles'), 'edit-profile', :controller => :followers) %>
+ <%= control_panel_button(_('Manage circles'), 'edit-profile-group', :controller => :circles) %>
+ <% end %>
+
<% @plugins.dispatch(:control_panel_buttons).each do |button| %>
<%= control_panel_button(button[:title], button[:icon], button[:url], button[:html_options]) %>
<% end %>
diff --git a/config/initializers/action_tracker.rb b/config/initializers/action_tracker.rb
index 7080775..9bfcfa3 100644
--- a/config/initializers/action_tracker.rb
+++ b/config/initializers/action_tracker.rb
@@ -12,6 +12,10 @@ ActionTrackerConfig.verbs = {
type: :groupable
},
+ new_follower: {
+ type: :groupable
+ },
+
join_community: {
type: :groupable
},
diff --git a/db/migrate/20160608123748_create_profile_followers_table.rb b/db/migrate/20160608123748_create_profile_followers_table.rb
new file mode 100644
index 0000000..94d5332
--- /dev/null
+++ b/db/migrate/20160608123748_create_profile_followers_table.rb
@@ -0,0 +1,42 @@
+class CreateProfileFollowersTable < ActiveRecord::Migration
+ def up
+ create_table :profiles_circles do |t|
+ t.column :profile_id, :integer
+ t.column :circle_id, :integer
+ t.timestamps
+ end
+
+ create_table :circles do |t|
+ t.column :name, :string
+ t.belongs_to :person
+ t.column :profile_type, :string, :null => false
+ end
+
+ add_foreign_key :profiles_circles, :circles, :on_delete => :nullify
+
+ add_index :profiles_circles, [:profile_id, :circle_id], :name => "profiles_circles_composite_key_index", :unique => true
+ add_index :circles, [:person_id, :name], :name => "circles_composite_key_index", :unique => true
+
+ #insert one category for each friend group a person has
+ execute("INSERT INTO circles(name, person_id, profile_type) SELECT DISTINCT (CASE WHEN (f.group IS NULL OR f.group = '') THEN 'friendships' ELSE f.group END), f.person_id, 'Person' FROM friendships as f")
+ #insert 'memberships' category if a person is in a community as a member, moderator or profile admin
+ execute("INSERT INTO circles(name, person_id, profile_type) SELECT DISTINCT 'memberships', ra.accessor_id, 'Community' FROM role_assignments as ra JOIN roles ON ra.role_id = roles.id WHERE roles.name IN ('Member','Moderator','Profile Administrator')")
+ #insert 'favorites' category if a person has any favorited enterprise
+ execute("INSERT INTO circles(name, person_id, profile_type) SELECT DISTINCT 'favorites', person_id, 'Enterprise' FROM favorite_enterprise_people")
+
+ #insert a follower entry for each friend, with the category the same as the friendship group or equals 'friendships'
+ execute("INSERT INTO profiles_circles(profile_id, circle_id) SELECT DISTINCT f.friend_id, c.id FROM friendships as f JOIN circles as c ON f.person_id = c.person_id WHERE c.name = f.group OR c.name = 'friendships'")
+ #insert a follower entry for each favorited enterprise, with the category 'favorites'
+ execute("INSERT INTO profiles_circles(profile_id, circle_id) SELECT DISTINCT f.enterprise_id, c.id FROM favorite_enterprise_people AS f JOIN circles as c ON f.person_id = c.person_id WHERE c.name = 'favorites' ")
+ #insert a follower entry for each community a person participates as a member, moderator or admininstrator
+ execute("INSERT INTO profiles_circles(profile_id, circle_id) SELECT DISTINCT ra.resource_id, c.id FROM role_assignments as ra JOIN roles ON ra.role_id = roles.id JOIN circles as c ON ra.accessor_id = c.person_id WHERE roles.name IN ('Member','Moderator','Profile Administrator') AND c.name = 'memberships'")
+ end
+
+ def down
+ remove_foreign_key :profiles_circles, :circles
+ remove_index :profiles_circles, :name => "profiles_circles_composite_key_index"
+ remove_index :circles, :name => "circles_composite_key_index"
+ drop_table :circles
+ drop_table :profiles_circles
+ end
+end
diff --git a/features/follow_profile.feature b/features/follow_profile.feature
new file mode 100644
index 0000000..b9f420e
--- /dev/null
+++ b/features/follow_profile.feature
@@ -0,0 +1,114 @@
+Feature: follow profile
+ As a noosfero user
+ I want to follow a profile
+ So I can receive notifications from it
+
+ Background:
+ Given the following community
+ | identifier | name |
+ | nightswatch | Nights Watch |
+ And the following users
+ | login |
+ | johnsnow |
+ And the user "johnsnow" has the following circles
+ | name | profile_type |
+ | Family | Person |
+ | Work | Community |
+ | Favorites | Community |
+
+ @selenium
+ Scenario: Common noofero user follow a community
+ Given I am logged in as "johnsnow"
+ When I go to nightswatch's homepage
+ When I follow "Follow"
+ When I check "Work"
+ When I press "Follow"
+ And I wait 1 second
+ Then "johnsnow" should be a follower of "nightswatch" in circle "Work"
+
+ @selenium
+ Scenario: Common noofero user follow a community in more than one circle
+ Given I am logged in as "johnsnow"
+ When I go to nightswatch's homepage
+ When I follow "Follow"
+ When I check "Work"
+ When I check "Favorites"
+ When I press "Follow"
+ And I wait 1 second
+ Then "johnsnow" should be a follower of "nightswatch" in circle "Work"
+ And "johnsnow" should be a follower of "nightswatch" in circle "Favorites"
+
+ @selenium
+ Scenario: No see another profile type circle when following a community
+ Given I am logged in as "johnsnow"
+ When I go to nightswatch's homepage
+ When I follow "Follow"
+ Then I should not see "Family"
+ And I should see "Favorites"
+ And I should see "Work"
+
+ @selenium
+ Scenario: Common noofero user follow a community then cancel the action
+ Given I am logged in as "johnsnow"
+ When I go to nightswatch's homepage
+ When I follow "Follow"
+ When I press "Cancel"
+ And I wait 1 second
+ Then I should not see "Family"
+ And I should not see "Favorites"
+ And I should not see "Work"
+ And I should not see "New Circle"
+ Then "johnsnow" should not be a follower of "nightswatch"
+
+ @selenium
+ Scenario: Common noofero user cancel the circle creation action
+ Given I am logged in as "johnsnow"
+ When I go to nightswatch's homepage
+ When I follow "Follow"
+ When I follow "New Circle"
+ When I press "Cancel"
+ And I wait 1 second
+ Then I should not see "Circle name"
+ And I should not see "Create"
+
+ @selenium
+ Scenario: Noosfero user see new circle option when following a community
+ Given I am logged in as "johnsnow"
+ When I go to nightswatch's homepage
+ When I follow "Follow"
+ Then I should see "New Circle"
+
+ @selenium
+ Scenario: Common noofero user follow a community with a new circle
+ Given I am logged in as "johnsnow"
+ When I go to nightswatch's homepage
+ When I follow "Follow"
+ When I follow "New Circle"
+ And I fill in "text-field-name-new-circle" with "Winterfell"
+ When I follow "Create"
+ When I check "Winterfell"
+ When I press "Follow"
+ And I wait 1 second
+ Then "johnsnow" should be a follower of "nightswatch" in circle "Winterfell"
+
+ @selenium
+ Scenario: Common noofero user create a new circle when following a community
+ Given I am logged in as "johnsnow"
+ When I go to nightswatch's homepage
+ When I follow "Follow"
+ When I follow "New Circle"
+ And I fill in "text-field-name-new-circle" with "Winterfell"
+ When I follow "Create"
+ And I wait 1 second
+ Then "johnsnow" should have the circle "Winterfell" with profile type "Community"
+ Then I should not see "Circle name"
+ Then I should not see "Create"
+
+ @selenium
+ Scenario: Common noofero user unfollow a community
+ Given "johnsnow" is a follower of "nightswatch" in circle "Work"
+ And I am logged in as "johnsnow"
+ When I go to nightswatch's homepage
+ When I follow "Unfollow"
+ Then "johnsnow" should not be a follower of "nightswatch"
+
diff --git a/features/step_definitions/followers_steps.rb b/features/step_definitions/followers_steps.rb
new file mode 100644
index 0000000..86aef1f
--- /dev/null
+++ b/features/step_definitions/followers_steps.rb
@@ -0,0 +1,35 @@
+Given /^the user "(.+)" has the following circles$/ do |user_name,table|
+ person = User.find_by(:login => user_name).person
+ table.hashes.each do |circle|
+ Circle.create!(:person => person, :name => circle[:name], :profile_type => circle[:profile_type])
+ end
+end
+
+Then /^"(.+)" should be a follower of "(.+)" in circle "(.+)"$/ do |person, profile, circle|
+ profile = Profile.find_by(identifier: profile)
+ followers = profile.followers
+ person = Person.find_by(identifier: person)
+ followers.should include(person)
+
+ circle = Circle.find_by(:name => circle, :person => person)
+ ProfileFollower.find_by(:circle => circle, :profile => profile).should_not == nil
+end
+
+Then /^"(.+)" should not be a follower of "(.+)"$/ do |person, profile|
+ profile = Profile.find_by(identifier: profile)
+ followers = profile.followers
+ person = Person.find_by(identifier: person)
+ followers.should_not include(person)
+end
+
+Given /^"(.+)" is a follower of "(.+)" in circle "(.+)"$/ do |person, profile, circle|
+ profile = Profile.find_by(identifier: profile)
+ person = Person.find_by(identifier: person)
+ circle = Circle.find_by(:name => circle, :person => person)
+ ProfileFollower.create!(:circle => circle, :profile => profile)
+end
+
+Then /^"(.+)" should have the circle "(.+)" with profile type "(.+)"$/ do |user_name, circle, profile_type|
+ person = User.find_by(:login => user_name).person
+ Circle.find_by(:name => circle, :person => person, :profile_type => profile_type).should_not == nil
+end
diff --git a/public/javascripts/application.js b/public/javascripts/application.js
index fff7e9b..d9c7db4 100644
--- a/public/javascripts/application.js
+++ b/public/javascripts/application.js
@@ -26,6 +26,8 @@
*= require pagination.js
* views speficics
*= require add-and-join.js
+*= require followers.js
+*= require manage-followers.js
*= require report-abuse.js
*= require autogrow.js
*= require require_login.js
@@ -550,6 +552,11 @@ function loading_for_button(selector) {
jQuery(selector).css('cursor', 'progress');
}
+function hide_loading_for_button(selector) {
+ selector.css("cursor","");
+ $(".small-loading").remove();
+}
+
function new_qualifier_row(selector, select_qualifiers, delete_button) {
index = jQuery(selector + ' tr').size() - 1;
jQuery(selector).append("
" + select_qualifiers + "
" + delete_button + "
");
diff --git a/public/javascripts/followers.js b/public/javascripts/followers.js
new file mode 100644
index 0000000..fb69c35
--- /dev/null
+++ b/public/javascripts/followers.js
@@ -0,0 +1,81 @@
+$("#action-follow").live("click", function() {
+ var button = $(this);
+ var url = button.attr("href");
+ loading_for_button(button);
+
+ $.post(url, function(data) {
+ button.fadeOut("fast", function() {
+ $("#circles-container").html(data);
+ $("#circles-container").fadeIn();
+ });
+ }).always(function() {
+ hide_loading_for_button(button);
+ });
+ return false;
+});
+
+$("#cancel-set-circle").live("click", function() {
+ $("#circles-container").fadeOut("fast", function() {
+ $("#action-follow").fadeIn();
+ });
+ return false;
+});
+
+$("#new-circle").live("click", function() {
+ $(this).fadeOut();
+ $("#circle-actions").fadeOut("fast", function() {
+ $("#new-circle-form").fadeIn();
+ });
+ return false;
+});
+
+$("#new-circle-cancel").live("click", function() {
+ $("#new-circle-form").fadeOut("fast", function() {
+ $("#circle-actions").fadeIn();
+ $("#new-circle").fadeIn();
+ $("#text-field-name-new-circle").val('')
+ });
+ return false;
+});
+
+$('#follow-circles-form').live("submit", function() {
+ var valuesToSubmit = $(this).serialize();
+ $.ajax({
+ type: "POST",
+ url: $(this).attr('action'),
+ data: valuesToSubmit,
+ dataType: "JSON",
+ statusCode: {
+ 200: function(response){
+ $("#circles-container").fadeOut();
+ $("#action-unfollow").fadeIn();
+ $.colorbox.close();
+ display_notice(response.responseText);
+ },
+ 400: function(response) {
+ display_notice(response.responseText);
+ }
+ }
+ })
+ return false;
+});
+
+$("#new-circle-submit").live("click", function() {
+ $.ajax({
+ method: 'POST',
+ url: $(this).attr("href"),
+ data: {'circle[name]': $("#text-field-name-new-circle").val(),
+ 'circle[profile_type]': $("#circle_profile_type").val()},
+ success: function(response) {
+ $('#circles-checkboxes').append(response);
+ },
+ error: function(response) {
+ display_notice(response.responseText);
+ },
+ complete: function(response) {
+ $("#text-field-name-new-circle").val('')
+ $("#new-circle-cancel").trigger("click");
+ }
+ })
+ return false;
+});
diff --git a/public/javascripts/manage-followers.js b/public/javascripts/manage-followers.js
new file mode 100644
index 0000000..f01e72f
--- /dev/null
+++ b/public/javascripts/manage-followers.js
@@ -0,0 +1,9 @@
+$('#profile-type-filter').live('change', function() {
+ var filter_type = $(this).val();
+ $(".profile-list").addClass("fetching");
+ $.get(window.location.pathname, {filter: filter_type}, function(data) {
+ $(".main-content").html(data);
+ }).fail(function(data) {
+ $(".profile-list").removeClass("fetching");
+ });
+});
diff --git a/public/stylesheets/blocks/profile-info.scss b/public/stylesheets/blocks/profile-info.scss
index 80fd7f0..1ff89ca 100644
--- a/public/stylesheets/blocks/profile-info.scss
+++ b/public/stylesheets/blocks/profile-info.scss
@@ -99,3 +99,44 @@
margin: 0px 0px 5px 0px;
padding: 2px;
}
+#circles-container {
+ background-color: #eee;
+ padding: 5px;
+ display: flex;
+}
+#circles-container p {
+ font-size: 12px;
+ margin-bottom: 5px;
+}
+#circle-actions {
+ margin-top: 15px;
+}
+#new-category-field-actions-block {
+ float: left;
+ width: 80%;
+ margin-bottom: 10px;
+}
+#new-circle-form {
+ margin-top: 10px;
+}
+#new-circle-form input {
+ width: 90px;
+}
+#new-circle-form select {
+ margin-top: 2px;
+ width: 95px;
+}
+#new-circle-form label {
+ font-size: 10px;
+ margin-right: 5px;
+}
+#new-circle-form .button-bar {
+ padding-top: 0px;
+}
+#new-circle-form .button {
+ width: 60px;
+}
+#new-circle-form .button-bar .button {
+ width: 40px;
+ font-size: 10px;
+}
diff --git a/public/stylesheets/profile-activity.scss b/public/stylesheets/profile-activity.scss
index 91848a1..6163fe1 100644
--- a/public/stylesheets/profile-activity.scss
+++ b/public/stylesheets/profile-activity.scss
@@ -167,7 +167,9 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img {
#profile-wall li.profile-activity-item.join_community .profile-activity-text a img,
#profile-wall li.profile-activity-item.new_friendship .profile-activity-text a img,
+#profile-wall li.profile-activity-item.new_follower .profile-activity-text a img,
#profile-network li.profile-activity-item.join_community .profile-activity-text a img,
+#profile-network li.profile-activity-item.new_follower .profile-activity-text a img,
#profile-network li.profile-activity-item.new_friendship .profile-activity-text a img {
margin: 5px 5px 0 0;
padding: 1px;
diff --git a/public/stylesheets/profile-editor.scss b/public/stylesheets/profile-editor.scss
index d0ac0b9..ea49c89 100644
--- a/public/stylesheets/profile-editor.scss
+++ b/public/stylesheets/profile-editor.scss
@@ -263,3 +263,6 @@
-webkit-border-radius: 5px;
}
+#profile_allow_follows {
+ margin-top: 10px;
+}
diff --git a/public/stylesheets/profile-list.scss b/public/stylesheets/profile-list.scss
index cbd9bc1..3458bb9 100644
--- a/public/stylesheets/profile-list.scss
+++ b/public/stylesheets/profile-list.scss
@@ -23,6 +23,7 @@
}
.controller-favorite_enterprises .profile-list a.profile-link,
.controller-friends .profile-list a.profile-link,
+.controller-followers .profile-list a.profile-link,
.list-profile-connections .profile-list a.profile-link,
.profiles-suggestions .profile-list a.profile-link {
text-decoration: none;
@@ -32,11 +33,13 @@
}
.controller-favorite_enterprises .profile-list a.profile-link:hover,
.controller-friends .profile-list a.profile-link:hover,
+.controller-followers .profile-list a.profile-link:hover,
.profiles-suggestions .profile-list a.profile-link:hover {
color: #FFF;
}
.controller-favorite_enterprises .profile-list .profile_link span,
.controller-friends .profile-list .profile_link span,
+.controller-followers .profile-list .profile_link span,
.box-1 .profiles-suggestions .profile-list .profile_link span {
width: 80px;
display: block;
@@ -44,12 +47,14 @@
}
.controller-favorite_enterprises .profile-list,
.controller-friends .profile-list,
+.controller-followers .profile-list,
.profiles-suggestions .profile-list {
position: relative;
}
.controller-favorite_enterprises .profile-list .controll,
.controller-friends .profile-list .controll,
+.controller-followers .profile-list .controll,
.profiles-suggestions .profile-list .controll {
position: absolute;
top: 7px;
@@ -57,17 +62,20 @@
}
.controller-favorite_enterprises .profile-list .controll a,
.controller-friends .profile-list .controll a,
+.controller-followers .profile-list .controll a,
.profiles-suggestions .profile-list .controll a {
display: block;
margin-bottom: 2px;
}
.controller-favorite_enterprises .msie6 .profile-list .controll a,
.controller-friends .msie6 .profile-list .controll a,
+.controller-folloed_people .msie6 .profile-list .controll a,
.profiles-suggestions .msie6 .profile-list .controll a {
width: 0px;
}
.controller-favorite_enterprises .button-bar,
.controller-friends .button-bar,
+.controller-followers .button-bar,
.profiles-suggestions .button-bar {
clear: both;
padding-top: 20px;
@@ -208,22 +216,35 @@
font-size: 12px;
}
.action-profile-members .profile_link{
- position: relative;
+ position: relative;
}
.action-profile-members .profile_link span.new-profile:last-child{
- position: absolute;
- top: 3px;
- right: 2px;
- text-transform: uppercase;
- color: #FFF;
- font-size: 9px;
- background: #66CC33;
- padding: 2px;
- display: block;
- width: 35px;
- font-weight: 700;
+ position: absolute;
+ top: 3px;
+ right: 2px;
+ text-transform: uppercase;
+ color: #FFF;
+ font-size: 9px;
+ background: #66CC33;
+ padding: 2px;
+ display: block;
+ width: 35px;
+ font-weight: 700;
}
.action-profile-members .profile_link .fn{
- font-style: normal;
- color: #000;
+ font-style: normal;
+ color: #000;
+}
+.category-name {
+ margin-top: 0px;
+ margin-bottom: 0px;
+ font-style: italic;
+ color: #888a85;
+ text-align: center;
+}
+.set-category-modal {
+ width: 250px;
+}
+.set-category-modal #actions-container {
+ margin-top: 20px
}
diff --git a/public/stylesheets/profile.scss b/public/stylesheets/profile.scss
index 8152e2d..3bdcb10 100644
--- a/public/stylesheets/profile.scss
+++ b/public/stylesheets/profile.scss
@@ -39,3 +39,8 @@
width: 470px;
overflow-x: hidden;
}
+
+#circles-checkboxes {
+ text-align: left;
+ margin-left: 15%;
+}
diff --git a/test/functional/circles_controller_test.rb b/test/functional/circles_controller_test.rb
new file mode 100644
index 0000000..3bd8f40
--- /dev/null
+++ b/test/functional/circles_controller_test.rb
@@ -0,0 +1,129 @@
+require_relative "../test_helper"
+require 'circles_controller'
+
+class CirclesControllerTest < ActionController::TestCase
+
+ def setup
+ @controller = CirclesController.new
+ @person = create_user('person').person
+ login_as(@person.identifier)
+ end
+
+ should 'return all circles of a profile' do
+ circle1 = Circle.create!(:name => "circle1", :person => @person, :profile_type => 'Person')
+ circle2 = Circle.create!(:name => "circle2", :person => @person, :profile_type => 'Person')
+ get :index, :profile => @person.identifier
+
+ assert_equivalent [circle1, circle2], assigns[:circles]
+ end
+
+ should 'initialize an empty circle for creation' do
+ get :new, :profile => @person.identifier
+ assert_nil assigns[:circle].id
+ assert_nil assigns[:circle].name
+ end
+
+ should 'create a new circle' do
+ assert_difference '@person.circles.count' do
+ post :create, :profile => @person.identifier,
+ :circle => { :name => 'circle' , :profile_type => Person.name}
+ end
+ assert_redirected_to :action => :index
+ end
+
+ should 'not create a circle without a name' do
+ assert_no_difference '@person.circles.count' do
+ post :create, :profile => @person.identifier, :circle => { :name => nil }
+ end
+ assert_template :new
+ end
+
+ should 'retrieve an existing circle when editing' do
+ circle = Circle.create!(:name => "circle", :person => @person, :profile_type => 'Person')
+ get :edit, :profile => @person.identifier, :id => circle.id
+ assert_equal circle.name, assigns[:circle].name
+ end
+
+ should 'return 404 when editing a circle that does not exist' do
+ get :edit, :profile => @person.identifier, :id => "nope"
+ assert_response 404
+ end
+
+ should 'update an existing circle' do
+ circle = Circle.create!(:name => "circle", :person => @person, :profile_type => 'Person')
+ post :update, :profile => @person.identifier, :id => circle.id,
+ :circle => { :name => "new name" }
+
+ circle.reload
+ assert_equal "new name", circle.name
+ assert_redirected_to :action => :index
+ end
+
+ should 'not update an existing circle without a name' do
+ circle = Circle.create!(:name => "circle", :person => @person, :profile_type => 'Person')
+ post :update, :profile => @person.identifier, :id => circle.id,
+ :circle => { :name => nil }
+
+ circle.reload
+ assert_equal "circle", circle.name
+ assert_template :edit
+ end
+
+ should 'return 404 when updating a circle that does not exist' do
+ post :update, :profile => @person.identifier, :id => "nope", :name => "new name"
+ assert_response 404
+ end
+
+ should 'destroy an existing circle and update related profiles' do
+ circle = Circle.create!(:name => "circle", :person => @person, :profile_type => 'Person')
+ follower = fast_create(ProfileFollower, :profile_id => fast_create(Person).id,
+ :circle_id => circle.id)
+
+ assert_difference "@person.circles.count", -1 do
+ post :destroy, :profile => @person.identifier, :id => circle.id
+ end
+
+ follower.reload
+ assert_nil follower.circle
+ end
+
+ should 'not destroy an existing circle if action is not post' do
+ circle = Circle.create!(:name => "circle", :person => @person, :profile_type => 'Person')
+
+ assert_no_difference "@person.circles.count" do
+ get :destroy, :profile => @person.identifier, :id => circle.id
+ end
+ assert_response 404
+ end
+
+ should 'return 404 when deleting and circle that does not exist' do
+ get :destroy, :profile => @person.identifier, :id => "nope"
+ assert_response 404
+ end
+
+ should 'return 404 for xhr_create if request is not xhr' do
+ post :xhr_create, :profile => @person.identifier
+ assert_response 404
+ end
+
+ should 'return 400 if not possible to create circle via xhr' do
+ xhr :post, :xhr_create, :profile => @person.identifier,
+ :circle => { :name => 'Invalid Circle' }
+ assert_response 400
+ end
+
+ should 'create a new circle via xhr' do
+ xhr :post, :xhr_create, :profile => @person.identifier,
+ :circle => { :name => 'A Brand New Circle',
+ :profile_type => Person.name }
+ assert_response 201
+ assert_match /A Brand New Circle/, response.body
+ end
+
+ should 'not create a new circle via xhr with an invalid profile_type' do
+ xhr :post, :xhr_create, :profile => @person.identifier,
+ :circle => { :name => 'A Brand New Circle',
+ :profile_type => '__invalid__' }
+ assert_response 400
+ end
+end
diff --git a/test/functional/followers_controller_test.rb b/test/functional/followers_controller_test.rb
new file mode 100644
index 0000000..fbe0278
--- /dev/null
+++ b/test/functional/followers_controller_test.rb
@@ -0,0 +1,58 @@
+require_relative "../test_helper"
+require 'followers_controller'
+
+class FollowersControllerTest < ActionController::TestCase
+ def setup
+ @profile = create_user('testuser').person
+ end
+
+ should 'return followed people list' do
+ login_as(@profile.identifier)
+ person = fast_create(Person)
+ circle = Circle.create!(:person=> @profile, :name => "Zombies", :profile_type => 'Person')
+ fast_create(ProfileFollower, :profile_id => person.id, :circle_id => circle.id)
+
+ get :index, :profile => @profile.identifier
+ assert_includes assigns(:followed_people), person
+ end
+
+ should 'return filtered followed people list' do
+ login_as(@profile.identifier)
+ person = fast_create(Person)
+ community = fast_create(Community)
+ circle = Circle.create!(:person=> @profile, :name => "Zombies", :profile_type => 'Person')
+ circle2 = Circle.create!(:person=> @profile, :name => "Teams", :profile_type => 'Community')
+ fast_create(ProfileFollower, :profile_id => person.id, :circle_id => circle.id)
+ fast_create(ProfileFollower, :profile_id => community.id, :circle_id => circle2.id)
+
+ get :index, :profile => @profile.identifier, :filter => "Community"
+ assert_equal assigns(:followed_people), [community]
+
+ get :index, :profile => @profile.identifier, :filter => "Person"
+ assert_equal assigns(:followed_people), [person]
+ end
+
+ should 'redirect to login page if not logged in' do
+ get :index, :profile => @profile.identifier
+ assert_redirected_to :controller => 'account', :action => 'login'
+ end
+
+ should 'render set category modal' do
+ login_as(@profile.identifier)
+ person = fast_create(Person)
+ get :set_category_modal, :profile => @profile.identifier, :followed_profile_id => person.id
+ assert_tag :tag => "input", :attributes => { :id => "followed_profile_id", :value => person.id }
+ end
+
+ should 'update followed person category' do
+ login_as(@profile.identifier)
+ person = fast_create(Person)
+ circle = Circle.create!(:person=> @profile, :name => "Zombies", :profile_type => 'Person')
+ circle2 = Circle.create!(:person=> @profile, :name => "DotA", :profile_type => 'Person')
+ fast_create(ProfileFollower, :profile_id => person.id, :circle_id => circle.id)
+
+ post :update_category, :profile => @profile.identifier, :circles => {"DotA"=> circle2.id}, :followed_profile_id => person.id
+ assert_equivalent ProfileFollower.with_profile(person).with_follower(@profile).map(&:circle), [circle2]
+ end
+
+end
diff --git a/test/functional/profile_controller_test.rb b/test/functional/profile_controller_test.rb
index 57da6e0..808b063 100644
--- a/test/functional/profile_controller_test.rb
+++ b/test/functional/profile_controller_test.rb
@@ -771,12 +771,15 @@ class ProfileControllerTest < ActionController::TestCase
assert_equal 15, assigns(:activities).size
end
- should 'not see the friends activities in the current profile' do
+ should 'not see the followers activities in the current profile' do
+ circle = Circle.create!(:person=> profile, :name => "Zombies", :profile_type => 'Person')
+
p2 = create_user.person
- refute profile.is_a_friend?(p2)
+ refute profile.follows?(p2)
p3 = create_user.person
- p3.add_friend(profile)
- assert p3.is_a_friend?(profile)
+ profile.follow(p3, circle)
+ assert profile.follows?(p3)
+
ActionTracker::Record.destroy_all
scrap1 = create(Scrap, defaults_for_scrap(:sender => p2, :receiver => p3))
@@ -964,7 +967,11 @@ class ProfileControllerTest < ActionController::TestCase
should 'have activities defined if logged in and is following profile' do
login_as(profile.identifier)
p1= fast_create(Person)
- p1.add_friend(profile)
+
+ circle = Circle.create!(:person=> profile, :name => "Zombies", :profile_type => 'Person')
+
+ profile.follow(p1, circle)
+
ActionTracker::Record.destroy_all
get :index, :profile => p1.identifier
assert_equal [], assigns(:activities)
@@ -1932,4 +1939,110 @@ class ProfileControllerTest < ActionController::TestCase
assert_redirected_to :controller => 'account', :action => 'login'
end
+ should 'not follow a user without defining a circle' do
+ login_as(@profile.identifier)
+ person = fast_create(Person)
+ assert_no_difference 'ProfileFollower.count' do
+ post :follow, :profile => person.identifier, :circles => {}
+ end
+ end
+
+ should "not follow user if not logged" do
+ person = fast_create(Person)
+ get :follow, :profile => person.identifier
+
+ assert_redirected_to :controller => 'account', :action => 'login'
+ end
+
+ should 'follow a user with a circle' do
+ login_as(@profile.identifier)
+ person = fast_create(Person)
+
+ circle = Circle.create!(:person=> @profile, :name => "Zombies", :profile_type => 'Person')
+
+ assert_difference 'ProfileFollower.count' do
+ post :follow, :profile => person.identifier, :circles => {"Zombies" => circle.id}
+ end
+ end
+
+ should 'follow a user with more than one circle' do
+ login_as(@profile.identifier)
+ person = fast_create(Person)
+
+ circle = Circle.create!(:person=> @profile, :name => "Zombies", :profile_type => 'Person')
+ circle2 = Circle.create!(:person=> @profile, :name => "Brainsss", :profile_type => 'Person')
+
+ assert_difference 'ProfileFollower.count', 2 do
+ post :follow, :profile => person.identifier, :circles => {"Zombies" => circle.id, "Brainsss"=> circle2.id}
+ end
+ end
+
+ should 'not follow a user with no circle selected' do
+ login_as(@profile.identifier)
+ person = fast_create(Person)
+
+ circle = Circle.create!(:person=> @profile, :name => "Zombies", :profile_type => 'Person')
+ circle2 = Circle.create!(:person=> @profile, :name => "Brainsss", :profile_type => 'Person')
+
+ assert_no_difference 'ProfileFollower.count' do
+ post :follow, :profile => person.identifier, :circles => {"Zombies" => "0", "Brainsss" => "0"}
+ end
+
+ assert_match /Select at least one circle to follow/, response.body
+ end
+
+ should 'not follow if current_person already follows the person' do
+ login_as(@profile.identifier)
+ person = fast_create(Person)
+
+ circle = Circle.create!(:person=> @profile, :name => "Zombies", :profile_type => 'Person')
+ fast_create(ProfileFollower, :profile_id => person.id, :circle_id => circle.id)
+
+ assert_no_difference 'ProfileFollower.count' do
+ post :follow, :profile => person.identifier, :follow => { :circles => {"Zombies" => circle.id} }
+ end
+ assert_response 400
+ end
+
+ should "not unfollow user if not logged" do
+ person = fast_create(Person)
+ get :unfollow, :profile => person.identifier
+
+ assert_redirected_to :controller => 'account', :action => 'login'
+ end
+
+ should "unfollow a followed person" do
+ login_as(@profile.identifier)
+ person = fast_create(Person)
+
+ circle = Circle.create!(:person=> @profile, :name => "Zombies", :profile_type => 'Person')
+ follower = fast_create(ProfileFollower, :profile_id => person.id, :circle_id => circle.id)
+
+ assert_not_nil follower
+
+ get :unfollow, :profile => person.identifier
+ follower = ProfileFollower.find_by(:profile_id => person.id, :circle_id => circle.id)
+ assert_nil follower
+ end
+
+ should "not unfollow a not followed person" do
+ login_as(@profile.identifier)
+ person = fast_create(Person)
+
+ assert_no_difference 'ProfileFollower.count' do
+ get :unfollow, :profile => person.identifier
+ end
+ end
+
+ should "redirect to page after unfollow" do
+ login_as(@profile.identifier)
+ person = fast_create(Person)
+
+ circle = Circle.create!(:person=> @profile, :name => "Zombies", :profile_type => 'Person')
+ fast_create(ProfileFollower, :profile_id => person.id, :circle_id => circle.id)
+
+ get :unfollow, :profile => person.identifier, :redirect_to => "/some/url"
+ assert_redirected_to "/some/url"
+ end
+
end
diff --git a/test/unit/article_test.rb b/test/unit/article_test.rb
index 68cb57f..82a4fdf 100644
--- a/test/unit/article_test.rb
+++ b/test/unit/article_test.rb
@@ -1099,9 +1099,10 @@ class ArticleTest < ActiveSupport::TestCase
assert_equal 3, ActionTrackerNotification.where(action_tracker_id: second_activity.id).count
end
- should 'create notifications to friends when creating an article' do
+ should 'create notifications to followers when creating an article' do
friend = fast_create(Person)
- profile.add_friend(friend)
+ circle = Circle.create!(:person=> friend, :name => "Zombies", :profile_type => 'Person')
+ friend.follow(profile, circle)
Article.destroy_all
ActionTracker::Record.destroy_all
ActionTrackerNotification.destroy_all
@@ -1112,9 +1113,10 @@ class ArticleTest < ActiveSupport::TestCase
assert_equal friend, ActionTrackerNotification.last.profile
end
- should 'create the notification to the friend when one friend has the notification and the other no' do
+ should 'create the notification to the follower when one follower has the notification and the other no' do
f1 = fast_create(Person)
- profile.add_friend(f1)
+ circle = Circle.create!(:person=> f1, :name => "Zombies", :profile_type => 'Person')
+ f1.follow(profile, circle)
User.current = profile.user
article = create TinyMceArticle, :name => 'Tracked Article 1', :profile_id => profile.id
@@ -1123,16 +1125,22 @@ class ArticleTest < ActiveSupport::TestCase
assert_equal 2, ActionTrackerNotification.where(action_tracker_id: article.activity.id).count
f2 = fast_create(Person)
- profile.add_friend(f2)
+ circle2 = Circle.create!(:person=> f2, :name => "Zombies", :profile_type => 'Person')
+ f2.follow(profile, circle2)
+
article2 = create TinyMceArticle, :name => 'Tracked Article 2', :profile_id => profile.id
assert_equal 2, ActionTracker::Record.where(verb: 'create_article').count
process_delayed_job_queue
assert_equal 3, ActionTrackerNotification.where(action_tracker_id: article2.activity.id).count
end
- should 'destroy activity and notifications of friends when destroying an article' do
+ should 'destroy activity and notifications of followers when destroying an article' do
friend = fast_create(Person)
- profile.add_friend(friend)
+
+ circle = Circle.create!(:person=> friend, :name => "Zombies", :profile_type => 'Person')
+
+ friend.follow(profile, circle)
+
Article.destroy_all
ActionTracker::Record.destroy_all
ActionTrackerNotification.destroy_all
diff --git a/test/unit/friendship_test.rb b/test/unit/friendship_test.rb
index 8ab5729..05778e8 100644
--- a/test/unit/friendship_test.rb
+++ b/test/unit/friendship_test.rb
@@ -28,14 +28,14 @@ class FriendshipTest < ActiveSupport::TestCase
f.person = a
f.friend = b
f.save!
- ta = ActionTracker::Record.last
+ ta = ActionTracker::Record.where(:target_type => "Friendship").last
assert_equal a, ta.user
assert_equal 'b', ta.get_friend_name[0]
f = Friendship.new
f.person = a
f.friend = c
f.save!
- ta = ActionTracker::Record.last
+ ta = ActionTracker::Record.where(:target_type => "Friendship").last
assert_equal a, ta.user
assert_equal 'c', ta.get_friend_name[1]
end
@@ -46,14 +46,14 @@ class FriendshipTest < ActiveSupport::TestCase
f.person = a
f.friend = b
f.save!
- ta = ActionTracker::Record.last
+ ta = ActionTracker::Record.where(:target_type => "Friendship").last
assert_equal a, ta.user
assert_equal ['b'], ta.get_friend_name
f = Friendship.new
f.person = b
f.friend = a
f.save!
- ta = ActionTracker::Record.last
+ ta = ActionTracker::Record.where(:target_type => "Friendship").last
assert_equal b, ta.user
assert_equal ['a'], ta.get_friend_name
end
@@ -72,4 +72,55 @@ class FriendshipTest < ActiveSupport::TestCase
assert_not_includes p2.friends(true), p1
end
+ should 'add follower when adding friend' do
+ p1 = create_user('testuser1').person
+ p2 = create_user('testuser2').person
+
+ assert_difference 'ProfileFollower.count', 2 do
+ p1.add_friend(p2, 'friends')
+ p2.add_friend(p1, 'friends')
+ end
+
+ assert_includes p1.followers(true), p2
+ assert_includes p2.followers(true), p1
+ end
+
+ should 'remove follower when a friend removal occurs' do
+ p1 = create_user('testuser1').person
+ p2 = create_user('testuser2').person
+
+ p1.add_friend(p2, 'friends')
+ p2.add_friend(p1, 'friends')
+
+ Friendship.remove_friendship(p1, p2)
+
+ assert_not_includes p1.followers(true), p2
+ assert_not_includes p2.followers(true), p1
+ end
+
+ should 'keep friendship intact when stop following' do
+ p1 = create_user('testuser1').person
+ p2 = create_user('testuser2').person
+
+ p1.add_friend(p2, 'friends')
+ p2.add_friend(p1, 'friends')
+
+ p1.unfollow(p2)
+
+ assert_includes p1.friends(true), p2
+ assert_includes p2.friends(true), p1
+ end
+
+ should 'do not add friendship when start following' do
+ p1 = create_user('testuser1').person
+ p2 = create_user('testuser2').person
+
+ circle1 = Circle.create!(:person=> p1, :name => "Zombies", :profile_type => 'Person')
+ circle2 = Circle.create!(:person=> p2, :name => "Zombies", :profile_type => 'Person')
+ p1.follow(p2, circle1)
+ p2.follow(p1, circle2)
+
+ assert_not_includes p1.friends(true), p2
+ assert_not_includes p2.friends(true), p1
+ end
end
diff --git a/test/unit/notify_activity_to_profiles_job_test.rb b/test/unit/notify_activity_to_profiles_job_test.rb
index 311113d..c0e6ed5 100644
--- a/test/unit/notify_activity_to_profiles_job_test.rb
+++ b/test/unit/notify_activity_to_profiles_job_test.rb
@@ -24,15 +24,21 @@ class NotifyActivityToProfilesJobTest < ActiveSupport::TestCase
end
end
- should 'notify just the users and his friends tracking user actions' do
+ should 'notify just the users and his followers tracking user actions' do
person = fast_create(Person)
community = fast_create(Community)
action_tracker = fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person.id, :target_type => 'Profile', :verb => 'create_article')
refute NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY.include?(action_tracker.verb)
p1, p2, m1, m2 = fast_create(Person), fast_create(Person), fast_create(Person), fast_create(Person)
- fast_create(Friendship, :person_id => person.id, :friend_id => p1.id)
- fast_create(Friendship, :person_id => person.id, :friend_id => p2.id)
- fast_create(Friendship, :person_id => p1.id, :friend_id => m1.id)
+
+ circle1 = Circle.create!(:person=> p1, :name => "Zombies", :profile_type => 'Person')
+ circle2 = Circle.create!(:person=> p2, :name => "Zombies", :profile_type => 'Person')
+ circle = Circle.create!(:person=> person, :name => "Zombies", :profile_type => 'Person')
+
+ fast_create(ProfileFollower, :profile_id => person.id, :circle_id => circle1.id)
+ fast_create(ProfileFollower, :profile_id => person.id, :circle_id => circle2.id)
+ fast_create(ProfileFollower, :profile_id => m1.id, :circle_id => circle.id)
+
fast_create(RoleAssignment, :accessor_id => m2.id, :role_id => 3, :resource_id => community.id)
ActionTrackerNotification.delete_all
job = NotifyActivityToProfilesJob.new(action_tracker.id)
@@ -66,23 +72,24 @@ class NotifyActivityToProfilesJobTest < ActiveSupport::TestCase
end
end
- should 'notify users its friends, the community and its members' do
+ should 'notify users its followers, the community and its members' do
person = fast_create(Person)
community = fast_create(Community)
action_tracker = fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person.id, :target_type => 'Profile', :target_id => community.id, :verb => 'create_article')
refute NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY.include?(action_tracker.verb)
p1, p2, m1, m2 = fast_create(Person), fast_create(Person), fast_create(Person), fast_create(Person)
- fast_create(Friendship, :person_id => person.id, :friend_id => p1.id)
- fast_create(Friendship, :person_id => person.id, :friend_id => p2.id)
+
+ circle1 = Circle.create!(:person=> p1, :name => "Zombies", :profile_type => 'Person')
+ fast_create(ProfileFollower, :profile_id => person.id, :circle_id => circle1.id)
+
fast_create(RoleAssignment, :accessor_id => m1.id, :role_id => 3, :resource_id => community.id)
fast_create(RoleAssignment, :accessor_id => m2.id, :role_id => 3, :resource_id => community.id)
ActionTrackerNotification.delete_all
job = NotifyActivityToProfilesJob.new(action_tracker.id)
job.perform
process_delayed_job_queue
-
- assert_equal 6, ActionTrackerNotification.count
- [person, community, p1, p2, m1, m2].each do |profile|
+ assert_equal 5, ActionTrackerNotification.count
+ [person, community, p1, m1, m2].each do |profile|
notification = ActionTrackerNotification.find_by profile_id: profile.id
assert_equal action_tracker, notification.action_tracker
end
@@ -119,8 +126,13 @@ class NotifyActivityToProfilesJobTest < ActiveSupport::TestCase
action_tracker = fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person.id, :target_type => 'Profile', :target_id => community.id, :verb => 'join_community')
refute NotifyActivityToProfilesJob::NOTIFY_ONLY_COMMUNITY.include?(action_tracker.verb)
p1, p2, m1, m2 = fast_create(Person), fast_create(Person), fast_create(Person), fast_create(Person)
- fast_create(Friendship, :person_id => person.id, :friend_id => p1.id)
- fast_create(Friendship, :person_id => person.id, :friend_id => p2.id)
+
+ circle1 = Circle.create!(:person=> p1, :name => "Zombies", :profile_type => 'Person')
+ circle2 = Circle.create!(:person=> p2, :name => "Zombies", :profile_type => 'Person')
+
+ fast_create(ProfileFollower, :profile_id => person.id, :circle_id => circle1.id)
+ fast_create(ProfileFollower, :profile_id => person.id, :circle_id => circle2.id)
+
fast_create(RoleAssignment, :accessor_id => m1.id, :role_id => 3, :resource_id => community.id)
fast_create(RoleAssignment, :accessor_id => m2.id, :role_id => 3, :resource_id => community.id)
ActionTrackerNotification.delete_all
diff --git a/test/unit/person_notifier_test.rb b/test/unit/person_notifier_test.rb
index 0a37d1e..6b1c4a1 100644
--- a/test/unit/person_notifier_test.rb
+++ b/test/unit/person_notifier_test.rb
@@ -178,6 +178,7 @@ class PersonNotifierTest < ActiveSupport::TestCase
update_product: -> { create Product, profile: @profile, product_category: create(ProductCategory, environment: Environment.default) },
remove_product: -> { create Product, profile: @profile, product_category: create(ProductCategory, environment: Environment.default) },
favorite_enterprise: -> { create FavoriteEnterprisePerson, enterprise: create(Enterprise), person: @member },
+ new_follower: -> { @member }
}
ActionTrackerConfig.verb_names.each do |verb|
@@ -197,6 +198,7 @@ class PersonNotifierTest < ActiveSupport::TestCase
'friend_url' => '/', 'friend_profile_custom_icon' => [], 'friend_name' => ['joe'],
'resource_name' => ['resource'], 'resource_profile_custom_icon' => [], 'resource_url' => ['/'],
'enterprise_name' => 'coop', 'enterprise_url' => '/coop',
+ 'follower_url' => '/', 'follower_profile_custom_icon' => [], 'follower_name' => ['joe'],
'view_url'=> ['/'], 'thumbnail_path' => ['1'],
}
a.get_url = ''
diff --git a/test/unit/person_test.rb b/test/unit/person_test.rb
index 440a8f6..6fbf2a1 100644
--- a/test/unit/person_test.rb
+++ b/test/unit/person_test.rb
@@ -728,7 +728,7 @@ class PersonTest < ActiveSupport::TestCase
assert_equal [s4], p2.scraps_received.not_replies
end
- should "the followed_by method be protected and true to the person friends and herself by default" do
+ should "the followed_by method return true to the person friends and herself by default" do
p1 = fast_create(Person)
p2 = fast_create(Person)
p3 = fast_create(Person)
@@ -740,9 +740,9 @@ class PersonTest < ActiveSupport::TestCase
assert p1.is_a_friend?(p4)
assert_equal true, p1.send(:followed_by?,p1)
- assert_equal true, p1.send(:followed_by?,p2)
- assert_equal true, p1.send(:followed_by?,p4)
- assert_equal false, p1.send(:followed_by?,p3)
+ assert_equal true, p2.send(:followed_by?,p1)
+ assert_equal true, p4.send(:followed_by?,p1)
+ assert_equal false, p3.send(:followed_by?,p1)
end
should "the person follows her friends and herself by default" do
@@ -757,9 +757,9 @@ class PersonTest < ActiveSupport::TestCase
assert p4.is_a_friend?(p1)
assert_equal true, p1.follows?(p1)
- assert_equal true, p1.follows?(p2)
- assert_equal true, p1.follows?(p4)
- assert_equal false, p1.follows?(p3)
+ assert_equal true, p2.follows?(p1)
+ assert_equal true, p4.follows?(p1)
+ assert_equal false, p3.follows?(p1)
end
should "a person member of a community follows the community" do
@@ -836,18 +836,21 @@ class PersonTest < ActiveSupport::TestCase
assert_nil Scrap.find_by(id: scrap.id)
end
- should "the tracked action be notified to person friends and herself" do
+ should "the tracked action be notified to person followers and herself" do
Person.destroy_all
p1 = fast_create(Person)
p2 = fast_create(Person)
p3 = fast_create(Person)
p4 = fast_create(Person)
- p1.add_friend(p2)
- assert p1.is_a_friend?(p2)
- refute p1.is_a_friend?(p3)
- p1.add_friend(p4)
- assert p1.is_a_friend?(p4)
+ circle2 = Circle.create!(:person=> p2, :name => "Zombies", :profile_type => 'Person')
+ circle4 = Circle.create!(:person=> p4, :name => "Zombies", :profile_type => 'Person')
+
+ p2.follow(p1, circle2)
+ assert p2.follows?(p1)
+ refute p3.follows?(p1)
+ p4.follow(p1, circle4)
+ assert p4.follows?(p1)
action_tracker = fast_create(ActionTracker::Record, :user_id => p1.id)
ActionTrackerNotification.delete_all
@@ -880,17 +883,19 @@ class PersonTest < ActiveSupport::TestCase
end
end
- should "the tracked action notify friends with one delayed job process" do
+ should "the tracked action notify followers with one delayed job process" do
p1 = fast_create(Person)
p2 = fast_create(Person)
p3 = fast_create(Person)
p4 = fast_create(Person)
- p1.add_friend(p2)
- assert p1.is_a_friend?(p2)
- refute p1.is_a_friend?(p3)
- p1.add_friend(p4)
- assert p1.is_a_friend?(p4)
+ circle2 = Circle.create!(:person=> p2, :name => "Zombies", :profile_type => 'Person')
+ circle4 = Circle.create!(:person=> p4, :name => "Zombies", :profile_type => 'Person')
+ p2.follow(p1, circle2)
+ assert p2.follows?(p1)
+ refute p3.follows?(p1)
+ p4.follow(p1, circle4)
+ assert p4.follows?(p1)
action_tracker = fast_create(ActionTracker::Record, :user_id => p1.id)
@@ -1035,11 +1040,13 @@ class PersonTest < ActiveSupport::TestCase
p2 = create_user('p2').person
p3 = create_user('p3').person
c = fast_create(Community, :name => "Foo")
+
c.add_member(p1)
process_delayed_job_queue
c.add_member(p3)
process_delayed_job_queue
- assert_equal 4, ActionTracker::Record.count
+
+ assert_equal 5, ActionTracker::Record.count
assert_equal 5, ActionTrackerNotification.count
has_add_member_notification = false
ActionTrackerNotification.all.map do |notification|
@@ -1951,4 +1958,51 @@ class PersonTest < ActiveSupport::TestCase
person.save!
end
+ should 'update profile circles for a person' do
+ person = create_user('testuser').person
+ community = fast_create(Community)
+ circle = Circle.create!(:person=> person, :name => "Zombies", :profile_type => 'Community')
+ circle2 = Circle.create!(:person=> person, :name => "Dota", :profile_type => 'Community')
+ circle3 = Circle.create!(:person=> person, :name => "Quadrado", :profile_type => 'Community')
+ person.follow(community, [circle, circle2])
+ person.update_profile_circles(community, [circle2, circle3])
+ assert_equivalent [circle2, circle3], ProfileFollower.with_profile(community).with_follower(person).map(&:circle)
+ end
+
+ should 'a person follow a profile' do
+ person = create_user('testuser').person
+ community = fast_create(Community)
+ circle = Circle.create!(:person=> person, :name => "Zombies", :profile_type => 'Community')
+ person.follow(community, circle)
+ assert_includes person.followed_profiles, community
+ end
+
+ should 'a person follow a profile with more than one circle' do
+ person = create_user('testuser').person
+ community = fast_create(Community)
+ circle = Circle.create!(:person=> person, :name => "Zombies", :profile_type => 'Community')
+ circle2 = Circle.create!(:person=> person, :name => "Dota", :profile_type => 'Community')
+ person.follow(community, [circle, circle2])
+ assert_includes person.followed_profiles, community
+ assert_equivalent [circle, circle2], ProfileFollower.with_profile(community).with_follower(person).map(&:circle)
+ end
+
+ should 'a person unfollow a profile' do
+ person = create_user('testuser').person
+ community = fast_create(Community)
+ circle = Circle.create!(:person=> person, :name => "Zombies", :profile_type => 'Community')
+ person.follow(community, circle)
+ person.unfollow(community)
+ assert_not_includes person.followed_profiles, community
+ end
+
+ should 'a person remove a profile from a circle' do
+ person = create_user('testuser').person
+ community = fast_create(Community)
+ circle = Circle.create!(:person=> person, :name => "Zombies", :profile_type => 'Community')
+ circle2 = Circle.create!(:person=> person, :name => "Dota", :profile_type => 'Community')
+ person.follow(community, [circle, circle2])
+ person.remove_profile_from_circle(community, circle)
+ assert_equivalent [circle2], ProfileFollower.with_profile(community).with_follower(person).map(&:circle)
+ end
end
diff --git a/test/unit/profile_followers_test.rb b/test/unit/profile_followers_test.rb
new file mode 100644
index 0000000..89684e3
--- /dev/null
+++ b/test/unit/profile_followers_test.rb
@@ -0,0 +1,73 @@
+require_relative "../test_helper"
+
+class ProfileFollowersTest < ActiveSupport::TestCase
+
+ should 'a person follow another' do
+ p1 = create_user('person_test').person
+ p2 = create_user('person_test_2').person
+ circle = Circle.create!(:person=> p1, :name => "Zombies", :profile_type => 'Person')
+
+ assert_difference 'ProfileFollower.count' do
+ p1.follow(p2, circle)
+ end
+
+ assert_includes p2.followers(true), p1
+ assert_not_includes p1.followers(true), p2
+ end
+
+ should 'a person unfollow another person' do
+ p1 = create_user('person_test').person
+ p2 = create_user('person_test_2').person
+ circle = Circle.create!(:person=> p1, :name => "Zombies", :profile_type => 'Person')
+
+ p1.follow(p2,circle)
+
+ assert_difference 'ProfileFollower.count', -1 do
+ p1.unfollow(p2)
+ end
+
+ assert_not_includes p2.followers(true), p1
+ end
+
+ should 'get the followed persons for a profile' do
+ p1 = create_user('person_test').person
+ p2 = create_user('person_test_2').person
+ p3 = create_user('person_test_3').person
+ circle = Circle.create!(:person=> p1, :name => "Zombies", :profile_type => 'Person')
+
+ p1.follow(p2, circle)
+ p1.follow(p3, circle)
+
+ assert_equivalent p1.followed_profiles, [p2,p3]
+ assert_equivalent Profile.followed_by(p1), [p2,p3]
+ end
+
+ should 'not follow same person twice' do
+ p1 = create_user('person_test').person
+ p2 = create_user('person_test_2').person
+ circle = Circle.create!(:person=> p1, :name => "Zombies", :profile_type => 'Person')
+
+ assert_difference 'ProfileFollower.count' do
+ p1.follow(p2, circle)
+ p1.follow(p2, circle)
+ end
+
+ assert_equivalent p1.followed_profiles, [p2]
+ assert_equivalent p2.followers, [p1]
+ end
+
+ should 'show the correct message when a profile is followed by the same person' do
+ p1 = create_user('person_test').person
+ p2 = create_user('person_test_2').person
+ circle = Circle.create!(:person=> p1, :name => "Zombies", :profile_type => 'Person')
+
+ p1.follow(p2, circle)
+ profile_follower = ProfileFollower.new
+ profile_follower.circle = circle
+ profile_follower.profile = p2
+ profile_follower.valid?
+
+ assert_includes profile_follower.errors.messages[:profile_id],
+ "can't put a profile in the same circle twice"
+ end
+end
diff --git a/test/unit/scrap_test.rb b/test/unit/scrap_test.rb
index fb68094..49e5c20 100644
--- a/test/unit/scrap_test.rb
+++ b/test/unit/scrap_test.rb
@@ -125,11 +125,11 @@ class ScrapTest < ActiveSupport::TestCase
assert_equal c, ta.target
end
- should "notify leave_scrap action tracker verb to friends and itself" do
+ should "notify leave_scrap action tracker verb to followers and itself" do
User.current = create_user
p1 = User.current.person
p2 = create_user.person
- p1.add_friend(p2)
+ p2.add_friend(p1)
process_delayed_job_queue
s = Scrap.new
s.sender= p1
@@ -180,11 +180,11 @@ class ScrapTest < ActiveSupport::TestCase
assert_equal p, ta.user
end
- should "notify leave_scrap_to_self action tracker verb to friends and itself" do
+ should "notify leave_scrap_to_self action tracker verb to followers and itself" do
User.current = create_user
p1 = User.current.person
p2 = create_user.person
- p1.add_friend(p2)
+ p2.add_friend(p1)
ActionTrackerNotification.delete_all
Delayed::Job.delete_all
s = Scrap.new
--
libgit2 0.21.2