Commit f5922203e2dd09c952a7163baec39e98355bbca1

Authored by Joenio Costa
2 parents edfe30e8 db1cdcce

Merge branch 'stable'

Conflicts:
	app/models/qualifier.rb
	db/schema.rb
	test/unit/manage_products_helper_test.rb
	test/unit/qualifier_test.rb
Showing 46 changed files with 461 additions and 98 deletions   Show diff stats
app/controllers/my_profile/cms_controller.rb
@@ -49,6 +49,9 @@ class CmsController < MyProfileController @@ -49,6 +49,9 @@ class CmsController < MyProfileController
49 if profile.enterprise? 49 if profile.enterprise?
50 articles << EnterpriseHomepage 50 articles << EnterpriseHomepage
51 end 51 end
  52 + if @parent && @parent.blog?
  53 + articles -= Article.folder_types.map(&:constantize)
  54 + end
52 articles 55 articles
53 end 56 end
54 57
@@ -109,6 +112,7 @@ class CmsController &lt; MyProfileController @@ -109,6 +112,7 @@ class CmsController &lt; MyProfileController
109 112
110 # user must choose an article type first 113 # user must choose an article type first
111 114
  115 + @parent = profile.articles.find(params[:parent_id]) if params && params[:parent_id]
112 record_coming 116 record_coming
113 @type = params[:type] 117 @type = params[:type]
114 if @type.blank? 118 if @type.blank?
app/controllers/my_profile/tasks_controller.rb
@@ -16,16 +16,18 @@ class TasksController &lt; MyProfileController @@ -16,16 +16,18 @@ class TasksController &lt; MyProfileController
16 def close 16 def close
17 failed = {} 17 failed = {}
18 18
19 - params[:tasks].each do |id, value|  
20 - decision = value[:decision]  
21 - if request.post? && VALID_DECISIONS.include?(decision) && id && decision != 'skip'  
22 - task = profile.find_in_all_tasks(id)  
23 - task.update_attributes!(value[:task])  
24 - begin  
25 - task.send(decision)  
26 - rescue Exception => ex  
27 - message = "#{task.title} (#{task.requestor ? task.requestor.name : task.author_name})"  
28 - failed[ex.clean_message] ? failed[ex.clean_message] << message : failed[ex.clean_message] = [message] 19 + if params[:tasks]
  20 + params[:tasks].each do |id, value|
  21 + decision = value[:decision]
  22 + if request.post? && VALID_DECISIONS.include?(decision) && id && decision != 'skip'
  23 + task = profile.find_in_all_tasks(id)
  24 + begin
  25 + task.update_attributes(value[:task])
  26 + task.send(decision)
  27 + rescue Exception => ex
  28 + message = "#{task.title} (#{task.requestor ? task.requestor.name : task.author_name})"
  29 + failed[ex.clean_message] ? failed[ex.clean_message] << message : failed[ex.clean_message] = [message]
  30 + end
29 end 31 end
30 end 32 end
31 end 33 end
app/controllers/public/browse_controller.rb
@@ -8,17 +8,20 @@ class BrowseController &lt; PublicController @@ -8,17 +8,20 @@ class BrowseController &lt; PublicController
8 more_popular 8 more_popular
9 ) 9 )
10 10
  11 + def per_page
  12 + 27
  13 + end
  14 +
11 def people 15 def people
12 @filter = filter 16 @filter = filter
13 @title = self.filter_description(params[:action] + '_' + @filter ) 17 @title = self.filter_description(params[:action] + '_' + @filter )
14 18
15 @results = @environment.people.visible.send(@filter) 19 @results = @environment.people.visible.send(@filter)
16 20
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 + if !params[:query].blank?
  22 + @results = @results.find_by_contents(params[:query])
21 end 23 end
  24 + @results = @results.compact.paginate(:per_page => per_page, :page => params[:page])
22 end 25 end
23 26
24 def communities 27 def communities
@@ -27,11 +30,10 @@ class BrowseController &lt; PublicController @@ -27,11 +30,10 @@ class BrowseController &lt; PublicController
27 30
28 @results = @environment.communities.visible.send(@filter) 31 @results = @environment.communities.visible.send(@filter)
29 32
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]) 33 + if !params[:query].blank?
  34 + @results = @results.find_by_contents(params[:query])
34 end 35 end
  36 + @results = @results.compact.paginate(:per_page => per_page, :page => params[:page])
35 end 37 end
36 38
37 protected 39 protected
app/controllers/public/profile_controller.rb
@@ -105,6 +105,8 @@ class ProfileController &lt; PublicController @@ -105,6 +105,8 @@ class ProfileController &lt; PublicController
105 end 105 end
106 if request.xhr? 106 if request.xhr?
107 render :layout => false 107 render :layout => false
  108 + else
  109 + redirect_to profile.url
108 end 110 end
109 end 111 end
110 end 112 end
app/helpers/search_helper.rb
@@ -65,7 +65,7 @@ module SearchHelper @@ -65,7 +65,7 @@ module SearchHelper
65 data << content_tag('strong', _('Address: ')) + profile.address + '<br/>' 65 data << content_tag('strong', _('Address: ')) + profile.address + '<br/>'
66 end 66 end
67 unless profile.products.empty? 67 unless profile.products.empty?
68 - data << content_tag('strong', _('Products/Services: ')) + profile.products.map{|i| link_to(i.name, :controller => 'catalog', :profile => profile.identifier, :action => 'show', :id => i)}.join(', ') + '<br/>' 68 + data << content_tag('strong', _('Products/Services: ')) + profile.products.map{|i| link_to(i.name, :controller => 'catalog', :profile => profile.identifier, :action => 'show', :id => i.id)}.join(', ') + '<br/>'
69 end 69 end
70 if profile.respond_to?(:distance) and !profile.distance.nil? 70 if profile.respond_to?(:distance) and !profile.distance.nil?
71 data << content_tag('strong', _('Distance: ')) + "%.2f%" % profile.distance + '<br/>' 71 data << content_tag('strong', _('Distance: ')) + "%.2f%" % profile.distance + '<br/>'
app/models/article.rb
@@ -339,8 +339,13 @@ class Article &lt; ActiveRecord::Base @@ -339,8 +339,13 @@ class Article &lt; ActiveRecord::Base
339 end 339 end
340 end 340 end
341 341
  342 + def self.folder_types
  343 + ['Folder', 'Blog', 'Forum', 'Gallery']
  344 + end
  345 +
342 named_scope :published, :conditions => { :published => true } 346 named_scope :published, :conditions => { :published => true }
343 - named_scope :folders, :conditions => { :type => ['Folder', 'Blog', 'Forum', 'Gallery'] } 347 + named_scope :folders, :conditions => { :type => folder_types}
  348 + named_scope :no_folders, :conditions => ['type NOT IN (?)', folder_types]
344 named_scope :galleries, :conditions => { :type => 'Gallery' } 349 named_scope :galleries, :conditions => { :type => 'Gallery' }
345 named_scope :images, :conditions => { :is_image => true } 350 named_scope :images, :conditions => { :is_image => true }
346 351
app/models/blog.rb
@@ -2,6 +2,13 @@ class Blog &lt; Folder @@ -2,6 +2,13 @@ class Blog &lt; Folder
2 2
3 acts_as_having_posts 3 acts_as_having_posts
4 4
  5 + #FIXME This should be used until there is a migration to fix all blogs that
  6 + # already have folders inside them
  7 + def posts_with_no_folders
  8 + posts_without_no_folders.no_folders
  9 + end
  10 + alias_method_chain :posts, :no_folders
  11 +
