Commit da4b277d048cee258e8d174df2eb243dc20136d4

Authored by Leandro Santos
2 parents 08b24ad2 a5c0c0f3

Merge branches 'rails235' and 'noosfero_grape_api' into noosfero_grape_api

Showing 60 changed files with 1197 additions and 225 deletions   Show diff stats
app/controllers/embed_controller.rb 0 → 100644
... ... @@ -0,0 +1,13 @@
  1 +class EmbedController < ApplicationController
  2 + layout 'embed'
  3 +
  4 + def block
  5 + @block = Block.find(params[:id])
  6 + if !@block.embedable? || !@block.visible?
  7 + render 'unavailable.rhtml', :status => 403
  8 + end
  9 + rescue ActiveRecord::RecordNotFound
  10 + render 'not_found.rhtml', :status => 404
  11 + end
  12 +
  13 +end
... ...
app/controllers/my_profile/maps_controller.rb
... ... @@ -31,23 +31,11 @@ class MapsController &lt; MyProfileController
31 31 end
32 32  
33 33 def search_city
34   -
35   - term = params[:term];
36   -
37   - regions = NationalRegion.search_city(term + "%", true).map {|r|{ :label => r.city , :category => r.state}}
38   -
39   - render :json => regions
40   -
  34 + render :json => MapsHelper.search_city(params[:term])
41 35 end
42 36  
43 37 def search_state
44   -
45   - term = params[:term];
46   -
47   - regions = NationalRegion.search_state(term + "%", true).map {|r|{ :label => r.state}}
48   -
49   - render :json => regions
50   -
  38 + render :json => MapsHelper.search_state(params[:term])
51 39 end
52 40  
53 41 end
... ...
app/controllers/public/account_controller.rb
... ... @@ -250,15 +250,19 @@ class AccountController &lt; ApplicationController
250 250 end
251 251 end
252 252  
253   - def check_url
  253 + def check_valid_name
254 254 @identifier = params[:identifier]
255 255 valid = Person.is_available?(@identifier, environment)
256 256 if valid
257 257 @status = _('This login name is available')
258 258 @status_class = 'validated'
259   - else
  259 + elsif !@identifier.empty?
  260 + @suggested_usernames = suggestion_based_on_username(@identifier)
260 261 @status = _('This login name is unavailable')
261 262 @status_class = 'invalid'
  263 + else
  264 + @status_class = 'invalid'
  265 + @status = _('This field can\'t be blank')
262 266 end
263 267 render :partial => 'identifier_status'
264 268 end
... ... @@ -291,6 +295,23 @@ class AccountController &lt; ApplicationController
291 295 render :text => user_data.to_json, :layout => false, :content_type => "application/javascript"
292 296 end
293 297  
  298 + def search_cities
  299 + if request.xhr? and params[:state_name] and params[:city_name]
  300 + render :json => MapsHelper.search_city(params[:city_name], params[:state_name])
  301 + else
  302 + render :json => [].to_json
  303 + end
  304 + end
  305 +
  306 + def search_state
  307 + if request.xhr? and params[:state_name]
  308 + render :json => MapsHelper.search_state(params[:state_name])
  309 + else
  310 + render :json => [].to_json
  311 + end
  312 + end
  313 +
  314 +
294 315 protected
295 316  
296 317 def redirect?
... ...
app/controllers/public/content_viewer_controller.rb
... ... @@ -50,7 +50,7 @@ class ContentViewerController &lt; ApplicationController
50 50 end
51 51  
52 52 # At this point the page will be showed
53   - @page.hit
  53 + @page.hit unless user_is_a_bot?
54 54  
55 55 @page = FilePresenter.for @page
56 56  
... ... @@ -183,4 +183,13 @@ class ContentViewerController &lt; ApplicationController
183 183 allowed
184 184 end
185 185  
  186 + def user_is_a_bot?
  187 + user_agent= request.env["HTTP_USER_AGENT"]
  188 + user_agent.blank? ||
  189 + user_agent.match(/bot/) ||
  190 + user_agent.match(/spider/) ||
  191 + user_agent.match(/crawler/) ||
  192 + user_agent.match(/\(.*https?:\/\/.*\)/)
  193 + end
  194 +
186 195 end
... ...
app/controllers/public/events_controller.rb
... ... @@ -21,7 +21,7 @@ class EventsController &lt; PublicController
21 21  
22 22 def events_by_day
23 23 @date = build_date(params[:year], params[:month], params[:day])
24   - @events = profile.events.by_day(@date)
  24 + @events = profile.events.by_day(@date).paginate(:per_page => per_page, :page => params[:page])
25 25 render :partial => 'events'
26 26 end
27 27  
... ...
app/helpers/account_helper.rb
... ... @@ -12,4 +12,17 @@ module AccountHelper
12 12 _('Checking if e-mail address is already taken...')
13 13 end
14 14 end
  15 +
  16 + def suggestion_based_on_username(requested_username='')
  17 + return "" if requested_username.empty?
  18 + usernames = []
  19 + 3.times do
  20 + begin
  21 + valid_name = requested_username + rand(1000).to_s
  22 + end while (usernames.include?(valid_name) || !Person.is_available?(valid_name, environment))
  23 + usernames << valid_name
  24 + end
  25 + usernames
  26 + end
  27 +
15 28 end
... ...
app/helpers/boxes_helper.rb
... ... @@ -219,6 +219,17 @@ module BoxesHelper
219 219 buttons << thickbox_inline_popup_icon(:help, _('Help on this block'), {}, "help-on-box-#{block.id}") << content_tag('div', content_tag('h2', _('Help')) + content_tag('div', block.help, :style => 'margin-bottom: 1em;') + thickbox_close_button(_('Close')), :style => 'display: none;', :id => "help-on-box-#{block.id}")
220 220 end
221 221  
  222 + if block.embedable?
  223 + embed_code = block.embed_code
  224 + embed_code = instance_eval(&embed_code) if embed_code.respond_to?(:call)
  225 + html = content_tag('div',
  226 + content_tag('h2', _('Embed block code')) +
  227 + content_tag('div', _('Below, you''ll see a field containing embed code for the block. Just copy the code and paste it into your website or blogging software.'), :style => 'margin-bottom: 1em;') +
  228 + content_tag('textarea', embed_code, :style => 'margin-bottom: 1em; width:100%; height:40%;', :readonly => 'readonly') +
  229 + thickbox_close_button(_('Close')), :style => 'display: none;', :id => "embed-code-box-#{block.id}")
  230 + buttons << thickbox_inline_popup_icon(:embed, _('Embed code'), {}, "embed-code-box-#{block.id}") << html
  231 + end
  232 +
222 233 content_tag('div', buttons.join("\n") + tag('br', :style => 'clear: left'), :class => 'button-bar')
223 234 end
224 235  
... ...
app/helpers/maps_helper.rb 0 → 100644
... ... @@ -0,0 +1,14 @@
  1 +module MapsHelper
  2 + def self.search_city term, state=""
  3 + cities = if state.empty?
  4 + NationalRegion.search_city(term + "%", true)
  5 + else
  6 + NationalRegion.search_city(term + "%", true, state)
  7 + end
  8 + cities.map {|r|{ :label => r.city , :category => r.state}}
  9 + end
  10 +
  11 + def self.search_state term
  12 + NationalRegion.search_state(term + "%", true).map {|r|{ :label => r.state}}
  13 + end
  14 +end
... ...
app/models/block.rb
... ... @@ -16,6 +16,23 @@ class Block &lt; ActiveRecord::Base
16 16  
17 17 named_scope :enabled, :conditions => { :enabled => true }
18 18  
  19 + def embedable?
  20 + false
  21 + end
  22 +
  23 + def embed_code
  24 + me = self
  25 + lambda do
  26 + content_tag('iframe', '',
  27 + :src => url_for(:controller => 'embed', :action => 'block', :id => me.id, :only_path => false),
  28 + :frameborder => 0,
  29 + :width => 1024,
  30 + :height => 768,
  31 + :class => "embed block #{me.class.name.to_css_class}"
  32 + )
  33 + end
  34 + end
  35 +
19 36 # Determines whether a given block must be visible. Optionally a
20 37 # <tt>context</tt> must be specified. <tt>context</tt> must be a hash, and
21 38 # may contain the following keys:
... ...
app/models/national_region.rb
... ... @@ -12,7 +12,7 @@ class NationalRegion &lt; ActiveRecord::Base
12 12 adtional_contions = "";
13 13  
14 14 if like
15   - operator = "like"
  15 + operator = "ilike"
16 16 find_return = :all
17 17 end
18 18  
... ... @@ -41,7 +41,7 @@ class NationalRegion &lt; ActiveRecord::Base
41 41 find_return = :first
42 42  
43 43 if like
44   - operator = "like"
  44 + operator = "ilike"
45 45 find_return = :all
46 46 end
47 47  
... ...
app/models/text_article.rb
... ... @@ -20,4 +20,23 @@ class TextArticle &lt; Article
20 20 def can_display_versions?
21 21 true
22 22 end
  23 +
  24 + before_save :set_relative_path
  25 +
  26 + def set_relative_path
  27 + parsed = Hpricot(self.body.to_s)
  28 + parsed.search('img[@src]').map { |i| change_element_path(i, 'src') }
  29 + parsed.search('a[@href]').map { |i| change_element_path(i, 'href') }
  30 + self.body = parsed.to_s
  31 + end
  32 +
  33 + def change_element_path(el, attribute)
  34 + fullpath = /(https?):\/\/(#{environment.default_hostname})(:\d+)?(\/.*)/.match(el[attribute])
  35 + if fullpath
  36 + domain = fullpath[2]
  37 + path = fullpath[4]
  38 + el[attribute] = path if domain == environment.default_hostname
  39 + end
  40 + end
  41 +
23 42 end
... ...
app/views/account/_identifier_status.rhtml
1 1 <div class='status-identifier'>
2   - <p><span class='<%= @status_class %>'><%= @status %></span></p>
  2 +
  3 + <span class='<%= @status_class %>'><%= @status %></span>
  4 + <% if @suggested_usernames %>
  5 + <div class='suggested_usernames'>
  6 + <%= _('Available: ') %>
  7 + <% @suggested_usernames.each do |username| %>
  8 + <a href='#'><%= username %></a>
  9 + <% end %>
  10 + </div>
  11 + <% end %>
3 12 <script type="text/javascript">
4 13 jQuery('#user_login').removeClass('<%= validation_classes %>');
5 14 jQuery('#user_login').addClass('<%= @status_class %>');
  15 + jQuery('.suggested_usernames a').click(function(e) {
  16 + e.preventDefault();
  17 +
  18 + fill_username(this.innerHTML);
  19 + });
6 20 </script>
7 21 </div>
... ...
app/views/account/_signup_form.rhtml
... ... @@ -37,20 +37,13 @@
37 37 <%= required text_field(:user, :login, :id => 'user_login',
38 38 :onchange => 'this.value = convToValidUsername(this.value);') %>
39 39 <div id='url-check'><p>&nbsp;</p></div>
  40 + <span id='checking-message' class='checking' style='display:none'><%= _('Checking availability of login name...') %></span>
40 41 </div>
41 42 <%= content_tag(:small, _('Choose your login name carefully! It will be your network access and you will not be able to change it later.'), :id => 'signup-balloon') %>
42 43 <br style="clear: both;" />
43 44 </div>
44 45 </div>
45   - <%= observe_field 'user_login',
46   - :url => { :action => 'check_url' },
47   - :with => 'identifier',
48   - :update => 'url-check',
49   - :loading => "jQuery('#user_login').removeClass('#{validation_classes}').addClass('checking');
50   - jQuery('#url-check').html('<p><span class=\"checking\">#{checking_message(:url)}</span></p>');",
51   - :complete => "jQuery('#user_login').removeClass('checking')"
52   - %>
53   -
  46 + <%= javascript_include_tag "signup_form" %>
54 47 <div id='signup-password'>
55 48 <%= required f.password_field(:password, :id => 'user_pw') %>
56 49 <%= content_tag(:small,_('Choose a password that you can remember easily. It must have at least 4 characters.'), :id => 'password-balloon') %>
... ... @@ -198,4 +191,8 @@ jQuery(function($) {
198 191 });
199 192 });
200 193  
  194 +function fill_username(element){
  195 + jQuery('#url-check').html("<p><span class='checking'><%= _('This login name is available') %></span></p>")
  196 + jQuery('#user_login').val(element).addClass('validated').removeClass('invalid')
  197 +}
