Commit ea03b2d7a0a7bdc41cdfacabcb7ca7758b33583d

Authored by Victor Costa
2 parents 57521d2e 2f142b41

Merge branch 'api' into stable

Conflicts:
	test/unit/block_test.rb
app/controllers/my_profile/cms_controller.rb
@@ -350,7 +350,8 @@ class CmsController < MyProfileController @@ -350,7 +350,8 @@ class CmsController < MyProfileController
350 @task.ip_address = request.remote_ip 350 @task.ip_address = request.remote_ip
351 @task.user_agent = request.user_agent 351 @task.user_agent = request.user_agent
352 @task.referrer = request.referrer 352 @task.referrer = request.referrer
353 - if verify_recaptcha(:model => @task, :message => _('Please type the words correctly')) && @task.save 353 + @task.requestor = current_person if logged_in?
  354 + if (logged_in? || verify_recaptcha(:model => @task, :message => _('Please type the words correctly'))) && @task.save
354 session[:notice] = _('Thanks for your suggestion. The community administrators were notified.') 355 session[:notice] = _('Thanks for your suggestion. The community administrators were notified.')
355 redirect_to @back_to 356 redirect_to @back_to
356 end 357 end
app/helpers/tinymce_helper.rb
@@ -17,6 +17,7 @@ module TinymceHelper @@ -17,6 +17,7 @@ module TinymceHelper
17 searchreplace wordcount visualblocks visualchars code fullscreen 17 searchreplace wordcount visualblocks visualchars code fullscreen
18 insertdatetime media nonbreaking save table contextmenu directionality 18 insertdatetime media nonbreaking save table contextmenu directionality
19 emoticons template paste textcolor colorpicker textpattern], 19 emoticons template paste textcolor colorpicker textpattern],
  20 + :image_advtab => true,
20 :language => tinymce_language 21 :language => tinymce_language
21 22
22 options[:toolbar1] = "insertfile undo redo | copy paste | bold italic underline | styleselect fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image" 23 options[:toolbar1] = "insertfile undo redo | copy paste | bold italic underline | styleselect fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image"
app/models/article.rb
@@ -5,7 +5,7 @@ class Article < ActiveRecord::Base @@ -5,7 +5,7 @@ class Article < ActiveRecord::Base
5 :allow_members_to_edit, :translation_of_id, :language, 5 :allow_members_to_edit, :translation_of_id, :language,
6 :license_id, :parent_id, :display_posts_in_current_language, 6 :license_id, :parent_id, :display_posts_in_current_language,
7 :category_ids, :posts_per_page, :moderate_comments, 7 :category_ids, :posts_per_page, :moderate_comments,
8 - :accept_comments, :feed, :published, :source, 8 + :accept_comments, :feed, :published, :source, :source_name,
9 :highlighted, :notify_comments, :display_hits, :slug, 9 :highlighted, :notify_comments, :display_hits, :slug,
10 :external_feed_builder, :display_versions, :external_link, 10 :external_feed_builder, :display_versions, :external_link,
11 :image_builder, :show_to_followers, :published_at 11 :image_builder, :show_to_followers, :published_at
app/models/block.rb
@@ -23,7 +23,7 @@ class Block < ActiveRecord::Base @@ -23,7 +23,7 @@ class Block < ActiveRecord::Base
23 end 23 end
24 24
25 def get_limit 25 def get_limit
26 - [0,limit].max 26 + [0,limit.to_i].max
27 end 27 end
28 28
29 def embed_code 29 def embed_code
app/models/highlights_block.rb
@@ -26,8 +26,16 @@ class HighlightsBlock < Block @@ -26,8 +26,16 @@ class HighlightsBlock < Block
26 end 26 end
27 27
28 def featured_images 28 def featured_images
29 - block_images = images.select{|i| !i[:image_src].nil? }.sort { |x, y| x[:position] <=> y[:position] }  
30 - shuffle ? block_images.shuffle : block_images 29 + images = get_images
  30 + shuffle ? images.shuffle : images
  31 + end
  32 +
  33 + def get_images
  34 + images.select do |i|
  35 + !i[:image_src].nil?
  36 + end.sort do |x, y|
  37 + x[:position] <=> y[:position]
  38 + end
31 end 39 end
32 40
33 def content(args={}) 41 def content(args={})
app/models/suggest_article.rb
1 class SuggestArticle < Task 1 class SuggestArticle < Task
2 2
3 - validates_presence_of :target_id, :article_name, :email, :name, :article_body 3 + validates_presence_of :target_id
  4 + validates_presence_of :email, :name, :if => Proc.new { |task| task.requestor.blank? }
  5 + validates_associated :article_object
4 6
5 settings_items :email, :type => String 7 settings_items :email, :type => String
6 settings_items :name, :type => String 8 settings_items :name, :type => String
7 - settings_items :article_name, :type => String  
8 - settings_items :article_body, :type => String  
9 - settings_items :article_abstract, :type => String  
10 - settings_items :article_parent_id, :type => String  
11 - settings_items :source, :type => String  
12 - settings_items :source_name, :type => String  
13 - settings_items :highlighted, :type => :boolean, :default => false  
14 settings_items :ip_address, :type => String 9 settings_items :ip_address, :type => String
15 settings_items :user_agent, :type => String 10 settings_items :user_agent, :type => String
16 settings_items :referrer, :type => String 11 settings_items :referrer, :type => String
  12 + settings_items :article, :type => Hash, :default => {}
17 13
18 after_create :schedule_spam_checking 14 after_create :schedule_spam_checking
19 15
@@ -24,34 +20,49 @@ class SuggestArticle &lt; Task @@ -24,34 +20,49 @@ class SuggestArticle &lt; Task
24 include Noosfero::Plugin::HotSpot 20 include Noosfero::Plugin::HotSpot
25 21
26 def sender 22 def sender
27 - "#{name} (#{email})" 23 + requestor ? "#{requestor.name}" : "#{name} (#{email})"
  24 + end
  25 +
  26 + def article_object
  27 + if @article_object.nil?
  28 + @article_object = article_type.new(article.merge({:profile => target}).except(:type))
  29 + if requestor.present?
  30 + @article_object.author = requestor
  31 + else
  32 + @article_object.author_name = name
  33 + end
  34 + end
  35 + @article_object
  36 + end
  37 +
  38 + def article_type
  39 + if article[:type].present?
  40 + type = article[:type].constantize
  41 + return type if type < Article
  42 + end
  43 + TinyMceArticle
28 end 44 end
29 45
30 def perform 46 def perform
31 - task = TinyMceArticle.new  
32 - task.profile = target  
33 - task.name = article_name  
34 - task.author_name = name  
35 - task.body = article_body  
36 - task.abstract = article_abstract  
37 - task.parent_id = article_parent_id  
38 - task.source = source  
39 - task.source_name = source_name  
40 - task.highlighted = highlighted  
41 - task.save! 47 + article_object.save!
42 end 48 end
43 49
44 def title 50 def title
45 _("Article suggestion") 51 _("Article suggestion")
46 end 52 end
47 53
  54 + def article_name
  55 + article[:name]
  56 + end
  57 +
48 def subject 58 def subject
49 article_name 59 article_name
50 end 60 end
51 61
52 def information 62 def information
53 - { :message => _('%{sender} suggested the publication of the article: %{subject}.'),  
54 - :variables => {:sender => sender} } 63 + variables = requestor.blank? ? {:requestor => sender} : {}
  64 + { :message => _('%{requestor} suggested the publication of the article: %{subject}.'),
  65 + :variables => variables }
55 end 66 end
56 67
57 def accept_details 68 def accept_details
@@ -63,8 +74,8 @@ class SuggestArticle &lt; Task @@ -63,8 +74,8 @@ class SuggestArticle &lt; Task
63 end 74 end
64 75
65 def target_notification_description 76 def target_notification_description
66 - _('%{sender} suggested the publication of the article: %{article}.') %  
67 - {:sender => sender, :article => article_name} 77 + _('%{requestor} suggested the publication of the article: %{article}.') %
  78 + {:requestor => sender, :article => article_name}
68 end 79 end
69 80
70 def target_notification_message 81 def target_notification_message
app/models/user.rb
@@ -46,7 +46,7 @@ class User &lt; ActiveRecord::Base @@ -46,7 +46,7 @@ class User &lt; ActiveRecord::Base
46 p = Person.new 46 p = Person.new
47 47
48 p.attributes = user.person_data 48 p.attributes = user.person_data
49 - p.identifier = user.login 49 + p.identifier = user.login if p.identifier.blank?
50 p.user = user 50 p.user = user
51 p.environment = user.environment 51 p.environment = user.environment
52 p.name ||= user.name || user.login 52 p.name ||= user.name || user.login
app/views/cms/suggest_an_article.html.erb
@@ -6,21 +6,22 @@ @@ -6,21 +6,22 @@
6 6
7 <%= labelled_form_for 'task' do |f| %> 7 <%= labelled_form_for 'task' do |f| %>
8 8
9 - <%= required labelled_form_field(_('Title'), text_field(:task, 'article_name', :size => 50)) %> 9 + <%= required labelled_form_field(_('Title'), text_field('task[article]', 'name', :size => 50)) %>
10 10
11 - <%= labelled_form_field(_('Source'), text_field(:task, 'source_name')) %> 11 + <%= labelled_form_field(_('Source'), text_field('task[article]', 'source_name')) %>
12 12
13 - <%= labelled_form_field(_('Source URL'), text_field(:task, 'source')) %> 13 + <%= labelled_form_field(_('Source URL'), text_field('task[article]', 'source')) %>
14 14
15 - <%= required labelled_form_field(_('Your name'), text_field(:task, 'name')) %>  
16 -  
17 - <%= required labelled_form_field(_('Email'), text_field(:task, 'email')) %> 15 + <% unless logged_in? %>
  16 + <%= required labelled_form_field(_('Your name'), text_field(:task, 'name')) %>
  17 + <%= required labelled_form_field(_('Email'), text_field(:task, 'email')) %>
  18 + <% end %>