5 def self.short_description 12 def self.short_description
6 _('Blog') 13 _('Blog')
7 end 14 end
app/models/blog_archives_block.rb
@@ -17,7 +17,7 @@ class BlogArchivesBlock &lt; Block @@ -17,7 +17,7 @@ class BlogArchivesBlock &lt; Block
17 settings_items :blog_id, Integer 17 settings_items :blog_id, Integer
18 18
19 def blog 19 def blog
20 - blog_id ? owner.blogs.find(blog_id) : owner.blog 20 + blog_id && owner.blogs.exists?(blog_id) ? owner.blogs.find(blog_id) : owner.blog
21 end 21 end
22 22
23 def content 23 def content
app/models/change_password.rb
@@ -68,6 +68,10 @@ class ChangePassword &lt; Task @@ -68,6 +68,10 @@ class ChangePassword &lt; Task
68 user.force_change_password!(self.password, self.password_confirmation) 68 user.force_change_password!(self.password, self.password_confirmation)
69 end 69 end
70 70
  71 + def target_notification_description
  72 + _('%{requestor} wants to change its password.') % {:requestor => requestor.name}
  73 + end
  74 +
71 # overriding messages 75 # overriding messages
72 76
73 def task_cancelled_message 77 def task_cancelled_message
app/models/enterprise_activation.rb
@@ -35,4 +35,8 @@ class EnterpriseActivation &lt; Task @@ -35,4 +35,8 @@ class EnterpriseActivation &lt; Task
35 {:type => :profile_image, :profile => requestor, :url => requestor.url} 35 {:type => :profile_image, :profile => requestor, :url => requestor.url}
36 end 36 end
37 37
  38 + def target_notification_description
  39 + _('%{requestor} wants to activate enterprise %{enterprise}.') % {:requestor => requestor.name, :enterprise => enterprise.name}
  40 + end
  41 +
38 end 42 end
app/models/folder.rb
1 class Folder < Article 1 class Folder < Article
2 2
  3 + validate :not_belong_to_blog
  4 +
  5 + def not_belong_to_blog
  6 + errors.add(:parent, "A folder should not belong to a blog.") if parent && parent.blog?
  7 + end
  8 +
3 acts_as_having_settings :field => :setting 9 acts_as_having_settings :field => :setting
4 10
5 xss_terminate :only => [ :body ], :with => 'white_list', :on => 'validation' 11 xss_terminate :only => [ :body ], :with => 'white_list', :on => 'validation'
app/models/invite_friend.rb
@@ -23,6 +23,10 @@ class InviteFriend &lt; Invitation @@ -23,6 +23,10 @@ class InviteFriend &lt; Invitation
23 {:type => :profile_image, :profile => requestor, :url => requestor.url} 23 {:type => :profile_image, :profile => requestor, :url => requestor.url}
24 end 24 end
25 25
  26 + def target_notification_description
  27 + _('%{requestor} wants to be your friend.') % {:requestor => requestor.name}
  28 + end
  29 +
26 def permission 30 def permission
27 :manage_friends 31 :manage_friends
28 end 32 end
app/models/invite_member.rb
@@ -35,6 +35,10 @@ class InviteMember &lt; Invitation @@ -35,6 +35,10 @@ class InviteMember &lt; Invitation
35 {:type => :profile_image, :profile => community, :url => community.url} 35 {:type => :profile_image, :profile => community, :url => community.url}
36 end 36 end
37 37
  38 + def target_notification_description
  39 + _('%{requestor} invited you to join %{community}.') % {:requestor => requestor.name, :community => community.name}
  40 + end
  41 +
38 def expanded_message 42 def expanded_message
39 super.gsub /<community>/, community.name 43 super.gsub /<community>/, community.name
40 end 44 end
app/models/qualifier.rb
@@ -8,6 +8,8 @@ class Qualifier &lt; ActiveRecord::Base @@ -8,6 +8,8 @@ class Qualifier &lt; ActiveRecord::Base
8 validates_presence_of :environment_id 8 validates_presence_of :environment_id
9 validates_presence_of :name 9 validates_presence_of :name
10 10
  11 + has_many :product_qualifiers, :dependent => :destroy
  12 +
11 def <=>(b) 13 def <=>(b)
12 self.name.downcase.transliterate <=> b.name.downcase.transliterate 14 self.name.downcase.transliterate <=> b.name.downcase.transliterate
13 end 15 end
app/models/task_mailer.rb
@@ -32,7 +32,7 @@ class TaskMailer &lt; ActionMailer::Base @@ -32,7 +32,7 @@ class TaskMailer &lt; ActionMailer::Base
32 recipients task.friend_email 32 recipients task.friend_email
33 33
34 from self.class.generate_from(task) 34 from self.class.generate_from(task)
35 - subject '[%s] %s' % [ task.requestor.environment.name, task.information ] 35 + subject '[%s] %s' % [ task.requestor.environment.name, task.target_notification_description ]
36 body :message => msg 36 body :message => msg
37 end 37 end
38 38
@@ -52,7 +52,7 @@ class TaskMailer &lt; ActionMailer::Base @@ -52,7 +52,7 @@ class TaskMailer &lt; ActionMailer::Base
52 52
53 recipients task.requestor.notification_emails 53 recipients task.requestor.notification_emails
54 from self.class.generate_from(task) 54 from self.class.generate_from(task)
55 - subject '[%s] %s' % [task.requestor.environment.name, task.information] 55 + subject '[%s] %s' % [task.requestor.environment.name, task.target_notification_description]
56 body :requestor => task.requestor.name, 56 body :requestor => task.requestor.name,
57 :message => text, 57 :message => text,
58 :environment => task.requestor.environment.name, 58 :environment => task.requestor.environment.name,
app/views/profile_editor/header_footer.rhtml
@@ -21,9 +21,9 @@ @@ -21,9 +21,9 @@
21 </div> 21 </div>
22 <% end %> 22 <% end %>
23 <h2><%= _('Content for header ') %></h2> 23 <h2><%= _('Content for header ') %></h2>
24 - <%= text_area_tag(:custom_header, @header, :style => 'width: 100%; height: 150px;') %> 24 + <%= text_area_tag(:custom_header, @header, :style => 'width: 100%; height: 150px;', :class => 'mceEditor') %>
25 <h2><%= _('Content for footer') %></h2> 25 <h2><%= _('Content for footer') %></h2>
26 - <%= text_area_tag(:custom_footer, @footer, :style => 'width: 100%; height: 150px;') %> 26 + <%= text_area_tag(:custom_footer, @footer, :style => 'width: 100%; height: 150px;', :class => 'mceEditor') %>
27 <% button_bar do %> 27 <% button_bar do %>
28 <%= submit_button(:save, _('Save')) %> 28 <%= submit_button(:save, _('Save')) %>
29 <%= button(:cancel, _('Cancel'), :action => 'index') %> 29 <%= button(:cancel, _('Cancel'), :action => 'index') %>
db/migrate/20110222211802_remove_action_tracker_records_with_nil_users.rb 0 → 100644
@@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
  1 +class RemoveActionTrackerRecordsWithNilUsers < ActiveRecord::Migration
  2 + # This migration is a copy of 20110127174236_remove_action_tracker_record_with_nil_users.rb
  3 + def self.up
  4 + ActionTracker::Record.all.map {|record| record.destroy if record.user.nil?}
  5 + end
  6 +
  7 + def self.down
  8 + say "this migration can't be reverted"
  9 + end
  10 +end