201 198 </script>
... ...
app/views/embed/block.html.erb 0 → 100644
... ... @@ -0,0 +1 @@
  1 +<%= display_block(@block) %>
... ...
app/views/embed/not_found.rhtml 0 → 100644
... ... @@ -0,0 +1,6 @@
  1 +<div id='not-found'>
  2 + <p>
  3 + <%= _('You may have clicked an expired link or mistyped the address.') %>
  4 + <%= _('If you clicked a link that was in another site, or was given to you by someone else, it would be nice if you tell them that their link is not valid anymore.') %>
  5 + </p>
  6 +</div>
... ...
app/views/embed/unavailable.rhtml 0 → 100644
... ... @@ -0,0 +1,3 @@
  1 +<div id='unavailable'>
  2 + <p><%= _('Embed unavailable.') %></p>
  3 +</div>
... ...
app/views/layouts/embed.rhtml 0 → 100644
... ... @@ -0,0 +1,35 @@
  1 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2 +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<%= html_language %>" lang="<%= html_language %>">
  3 + <head>
  4 + <title>Noosfero embed block</title>
  5 + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  6 + <%= noosfero_stylesheets %>
  7 + <%= noosfero_javascript %>
  8 + </head>
  9 + <body class="<%= h body_classes %>">
  10 + <div id="embed">
  11 + <div id="wrap-1">
  12 + <div id="wrap-2">
  13 + <div id="content">
  14 + <div id="content-inner">
  15 + <div class="boxes" id="boxes">
  16 + <div class="box box-1" id="box-1">
  17 + <div class="blocks">
  18 + <%= yield %>
  19 + </div>
  20 + </div>
  21 + </div>
  22 + </div>
  23 + </div>
  24 + </div>
  25 + </div>
  26 + </div>
  27 +
  28 + <script type="text/javascript">
  29 + jQuery(document).ready(function(){
  30 + jQuery('a').attr('target','_blank');
  31 + });
  32 + </script>
  33 +
  34 + </body>
  35 +</html>
... ...
app/views/profile_editor/_person_form.rhtml
... ... @@ -19,8 +19,8 @@
19 19 <%= optional_field(@person, 'birth_date', labelled_form_field(_('Birth date'), '<div class="select-birth-date">' + pick_date(:profile_data, :birth_date, {:start_year => (Date.today.year - 100), :end_year => (Date.today.year - 5)}) + '</div>')) %>
20 20 <%= optional_field(@person, 'nationality', f.text_field(:nationality, :rel => _('Nationality'))) %>
21 21 <%= optional_field(@person, 'country', select_country(_('Country'), 'profile_data', 'country', {:class => 'type-select'})) %>
22   -<%= optional_field(@person, 'state', f.text_field(:state, :rel => _('State'))) %>
23   -<%= optional_field(@person, 'city', f.text_field(:city, :rel => _('City'))) %>
  22 +<%= optional_field(@person, 'state', f.text_field(:state, :id => 'state_field', :rel => _('State'))) %>
  23 +<%= optional_field(@person, 'city', f.text_field(:city, :id => 'city_field', :rel => _('City'))) %>
24 24 <%= optional_field(@person, 'zip_code', labelled_form_field(_('ZIP code'), text_field(:profile_data, :zip_code, :rel => _('ZIP code')))) %>
25 25 <%= optional_field(@person, 'address', labelled_form_field(_('Address (street and number)'), text_field(:profile_data, :address, :rel => _('Address')))) %>
26 26 <%= optional_field(@person, 'address_reference', labelled_form_field(_('Address reference'), text_field(:profile_data, :address_reference, :rel => _('Address reference')))) %>
... ... @@ -36,6 +36,7 @@
36 36 </div>
37 37 <% end %>
38 38  
  39 +<%= javascript_include_tag('city_state_validation') %>