18 19
19 - <%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true, :object => :task, :abstract_method => 'article_abstract', :body_method => 'article_body'} %> 20 + <%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true, :object => 'task[article]'} %>
20 21
21 <%= hidden_field_tag('back_to', @back_to) %> 22 <%= hidden_field_tag('back_to', @back_to) %>
22 23
23 - <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) %> 24 + <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) unless logged_in? %>
24 25
25 <% button_bar do %> 26 <% button_bar do %>
26 <%= submit_button :save, _('Save') %> 27 <%= submit_button :save, _('Save') %>
app/views/profile/report_abuse.html.erb
@@ -24,7 +24,7 @@ @@ -24,7 +24,7 @@
24 $('#report-abuse-submit-button').css('cursor', 'progress'); 24 $('#report-abuse-submit-button').css('cursor', 'progress');
25 $.ajax({ 25 $.ajax({
26 type: 'POST', 26 type: 'POST',
27 - url: <%= url_for({:controller => 'profile', :action => 'register_report', :profile => profile.identifier}) %>, 27 + url: <%= url_for({:controller => 'profile', :action => 'register_report', :profile => profile.identifier}).to_json %>,
28 data: $(form).serialize(), 28 data: $(form).serialize(),
29 dataType: 'json', 29 dataType: 'json',
30 success: function(data, status, ajax){ 30 success: function(data, status, ajax){
app/views/profile_editor/edit.html.erb
1 <h1><%= _('Profile settings for %s') % profile.name %></h1> 1 <h1><%= _('Profile settings for %s') % profile.name %></h1>
2 2
3 -<%= javascript_include_tag 'deactivate_profile' %>  
4 <%= error_messages_for :profile_data %> 3 <%= error_messages_for :profile_data %>
5 4
6 <%= labelled_form_for :profile_data, :html => { :id => 'profile-data', :multipart => true } do |f| %> 5 <%= labelled_form_for :profile_data, :html => { :id => 'profile-data', :multipart => true } do |f| %>
app/views/shared/_profile_search_form.html.erb
  1 +<% search_label = _("Find in %s's content") % profile.short_name %>
1 <%= form_tag( { :controller => 'profile_search', :profile => profile.identifier}, :method => 'get', :class => 'search_form' ) do %> 2 <%= form_tag( { :controller => 'profile_search', :profile => profile.identifier}, :method => 'get', :class => 'search_form' ) do %>
2 <div class="search-field"> 3 <div class="search-field">
3 <span class="formfield"> 4 <span class="formfield">
4 - <%= search_input_with_suggestions 'q', :articles, @q, :title => _("Find in %s's content") % profile.short_name %> 5 + <%= search_input_with_suggestions 'q', :articles, @q, :title => search_label, :placeholder => search_label %>
5 </span> 6 </span>
6 <%= submit_button(:search, _('Search')) %> 7 <%= submit_button(:search, _('Search')) %>
7 <div> 8 <div>
app/views/spam/_suggest_article.html.erb
@@ -7,13 +7,13 @@ @@ -7,13 +7,13 @@
7 <ul class="suggest-article-details" style="display: none"> 7 <ul class="suggest-article-details" style="display: none">
8 <li><strong><%=_('Sent by')%></strong>: <%=task.name%> </li> 8 <li><strong><%=_('Sent by')%></strong>: <%=task.name%> </li>
9 <li><strong><%=_('Email')%></strong>: <%=task.email%> </li> 9 <li><strong><%=_('Email')%></strong>: <%=task.email%> </li>
10 - <li><strong><%=_('Source')%></strong>: <%=task.source_name%> </li>  
11 - <li><strong><%=_('Source URL')%></strong>: <%=task.source%> </li>  
12 - <li><strong><%=_('Folder')%></strong>: <%=(a = Article.find_by_id(task.article_parent_id))?a.name : '<em>' + s_('Folder|none') + '</em>'%> </li>  
13 - <li><strong><%=_('Lead')%></strong>: <%=task.article_abstract.blank? ? '<em>' + s_('Abstract|empty') + '</em>' : task.article_abstract%> </li> 10 + <li><strong><%=_('Source')%></strong>: <%=task.article_object.source_name%> </li>
  11 + <li><strong><%=_('Source URL')%></strong>: <%=task.article_object.source%> </li>
  12 + <li><strong><%=_('Folder')%></strong>: <%=(a = Article.find_by_id(task.article_object.parent_id))?a.name : '<em>' + s_('Folder|none') + '</em>'%> </li>
  13 + <li><strong><%=_('Lead')%></strong>: <%=task.article_object.abstract.blank? ? '<em>' + s_('Abstract|empty') + '</em>' : task.article_object.abstract%> </li>
14 <li><strong><%=_('Body')%></strong>: 14 <li><strong><%=_('Body')%></strong>:
15 <div class='suggest-article-body'> 15 <div class='suggest-article-body'>
16 - <%= task.article_body %> 16 + <%= task.article_object.body %>
17 </div> 17 </div>
18 </li> 18 </li>
19 </ul> 19 </ul>
app/views/tasks/_suggest_article_accept_details.html.erb
1 <%= render :file => 'shared/tiny_mce' %> 1 <%= render :file => 'shared/tiny_mce' %>
2 2
3 -<%= labelled_form_field(_("Sent by: "), f.text_field(:name)) %>  
4 -<p><%= label_tag(_("Email: %s") % task.email) %> </p>  
5 -<%= required labelled_form_field(_('Title'), f.text_field(:article_name, :size => 50)) %>  
6 -<%= labelled_form_field(_('Source'), f.text_field(:source_name)) %>  
7 -<%= labelled_form_field(_("Source URL"), f.text_field(:source)) %> 3 +<% unless task.requestor %>
  4 + <%= labelled_form_field(_("Sent by: "), f.text_field(:name)) %>
  5 + <p><%= label_tag(_("Email: %s") % task.email) %> </p>
  6 +<% end %>
8 7
9 -<%= select_profile_folder(_('Select the folder where the article must be published'), "tasks[#{task.id}][task][article_parent_id]", task.target) %>  
10 -<%= labelled_form_field(_('Highlight this article'), f.check_box(:highlighted)) %> 8 +<%= f.fields_for 'article', OpenStruct.new(task.article) do |a| %>
  9 + <%= required labelled_form_field(_('Title'), a.text_field(:name, :size => 50)) %>
  10 + <%= labelled_form_field(_('Source'), a.text_field(:source_name)) %>
  11 + <%= labelled_form_field(_("Source URL"), a.text_field(:source)) %>
11 12
12 -<%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true, :f => f, :abstract_method => 'article_abstract', :body_method => 'article_body', :lead_id => task.id} %> 13 + <%= select_profile_folder(_('Select the folder where the article must be published'), "tasks[#{task.id}][task][article][parent_id]", task.target, task.article[:parent_id]) %>
  14 + <%= labelled_form_field(_('Highlight this article'), a.check_box(:highlighted)) %>
  15 +
  16 + <%= a.hidden_field(:type) %>
  17 +
  18 + <%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true, :f => a, :lead_id => task.id} %>
  19 +<% end %>
app/views/user_mailer/profiles_suggestions_email.html.erb
@@ -10,8 +10,8 @@ @@ -10,8 +10,8 @@
10 <% @people_suggestions.each do |person| %> 10 <% @people_suggestions.each do |person| %>
11 <li><a href="<%= url_for(person.public_profile_url) %>"><%= person.name %></a></li> 11 <li><a href="<%= url_for(person.public_profile_url) %>"><%= person.name %></a></li>
12 <% end %> 12 <% end %>
13 - <ul>  
14 - <%= _("To see the full list of friends suggestions, follow the link: %s") % @people_suggestions_url %> 13 + </ul>
  14 + <%= _("To see the full list of friends suggestions, follow the link: %s") % url_for(@people_suggestions_url) %>
15 <% end %> 15 <% end %>
16 16
17 <% unless @communities_suggestions.empty? %> 17 <% unless @communities_suggestions.empty? %>
@@ -21,13 +21,15 @@ @@ -21,13 +21,15 @@
21 <% @communities_suggestions.each do |community| %> 21 <% @communities_suggestions.each do |community| %>
22 <li><a href="<%= url_for(community.public_profile_url) %>"><%= community.name %></a></li> 22 <li><a href="<%= url_for(community.public_profile_url) %>"><%= community.name %></a></li>
23 <% end %> 23 <% end %>
24 - <ul>  
25 - <%= _("To see the full list of communities suggestions, follow the link: %s") % @communities_suggestions_url %> 24 + </ul>
  25 + <%= _("To see the full list of communities suggestions, follow the link: %s") % url_for(@communities_suggestions_url) %>
26 <% end %> 26 <% end %>
27 27
28 28
29 <%= _("Greetings,") %> 29 <%= _("Greetings,") %>
30 30
31 ---  
32 -<%= _('%s team.') % @environment %> 31 +<p><%= _("Greetings,") %></p>
  32 +
  33 +--<br/>
  34 +<%= _('%s team.') % @environment %><br/>
33 <%= @url %> 35 <%= @url %>
debian/noosfero.install
@@ -25,6 +25,7 @@ etc/init.d/noosfero etc/init.d @@ -25,6 +25,7 @@ etc/init.d/noosfero etc/init.d
25 etc/logrotate.d/noosfero etc/logrotate.d 25 etc/logrotate.d/noosfero etc/logrotate.d
26 etc/noosfero/varnish-accept-language.vcl etc/noosfero 26 etc/noosfero/varnish-accept-language.vcl etc/noosfero
27 etc/noosfero/varnish-noosfero.vcl etc/noosfero 27 etc/noosfero/varnish-noosfero.vcl etc/noosfero
  28 +etc/awstats-noosfero.conf etc/noosfero
28 lib usr/share/noosfero 29 lib usr/share/noosfero
29 locale usr/share/noosfero 30 locale usr/share/noosfero
30 plugins usr/share/noosfero 31 plugins usr/share/noosfero
features/signup.feature
@@ -267,32 +267,6 @@ Feature: signup @@ -267,32 +267,6 @@ Feature: signup
267 Then I should be on the homepage 267 Then I should be on the homepage
268 268
269 @selenium 269 @selenium
270 - Scenario: join community on signup  
271 - Given the following users  
272 - | login | name |  
273 - | mariasilva | Maria Silva |  
274 - And the following communities  
275 - | name | identifier | owner |  
276 - | Free Software | freesoftware | mariasilva |  
277 - And feature "skip_new_user_email_confirmation" is disabled on environment  
278 - And I am on /freesoftware  
279 - When I follow "Join"  
280 - And I follow "New user"  
281 - And I fill in the following within ".no-boxes":  
282 - | e-Mail | josesilva@example.com |  
283 - | Username | josesilva |  
284 - | Password | secret |  
285 - | Password confirmation | secret |  
286 - | Full name | José da Silva |  
287 - And wait for the captcha signup time  
288 - And I press "Create my account"  
289 - And I go to josesilva's confirmation URL  
290 - And I fill in "Username" with "josesilva"  
291 - And I fill in "Password" with "secret"  
292 - And I press "Log in"  
293 - Then "José da Silva" should be a member of "Free Software"  
294 -  
295 - @selenium  
296 Scenario: user registration is moderated by admin 270 Scenario: user registration is moderated by admin
297 Given feature "admin_must_approve_new_users" is enabled on environment 271 Given feature "admin_must_approve_new_users" is enabled on environment
298 And feature "skip_new_user_email_confirmation" is disabled on environment 272 And feature "skip_new_user_email_confirmation" is disabled on environment
lib/noosfero/api/entities.rb
@@ -101,7 +101,12 @@ module Noosfero @@ -101,7 +101,12 @@ module Noosfero
101 class UserLogin < User 101 class UserLogin < User
102 expose :private_token 102 expose :private_token
103 end 103 end
104 - 104 +
  105 + class Task < Entity
  106 + expose :id
  107 + expose :type
  108 + end
  109 +
105 end 110 end
106 end 111 end
107 end 112 end
lib/noosfero/api/v1/articles.rb
@@ -57,6 +57,21 @@ module Noosfero @@ -57,6 +57,21 @@ module Noosfero
57 present find_article(article.children, params[:child_id]), :with => Entities::Article, :fields => params[:fields] 57 present find_article(article.children, params[:child_id]), :with => Entities::Article, :fields => params[:fields]
58 end 58 end
59 59
  60 + post ':id/children/suggest' do
  61 + parent_article = environment.articles.find(params[:id])
  62 +
  63 + suggest_article = SuggestArticle.new
  64 + suggest_article.article = params[:article]
  65 + suggest_article.article[:parent_id] = parent_article.id
  66 + suggest_article.target = parent_article.profile
  67 + suggest_article.requestor = current_person
  68 +
  69 + unless suggest_article.save
  70 + render_api_errors!(suggest_article.article_object.errors.full_messages)
  71 + end
  72 + present suggest_article, :with => Entities::Task, :fields => params[:fields]
  73 + end
  74 +
60 # Example Request: 75 # Example Request:
61 # POST api/v1/articles/:id/children?private_token=234298743290432&article[name]=title&article[body]=body 76 # POST api/v1/articles/:id/children?private_token=234298743290432&article[name]=title&article[body]=body
62 post ':id/children' do 77 post ':id/children' do
@@ -81,7 +96,6 @@ module Noosfero @@ -81,7 +96,6 @@ module Noosfero
81 present article, :with => Entities::Article, :fields => params[:fields] 96 present article, :with => Entities::Article, :fields => params[:fields]
82 end 97 end
83 98
84 -  
85 end 99 end
86 100
87 resource :communities do 101 resource :communities do
lib/noosfero/plugin.rb
@@ -8,6 +8,10 @@ class Noosfero::Plugin @@ -8,6 +8,10 @@ class Noosfero::Plugin
8 self.context = context 8 self.context = context
9 end 9 end
10 10
  11 + def environment
  12 + context.environment if self.context
  13 + end
  14 +
11 class << self 15 class << self
12 16
13 attr_writer :should_load 17 attr_writer :should_load
@@ -35,6 +39,7 @@ class Noosfero::Plugin @@ -35,6 +39,7 @@ class Noosfero::Plugin
35 # filters must be loaded after all extensions 39 # filters must be loaded after all extensions
36 klasses.each do |plugin| 40 klasses.each do |plugin|
37 load_plugin_filters plugin 41 load_plugin_filters plugin
  42 + load_plugin_hotspots plugin
38 end 43 end
39 end 44 end
40 45
@@ -108,6 +113,23 @@ class Noosfero::Plugin @@ -108,6 +113,23 @@ class Noosfero::Plugin
108 end 113 end
109 end 114 end
110 115
  116 + # This is a generic method to extend the hotspots list with plugins
  117 + # hotspots. This allows plugins to extend other plugins.
  118 + # To use this, the plugin must define its hotspots inside a module Hotspots.
  119 + # Its also needed to include Noosfero::Plugin::HotSpot module
  120 + # in order to dispatch plugins methods.
  121 + #
  122 + # Checkout FooPlugin for usage example.
  123 + def load_plugin_hotspots(plugin)
  124 + ActionDispatch::Reloader.to_prepare do
  125 + begin
  126 + module_name = "#{plugin.name}::Hotspots"
  127 + Noosfero::Plugin.send(:include, module_name.constantize)
  128 + rescue NameError
  129 + end
  130 + end
  131 + end
  132 +
111 def add_controller_filters(controller_class, plugin, filters) 133 def add_controller_filters(controller_class, plugin, filters)
112 unless filters.is_a?(Array) 134 unless filters.is_a?(Array)
113 filters = [filters] 135 filters = [filters]
plugins/event/po/pt/event.po
@@ -5,8 +5,8 @@ @@ -5,8 +5,8 @@
5 # 5 #
6 msgid "" 6 msgid ""
7 msgstr "" 7 msgstr ""
8 -"Project-Id-Version: 1.0-690-gcb6e853\n"  
9 -"POT-Creation-Date: 2015-03-05 12:09-0300\n" 8 +"Project-Id-Version: 1.1~rc4\n"
  9 +"POT-Creation-Date: 2015-04-20 19:44-0300\n"
10 "PO-Revision-Date: 2015-01-30 00:18-0000\n" 10 "PO-Revision-Date: 2015-01-30 00:18-0000\n"
11 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" 11 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12 "Language-Team: LANGUAGE <LL@li.org>\n" 12 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -16,61 +16,53 @@ msgstr &quot;&quot; @@ -16,61 +16,53 @@ msgstr &quot;&quot;
16 "Content-Transfer-Encoding: 8bit\n" 16 "Content-Transfer-Encoding: 8bit\n"
17 "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" 17 "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
18 18
  19 +#: plugins/event/lib/event_plugin.rb:4
  20 +msgid "Event Extras"
  21 +msgstr "Extras para Eventos"
  22 +
  23 +#: plugins/event/lib/event_plugin.rb:8
  24 +msgid ""
  25 +"Include a new block to show the environment's or profiles' events information"
  26 +msgstr ""
  27 +"Adiciona um novo bloco para apresentar as informações de eventos do ambiente "
  28 +"ou dos perfis"
  29 +
19 #: plugins/event/lib/event_plugin/event_block.rb:12 30 #: plugins/event/lib/event_plugin/event_block.rb:12
20 msgid "Events" 31 msgid "Events"
21 msgstr "Eventos" 32 msgstr "Eventos"
22 33
23 #: plugins/event/lib/event_plugin/event_block.rb:16 34 #: plugins/event/lib/event_plugin/event_block.rb:16
24 msgid "Show the profile events or all environment events." 35 msgid "Show the profile events or all environment events."
25 -msgstr "Mostrar todos os eventos." 36 +msgstr "Mostra todos os eventos de um perfil ou do ambiente."
26 37
27 #: plugins/event/lib/event_plugin/event_block.rb:65 38 #: plugins/event/lib/event_plugin/event_block.rb:65
28 -#, fuzzy  
29 msgid "One month ago" 39 msgid "One month ago"
30 msgid_plural "%d months ago" 40 msgid_plural "%d months ago"
31 -msgstr[0] "Iniciou a um mês atrás."  
32 -msgstr[1] "Iniciou a %d meses atrás." 41 +msgstr[0] "Um mês atrás"
  42 +msgstr[1] "%d meses atrás."
33 43
34 #: plugins/event/lib/event_plugin/event_block.rb:67 44 #: plugins/event/lib/event_plugin/event_block.rb:67
35 msgid "Yesterday" 45 msgid "Yesterday"
36 msgid_plural "%d days ago" 46 msgid_plural "%d days ago"
37 -msgstr[0] ""  
38 -msgstr[1] "" 47 +msgstr[0] "Ontem"
  48 +msgstr[1] "%d dias atrás"
39 49
40 #: plugins/event/lib/event_plugin/event_block.rb:69 50 #: plugins/event/lib/event_plugin/event_block.rb:69
41 msgid "Today" 51 msgid "Today"
42 -msgstr "" 52 +msgstr "Hoje"
43 53
44 #: plugins/event/lib/event_plugin/event_block.rb:71 54 #: plugins/event/lib/event_plugin/event_block.rb:71
45 msgid "Tomorrow" 55 msgid "Tomorrow"
46 msgid_plural "%d days left to start" 56 msgid_plural "%d days left to start"
47 -msgstr[0] ""  
48 -msgstr[1] "" 57 +msgstr[0] "Amanhã"
  58 +msgstr[1] "%d dias para começar"
49 59
50 #: plugins/event/lib/event_plugin/event_block.rb:73 60 #: plugins/event/lib/event_plugin/event_block.rb:73
51 -#, fuzzy  
52 msgid "One month left to start" 61 msgid "One month left to start"
53 msgid_plural "%d months left to start" 62 msgid_plural "%d months left to start"
54 msgstr[0] "Um mês para iniciar" 63 msgstr[0] "Um mês para iniciar"
55 msgstr[1] "% meses para iniciar" 64 msgstr[1] "% meses para iniciar"
56 65
57 -#: plugins/event/lib/event_plugin.rb:4  
58 -msgid "Event Extras"  
59 -msgstr "Eventos"  
60 -  
61 -#: plugins/event/lib/event_plugin.rb:8  
62 -msgid ""  
63 -"Include a new block to show the environment's or profiles' events information"  
64 -msgstr ""  
65 -"Adiciona um novo bloco para apresentar as informações de eventos do ambiente "  
66 -"ou de perfis"  
67 -  
68 -#: plugins/event/views/event_plugin/event_block_item.html.erb:6  
69 -msgid "Duration: 1 day"  
70 -msgid_plural "Duration: %s days"  
71 -msgstr[0] ""  
72 -msgstr[1] ""  
73 -  
74 #: plugins/event/views/profile_design/event_plugin/_event_block.html.erb:1 66 #: plugins/event/views/profile_design/event_plugin/_event_block.html.erb:1
75 msgid "Limit of items" 67 msgid "Limit of items"
76 msgstr "Limite de itens" 68 msgstr "Limite de itens"
@@ -94,12 +86,17 @@ msgstr &quot;Mostrar apenas eventos futuros&quot; @@ -94,12 +86,17 @@ msgstr &quot;Mostrar apenas eventos futuros&quot;
94 86
95 #: plugins/event/views/profile_design/event_plugin/_event_block.html.erb:22 87 #: plugins/event/views/profile_design/event_plugin/_event_block.html.erb:22
96 msgid "Limit of days to display" 88 msgid "Limit of days to display"
97 -msgstr "Limite de dias de distância para mostrar eventos" 89 +msgstr "Limite de dias para mostrar"
98 90
99 #: plugins/event/views/profile_design/event_plugin/_event_block.html.erb:24 91 #: plugins/event/views/profile_design/event_plugin/_event_block.html.erb:24
100 -#, fuzzy  
101 msgid "Only show events in this interval of days." 92 msgid "Only show events in this interval of days."
102 -msgstr "Mostar somente eventos que acontecem dentro do limite de dias" 93 +msgstr "Mostar somente os eventos nesse intervalo de dias"
  94 +
  95 +#: plugins/event/views/event_plugin/event_block_item.html.erb:6
  96 +msgid "Duration: 1 day"
  97 +msgid_plural "Duration: %s days"
  98 +msgstr[0] "Duração: 1 dia"
  99 +msgstr[1] "Duração: %s dias"
103 100
104 #~ msgid "Started one day ago." 101 #~ msgid "Started one day ago."
105 #~ msgid_plural "Started %d days ago." 102 #~ msgid_plural "Started %d days ago."
plugins/foo/lib/foo_plugin.rb
1 class FooPlugin < Noosfero::Plugin 1 class FooPlugin < Noosfero::Plugin
  2 + include Noosfero::Plugin::HotSpot
2 3
3 def self.plugin_name 4 def self.plugin_name
4 "Foo" 5 "Foo"
@@ -8,12 +9,29 @@ class FooPlugin &lt; Noosfero::Plugin @@ -8,12 +9,29 @@ class FooPlugin &lt; Noosfero::Plugin
8 _("A sample plugin to test autoload craziness.") 9 _("A sample plugin to test autoload craziness.")
9 end 10 end
10 11
  12 + module Hotspots
  13 + # -> Custom foo plugin hotspot
  14 + # do something to extend the FooPlugin behaviour
  15 + # receive params a, b and c
  16 + # returns = boolean or something else
  17 + def foo_plugin_my_hotspot(a, b, c)
  18 + end
  19 +
  20 + # -> Custom title for foo profiles tab
  21 + # returns = a string with a custom title
  22 + def foo_plugin_tab_title
  23 + end
  24 + end
  25 +
11 def control_panel_buttons 26 def control_panel_buttons
12 {:title => 'Foo plugin button', :icon => '', :url => ''} 27 {:title => 'Foo plugin button', :icon => '', :url => ''}
13 end 28 end
14 29
15 def profile_tabs 30 def profile_tabs
16 - {:title => 'Foo plugin tab', :id => 'foo_plugin', :content => lambda {'Foo plugin random content'} } 31 + title = plugins.dispatch_first(:foo_plugin_tab_title)
  32 + title = 'Foo plugin tab' unless title
  33 +
  34 + {:title => title, :id => 'foo_plugin', :content => lambda {'Foo plugin random content'} }
17 end 35 end
18 36
19 end 37 end
plugins/foo/test/unit/foo_plugin_test.rb
@@ -4,7 +4,25 @@ class FooPluginTest &lt; ActiveSupport::TestCase @@ -4,7 +4,25 @@ class FooPluginTest &lt; ActiveSupport::TestCase
4 def test_foo 4 def test_foo
5 FooPlugin::Bar.create! 5 FooPlugin::Bar.create!
6 end 6 end
  7 +
7 def test_monkey_patch 8 def test_monkey_patch
8 Profile.new.bar 9 Profile.new.bar
9 end 10 end
  11 +
  12 + should "respond to new hotspots" do
  13 + plugin = FooPlugin.new
  14 +
  15 + assert plugin.respond_to?(:foo_plugin_my_hotspot)
  16 + assert plugin.respond_to?(:foo_plugin_tab_title)
  17 + end
  18 +
  19 + should "other plugin respond to new hotspots" do
  20 + class TestPlugin < Noosfero::Plugin
  21 + end
  22 +
  23 + plugin = TestPlugin.new
  24 +
  25 + assert plugin.respond_to?(:foo_plugin_my_hotspot)
  26 + assert plugin.respond_to?(:foo_plugin_tab_title)
  27 + end
10 end 28 end
plugins/ldap/lib/ldap_authentication.rb
@@ -77,18 +77,20 @@ class LdapAuthentication @@ -77,18 +77,20 @@ class LdapAuthentication
77 end 77 end
78 78
79 def get_user_attributes_from_ldap_entry(entry) 79 def get_user_attributes_from_ldap_entry(entry)
80 - {  
81 - :dn => entry.dn,  
82 - :fullname => LdapAuthentication.get_attr(entry, self.attr_fullname),  
83 - :mail => LdapAuthentication.get_attr(entry, self.attr_mail),  
84 - } 80 + attributes = entry.instance_values["myhash"]
  81 +
  82 + attributes[:dn] = entry.dn
  83 + attributes[:fullname] = LdapAuthentication.get_attr(entry, self.attr_fullname)
  84 + attributes[:mail] = LdapAuthentication.get_attr(entry, self.attr_mail)
  85 +
  86 + attributes
85 end 87 end
86 88
87 # Return the attributes needed for the LDAP search. It will only 89 # Return the attributes needed for the LDAP search. It will only
88 # include the user attributes if on-the-fly registration is enabled 90 # include the user attributes if on-the-fly registration is enabled
89 def search_attributes 91 def search_attributes
90 if onthefly_register? 92 if onthefly_register?
91 - ['dn', self.attr_fullname, self.attr_mail] 93 + nil
92 else 94 else
93 ['dn'] 95 ['dn']
94 end 96 end
@@ -111,6 +113,7 @@ class LdapAuthentication @@ -111,6 +113,7 @@ class LdapAuthentication
111 end 113 end
112 login_filter = Net::LDAP::Filter.eq( self.attr_login, login ) 114 login_filter = Net::LDAP::Filter.eq( self.attr_login, login )
113 object_filter = Net::LDAP::Filter.eq( "objectClass", "*" ) 115 object_filter = Net::LDAP::Filter.eq( "objectClass", "*" )
  116 +
114 attrs = {} 117 attrs = {}
115 118
116 search_filter = object_filter & login_filter 119 search_filter = object_filter & login_filter
plugins/ldap/lib/ldap_plugin.rb
1 require File.dirname(__FILE__) + '/ldap_authentication.rb' 1 require File.dirname(__FILE__) + '/ldap_authentication.rb'
2 2
3 class LdapPlugin < Noosfero::Plugin 3 class LdapPlugin < Noosfero::Plugin
  4 + include Noosfero::Plugin::HotSpot
4 5
5 def self.plugin_name 6 def self.plugin_name
6 "LdapPlugin" 7 "LdapPlugin"
@@ -10,6 +11,25 @@ class LdapPlugin &lt; Noosfero::Plugin @@ -10,6 +11,25 @@ class LdapPlugin &lt; Noosfero::Plugin
10 _("A plugin that add ldap support.") 11 _("A plugin that add ldap support.")
11 end 12 end
12 13
  14 + module Hotspots
  15 + # -> Custom ldap plugin hotspot to set profile data before user creation
  16 + # receive the followings params:
  17 + # - attrs with ldap received data
  18 + # - login received by ldap
  19 + # - params from current context
  20 + # returns = updated person_data hash
  21 + def ldap_plugin_set_profile_data(attrs, login, params)
  22 + end
  23 +
  24 + # -> Custom ldap plugin hotspot to update user object
  25 + # receive the followings params:
  26 + # - user: user object
  27 + # - attrs with ldap received data
  28 + # returns = none
  29 + def ldap_plugin_update_user(user, attrs)
  30 + end
  31 + end
  32 +
13 def allow_user_registration 33 def allow_user_registration
14 false 34 false
15 end 35 end
@@ -39,13 +59,15 @@ class LdapPlugin &lt; Noosfero::Plugin @@ -39,13 +59,15 @@ class LdapPlugin &lt; Noosfero::Plugin
39 user.name = attrs[:fullname] 59 user.name = attrs[:fullname]
40 user.password = password 60 user.password = password
41 user.password_confirmation = password 61 user.password_confirmation = password
42 - user.person_data = context.params[:profile_data] 62 + person_data = plugins.dispatch(:ldap_plugin_set_profile_data, attrs, login, context.params)
  63 + user.person_data = person_data.blank? ? context.params[:profile_data] : person_data
43 user.activated_at = Time.now.utc 64 user.activated_at = Time.now.utc
44 user.activation_code = nil 65 user.activation_code = nil
45 66
46 ldap = LdapAuthentication.new(context.environment.ldap_plugin_attributes) 67 ldap = LdapAuthentication.new(context.environment.ldap_plugin_attributes)
47 begin 68 begin
48 - user = nil unless user.save 69 + user = nil unless user.save!
  70 + plugins.dispatch(:ldap_plugin_update_user, user, attrs)
49 rescue 71 rescue
50 #User not saved 72 #User not saved
51 end 73 end
@@ -54,7 +76,6 @@ class LdapPlugin &lt; Noosfero::Plugin @@ -54,7 +76,6 @@ class LdapPlugin &lt; Noosfero::Plugin
54 end 76 end
55 77
56 else 78 else
57 -  
58 return nil if !user.activated? 79 return nil if !user.activated?
59 80
60 begin 81 begin
public/javascripts/report-abuse.js
1 jQuery(function($) { 1 jQuery(function($) {
2 $('.report-abuse-action').live('click', function() { 2 $('.report-abuse-action').live('click', function() {
3 - if($(this).attr('href')){  
4 - noosfero.modal.inline($(this).attr('href'), {  
5 - innerHeight: '300px',  
6 - innerWidth: '445px'  
7 - });  
8 - } 3 + if($(this).attr('href'))
  4 + noosfero.modal.url($(this).attr('href'));
  5 +
9 return false; 6 return false;
10 }); 7 });
11 8
script/production
@@ -85,7 +85,7 @@ environments_loop() { @@ -85,7 +85,7 @@ environments_loop() {
85 } 85 }
86 86
87 do_running() { 87 do_running() {
88 - pids=$(sed "s/.*/& /" tmp/pids/thin.*.pid | tr -d '\n' 2>/dev/null || true) 88 + pids=$(sed "s/.*/& /" tmp/pids/thin.*.pid 2>/dev/null | tr -d '\n')
89 # passes if any of $pids exist, fails otherwise 89 # passes if any of $pids exist, fails otherwise
90 kill -0 $pids > /dev/null 2>&1 90 kill -0 $pids > /dev/null 2>&1
91 } 91 }
test/factories.rb
@@ -454,7 +454,7 @@ module Noosfero::Factory @@ -454,7 +454,7 @@ module Noosfero::Factory
454 end 454 end
455 455
456 def defaults_for_suggest_article 456 def defaults_for_suggest_article
457 - { :name => 'Sender', :email => 'sender@example.com', :article_name => 'Some title', :article_body => 'some body text', :article_abstract => 'some abstract text'} 457 + { :name => 'Sender', :email => 'sender@example.com', :article => {:name => 'Some title', :body => 'some body text', :abstract => 'some abstract text'}}
458 end 458 end
459 459
460 def defaults_for_comment(params = {}) 460 def defaults_for_comment(params = {})
test/functional/cms_controller_test.rb
@@ -1407,22 +1407,57 @@ class CmsControllerTest &lt; ActionController::TestCase @@ -1407,22 +1407,57 @@ class CmsControllerTest &lt; ActionController::TestCase
1407 assert_template 'suggest_an_article' 1407 assert_template 'suggest_an_article'
1408 end 1408 end
1409 1409
  1410 + should 'display name and email when a not logged in user suggest an article' do
  1411 + logout
  1412 + get :suggest_an_article, :profile => profile.identifier, :back_to => 'action_view'
  1413 +
  1414 + assert_select '#task_name'
  1415 + assert_select '#task_email'
  1416 + end
  1417 +
  1418 + should 'do not display name and email when a logged in user suggest an article' do
  1419 + get :suggest_an_article, :profile => profile.identifier, :back_to => 'action_view'
  1420 +
  1421 + assert_select '#task_name', 0
  1422 + assert_select '#task_email', 0
  1423 + end
  1424 +
  1425 + should 'display captcha when suggest an article for not logged in users' do
  1426 + logout
  1427 + get :suggest_an_article, :profile => profile.identifier, :back_to => 'action_view'
  1428 +
  1429 + assert_select '#dynamic_recaptcha'
  1430 + end
  1431 +
  1432 + should 'not display captcha when suggest an article for logged in users' do
  1433 + get :suggest_an_article, :profile => profile.identifier, :back_to => 'action_view'
  1434 +
  1435 + assert_select '#dynamic_recaptcha', 0
  1436 + end
  1437 +
1410 should 'render TinyMce Editor on suggestion of article' do 1438 should 'render TinyMce Editor on suggestion of article' do
1411 logout 1439 logout
1412 get :suggest_an_article, :profile => profile.identifier 1440 get :suggest_an_article, :profile => profile.identifier
1413 1441
1414 - assert_tag :tag => 'textarea', :attributes => { :name => /article_abstract/, :class => 'mceEditor' }  
1415 - assert_tag :tag => 'textarea', :attributes => { :name => /article_body/, :class => 'mceEditor' } 1442 + assert_tag :tag => 'textarea', :attributes => { :name => /task\[article\]\[abstract\]/, :class => 'mceEditor' }
  1443 + assert_tag :tag => 'textarea', :attributes => { :name => /task\[article\]\[body\]/, :class => 'mceEditor' }
1416 end 1444 end
1417 1445
1418 should 'create a task suggest task to a profile' do 1446 should 'create a task suggest task to a profile' do
1419 c = Community.create!(:name => 'test comm', :identifier => 'test_comm', :moderated_articles => true) 1447 c = Community.create!(:name => 'test comm', :identifier => 'test_comm', :moderated_articles => true)
1420 1448
1421 assert_difference 'SuggestArticle.count' do 1449 assert_difference 'SuggestArticle.count' do
1422 - post :suggest_an_article, :profile => c.identifier, :back_to => 'action_view', :task => {:article_name => 'some name', :article_body => 'some body', :email => 'some@localhost.com', :name => 'some name'} 1450 + post :suggest_an_article, :profile => c.identifier, :back_to => 'action_view', :task => {:article => {:name => 'some name', :body => 'some body'}, :email => 'some@localhost.com', :name => 'some name'}
1423 end 1451 end
1424 end 1452 end
1425 1453
  1454 + should 'create suggest task with logged in user as the article author' do
  1455 + c = Community.create!(:name => 'test comm', :identifier => 'test_comm', :moderated_articles => true)
  1456 +
  1457 + post :suggest_an_article, :profile => c.identifier, :back_to => 'action_view', :task => {:article => {:name => 'some name', :body => 'some body'}}
  1458 + assert_equal profile, SuggestArticle.last.requestor
  1459 + end
  1460 +
1426 should 'suggest an article from a profile' do 1461 should 'suggest an article from a profile' do
1427 c = Community.create!(:name => 'test comm', :identifier => 'test_comm', :moderated_articles => true) 1462 c = Community.create!(:name => 'test comm', :identifier => 'test_comm', :moderated_articles => true)
1428 get :suggest_an_article, :profile => c.identifier, :back_to => c.identifier 1463 get :suggest_an_article, :profile => c.identifier, :back_to => c.identifier
test/functional/spam_controller_test.rb
@@ -10,7 +10,7 @@ class SpamControllerTest &lt; ActionController::TestCase @@ -10,7 +10,7 @@ class SpamControllerTest &lt; ActionController::TestCase
10 @article = fast_create(TextileArticle, :profile_id => @community.id) 10 @article = fast_create(TextileArticle, :profile_id => @community.id)
11 @spam_comment = fast_create(Comment, :source_id => @article.id, :spam => true, :name => 'foo', :email => 'foo@example.com') 11 @spam_comment = fast_create(Comment, :source_id => @article.id, :spam => true, :name => 'foo', :email => 'foo@example.com')
12 12
13 - @spam_suggest_article = SuggestArticle.create!(:name => 'spammer', :article_name => 'Spam article', :email => 'spammer@shady.place', :article_body => "Something you don't need", :target => @community, :spam => true) 13 + @spam_suggest_article = SuggestArticle.create!(:name => 'spammer', :article => {:name => 'Spam article', :body => "Something you don't need"}, :email => 'spammer@shady.place', :target => @community, :spam => true)
14 login_as @profile.identifier 14 login_as @profile.identifier
15 end 15 end
16 16
test/functional/tasks_controller_test.rb
@@ -295,11 +295,11 @@ class TasksControllerTest &lt; ActionController::TestCase @@ -295,11 +295,11 @@ class TasksControllerTest &lt; ActionController::TestCase
295 c = fast_create(Community) 295 c = fast_create(Community)
296 c.add_admin profile 296 c.add_admin profile
297 @controller.stubs(:profile).returns(c) 297 @controller.stubs(:profile).returns(c)
298 - t = SuggestArticle.create!(:article_name => 'test name', :article_abstract => 'test abstract', :article_body => 'test body', :name => 'some name', :email => 'test@localhost.com', :target => c) 298 + t = SuggestArticle.create!(:article => {:name => 'test name', :abstract => 'test abstract', :body => 'test body'}, :name => 'some name', :email => 'test@localhost.com', :target => c)
299 299
300 get :index 300 get :index
301 - assert_tag :tag => 'textarea', :content => /test abstract/, :attributes => { :name => /article_abstract/, :class => 'mceEditor' }  
302 - assert_tag :tag => 'textarea', :content => /test body/, :attributes => { :name => /article_body/, :class => 'mceEditor' } 301 + assert_tag :tag => 'textarea', :content => /test abstract/, :attributes => { :name => /tasks\[#{t.id}\]\[task\]\[article\]\[abstract\]/, :class => 'mceEditor' }
  302 + assert_tag :tag => 'textarea', :content => /test body/, :attributes => { :name => /tasks\[#{t.id}\]\[task\]\[article\]\[body\]/, :class => 'mceEditor' }
303 end 303 end
304 304
305 should 'create TinyMceArticle article after finish approve suggested article task' do 305 should 'create TinyMceArticle article after finish approve suggested article task' do
@@ -307,7 +307,7 @@ class TasksControllerTest &lt; ActionController::TestCase @@ -307,7 +307,7 @@ class TasksControllerTest &lt; ActionController::TestCase
307 c = fast_create(Community) 307 c = fast_create(Community)
308 c.affiliate(profile, Profile::Roles.all_roles(profile.environment.id)) 308 c.affiliate(profile, Profile::Roles.all_roles(profile.environment.id))
309 @controller.stubs(:profile).returns(c) 309 @controller.stubs(:profile).returns(c)
310 - t = SuggestArticle.create!(:article_name => 'test name', :article_body => 'test body', :name => 'some name', :email => 'test@localhost.com', :target => c) 310 + t = SuggestArticle.create!(:article => {:name => 'test name', :body => 'test body'}, :name => 'some name', :email => 'test@localhost.com', :target => c)
311 311
312 post :close, :tasks => {t.id => { :task => {}, :decision => "finish"}} 312 post :close, :tasks => {t.id => { :task => {}, :decision => "finish"}}
313 assert_not_nil TinyMceArticle.find(:first) 313 assert_not_nil TinyMceArticle.find(:first)
@@ -319,16 +319,13 @@ class TasksControllerTest &lt; ActionController::TestCase @@ -319,16 +319,13 @@ class TasksControllerTest &lt; ActionController::TestCase
319 c.affiliate(profile, Profile::Roles.all_roles(profile.environment.id)) 319 c.affiliate(profile, Profile::Roles.all_roles(profile.environment.id))
320 @controller.stubs(:profile).returns(c) 320 @controller.stubs(:profile).returns(c)
321 t = SuggestArticle.new 321 t = SuggestArticle.new
322 - t.article_name = 'test name'  
323 - t.article_body = 'test body' 322 + t.article = {:name => 'test name', :body => 'test body', :source => 'http://test.com', :source_name => 'some source name'}
324 t.name = 'some name' 323 t.name = 'some name'
325 - t.source = 'http://test.com'  
326 - t.source_name = 'some source name'  
327 t.email = 'test@localhost.com' 324 t.email = 'test@localhost.com'
328 t.target = c 325 t.target = c
329 t.save! 326 t.save!
330 327
331 - post :close, :tasks => {t.id => { :task => {:article_name => 'new article name', :article_body => 'new body', :source => 'http://www.noosfero.com', :source_name => 'new source', :name => 'new name'}, :decision => "finish"}} 328 + post :close, :tasks => {t.id => { :task => {:article => {:name => 'new article name', :body => 'new body', :source => 'http://www.noosfero.com', :source_name => 'new source'}, :name => 'new name'}, :decision => "finish"}}
332 assert_equal 'new article name', TinyMceArticle.find(:first).name 329 assert_equal 'new article name', TinyMceArticle.find(:first).name
333 assert_equal 'new name', TinyMceArticle.find(:first).author_name 330 assert_equal 'new name', TinyMceArticle.find(:first).author_name
334 assert_equal 'new body', TinyMceArticle.find(:first).body 331 assert_equal 'new body', TinyMceArticle.find(:first).body
@@ -336,6 +333,51 @@ class TasksControllerTest &lt; ActionController::TestCase @@ -336,6 +333,51 @@ class TasksControllerTest &lt; ActionController::TestCase
336 assert_equal 'new source', TinyMceArticle.find(:first).source_name 333 assert_equal 'new source', TinyMceArticle.find(:first).source_name
337 end 334 end
338 335
  336 + should "display name from article suggestion when requestor was not setted" do
  337 + Task.destroy_all
  338 + c = fast_create(Community)
  339 + c.add_admin profile
  340 + @controller.stubs(:profile).returns(c)
  341 + t = SuggestArticle.create!(:article => {:name => 'test name', :abstract => 'test abstract', :body => 'test body'}, :name => 'some name', :email => 'test@localhost.com', :target => c)
  342 +
  343 + get :index
  344 + assert_select "#tasks_#{t.id}_task_name"
  345 + end
  346 +
  347 + should "append hidden tag with type value from article suggestion" do
  348 + Task.destroy_all
  349 + c = fast_create(Community)
  350 + c.add_admin profile
  351 + @controller.stubs(:profile).returns(c)
  352 + t = SuggestArticle.create!(:article => {:name => 'test name', :abstract => 'test abstract', :body => 'test body', :type => 'TextArticle'}, :name => 'some name', :email => 'test@localhost.com', :target => c)
  353 +
  354 + get :index
  355 + assert_select "#tasks_#{t.id}_task_article_type[value=TextArticle]"
  356 + end
  357 +
  358 + should "display parent_id selection from article suggestion with predefined value" do
  359 + Task.destroy_all
  360 + c = fast_create(Community)
  361 + c.add_admin profile
  362 + @controller.stubs(:profile).returns(c)
  363 + parent = fast_create(Folder, :profile_id => c.id)
  364 + t = SuggestArticle.create!(:article => {:name => 'test name', :abstract => 'test abstract', :body => 'test body', :parent_id => parent.id}, :name => 'some name', :email => 'test@localhost.com', :target => c)
  365 +
  366 + get :index
  367 + assert_select "#tasks_#{t.id}_task_article_parent_id option[value=#{parent.id}]"
  368 + end
  369 +
  370 + should "not display name from article suggestion when requestor was setted" do
  371 + Task.destroy_all
  372 + c = fast_create(Community)
  373 + c.add_admin profile
  374 + @controller.stubs(:profile).returns(c)
  375 + t = SuggestArticle.create!(:article => {:name => 'test name', :abstract => 'test abstract', :body => 'test body'}, :requestor => fast_create(Person), :target => c)
  376 +
  377 + get :index
  378 + assert_select "#tasks_#{t.id}_task_name", 0
  379 + end
  380 +
339 should "not crash if accessing close without tasks parameter" do 381 should "not crash if accessing close without tasks parameter" do
340 assert_nothing_raised do 382 assert_nothing_raised do
341 post :close 383 post :close
test/unit/api/articles_test.rb
@@ -492,4 +492,26 @@ class ArticlesTest &lt; ActiveSupport::TestCase @@ -492,4 +492,26 @@ class ArticlesTest &lt; ActiveSupport::TestCase
492 assert_equal ['title'], json['articles'].first.keys 492 assert_equal ['title'], json['articles'].first.keys
493 end 493 end
494 494
  495 + should 'suggest article children' do
  496 + article = fast_create(Article, :profile_id => user.person.id, :name => "Some thing")
  497 + params[:target_id] = user.person.id
  498 + params[:article] = {:name => "Article name", :body => "Article body"}
  499 + assert_difference "SuggestArticle.count" do
  500 + post "/api/v1/articles/#{article.id}/children/suggest?#{params.to_query}"
  501 + end
  502 + json = JSON.parse(last_response.body)
  503 + assert_equal 'SuggestArticle', json['type']
  504 + end
  505 +
  506 + should 'suggest event children' do
  507 + article = fast_create(Article, :profile_id => user.person.id, :name => "Some thing")
  508 + params[:target_id] = user.person.id
  509 + params[:article] = {:name => "Article name", :body => "Article body", :type => "Event"}
  510 + assert_difference "SuggestArticle.count" do
  511 + post "/api/v1/articles/#{article.id}/children/suggest?#{params.to_query}"
  512 + end
  513 + json = JSON.parse(last_response.body)
  514 + assert_equal 'SuggestArticle', json['type']
  515 + end
  516 +
495 end 517 end
test/unit/block_test.rb
@@ -364,4 +364,10 @@ class BlockTest &lt; ActiveSupport::TestCase @@ -364,4 +364,10 @@ class BlockTest &lt; ActiveSupport::TestCase
364 assert_equal 'block_preview.png', NewBlock.default_preview_path 364 assert_equal 'block_preview.png', NewBlock.default_preview_path
365 end 365 end
366 366
  367 + should 'get limit as a number when limit is string' do
  368 + block = RecentDocumentsBlock.new
  369 + block.settings[:limit] = '5'
  370 + assert block.get_limit.is_a?(Fixnum)
  371 + end
  372 +
367 end 373 end
test/unit/highlights_block_test.rb
@@ -109,33 +109,14 @@ class HighlightsBlockTest &lt; ActiveSupport::TestCase @@ -109,33 +109,14 @@ class HighlightsBlockTest &lt; ActiveSupport::TestCase
109 end 109 end
110 110
111 should 'list images randomically' do 111 should 'list images randomically' do
112 - f1 = mock()  
113 - f1.expects(:public_filename).returns('address')  
114 - UploadedFile.expects(:find).with(1).returns(f1)  
115 - f2 = mock()  
116 - f2.expects(:public_filename).returns('address')  
117 - UploadedFile.expects(:find).with(2).returns(f2)  
118 - f3 = mock()  
119 - f3.expects(:public_filename).returns('address')  
120 - UploadedFile.expects(:find).with(3).returns(f3)  
121 - f4 = mock()  
122 - f4.expects(:public_filename).returns('address')  
123 - UploadedFile.expects(:find).with(4).returns(f4)  
124 - f5 = mock()  
125 - f5.expects(:public_filename).returns('address')  
126 - UploadedFile.expects(:find).with(5).returns(f5)  
127 block = HighlightsBlock.new 112 block = HighlightsBlock.new
128 - i1 = {:image_id => 1, :address => '/address', :position => 3, :title => 'address'}  
129 - i2 = {:image_id => 2, :address => '/address', :position => 1, :title => 'address'}  
130 - i3 = {:image_id => 3, :address => '/address', :position => 2, :title => 'address'}  
131 - i4 = {:image_id => 4, :address => '/address', :position => 5, :title => 'address'}  
132 - i5 = {:image_id => 5, :address => '/address', :position => 4, :title => 'address'}  
133 - block.images = [i1,i2,i3,i4,i5]  
134 block.shuffle = true 113 block.shuffle = true
135 - block.save!  
136 - block.reload  
137 - assert_equal [i1,i2,i3,i4,i5], block.images  
138 - assert_not_equal [i2,i3,i1,i4,i5], block.featured_images 114 +
  115 + images = []
  116 + block.expects(:get_images).returns(images)
  117 + images.expects(:shuffle).returns(images)
  118 +
  119 + block.featured_images
139 end 120 end
140 121
141 [Environment, Profile].each do |klass| 122 [Environment, Profile].each do |klass|
test/unit/layout_helper_test.rb
@@ -30,4 +30,17 @@ class LayoutHelperTest &lt; ActionView::TestCase @@ -30,4 +30,17 @@ class LayoutHelperTest &lt; ActionView::TestCase
30 assert_match /<link [^<]*href="\/designs\/themes\/my-theme\/global.css"/, css 30 assert_match /<link [^<]*href="\/designs\/themes\/my-theme\/global.css"/, css
31 end 31 end
32 32
  33 + should 'append javascript files of enabled plugins in noosfero javascripts' do
  34 + plugin1 = Noosfero::Plugin.new
  35 + plugin1.expects(:js_files).returns(['plugin1.js'])
  36 + plugin2 = Noosfero::Plugin.new
  37 + plugin2.expects(:js_files).returns('plugin2.js')
  38 + @plugins = [plugin1, plugin2]
  39 + expects(:environment).returns(Environment.default).at_least_once
  40 + expects(:profile).returns(nil).at_least_once
  41 + js_tag = noosfero_javascript
  42 + assert_match /plugin1\.js/, js_tag
  43 + assert_match /plugin2\.js/, js_tag
  44 + end
  45 +
33 end 46 end
test/unit/suggest_article_test.rb
@@ -13,16 +13,9 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase @@ -13,16 +13,9 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
13 13
14 should 'have the article_name' do 14 should 'have the article_name' do
15 t = SuggestArticle.new 15 t = SuggestArticle.new
16 - assert !t.errors[:article_name.to_s].present?  
17 - t.valid?  
18 - assert t.errors[:article_name.to_s].present?  
19 - end  
20 -  
21 - should 'have the article_body' do  
22 - t = SuggestArticle.new  
23 - assert !t.errors[:article_body.to_s].present?  
24 - t.valid?  
25 - assert t.errors[:article_body.to_s].present? 16 + assert !t.article_object.errors[:name].present?
  17 + t.article_object.valid?
  18 + assert t.article_object.errors[:name].present?
26 end 19 end
27 20
28 should 'have the email' do 21 should 'have the email' do
@@ -46,19 +39,12 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase @@ -46,19 +39,12 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
46 assert t.errors[:target_id.to_s].present? 39 assert t.errors[:target_id.to_s].present?
47 end 40 end
48 41
49 - should 'have the article_abstract' do  
50 - t = SuggestArticle.new  
51 - assert t.respond_to?(:article_abstract)  
52 - end  
53 -  
54 - should 'have the article_parent_id' do  
55 - t = SuggestArticle.new  
56 - assert t.respond_to?(:article_parent_id)  
57 - end  
58 -  
59 - should 'source be defined' do 42 + should 'have the article' do
60 t = SuggestArticle.new 43 t = SuggestArticle.new
61 - assert t.respond_to?(:source) 44 + assert t.respond_to?(:article_object)
  45 + assert !t.errors[:article_object].present?
  46 + t.valid?
  47 + assert t.errors[:article_object].present?
62 end 48 end
63 49
64 should 'create an article on with perfom method' do 50 should 'create an article on with perfom method' do
@@ -66,9 +52,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase @@ -66,9 +52,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
66 name = 'some name' 52 name = 'some name'
67 body = 'some body' 53 body = 'some body'
68 abstract = 'some abstract' 54 abstract = 'some abstract'
69 - t.article_name = name  
70 - t.article_body = body  
71 - t.article_abstract = abstract 55 + t.article = {:name => name, :body => body, :abstract => abstract}
72 t.target = @profile 56 t.target = @profile
73 count = TinyMceArticle.count 57 count = TinyMceArticle.count
74 t.perform 58 t.perform
@@ -77,8 +61,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase @@ -77,8 +61,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
77 61
78 should 'fill source name and URL into created article' do 62 should 'fill source name and URL into created article' do
79 t = build(SuggestArticle, :target => @profile) 63 t = build(SuggestArticle, :target => @profile)
80 - t.source_name = 'GNU project'  
81 - t.source = 'http://www.gnu.org/' 64 + t.article.merge!({:source_name => 'GNU project', :source => 'http://www.gnu.org/'})
82 t.perform 65 t.perform
83 66
84 article = TinyMceArticle.last 67 article = TinyMceArticle.last
@@ -95,7 +78,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase @@ -95,7 +78,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
95 78
96 should 'highlight created article' do 79 should 'highlight created article' do
97 t = build(SuggestArticle, :target => @profile) 80 t = build(SuggestArticle, :target => @profile)
98 - t.highlighted = true 81 + t.article[:highlighted] = true
99 t.perform 82 t.perform
100 83
101 article = TinyMceArticle.last(:conditions => { :name => t.article_name}) # just to be sure 84 article = TinyMceArticle.last(:conditions => { :name => t.article_name}) # just to be sure
@@ -132,19 +115,19 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase @@ -132,19 +115,19 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
132 end 115 end
133 116
134 should 'have target notification message' do 117 should 'have target notification message' do
135 - task = build(SuggestArticle, :target => @profile, :article_name => 'suggested article', :name => 'johndoe') 118 + task = build(SuggestArticle, :target => @profile, :article => {:name => 'suggested article'}, :name => 'johndoe')
136 119
137 assert_match(/#{task.name}.*suggested the publication of the article: #{task.subject}.*[\n]*.*to approve or reject/, task.target_notification_message) 120 assert_match(/#{task.name}.*suggested the publication of the article: #{task.subject}.*[\n]*.*to approve or reject/, task.target_notification_message)
138 end 121 end
139 122
140 should 'have target notification description' do 123 should 'have target notification description' do
141 - task = build(SuggestArticle,:target => @profile, :article_name => 'suggested article', :name => 'johndoe') 124 + task = build(SuggestArticle,:target => @profile, :article => {:name => 'suggested article'}, :name => 'johndoe')
142 125
143 assert_match(/#{task.name}.*suggested the publication of the article: #{task.subject}/, task.target_notification_description) 126 assert_match(/#{task.name}.*suggested the publication of the article: #{task.subject}/, task.target_notification_description)
144 end 127 end
145 128
146 should 'deliver target notification message' do 129 should 'deliver target notification message' do
147 - task = build(SuggestArticle, :target => @profile, :article_name => 'suggested article', :name => 'johndoe', :email => 'johndoe@example.com') 130 + task = build(SuggestArticle, :target => @profile, :article => {:name => 'suggested article'}, :name => 'johndoe', :email => 'johndoe@example.com')
148 131
149 email = TaskMailer.target_notification(task, task.target_notification_message).deliver 132 email = TaskMailer.target_notification(task, task.target_notification_message).deliver
150 133
@@ -160,7 +143,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase @@ -160,7 +143,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
160 should 'delegate spam detection to plugins' do 143 should 'delegate spam detection to plugins' do
161 Environment.default.enable_plugin(EverythingIsSpam) 144 Environment.default.enable_plugin(EverythingIsSpam)
162 145
163 - t1 = build(SuggestArticle, :target => @profile, :article_name => 'suggested article', :name => 'johndoe', :email => 'johndoe@example.com') 146 + t1 = build(SuggestArticle, :target => @profile, :article => {:name => 'suggested article'}, :name => 'johndoe', :email => 'johndoe@example.com')
164 147
165 EverythingIsSpam.any_instance.expects(:check_for_spam) 148 EverythingIsSpam.any_instance.expects(:check_for_spam)
166 149
@@ -189,7 +172,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase @@ -189,7 +172,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
189 should 'notify plugins of suggest_articles being marked as spam' do 172 should 'notify plugins of suggest_articles being marked as spam' do
190 Environment.default.enable_plugin(SpamNotification) 173 Environment.default.enable_plugin(SpamNotification)
191 174
192 - t = SuggestArticle.create!(:target => @profile, :article_name => 'suggested article', :name => 'johndoe', :article_body => 'wanna feel my body? my body baaaby', :email => 'johndoe@example.com') 175 + t = SuggestArticle.create!(:target => @profile, :article => {:name => 'suggested article', :body => 'wanna feel my body? my body baaaby'}, :name => 'johndoe', :email => 'johndoe@example.com')
193 176
194 t.spam! 177 t.spam!
195 process_delayed_job_queue 178 process_delayed_job_queue
@@ -200,7 +183,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase @@ -200,7 +183,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
200 should 'notify plugins of suggest_articles being marked as ham' do 183 should 'notify plugins of suggest_articles being marked as ham' do
201 Environment.default.enable_plugin(SpamNotification) 184 Environment.default.enable_plugin(SpamNotification)
202 185
203 - t = SuggestArticle.create!(:target => @profile, :article_name => 'suggested article', :name => 'johndoe', :article_body => 'wanna feel my body? my body baaaby', :email => 'johndoe@example.com') 186 + t = SuggestArticle.create!(:target => @profile, :article => {:name => 'suggested article', :body => 'wanna feel my body? my body baaaby'}, :name => 'johndoe', :email => 'johndoe@example.com')
204 187
205 t.ham! 188 t.ham!
206 process_delayed_job_queue 189 process_delayed_job_queue
@@ -219,10 +202,44 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase @@ -219,10 +202,44 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
219 end 202 end
220 203
221 should 'log spammer ip after marking comment as spam' do 204 should 'log spammer ip after marking comment as spam' do
222 - t = SuggestArticle.create!(:target => @profile, :article_name => 'suggested article', :name => 'johndoe', :article_body => 'wanna feel my body? my body baaaby', :email => 'johndoe@example.com', :ip_address => '192.168.0.1') 205 + t = SuggestArticle.create!(:target => @profile, :article => {:name => 'suggested article', :body => 'wanna feel my body? my body baaaby'}, :name => 'johndoe', :email => 'johndoe@example.com', :ip_address => '192.168.0.1')
223 t.spam! 206 t.spam!
224 log = File.open('log/test_spammers.log') 207 log = File.open('log/test_spammers.log')
225 assert_match "SuggestArticle-id: #{t.id} IP: 192.168.0.1", log.read 208 assert_match "SuggestArticle-id: #{t.id} IP: 192.168.0.1", log.read
226 end 209 end
227 210
  211 + should 'not require name and email when requestor is present' do
  212 + t = SuggestArticle.new(:requestor => fast_create(Person))
  213 + t.valid?
  214 + assert t.errors[:email].blank?
  215 + assert t.errors[:name].blank?
  216 + end
  217 +
  218 + should 'return name as sender when requestor is setted' do
  219 + person = fast_create(Person)
  220 + t = SuggestArticle.new(:requestor => person)
  221 + assert_equal person.name, t.sender
  222 + end
  223 +
  224 + should 'create an event on perfom method' do
  225 + t = SuggestArticle.new
  226 + t.article = {:name => 'name', :body => 'body', :type => 'Event'}
  227 + t.target = @profile
  228 + assert_difference "Event.count" do
  229 + t.perform
  230 + end
  231 + end
  232 +
  233 + should 'accept article type parameter' do
  234 + t = SuggestArticle.new
  235 + t.article = {:name => 'name', :body => 'body', :type => 'TextArticle'}
  236 + t.article_type == TextArticle
  237 + end
  238 +
  239 + should 'fallback to tinymce when type parameter is invalid' do
  240 + t = SuggestArticle.new
  241 + t.article = {:name => 'name', :body => 'body', :type => 'Comment'}
  242 + t.article_type == TinyMceArticle
  243 + end
  244 +
228 end 245 end
test/unit/user_mailer_test.rb
@@ -18,6 +18,14 @@ class UserMailerTest &lt; ActiveSupport::TestCase @@ -18,6 +18,14 @@ class UserMailerTest &lt; ActiveSupport::TestCase
18 end 18 end
19 end 19 end
20 20
  21 + should 'deliver profiles suggestions email' do
  22 + person = create_user('some-user').person
  23 + ProfileSuggestion.create!(:person => person, :suggestion =>
  24 +fast_create(Person))
  25 + email = UserMailer.profiles_suggestions_email(person).deliver
  26 + assert_match /profile\/some-user\/friends\/suggest/, email.body.to_s
  27 + end
  28 +
21 private 29 private
22 30
23 def read_fixture(action) 31 def read_fixture(action)
test/unit/user_test.rb
@@ -87,6 +87,14 @@ class UserTest &lt; ActiveSupport::TestCase @@ -87,6 +87,14 @@ class UserTest &lt; ActiveSupport::TestCase
87 assert_equal person_count + 1, Person.count 87 assert_equal person_count + 1, Person.count
88 end 88 end
89 89
  90 + def test_should_create_person_with_identifier_different_from_login
  91 + user = User.create!(:login => 'new_user', :email => 'new_user@example.com', :password => 'test', :password_confirmation => 'test', :person_data => {:identifier => "new_test"})
  92 +
  93 + assert Person.exists?(['user_id = ?', user.id])
  94 +
  95 + assert user.login != user.person.identifier
  96 + end
  97 +
90 def test_login_validation 98 def test_login_validation
91 u = User.new 99 u = User.new
92 u.valid? 100 u.valid?
@@ -355,7 +363,7 @@ class UserTest &lt; ActiveSupport::TestCase @@ -355,7 +363,7 @@ class UserTest &lt; ActiveSupport::TestCase
355 Person.any_instance.stubs(:created_at).returns(DateTime.parse('16-08-2010')) 363 Person.any_instance.stubs(:created_at).returns(DateTime.parse('16-08-2010'))
356 expected_hash = { 364 expected_hash = {
357 'login' => 'x_and_y', 'is_admin' => true, 'since_month' => 8, 365 'login' => 'x_and_y', 'is_admin' => true, 'since_month' => 8,
358 - 'chat_enabled' => false, 'since_year' => 2010, 'email_domain' => nil, 366 + 'chat_enabled' => false, 'since_year' => 2010, 'email_domain' => nil,
359 'amount_of_friends' => 0, 'friends_list' => {}, 'enterprises' => [], 367 'amount_of_friends' => 0, 'friends_list' => {}, 'enterprises' => [],
360 } 368 }
361 369