@@ -9,7 +9,7 @@ @@ -9,7 +9,7 @@
9 # 9 #
10 # It's strongly recommended to check this file into your version control system. 10 # It's strongly recommended to check this file into your version control system.
11 11
12 -ActiveRecord::Schema.define(:version => 20110221195242) do 12 +ActiveRecord::Schema.define(:version => 20110222211802) do
13 13
14 create_table "action_tracker", :force => true do |t| 14 create_table "action_tracker", :force => true do |t|
15 t.integer "user_id" 15 t.integer "user_id"
debian/changelog
  1 +noosfero (0.28.6) unstable; urgency=low
  2 +
  3 + * Bugfixes Version release. (Closes: AI#1874 AI#1890 AI#1893 AI#1871 AI#1884 AI#1892 AI#1882 AI#1883 AI#1896 AI#1875 AI#1895 AI#1879)
  4 +
  5 + -- Joenio Costa <joenio@perl.org.br> Sun, 27 Feb 2011 23:56:51 -0300
  6 +
1 noosfero (0.28.5) unstable; urgency=low 7 noosfero (0.28.5) unstable; urgency=low
2 8
3 * Bugfixes Version release. (Closes: AI#1867 AI#1866 AI#1870 AI#1854 AI#1851 AI#1810 AI#1889 AI#1868 AI#1855 AI#1887) 9 * Bugfixes Version release. (Closes: AI#1867 AI#1866 AI#1870 AI#1854 AI#1851 AI#1810 AI#1889 AI#1868 AI#1855 AI#1887)
lib/noosfero.rb
1 module Noosfero 1 module Noosfero
2 PROJECT = 'noosfero' 2 PROJECT = 'noosfero'
3 - VERSION = '0.28.5' 3 + VERSION = '0.28.6'
4 4
5 def self.pattern_for_controllers_in_directory(dir) 5 def self.pattern_for_controllers_in_directory(dir)
6 disjunction = controllers_in_directory(dir).join('|') 6 disjunction = controllers_in_directory(dir).join('|')
public/stylesheets/application.css
@@ -1314,8 +1314,8 @@ a.comment-picture { @@ -1314,8 +1314,8 @@ a.comment-picture {
1314 } 1314 }
1315 1315
1316 .comment-replies .comment-picture img { 1316 .comment-replies .comment-picture img {
1317 - width: 32px;  
1318 - height: 32px; 1317 + max-width: 32px;
  1318 + max-height: 32px;
1319 } 1319 }
1320 1320
1321 .article-comment .comment-replies .button-bar { 1321 .article-comment .comment-replies .button-bar {
@@ -2137,8 +2137,8 @@ input.disabled { @@ -2137,8 +2137,8 @@ input.disabled {
2137 2137
2138 .common-profile-list-block img { 2138 .common-profile-list-block img {
2139 border: none; 2139 border: none;
2140 - width: 50px;  
2141 - height: 50px; 2140 + max-width: 50px;
  2141 + max-height: 50px;
2142 } 2142 }
2143 2143
2144 .box-2 .common-profile-list-block span, 2144 .box-2 .common-profile-list-block span,
@@ -4400,11 +4400,20 @@ h1#agenda-title { @@ -4400,11 +4400,20 @@ h1#agenda-title {
4400 padding: 0px; 4400 padding: 0px;
4401 list-style: none; 4401 list-style: none;
4402 } 4402 }
4403 -.controller-search #content .search-results-type-article li,  
4404 .controller-search #content .search-results-type-event li { 4403 .controller-search #content .search-results-type-event li {
4405 padding: 2px 0px 4px 0px; 4404 padding: 2px 0px 4px 0px;
4406 } 4405 }
4407 4406
  4407 +.controller-search #content .search-results-type-article li {
  4408 + padding: 0px 0px 4px 20px;
  4409 + background-repeat: no-repeat;
  4410 + border-color: transparent;
  4411 +}
  4412 +
  4413 +.controller-search #content .search-results-type-article li:hover {
  4414 + background-color: transparent;
  4415 +}
  4416 +
4408 .controller-search .search-results-type-article .item_meta, 4417 .controller-search .search-results-type-article .item_meta,
4409 .controller-search .search-results-type-event .item_meta { 4418 .controller-search .search-results-type-event .item_meta {
4410 font-size: 10px; 4419 font-size: 10px;
@@ -5596,8 +5605,8 @@ h1#agenda-title { @@ -5596,8 +5605,8 @@ h1#agenda-title {
5596 padding: 1px; 5605 padding: 1px;
5597 border: 1px solid #ccc; 5606 border: 1px solid #ccc;
5598 margin: 4px 3px 0 0; 5607 margin: 4px 3px 0 0;
5599 - width: 20px;  
5600 - height: 20px; 5608 + max-width: 20px;
  5609 + max-height: 20px;
5601 } 5610 }
5602 5611
5603 .profile-wall-image { 5612 .profile-wall-image {
@@ -5625,8 +5634,8 @@ h1#agenda-title { @@ -5625,8 +5634,8 @@ h1#agenda-title {
5625 5634
5626 #profile-network .upload_image .profile-network-text span img, 5635 #profile-network .upload_image .profile-network-text span img,
5627 #profile-activity .upload_image .profile-activity-text span img { 5636 #profile-activity .upload_image .profile-activity-text span img {
5628 - width: auto;  
5629 - height: auto; 5637 + max-width: none;
  5638 + max-height: none;
5630 } 5639 }
5631 5640
5632 #profile-network .upload_image .profile-network-text img, 5641 #profile-network .upload_image .profile-network-text img,
test/factories.rb
@@ -310,6 +310,8 @@ module Noosfero::Factory @@ -310,6 +310,8 @@ module Noosfero::Factory
310 { } 310 { }
311 end 311 end
312 312
  313 + alias :defaults_for_blog_archives_block :defaults_for_block
  314 +
313 ############################################### 315 ###############################################
314 # Task 316 # Task
315 ############################################### 317 ###############################################
@@ -358,7 +360,9 @@ module Noosfero::Factory @@ -358,7 +360,9 @@ module Noosfero::Factory
358 # Certifier 360 # Certifier
359 ############################################### 361 ###############################################
360 362
361 - alias :defaults_for_certifier :defaults_for_qualifier 363 + def defaults_for_certifier
  364 + defaults_for_qualifier.merge({ :name => 'Certifier ' + factory_num_seq.to_s })
  365 + end
362 366
363 ############################################### 367 ###############################################
364 # Scrap 368 # Scrap
test/functional/browse_controller_test.rb
@@ -65,6 +65,25 @@ class BrowseControllerTest &lt; Test::Unit::TestCase @@ -65,6 +65,25 @@ class BrowseControllerTest &lt; Test::Unit::TestCase
65 assert_tag :a, '', :attributes => {:class => 'next_page'} 65 assert_tag :a, '', :attributes => {:class => 'next_page'}
66 end 66 end
67 67
  68 + should 'not return nil results in the more_active people list' do
  69 + Profile.delete_all
  70 + p1 = fast_create(Person)
  71 + p2 = fast_create(Person)
  72 + p3 = fast_create(Person)
  73 + fast_create(Article, :profile_id => p1, :created_at => 1.day.ago)
  74 + fast_create(Article, :profile_id => p2, :created_at => 1.day.ago)
  75 + fast_create(Article, :profile_id => p2, :created_at => 1.day.ago)
  76 + fast_create(Article, :profile_id => p2, :created_at => 1.day.ago)
  77 + fast_create(Article, :profile_id => p3, :created_at => 1.day.ago)
  78 +
  79 + per_page = 1
  80 + @controller.stubs(:per_page).returns(per_page)
  81 +
  82 + get :people, :filter => 'more_active'
  83 +
  84 + assert_equal Person.count/per_page, assigns(:results).total_pages
  85 + end
  86 +
68 should 'list all people filter by more active' do 87 should 'list all people filter by more active' do
69 Person.delete_all 88 Person.delete_all
70 p1 = create(Person, :name => 'Testing person 1', :user_id => 1) 89 p1 = create(Person, :name => 'Testing person 1', :user_id => 1)
@@ -160,6 +179,26 @@ class BrowseControllerTest &lt; Test::Unit::TestCase @@ -160,6 +179,26 @@ class BrowseControllerTest &lt; Test::Unit::TestCase
160 assert_tag :a, '', :attributes => {:class => 'next_page'} 179 assert_tag :a, '', :attributes => {:class => 'next_page'}
161 end 180 end
162 181
  182 + should 'not return nil results in the more_active communities list' do
  183 + Profile.delete_all
  184 + c1 = fast_create(Community)
  185 + c2 = fast_create(Community)
  186 + c3 = fast_create(Community)
  187 + fast_create(Article, :profile_id => c1, :created_at => 1.day.ago)
  188 + fast_create(Article, :profile_id => c2, :created_at => 1.day.ago)
  189 + fast_create(Article, :profile_id => c2, :created_at => 1.day.ago)
  190 + fast_create(Article, :profile_id => c2, :created_at => 1.day.ago)
  191 + fast_create(Article, :profile_id => c3, :created_at => 1.day.ago)
  192 +
  193 + per_page = 1
  194 + @controller.stubs(:per_page).returns(per_page)
  195 +
  196 + get :communities, :filter => 'more_active'
  197 +
  198 + assert_equal Community.count/per_page, assigns(:results).total_pages
  199 + end
  200 +
  201 +