39 40 <script type='text/javascript'>
40 41 function toggle_text_field(id, span_id) {
41 42 if ($(id).value == "Others") {
... ...
app/views/shared/_organization_custom_fields.rhtml
... ... @@ -13,8 +13,8 @@
13 13 <%= optional_field(profile, 'address_reference', labelled_form_field(_('Address reference'), text_field(object_name, :address_reference))) %>
14 14 <%= optional_field(profile, 'district', labelled_form_field(_('District'), text_field(object_name, :district))) %>
15 15 <%= optional_field(profile, 'zip_code', labelled_form_field(_('ZIP code'), text_field(object_name, :zip_code))) %>
16   -<%= optional_field(profile, 'city', f.text_field(:city)) %>
17   -<%= optional_field(profile, 'state', f.text_field(:state)) %>
  16 +<%= optional_field(profile, 'city', f.text_field(:city, :id =>'city_field')) %>
  17 +<%= optional_field(profile, 'state', f.text_field(:state,:id =>'state_field')) %>
18 18 <%= optional_field(profile, 'country', select_country(_('Country'), object_name, 'country', {:class => 'type-select'})) %>
19 19 <%= optional_field(profile, 'tag_list', f.text_field(:tag_list)) %>
20 20  
... ... @@ -29,3 +29,4 @@
29 29 <%= optional_field(profile, 'acronym', f.text_field(:acronym)) %>
30 30 <%= optional_field(profile, 'foundation_year', f.text_field(:foundation_year)) %>
31 31 <% end %>
  32 +<%= javascript_include_tag('city_state_validation') %>
... ...
config/routes.rb
... ... @@ -31,6 +31,9 @@ ActionController::Routing::Routes.draw do |map|
31 31 map.connect 'thumbnails/*stuff', :controller => 'not_found', :action => 'nothing'
32 32 map.connect 'user_themes/*stuff', :controller => 'not_found', :action => 'nothing'
33 33  
  34 + # embed controller
  35 + map.embed 'embed/:action/:id', :controller => 'embed', :id => /\d+/
  36 +
34 37 # online documentation
35 38 map.doc 'doc', :controller => 'doc', :action => 'index'
36 39 map.doc_section 'doc/:section', :controller => 'doc', :action => 'section'
... ...
features/balloon.feature
... ... @@ -8,6 +8,7 @@ Feature: balloon
8 8 And the following communities
9 9 | identifier | name |
10 10 | sample | Sample |
  11 + And I am logged in as "joaosilva"
11 12  
12 13 @selenium
13 14 Scenario: I should not see trigger if not enabled
... ...
features/categories_block.feature
... ... @@ -24,16 +24,12 @@ Feature: categories_block
24 24 | owner | type |
25 25 | environment | CategoriesBlock |
26 26 And I am logged in as admin
  27 + And I go to /admin/environment_design
  28 + And display ".button-bar"
27 29  
28   - # Note that this @ignore-hidden-elements only works for seeing hidden
29   - # elements. It actually doesn't work for following hidden link or pressing
30   - # hidden buttons. That's why it's necessary to use this display hack to show
31   - # the link.
32   - @selenium @ignore-hidden-elements
  30 + @selenium
33 31 Scenario: List just product categories
34   - Given I go to /admin/environment_design
35   - And display ".categories-block .button-bar"
36   - And I follow "Edit" within ".categories-block"
  32 + Given I follow "Edit" within ".categories-block"
37 33 And I check "Product"
38 34 When I press "Save"
39 35 Then I should see "Food"
... ... @@ -42,11 +38,9 @@ Feature: categories_block
42 38 And "Steak" should not be visible within "span#category-name"
43 39 And "Fiction" should not be visible within "span#category-name"
44 40  
45   - @selenium @ignore-hidden-elements
  41 + @selenium
46 42 Scenario: Show submenu if it exists
47   - Given I go to /admin/environment_design
48   - And display ".categories-block .button-bar"
49   - And I follow "Edit" within ".categories-block"
  43 + Given I follow "Edit" within ".categories-block"
50 44 And I check "Product"
51 45 And I press "Save"
52 46 Then I should see "Food"
... ... @@ -61,11 +55,9 @@ Feature: categories_block
61 55 And I should see "Steak"
62 56 And I should not see "Fiction"
63 57  
64   - @selenium @ignore-hidden-elements
  58 + @selenium
65 59 Scenario: Show only one submenu per time
66   - Given I go to /admin/environment_design
67   - And display ".categories-block .button-bar"
68   - And I follow "Edit" within ".categories-block"
  60 + Given I follow "Edit" within ".categories-block"
69 61 And I check "Product"
70 62 And I press "Save"
71 63 Then I should see "Book"
... ... @@ -73,20 +65,16 @@ Feature: categories_block
73 65 When I follow "block_2_category_2"
74 66 Then I should see "Literature"
75 67  
76   - @selenium @ignore-hidden-elements
  68 + @selenium
77 69 Scenario: List just general categories
78   - Given I go to /admin/environment_design
79   - And display ".categories-block .button-bar"
80   - And I follow "Edit" within ".categories-block"
  70 + Given I follow "Edit" within ".categories-block"
81 71 And I check "Generic category"
82 72 When I press "Save"
83 73 Then I should see "Wood"
84 74  
85   - @selenium @ignore-hidden-elements
  75 + @selenium
86 76 Scenario: List just regions
87   - Given I go to /admin/environment_design
88   - And display ".categories-block .button-bar"
89   - And I follow "Edit" within ".categories-block"
  77 + Given I follow "Edit" within ".categories-block"
90 78 And I check "Region"
91 79 When I press "Save"
92 80 Then I should see "Bahia"
... ...
features/comment.feature
... ... @@ -39,7 +39,7 @@ Feature: comment
39 39 When I press "Post comment"
40 40 Then I should see "Hey ho, let's go"
41 41  
42   - @selenium
  42 + @selenium-fixme
43 43 Scenario: redirect to right place after comment a picture
44 44 Given the following files
45 45 | owner | file | mime |
... ... @@ -134,4 +134,4 @@ Feature: comment
134 134 | Post one | joaosilva | Hello | Hello |
135 135 When I go to /joaosilva/forum/post-one
136 136 And I select "Oldest first" from "comment_order" within ".comment-order"
137   - Then I should see "Hi all" within ".article-comment"
138 137 \ No newline at end of file
  138 + Then I should see "Hi all" within ".article-comment"
... ...
features/short_filename.feature
... ... @@ -1,21 +0,0 @@
1   -Feature: sitemap
2   - As a noosfero user
3   - I want to list articles
4   -
5   - Background:
6   - Given I am on the homepage
7   - And the following users
8   - | login | name |
9   - | joaosilva | Joao Silva |
10   - And the following files
11   - | owner | file | mime |
12   - | joaosilva | AGENDA_CULTURA_-_FESTA_DE_VAQUEIROS_PONTO_DE_SERRA_PRETA_BAIXA.txt | text/plain |
13   -
14   - Scenario: view a folder page
15   - When I am on /profile/joaosilva/sitemap
16   - Then I should see "AGENDA_CULTURA_-_FESTA_DE_VAQUEIRO(...).txt"
17   -
18   - Scenario: view the CMS
19   - Given I am logged in as "joaosilva"
20   - When I am on /myprofile/joaosilva/cms
21   - Then I should see "AGENDA_CULTURA_-_FESTA_DE_VAQUEIROS_PONTO_DE_SERRA_(...).txt"
features/signup.feature
... ... @@ -29,10 +29,20 @@ Feature: signup
29 29 And I press "Log in"
30 30 Then I should be logged in as "josesilva"
31 31  
  32 + @selenium
  33 + Scenario: show error message if username is already used
  34 + Given the following users
  35 + | login |
  36 + | josesilva |
  37 + When I go to signup page
  38 + And I fill in "Username" with "josesilva"
  39 + And I fill in "e-Mail" with "josesilva1"
  40 + Then I should see "This login name is unavailable"
  41 +
32 42 Scenario: be redirected if user goes to signup page and is logged
33 43 Given the following users
34 44 | login | name |
35   - | joaosilva | Joao Silva |
  45 + | joaosilva | joao silva |
36 46 Given I am logged in as "joaosilva"
37 47 And I go to signup page
38 48 Then I should be on joaosilva's control panel
... ...
lib/feed_handler.rb
... ... @@ -51,7 +51,6 @@ class FeedHandler
51 51 end
52 52  
53 53 def process(container)
54   - RAILS_DEFAULT_LOGGER.info("Processing %s with id = %d" % [container.class.name, container.id])
55 54 begin
56 55 container.class.transaction do
57 56 if container.update_errors > FeedHandler.max_errors && container.fetched_at < (Time.now - FeedHandler.disabled_period)
... ...
lib/file_presenter.rb
... ... @@ -50,6 +50,10 @@ class FilePresenter
50 50 nil
51 51 end
52 52  
  53 + def download?(view=nil)
  54 + false
  55 + end
  56 +
53 57 def short_description
54 58 file_type = if content_type.present?
55 59 content_type.sub(/^application\//, '').sub(/^x-/, '').sub(/^image\//, '')
... ...
lib/tasks/plugins_tests.rake
... ... @@ -25,51 +25,87 @@ def plugin_disabled_warning(plugin)
25 25 puts "E: you should enable #{plugin} plugin before running it's tests!"
26 26 end
27 27  
28   -def run_tests(name, files_glob)
29   - files = Dir.glob(files_glob)
30   - if files.empty?
31   - puts "I: no tests to run (#{name})"
  28 +def task2ext(task)
  29 + (task == :selenium || task == :cucumber) ? :feature : :rb
  30 +end
  31 +
  32 +def task2profile(task, plugin)
  33 + if task == :cucumber
  34 + return plugin
  35 + elsif task == :selenium
  36 + return "#{plugin}_selenium"
32 37 else
33   - sh 'testrb', '-Itest', *files
  38 + return 'default'
34 39 end
35 40 end
36 41  
37   -def run_cucumber(name, profile, files_glob)
38   - files = Dir.glob(files_glob)
39   - if files.empty?
40   - puts "I: no tests to run #{name}"
  42 +def filename2plugin(filename)
  43 + filename.split('/')[1]
  44 +end
  45 +
  46 +def task2folder(task)
  47 + result = case task.to_sym
  48 + when :units
  49 + :unit
  50 + when :functionals
  51 + :functional
  52 + when :integration
  53 + :integration
  54 + when :cucumber
  55 + :features
  56 + when :selenium
  57 + :features
  58 + end
  59 +
  60 + return result
  61 +end
  62 +
  63 +def run_test(name, files)
  64 + files = Array(files)
  65 + plugin = filename2plugin(files.first)
  66 + if name == :cucumber || name == :selenium
  67 + run_cucumber task2_profile(name, plugin), files
41 68 else
42   - sh 'xvfb-run', 'ruby', '-S', 'cucumber', '--profile', profile.to_s, '--format', ENV['CUCUMBER_FORMAT'] || 'progress' , *files
  69 + run_testrb files
43 70 end
44 71 end
45 72  
46   -def plugin_test_task(name, plugin, files_glob)
47   - desc "Run #{name} tests for #{plugin_name(plugin)}"
48   - task name => 'db:test:plugins:prepare' do |t|
49   - if plugin_enabled?(plugin)
50   - run_tests t.name, files_glob
51   - else
52   - plugin_disabled_warning(plugin)
  73 +def run_testrb(files)
  74 + sh 'testrb', '-Itest', *files
  75 +end
  76 +
  77 +def run_cucumber(profile, files)
  78 + sh 'xvfb-run', 'ruby', '-S', 'cucumber', '--profile', profile.to_s, '--format', ENV['CUCUMBER_FORMAT'] || 'progress' , *files
  79 +end
  80 +
  81 +def custom_run(name, files, run=:individually)
  82 + case run
  83 + when :all
  84 + run_test name, files
  85 + when :individually
  86 + files.each do |file|
  87 + run_test name, file
53 88 end
  89 + when :by_plugin
54 90 end
55 91 end
56 92  
57   -def plugin_cucumber_task(name, plugin, files_glob)
58   - desc "Run #{name} tests for #{plugin_name(plugin)}"
59   - task name => 'db:test:plugins:prepare' do |t|
60   - if plugin_enabled?(plugin)
61   - run_cucumber t.name, plugin, files_glob
62   - else
63   - plugin_disabled_warning(plugin)
64   - end
  93 +def run_tests(name, plugins, run=:individually)
  94 + plugins = Array(plugins)
  95 + glob = "plugins/{#{plugins.join(',')}}/test/#{task2folder(name)}/**/*.#{task2ext(name)}"
  96 + files = Dir.glob(glob)
  97 + if files.empty?
  98 + puts "I: no tests to run #{name}"
  99 + else
  100 + custom_run(name, files, run)
65 101 end
66 102 end
67 103  
68   -def plugin_selenium_task(name, plugin, files_glob)
  104 +def plugin_test_task(name, plugin, run=:individually)
69 105 desc "Run #{name} tests for #{plugin_name(plugin)}"
70 106 task name => 'db:test:plugins:prepare' do |t|
71 107 if plugin_enabled?(plugin)
72   - run_cucumber t.name, "#{plugin}_selenium", files_glob
  108 + run_tests(name, plugin, run)
73 109 else
74 110 plugin_disabled_warning(plugin)
75 111 end
... ... @@ -98,28 +134,28 @@ namespace :test do
98 134 namespace :noosfero_plugins do
99 135 all_plugins.each do |plugin|
100 136 namespace plugin do
101   - plugin_test_task :units, plugin, "plugins/#{plugin}/test/unit/**/*.rb"
102   - plugin_test_task :functionals, plugin, "plugins/#{plugin}/test/functional/**/*.rb"
103   - plugin_test_task :integration, plugin, "plugins/#{plugin}/test/integration/**/*.rb"
104   - plugin_cucumber_task :cucumber, plugin, "plugins/#{plugin}/features/**/*.feature"
105   - plugin_selenium_task :selenium, plugin, "plugins/#{plugin}/features/**/*.feature"
  137 + plugin_test_task :units, plugin
  138 + plugin_test_task :functionals, plugin
  139 + plugin_test_task :integration, plugin
  140 + plugin_test_task :cucumber, plugin
  141 + plugin_test_task :selenium, plugin
106 142 end
107 143  
108 144 test_sequence_task(plugin, plugin, "#{plugin}:units", "#{plugin}:functionals", "#{plugin}:integration", "#{plugin}:cucumber", "#{plugin}:selenium")
109 145 end
110 146  
111   - { :units => :unit , :functionals => :functional , :integration => :integration }.each do |taskname,folder|
  147 + [:units, :functionals, :integration].each do |taskname|
112 148 task taskname => 'db:test:plugins:prepare' do |t|
113   - run_tests t.name, "plugins/{#{enabled_plugins.join(',')}}/test/#{folder}/**/*.rb"
  149 + run_tests taskname, enabled_plugins
114 150 end
115 151 end
116 152  
117 153 task :cucumber => 'db:test:plugins:prepare' do |t|
118   - run_cucumber t.name, :default, "plugins/{#{enabled_plugins.join(',')}}/test/features/**/*.features"
  154 + run_tests :cucumber, enabled_plugins
119 155 end
120 156  
121 157 task :selenium => 'db:test:plugins:prepare' do |t|
122   - run_cucumber t.name, :selenium, "plugins/{#{enabled_plugins.join(',')}}/test/features/**/*.features"
  158 + run_tests :selenium, enabled_plugins
123 159 end
124 160  
125 161 task :temp_enable_all_plugins do
... ...
plugins/anti_spam/lib/anti_spam_plugin/wrapper.rb
... ... @@ -2,9 +2,10 @@ class AntiSpamPlugin::Wrapper &lt; SimpleDelegator
2 2 include Rakismet::Model
3 3  
4 4 @@wrappers = []
  5 + cattr_accessor :wrappers
5 6  
6 7 def self.wrap(object)
7   - wrapper = @@wrappers.find { |wrapper| wrapper.wraps?(object) }
  8 + wrapper = wrappers.find { |wrapper| wrapper.wraps?(object) }
8 9 wrapper ? wrapper.new(object) : object
9 10 end
10 11  
... ... @@ -13,6 +14,10 @@ class AntiSpamPlugin::Wrapper &lt; SimpleDelegator
13 14 end
14 15  
15 16 def self.inherited(child)
16   - @@wrappers << child
  17 + wrappers << child
17 18 end
18 19 end
  20 +
  21 +Dir.glob(File.join(AntiSpamPlugin.root_path, 'lib', 'anti_spam_plugin', '*_wrapper.rb')) do |file|
  22 + load(file)
  23 +end
... ...
plugins/comment_group/test/functional/comment_group_plugin_profile_controller_test.rb
... ... @@ -36,10 +36,10 @@ class CommentGroupPluginProfileControllerTest &lt; ActionController::TestCase
36 36 end
37 37  
38 38 should 'show first page comments only' do
39   - comment1 = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'secondpage', :group_id => 0)
40   - comment2 = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'firstpage 1', :group_id => 0)
41   - comment3 = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'firstpage 2', :group_id => 0)
42   - comment4 = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'firstpage 3', :group_id => 0)
  39 + comment1 = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :created_at => Time.now, :body => 'secondpage', :group_id => 0)
  40 + comment2 = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :created_at => Time.now - 1.day, :body => 'firstpage 1', :group_id => 0)
  41 + comment3 = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :created_at => Time.now - 2.days, :body => 'firstpage 2', :group_id => 0)
  42 + comment4 = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :created_at => Time.now - 3.days, :body => 'firstpage 3', :group_id => 0)
43 43 xhr :get, :view_comments, :profile => @profile.identifier, :article_id => article.id, :group_id => 0
44 44 assert_match /firstpage 1/, @response.body
45 45 assert_match /firstpage 2/, @response.body
... ...
plugins/community_track/lib/community_track_plugin/track_card_list_block.rb
... ... @@ -12,4 +12,8 @@ class CommunityTrackPlugin::TrackCardListBlock &lt; CommunityTrackPlugin::TrackList
12 12 'track_card'
13 13 end
14 14  
  15 + def embedable?
  16 + true
  17 + end
  18 +
15 19 end
... ...
plugins/community_track/test/functional/community_track_plugin_content_viewer_controller_test.rb
... ... @@ -10,7 +10,7 @@ end
10 10 class ContentViewerControllerTest < ActionController::TestCase
11 11  
12 12 def setup
13   - @profile = fast_create(Community)
  13 + @profile = Community.create!(:name => 'Sample community', :identifier => 'sample-community')
14 14 @track = create_track('track', @profile)
15 15 @step = CommunityTrackPlugin::Step.create!(:name => 'step1', :body => 'body', :profile => @profile, :parent => @track, :published => false, :end_date => Date.today, :start_date => Date.today, :tool_type => TinyMceArticle.name)
16 16  
... ... @@ -87,43 +87,35 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
87 87 end
88 88  
89 89 should 'render a div with block id for track list block' do
90   - box = fast_create(Box, :owner_id => @profile.id, :owner_type => @profile.class.name)
91   - @block = CommunityTrackPlugin::TrackListBlock.create!(:box => box)
92   - @profile.boxes << box
  90 + @block = CommunityTrackPlugin::TrackListBlock.create!(:box => @profile.boxes.last)
