Commit 841621ab0a17b37c13f2e8f3d9259bbd943c8d0e
Committed by
Joenio Costa
1 parent
3c6a2941
Exists in
master
and in
28 other branches
Improving profile/communities listing and show a profile balloon when trigger is clicked
(ActionItem1587,ActionItem1588)
Showing
29 changed files
with
1225 additions
and
41 deletions
Show diff stats
@@ -0,0 +1,58 @@ | @@ -0,0 +1,58 @@ | ||
1 | +class BrowseController < PublicController | ||
2 | + | ||
3 | + no_design_blocks | ||
4 | + | ||
5 | + FILTERS = %w( | ||
6 | + more_recent | ||
7 | + more_active | ||
8 | + more_popular | ||
9 | + ) | ||
10 | + | ||
11 | + def people | ||
12 | + @filter = filter | ||
13 | + @title = self.filter_description(params[:action] + '_' + @filter ) | ||
14 | + | ||
15 | + @results = @environment.people.send(@filter) | ||
16 | + | ||
17 | + if params[:query].blank? | ||
18 | + @results = @results.paginate(:per_page => 27, :page => params[:page]) | ||
19 | + else | ||
20 | + @results = @results.find_by_contents(params[:query]).paginate(:per_page => 27, :page => params[:page]) | ||
21 | + end | ||
22 | + end | ||
23 | + | ||
24 | + def communities | ||
25 | + @filter = filter | ||
26 | + @title = self.filter_description(params[:action] + '_' + @filter ) | ||
27 | + | ||
28 | + @results = @environment.communities.send(@filter) | ||
29 | + | ||
30 | + if params[:query].blank? | ||
31 | + @results = @results.paginate(:per_page => 27, :page => params[:page]) | ||
32 | + else | ||
33 | + @results = @results.find_by_contents(params[:query]).paginate(:per_page => 27, :page => params[:page]) | ||
34 | + end | ||
35 | + end | ||
36 | + | ||
37 | + protected | ||
38 | + | ||
39 | + def filter | ||
40 | + if FILTERS.include?(params[:filter]) | ||
41 | + params[:filter] | ||
42 | + else | ||
43 | + 'more_recent' | ||
44 | + end | ||
45 | + end | ||
46 | + | ||
47 | + def filter_description(str) | ||
48 | + { | ||
49 | + 'people_more_recent' => _('People more recent'), | ||
50 | + 'people_more_active' => _('People more active'), | ||
51 | + 'people_more_popular' => _('People more popular'), | ||
52 | + 'communities_more_recent' => _('Communities more recent'), | ||
53 | + 'communities_more_active' => _('Communities more active'), | ||
54 | + 'communities_more_popular' => _('Communities more popular'), | ||
55 | + }[str] || str | ||
56 | + end | ||
57 | + | ||
58 | +end |
app/helpers/application_helper.rb
@@ -479,9 +479,38 @@ module ApplicationHelper | @@ -479,9 +479,38 @@ module ApplicationHelper | ||
479 | :class => the_class | 479 | :class => the_class |
480 | end | 480 | end |
481 | 481 | ||
482 | + def links_for_balloon(profile) | ||
483 | + if environment.enabled?(:show_balloon_with_profile_links_when_clicked) | ||
484 | + if profile.kind_of?(Person) | ||
485 | + [ | ||
486 | + {_('Home Page') => url_for(profile.url)}, | ||
487 | + {_('Profile') => url_for(profile.public_profile_url)}, | ||
488 | + {_('Friends') => url_for(:controller => :profile, :action => :friends, :profile => profile.identifier)}, | ||
489 | + {_('Communities') => url_for(:controller => :profile, :action => :communities, :profile => profile.identifier)} | ||
490 | + ] | ||
491 | + elsif profile.kind_of?(Community) | ||
492 | + [ | ||
493 | + {_('Home Page') => url_for(profile.url)}, | ||
494 | + {_('Profile') => url_for(profile.public_profile_url)}, | ||
495 | + {_('Members') => url_for(:controller => :profile, :action => :members, :profile => profile.identifier)}, | ||
496 | + {_('Agenda') => url_for(:controller => :profile, :action => :events, :profile => profile.identifier)} | ||
497 | + ] | ||
498 | + elsif profile.kind_of?(Enterprise) | ||
499 | + [ | ||
500 | + {_('Home Page') => url_for(profile.url)}, | ||
501 | + {_('Products') => catalog_path(profile.identifier)}, | ||
502 | + {_('Members') => url_for(:controller => :profile, :action => :members, :profile => profile.identifier)}, | ||
503 | + {_('Agenda') => url_for(:controller => :profile, :action => :events, :profile => profile.identifier)} | ||
504 | + ] | ||
505 | + else | ||
506 | + [] | ||
507 | + end | ||
508 | + end | ||
509 | + end | ||
510 | + | ||
482 | # displays a link to the profile homepage with its image (as generated by | 511 | # displays a link to the profile homepage with its image (as generated by |
483 | # #profile_image) and its name below it. | 512 | # #profile_image) and its name below it. |
484 | - def profile_image_link( profile, size=:portrait, tag='li' ) | 513 | + def profile_image_link( profile, size=:portrait, tag='li', extra_info = nil ) |
485 | if profile.class == Person | 514 | if profile.class == Person |
486 | name = profile.short_name | 515 | name = profile.short_name |
487 | city = content_tag 'span', content_tag( 'span', profile.city, :class => 'locality' ), :class => 'adr' | 516 | city = content_tag 'span', content_tag( 'span', profile.city, :class => 'locality' ), :class => 'adr' |
@@ -489,11 +518,14 @@ module ApplicationHelper | @@ -489,11 +518,14 @@ module ApplicationHelper | ||
489 | name = profile.short_name | 518 | name = profile.short_name |
490 | city = '' | 519 | city = '' |
491 | end | 520 | end |
521 | + extra_info = extra_info.nil? ? '' : content_tag( 'span', extra_info, :class => 'extra_info' ) | ||
522 | + links = links_for_balloon(profile) | ||
492 | content_tag tag, | 523 | content_tag tag, |
524 | + (environment.enabled?(:show_balloon_with_profile_links_when_clicked) ? link_to( content_tag( 'span', _('Profile links')), '#', :onclick => "toggleSubmenu(this, '#{profile.short_name}', #{links.to_json}); return false", :class => 'menu-submenu-trigger' ) : "") + | ||
493 | link_to( | 525 | link_to( |
494 | content_tag( 'span', profile_image( profile, size ), :class => 'profile-image' ) + | 526 | content_tag( 'span', profile_image( profile, size ), :class => 'profile-image' ) + |
495 | content_tag( 'span', h(name), :class => ( profile.class == Person ? 'fn' : 'org' ) ) + | 527 | content_tag( 'span', h(name), :class => ( profile.class == Person ? 'fn' : 'org' ) ) + |
496 | - city + profile_sex_icon( profile ) + profile_cat_icons( profile ), | 528 | + city + extra_info + profile_sex_icon( profile ) + profile_cat_icons( profile ), |
497 | profile.url, | 529 | profile.url, |
498 | :onclick => 'document.location.href = this.href', # work-arround for ie. | 530 | :onclick => 'document.location.href = this.href', # work-arround for ie. |
499 | :class => 'profile_link url', | 531 | :class => 'profile_link url', |
@@ -1019,4 +1051,34 @@ module ApplicationHelper | @@ -1019,4 +1051,34 @@ module ApplicationHelper | ||
1019 | ") : '') | 1051 | ") : '') |
1020 | end | 1052 | end |
1021 | 1053 | ||
1054 | + def browse_people_menu | ||
1055 | + links = [ | ||
1056 | + {_('More Recent') => url_for({:controller => 'browse', :action => 'people', :filter => 'more_recent'})}, | ||
1057 | + {_('More Active') => url_for({:controller => 'browse', :action => 'people', :filter => 'more_active'})}, | ||
1058 | + {_('More Popular') => url_for({:controller => 'browse', :action => 'people', :filter => 'more_popular'})} | ||
1059 | + ] | ||
1060 | + if logged_in? | ||
1061 | + links.push(_('My friends') => url_for({:profile => current_user.login, :controller => 'friends'})) | ||
1062 | + links.push(_('Invite friends') => url_for({:profile => current_user.login, :controller => 'invite', :action => 'friends'})) | ||
1063 | + end | ||
1064 | + | ||
1065 | + link_to(content_tag(:span, _('People'), :class => 'icon-menu-people'), {:controller => "browse", :action => 'people'}, :id => 'submenu-people') + | ||
1066 | + link_to(content_tag(:span, _('People Menu')), '#', :onclick => "toggleSubmenu(this,'',#{links.to_json})", :class => 'menu-submenu-trigger up', :id => 'submenu-people-trigger') | ||
1067 | + end | ||
1068 | + | ||
1069 | + def browse_communities_menu | ||
1070 | + links = [ | ||
1071 | + {_('More Recent') => url_for({:controller => 'browse', :action => 'communities', :filter => 'more_recent'})}, | ||
1072 | + {_('More Active') => url_for({:controller => 'browse', :action => 'communities', :filter => 'more_active'})}, | ||
1073 | + {_('More Popular') => url_for({:controller => 'browse', :action => 'communities', :filter => 'more_popular'})} | ||
1074 | + ] | ||
1075 | + if logged_in? | ||
1076 | + links.push(_('My communities') => url_for({:profile => current_user.login, :controller => 'memberships'})) | ||
1077 | + links.push(_('New community') => url_for({:profile => current_user.login, :controller => 'memberships', :action => 'new_community'})) | ||
1078 | + end | ||
1079 | + | ||
1080 | + link_to(content_tag(:span, _('Communities'), :class => 'icon-menu-community'), {:controller => "browse", :action => 'communities'}, :id => 'submenu-communities') + | ||
1081 | + link_to(content_tag(:span, _('Communities Menu')), '#', :onclick => "toggleSubmenu(this,'',#{links.to_json})", :class => 'menu-submenu-trigger up', :id => 'submenu-communities-trigger') | ||
1082 | + end | ||
1083 | + | ||
1022 | end | 1084 | end |
app/models/enterprise.rb
@@ -4,7 +4,7 @@ class Enterprise < Organization | @@ -4,7 +4,7 @@ class Enterprise < Organization | ||
4 | 4 | ||
5 | N_('Enterprise') | 5 | N_('Enterprise') |
6 | 6 | ||
7 | - has_many :products, :dependent => :destroy | 7 | + has_many :products, :dependent => :destroy, :order => 'name ASC' |
8 | 8 | ||
9 | extra_data_for_index :product_categories | 9 | extra_data_for_index :product_categories |
10 | 10 |
app/models/environment.rb
@@ -108,6 +108,7 @@ class Environment < ActiveRecord::Base | @@ -108,6 +108,7 @@ class Environment < ActiveRecord::Base | ||
108 | 'enable_organization_url_change' => _("Allow organizations to change their URL"), | 108 | 'enable_organization_url_change' => _("Allow organizations to change their URL"), |
109 | 'admin_must_approve_new_communities' => _("Admin must approve creation of communities"), | 109 | 'admin_must_approve_new_communities' => _("Admin must approve creation of communities"), |
110 | 'enterprises_are_disabled_when_created' => __('Enterprises are disabled when created'), | 110 | 'enterprises_are_disabled_when_created' => __('Enterprises are disabled when created'), |
111 | + 'show_balloon_with_profile_links_when_clicked' => _('Show a balloon with profile links when a profile image is clicked'), | ||
111 | } | 112 | } |
112 | end | 113 | end |
113 | 114 |
app/models/person.rb
@@ -8,6 +8,12 @@ class Person < Profile | @@ -8,6 +8,12 @@ class Person < Profile | ||
8 | 8 | ||
9 | has_many :requested_tasks, :class_name => 'Task', :foreign_key => :requestor_id, :dependent => :destroy | 9 | has_many :requested_tasks, :class_name => 'Task', :foreign_key => :requestor_id, :dependent => :destroy |
10 | 10 | ||
11 | + named_scope :more_popular, | ||
12 | + :select => "#{Profile.qualified_column_names}, count(friend_id) as total", | ||
13 | + :group => Profile.qualified_column_names, | ||
14 | + :joins => :friendships, | ||
15 | + :order => "total DESC" | ||
16 | + | ||
11 | after_destroy do |person| | 17 | after_destroy do |person| |
12 | Friendship.find(:all, :conditions => { :friend_id => person.id}).each { |friendship| friendship.destroy } | 18 | Friendship.find(:all, :conditions => { :friend_id => person.id}).each { |friendship| friendship.destroy } |
13 | end | 19 | end |
@@ -286,4 +292,13 @@ class Person < Profile | @@ -286,4 +292,13 @@ class Person < Profile | ||
286 | def relationships_cache_key | 292 | def relationships_cache_key |
287 | cache_key + '-profile-relationships' | 293 | cache_key + '-profile-relationships' |
288 | end | 294 | end |
295 | + | ||
296 | + def more_popular_label | ||
297 | + amount = self.friends.count | ||
298 | + { | ||
299 | + 0 => _('none'), | ||
300 | + 1 => _('one friend') | ||
301 | + }[amount] || _("%s friends") % amount | ||
302 | + end | ||
303 | + | ||
289 | end | 304 | end |
app/models/profile.rb
@@ -57,7 +57,23 @@ class Profile < ActiveRecord::Base | @@ -57,7 +57,23 @@ class Profile < ActiveRecord::Base | ||
57 | 57 | ||
58 | acts_as_taggable | 58 | acts_as_taggable |
59 | 59 | ||
60 | + def self.qualified_column_names | ||
61 | + Profile.column_names.map{|n| [Profile.table_name, n].join('.')}.join(',') | ||
62 | + end | ||
63 | + | ||
60 | named_scope :visible, :conditions => { :visible => true } | 64 | named_scope :visible, :conditions => { :visible => true } |
65 | + named_scope :more_recent, :order => "created_at DESC" | ||
66 | + named_scope :more_popular, | ||
67 | + :select => "#{Profile.qualified_column_names}, count(resource_id) as total", | ||
68 | + :group => Profile.qualified_column_names, | ||
69 | + :joins => :role_assignments, | ||
70 | + :order => "total DESC" | ||
71 | + named_scope :more_active, | ||
72 | + :select => "#{Profile.qualified_column_names}, count(articles.id) as total, sum(articles.comments_count) as total_comments", | ||
73 | + :joins => :articles, | ||
74 | + :group => Profile.qualified_column_names, | ||
75 | + :order => "total DESC, total_comments DESC", | ||
76 | + :conditions => ["articles.created_at BETWEEN ? AND ?", 7.days.ago, DateTime.now] | ||
61 | 77 | ||
62 | # FIXME ugly workaround | 78 | # FIXME ugly workaround |
63 | def self.human_attribute_name(attrib) | 79 | def self.human_attribute_name(attrib) |
@@ -675,6 +691,26 @@ private :generate_url, :url_options | @@ -675,6 +691,26 @@ private :generate_url, :url_options | ||
675 | cache_key + '-members-page-' + page | 691 | cache_key + '-members-page-' + page |
676 | end | 692 | end |
677 | 693 | ||
694 | + def more_recent_label | ||
695 | + _("Since: ") | ||
696 | + end | ||
697 | + | ||
698 | + def more_active_label | ||
699 | + amount = self.articles.count | ||
700 | + { | ||
701 | + 0 => _('none'), | ||
702 | + 1 => _('one article') | ||
703 | + }[amount] || _("%s articles") % amount | ||
704 | + end | ||
705 | + | ||
706 | + def more_popular_label | ||
707 | + amount = self.members.count | ||
708 | + { | ||
709 | + 0 => _('none'), | ||
710 | + 1 => _('one member') | ||
711 | + }[amount] || _("%s members") % amount | ||
712 | + end | ||
713 | + | ||
678 | protected | 714 | protected |
679 | 715 | ||
680 | def display_private_info_to?(user) | 716 | def display_private_info_to?(user) |
@@ -684,4 +720,5 @@ private :generate_url, :url_options | @@ -684,4 +720,5 @@ private :generate_url, :url_options | ||
684 | (user == self) || (user.is_admin?(self.environment)) || user.is_admin?(self) || user.memberships.include?(self) | 720 | (user == self) || (user.is_admin?(self.environment)) || user.is_admin?(self) || user.memberships.include?(self) |
685 | end | 721 | end |
686 | end | 722 | end |
723 | + | ||
687 | end | 724 | end |
@@ -0,0 +1,19 @@ | @@ -0,0 +1,19 @@ | ||
1 | +<div id="browse-results"> | ||
2 | + | ||
3 | + <div class='browse-results-innerbox'> | ||
4 | + <% if @results.empty? %> | ||
5 | + <div class="browse-results-type-empty"> | ||
6 | + <div> <%= _('None') %> </div> | ||
7 | + </div><!-- end class="browse-results-innerbox" --> | ||
8 | + <% end %> | ||
9 | + <ul class='common-profile-list-block'> | ||
10 | + <% @results.each do |result| %> | ||
11 | + <%= render :partial => partial_for_class(result.class), :locals => {:profile => result} %> | ||
12 | + <% end %> | ||
13 | + </ul> | ||
14 | + <br style='clear: both;'> | ||
15 | + </div> | ||
16 | + | ||
17 | + <br style="clear:both" /> | ||
18 | +</div><!-- end id="browse-results" --> | ||
19 | + |
@@ -0,0 +1 @@ | @@ -0,0 +1 @@ | ||
1 | +<%= profile_image_link profile, :portrait, 'li', @filter == 'more_recent' ? profile.send(@filter + '_label') + show_date(profile.created_at) : profile.send(@filter + '_label') %> |
@@ -0,0 +1,10 @@ | @@ -0,0 +1,10 @@ | ||
1 | +<% form_tag( { :controller => 'browse', :action => action}, :method => 'get', :class => 'search_form' ) do %> | ||
2 | + | ||
3 | + <div class="search-field"> | ||
4 | + <span class="formfield"> | ||
5 | + <%= text_field_tag 'query', @query, :size => 50 %> | ||
6 | + </span> | ||
7 | + <%= submit_button(:search, _('Search')) %> | ||
8 | + </div> | ||
9 | + | ||
10 | +<% end %> |
config/routes.rb
@@ -51,6 +51,10 @@ ActionController::Routing::Routes.draw do |map| | @@ -51,6 +51,10 @@ ActionController::Routing::Routes.draw do |map| | ||
51 | # search | 51 | # search |
52 | map.connect 'search/:action/*category_path', :controller => 'search' | 52 | map.connect 'search/:action/*category_path', :controller => 'search' |
53 | 53 | ||
54 | + # Browse | ||
55 | + map.connect 'browse/:action/:filter', :controller => 'browse' | ||
56 | + map.connect 'browse/:action', :controller => 'browse' | ||
57 | + | ||
54 | # events | 58 | # events |
55 | map.events 'profile/:profile/events_by_day', :controller => 'events', :action => 'events_by_day', :profile => /#{Noosfero.identifier_format}/ | 59 | map.events 'profile/:profile/events_by_day', :controller => 'events', :action => 'events_by_day', :profile => /#{Noosfero.identifier_format}/ |
56 | map.events 'profile/:profile/events/:year/:month/:day', :controller => 'events', :action => 'events', :year => /\d*/, :month => /\d*/, :day => /\d*/, :profile => /#{Noosfero.identifier_format}/ | 60 | map.events 'profile/:profile/events/:year/:month/:day', :controller => 'events', :action => 'events', :year => /\d*/, :month => /\d*/, :day => /\d*/, :profile => /#{Noosfero.identifier_format}/ |
@@ -0,0 +1,62 @@ | @@ -0,0 +1,62 @@ | ||
1 | +Feature: balloon | ||
2 | + I want to view a balloon when mouse clicks on profile trigger | ||
3 | + | ||
4 | + Background: | ||
5 | + Given I am on the homepage | ||
6 | + Given the following users | ||
7 | + | login | name | | ||
8 | + | joaosilva | Joao Silva | | ||
9 | + And the following communities | ||
10 | + | identifier | name | | ||
11 | + | sample | Sample | | ||
12 | + | ||
13 | + @selenium | ||
14 | + Scenario: I should not see trigger if not enabled | ||
15 | + Given the following blocks | ||
16 | + | owner | type | | ||
17 | + | environment | PeopleBlock | | ||
18 | + And feature "show_balloon_with_profile_links_when_clicked" is disabled on environment | ||
19 | + And I go to the homepage | ||
20 | + Then I should not see "Friends" | ||
21 | + | ||
22 | + @selenium | ||
23 | + Scenario: I should not see trigger by default | ||
24 | + Given the following blocks | ||
25 | + | owner | type | | ||
26 | + | environment | PeopleBlock | | ||
27 | + And feature "show_balloon_with_profile_links_when_clicked" is enabled on environment | ||
28 | + And I go to the homepage | ||
29 | + Then I should not see "Friends" | ||
30 | + | ||
31 | + @selenium | ||
32 | + Scenario: I should see balloon when clicked on block trigger | ||
33 | + Given the following blocks | ||
34 | + | owner | type | | ||
35 | + | environment | PeopleBlock | | ||
36 | + And feature "show_balloon_with_profile_links_when_clicked" is enabled on environment | ||
37 | + And I go to the homepage | ||
38 | + When I click ".menu-submenu-trigger" | ||
39 | + Then I should see "Profile" | ||
40 | + And I should see "Friends" | ||
41 | + And I should see "Home Page" | ||
42 | + | ||
43 | + @selenium | ||
44 | + Scenario: I should not see trigger if not enabled on page | ||
45 | + Given feature "show_balloon_with_profile_links_when_clicked" is disabled on environment | ||
46 | + And I go to /assets/communities | ||
47 | + Then I should not see "Members" | ||
48 | + | ||
49 | + @selenium | ||
50 | + Scenario: I should not see trigger by default on page | ||
51 | + Given feature "show_balloon_with_profile_links_when_clicked" is enabled on environment | ||
52 | + And I go to /assets/communities | ||
53 | + Then I should not see "Members" | ||
54 | + | ||
55 | + @selenium | ||
56 | + Scenario: I should see balloon when clicked on page trigger | ||
57 | + Given feature "show_balloon_with_profile_links_when_clicked" is enabled on environment | ||
58 | + And I go to /assets/communities | ||
59 | + When I click ".menu-submenu-trigger" | ||
60 | + Then I should see "Members" | ||
61 | + And I should see "Agenda" | ||
62 | + And I should see "Home Page" |
@@ -0,0 +1,89 @@ | @@ -0,0 +1,89 @@ | ||
1 | +Feature: browse | ||
2 | + As a noosfero visitor | ||
3 | + I want to browse people and communities | ||
4 | + | ||
5 | + Background: | ||
6 | + Given I am on the homepage | ||
7 | + And the following users | ||
8 | + | login | name | | ||
9 | + | joaosilva | Joao Silva | | ||
10 | + | pedrosilva | Pedro Silva | | ||
11 | + | pauloneto | Paulo Neto | | ||
12 | + And the following communities | ||
13 | + | identifier | name | | ||
14 | + | comunity-silva | Community Silva | | ||
15 | + | comunity-neto | Community Neto | | ||
16 | + | ||
17 | + @selenium | ||
18 | + Scenario: Show people browse menu | ||
19 | + Given I should not see "More Recent" | ||
20 | + And I should not see "More Active" | ||
21 | + And I should not see "More Popular" | ||
22 | + When I click "#submenu-people-trigger" | ||
23 | + Then I should see "More Recent" | ||
24 | + And I should see "More Active" | ||
25 | + And I should see "More Popular" | ||
26 | + | ||
27 | + @selenium | ||
28 | + Scenario: People browse menu should add logged information | ||
29 | + Given I am logged in as "joaosilva" | ||
30 | + And I should not see "More Recent" | ||
31 | + And I should not see "More Active" | ||
32 | + And I should not see "More Popular" | ||
33 | + And I should not see "Invite friends" | ||
34 | + And I should not see "My friends" | ||
35 | + When I click "#submenu-people-trigger" | ||
36 | + Then I should see "More Recent" | ||
37 | + And I should see "More Active" | ||
38 | + And I should see "More Popular" | ||
39 | + And I should see "Invite friends" | ||
40 | + And I should see "My friends" | ||
41 | + | ||
42 | + @selenium | ||
43 | + Scenario: Browse people by query | ||
44 | + Given I go to /browse/people | ||
45 | + When I fill in "query" with "Silva" | ||
46 | + And I press "Search" | ||
47 | + Then I should see "Joao Silva" | ||
48 | + And I should see "Pedro Silva" | ||
49 | + And I should not see "Paulo Neto" | ||
50 | + And I should not see "Community Silva" | ||
51 | + And I should not see "Community Neto" | ||
52 | + | ||
53 | + @selenium | ||
54 | + Scenario: Communities browse menu should add logged information | ||
55 | + Given I am logged in as "joaosilva" | ||
56 | + And I am on the homepage | ||
57 | + And I should not see "More Recent" | ||
58 | + And I should not see "More Active" | ||
59 | + And I should not see "More Popular" | ||
60 | + And I should not see "My communities" | ||
61 | + And I should not see "New community" | ||
62 | + When I click "#submenu-communities-trigger" | ||
63 | + Then I should see "More Recent" | ||
64 | + And I should see "More Active" | ||
65 | + And I should see "More Popular" | ||
66 | + And I should see "My communities" | ||
67 | + And I should see "New community" | ||
68 | + | ||
69 | + @selenium | ||
70 | + Scenario: Show communities browse menu | ||
71 | + Given I should not see "More Recent" | ||
72 | + And I should not see "More Active" | ||
73 | + And I should not see "More Popular" | ||
74 | + When I click "#submenu-communities-trigger" | ||
75 | + Then I should see "More Recent" | ||
76 | + And I should see "More Active" | ||
77 | + And I should see "More Popular" | ||
78 | + | ||
79 | + @selenium | ||
80 | + Scenario: Browse communities by query | ||
81 | + Given I go to /browse/communities | ||
82 | + When I fill in "query" with "Silva" | ||
83 | + And I press "Search" | ||
84 | + Then I should see "Community Silva" | ||
85 | + And I should not see "Joao Silva" | ||
86 | + And I should not see "Pedro Silva" | ||
87 | + And I should not see "Paulo Neto" | ||
88 | + And I should not see "Community Neto" | ||
89 | + |
features/manage_products.feature
@@ -17,31 +17,31 @@ Feature: manage products | @@ -17,31 +17,31 @@ Feature: manage products | ||
17 | | Bicycle | | 17 | | Bicycle | |
18 | And the following products | 18 | And the following products |
19 | | owner | category | name | description | | 19 | | owner | category | name | description | |
20 | - | redemoinho | bicycle | Bike 1 | bicycle 1 | | ||
21 | - | redemoinho | bicycle | Bike 2 | bicycle 2 | | ||
22 | - | redemoinho | bicycle | Bike 3 | bicycle 3 | | ||
23 | - | redemoinho | bicycle | Bike 4 | bicycle 4 | | ||
24 | - | redemoinho | bicycle | Bike 5 | bicycle 5 | | ||
25 | - | redemoinho | bicycle | Bike 6 | bicycle 6 | | ||
26 | - | redemoinho | bicycle | Bike 7 | bicycle 7 | | ||
27 | - | redemoinho | bicycle | Bike 8 | bicycle 8 | | ||
28 | - | redemoinho | bicycle | Bike 9 | bicycle 9 | | ||
29 | - | redemoinho | bicycle | Bike 10| bicycle 10 | | ||
30 | - | redemoinho | bicycle | Bike 11| bicycle 11 | | 20 | + | redemoinho | bicycle | Bike A | bicycle 1 | |
21 | + | redemoinho | bicycle | Bike B | bicycle 2 | | ||
22 | + | redemoinho | bicycle | Bike C | bicycle 3 | | ||
23 | + | redemoinho | bicycle | Bike D | bicycle 4 | | ||
24 | + | redemoinho | bicycle | Bike E | bicycle 5 | | ||
25 | + | redemoinho | bicycle | Bike F | bicycle 6 | | ||
26 | + | redemoinho | bicycle | Bike G | bicycle 7 | | ||
27 | + | redemoinho | bicycle | Bike H | bicycle 8 | | ||
28 | + | redemoinho | bicycle | Bike I | bicycle 9 | | ||
29 | + | redemoinho | bicycle | Bike J | bicycle 10 | | ||
30 | + | redemoinho | bicycle | Bike K | bicycle 11 | | ||
31 | When I go to /catalog/redemoinho | 31 | When I go to /catalog/redemoinho |
32 | - Then I should see "Bike 1" | ||
33 | - And I should see "Bike 2" | ||
34 | - And I should see "Bike 3" | ||
35 | - And I should see "Bike 4" | ||
36 | - And I should see "Bike 5" | ||
37 | - And I should see "Bike 6" | ||
38 | - And I should see "Bike 7" | ||
39 | - And I should see "Bike 8" | ||
40 | - And I should see "Bike 9" | ||
41 | - And I should see "Bike 10" | ||
42 | - And I should not see "Bike 11" | 32 | + Then I should see "Bike A" within "#product_list" |
33 | + And I should see "Bike B" within "#product_list" | ||
34 | + And I should see "Bike C" within "#product_list" | ||
35 | + And I should see "Bike D" within "#product_list" | ||
36 | + And I should see "Bike E" within "#product_list" | ||
37 | + And I should see "Bike F" within "#product_list" | ||
38 | + And I should see "Bike G" within "#product_list" | ||
39 | + And I should see "Bike H" within "#product_list" | ||
40 | + And I should see "Bike I" within "#product_list" | ||
41 | + And I should see "Bike J" within "#product_list" | ||
42 | + And I should not see "Bike K" within "#product_list" | ||
43 | When I follow "Next" | 43 | When I follow "Next" |
44 | - Then I should see "Bike 11" | 44 | + Then I should see "Bike K" within "#product_list" |
45 | 45 | ||
46 | Scenario: listing products and services | 46 | Scenario: listing products and services |
47 | Given I am logged in as "joaosilva" | 47 | Given I am logged in as "joaosilva" |
public/designs/themes/base/navigation.rhtml
1 | -<li><a href="/assets/people"><span class='icon-menu-people'><%= _('People') %></span></a></li> | ||
2 | -<li><a href="/assets/communities"><span class='icon-menu-community'><%= _('Communities') %></span></a></li> | ||
3 | -<li><a href="/assets/enterprises"><span class='icon-menu-enterprise'><%= _('Enterprises') %></span></a></li> | ||
4 | -<li><a href="/assets/products"><span class='icon-menu-product'><%= _('Products') %></span></a></li> | 1 | +<li> |
2 | + <%= browse_people_menu %> | ||
3 | +</li> | ||
4 | +<li> | ||
5 | + <%= browse_communities_menu %> | ||
6 | +</li> | ||
5 | <li><a href="/assets/events"><span class='icon-menu-events'><%= _('Events') %></span></a></li> | 7 | <li><a href="/assets/events"><span class='icon-menu-events'><%= _('Events') %></span></a></li> |
public/designs/themes/base/style.css
@@ -201,18 +201,20 @@ body, th, td, input { | @@ -201,18 +201,20 @@ body, th, td, input { | ||
201 | margin: 0px; | 201 | margin: 0px; |
202 | padding: 0px 10px 0px 0px; | 202 | padding: 0px 10px 0px 0px; |
203 | float: right; | 203 | float: right; |
204 | - overflow: hidden; | ||
205 | } | 204 | } |
206 | 205 | ||
207 | #navigation li { | 206 | #navigation li { |
208 | list-style: none; | 207 | list-style: none; |
209 | display: block; | 208 | display: block; |
210 | - height: 54px; | 209 | + height: auto; |
210 | + width: 125px; | ||
211 | float: left; | 211 | float: left; |
212 | - border-left: 1px solid #888a85; | 212 | + text-align: center; |
213 | + position: relative; | ||
213 | } | 214 | } |
214 | 215 | ||
215 | #navigation a { | 216 | #navigation a { |
217 | + border-left: 1px solid #888a85; | ||
216 | display: block; | 218 | display: block; |
217 | font-size: 15px; | 219 | font-size: 15px; |
218 | line-height: 42px; | 220 | line-height: 42px; |
@@ -225,11 +227,71 @@ body, th, td, input { | @@ -225,11 +227,71 @@ body, th, td, input { | ||
225 | } | 227 | } |
226 | 228 | ||
227 | #navigation span { | 229 | #navigation span { |
228 | - padding: 0px 10px 0px 35px; | ||
229 | - background-position: 15px 50%; | 230 | + padding: 0px 0px 0px 30px; |
231 | + background-position: 5px 50%; | ||
230 | background-repeat: no-repeat; | 232 | background-repeat: no-repeat; |
231 | } | 233 | } |
232 | 234 | ||
235 | +#navigation .menu-submenu ul, #navigation .menu-submenu li{ | ||
236 | + float: none; | ||
237 | + text-align: right; | ||
238 | + border-left: 0px; | ||
239 | +} | ||
240 | + | ||
241 | +#navigation .menu-submenu ul{ | ||
242 | + border: 1px solid #888a85; | ||
243 | + border-top: 0px; | ||
244 | + border-left: 0px; | ||
245 | + background-color: #ccc; | ||
246 | + padding-right: 2px; | ||
247 | + height: auto; | ||
248 | + display: block; | ||
249 | +} | ||
250 | + | ||
251 | +#navigation .menu-submenu{ | ||
252 | + bottom: -75px; | ||
253 | + width: 126px; | ||
254 | + top: 0px; | ||
255 | + right: 0px; | ||
256 | + position: relative; | ||
257 | +} | ||
258 | + | ||
259 | +#navigation .menu-submenu a{ | ||
260 | + padding: 4px 5px; | ||
261 | + font-size: 12px; | ||
262 | + line-height: normal; | ||
263 | +} | ||
264 | + | ||
265 | +#navigation .menu-submenu-trigger { | ||
266 | + background: #eee url(/images/down-arrow.png) center center no-repeat; | ||
267 | + border: 0px; | ||
268 | + height: 8px; | ||
269 | + width: 124px; | ||
270 | +} | ||
271 | +#navigation li:hover .menu-submenu-trigger:hover { | ||
272 | + background: #eee url(/images/down-arrow.png) center center no-repeat; | ||
273 | +} | ||
274 | + | ||
275 | +#navigation li:hover .menu-submenu-trigger{ | ||
276 | + display: block; | ||
277 | +} | ||
278 | + | ||
279 | +#navigation li .menu-submenu-trigger{ | ||
280 | + display: none; | ||
281 | +} | ||
282 | + | ||
283 | +#navigation .menu-submenu-header, #navigation .menu-submenu-footer, #navigation .menu-submenu h4{ | ||
284 | + display: none; | ||
285 | +} | ||
286 | + | ||
287 | +#navigation .common-profile-list-block .vcard .menu-submenu-trigger, | ||
288 | +.menu-submenu-trigger { | ||
289 | + left: 1px; | ||
290 | + top: 33px; | ||
291 | + -moz-border-radius: 0px; | ||
292 | + -webkit-border-radius: 0px; | ||
293 | +} | ||
294 | + | ||
233 | /***************************** boxes ********************************/ | 295 | /***************************** boxes ********************************/ |
234 | 296 | ||
235 | .template-default .box-1 { /* Center */ | 297 | .template-default .box-1 { /* Center */ |
@@ -1119,12 +1181,12 @@ hr.pre-posts, hr.sep-posts { | @@ -1119,12 +1181,12 @@ hr.pre-posts, hr.sep-posts { | ||
1119 | /******** controller-friends action-friends-index ********/ | 1181 | /******** controller-friends action-friends-index ********/ |
1120 | 1182 | ||
1121 | .action-friends-index .profile-list li, | 1183 | .action-friends-index .profile-list li, |
1122 | -.common-profile-list-block .vcard a { | 1184 | +.common-profile-list-block .vcard { |
1123 | border: 1px solid transparent; | 1185 | border: 1px solid transparent; |
1124 | } | 1186 | } |
1125 | 1187 | ||
1126 | .action-friends-index .profile-list li:hover, | 1188 | .action-friends-index .profile-list li:hover, |
1127 | -.common-profile-list-block .vcard a:hover { | 1189 | +.common-profile-list-block .vcard:hover { |
1128 | border: 1px solid #CCC; | 1190 | border: 1px solid #CCC; |
1129 | -moz-border-radius: 5px; | 1191 | -moz-border-radius: 5px; |
1130 | -webkit-border-radius: 5px; | 1192 | -webkit-border-radius: 5px; |
@@ -1132,6 +1194,11 @@ hr.pre-posts, hr.sep-posts { | @@ -1132,6 +1194,11 @@ hr.pre-posts, hr.sep-posts { | ||
1132 | text-decoration: none; | 1194 | text-decoration: none; |
1133 | } | 1195 | } |
1134 | 1196 | ||
1197 | +.common-profile-list-block .vcard a, | ||
1198 | +.common-profile-list-block .vcard a:hover { | ||
1199 | + background: transparent; | ||
1200 | + border: 0; | ||
1201 | +} | ||
1135 | 1202 | ||
1136 | /******** controller-profile action-profile-index ********/ | 1203 | /******** controller-profile action-profile-index ********/ |
1137 | 1204 | ||
@@ -1205,4 +1272,56 @@ table.profile th { | @@ -1205,4 +1272,56 @@ table.profile th { | ||
1205 | border-bottom: 2px solid black; | 1272 | border-bottom: 2px solid black; |
1206 | } | 1273 | } |
1207 | 1274 | ||
1275 | +/**************************** Browse *******************************/ | ||
1208 | 1276 | ||
1277 | +.controller-browse #content .search_form { | ||
1278 | + background: #DDD; | ||
1279 | + -moz-border-radius: 5px; | ||
1280 | + -webkit-border-radius: 5px; | ||
1281 | + padding: 12px 15px 13px 15px; | ||
1282 | + position: relative; | ||
1283 | + text-align: left; | ||
1284 | +} | ||
1285 | + | ||
1286 | +.controller-browse a { | ||
1287 | + color: #555753; | ||
1288 | +} | ||
1289 | + | ||
1290 | +.browse-results-innerbox { | ||
1291 | + margin-top: 10px; | ||
1292 | + border-bottom: none; | ||
1293 | + border: 1px solid #CCC; | ||
1294 | + background: url(imgs/comment-bg-S.png) 0% 100% repeat-x; | ||
1295 | + padding-bottom: 10px; | ||
1296 | + | ||
1297 | +} | ||
1298 | +.browse-results-innerbox ul{ | ||
1299 | + padding: 0px; | ||
1300 | +} | ||
1301 | + | ||
1302 | +.browse-results-innerbox .browse-results-type-empty div { | ||
1303 | + text-align: center; | ||
1304 | + color: #DDD; | ||
1305 | + font-weight: bold; | ||
1306 | + font-size: 30px; | ||
1307 | + padding: 70px 10px 0px 0px; | ||
1308 | + border: none; | ||
1309 | + | ||
1310 | +} | ||
1311 | + | ||
1312 | +.search-results-type-article.search-results-innerbox { | ||
1313 | + padding: 5px 0px 5px 10px; | ||
1314 | + max-height: 215px; | ||
1315 | + height: 225px; | ||
1316 | +} | ||
1317 | + | ||
1318 | +#content .search-results-type-article li { | ||
1319 | + padding: 5px 0px; | ||
1320 | +} | ||
1321 | + | ||
1322 | +.search-results-type-article a { | ||
1323 | + text-decoration: none; | ||
1324 | +} | ||
1325 | +.search-results-type-article a:hover { | ||
1326 | + text-decoration: underline; | ||
1327 | +} |
1.91 KB
1.01 KB
267 Bytes
407 Bytes
261 Bytes
public/javascripts/application.js
@@ -214,3 +214,52 @@ function expandCategory(block, id) { | @@ -214,3 +214,52 @@ function expandCategory(block, id) { | ||
214 | } | 214 | } |
215 | } | 215 | } |
216 | } | 216 | } |
217 | + | ||
218 | +function toggleSubmenu(trigger, title, link_list) { | ||
219 | + trigger.onclick = function() { | ||
220 | + var submenu = jQuery(trigger).siblings('.menu-submenu'); | ||
221 | + var hide = false; | ||
222 | + if (submenu.length > 0 && submenu.is(':visible')) hide = true; | ||
223 | + hideAllSubmenus(); | ||
224 | + // Hide or show this submenu if it already exists | ||
225 | + if (submenu.length > 0) { | ||
226 | + if (!hide) { | ||
227 | + var direction = 'down'; | ||
228 | + if (submenu.hasClass('up')) direction = 'up'; | ||
229 | + submenu.show('slide', { 'direction' : direction }, 'slow'); | ||
230 | + } | ||
231 | + } | ||
232 | + return false; | ||
233 | + } | ||
234 | + | ||
235 | + hideAllSubmenus(); | ||
236 | + // Build and show this submenu if it doesn't exist yet | ||
237 | + var direction = 'down'; | ||
238 | + if (jQuery(trigger).hasClass('up')) direction = 'up'; | ||
239 | + var submenu = jQuery('<div></div>').attr('class', 'menu-submenu ' + direction).attr('style', 'display: none'); | ||
240 | + var header = jQuery('<div></div>').attr('class', 'menu-submenu-header'); | ||
241 | + var content = jQuery('<div></div>').attr('class', 'menu-submenu-content'); | ||
242 | + var list = jQuery('<ul></ul>').attr('class', 'menu-submenu-list'); | ||
243 | + var footer = jQuery('<div></div>').attr('class', 'menu-submenu-footer'); | ||
244 | + content.append('<h4>' + title + '</h4>'); | ||
245 | + jQuery.each(link_list, function(index, link_hash) { | ||
246 | + for (label in link_hash) { | ||
247 | + list.append('<li><a href="' + link_hash[label] + '">' + label + '</a></li>'); | ||
248 | + } | ||
249 | + }); | ||
250 | + content.append(list); | ||
251 | + submenu.append(header).append(content).append(footer); | ||
252 | + jQuery(trigger).before(submenu); | ||
253 | + submenu.show('slide', { 'direction' : direction }, 'slow'); | ||
254 | +} | ||
255 | + | ||
256 | +function hideAllSubmenus() { | ||
257 | + jQuery('.menu-submenu.up:visible').hide('slide', { 'direction' : 'up' }, 'slow'); | ||
258 | + jQuery('.menu-submenu.down:visible').hide('slide', { 'direction' : 'down' }, 'slow'); | ||
259 | +} | ||
260 | + | ||
261 | +// Hide visible ballons when clicked outside them | ||
262 | +jQuery(document).ready(function() { | ||
263 | + jQuery('body').click(function() { hideAllSubmenus(); }); | ||
264 | + jQuery('.menu-submenu-trigger').click(function(e) { e.stopPropagation(); }); | ||
265 | +}); |
public/stylesheets/application.css
@@ -1644,13 +1644,13 @@ input.disabled { | @@ -1644,13 +1644,13 @@ input.disabled { | ||
1644 | margin: 0px; | 1644 | margin: 0px; |
1645 | padding: 0px; | 1645 | padding: 0px; |
1646 | list-style: none; | 1646 | list-style: none; |
1647 | - display: inline; | 1647 | + position: relative; |
1648 | } | 1648 | } |
1649 | 1649 | ||
1650 | .common-profile-list-block .vcard a { | 1650 | .common-profile-list-block .vcard a { |
1651 | display: block; | 1651 | display: block; |
1652 | - height: 95px; | ||
1653 | - max-height: 92px; | 1652 | + height: 112px; |
1653 | + max-height: 112px; | ||
1654 | padding-top: 3px; | 1654 | padding-top: 3px; |
1655 | margin: 0px 2px; | 1655 | margin: 0px 2px; |
1656 | float: left; | 1656 | float: left; |
@@ -1738,6 +1738,12 @@ input.disabled { | @@ -1738,6 +1738,12 @@ input.disabled { | ||
1738 | display: none; | 1738 | display: none; |
1739 | } | 1739 | } |
1740 | 1740 | ||
1741 | +.common-profile-list-block .extra_info { | ||
1742 | + font-size: 9px; | ||
1743 | + opacity: 0.5; | ||
1744 | + filter: alpha(opacity=50); | ||
1745 | +} | ||
1746 | + | ||
1741 | 1747 | ||
1742 | /* ==> blocks/recent-documents-block.css <<= */ | 1748 | /* ==> blocks/recent-documents-block.css <<= */ |
1743 | 1749 | ||
@@ -3603,7 +3609,6 @@ h1#agenda-title { | @@ -3603,7 +3609,6 @@ h1#agenda-title { | ||
3603 | border: 1px solid #2A5896; | 3609 | border: 1px solid #2A5896; |
3604 | padding: 10px 0px 10px 10px; | 3610 | padding: 10px 0px 10px 10px; |
3605 | height: 205px; | 3611 | height: 205px; |
3606 | - overflow: auto; | ||
3607 | position: relative; /* work-arround-bug fo MSIE */ | 3612 | position: relative; /* work-arround-bug fo MSIE */ |
3608 | } | 3613 | } |
3609 | 3614 | ||
@@ -3630,6 +3635,7 @@ h1#agenda-title { | @@ -3630,6 +3635,7 @@ h1#agenda-title { | ||
3630 | .controller-search .only-one-result-box .search-results-innerbox, | 3635 | .controller-search .only-one-result-box .search-results-innerbox, |
3631 | .controller-search .only-one-result-box .search-results-innerbox.common-profile-list-block { | 3636 | .controller-search .only-one-result-box .search-results-innerbox.common-profile-list-block { |
3632 | height: auto; | 3637 | height: auto; |
3638 | + float: left; | ||
3633 | padding: 10px 4px 10px 10px; | 3639 | padding: 10px 4px 10px 10px; |
3634 | } | 3640 | } |
3635 | 3641 | ||
@@ -4088,3 +4094,100 @@ h1#agenda-title { | @@ -4088,3 +4094,100 @@ h1#agenda-title { | ||
4088 | .categories-block .ui-icon { | 4094 | .categories-block .ui-icon { |
4089 | margin-top: 2px; | 4095 | margin-top: 2px; |
4090 | } | 4096 | } |
4097 | + | ||
4098 | +/* Profile balloon */ | ||
4099 | + | ||
4100 | +.common-profile-list-block .vcard { | ||
4101 | + position: relative !important; | ||
4102 | + float: left; | ||
4103 | +} | ||
4104 | + | ||
4105 | +.common-profile-list-block .vcard .menu-submenu-trigger, | ||
4106 | +.menu-submenu-trigger { | ||
4107 | + display: none; | ||
4108 | + width: 16px; | ||
4109 | + height: 16px; | ||
4110 | + position: absolute; | ||
4111 | + top: -1px; | ||
4112 | + left: -3px; | ||
4113 | + overflow: hidden; | ||
4114 | + background: #efefef url(/images/top-arrow.png) center center no-repeat; | ||
4115 | + border: 1px solid #ccc; | ||
4116 | + z-index: 2; | ||
4117 | + -moz-border-radius: 5px; | ||
4118 | + -webkit-border-radius: 5px; | ||
4119 | +} | ||
4120 | + | ||
4121 | +.common-profile-list-block .vcard .menu-submenu-trigger:hover, | ||
4122 | +.menu-submenu-trigger:hover { | ||
4123 | + background: #fff url(/images/top-arrow.png) center center no-repeat; | ||
4124 | + border: 1px solid #ccc; | ||
4125 | +} | ||
4126 | + | ||
4127 | +.menu-submenu-trigger span { | ||
4128 | + display: none; | ||
4129 | +} | ||
4130 | + | ||
4131 | +.common-profile-list-block .vcard:hover .menu-submenu-trigger { | ||
4132 | + display: block; | ||
4133 | +} | ||
4134 | + | ||
4135 | +.menu-submenu { | ||
4136 | + position: absolute; | ||
4137 | + bottom: 115px; | ||
4138 | + right: -27px; | ||
4139 | + z-index: 11; | ||
4140 | + width: 150px; | ||
4141 | + padding: 0; | ||
4142 | + text-align: left; | ||
4143 | +} | ||
4144 | + | ||
4145 | +.menu-submenu-footer { | ||
4146 | + background: transparent url(/images/balloon-footer.png) center center no-repeat; | ||
4147 | + height: 29px; | ||
4148 | + margin: 0; | ||
4149 | +} | ||
4150 | + | ||
4151 | +.menu-submenu-header { | ||
4152 | + background: transparent url(/images/balloon-header.png) center center no-repeat; | ||
4153 | + height: 17px; | ||
4154 | + margin: 0; | ||
4155 | +} | ||
4156 | + | ||
4157 | +.menu-submenu-content { | ||
4158 | + background: transparent url(/images/balloon-middle.png) top left repeat-y; | ||
4159 | + margin: 0; | ||
4160 | + padding: 0; | ||
4161 | + width: 100%; | ||
4162 | +} | ||
4163 | + | ||
4164 | +#content .menu-submenu-content ul { | ||
4165 | + margin: 0; | ||
4166 | + padding: 0; | ||
4167 | + width: 100% !important; | ||
4168 | + min-width: 100% !important; | ||
4169 | +} | ||
4170 | + | ||
4171 | +#content .menu-submenu-content ul a { | ||
4172 | + text-align: left; | ||
4173 | + padding-left: 12px; | ||
4174 | +} | ||
4175 | + | ||
4176 | +.common-profile-list-block .vcard .menu-submenu a { | ||
4177 | + float: none; | ||
4178 | + display: block; | ||
4179 | + height: auto; | ||
4180 | + font-size: 12px; | ||
4181 | +} | ||
4182 | + | ||
4183 | +#content .menu-submenu h4 { | ||
4184 | + margin: 0; | ||
4185 | + font-size: 12px; | ||
4186 | + font-weight: bold; | ||
4187 | + text-align: left; | ||
4188 | + margin: 0 auto; | ||
4189 | + padding-bottom: 3px; | ||
4190 | + margin-bottom: 3px; | ||
4191 | + border-bottom: 1px solid #000; | ||
4192 | + width: 90%; | ||
4193 | +} |
@@ -0,0 +1,221 @@ | @@ -0,0 +1,221 @@ | ||
1 | +require File.dirname(__FILE__) + '/../test_helper' | ||
2 | +require 'browse_controller' | ||
3 | + | ||
4 | +# Re-raise errors caught by the controller. | ||
5 | +class BrowseController; def rescue_action(e) raise e end; end | ||
6 | + | ||
7 | +class BrowseControllerTest < Test::Unit::TestCase | ||
8 | + | ||
9 | + def setup | ||
10 | + @controller = BrowseController.new | ||
11 | + @request = ActionController::TestRequest.new | ||
12 | + @request.stubs(:ssl?).returns(false) | ||
13 | + @response = ActionController::TestResponse.new | ||
14 | + | ||
15 | + # By pass user validation on person creation | ||
16 | + user = mock() | ||
17 | + user.stubs(:id).returns(1) | ||
18 | + user.stubs(:valid?).returns(true) | ||
19 | + user.stubs(:email).returns('some@test.com') | ||
20 | + user.stubs(:save!).returns(true) | ||
21 | + Person.any_instance.stubs(:user).returns(user) | ||
22 | + end | ||
23 | + | ||
24 | + should 'search for people' do | ||
25 | + Person.delete_all | ||
26 | + small = create(Person, :name => 'A small person for testing', :user_id => 1) | ||
27 | + create(Person, :name => 'A big person for testing', :user_id => 2) | ||
28 | + | ||
29 | + get :people, :query => 'small' | ||
30 | + assert_equal [small], assigns(:results) | ||
31 | + end | ||
32 | + | ||
33 | + should 'list all people order by more recent one by default' do | ||
34 | + Person.delete_all | ||
35 | + p1 = create(Person, :name => 'Testing person 1', :user_id => 1, :created_at => DateTime.now - 2) | ||
36 | + p2 = create(Person, :name => 'Testing person 2', :user_id => 2, :created_at => DateTime.now - 1) | ||
37 | + p3 = create(Person, :name => 'Testing person 3', :user_id => 3) | ||
38 | + | ||
39 | + get :people | ||
40 | + assert_equal [p3,p2,p1] , assigns(:results) | ||
41 | + end | ||
42 | + | ||
43 | + should 'paginate search of people in groups of 27' do | ||
44 | + Person.delete_all | ||
45 | + | ||
46 | + 1.upto(30).map do |n| | ||
47 | + create(Person, :name => 'Testing person', :user_id => n) | ||
48 | + end | ||
49 | + | ||
50 | + get :people | ||
51 | + assert_equal 30 , Person.count | ||
52 | + assert_equal 27 , assigns(:results).count | ||
53 | + assert_tag :a, '', :attributes => {:class => 'next_page'} | ||
54 | + end | ||
55 | + | ||
56 | + should 'paginate ferret search of people in groups of 27' do | ||
57 | + Person.delete_all | ||
58 | + | ||
59 | + 1.upto(30).map do |n| | ||
60 | + create(Person, :name => 'Testing person', :user_id => n) | ||
61 | + end | ||
62 | + | ||
63 | + get :people, :query => 'Testing' | ||
64 | + assert_equal 27 , assigns(:results).count | ||
65 | + assert_tag :a, '', :attributes => {:class => 'next_page'} | ||
66 | + end | ||
67 | + | ||
68 | + should 'list all people filter by more active' do | ||
69 | + Person.delete_all | ||
70 | + p1 = create(Person, :name => 'Testing person 1', :user_id => 1) | ||
71 | + p2 = create(Person, :name => 'Testing person 2', :user_id => 2) | ||
72 | + p3 = create(Person, :name => 'Testing person 3', :user_id => 3) | ||
73 | + Article.delete_all | ||
74 | + fast_create(Article, :profile_id => p1, :created_at => 1.day.ago) | ||
75 | + fast_create(Article, :profile_id => p2, :created_at => DateTime.now.beginning_of_day) | ||
76 | + get :people, :filter => 'more_active' | ||
77 | + assert_equal [p1,p2] , assigns(:results) | ||
78 | + end | ||
79 | + | ||
80 | + should 'filter more popular people' do | ||
81 | + Person.delete_all | ||
82 | + p1 = create(Person, :name => 'Testing person 1', :user_id => 1) | ||
83 | + p2 = create(Person, :name => 'Testing person 2', :user_id => 2) | ||
84 | + p3 = create(Person, :name => 'Testing person 3', :user_id => 3) | ||
85 | + | ||
86 | + p1.add_friend(p2) | ||
87 | + p2.add_friend(p1) | ||
88 | + p2.add_friend(p3) | ||
89 | + get :people, :filter => 'more_popular' | ||
90 | + assert_equal [p2,p1] , assigns(:results) | ||
91 | + end | ||
92 | + | ||
93 | + should 'the people filter be only the hardcoded one' do | ||
94 | + get :people, :filter => 'more_recent' | ||
95 | + assert_equal 'more_recent' , assigns(:filter) | ||
96 | + | ||
97 | + get :people, :filter => 'more_active' | ||
98 | + assert_equal 'more_active' , assigns(:filter) | ||
99 | + | ||
100 | + get :people, :filter => 'more_popular' | ||
101 | + assert_equal 'more_popular' , assigns(:filter) | ||
102 | + | ||
103 | + get :people, :filter => 'more_anything' | ||
104 | + assert_equal 'more_recent' , assigns(:filter) | ||
105 | + end | ||
106 | + | ||
107 | + should 'the people filter define the title' do | ||
108 | + get :people, :filter => 'more_recent' | ||
109 | + assert_equal 'People more recent' , assigns(:title) | ||
110 | + assert_tag :h1, :content => 'People more recent' | ||
111 | + | ||
112 | + get :people, :filter => 'more_active' | ||
113 | + assert_equal 'People more active' , assigns(:title) | ||
114 | + assert_tag :h1, :content => 'People more active' | ||
115 | + | ||
116 | + get :people, :filter => 'more_popular' | ||
117 | + assert_equal 'People more popular' , assigns(:title) | ||
118 | + assert_tag :h1, :content => 'People more popular' | ||
119 | + | ||
120 | + get :people, :filter => 'more_anything' | ||
121 | + assert_equal 'People more recent' , assigns(:title) | ||
122 | + assert_tag :h1, :content => 'People more recent' | ||
123 | + end | ||
124 | + | ||
125 | + should 'search for community' do | ||
126 | + small = create(Community, :name => 'A small community for testing') | ||
127 | + create(Community, :name => 'A big community for testing') | ||
128 | + | ||
129 | + get :communities, :query => 'small' | ||
130 | + assert_equal [small], assigns(:results) | ||
131 | + end | ||
132 | + | ||
133 | + should 'list all community order by more recent one by default' do | ||
134 | + c1 = create(Community, :name => 'Testing community 1', :created_at => DateTime.now - 2) | ||
135 | + c2 = create(Community, :name => 'Testing community 2', :created_at => DateTime.now - 1) | ||
136 | + c3 = create(Community, :name => 'Testing community 3') | ||
137 | + | ||
138 | + get :communities | ||
139 | + assert_equal [c3,c2,c1] , assigns(:results) | ||
140 | + end | ||
141 | + | ||
142 | + should 'paginate search of communities in groups of 27' do | ||
143 | + 1.upto(30).map do |n| | ||
144 | + create(Community, :name => 'Testing community') | ||
145 | + end | ||
146 | + | ||
147 | + get :communities | ||
148 | + assert_equal 30 , Community.count | ||
149 | + assert_equal 27 , assigns(:results).count | ||
150 | + assert_tag :a, '', :attributes => {:class => 'next_page'} | ||
151 | + end | ||
152 | + | ||
153 | + should 'paginate ferret search of communities in groups of 27' do | ||
154 | + 1.upto(30).map do |n| | ||
155 | + create(Community, :name => 'Testing community') | ||
156 | + end | ||
157 | + | ||
158 | + get :communities, :query => 'Testing' | ||
159 | + assert_equal 27 , assigns(:results).count | ||
160 | + assert_tag :a, '', :attributes => {:class => 'next_page'} | ||
161 | + end | ||
162 | + | ||
163 | + should 'list all communities filter by more active' do | ||
164 | + c1 = create(Community, :name => 'Testing community 1') | ||
165 | + c2 = create(Community, :name => 'Testing community 2') | ||
166 | + c3 = create(Community, :name => 'Testing community 3') | ||
167 | + Article.delete_all | ||
168 | + fast_create(Article, :profile_id => c1, :created_at => 1.day.ago) | ||
169 | + fast_create(Article, :profile_id => c2, :created_at => DateTime.now.beginning_of_day) | ||
170 | + get :communities, :filter => 'more_active' | ||
171 | + assert_equal [c1,c2] , assigns(:results) | ||
172 | + end | ||
173 | + | ||
174 | + should 'filter more popular communities' do | ||
175 | + Person.delete_all | ||
176 | + c1 = create(Community, :name => 'Testing community 1') | ||
177 | + c2 = create(Community, :name => 'Testing community 2') | ||
178 | + create(Community, :name => 'Testing community 3') | ||
179 | + | ||
180 | + p1 = create(Person, :name => 'Testing person 1', :user_id => 1) | ||
181 | + p2 = create(Person, :name => 'Testing person 2', :user_id => 2) | ||
182 | + c1.add_member(p1) | ||
183 | + c2.add_member(p1) | ||
184 | + c2.add_member(p2) | ||
185 | + get :communities, :filter => 'more_popular' | ||
186 | + assert_equal [c2,c1] , assigns(:results) | ||
187 | + end | ||
188 | + | ||
189 | + should 'the communities filter be only the hardcoded one' do | ||
190 | + get :communities, :filter => 'more_recent' | ||
191 | + assert_equal 'more_recent' , assigns(:filter) | ||
192 | + | ||
193 | + get :communities, :filter => 'more_active' | ||
194 | + assert_equal 'more_active' , assigns(:filter) | ||
195 | + | ||
196 | + get :communities, :filter => 'more_popular' | ||
197 | + assert_equal 'more_popular' , assigns(:filter) | ||
198 | + | ||
199 | + get :communities, :filter => 'more_anything' | ||
200 | + assert_equal 'more_recent' , assigns(:filter) | ||
201 | + end | ||
202 | + | ||
203 | + should 'the communities filter define the title' do | ||
204 | + get :communities, :filter => 'more_recent' | ||
205 | + assert_equal 'Communities more recent' , assigns(:title) | ||
206 | + assert_tag :h1, :content => 'Communities more recent' | ||
207 | + | ||
208 | + get :communities, :filter => 'more_active' | ||
209 | + assert_equal 'Communities more active' , assigns(:title) | ||
210 | + assert_tag :h1, :content => 'Communities more active' | ||
211 | + | ||
212 | + get :communities, :filter => 'more_popular' | ||
213 | + assert_equal 'Communities more popular' , assigns(:title) | ||
214 | + assert_tag :h1, :content => 'Communities more popular' | ||
215 | + | ||
216 | + get :communities, :filter => 'more_anything' | ||
217 | + assert_equal 'Communities more recent' , assigns(:title) | ||
218 | + assert_tag :h1, :content => 'Communities more recent' | ||
219 | + end | ||
220 | + | ||
221 | +end |
test/integration/routing_test.rb
@@ -216,4 +216,11 @@ class RoutingTest < ActionController::IntegrationTest | @@ -216,4 +216,11 @@ class RoutingTest < ActionController::IntegrationTest | ||
216 | assert_routing('/doc', :controller => 'doc', :action => 'index') | 216 | assert_routing('/doc', :controller => 'doc', :action => 'index') |
217 | end | 217 | end |
218 | 218 | ||
219 | + # browse controller | ||
220 | + def test_browse_routing | ||
221 | + assert_routing('/browse/people', :controller => 'browse', :action => 'people') | ||
222 | + assert_routing('/browse/people/more_popular', :controller => 'browse', :action => 'people', :filter => 'more_popular') | ||
223 | + assert_routing('/browse/communities', :controller => 'browse', :action => 'communities') | ||
224 | + assert_routing('/browse/communities/more_active', :controller => 'browse', :action => 'communities', :filter => 'more_active') | ||
225 | + end | ||
219 | end | 226 | end |
test/unit/application_helper_test.rb
@@ -567,6 +567,60 @@ class ApplicationHelperTest < Test::Unit::TestCase | @@ -567,6 +567,60 @@ class ApplicationHelperTest < Test::Unit::TestCase | ||
567 | assert_equal environment.theme, current_theme | 567 | assert_equal environment.theme, current_theme |
568 | end | 568 | end |
569 | 569 | ||
570 | + should 'trunc to 15 chars the big filename' do | ||
571 | + assert_equal 'AGENDA(...).mp3', short_filename('AGENDA_CULTURA_-_FESTA_DE_VAQUEIROS_PONTO_DE_SERRA_PRETA_BAIXA.mp3',15) | ||
572 | + end | ||
573 | + | ||
574 | + should 'trunc to default limit the big filename' do | ||
575 | + assert_equal 'AGENDA_CULTURA_-_FESTA_DE_VAQUEIRO(...).mp3', short_filename('AGENDA_CULTURA_-_FESTA_DE_VAQUEIROS_PONTO_DE_SERRA_PRETA_BAIXA.mp3') | ||
576 | + end | ||
577 | + | ||
578 | + should 'does not trunc short filename' do | ||
579 | + assert_equal 'filename.mp3', short_filename('filename.mp3') | ||
580 | + end | ||
581 | + | ||
582 | + should 'return nil when :show_balloon_with_profile_links_when_clicked is not enabled in environment' do | ||
583 | + env = Environment.default | ||
584 | + env.stubs(:enabled?).with(:show_balloon_with_profile_links_when_clicked).returns(false) | ||
585 | + stubs(:environment).returns(env) | ||
586 | + profile = Profile.new | ||
587 | + assert_nil links_for_balloon(profile) | ||
588 | + end | ||
589 | + | ||
590 | + should 'return ordered list of links to balloon to Person' do | ||
591 | + env = Environment.default | ||
592 | + env.stubs(:enabled?).with(:show_balloon_with_profile_links_when_clicked).returns(true) | ||
593 | + stubs(:environment).returns(env) | ||
594 | + person = Person.new | ||
595 | + person.stubs(:url).returns('url for person') | ||
596 | + person.stubs(:public_profile_url).returns('url for person') | ||
597 | + links = links_for_balloon(person) | ||
598 | + assert_equal ['Home Page', 'Profile', 'Friends', 'Communities'], links.map{|i| i.keys.first} | ||
599 | + end | ||
600 | + | ||
601 | + should 'return ordered list of links to balloon to Community' do | ||
602 | + env = Environment.default | ||
603 | + env.stubs(:enabled?).with(:show_balloon_with_profile_links_when_clicked).returns(true) | ||
604 | + stubs(:environment).returns(env) | ||
605 | + community = Community.new | ||
606 | + community.stubs(:url).returns('url for community') | ||
607 | + community.stubs(:public_profile_url).returns('url for community') | ||
608 | + links = links_for_balloon(community) | ||
609 | + assert_equal ['Home Page', 'Profile', 'Members', 'Agenda'], links.map{|i| i.keys.first} | ||
610 | + end | ||
611 | + | ||
612 | + should 'return ordered list of links to balloon to Enterprise' do | ||
613 | + env = Environment.default | ||
614 | + env.stubs(:enabled?).with(:show_balloon_with_profile_links_when_clicked).returns(true) | ||
615 | + stubs(:environment).returns(env) | ||
616 | + enterprise = Enterprise.new | ||
617 | + enterprise.stubs(:url).returns('url for enterprise') | ||
618 | + enterprise.stubs(:public_profile_url).returns('url for enterprise') | ||
619 | + stubs(:catalog_path) | ||
620 | + links = links_for_balloon(enterprise) | ||
621 | + assert_equal ['Home Page', 'Products', 'Members', 'Agenda'], links.map{|i| i.keys.first} | ||
622 | + end | ||
623 | + | ||
570 | protected | 624 | protected |
571 | 625 | ||
572 | def url_for(args = {}) | 626 | def url_for(args = {}) |
test/unit/person_test.rb
@@ -588,4 +588,51 @@ class PersonTest < Test::Unit::TestCase | @@ -588,4 +588,51 @@ class PersonTest < Test::Unit::TestCase | ||
588 | end | 588 | end |
589 | end | 589 | end |
590 | 590 | ||
591 | + should "return none on label if the person hasn't friends" do | ||
592 | + p = fast_create(Person) | ||
593 | + assert_equal 0, p.friends.count | ||
594 | + assert_equal "none", p.more_popular_label | ||
595 | + end | ||
596 | + | ||
597 | + should "return one friend on label if the profile has one member" do | ||
598 | + p1 = fast_create(Person) | ||
599 | + p2 = fast_create(Person) | ||
600 | + p1.add_friend(p2) | ||
601 | + assert_equal 1, p1.friends.count | ||
602 | + assert_equal "one friend", p1.more_popular_label | ||
603 | + end | ||
604 | + | ||
605 | + should "return the number of friends on label if the person has more than one friend" do | ||
606 | + p1 = fast_create(Person) | ||
607 | + p2 = fast_create(Person) | ||
608 | + p3 = fast_create(Person) | ||
609 | + p1.add_friend(p2) | ||
610 | + p1.add_friend(p3) | ||
611 | + assert_equal 2, p1.friends.count | ||
612 | + assert_equal "2 friends", p1.more_popular_label | ||
613 | + | ||
614 | + p4 = fast_create(Person) | ||
615 | + p1.add_friend(p4) | ||
616 | + assert_equal 3, p1.friends.count | ||
617 | + assert_equal "3 friends", p1.more_popular_label | ||
618 | + end | ||
619 | + | ||
620 | + should 'find more popular people' do | ||
621 | + Person.delete_all | ||
622 | + env = fast_create(Environment) | ||
623 | + p1 = fast_create(Person) | ||
624 | + p2 = fast_create(Person) | ||
625 | + p3 = fast_create(Person) | ||
626 | + | ||
627 | + p1.add_friend(p2) | ||
628 | + assert_equal [p1], Person.more_popular | ||
629 | + | ||
630 | + p2.add_friend(p1) | ||
631 | + p2.add_friend(p3) | ||
632 | + assert_equal [p2,p1] , Person.more_popular | ||
633 | + | ||
634 | + p2.remove_friend(p3) | ||
635 | + assert_equal [p1,p2] , Person.more_popular | ||
636 | + end | ||
637 | + | ||
591 | end | 638 | end |
test/unit/profile_test.rb
@@ -1563,6 +1563,212 @@ class ProfileTest < Test::Unit::TestCase | @@ -1563,6 +1563,212 @@ class ProfileTest < Test::Unit::TestCase | ||
1563 | assert_match /<!-- .* --> <h1> Wellformed html code <\/h1>/, profile.custom_footer | 1563 | assert_match /<!-- .* --> <h1> Wellformed html code <\/h1>/, profile.custom_footer |
1564 | end | 1564 | end |
1565 | 1565 | ||
1566 | + should 'find more recent people' do | ||
1567 | + Person.delete_all | ||
1568 | + p1 = fast_create(Person,:created_at => 4.days.ago) | ||
1569 | + p2 = fast_create(Person, :created_at => DateTime.now) | ||
1570 | + p3 = fast_create(Person, :created_at => 2.days.ago) | ||
1571 | + | ||
1572 | + assert_equal [p2,p3,p1] , Person.more_recent | ||
1573 | + | ||
1574 | + p4 = fast_create(Person, :created_at => 3.days.ago) | ||
1575 | + assert_equal [p2,p3,p4,p1] , Person.more_recent | ||
1576 | + end | ||
1577 | + | ||
1578 | + should 'find more active people' do | ||
1579 | + Person.delete_all | ||
1580 | + p1 = fast_create(Person) | ||
1581 | + p2 = fast_create(Person) | ||
1582 | + p3 = fast_create(Person) | ||
1583 | + Article.delete_all | ||
1584 | + fast_create(Article, :profile_id => p1, :created_at => 7.days.ago) | ||
1585 | + fast_create(Article, :profile_id => p1, :created_at => DateTime.now.beginning_of_day) | ||
1586 | + fast_create(Article, :profile_id => p2, :created_at => DateTime.now.beginning_of_day) | ||
1587 | + assert_equal [p1,p2] , Person.more_active | ||
1588 | + | ||
1589 | + fast_create(Article, :profile_id => p2, :created_at => 1.day.ago) | ||
1590 | + fast_create(Article, :profile_id => p2, :created_at => 5.days.ago) | ||
1591 | + fast_create(Article, :profile_id => p3, :created_at => 2.days.ago) | ||
1592 | + assert_equal [p2,p1,p3] , Person.more_active | ||
1593 | + end | ||
1594 | + | ||
1595 | + should 'the ties on more active people be solved by the number of comments' do | ||
1596 | + Person.delete_all | ||
1597 | + p1 = fast_create(Person) | ||
1598 | + p2 = fast_create(Person) | ||
1599 | + Article.delete_all | ||
1600 | + a1 = fast_create(Article, :profile_id => p1, :created_at => DateTime.now.beginning_of_day) | ||
1601 | + a2 = fast_create(Article, :profile_id => p2, :created_at => DateTime.now.beginning_of_day) | ||
1602 | + assert_equal [], [p1,p2] - Person.more_active | ||
1603 | + assert_equal [], Person.more_active - [p1, p2] | ||
1604 | + | ||
1605 | + a2.comments.build(:title => 'test comment', :body => 'anything', :author => p1).save! | ||
1606 | + assert_equal [p2,p1] , Person.more_active | ||
1607 | + | ||
1608 | + a1.comments.build(:title => 'test comment', :body => 'anything', :author => p2).save! | ||
1609 | + a1.comments.build(:title => 'test comment', :body => 'anything', :author => p2).save! | ||
1610 | + assert_equal [p1,p2] , Person.more_active | ||
1611 | + end | ||
1612 | + | ||
1613 | + should 'more active people take in consideration only articles created current the last week' do | ||
1614 | + Person.delete_all | ||
1615 | + env = fast_create(Environment) | ||
1616 | + p1 = fast_create(Person) | ||
1617 | + p2 = fast_create(Person) | ||
1618 | + p3 = fast_create(Person) | ||
1619 | + Article.delete_all | ||
1620 | + fast_create(Article, :profile_id => p1, :created_at => DateTime.now.beginning_of_day) | ||
1621 | + fast_create(Article, :profile_id => p2, :created_at => 10.days.ago) | ||
1622 | + assert_equal [p1] , Person.more_active | ||
1623 | + | ||
1624 | + fast_create(Article, :profile_id => p2, :created_at => DateTime.now.beginning_of_day) | ||
1625 | + fast_create(Article, :profile_id => p2, :created_at => 7.days.ago) | ||
1626 | + fast_create(Article, :profile_id => p3, :created_at => 8.days.ago) | ||
1627 | + assert_equal [p2,p1] , Person.more_active | ||
1628 | + end | ||
1629 | + | ||
1630 | + should 'find more recent community' do | ||
1631 | + c1 = fast_create(Community, :created_at => 3.days.ago) | ||
1632 | + c2 = fast_create(Community, :created_at => 1.day.ago) | ||
1633 | + c3 = fast_create(Community, :created_at => DateTime.now) | ||
1634 | + | ||
1635 | + assert_equal [c3,c2,c1] , Community.more_recent | ||
1636 | + | ||
1637 | + c4 = fast_create(Community, :created_at => 2.days.ago) | ||
1638 | + assert_equal [c3,c2,c4,c1] , Community.more_recent | ||
1639 | + end | ||
1640 | + | ||
1641 | + should 'find more active community' do | ||
1642 | + c1 = fast_create(Community) | ||
1643 | + c2 = fast_create(Community) | ||
1644 | + c3 = fast_create(Community) | ||
1645 | + | ||
1646 | + Article.delete_all | ||
1647 | + fast_create(Article, :profile_id => c1, :created_at => 1.day.ago) | ||
1648 | + fast_create(Article, :profile_id => c1, :created_at => DateTime.now.beginning_of_day) | ||
1649 | + fast_create(Article, :profile_id => c2, :created_at => DateTime.now.beginning_of_day) | ||
1650 | + assert_equal [c1,c2], Community.more_active | ||
1651 | + | ||
1652 | + fast_create(Article, :profile_id => c2, :created_at => 2.days.ago) | ||
1653 | + fast_create(Article, :profile_id => c2, :created_at => 7.days.ago) | ||
1654 | + fast_create(Article, :profile_id => c3, :created_at => 1.day.ago) | ||
1655 | + assert_equal [c2,c1,c3] , Community.more_active | ||
1656 | + end | ||
1657 | + | ||
1658 | + should 'the ties on more active communities be solved by the number of comments' do | ||
1659 | + env = create(Environment) | ||
1660 | + Community.delete_all | ||
1661 | + c1 = fast_create(Community) | ||
1662 | + c2 = fast_create(Community) | ||
1663 | + Article.delete_all | ||
1664 | + a1 = fast_create(Article, :profile_id => c1, :created_at => DateTime.now.beginning_of_day) | ||
1665 | + a2 = fast_create(Article, :profile_id => c2, :created_at => DateTime.now.beginning_of_day) | ||
1666 | + assert_equal [c1,c2] , Community.more_active | ||
1667 | + | ||
1668 | + p1 = fast_create(Person) | ||
1669 | + a2.comments.build(:title => 'test comment', :body => 'anything', :author => p1).save! | ||
1670 | + assert_equal [c2,c1] , Community.more_active | ||
1671 | + | ||
1672 | + a1.comments.build(:title => 'test comment', :body => 'anything', :author => p1).save! | ||
1673 | + a1.comments.build(:title => 'test comment', :body => 'anything', :author => p1).save! | ||
1674 | + assert_equal [c1,c2] , Community.more_active | ||
1675 | + end | ||
1676 | + | ||
1677 | + should 'more active communities take in consideration only articles created current the last week' do | ||
1678 | + c1 = fast_create(Community) | ||
1679 | + c2 = fast_create(Community) | ||
1680 | + c3 = fast_create(Community) | ||
1681 | + Article.delete_all | ||
1682 | + fast_create(Article, :profile_id => c1, :created_at => DateTime.now.beginning_of_day) | ||
1683 | + fast_create(Article, :profile_id => c2, :created_at => 10.days.ago) | ||
1684 | + assert_equal [c1] , Community.more_active | ||
1685 | + | ||
1686 | + fast_create(Article, :profile_id => c2, :created_at => DateTime.now.beginning_of_day) | ||
1687 | + fast_create(Article, :profile_id => c2, :created_at => 7.days.ago) | ||
1688 | + fast_create(Article, :profile_id => c3, :created_at => 8.days.ago) | ||
1689 | + assert_equal [c2,c1] , Community.more_active | ||
1690 | + end | ||
1691 | + | ||
1692 | + should 'find more popular communities' do | ||
1693 | + Community.delete_all | ||
1694 | + | ||
1695 | + c1 = fast_create(Community) | ||
1696 | + c2 = fast_create(Community) | ||
1697 | + fast_create(Community) | ||
1698 | + | ||
1699 | + p1 = fast_create(Person) | ||
1700 | + p2 = fast_create(Person) | ||
1701 | + c1.add_member(p1) | ||
1702 | + assert_equal [c1] , Community.more_popular | ||
1703 | + | ||
1704 | + c2.add_member(p1) | ||
1705 | + c2.add_member(p2) | ||
1706 | + assert_equal [c2,c1] , Community.more_popular | ||
1707 | + | ||
1708 | + c2.remove_member(p2) | ||
1709 | + c2.remove_member(p1) | ||
1710 | + assert_equal [c1] , Community.more_popular | ||
1711 | + end | ||
1712 | + | ||
1713 | + should "return the more recent label" do | ||
1714 | + p = fast_create(Profile) | ||
1715 | + assert_equal "Since: ", p.more_recent_label | ||
1716 | + end | ||
1717 | + | ||
1718 | + should "return none on label if the profile hasn't articles" do | ||
1719 | + p = fast_create(Profile) | ||
1720 | + assert_equal 0, p.articles.count | ||
1721 | + assert_equal "none", p.more_active_label | ||
1722 | + end | ||
1723 | + | ||
1724 | + should "return one article on label if the profile has one article" do | ||
1725 | + p = fast_create(Profile) | ||
1726 | + fast_create(Article, :profile_id => p.id) | ||
1727 | + assert_equal 1, p.articles.count | ||
1728 | + assert_equal "one article", p.more_active_label | ||
1729 | + end | ||
1730 | + | ||
1731 | + should "return number of artciles on label if the profile has more than one article" do | ||
1732 | + p = fast_create(Profile) | ||
1733 | + fast_create(Article, :profile_id => p.id) | ||
1734 | + fast_create(Article, :profile_id => p.id) | ||
1735 | + assert_equal 2, p.articles.count | ||
1736 | + assert_equal "2 articles", p.more_active_label | ||
1737 | + | ||
1738 | + fast_create(Article, :profile_id => p.id) | ||
1739 | + assert_equal 3, p.articles.count | ||
1740 | + assert_equal "3 articles", p.more_active_label | ||
1741 | + end | ||
1742 | + | ||
1743 | + should "return none on label if the profile hasn't members" do | ||
1744 | + p = fast_create(Profile) | ||
1745 | + assert_equal 0, p.members.count | ||
1746 | + assert_equal "none", p.more_popular_label | ||
1747 | + end | ||
1748 | + | ||
1749 | + should "return one member on label if the profile has one member" do | ||
1750 | + p = fast_create(Person) | ||
1751 | + c = fast_create(Community) | ||
1752 | + c.add_member(p) | ||
1753 | + assert_equal 1, c.members.count | ||
1754 | + assert_equal "one member", c.more_popular_label | ||
1755 | + end | ||
1756 | + | ||
1757 | + should "return the number of members on label if the profile has more than one member" do | ||
1758 | + p1 = fast_create(Profile) | ||
1759 | + p2 = fast_create(Person) | ||
1760 | + c = fast_create(Community) | ||
1761 | + c.add_member(p1) | ||
1762 | + c.add_member(p2) | ||
1763 | + assert_equal 2, c.members.count | ||
1764 | + assert_equal "2 members", c.more_popular_label | ||
1765 | + | ||
1766 | + p3 = fast_create(Person) | ||
1767 | + c.add_member(p3) | ||
1768 | + assert_equal 3, c.members.count | ||
1769 | + assert_equal "3 members", c.more_popular_label | ||
1770 | + end | ||
1771 | + | ||
1566 | private | 1772 | private |
1567 | 1773 | ||
1568 | def assert_invalid_identifier(id) | 1774 | def assert_invalid_identifier(id) |