163 should 'list all communities filter by more active' do 202 should 'list all communities filter by more active' do
164 c1 = create(Community, :name => 'Testing community 1') 203 c1 = create(Community, :name => 'Testing community 1')
165 c2 = create(Community, :name => 'Testing community 2') 204 c2 = create(Community, :name => 'Testing community 2')
test/functional/cms_controller_test.rb
@@ -818,6 +818,15 @@ class CmsControllerTest &lt; Test::Unit::TestCase @@ -818,6 +818,15 @@ class CmsControllerTest &lt; Test::Unit::TestCase
818 assert_no_tag :tag => 'a', :attributes => { :href => "/myprofile/#{profile.identifier}/cms/new?type=Forum"} 818 assert_no_tag :tag => 'a', :attributes => { :href => "/myprofile/#{profile.identifier}/cms/new?type=Forum"}
819 end 819 end
820 820
  821 + should 'not offer folders if in a blog' do
  822 + blog = fast_create(Blog, :profile_id => profile.id)
  823 + get :new, :profile => profile.identifier, :parent_id => blog.id, :cms => true
  824 + types = assigns(:article_types).map {|t| t[:name]}
  825 + Article.folder_types.each do |type|
  826 + assert_not_includes types, type
  827 + end
  828 + end
  829 +
821 should 'offer to edit a blog' do 830 should 'offer to edit a blog' do
822 profile.articles << Blog.new(:name => 'blog test', :profile => profile) 831 profile.articles << Blog.new(:name => 'blog test', :profile => profile)
823 832
test/functional/content_viewer_controller_test.rb
@@ -714,8 +714,8 @@ class ContentViewerControllerTest &lt; Test::Unit::TestCase @@ -714,8 +714,8 @@ class ContentViewerControllerTest &lt; Test::Unit::TestCase
714 714
715 should 'add meta tag to rss feed on view post blog' do 715 should 'add meta tag to rss feed on view post blog' do
716 login_as(profile.identifier) 716 login_as(profile.identifier)
717 - profile.articles << Blog.new(:name => 'Blog', :profile => profile)  
718 - profile.blog.posts << TextileArticle.new(:name => 'first post', :parent => profile.blog, :profile => profile) 717 + blog = Blog.create!(:name => 'Blog', :profile => profile)
  718 + TextileArticle.create!(:name => 'first post', :parent => blog, :profile => profile)
719 get :view_page, :profile => profile.identifier, :page => ['blog', 'first-post'] 719 get :view_page, :profile => profile.identifier, :page => ['blog', 'first-post']
720 assert_tag :tag => 'link', :attributes => { :rel => 'alternate', :type => 'application/rss+xml', :title => 'Blog', :href => "http://#{environment.default_hostname}/testinguser/blog/feed" } 720 assert_tag :tag => 'link', :attributes => { :rel => 'alternate', :type => 'application/rss+xml', :title => 'Blog', :href => "http://#{environment.default_hostname}/testinguser/blog/feed" }
721 end 721 end
@@ -1215,9 +1215,8 @@ class ContentViewerControllerTest &lt; Test::Unit::TestCase @@ -1215,9 +1215,8 @@ class ContentViewerControllerTest &lt; Test::Unit::TestCase
1215 FastGettext.stubs(:locale).returns('es') 1215 FastGettext.stubs(:locale).returns('es')
1216 blog = fast_create(Blog, :profile_id => profile.id, :path => 'blog') 1216 blog = fast_create(Blog, :profile_id => profile.id, :path => 'blog')
1217 blog.stubs(:display_posts_in_current_language).returns(true) 1217 blog.stubs(:display_posts_in_current_language).returns(true)
1218 - en_article = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'en_article', :language => 'en')  
1219 - es_article = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'es_article', :language => 'es', :translation_of_id => en_article)  
1220 - blog.posts = [en_article, es_article] 1218 + en_article = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'en_article', :language => 'en', :parent_id => blog.id)
  1219 + es_article = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'es_article', :language => 'es', :parent_id => blog.id, :translation_of_id => en_article)
1221 1220
1222 get :view_page, :profile => @profile.identifier, :page => blog.explode_path 1221 get :view_page, :profile => @profile.identifier, :page => blog.explode_path
1223 assert_tag :div, :attributes => { :id => "post-#{es_article.id}" } 1222 assert_tag :div, :attributes => { :id => "post-#{es_article.id}" }
@@ -1239,8 +1238,8 @@ class ContentViewerControllerTest &lt; Test::Unit::TestCase @@ -1239,8 +1238,8 @@ class ContentViewerControllerTest &lt; Test::Unit::TestCase
1239 FastGettext.stubs(:locale).returns('es') 1238 FastGettext.stubs(:locale).returns('es')
1240 blog = fast_create(Blog, :profile_id => profile.id, :path => 'blog') 1239 blog = fast_create(Blog, :profile_id => profile.id, :path => 'blog')
1241 blog.stubs(:display_posts_in_current_language).returns(true) 1240 blog.stubs(:display_posts_in_current_language).returns(true)
1242 - en_article = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'en_article', :language => 'en')  
1243 - es_article = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'es_article', :language => 'es', :translation_of_id => en_article) 1241 + en_article = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'en_article', :language => 'en', :parent_id => blog.id)
  1242 + es_article = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'es_article', :language => 'es', :parent_id => blog.id, :translation_of_id => en_article)
1244 blog.posts = [en_article, es_article] 1243 blog.posts = [en_article, es_article]
1245 1244
1246 get :view_page, :profile => @profile.identifier, :page => blog.explode_path 1245 get :view_page, :profile => @profile.identifier, :page => blog.explode_path
test/functional/profile_controller_test.rb
@@ -482,9 +482,9 @@ class ProfileControllerTest &lt; Test::Unit::TestCase @@ -482,9 +482,9 @@ class ProfileControllerTest &lt; Test::Unit::TestCase
482 482
483 should 'show number of published posts in index' do 483 should 'show number of published posts in index' do
484 profile.articles << blog = Blog.create(:name => 'Blog', :profile_id => profile.id) 484 profile.articles << blog = Blog.create(:name => 'Blog', :profile_id => profile.id)
485 - blog.posts << TextileArticle.new(:name => 'Published post', :parent => profile.blog, :profile => profile)  
486 - blog.posts << TextileArticle.new(:name => 'Other published post', :parent => profile.blog, :profile => profile)  
487 - blog.posts << TextileArticle.new(:name => 'Unpublished post', :parent => profile.blog, :profile => profile, :published => false) 485 + fast_create(TextileArticle, :name => 'Published post', :parent_id => profile.blog.id, :profile_id => profile.id)
  486 + fast_create(TextileArticle, :name => 'Other published post', :parent_id => profile.blog.id, :profile_id => profile.id)
  487 + fast_create(TextileArticle, :name => 'Unpublished post', :parent_id => profile.blog.id, :profile_id => profile.id, :published => false)