93 91 get :view_page, @step.url
94 92 assert_tag :tag => 'div', :attributes => { :class => 'track_list', :id => "track_list_#{@block.id}" }
95 93 end
96 94  
97 95 should 'render a div with block id for track card list block' do
98   - box = fast_create(Box, :owner_id => @profile.id, :owner_type => @profile.class.name)
99   - @block = CommunityTrackPlugin::TrackCardListBlock.create!(:box => box)
100   - @profile.boxes << box
  96 + @block = CommunityTrackPlugin::TrackCardListBlock.create!(:box => @profile.boxes.last)
101 97 get :view_page, @step.url
102 98 assert_tag :tag => 'div', :attributes => { :class => 'track_list', :id => "track_list_#{@block.id}" }
103 99 end
104 100  
105 101 should 'render tracks in track list block' do
106   - box = fast_create(Box, :owner_id => @profile.id, :owner_type => @profile.class.name)
107   - @block = CommunityTrackPlugin::TrackListBlock.create!(:box => box)
108   - @profile.boxes << box
  102 + @block = CommunityTrackPlugin::TrackListBlock.create!(:box => @profile.boxes.last)
109 103 get :view_page, @step.url
  104 + file = File.open('result.html', 'w+')
  105 + file.write(@response.body)
  106 + file.close
110 107 assert_tag :tag => 'div', :attributes => { :class => "item category_#{@track.category_name}" }, :descendant => { :tag => 'div', :attributes => { :class => 'steps' }, :descendant => { :tag => 'span', :attributes => { :class => "step #{@block.status_class(@step)}" } } }
111 108 end
112 109  
113 110 should 'render tracks in track card list block' do
114   - box = fast_create(Box, :owner_id => @profile.id, :owner_type => @profile.class.name)
115   - @block = CommunityTrackPlugin::TrackCardListBlock.create!(:box => box)
116   - @profile.boxes << box
  111 + @block = CommunityTrackPlugin::TrackCardListBlock.create!(:box => @profile.boxes.last)
117 112 get :view_page, @step.url
118 113 assert_tag :tag => 'div', :attributes => { :class => "item_card category_#{@track.category_name}" }, :descendant => { :tag => 'div', :attributes => { :class => 'track_content' } }
119 114 assert_tag :tag => 'div', :attributes => { :class => "item_card category_#{@track.category_name}" }, :descendant => { :tag => 'div', :attributes => { :class => 'track_stats' } }
120 115 end
121 116  
122 117 should 'render link to display more tracks in track list block' do
123   - box = fast_create(Box, :owner_id => @profile.id, :owner_type => @profile.class.name)
124   - @block = CommunityTrackPlugin::TrackCardListBlock.create!(:box => box)
125   - @profile.boxes << box
126   -
  118 + @block = CommunityTrackPlugin::TrackCardListBlock.create!(:box => @profile.boxes.last)
127 119 (@block.limit+1).times { |i| create_track("track#{i}", @profile) }
128 120  
129 121 get :view_page, @step.url
... ... @@ -131,9 +123,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
131 123 end
132 124  
133 125 should 'render link to show all tracks in track list block' do
134   - box = fast_create(Box, :owner_id => @profile.id, :owner_type => @profile.class.name)
135   - @block = CommunityTrackPlugin::TrackCardListBlock.create!(:box => box)
136   - @profile.boxes << box
  126 + @block = CommunityTrackPlugin::TrackCardListBlock.create!(:box => @profile.boxes.last)
137 127 @block.more_another_page = true
138 128 @block.save!
139 129  
... ...
plugins/recent_content/test/unit/recent_content_block_test.rb
... ... @@ -61,9 +61,9 @@ class RecentContentBlockTest &lt; ActiveSupport::TestCase
61 61  
62 62 root = fast_create(Blog, :name => 'test-blog', :profile_id => profile.id)
63 63  
64   - a1 = fast_create(TextileArticle, :name => 'article #1', :profile_id => profile.id, :parent_id => root.id)
65   - a2 = fast_create(TextileArticle, :name => 'article #2', :profile_id => profile.id, :parent_id => root.id)
66   - a3 = fast_create(TextileArticle, :name => 'article #3', :profile_id => profile.id, :parent_id => root.id)
  64 + a1 = fast_create(TextileArticle, :name => 'article #1', :profile_id => profile.id, :parent_id => root.id, :created_at => Time.now - 2.days)
  65 + a2 = fast_create(TextileArticle, :name => 'article #2', :profile_id => profile.id, :parent_id => root.id, :created_at => Time.now - 1.days)
  66 + a3 = fast_create(TextileArticle, :name => 'article #3', :profile_id => profile.id, :parent_id => root.id, :created_at => Time.now)
67 67  
68 68 block = RecentContentBlock.new
69 69 block.stubs(:holder).returns(profile)
... ...
plugins/relevant_content/lib/ext/article.rb 0 → 100644
... ... @@ -0,0 +1,95 @@
  1 +require_dependency 'article'
  2 +
  3 +class Article
  4 +
  5 + named_scope :relevant_content, :conditions => ["articles.published = true and (articles.type != 'UploadedFile' and articles.type != 'Blog' and articles.type != 'RssFeed') OR articles.type is NULL"]
  6 +
  7 + def self.articles_columns
  8 + Article.column_names.map {|c| "articles.#{c}"} .join(",")
  9 + end
  10 +
  11 + def self.most_accessed(owner, limit = nil)
  12 + conditions = owner.kind_of?(Environment) ? ["hits > 0"] : ["profile_id = ? and hits > 0", owner.id]
  13 + result = Article.relevant_content.find(
  14 + :all,
  15 + :order => 'hits desc',
  16 + :limit => limit,
  17 + :conditions => conditions)
  18 + result.paginate({:page => 1, :per_page => limit})
  19 + end
  20 +
  21 + def self.most_commented_relevant_content(owner, limit)
  22 + conditions = owner.kind_of?(Environment) ? ["comments_count > 0"] : ["profile_id = ? and comments_count > 0", owner.id]
  23 + result = Article.relevant_content.find(
  24 + :all,
  25 + :order => 'comments_count desc',
  26 + :limit => limit,
  27 + :conditions => conditions)
  28 + result.paginate({:page => 1, :per_page => limit})
  29 + end
  30 +
  31 + def self.more_positive_votes(owner, limit = nil)
  32 + conditions = owner.kind_of?(Environment) ? {'votes.voteable_type' => 'Article'} : ["profile_id = ? and votes.voteable_type = ? ", owner.id, 'Article']
  33 + result = Article.relevant_content.find(
  34 + :all,
  35 + :order => 'sum(vote) desc',
  36 + :group => 'voteable_id, ' + articles_columns,
  37 + :limit => limit,
  38 + :having => ['sum(vote) > 0'],
  39 + :conditions => conditions,
  40 + :joins => 'INNER JOIN votes ON articles.id = votes.voteable_id')
  41 + result.paginate({:page => 1, :per_page => limit})
  42 + end
  43 +
  44 + def self.more_negative_votes(owner, limit = nil)
  45 + conditions = owner.kind_of?(Environment) ? {'votes.voteable_type' => 'Article'} : ["profile_id = ? and votes.voteable_type = 'Article' ", owner.id]
  46 + result = Article.relevant_content.find(
  47 + :all,
  48 + :order => 'sum(vote) asc',
  49 + :group => 'voteable_id, ' + articles_columns,
  50 + :limit => limit,
  51 + :having => ['sum(vote) < 0'],
  52 + :conditions => conditions,
  53 + :joins => 'INNER JOIN votes ON articles.id = votes.voteable_id'
  54 + )
  55 + result.paginate({:page => 1, :per_page => limit})
  56 + end
  57 +
  58 + def self.most_liked(owner, limit = nil)
  59 + conditions = owner.kind_of?(Environment) ? ["votes.voteable_type = 'Article' and vote > 0"] : ["votes.voteable_type = 'Article' and vote > 0 and profile_id = ? ", owner.id]
  60 + result = Article.relevant_content.find(
  61 + :all,
  62 + :select => articles_columns,
  63 + :order => 'count(voteable_id) desc',
  64 + :group => 'voteable_id, ' + articles_columns,
  65 + :limit => limit,
  66 + :conditions => conditions,
  67 + :joins => 'INNER JOIN votes ON articles.id = votes.voteable_id')
  68 + result.paginate({:page => 1, :per_page => limit})
  69 + end
  70 +
  71 + def self.most_disliked(owner, limit = nil)
  72 + conditions = owner.kind_of?(Environment) ? ["votes.voteable_type = 'Article' and vote < 0"] : ["votes.voteable_type = 'Article' and vote < 0 and profile_id = ? ", owner.id]
  73 + result = Article.relevant_content.find(
  74 + :all,
  75 + :order => 'count(voteable_id) desc',
  76 + :group => 'voteable_id, ' + articles_columns,
  77 + :limit => limit,
  78 + :conditions => conditions,
  79 + :joins => 'INNER JOIN votes ON articles.id = votes.voteable_id')
  80 + result.paginate({:page => 1, :per_page => limit})
  81 + end
  82 +
  83 + def self.most_voted(owner, limit = nil)
  84 + conditions = owner.kind_of?(Environment) ? ["votes.voteable_type = 'Article'"] : ["votes.voteable_type = 'Article' and profile_id = ? ", owner.id]
  85 + result = Article.relevant_content.find(
  86 + :all,
  87 + :select => articles_columns,
  88 + :order => 'count(voteable_id) desc',
  89 + :group => 'voteable_id, ' + articles_columns,
  90 + :limit => limit,
  91 + :conditions => conditions,
  92 + :joins => 'INNER JOIN votes ON articles.id = votes.voteable_id')
  93 + result.paginate({:page => 1, :per_page => limit})
  94 + end
  95 +end
... ...
plugins/relevant_content/lib/relevant_content_plugin.rb 0 → 100644
... ... @@ -0,0 +1,21 @@
  1 +class RelevantContentPlugin < Noosfero::Plugin
  2 +
  3 + def self.plugin_name
  4 + "Relevant Content Plugin"
  5 + end
  6 +
  7 + def self.plugin_description
  8 + _("A plugin that lists the most accessed, most commented, most liked and most disliked contents.")
  9 + end
  10 +
  11 + def self.extra_blocks
  12 + {
  13 + RelevantContentPlugin::RelevantContentBlock => {}
  14 + }
  15 + end
  16 +
  17 + def stylesheet?
  18 + true
  19 + end
  20 +
  21 +end