488 488
489 get :index, :profile => profile.identifier 489 get :index, :profile => profile.identifier
490 assert_tag :tag => 'a', :content => '2 posts', :attributes => { :href => /\/testuser\/blog/ } 490 assert_tag :tag => 'a', :content => '2 posts', :attributes => { :href => /\/testuser\/blog/ }
@@ -1159,4 +1159,13 @@ class ProfileControllerTest &lt; Test::Unit::TestCase @@ -1159,4 +1159,13 @@ class ProfileControllerTest &lt; Test::Unit::TestCase
1159 assert_tag :tag => 'div', :content => /#{plugin1_tab[:content]}/, :attributes => {:id => /#{plugin1_tab[:id]}/} 1159 assert_tag :tag => 'div', :content => /#{plugin1_tab[:content]}/, :attributes => {:id => /#{plugin1_tab[:id]}/}
1160 end 1160 end
1161 1161
  1162 + should 'redirect to profile page when try to request join_not_logged via GET method' do
  1163 + community = Community.create!(:name => 'my test community')
  1164 + login_as(profile.identifier)
  1165 + get :join_not_logged, :profile => community.identifier
  1166 + assert_nothing_raised do
  1167 + assert_redirected_to community.url
  1168 + end
  1169 + end
  1170 +
1162 end 1171 end
test/functional/profile_editor_controller_test.rb
@@ -498,6 +498,12 @@ class ProfileEditorControllerTest &lt; Test::Unit::TestCase @@ -498,6 +498,12 @@ class ProfileEditorControllerTest &lt; Test::Unit::TestCase
498 assert_tag :tag => 'textarea', :content => 'my custom footer' 498 assert_tag :tag => 'textarea', :content => 'my custom footer'
499 end 499 end
500 500
  501 + should 'render TinyMce Editor for header and footer' do
  502 + get :header_footer, :profile => profile.identifier
  503 + assert_tag :tag => 'textarea', :attributes => { :id => 'custom_header', :class => 'mceEditor' }
  504 + assert_tag :tag => 'textarea', :attributes => { :id => 'custom_footer', :class => 'mceEditor' }
  505 + end
  506 +
501 should 'save footer and header' do 507 should 'save footer and header' do
502 person = profile 508 person = profile
503 post :header_footer, :profile => profile.identifier, :custom_header => 'new header', :custom_footer => 'new footer' 509 post :header_footer, :profile => profile.identifier, :custom_header => 'new header', :custom_footer => 'new footer'
test/functional/tasks_controller_test.rb
@@ -217,16 +217,18 @@ class TasksControllerTest &lt; Test::Unit::TestCase @@ -217,16 +217,18 @@ class TasksControllerTest &lt; Test::Unit::TestCase
217 assert_includes c_blog2.children(true), p_article 217 assert_includes c_blog2.children(true), p_article
218 end 218 end
219 219
220 - should 'raise error if there is an enterprise with the same identifier and keep the task active' do 220 + should 'display error if there is an enterprise with the same identifier and keep the task active' do
221 e = Environment.default 221 e = Environment.default
222 e.add_admin(profile) 222 e.add_admin(profile)
223 task = CreateEnterprise.create!(:name => "My Enterprise", :identifier => "my-enterprise", :requestor => profile, :target => e) 223 task = CreateEnterprise.create!(:name => "My Enterprise", :identifier => "my-enterprise", :requestor => profile, :target => e)
224 enterprise = fast_create(Enterprise, :name => "My Enterprise", :identifier => "my-enterprise") 224 enterprise = fast_create(Enterprise, :name => "My Enterprise", :identifier => "my-enterprise")
225 225
226 - assert_raise ActiveRecord::RecordInvalid do  
227 - post :close, :tasks => {task.id => { :task => {:reject_explanation => "Bla bla"}, :decision => "cancel"}} 226 + assert_nothing_raised do
  227 + post :close, :tasks => {task.id => {:decision => "finish"}}
228 end 228 end
229 229
  230 + assert_match /Validation.failed/, @response.body
  231 +
230 task.reload 232 task.reload
231 assert_equal Task::Status::ACTIVE, task.status 233 assert_equal Task::Status::ACTIVE, task.status
232 end 234 end
@@ -280,4 +282,22 @@ class TasksControllerTest &lt; Test::Unit::TestCase @@ -280,4 +282,22 @@ class TasksControllerTest &lt; Test::Unit::TestCase
280 assert_equal 'new source', TinyMceArticle.find(:first).source_name 282 assert_equal 'new source', TinyMceArticle.find(:first).source_name
281 end 283 end
282 284
  285 + should "not crash if accessing close without tasks parameter" do
  286 + assert_nothing_raised do
  287 + post :close
  288 + end
  289 + end
  290 +
  291 + should 'close create enterprise if trying to cancel even if there is already an existing identifier' do
  292 + identifier = "common-identifier"
  293 + task = CreateEnterprise.create!(:identifier => identifier, :name => identifier, :requestor => profile, :target => profile)
  294 + fast_create(Profile, :identifier => identifier)
  295 +
  296 + assert_nothing_raised do
  297 + post :close, :tasks => {task.id => {:task => {:reject_explanation => "Some explanation"}, :decision => 'cancel'}}
  298 + end
  299 +
  300 + task.reload
  301 + assert_equal Task::Status::CANCELLED, task.status
  302 + end