... ...
plugins/relevant_content/lib/relevant_content_plugin/relevant_content_block.rb 0 → 100644
... ... @@ -0,0 +1,93 @@
  1 +class RelevantContentPlugin::RelevantContentBlock < Block
  2 + def self.description
  3 + _('Relevant content')
  4 + end
  5 +
  6 + def default_title
  7 + _('Relevant content')
  8 + end
  9 +
  10 + def help
  11 + _('This block lists the most popular content.')
  12 + end
  13 +
  14 + settings_items :limit, :type => :integer, :default => 5
  15 + settings_items :show_most_read, :type => :boolean, :default => 1
  16 + settings_items :show_most_commented, :type => :boolean, :default => 1
  17 + settings_items :show_most_liked, :type => :boolean, :default => 1
  18 + settings_items :show_most_disliked, :type => :boolean, :default => 0
  19 + settings_items :show_most_voted, :type => :boolean, :default => 1
  20 +
  21 + include ActionController::UrlWriter
  22 + def content(args={})
  23 +
  24 + content = block_title(title)
  25 +
  26 + if self.show_most_read
  27 + docs = Article.most_accessed(owner, self.limit)
  28 + if !docs.blank?
  29 + subcontent = ""
  30 + subcontent += content_tag(:span, _("Most read articles"), :class=>"title mread") + "\n"
  31 + subcontent += content_tag(:ul, docs.map {|item| content_tag('li', link_to(h(item.title), item.url))}.join("\n"))
  32 + content += content_tag(:div, subcontent, :class=>"block mread") + "\n"
  33 + end
  34 + end
  35 +
  36 + if self.show_most_commented
  37 + docs = Article.most_commented_relevant_content(owner, self.limit)
  38 + if !docs.blank?
  39 + subcontent = ""
  40 + subcontent += content_tag(:span, _("Most commented articles"), :class=>"title mcommented") + "\n"
  41 + subcontent += content_tag(:ul, docs.map {|item| content_tag('li', link_to(h(item.title), item.url))}.join("\n"))
  42 + content += content_tag(:div, subcontent, :class=>"block mcommented") + "\n"
  43 + end
  44 + end
  45 +
  46 + if owner.kind_of?(Environment)
  47 + env = owner
  48 + else
  49 + env = owner.environment
  50 + end
  51 +
  52 + if env.plugin_enabled?(VotePlugin)
  53 + if self.show_most_liked
  54 + docs = Article.more_positive_votes(owner, self.limit)
  55 + if !docs.blank?
  56 + subcontent = ""
  57 + subcontent += content_tag(:span, _("Most liked articles"), :class=>"title mliked") + "\n"
  58 + subcontent += content_tag(:ul, docs.map {|item| content_tag('li', link_to(h(item.title), item.url))}.join("\n"))
  59 + content += content_tag(:div, subcontent, :class=>"block mliked") + "\n"
  60 + end
  61 + end
  62 + if self.show_most_disliked
  63 + docs = Article.more_negative_votes(owner, self.limit)
  64 + if !docs.blank?
  65 + subcontent = ""
  66 + subcontent += content_tag(:span, _("Most disliked articles"), :class=>"title mdisliked") + "\n"
  67 + subcontent += content_tag(:ul, docs.map {|item| content_tag('li', link_to(h(item.title), item.url))}.join("\n"))
  68 + content += content_tag(:div, subcontent, :class=>"block mdisliked") + "\n"
  69 + end
  70 + end
  71 +
  72 + if self.show_most_voted
  73 + docs = Article.most_voted(owner, self.limit)
  74 + if !docs.blank?
  75 + subcontent = ""
  76 + subcontent += content_tag(:span, _("Most voted articles"), :class=>"title mvoted") + "\n"
  77 + subcontent += content_tag(:ul, docs.map {|item| content_tag('li', link_to(h(item.title), item.url))}.join("\n"))
  78 + content += content_tag(:div, subcontent, :class=>"block mvoted") + "\n"
  79 + end
  80 + end
  81 + end
  82 + return content
  83 + end
  84 +
  85 + def timeout
  86 + 4.hours
  87 + end
  88 +
  89 + def self.expire_on
  90 + { :profile => [:article], :environment => [:article] }
  91 + end
  92 +
  93 +end
0 94 \ No newline at end of file
... ...
plugins/relevant_content/public/style.css 0 → 100644
... ... @@ -0,0 +1,79 @@
  1 +#content .relevant-content-plugin_relevant-content-block {
  2 + padding: 10px 0px 10px 10px;
  3 + word-wrap: break-word;
  4 +}
  5 +
  6 +.relevant-content-plugin_relevant-content-block ul {
  7 + margin: 0px;
  8 + padding: 0px 0px 0px 20px;
  9 +}
  10 +.relevant-content-plugin_relevant-content-block li {
  11 + margin: 0px;
  12 + padding: 0px;
  13 + list-style: none
  14 +}
  15 +.relevant-content-plugin_relevant-content-block a {
  16 + text-decoration: none;
  17 +}
  18 +.relevant-content-plugin_relevant-content-block .block-footer-content {
  19 + font-size: 10px;
  20 +}
  21 +.relevant-content-plugin_relevant-content-block .block-footer-content a:hover {
  22 + text-decoration: underline;
  23 +}
  24 +
  25 +.relevant-content-plugin_relevant-content-block p {
  26 + text-align:center;
  27 +}
  28 +
  29 +.relevant-content-plugin_relevant-content-block p.like{
  30 + background-image: url('images/positive-hand.png');
  31 + background-repeat: no-repeat;
  32 + min-width: 50px;
  33 + text-align:center;
  34 +}
  35 +
  36 +.relevant-content-plugin_relevant-content-block p.dislike{
  37 + background-image: url('images/negative-hand.png');
  38 + background-repeat: no-repeat;
  39 + min-width: 50px;
  40 + text-align:center;
  41 +}
  42 +
  43 +
  44 +.relevant-content-plugin_relevant-content-block {
  45 + //overflow: hidden;
  46 + display: block;
  47 + width: 100%;
  48 +}
  49 +
  50 +
  51 +.relevant-content-cover img {
  52 + width: 100%;
  53 +}
  54 +
  55 +.relevant-content-plugin_relevant-content-block span.title {
  56 + display: block;
  57 + margin: 20px 0px 0px;
  58 + padding: 0px 0px 0px 20px;
  59 +}
  60 +
  61 +.relevant-content-plugin_relevant-content-block span.title.mread {
  62 +
  63 +}
  64 +
  65 +.relevant-content-plugin_relevant-content-block span.title.mcommented {
  66 +
  67 +}
  68 +
  69 +.relevant-content-plugin_relevant-content-block span.title.mliked {
  70 +
  71 +}
  72 +
  73 +.relevant-content-plugin_relevant-content-block span.title.mdisliked {
  74 +
  75 +}
  76 +
  77 +.relevant-content-plugin_relevant-content-block span.title.mvoted {
  78 +
  79 +}
... ...
plugins/relevant_content/test/test_helper.rb 0 → 100644
... ... @@ -0,0 +1 @@
  1 +require File.dirname(__FILE__) + '/../../../test/test_helper'
... ...
plugins/relevant_content/test/unit/article.rb 0 → 100644
... ... @@ -0,0 +1,148 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +require 'comment_controller'
  4 +# Re-raise errors caught by the controller.
  5 +class CommentController; def rescue_action(e) raise e end; end
  6 +
  7 +class RelevantContentBlockTest < ActiveSupport::TestCase
  8 +
  9 + include AuthenticatedTestHelper
  10 + fixtures :users, :environments
  11 +
  12 + def setup
  13 + @controller = CommentController.new
  14 + @request = ActionController::TestRequest.new
  15 + @response = ActionController::TestResponse.new
  16 + @profile = create_user('testinguser').person
  17 + @environment = @profile.environment
  18 + end
  19 + attr_reader :profile, :environment
  20 +
  21 + def enable_vote_plugin
  22 + enabled = false
  23 + environment=Environment.default
  24 + if Noosfero::Plugin.all.include?('VotePlugin')
  25 + if not environment.enabled_plugins.include?(:vote)
  26 + environment.enable_plugin(Vote)
  27 + environment.save!
  28 + end
  29 + enabled = true
  30 + end
  31 + enabled
  32 + end
  33 +
  34 + should 'list most commented articles' do
  35 + Article.delete_all
  36 + a1 = create(TextileArticle, :name => "art 1", :profile_id => profile.id)
  37 + a2 = create(TextileArticle, :name => "art 2", :profile_id => profile.id)
  38 + a3 = create(TextileArticle, :name => "art 3", :profile_id => profile.id)
  39 +
  40 + 2.times { Comment.create(:title => 'test', :body => 'asdsad', :author => profile, :source => a2).save! }
  41 + 4.times { Comment.create(:title => 'test', :body => 'asdsad', :author => profile, :source => a3).save! }
  42 +
  43 + # should respect the order (more commented comes first)
  44 + assert_equal a3.name, profile.articles.most_commented_relevant_content(Environment.default, 3).first.name
  45 + # It is a2 instead of a1 since it does not list articles without comments
  46 + assert_equal a2.name, profile.articles.most_commented_relevant_content(Environment.default, 3).last.name
  47 + end
  48 +
  49 +
  50 + should 'find the most voted' do
  51 + if not enable_vote_plugin
  52 + return
  53 + end
  54 + article = fast_create(Article, {:name=>'2 votes'})
  55 + 2.times{
  56 + person = fast_create(Person)
  57 + person.vote_for(article)
  58 + }
  59 + article = fast_create(Article, {:name=>'10 votes'})
  60 + 10.times{
  61 + person = fast_create(Person)
  62 + person.vote_for(article)
  63 + }
  64 + article = fast_create(Article, {:name=>'5 votes'})
  65 + 5.times{
  66 + person = fast_create(Person)
  67 + person.vote_for(article)
  68 + }
  69 + articles = Article.most_voted(Environment.default, 5)
  70 + assert_equal '10 votes', articles.first.name
  71 + assert_equal '2 votes', articles.last.name
  72 + end
  73 +
  74 + should 'list the most postive' do
  75 + if not enable_vote_plugin
  76 + return
  77 + end
  78 + article = fast_create(Article, {:name=>'23 votes for 20 votes against'})
  79 + 20.times{
  80 + person = fast_create(Person)
  81 + person.vote_against(article)
  82 + }
  83 + 23.times{
  84 + person = fast_create(Person)
  85 + person.vote_for(article)
  86 + }
  87 + article = fast_create(Article, {:name=>'10 votes for 5 votes against'})
  88 + 10.times{
  89 + person = fast_create(Person)
  90 + person.vote_for(article)
  91 + }
  92 + 5.times{
  93 + person = fast_create(Person)
  94 + person.vote_against(article)
  95 + }
  96 + article = fast_create(Article, {:name=>'2 votes against'})
  97 + 2.times{
  98 + person = fast_create(Person)
  99 + person.vote_against(article)
  100 + }
  101 +
  102 + article = fast_create(Article, {:name=>'7 votes for'})
  103 + 7.times{
  104 + person = fast_create(Person)
  105 + person.vote_for(article)
  106 + }
  107 + articles = Article.more_positive_votes(Environment.default, 5)
  108 + assert_equal '7 votes for', articles.first.name
  109 + assert_equal '23 votes for 20 votes against', articles.last.name
  110 + end
  111 +
  112 + should 'list the most negative' do
  113 + if not enable_vote_plugin
  114 + return
  115 + end
  116 + article = fast_create(Article, {:name=>'23 votes for 29 votes against'})
  117 + 29.times{
  118 + person = fast_create(Person)
  119 + person.vote_against(article)
  120 + }
  121 + 23.times{
  122 + person = fast_create(Person)
  123 + person.vote_for(article)
  124 + }
  125 + article = fast_create(Article, {:name=>'10 votes for 15 votes against'})
  126 + 10.times{
  127 + person = fast_create(Person)
  128 + person.vote_for(article)
  129 + }
  130 + 15.times{
  131 + person = fast_create(Person)
  132 + person.vote_against(article)
  133 + }
  134 + article = fast_create(Article, {:name=>'2 votes against'})
  135 + 2.times{
  136 + person = fast_create(Person)
  137 + person.vote_against(article)
  138 + }
  139 + article = fast_create(Article, {:name=>'7 votes for'})
  140 + 7.times{
  141 + person = fast_create(Person)
  142 + person.vote_for(article)
  143 + }
  144 + articles = Article.more_negative_votes(Environment.default, 5)
  145 + assert_equal '23 votes for 29 votes against', articles.first.name
  146 + assert_equal '2 votes against', articles.last.name
  147 + end
  148 +end
0 149 \ No newline at end of file
... ...
plugins/relevant_content/test/unit/relevant_content_block_test.rb 0 → 100644
... ... @@ -0,0 +1,47 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +require 'comment_controller'
  4 +# Re-raise errors caught by the controller.
  5 +class CommentController; def rescue_action(e) raise e end; end
  6 +
  7 +class RelevantContentBlockTest < ActiveSupport::TestCase
  8 +
  9 + include AuthenticatedTestHelper
  10 + fixtures :users, :environments
  11 +
  12 + def setup
  13 + @controller = CommentController.new
  14 + @request = ActionController::TestRequest.new
  15 + @response = ActionController::TestResponse.new
  16 +
  17 + @profile = create_user('testinguser').person
  18 + @environment = @profile.environment
  19 + end
  20 + attr_reader :profile, :environment
  21 +
  22 + should 'have a default title' do
  23 + relevant_content_block = RelevantContentPlugin::RelevantContentBlock.new
  24 + block = Block.new
  25 + assert_not_equal block.default_title, relevant_content_block.default_title
  26 + end
  27 +
  28 + should 'have a help tooltip' do
  29 + relevant_content_block = RelevantContentPlugin::RelevantContentBlock.new
  30 + block = Block.new
  31 + assert_not_equal "", relevant_content_block.help
  32 + end
  33 +
  34 + should 'describe itself' do
  35 + assert_not_equal Block.description, RelevantContentPlugin::RelevantContentBlock.description
  36 + end
  37 +
  38 + should 'is editable' do
  39 + block = RelevantContentPlugin::RelevantContentBlock.new
  40 + assert block.editable?
  41 + end
  42 +
  43 + should 'expire' do
  44 + assert_equal RelevantContentPlugin::RelevantContentBlock.expire_on, {:environment=>[:article], :profile=>[:article]}
  45 + end
  46 +
  47 +end
... ...
plugins/relevant_content/test/unit/relevant_content_plugin_test.rb 0 → 100644
... ... @@ -0,0 +1,29 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class RelevantContentPluginTest < ActiveSupport::TestCase
  4 +
  5 + def setup
  6 + @plugin = RelevantContentPlugin.new
  7 + end
  8 +
  9 + should 'be a noosfero plugin' do
  10 + assert_kind_of Noosfero::Plugin, @plugin
  11 + end
  12 +
  13 + should 'have name' do
  14 + assert_equal 'Relevant Content Plugin', RelevantContentPlugin.plugin_name
  15 + end
  16 +
  17 + should 'have description' do
  18 + assert_equal _("A plugin that lists the most accessed, most commented, most liked and most disliked contents."), RelevantContentPlugin.plugin_description
  19 + end
  20 +
  21 + should 'have stylesheet' do
  22 + assert @plugin.stylesheet?
  23 + end
  24 +
  25 + should "return RelevantContentBlock in extra_blocks class method" do
  26 + assert RelevantContentPlugin.extra_blocks.keys.include?(RelevantContentPlugin::RelevantContentBlock)
  27 + end
  28 +
  29 +end
... ...
plugins/relevant_content/views/box_organizer/relevant_content_plugin/_relevant_content_block.rhtml 0 → 100644
... ... @@ -0,0 +1,8 @@
  1 +<div id='edit-relevant-content-block'>
  2 + <%= labelled_form_field _('Limit of items per category'), text_field(:block, :limit, :size => 3) %>
  3 + <%= labelled_check_box _('Display most accessed content'), "block[show_most_read]", 1 ,@block.show_most_read %><BR>
  4 + <%= labelled_check_box _('Display most commented content'), "block[show_most_commented]", 1 ,@block.show_most_commented %><BR>
  5 + <%= labelled_check_box _('Display most liked content'), "block[show_most_liked]", 1 ,@block.show_most_liked %><BR>
  6 + <%= labelled_check_box _('Display most voted content'), "block[show_most_voted]", 1 ,@block.show_most_voted %><BR>
  7 + <%= labelled_check_box _('Display most disliked content'), "block[show_most_disliked]", 1 , @block.show_most_disliked %><BR>
  8 +</div>
0 9 \ No newline at end of file
... ...
plugins/relevant_content/views/environment_design/relevant_content_plugin 0 → 120000
... ... @@ -0,0 +1 @@
  1 +../box_organizer/relevant_content_plugin
0 2 \ No newline at end of file
... ...
plugins/relevant_content/views/profile_design/relevant_content_plugin 0 → 120000
... ... @@ -0,0 +1 @@
  1 +../box_organizer/relevant_content_plugin
0 2 \ No newline at end of file
... ...
public/designs/icons/tango/style.css
1 1 /******************SMALL ICONS********************/
  2 +.icon-embed { background-image: url(Tango/16x16/apps/utilities-terminal.png) }
2 3 .icon-edit { background-image: url(Tango/16x16/apps/text-editor.png) }
3 4 .icon-home { background-image: url(Tango/16x16/actions/go-home.png) }
4 5 .icon-home-not { background-image: url(mod/16x16/actions/go-home-not.png) }
... ...
public/javascripts/city_state_validation.js 0 → 100644
... ... @@ -0,0 +1,60 @@
  1 +(function($){
  2 + autoCompleteStateCity($);
  3 + $('[id$="_country"]').change(function(){
  4 + autoCompleteStateCity($);
  5 + })
  6 +})(jQuery);
  7 +
  8 +function autoCompleteStateCity($) {
  9 + var country_selected = $('[id$="_country"] option:selected').val()
  10 + if(country_selected == "BR")
  11 + {
  12 + $('#state_field').autocomplete({
  13 + source : function(request, response){
  14 + $.ajax({
  15 + type: "GET",
  16 + url: '/account/search_state',
  17 + data: {state_name: request.term},
  18 + success: function(result){
  19 + response(result);
  20 + },
  21 + error: function(ajax, stat, errorThrown) {
  22 + console.log('Link not found : ' + errorThrown);
  23 + }
  24 + });
  25 + },
  26 +
  27 + minLength: 3
  28 + });
  29 +
  30 + $('#city_field').autocomplete({
  31 + source : function(request, response){
  32 + $.ajax({
  33 + type: "GET",
  34 + url: '/account/search_cities',
  35 + data: {city_name: request.term, state_name: $("#state_field").val()},
  36 + success: function(result){
  37 + response(result);
  38 + },
  39 + error: function(ajax, stat, errorThrown) {
  40 + console.log('Link not found : ' + errorThrown);
  41 + }
  42 + });
  43 + },
  44 +
  45 + minLength: 3
  46 + });
  47 + }
  48 + else
  49 + {
  50 + if ($('#state_field').data('autocomplete')) {
  51 + $('#state_field').autocomplete("destroy");
  52 + $('#state_field').removeData('autocomplete');
  53 + }
  54 +
  55 + if ($('#city_field').data('autocomplete')) {
  56 + $('#city_field').autocomplete("destroy");
  57 + $('#city_field').removeData('autocomplete');
  58 + }
  59 + }
  60 +}
... ...
public/javascripts/signup_form.js 0 → 100644
... ... @@ -0,0 +1,23 @@
  1 +function verifyLoginLoad() {
  2 + jQuery('#user_login').removeClass('available unavailable valid validated invalid checking').addClass('checking');
  3 + jQuery('#url-check').html(jQuery('#checking-message').html());
  4 +}
  5 +
  6 +function verifyLoginAjax(value) {
  7 + verifyLoginLoad();
  8 +
  9 + jQuery.get(
  10 + "/account/check_valid_name",
  11 + {'identifier': encodeURIComponent(value)},
  12 + function(request){
  13 + jQuery('#user_login').removeClass('checking');
  14 + jQuery("#url-check").html(request);
  15 + }
  16 + );
  17 +}
  18 +
  19 +jQuery(document).ready(function(){
  20 + jQuery("#user_login").blur(function(){
  21 + verifyLoginAjax(this.value);
  22 + });
  23 +});
... ...
public/stylesheets/application.css
... ... @@ -6040,6 +6040,11 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img {
6040 6040 text-align: right;
6041 6041 }
6042 6042  
  6043 +#url-check .suggested_usernames,
  6044 +#url-check .suggested_usernames a {
  6045 + color: #005000;
  6046 +}
  6047 +
6043 6048 #email-check,
6044 6049 #fake-check,
6045 6050 #password-rate,
... ...
test/functional/account_controller_test.rb
... ... @@ -8,7 +8,6 @@ class AccountControllerTest &lt; ActionController::TestCase
8 8 # Be sure to include AuthenticatedTestHelper in test/test_helper.rb instead
9 9 # Then, you can remove it from this and the units test.
10 10 include AuthenticatedTestHelper
11   -
12 11 all_fixtures
13 12  
14 13 def teardown
... ... @@ -17,8 +16,8 @@ class AccountControllerTest &lt; ActionController::TestCase
17 16  
18 17 def setup
19 18 @controller = AccountController.new
20   - @request = ActionController::TestRequest.new
21   - @response = ActionController::TestResponse.new
  19 + @request = ActionController::TestRequest.new
  20 + @response = ActionController::TestResponse.new
22 21 disable_signup_bot_check
23 22 end
24 23  
... ... @@ -646,21 +645,28 @@ class AccountControllerTest &lt; ActionController::TestCase
646 645 assert_redirected_to :controller => 'home', :action => 'index'
647 646 end
648 647  
649   - should 'check_url is available on environment' do
  648 + should 'check_valid_name is available on environment' do
650 649 env = fast_create(Environment, :name => 'Environment test')
651 650 @controller.expects(:environment).returns(env).at_least_once
652 651 profile = create_user('mylogin').person
653   - get :check_url, :identifier => 'mylogin'
  652 + get :check_valid_name, :identifier => 'mylogin'
654 653 assert_equal 'validated', assigns(:status_class)
655 654 end
656 655  
657 656 should 'check if url is not available on environment' do
658 657 @controller.expects(:environment).returns(Environment.default).at_least_once
659 658 profile = create_user('mylogin').person
660   - get :check_url, :identifier => 'mylogin'
  659 + get :check_valid_name, :identifier => 'mylogin'
661 660 assert_equal 'invalid', assigns(:status_class)
662 661 end
663 662  
  663 + should 'suggest a list with three possible usernames' do
  664 + profile = create_user('mylogin').person
  665 + get :check_valid_name, :identifier => 'mylogin'
  666 +
  667 + assert_equal 3, assigns(:suggested_usernames).uniq.size
  668 + end
  669 +
664 670 should 'check if e-mail is available on environment' do
665 671 env = fast_create(Environment, :name => 'Environment test')
666 672 @controller.expects(:environment).returns(env).at_least_once
... ... @@ -926,6 +932,30 @@ class AccountControllerTest &lt; ActionController::TestCase
926 932 assert @response.body.blank?
927 933 end
928 934  
  935 + should "Search for state" do
  936 + create_state_and_city
  937 +
  938 + xhr :get, :search_state, :state_name=>"Rio Grande"
  939 +
  940 + json_response = ActiveSupport::JSON.decode(@response.body)
  941 + label = json_response[0]['label']
  942 +
  943 + assert_equal label, "Rio Grande do Sul"
  944 + end
  945 +
  946 + should "Search for city" do
  947 + create_state_and_city
  948 +
  949 + xhr :get, :search_cities, :state_name=>"Rio Grande do Sul", :city_name=>"Lavras"
  950 +
  951 + json_response = ActiveSupport::JSON.decode(@response.body)
  952 + label = json_response[0]['label']
  953 + category = json_response[0]['category']
  954 +
  955 + assert_equal category, "Rio Grande do Sul"
  956 + assert_equal label, "Lavras do Sul"
  957 + end
  958 +
929 959 protected
930 960 def new_user(options = {}, extra_options ={})
931 961 data = {:profile_data => person_data}
... ... @@ -954,4 +984,18 @@ class AccountControllerTest &lt; ActionController::TestCase
954 984 environment.min_signup_delay = 0
955 985 environment.save!
956 986 end
  987 +
  988 + def create_state_and_city
  989 + city = 'Lavras do Sul'
  990 + state = 'Rio Grande do Sul'
  991 +
  992 + parent_region = fast_create(NationalRegion, :name => state,
  993 + :national_region_code => '43',
  994 + :national_region_type_id => NationalRegionType::STATE)
  995 +
  996 + fast_create(NationalRegion, :name => city,
  997 + :national_region_code => '431150',
  998 + :national_region_type_id => NationalRegionType::CITY,
  999 + :parent_national_region_code => parent_region.national_region_code)
  1000 + end