283 end 303 end
test/test_helper.rb
@@ -189,7 +189,7 @@ end @@ -189,7 +189,7 @@ end
189 189
190 module NoosferoTestHelper 190 module NoosferoTestHelper
191 def link_to(content, url, options = {}) 191 def link_to(content, url, options = {})
192 - "<a href='#{url.to_s}'>#{content}</a>" 192 + "<a href='#{url.inspect}'>#{content}</a>"
193 end 193 end
194 194
195 def content_tag(tag, content, options = {}) 195 def content_tag(tag, content, options = {})
test/unit/approve_article_test.rb
@@ -362,6 +362,14 @@ class ApproveArticleTest &lt; ActiveSupport::TestCase @@ -362,6 +362,14 @@ class ApproveArticleTest &lt; ActiveSupport::TestCase
362 assert_match(/#{task.requestor.name} wants to publish the article: #{article.name}/, email.subject) 362 assert_match(/#{task.requestor.name} wants to publish the article: #{article.name}/, email.subject)
363 end 363 end
364 364
  365 + should 'deliver target finished message' do
  366 + task = ApproveArticle.new(:article => article, :target => community, :requestor => profile)
  367 +
  368 + email = TaskMailer.deliver_task_finished(task)
  369 +
  370 + assert_match(/#{task.requestor.name} wants to publish the article: #{article.name}/, email.subject)
  371 + end
  372 +
365 should 'approve an event' do 373 should 'approve an event' do
366 event = fast_create(Event, :profile_id => profile.id, :name => 'Event test', :slug => 'event-test', :abstract => 'Lead of article', :body => 'This is my event') 374 event = fast_create(Event, :profile_id => profile.id, :name => 'Event test', :slug => 'event-test', :abstract => 'Lead of article', :body => 'This is my event')
367 task = ApproveArticle.create!(:name => 'Event test', :article => event, :target => community, :requestor => profile) 375 task = ApproveArticle.create!(:name => 'Event test', :article => event, :target => community, :requestor => profile)
test/unit/article_test.rb
@@ -1444,4 +1444,34 @@ class ArticleTest &lt; Test::Unit::TestCase @@ -1444,4 +1444,34 @@ class ArticleTest &lt; Test::Unit::TestCase
1444 assert !Article.new.tiny_mce? 1444 assert !Article.new.tiny_mce?
1445 end 1445 end
1446 1446
  1447 + should 'return only folders' do
  1448 + not_folders = [RssFeed, TinyMceArticle, Event, TextileArticle]
  1449 + folders = [Folder, Blog, Gallery, Forum]
  1450 +
  1451 + not_folders.each do |klass|
  1452 + item = fast_create(klass)
  1453 + assert_not_includes Article.folders, item
  1454 + end
  1455 +
  1456 + folders.each do |klass|
  1457 + item = fast_create(klass)
  1458 + assert_includes Article.folders, item
  1459 + end
  1460 + end
  1461 +
  1462 + should 'return no folders' do
  1463 + not_folders = [RssFeed, TinyMceArticle, Event, TextileArticle]
  1464 + folders = [Folder, Blog, Gallery, Forum]
  1465 +
  1466 + not_folders.each do |klass|
  1467 + item = fast_create(klass)
  1468 + assert_includes Article.no_folders, item
  1469 + end
  1470 +
  1471 + folders.each do |klass|
  1472 + item = fast_create(klass)
  1473 + assert_not_includes Article.no_folders, item
  1474 + end
  1475 + end
  1476 +
1447 end 1477 end
test/unit/blog_archives_block_test.rb
@@ -134,4 +134,27 @@ class BlogArchivesBlockTest &lt; ActiveSupport::TestCase @@ -134,4 +134,27 @@ class BlogArchivesBlockTest &lt; ActiveSupport::TestCase
134 assert_tag_in_string block.content, :tag => 'a', :content => 'January (2)', :attributes => {:href => /^http:\/\/.*\/flatline\/blog-one\?month=01&year=2008$/ } 134 assert_tag_in_string block.content, :tag => 'a', :content => 'January (2)', :attributes => {:href => /^http:\/\/.*\/flatline\/blog-one\?month=01&year=2008$/ }
135 end 135 end
136 136
  137 + should 'not try to load a removed blog' do
  138 + block = fast_create(BlogArchivesBlock)
  139 + block.blog_id = profile.blog.id
  140 + block.save!
  141 + block.stubs(:owner).returns(profile)
  142 + profile.blog.destroy
  143 + assert_nothing_raised do
  144 + assert_nil block.blog
  145 + end
  146 + end
  147 +
  148 + should 'load next blog if configured blog was removed' do
  149 + other_blog = fast_create(Blog, :profile_id => profile.id)
  150 + block = fast_create(BlogArchivesBlock)
  151 + block.blog_id = profile.blog.id
  152 + block.save!
  153 + block.stubs(:owner).returns(profile)
  154 + profile.blog.destroy
  155 + assert_nothing_raised do
  156 + assert_equal other_blog, block.blog
  157 + end
  158 + end
  159 +
137 end 160 end
test/unit/blog_test.rb
@@ -195,4 +195,15 @@ class BlogTest &lt; ActiveSupport::TestCase @@ -195,4 +195,15 @@ class BlogTest &lt; ActiveSupport::TestCase
195 assert !blog.reload.display_posts_in_current_language? 195 assert !blog.reload.display_posts_in_current_language?
196 end 196 end
197 197
  198 + #FIXME This should be used until there is a migration to fix all blogs that
  199 + # already have folders inside them
  200 + should 'not list folders in posts' do
  201 + blog = fast_create(Blog)
  202 + folder = fast_create(Folder, :parent_id => blog.id)
  203 + article = fast_create(TextileArticle, :parent_id => blog.id)
  204 +
  205 + assert_not_includes blog.posts, folder
  206 + assert_includes blog.posts, article
  207 + end
  208 +
198 end 209 end
test/unit/change_password_test.rb
@@ -132,4 +132,21 @@ class ChangePasswordTest &lt; Test::Unit::TestCase @@ -132,4 +132,21 @@ class ChangePasswordTest &lt; Test::Unit::TestCase
132 assert_equal c2.requestor, p2 132 assert_equal c2.requestor, p2
133 end 133 end
134 134
  135 + should 'have target notification description' do
  136 + person = fast_create(Person, :identifier => 'testuser')
  137 +
  138 + change = ChangePassword.create(:login => 'testuser', :email => 'test@example.com', :environment_id => Environment.default.id)
  139 +
  140 + assert_match(/#{change.requestor.name} wants to change its password/, change.target_notification_description)
  141 + end
  142 +
  143 + should 'deliver task created message' do
  144 + person = fast_create(Person, :identifier => 'testuser')
  145 +
  146 + task = ChangePassword.create(:login => 'testuser', :email => 'test@example.com', :environment_id => Environment.default.id)
  147 +
  148 + email = TaskMailer.deliver_task_created(task)
  149 + assert_match(/#{task.requestor.name} wants to change its password/, email.subject)
  150 + end
  151 +
135 end 152 end
test/unit/email_activation_test.rb
@@ -49,4 +49,13 @@ class EmailActivationTest &lt; Test::Unit::TestCase @@ -49,4 +49,13 @@ class EmailActivationTest &lt; Test::Unit::TestCase
49 assert !anothertask.save 49 assert !anothertask.save
50 end 50 end
51 51
  52 + should 'deliver activation email notification' do
  53 + user = create_user('testuser', :environment_id => Environment.default.id)
  54 +
  55 + task = EmailActivation.new(:requestor => user.person, :target => Environment.default)
  56 +
  57 + email = User::Mailer.deliver_activation_email_notify(user)
  58 + assert_match(/Welcome to #{task.requestor.environment.name} mail!/, email.subject)
  59 + end
  60 +
52 end 61 end
test/unit/enterprise_activation_test.rb
@@ -64,5 +64,12 @@ class EnterpriseActivationTest &lt; ActiveSupport::TestCase @@ -64,5 +64,12 @@ class EnterpriseActivationTest &lt; ActiveSupport::TestCase
64 t.finish 64 t.finish
65 end 65 end
66 66
  67 + should 'have target notification description' do
  68 + ent = fast_create(Enterprise, :enabled => false)
  69 + task = EnterpriseActivation.create!(:enterprise => ent, :requestor => profiles(:ze))
  70 +
  71 + assert_match(/#{task.requestor.name} wants to activate enterprise #{ent.name}/, task.target_notification_description)
  72 + end
  73 +
67 end 74 end
68 75
test/unit/folder_test.rb
@@ -132,4 +132,12 @@ class FolderTest &lt; ActiveSupport::TestCase @@ -132,4 +132,12 @@ class FolderTest &lt; ActiveSupport::TestCase
132 assert_no_match /[<>]/, folder.body 132 assert_no_match /[<>]/, folder.body
133 end 133 end
134 134
  135 + should 'not have a blog as parent' do
  136 + folder = Folder.new
  137 + folder.parent = Blog.new
  138 + folder.valid?
  139 +
  140 + assert folder.errors.on(:parent)
  141 + end
  142 +
135 end 143 end
test/unit/invite_friend_test.rb
@@ -120,4 +120,22 @@ class InviteFriendTest &lt; ActiveSupport::TestCase @@ -120,4 +120,22 @@ class InviteFriendTest &lt; ActiveSupport::TestCase
120 assert !task2.save 120 assert !task2.save
121 end 121 end
122 122
  123 + should 'have target notification description' do
  124 + person = create_user('testuser1').person
  125 +
  126 + task = InviteFriend.create!(:person => person, :friend_email => 'test@test.com', :message => '<url>')
  127 +
  128 + assert_match(/#{task.requestor.name} wants to be your friend./, task.target_notification_description)
  129 + end
  130 +
  131 + should 'deliver invitation notification' do
  132 + person = create_user('testuser1').person
  133 +
  134 + task = InviteFriend.create!(:person => person, :friend_email => 'test@test.com', :message => '<url>')
  135 +
  136 + email = TaskMailer.deliver_invitation_notification(task)
  137 +
  138 + assert_match(/#{task.requestor.name} wants to be your friend./, email.subject)
  139 + end
  140 +
123 end 141 end
test/unit/invite_member_test.rb
@@ -95,5 +95,25 @@ class InviteMemberTest &lt; ActiveSupport::TestCase @@ -95,5 +95,25 @@ class InviteMemberTest &lt; ActiveSupport::TestCase
95 assert !task2.save 95 assert !task2.save
96 end 96 end
97 97
  98 + should 'have target notification description' do
  99 + p = create_user('testuser1').person
  100 + community = fast_create(Community)
  101 +
  102 + task = InviteMember.create!(:person => p, :friend_email => 'test@test.com', :message => '<url>', :community_id => community.id)
  103 +
  104 + assert_match(/#{task.requestor.name} invited you to join #{community.name}/, task.target_notification_description)
  105 + end
  106 +
  107 + should 'deliver invitation notification' do
  108 + person = create_user('testuser1').person
  109 + community = fast_create(Community)
  110 +
  111 + task = InviteMember.create!(:person => person, :friend_email => 'test@test.com', :message => '<url>', :community_id => community.id)
  112 +
  113 + email = TaskMailer.deliver_invitation_notification(task)
  114 +
  115 + assert_match(/#{task.requestor.name} invited you to join #{community.name}/, email.subject)
  116 + end
  117 +
98 end 118 end
99 119
test/unit/manage_products_helper_test.rb
@@ -167,6 +167,38 @@ class ManageProductsHelperTest &lt; Test::Unit::TestCase @@ -167,6 +167,38 @@ class ManageProductsHelperTest &lt; Test::Unit::TestCase
167 assert_equal ["Self declared", "Colivre", "FBES"], result.map{|i| i[0]} 167 assert_equal ["Self declared", "Colivre", "FBES"], result.map{|i| i[0]}
168 end 168 end
169 169
  170 + should 'list qualifiers and certifiers of a product' do
  171 + product = fast_create(Product)
  172 + qualifier = fast_create(Qualifier)
  173 + certifier = fast_create(Certifier)
  174 + ProductQualifier.create!(:product => product, :qualifier => qualifier, :certifier => certifier)
  175 + assert_match /✔ Qualifier \d+ certified by Certifier \d+/, display_qualifiers(product)
  176 + end
  177 +
  178 + should 'product survive to a Qualifier deletation' do
  179 + product = fast_create(Product)
  180 + qualifier = fast_create(Qualifier)
  181 + certifier = fast_create(Certifier)
  182 + ProductQualifier.create!(:product => product, :qualifier => qualifier, :certifier => certifier)
  183 + qualifier.destroy
  184 + assert_nothing_raised do
  185 + assert_no_match /✔ Qualifier \d+ certified by Certifier \d+/, display_qualifiers(product)
  186 + end
  187 + end
  188 +
  189 + should 'product consider its Qualifier self-declared when Certifier is deleted' do
  190 + product = fast_create(Product)
  191 + qualifier = fast_create(Qualifier)
  192 + certifier = fast_create(Certifier)
  193 + ProductQualifier.create!(:product => product, :qualifier => qualifier, :certifier => certifier)
  194 + certifier.destroy
  195 + assert_nothing_raised do
  196 + result = display_qualifiers(product)
  197 + assert_match /✔ Qualifier \d+ \(Self declared\)/, result
  198 + assert_no_match /certified by Certifier \d+/, result
  199 + end
  200 + end
  201 +
170 protected 202 protected
171 include NoosferoTestHelper 203 include NoosferoTestHelper
172 include ActionView::Helpers::TextHelper 204 include ActionView::Helpers::TextHelper
test/unit/qualifier_test.rb
@@ -49,4 +49,16 @@ class QualifierTest &lt; Test::Unit::TestCase @@ -49,4 +49,16 @@ class QualifierTest &lt; Test::Unit::TestCase
49 assert_equal [first, last], Qualifier.all.sort 49 assert_equal [first, last], Qualifier.all.sort
50 end 50 end
51 51
  52 + should 'clean all ProductQualifier when destroy a Qualifier' do
  53 + product1 = fast_create(Product)
  54 + product2 = fast_create(Product)
  55 + qualifier = fast_create(Qualifier, :name => 'Free Software')
  56 + certifier = fast_create(Certifier, :name => 'FSF')
  57 + ProductQualifier.create!(:product => product1, :qualifier => qualifier, :certifier => certifier)
  58 + ProductQualifier.create!(:product => product2, :qualifier => qualifier, :certifier => certifier)
  59 + assert_equal [['Free Software', 'FSF']], product1.product_qualifiers.map{|i| [i.qualifier.name, i.certifier.name]}
  60 + Qualifier.destroy_all
  61 + assert_equal [], product1.product_qualifiers(true)
  62 + end
  63 +
52 end 64 end
test/unit/rss_feed_test.rb
@@ -212,7 +212,10 @@ class RssFeedTest &lt; Test::Unit::TestCase @@ -212,7 +212,10 @@ class RssFeedTest &lt; Test::Unit::TestCase
212 a = ApproveArticle.create!(:name => 'test name', :article => article, :target => profile, :requestor => fast_create(Person)) 212 a = ApproveArticle.create!(:name => 'test name', :article => article, :target => profile, :requestor => fast_create(Person))
213 a.finish 213 a.finish
214 214
215 - blog.posts << published_article = article.class.last 215 + published_article = article.class.last
  216 + published_article.parent = blog
  217 + published_article.save
  218 +
216 feed = RssFeed.new(:parent => blog, :profile => profile) 219 feed = RssFeed.new(:parent => blog, :profile => profile)
217 220
218 assert_match "This is the content of the Sample Article", feed.data 221 assert_match "This is the content of the Sample Article", feed.data
test/unit/search_helper_test.rb
@@ -10,25 +10,20 @@ class SearchHelperTest &lt; Test::Unit::TestCase @@ -10,25 +10,20 @@ class SearchHelperTest &lt; Test::Unit::TestCase
10 10
11 def setup 11 def setup
12 @profile = mock 12 @profile = mock
  13 + self.stubs(:profile_image).returns('profileimage.png')
  14 + self.stubs(:url_for).returns('link to profile')
  15 + profile.stubs(:name).returns('Name of Profile')
  16 + profile.stubs(:url).returns('')
  17 + profile.stubs(:products).returns([Product.new(:name => 'product test')])
  18 + profile.stubs(:identifier).returns('name-of-profile')
  19 + profile.stubs(:region).returns(Region.new(:name => 'Brazil'))
13 end 20 end
14 attr_reader :profile 21 attr_reader :profile
15 22
16 - include ActionView::Helpers::FormOptionsHelper  
17 - include ActionView::Helpers::FormTagHelper  
18 - include ActionView::Helpers::TagHelper  
19 should 'display profile info' do 23 should 'display profile info' do
20 - profile.stubs(:name).returns('Name of Profile')  
21 profile.stubs(:address).returns('Address of Profile') 24 profile.stubs(:address).returns('Address of Profile')
22 profile.stubs(:contact_email).returns('Email of Profile') 25 profile.stubs(:contact_email).returns('Email of Profile')
23 profile.stubs(:contact_phone).returns('Phone of Profile') 26 profile.stubs(:contact_phone).returns('Phone of Profile')
24 - profile.stubs(:url).returns('')  
25 - profile.stubs(:products).returns([Product.new(:name => 'product test')])  
26 - profile.stubs(:identifier).returns('name-of-profile')  
27 - profile.stubs(:region).returns(Region.new(:name => 'Brazil'))  
28 -  
29 - self.stubs(:profile_image).returns('profileimage.png')  
30 - self.stubs(:url_for).returns('merda')  
31 - self.stubs(:link_to).returns('link to profile')  
32 27
33 result = self.display_profile_info(profile) 28 result = self.display_profile_info(profile)
34 assert_match /profileimage.png/, result 29 assert_match /profileimage.png/, result
@@ -39,18 +34,9 @@ class SearchHelperTest &lt; Test::Unit::TestCase @@ -39,18 +34,9 @@ class SearchHelperTest &lt; Test::Unit::TestCase
39 end 34 end
40 35
41 should 'not display field if nil in profile info' do 36 should 'not display field if nil in profile info' do
42 - profile.stubs(:name).returns('Name of Profile')  
43 profile.stubs(:address).returns('nil') 37 profile.stubs(:address).returns('nil')
44 profile.stubs(:contact_email).returns('nil') 38 profile.stubs(:contact_email).returns('nil')
45 profile.stubs(:contact_phone).returns('nil') 39 profile.stubs(:contact_phone).returns('nil')
46 - profile.stubs(:url).returns('')  
47 - profile.stubs(:products).returns([Product.new(:name => 'product test')])  
48 - profile.stubs(:identifier).returns('name-of-profile')  
49 - profile.stubs(:region).returns(Region.new(:name => 'Brazil'))  
50 -  
51 - self.stubs(:profile_image).returns('profileimage.png')  
52 - self.stubs(:url_for).returns('merda')  
53 - self.stubs(:link_to).returns('link to profile')  
54 40
55 result = self.display_profile_info(profile) 41 result = self.display_profile_info(profile)
56 assert_match /profileimage.png/, result 42 assert_match /profileimage.png/, result
@@ -60,4 +46,16 @@ class SearchHelperTest &lt; Test::Unit::TestCase @@ -60,4 +46,16 @@ class SearchHelperTest &lt; Test::Unit::TestCase
60 assert_no_match /Address of Profile/, result 46 assert_no_match /Address of Profile/, result
61 end 47 end
62 48
  49 + should 'link to products and services of an profile' do
  50 + enterprise = fast_create(Enterprise)
  51 + product1 = fast_create(Product, :enterprise_id => enterprise.id)
  52 + product2 = fast_create(Product, :enterprise_id => enterprise.id)
  53 + result = display_profile_info(enterprise)
  54 + assert_tag_in_string result, :tag => 'a', :attributes => {:href => /:id=>#{product1.id}/}, :content => product1.name
  55 + assert_tag_in_string result, :tag => 'a', :attributes => {:href => /:id=>#{product2.id}/}, :content => product2.name
  56 + end
  57 +
  58 + protected
  59 + include NoosferoTestHelper
  60 +
63 end 61 end
test/unit/task_mailer_test.rb
@@ -17,7 +17,7 @@ class TaskMailerTest &lt; Test::Unit::TestCase @@ -17,7 +17,7 @@ class TaskMailerTest &lt; Test::Unit::TestCase
17 17
18 task = Task.new 18 task = Task.new
19 task.expects(:task_finished_message).returns('the message') 19 task.expects(:task_finished_message).returns('the message')
20 - task.expects(:information).returns('the task') 20 + task.expects(:target_notification_description).returns('the task')
21 21
22 requestor = mock() 22 requestor = mock()
23 requestor.expects(:notification_emails).returns(['requestor@example.com']) 23 requestor.expects(:notification_emails).returns(['requestor@example.com'])
@@ -40,7 +40,7 @@ class TaskMailerTest &lt; Test::Unit::TestCase @@ -40,7 +40,7 @@ class TaskMailerTest &lt; Test::Unit::TestCase
40 40
41 task = Task.new 41 task = Task.new
42 task.expects(:task_cancelled_message).returns('the message') 42 task.expects(:task_cancelled_message).returns('the message')
43 - task.expects(:information).returns('the task') 43 + task.expects(:target_notification_description).returns('the task')
44 44
45 requestor = mock() 45 requestor = mock()
46 requestor.expects(:notification_emails).returns(['requestor@example.com']) 46 requestor.expects(:notification_emails).returns(['requestor@example.com'])
@@ -64,7 +64,7 @@ class TaskMailerTest &lt; Test::Unit::TestCase @@ -64,7 +64,7 @@ class TaskMailerTest &lt; Test::Unit::TestCase
64 task = Task.new 64 task = Task.new
65 65
66 task.expects(:task_created_message).returns('the message') 66 task.expects(:task_created_message).returns('the message')
67 - task.expects(:information).returns('the task') 67 + task.expects(:target_notification_description).returns('the task')
68 68
69 requestor = mock() 69 requestor = mock()
70 requestor.expects(:notification_emails).returns(['requestor@example.com']) 70 requestor.expects(:notification_emails).returns(['requestor@example.com'])
@@ -129,6 +129,8 @@ class TaskMailerTest &lt; Test::Unit::TestCase @@ -129,6 +129,8 @@ class TaskMailerTest &lt; Test::Unit::TestCase
129 129
130 mail = TaskMailer.create_invitation_notification(task) 130 mail = TaskMailer.create_invitation_notification(task)
131 131
  132 + assert_match(/#{task.target_notification_description}/, mail.subject)
  133 +
132 assert_equal "Hello friend name, my name invite you, please follow this link: http://example.com/account/signup?invitation_code=123456", mail.body 134 assert_equal "Hello friend name, my name invite you, please follow this link: http://example.com/account/signup?invitation_code=123456", mail.body
133 135
134 TaskMailer.deliver(mail) 136 TaskMailer.deliver(mail)
vendor/plugins/action_tracker/lib/action_tracker_model.rb
@@ -12,6 +12,11 @@ module ActionTracker @@ -12,6 +12,11 @@ module ActionTracker
12 12
13 validates_presence_of :verb 13 validates_presence_of :verb
14 validates_presence_of :user 14 validates_presence_of :user
  15 + validate :user_existence
  16 +
  17 + def user_existence
  18 + errors.add(:user, "user doesn't exists") if user && !user.class.exists?(user)
  19 + end
15 20
16 alias_method :subject, :user 21 alias_method :subject, :user
17 22
vendor/plugins/action_tracker/test/action_tracker_model_test.rb
@@ -67,9 +67,32 @@ class ActionTrackerModelTest &lt; ActiveSupport::TestCase @@ -67,9 +67,32 @@ class ActionTrackerModelTest &lt; ActiveSupport::TestCase
67 end 67 end
68 end 68 end
69 69
  70 + def test_user_is_mandatory
  71 + ta = ActionTracker::Record.new :user_type => 'SomeModel', :verb => :some_verb
  72 + ta.valid?
  73 + assert ta.errors.on(:user)
  74 + assert_raise ActiveRecord::RecordInvalid do
  75 + ta.save!
  76 + end
  77 +
  78 + ta = ActionTracker::Record.new :user_id => 2, :verb => :some_verb
  79 + ta.valid?
  80 + assert ta.errors.on(:user)
  81 + assert_raise ActiveRecord::RecordInvalid do
  82 + ta.save!
  83 + end
  84 + end
  85 +
70 def test_user_exists_indeed 86 def test_user_exists_indeed
71 - ta = ActionTracker::Record.new(:user_id => -1, :user_type => "SomeModel", :verb => :some_verb)  
72 - assert !ta.valid? 87 + ta = ActionTracker::Record.new(:verb => :some_verb)
  88 + ta.valid?
  89 + assert ta.errors.on(:user)
  90 + user = SomeModel.create!
  91 + ta.user = user
  92 + assert ta.valid?
  93 + user.destroy
  94 + ta.valid?
  95 + assert ta.errors.on(:user)
73 end 96 end
74 97
75 def test_verb_must_be_declared_previously 98 def test_verb_must_be_declared_previously
@@ -333,24 +356,4 @@ class ActionTrackerModelTest &lt; ActiveSupport::TestCase @@ -333,24 +356,4 @@ class ActionTrackerModelTest &lt; ActiveSupport::TestCase
333 assert_equal(["foo 1", "bar 2"], t.collect_group_with_index(:test){|x, i| "#{x} #{i+1}" }) 356 assert_equal(["foo 1", "bar 2"], t.collect_group_with_index(:test){|x, i| "#{x} #{i+1}" })
334 end 357 end
335 358
336 - def test_user_id_is_mandatory  
337 - ActionTrackerConfig.verbs = { :some => { :description => "Some" } }  
338 - ta = ActionTracker::Record.new :user_type => 'SomeModel', :verb => :some  
339 - ta.valid?  
340 - assert ta.errors.on(:user_id)  
341 - assert_raise ActiveRecord::RecordInvalid do  
342 - ta.save!  
343 - end  
344 - end  
345 -  
346 - def test_user_type_is_mandatory  
347 - ActionTrackerConfig.verbs = { :some => { :description => "Some" } }  
348 - ta = ActionTracker::Record.new :user_id => 2, :verb => :some  
349 - ta.valid?  
350 - assert ta.errors.on(:user_type)  
351 - assert_raise ActiveRecord::RecordInvalid do  
352 - ta.save!  
353 - end  
354 - end  
355 -  
356 end 359 end