957 1001 end
... ...
test/functional/content_viewer_controller_test.rb
... ... @@ -72,9 +72,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
72 72 get :view_page, :profile => 'someone', :page => [ '500.html' ]
73 73  
74 74 assert_response :success
75   - assert_match /^text\/html/, @response.headers['Content-Type']
76   - assert @response.headers['Content-Disposition'].present?
77   - assert_match /attachment/, @response.headers['Content-Disposition']
  75 + assert_match /#{html.public_filename}/, @response.body
78 76 end
79 77  
80 78 should 'produce a download-link when article is not text/html' do
... ... @@ -577,14 +575,6 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
577 575 assert_template 'view_page'
578 576 end
579 577  
580   - should 'download data for image when not view' do
581   - file = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => profile)
582   - get :view_page, :profile => profile.identifier, :page => file.explode_path
583   -
584   - assert_response :success
585   - assert_template nil
586   - end
587   -
588 578 should "display 'Upload files' when create children of image gallery" do
589 579 login_as(profile.identifier)
590 580 f = Gallery.create!(:name => 'gallery', :profile => profile)
... ... @@ -1360,8 +1350,23 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
1360 1350  
1361 1351 should 'display link to download of non-recognized file types on its page' do
1362 1352 file = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/test.txt', 'bin/unknown'), :profile => profile)
1363   - get :view_page, file.url.merge(:view=>:true)
1364   - assert_match /this is a sample text file/, @response.body
  1353 + get :view_page, file.url
  1354 + assert_match /#{file.public_filename}/, @response.body
  1355 + end
  1356 +
  1357 + should 'not count hit from bots' do
  1358 + article = fast_create(Article, :profile_id => profile.id)
  1359 + assert_no_difference article, :hits do
  1360 + @request.env['HTTP_USER_AGENT'] = 'bot'
  1361 + get 'view_page', :profile => profile.identifier, :page => article.path.split('/')
  1362 + @request.env['HTTP_USER_AGENT'] = 'spider'
  1363 + get 'view_page', :profile => profile.identifier, :page => article.path.split('/')
  1364 + @request.env['HTTP_USER_AGENT'] = 'crawler'
  1365 + get 'view_page', :profile => profile.identifier, :page => article.path.split('/')
  1366 + @request.env['HTTP_USER_AGENT'] = '(http://some-crawler.com)'
  1367 + get 'view_page', :profile => profile.identifier, :page => article.path.split('/')
  1368 + article.reload
  1369 + end
1365 1370 end
1366 1371  
1367 1372 should 'add meta tags with article info' do
... ...
test/functional/embed_controller_test.rb 0 → 100644
... ... @@ -0,0 +1,39 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class EmbedControllerTest < ActionController::TestCase
  4 +
  5 + def setup
  6 + login_as(create_admin_user(Environment.default))
  7 + @block = LoginBlock.create!
  8 + @block.class.any_instance.stubs(:embedable?).returns(true)
  9 + @environment = Environment.default
  10 + @environment.boxes.create!
  11 + @environment.boxes.first.blocks << @block
  12 + end
  13 +
  14 + should 'be able to get embed block' do
  15 + get :block, :id => @block.id
  16 + assert_tag :tag => 'div', :attributes => { :id => "block-#{@block.id}" }
  17 + end
  18 +
  19 + should 'display error message when not found block' do
  20 + Block.delete_all
  21 + get :block, :id => 1
  22 + assert_tag :tag => 'div', :attributes => { :id => "not-found" }
  23 + end
  24 +
  25 + should 'display error message when block is not visible/public' do
  26 + @block.display = 'never'
  27 + assert @block.save
  28 + get :block, :id => @block.id
  29 + assert_tag :tag => 'div', :attributes => { :id => "unavailable" }
  30 + end
  31 +
  32 + should 'display error message when block is not embedable' do
  33 + @block.class.any_instance.stubs(:embedable?).returns(false)
  34 + get :block, :id => @block.id
  35 + assert_tag :tag => 'div', :attributes => { :id => "unavailable" }
  36 + end
  37 +
  38 +
  39 +end
... ...
test/functional/events_controller_test.rb
... ... @@ -46,4 +46,12 @@ class EventsControllerTest &lt; ActionController::TestCase
46 46 assert_equal 20, assigns(:events).count
47 47 end
48 48  
  49 + should 'show events of specific day' do
  50 + profile.events << Event.new(:name => 'Joao Birthday', :start_date => Date.new(2009, 10, 28))
  51 +
  52 + get :events_by_day, :profile => profile.identifier, :year => 2009, :month => 10, :day => 28
  53 +
  54 + assert_tag :tag => 'a', :content => /Joao Birthday/
  55 + end
  56 +
49 57 end
... ...
test/functional/search_controller_test.rb
... ... @@ -74,14 +74,14 @@ class SearchControllerTest &lt; ActionController::TestCase
74 74 assert_includes assigns(:searches)[:articles][:results], art
75 75 end
76 76  
77   - should 'redirect contents to articles' do
  77 + should 'redirect contents to articles' do
78 78 person = fast_create(Person)
79 79 art = create_article_with_optional_category('an article to be found', person)
80 80  
81 81 get 'contents', :query => 'article found'
82   - # full description to avoid deprecation warning
  82 + # full description to avoid deprecation warning
83 83 assert_redirected_to :controller => :search, :action => :articles, :query => 'article found'
84   - end
  84 + end
85 85  
86 86 # 'assets' outside any category
87 87 should 'list articles in general' do
... ... @@ -259,10 +259,10 @@ class SearchControllerTest &lt; ActionController::TestCase
259 259  
260 260 should 'render specific action when only one asset is enabled' do
261 261 environment = Environment.default
262   - # article is not disabled
  262 + # article is not disabled
263 263 [:enterprises, :people, :communities, :products, :events].select do |key, name|
264   - environment.enable('disable_asset_' + key.to_s)
265   - end
  264 + environment.enable('disable_asset_' + key.to_s)
  265 + end
266 266 environment.save!
267 267 @controller.stubs(:environment).returns(environment)
268 268  
... ... @@ -274,25 +274,25 @@ class SearchControllerTest &lt; ActionController::TestCase
274 274 assert !assigns(:searches).has_key?(:communities)
275 275 assert !assigns(:searches).has_key?(:products)
276 276 assert !assigns(:searches).has_key?(:events)
277   - end
  277 + end
278 278  
279 279 should 'search all enabled assets in general search' do
280 280 ent1 = create_profile_with_optional_category(Enterprise, 'test enterprise')
281 281 prod_cat = ProductCategory.create!(:name => 'pctest', :environment => Environment.default)
282 282 prod = ent1.products.create!(:name => 'test product', :product_category => prod_cat)
283   - art = Article.create!(:name => 'test article', :profile_id => fast_create(Person).id)
284   - per = Person.create!(:name => 'test person', :identifier => 'test-person', :user_id => fast_create(User).id)
285   - com = Community.create!(:name => 'test community')
286   - eve = Event.create!(:name => 'test event', :profile_id => fast_create(Person).id)
  283 + art = Article.create!(:name => 'test article', :profile_id => fast_create(Person).id)
  284 + per = Person.create!(:name => 'test person', :identifier => 'test-person', :user_id => fast_create(User).id)
  285 + com = Community.create!(:name => 'test community')
  286 + eve = Event.create!(:name => 'test event', :profile_id => fast_create(Person).id)
287 287  
288 288 get :index, :query => 'test'
289 289  
290 290 [:articles, :enterprises, :people, :communities, :products, :events].select do |key, name|
291   - !assigns(:environment).enabled?('disable_asset_' + key.to_s)
292   - end.each do |asset|
293   - assert !assigns(:searches)[asset][:results].empty?
294   - end
295   - end
  291 + !assigns(:environment).enabled?('disable_asset_' + key.to_s)
  292 + end.each do |asset|
  293 + assert !assigns(:searches)[asset][:results].empty?
  294 + end
  295 + end
296 296  
297 297 should 'display category image while in directory' do
298 298 parent = Category.create!(:name => 'category1', :environment => Environment.default)
... ... @@ -318,8 +318,8 @@ class SearchControllerTest &lt; ActionController::TestCase
318 318 person = create_user('someone').person
319 319 ten_days_ago = Date.today - 10.day
320 320  
321   - ev1 = create_event(person, :name => 'event 1', :category_ids => [@category.id], :start_date => ten_days_ago)
322   - ev2 = create_event(person, :name => 'event 2', :category_ids => [@category.id], :start_date => Date.today - 2.month)
  321 + ev1 = create_event(person, :name => 'event 1', :category_ids => [@category.id], :start_date => ten_days_ago)
  322 + ev2 = create_event(person, :name => 'event 2', :category_ids => [@category.id], :start_date => Date.today - 2.month)
323 323  
324 324 get :events, :day => ten_days_ago.day, :month => ten_days_ago.month, :year => ten_days_ago.year
325 325 assert_equal [ev1], assigns(:events)
... ... @@ -329,7 +329,7 @@ class SearchControllerTest &lt; ActionController::TestCase
329 329 person = create_user('someone').person
330 330 ten_days_ago = Date.today - 10.day
331 331  
332   - ev1 = create_event(person, :name => 'event 1', :category_ids => [@category.id], :start_date => ten_days_ago)
  332 + ev1 = create_event(person, :name => 'event 1', :category_ids => [@category.id], :start_date => ten_days_ago)
333 333 ev2 = create_event(person, :name => 'event 2', :start_date => ten_days_ago)
334 334  
335 335 get :events, :day => ten_days_ago.day, :month => ten_days_ago.month, :year => ten_days_ago.year, :category_path => @category.path.split('/')
... ... @@ -339,8 +339,8 @@ class SearchControllerTest &lt; ActionController::TestCase
339 339  
340 340 should 'return events of today when no date specified' do
341 341 person = create_user('someone').person
342   - ev1 = create_event(person, :name => 'event 1', :category_ids => [@category.id], :start_date => Date.today)
343   - ev2 = create_event(person, :name => 'event 2', :category_ids => [@category.id], :start_date => Date.today - 2.month)
  342 + ev1 = create_event(person, :name => 'event 1', :category_ids => [@category.id], :start_date => Date.today)
  343 + ev2 = create_event(person, :name => 'event 2', :category_ids => [@category.id], :start_date => Date.today - 2.month)
344 344  
345 345 get :events
346 346  
... ... @@ -351,9 +351,9 @@ class SearchControllerTest &lt; ActionController::TestCase
351 351 person = create_user('someone').person
352 352  
353 353 ev1 = create_event(person, :name => 'event 1', :category_ids => [@category.id],
354   - :start_date => Date.today + 2.month)
  354 + :start_date => Date.today + 2.month)
355 355 ev2 = create_event(person, :name => 'event 2', :category_ids => [@category.id],
356   - :start_date => Date.today + 2.day)
  356 + :start_date => Date.today + 2.day)
357 357  
358 358 get :events
359 359  
... ... @@ -373,8 +373,9 @@ class SearchControllerTest &lt; ActionController::TestCase
373 373 end
374 374  
375 375 should 'see the events paginated' do
  376 + person = create_user('testuser').person
376 377 30.times do |i|
377   - create_event(person, :name => "Event #{i}", :start_date => Date.today)
  378 + create_event(person, :name => "Event #{i}", :start_date => Date.today)
378 379 end
379 380 get :events
380 381 assert_equal 20, assigns(:events).count
... ... @@ -433,8 +434,8 @@ class SearchControllerTest &lt; ActionController::TestCase
433 434 end
434 435  
435 436 should 'show link to article asset in the see all foot link of the articles block in the category page' do
436   - (1..SearchController::MULTIPLE_SEARCH_LIMIT+1).each do |i|
437   - a = create_user("test#{i}").person.articles.create!(:name => "article #{i} to be found")
  437 + (1..SearchController::MULTIPLE_SEARCH_LIMIT+1).each do |i|
  438 + a = create_user("test#{i}").person.articles.create!(:name => "article #{i} to be found")
438 439 ArticleCategorization.add_category_to_article(@category, a)
439 440 end
440 441  
... ... @@ -580,55 +581,55 @@ class SearchControllerTest &lt; ActionController::TestCase
580 581 assert_not_includes assigns(:searches)[:communities][:results], p1
581 582 end
582 583  
583   - should 'keep old urls working' do
584   - get :assets, :asset => 'articles'
  584 + should 'keep old urls working' do
  585 + get :assets, :asset => 'articles'
585 586 assert_redirected_to :controller => :search, :action => :articles
586   - get :assets, :asset => 'people'
  587 + get :assets, :asset => 'people'
587 588 assert_redirected_to :controller => :search, :action => :people
588   - get :assets, :asset => 'communities'
  589 + get :assets, :asset => 'communities'
589 590 assert_redirected_to :controller => :search, :action => :communities
590   - get :assets, :asset => 'products'
  591 + get :assets, :asset => 'products'
591 592 assert_redirected_to :controller => :search, :action => :products
592   - get :assets, :asset => 'enterprises'
  593 + get :assets, :asset => 'enterprises'
593 594 assert_redirected_to :controller => :search, :action => :enterprises
594   - get :assets, :asset => 'events'
  595 + get :assets, :asset => 'events'
595 596 assert_redirected_to :controller => :search, :action => :events
596   - end
  597 + end
597 598  
598   - should 'show tag cloud' do
599   - @controller.stubs(:is_cache_expired?).returns(true)
  599 + should 'show tag cloud' do
  600 + @controller.stubs(:is_cache_expired?).returns(true)
600 601 a = Article.create!(:name => 'my article', :profile_id => fast_create(Person).id)
601 602 a.tag_list = ['one', 'two']
602   - a.save_tags
  603 + a.save_tags
603 604  
604   - get :tags
  605 + get :tags
605 606  
606   - assert assigns(:tags)["two"] = 1
607   - assert assigns(:tags)["one"] = 1
608   - end
  607 + assert assigns(:tags)["two"] = 1
  608 + assert assigns(:tags)["one"] = 1
  609 + end
609 610  
610 611 should 'show tagged content' do
611   - @controller.stubs(:is_cache_expired?).returns(true)
  612 + @controller.stubs(:is_cache_expired?).returns(true)
612 613 a = Article.create!(:name => 'my article', :profile_id => fast_create(Person).id)
613 614 a2 = Article.create!(:name => 'my article 2', :profile_id => fast_create(Person).id)
614 615 a.tag_list = ['one', 'two']
615 616 a2.tag_list = ['two', 'three']
616   - a.save_tags
  617 + a.save_tags
617 618 a2.save_tags
618 619  
619   - get :tag, :tag => 'two'
  620 + get :tag, :tag => 'two'
620 621  
621 622 assert_equivalent [a, a2], assigns(:searches)[:tag][:results]
622 623  
623   - get :tag, :tag => 'one'
  624 + get :tag, :tag => 'one'
624 625  
625 626 assert_equivalent [a], assigns(:searches)[:tag][:results]
626 627 end
627 628  
628 629 should 'not show assets from other environments' do
629 630 other_env = Environment.create!(:name => 'Another environment')
630   - p1 = Person.create!(:name => 'Hildebrando', :identifier => 'hild', :user_id => fast_create(User).id, :environment_id => other_env.id)
631   - p2 = Person.create!(:name => 'Adamastor', :identifier => 'adam', :user_id => fast_create(User).id)
  631 + p1 = Person.create!(:name => 'Hildebrando', :identifier => 'hild', :user_id => fast_create(User).id, :environment_id => other_env.id)
  632 + p2 = Person.create!(:name => 'Adamastor', :identifier => 'adam', :user_id => fast_create(User).id)
632 633 art1 = Article.create!(:name => 'my article', :profile_id => p1.id)
633 634 art2 = Article.create!(:name => 'my article', :profile_id => p2.id)
634 635  
... ... @@ -639,9 +640,9 @@ class SearchControllerTest &lt; ActionController::TestCase
639 640  
640 641 should 'order articles by more recent' do
641 642 Article.destroy_all
642   - art1 = Article.create!(:name => 'review C', :profile_id => fast_create(Person).id, :created_at => Time.now-1.days)
643   - art2 = Article.create!(:name => 'review A', :profile_id => fast_create(Person).id, :created_at => Time.now)
644   - art3 = Article.create!(:name => 'review B', :profile_id => fast_create(Person).id, :created_at => Time.now-2.days)
  643 + art1 = Article.create!(:name => 'review C', :profile_id => fast_create(Person).id, :created_at => Time.now-1.days)
  644 + art2 = Article.create!(:name => 'review A', :profile_id => fast_create(Person).id, :created_at => Time.now)
  645 + art3 = Article.create!(:name => 'review B', :profile_id => fast_create(Person).id, :created_at => Time.now-2.days)
645 646  
646 647 get :articles, :filter => :more_recent
647 648  
... ...
test/integration/routing_test.rb
... ... @@ -270,5 +270,8 @@ class RoutingTest &lt; ActionController::IntegrationTest
270 270 assert_routing('/work/free-software/versions', :controller => 'content_viewer', :action => 'article_versions', :page => [ 'work', 'free-software'] )
271 271 end
272 272  
  273 + should 'have route to get HTML code of Blocks to embed' do
  274 + assert_routing('/embed/block/12345', :controller => 'embed', :action => 'block', :id => '12345')
  275 + end
273 276  
274 277 end
... ...
test/unit/account_helper_test.rb 0 → 100644
... ... @@ -0,0 +1,21 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class AccountHelperTest < ActiveSupport::TestCase
  4 +
  5 + include AccountHelper
  6 + include ActionView::Helpers::TagHelper
  7 +
  8 + should 'not suggest usernames if username is empty' do
  9 + assert_equal '', suggestion_based_on_username
  10 + end
  11 +
  12 + should 'suggest valid usernames' do
  13 + ze = create_user('ze').person
  14 + stubs(:environment).returns(ze.environment)
  15 + suggestions = suggestion_based_on_username('ze')
  16 + suggestions.each do |suggestion|
  17 + assert_equal true, Person.is_available?(suggestion, ze.environment)
  18 + end
  19 + end
  20 +
  21 +end
... ...
test/unit/block_test.rb
... ... @@ -223,6 +223,16 @@ class BlockTest &lt; ActiveSupport::TestCase
223 223 assert !block.visible?(3)
224 224 end
225 225  
  226 + should 'not be embedable by default' do
  227 + assert !Block.new.embedable?
  228 + end
  229 +
  230 + should 'generate embed code' do
  231 + b = Block.new
  232 + b.stubs(:url_for).returns('http://myblogtest.com/embed/block/1')
  233 + assert_equal "<iframe class=\"embed block block\" frameborder=\"0\" height=\"768\" src=\"http://myblogtest.com/embed/block/1\" width=\"1024\"></iframe>", b.embed_code.call
  234 + end
  235 +
226 236 should 'default value for display_user is all' do
227 237 block = Block.new
228 238 assert_equal 'all', block.display_user
... ...
test/unit/profile_test.rb
... ... @@ -363,7 +363,7 @@ class ProfileTest &lt; ActiveSupport::TestCase
363 363 t2 = c.tasks.build; t2.save!; t2.finish
364 364 t3 = c.tasks.build; t3.save!; t3.finish
365 365  
366   - assert_equal [t2, t3], c.tasks.finished
  366 + assert_equivalent [t2, t3], c.tasks.finished
367 367 end
368 368  
369 369 should 'responds to categories' do
... ...
test/unit/tags_helper_test.rb
... ... @@ -20,12 +20,14 @@ class TagsHelperTest &lt; ActiveSupport::TestCase
20 20  
21 21 should 'order tags alphabetically with special characters' do
22 22 result = tag_cloud(
23   - { 'aula'=>9, 'área'=>2, 'area'=>2, 'avião'=>2, 'armário'=>2,
24   - 'A'=>1, 'Á'=>1, 'AB'=>1, 'ÁA'=>1 },
  23 + { 'area'=>9, 'área'=>2, 'base'=>2, 'báse' => 3,
  24 + 'A'=>1, 'Á'=>1, 'zebra'=>1, 'zebrá'=>1 },
25 25 :id,
26 26 { :host=>'noosfero.org', :controller=>'test', :action=>'tag' }
27 27 )
28   - assert_equal %w(A Á ÁA AB area área armário aula avião).join("\n"), result
  28 + result = result.split("\n")
  29 + assert_order ['Á', 'área', 'báse', 'zebrá'], result
  30 + assert_order ['A', 'area', 'base', 'zebra'], result
29 31 end
30 32  
31 33 end
... ...
test/unit/text_article_test.rb
... ... @@ -37,4 +37,51 @@ class TextArticleTest &lt; ActiveSupport::TestCase
37 37 assert_equal Blog.icon_name, TextArticle.icon_name(article)
38 38 end
39 39  
  40 + should 'change image path to relative' do
  41 + person = create_user('testuser').person
  42 + article = TextArticle.new(:profile => person, :name => 'test')
  43 + env = Environment.default
  44 + article.body = "<img src=\"http://#{env.default_hostname}/test.png\" />"
  45 + article.save!
  46 + assert_equal "<img src=\"/test.png\" />", article.body
  47 + end
  48 +
  49 + should 'change link to relative path' do
  50 + person = create_user('testuser').person
  51 + article = TextArticle.new(:profile => person, :name => 'test')
  52 + env = Environment.default
  53 + article.body = "<a href=\"http://#{env.default_hostname}/test\">test</a>"
  54 + article.save!
  55 + assert_equal "<a href=\"/test\">test</a>", article.body
  56 + end
  57 +
  58 + should 'change image path to relative for domain with https' do
  59 + person = create_user('testuser').person
  60 + article = TextArticle.new(:profile => person, :name => 'test')
  61 + env = Environment.default
  62 + article.body = "<img src=\"https://#{env.default_hostname}/test.png\" />"
  63 + article.save!
  64 + assert_equal "<img src=\"/test.png\" />", article.body
  65 + end
  66 +
  67 + should 'change image path to relative for domain with port' do
  68 + person = create_user('testuser').person
  69 + article = TextArticle.new(:profile => person, :name => 'test')
  70 + env = Environment.default
  71 + article.body = "<img src=\"http://#{env.default_hostname}:3000/test.png\" />"
  72 + article.save!
  73 + assert_equal "<img src=\"/test.png\" />", article.body
  74 + end
  75 +
  76 + should 'change image path to relative for domain with www' do
  77 + person = create_user('testuser').person
  78 + article = TextArticle.new(:profile => person, :name => 'test')
  79 + env = Environment.default
  80 + env.force_www = true
  81 + env.save!
  82 + article.body = "<img src=\"http://#{env.default_hostname}:3000/test.png\" />"
  83 + article.save!
  84 + assert_equal "<img src=\"/test.png\" />", article.body
  85 + end
  86 +
40 87 end
... ...
test/unit/uploaded_file_test.rb
... ... @@ -324,13 +324,11 @@ class UploadedFileTest &lt; ActiveSupport::TestCase
324 324 should 'group trackers activity of image\'s upload' do
325 325 ActionTracker::Record.delete_all
326 326 gallery = fast_create(Gallery, :profile_id => profile.id)
327   - count = ActionTracker::Record.find_all_by_verb('upload_image').count
328 327 image1 = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :parent => gallery, :profile => profile)
329   - count += 1
330   - assert_equal count, ActionTracker::Record.find_all_by_verb('upload_image').count
  328 + assert_equal 1, ActionTracker::Record.find_all_by_verb('upload_image').count
331 329  
332 330 image2 = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/other-pic.jpg', 'image/jpg'), :parent => gallery, :profile => profile)
333   - assert_equal count, ActionTracker::Record.find_all_by_verb('upload_image').count
  331 + assert_equal 1, ActionTracker::Record.find_all_by_verb('upload_image').count
334 332 end
335 333  
336 334 {
... ...