Commit af190be9024982c5d0fdd088782174420a3bf65c

Authored by Daniela Feitosa
2 parents cbcad870 d5f224bb

Merge branch 'rails235'

Conflicts:
	features/categories_block.feature
	public/stylesheets/application.css
Showing 92 changed files with 1924 additions and 205 deletions   Show diff stats
app/controllers/box_organizer_controller.rb
... ... @@ -80,6 +80,22 @@ class BoxOrganizerController < ApplicationController
80 80 render :action => 'edit', :layout => false
81 81 end
82 82  
  83 + def search_autocomplete
  84 + if request.xhr? and params[:query]
  85 + search = params[:query]
  86 + path_list = if boxes_holder.is_a?(Environment) && boxes_holder.enabled?('use_portal_community') && boxes_holder.portal_community
  87 + boxes_holder.portal_community.articles.find(:all, :conditions=>"name ILIKE '%#{search}%' or path ILIKE '%#{search}%'", :limit=>20).map { |content| "/{portal}/"+content.path }
  88 + elsif boxes_holder.is_a?(Profile)
  89 + boxes_holder.articles.find(:all, :conditions=>"name ILIKE '%#{search}%' or path ILIKE '%#{search}%'", :limit=>20).map { |content| "/{profile}/"+content.path }
  90 + else
  91 + []
  92 + end
  93 + render :json => path_list.to_json
  94 + else
  95 + redirect_to "/"
  96 + end
  97 + end
  98 +
83 99 def save
84 100 @block = boxes_holder.blocks.find(params[:id])
85 101 @block.update_attributes(params[:block])
... ... @@ -99,6 +115,12 @@ class BoxOrganizerController < ApplicationController
99 115 end
100 116 end
101 117  
  118 + def clone_block
  119 + block = Block.find(params[:id])
  120 + block.duplicate
  121 + redirect_to :action => 'index'
  122 + end
  123 +
102 124 protected :boxes_editor?
103 125  
104 126 end
... ...
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/my_profile/profile_design_controller.rb
... ... @@ -55,10 +55,4 @@ class ProfileDesignController &lt; BoxOrganizerController
55 55 blocks
56 56 end
57 57  
58   - def clone
59   - block = Block.find(params[:id])
60   - block.duplicate
61   - redirect_to :action => 'index'
62   - end
63   -
64 58 end
... ...
app/controllers/public/account_controller.rb
... ... @@ -246,15 +246,19 @@ class AccountController &lt; ApplicationController
246 246 end
247 247 end
248 248  
249   - def check_url
  249 + def check_valid_name
250 250 @identifier = params[:identifier]
251 251 valid = Person.is_available?(@identifier, environment)
252 252 if valid
253 253 @status = _('This login name is available')
254 254 @status_class = 'validated'
255   - else
  255 + elsif !@identifier.empty?
  256 + @suggested_usernames = suggestion_based_on_username(@identifier)
256 257 @status = _('This login name is unavailable')
257 258 @status_class = 'invalid'
  259 + else
  260 + @status_class = 'invalid'
  261 + @status = _('This field can\'t be blank')
258 262 end
259 263 render :partial => 'identifier_status'
260 264 end
... ... @@ -287,6 +291,23 @@ class AccountController &lt; ApplicationController
287 291 render :text => user_data.to_json, :layout => false, :content_type => "application/javascript"
288 292 end
289 293  
  294 + def search_cities
  295 + if request.xhr? and params[:state_name] and params[:city_name]
  296 + render :json => MapsHelper.search_city(params[:city_name], params[:state_name])
  297 + else
  298 + render :json => [].to_json
  299 + end
  300 + end
  301 +
  302 + def search_state
  303 + if request.xhr? and params[:state_name]
  304 + render :json => MapsHelper.search_state(params[:state_name])
  305 + else
  306 + render :json => [].to_json
  307 + end
  308 + end
  309 +
  310 +
290 311 protected
291 312  
292 313 def redirect?
... ...
app/controllers/public/content_viewer_controller.rb
... ... @@ -113,6 +113,15 @@ class ContentViewerController &lt; ApplicationController
113 113 @comments = @plugins.filter(:unavailable_comments, @comments)
114 114 @comments_count = @comments.count
115 115 @comments = @comments.without_reply.paginate(:per_page => per_page, :page => params[:comment_page] )
  116 + @comment_order = params[:comment_order].nil? ? 'oldest' : params[:comment_order]
  117 +
  118 + if request.xhr? and params[:comment_order]
  119 + if @comment_order == 'newest'
  120 + @comments = @comments.reverse
  121 + end
  122 +
  123 + return render :partial => 'comment/comment', :collection => @comments
  124 + end
116 125  
117 126 if params[:slideshow]
118 127 render :action => 'slideshow', :layout => 'slideshow'
... ...
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
... ... @@ -65,7 +65,7 @@ module BoxesHelper
65 65 end
66 66  
67 67 def display_box_content(box, main_content)
68   - context = { :article => @page, :request_path => request.path, :locale => locale, :params => request.params }
  68 + context = { :article => @page, :request_path => request.path, :locale => locale, :params => request.params, :user => user }
69 69 box_decorator.select_blocks(box.blocks.includes(:box), context).map { |item| display_block(item, main_content) }.join("\n") + box_decorator.block_target(box)
70 70 end
71 71  
... ... @@ -212,13 +212,24 @@ module BoxesHelper
212 212  
213 213 if !block.main?
214 214 buttons << icon_button(:delete, _('Remove block'), { :action => 'remove', :id => block.id }, { :method => 'post', :confirm => _('Are you sure you want to remove this block?')})
215   - buttons << icon_button(:clone, _('Clone'), { :action => 'clone', :id => block.id }, { :method => 'post' })
  215 + buttons << icon_button(:clone, _('Clone'), { :action => 'clone_block', :id => block.id }, { :method => 'post' })
216 216 end
217 217  
218 218 if block.respond_to?(:help)
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/macros_helper.rb
... ... @@ -20,14 +20,16 @@ module MacrosHelper
20 20 jQuery('<div>'+#{macro_configuration_dialog(macro).to_json}+'</div>').dialog({
21 21 title: #{macro_title(macro).to_json},
22 22 modal: true,
23   - buttons: [
24   - {text: #{_('Ok').to_json}, click: function(){
  23 + buttons: {
  24 + #{_('Ok').to_json}: function(){
25 25 tinyMCE.activeEditor.execCommand('mceInsertContent', false,
26 26 (function(dialog){ #{macro_generator(macro)} })(this));
27 27 jQuery(this).dialog('close');
28   - }},
29   - {text: #{_('Cancel').to_json}, click: function(){jQuery(this).dialog('close');}}
30   - ]
  28 + },
  29 + #{_('Cancel').to_json}: function(){
  30 + jQuery(this).dialog('close');
  31 + }
  32 + }
31 33 });
32 34 }"
33 35 end
... ... @@ -57,7 +59,11 @@ module MacrosHelper
57 59  
58 60 def macro_generator(macro)
59 61 if macro.configuration[:generator]
60   - macro.configuration[:generator]
  62 + if macro.configuration[:generator].respond_to?(:call)
  63 + macro.configuration[:generator].call(macro)
  64 + else
  65 + macro.configuration[:generator]
  66 + end
61 67 else
62 68 macro_default_generator(macro)
63 69 end
... ... @@ -66,8 +72,7 @@ module MacrosHelper
66 72  
67 73 def macro_default_generator(macro)
68 74 code = "var params = {};"
69   - configuration = macro_configuration(macro)
70   - configuration[:params].map do |field|
  75 + macro.configuration[:params].map do |field|
71 76 code += "params.#{field[:name]} = jQuery('*[name=#{field[:name]}]', dialog).val();"
72 77 end
73 78 code + "
... ...
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/helpers/token_helper.rb
... ... @@ -27,7 +27,7 @@ module TokenHelper
27 27 hintText: #{options[:hint_text].to_json},
28 28 noResultsText: #{options[:no_results_text].to_json},
29 29 searchingText: #{options[:searching_text].to_json},
30   - searchDelay: #{options[:serach_delay].to_json},
  30 + searchDelay: #{options[:search_delay].to_json},
31 31 preventDuplicates: #{options[:prevent_duplicates].to_json},
32 32 backspaceDeleteItem: #{options[:backspace_delete_item].to_json},
33 33 queryParam: #{name.to_json},
... ...
app/models/block.rb
... ... @@ -16,17 +16,36 @@ 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:
22 39 #
23 40 # * <tt>:article</tt>: the article being viewed currently
24 41 # * <tt>:language</tt>: in which language the block will be displayed
  42 + # * <tt>:user</tt>: the logged user
25 43 def visible?(context = nil)
26 44 return false if display == 'never'
27 45  
28 46 if context
29 47 return false if language != 'all' && language != context[:locale]
  48 + return false unless display_to_user?(context[:user])
30 49  
31 50 begin
32 51 return self.send("display_#{display}", context)
... ... @@ -38,6 +57,10 @@ class Block &lt; ActiveRecord::Base
38 57 true
39 58 end
40 59  
  60 + def display_to_user?(user)
  61 + display_user == 'all' || (user.nil? && display_user == 'not_logged') || (user && display_user == 'logged')
  62 + end
  63 +
41 64 def display_always(context)
42 65 true
43 66 end
... ... @@ -68,6 +91,14 @@ class Block &lt; ActiveRecord::Base
68 91 # the homepage of its owner.
69 92 settings_items :display, :type => :string, :default => 'always'
70 93  
  94 +
  95 + # The condition for displaying a block to users. It can assume the following values:
  96 + #
  97 + # * <tt>'all'</tt>: the block is always displayed
  98 + # * <tt>'logged'</tt>: the block is displayed to logged users only
  99 + # * <tt>'not_logged'</tt>: the block is displayed only to not logged users
  100 + settings_items :display_user, :type => :string, :default => 'all'
  101 +
71 102 # The block can be configured to be displayed in all languages or in just one language. It can assume any locale of the environment:
72 103 #
73 104 # * <tt>'all'</tt>: the block is always displayed
... ... @@ -171,12 +202,20 @@ class Block &lt; ActiveRecord::Base
171 202 'never' => __('Don\'t display'),
172 203 }
173 204  
174   - def display_options
  205 + def display_options_available
175 206 DISPLAY_OPTIONS.keys
176 207 end
177 208  
178   - def display_option_label(option)
179   - DISPLAY_OPTIONS[option]
  209 + def display_options
  210 + DISPLAY_OPTIONS.slice(*display_options_available)
  211 + end
  212 +
  213 + def display_user_options
  214 + @display_user_options ||= {
  215 + 'all' => __('All users'),
  216 + 'logged' => __('Logged'),
  217 + 'not_logged' => __('Not logged'),
  218 + }
180 219 end
181 220  
182 221 def duplicate
... ...
app/models/link_list_block.rb
... ... @@ -70,6 +70,8 @@ class LinkListBlock &lt; Block
70 70 def expand_address(address)
71 71 add = if owner.respond_to?(:identifier)
72 72 address.gsub('{profile}', owner.identifier)
  73 + elsif owner.is_a?(Environment) && owner.enabled?('use_portal_community') && owner.portal_community
  74 + address.gsub('{portal}', owner.portal_community.identifier)
73 75 else
74 76 address
75 77 end
... ...
app/models/main_block.rb
... ... @@ -24,7 +24,7 @@ class MainBlock &lt; Block
24 24 false
25 25 end
26 26  
27   - def display_options
  27 + def display_options_available
28 28 ['always', 'except_home_page']
29 29 end
30 30  
... ...
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
... ... @@ -7,6 +7,8 @@
7 7  
8 8 <% @profile_data = @person %>
9 9  
  10 +<%= javascript_include_tag('sign_up_password_rate') %>
  11 +
10 12 <%= error_messages_for :user, :person, :header_message => _('The account could not be created') %>
11 13  
12 14 <% labelled_form_for :user, @user, :html => { :multipart => true, :id => 'signup-form', :honeypot => true } do |f| %>
... ... @@ -35,24 +37,30 @@
35 37 <%= required text_field(:user, :login, :id => 'user_login',
36 38 :onchange => 'this.value = convToValidUsername(this.value);') %>
37 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>
38 41 </div>
39 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') %>
40 43 <br style="clear: both;" />
41 44 </div>
42 45 </div>
43   - <%= observe_field 'user_login',
44   - :url => { :action => 'check_url' },
45   - :with => 'identifier',
46   - :update => 'url-check',
47   - :loading => "jQuery('#user_login').removeClass('#{validation_classes}').addClass('checking');
48   - jQuery('#url-check').html('<p><span class=\"checking\">#{checking_message(:url)}</span></p>');",
49   - :complete => "jQuery('#user_login').removeClass('checking')"
50   - %>
51   -
  46 + <%= javascript_include_tag "signup_form" %>
52 47 <div id='signup-password'>
53 48 <%= required f.password_field(:password, :id => 'user_pw') %>
54 49 <%= content_tag(:small,_('Choose a password that you can remember easily. It must have at least 4 characters.'), :id => 'password-balloon') %>
55   - <div id='fake-check'><p>&nbsp;</p></div>
  50 + <div id='password-rate'>
  51 + <p><span class="invalid hidden" id='result-short'>
  52 + <%=_('Short') %>
  53 + </span></p>
  54 + <p><span class="invalid hidden" id='result-bad'>
  55 + <%=_('Bad') %>
  56 + </span></p>
  57 + <p><span class="invalid hidden" id='result-good'>
  58 + <%=_('Good') %>
  59 + </span></p>
  60 + <p><span class="invalid hidden" id='result-strong'>
  61 + <%=_('Strong') %>
  62 + </span></p>
  63 + </div>
56 64 </div>
57 65  
58 66 <div id='signup-password-confirmation'>
... ... @@ -182,4 +190,9 @@ jQuery(function($) {
182 190 else $(this).addClass('validated');
183 191 });
184 192 });
  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 +}
185 198 </script>
... ...
app/views/box_organizer/_link_list_block.rhtml
  1 +<%= javascript_include_tag "edit-link-list.js" %>
  2 +
1 3 <strong><%= _('Links') %></strong>
2 4 <div id='edit-link-list-block'>
3   -<table id='links' class='noborder'>
4   - <tr>
5   - <th><%= _('Icon') %></th>
6   - <th><%= _('Name') %></th>
7   - <th><%= _('Address') %></th>
8   - <th><%= _('Title') %></th>
9   - <th><%= _('Target') %></th>
10   - </tr>
11   - <% for link in @block.links do %>
12   - <tr>
13   - <td><%= icon_selector(link['icon']) %></td>
14   - <td><%= text_field_tag 'block[links][][name]', link[:name], :class => 'link-name', :maxlength => 20 %></td>
15   - <td class='cel-address'><%= text_field_tag 'block[links][][address]', link[:address], :class => 'link-address' %></td>
16   - <td><%= text_field_tag 'block[links][][title]', link[:title], :class => 'link-title' %></td>
17   - <td><%= select_tag('block[links][][target]', options_for_select(LinkListBlock::TARGET_OPTIONS, link[:target])) %></td>
18   - </tr>
19   - <% end %>
20   -</table>
  5 + <ul class='link-list-header'>
  6 + <li class='link-list-icon'><%= _('Icon') %></li>
  7 + <li class='link-list-name'><%= _('Name') %></li>
  8 + <li class='link-list-address'><%= _('Address') %></li>
  9 + <li class='link-list-target'><%= _('Target') %></li>
  10 + </ul>
  11 + <ul id="dropable-link-list">
  12 + <% for link in @block.links do %>
  13 + <li>
  14 + <ul class="link-list-row">
  15 + <li>
  16 + <%= icon_selector(link['icon']) %>
  17 + </li>
  18 + <li>
  19 + <%= text_field_tag 'block[links][][name]', link[:name], :class => 'link-name', :maxlength => 20 %>
  20 + </li>
  21 + <li>
  22 + <%= text_field_tag 'block[links][][address]', link[:address], :class => 'link-address' %>
  23 + </li>
  24 + <li>
  25 + <%= select_tag('block[links][][target]', options_for_select(LinkListBlock::TARGET_OPTIONS, link[:target])) %>
  26 + </li>
  27 + <li>
  28 + <%= button_without_text(:delete, _('Delete'), "#" , :class=>"delete-link-list-row") %>
  29 + </li>
  30 + </ul>
  31 + </li>
  32 + <% end %>
  33 + </ul>
  34 + <input type="hidden" id="page_url" value="<%=url_for(:action=>'search_autocomplete')%>" />
21 35 </div>
22 36  
23 37 <%= link_to_function(_('New link'), nil, :class => 'button icon-add with-text') do |page|
24   - page.insert_html :bottom, 'links', content_tag('tr',
25   - content_tag('td', icon_selector('ok')) +
26   - content_tag('td', text_field_tag('block[links][][name]', '', :maxlength => 20)) +
27   - content_tag('td', text_field_tag('block[links][][address]', nil, :class => 'link-address'), :class => 'cel-address') +
28   - content_tag('td', text_field_tag('block[links][][title]', '', :class => 'link-title')) +
29   - content_tag('td', select_tag('block[links][][target]', options_for_select(LinkListBlock::TARGET_OPTIONS, '_self')))
  38 + page.insert_html :bottom, 'dropable-link-list', content_tag('li',
  39 + content_tag('ul',
  40 + content_tag('li', icon_selector('ok')) +
  41 + content_tag('li', text_field_tag('block[links][][name]', '', :maxlength => 20)) +
  42 + content_tag('li', text_field_tag('block[links][][address]', nil, :class => 'link-address')) +
  43 + content_tag('li', select_tag('block[links][][target]',
  44 + options_for_select(LinkListBlock::TARGET_OPTIONS, '_self'))) +
  45 + content_tag('li', button_without_text(:delete, _('Delete'), "#" , :class=>"delete-link-list-row")),
  46 + :class=>"link-list-row new_link_row")
30 47 ) +
31   - javascript_tag("$('edit-link-list-block').scrollTop = $('edit-link-list-block').scrollHeight")
  48 + javascript_tag("new_link_action()")
32 49 end %>
... ...
app/views/box_organizer/edit.rhtml
... ... @@ -7,13 +7,14 @@
7 7  
8 8 <%= render :partial => partial_for_class(@block.class) %>
9 9  
10   - <%= labelled_form_field _('Display this block:'), '' %>
11   - <div style='margin-left: 10px'>
12   - <% @block.display_options.each do |option| %>
13   - <%= radio_button(:block, :display, option) %>
14   - <%= label_tag("block_display_#{option}", _(@block.display_option_label(option))) %>
15   - <br/>
16   - <% end %>
  10 + <div class="display">
  11 + <%= labelled_form_field _('Display this block:'),
  12 + select_tag('block[display]', options_from_collection_for_select(@block.display_options, :first, :last, @block.display))
  13 + %>
  14 + </div>
  15 + <div class="display_user">
  16 + <%= labelled_form_field _('Display to users:'), '' %>
  17 + <%= select_tag('block[display_user]', options_from_collection_for_select(@block.display_user_options, :first, :last, @block.display_user)) %>
17 18 </div>
18 19  
19 20 <%= labelled_form_field(_('Show for:'), select(:block, :language, [ [ _('all languages'), 'all']] + environment.locales.map {|key, value| [value, key]} )) %>
... ...
app/views/content_viewer/view_page.rhtml
... ... @@ -80,8 +80,26 @@
80 80 </h3>
81 81 <% end %>
82 82  
83   - <% if @page.accept_comments? && @comments.count > 1 %>
  83 + <% if @page.accept_comments? && @comments_count > 1 %>
84 84 <%= link_to(_('Post a comment'), '#', :class => 'display-comment-form', :id => 'top-post-comment-button', :onclick => "jQuery('#page-comment-form .display-comment-form').first().click();") %>
  85 +
  86 + <%= hidden_field_tag("page_url", url_for(:controller=>'content_viewer', :action=>'view_page', :profile=>profile.identifier)) %>
  87 + <%= javascript_include_tag "comment_order.js" %>
  88 + <div class="comment-order">
  89 + <% form_tag({:controller=>'content_viewer' , :action=>'view_page'}, {:method=>'get', :id=>"form_order"}) do %>
  90 + <%= select_tag 'comment_order', options_for_select({_('Oldest first')=>'oldest', _('Newest first')=>'newest'}, @comment_order) %>
  91 + <% end %>
  92 + </div>
  93 + <% end %>
  94 +
  95 + <% if @page.accept_comments? and @comments.count > 1 %>
  96 + <%= hidden_field_tag("page_url", url_for(:controller=>'content_viewer', :action=>'view_page', :profile=>profile.identifier)) %>
  97 + <%= javascript_include_tag "comment_order.js" %>
  98 + <div class="comment-order">
  99 + <% form_tag({:controller=>'content_viewer' , :action=>'view_page'}, {:method=>'get', :id=>"form_order"}) do %>
  100 + <%= select_tag 'comment_order', options_for_select({_('Oldest first')=>'oldest', _('Newest first')=>'newest'}, @comment_order) %>
  101 + <% end %>
  102 + </div>
85 103 <% end %>
86 104  
87 105 <ul class="article-comments-list">
... ...
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/categories_block.feature
... ... @@ -26,14 +26,9 @@ Feature: categories_block
26 26 And I am logged in as admin
27 27 And I go to /admin/environment_design
28 28  
29   - # Note that this @ignore-hidden-elements only works for seeing hidden
30   - # elements. It actually doesn't work for following hidden link or pressing
31   - # hidden buttons. That's why it's necessary to use this display hack to show
32   - # the link.
33   - @selenium @ignore-hidden-elements
  29 + @selenium
34 30 Scenario: List just product categories
35   - Given display ".button-bar"
36   - And I follow "Edit" within ".categories-block"
  31 + Given I follow "Edit" within ".categories-block"
37 32 And I check "Product"
38 33 When I press "Save"
39 34 Then I should see "Food"
... ... @@ -44,8 +39,7 @@ Feature: categories_block
44 39  
45 40 @selenium
46 41 Scenario: Show submenu if it exists
47   - Given display ".button-bar"
48   - And I follow "Edit" within ".categories-block"
  42 + Given I follow "Edit" within ".categories-block"
49 43 And I check "Product"
50 44 And I press "Save"
51 45 Then I should see "Food"
... ... @@ -62,8 +56,7 @@ Feature: categories_block
62 56  
63 57 @selenium
64 58 Scenario: Show only one submenu per time
65   - Given display ".button-bar"
66   - And I follow "Edit" within ".categories-block"
  59 + Given I follow "Edit" within ".categories-block"
67 60 And I check "Product"
68 61 And I press "Save"
69 62 Then I should see "Book"
... ... @@ -73,16 +66,14 @@ Feature: categories_block
73 66  
74 67 @selenium
75 68 Scenario: List just general categories
76   - Given display ".button-bar"
77   - And I follow "Edit" within ".categories-block"
  69 + Given I follow "Edit" within ".categories-block"
78 70 And I check "Generic category"
79 71 When I press "Save"
80 72 Then I should see "Wood"
81 73  
82 74 @selenium
83 75 Scenario: List just regions
84   - Given display ".button-bar"
85   - And I follow "Edit" within ".categories-block"
  76 + Given I follow "Edit" within ".categories-block"
86 77 And I check "Region"
87 78 When I press "Save"
88 79 Then I should see "Bahia"
... ...
features/comment.feature
... ... @@ -97,3 +97,41 @@ Feature: comment
97 97 Given I am on /booking/article-to-comment
98 98 And I follow "Post a comment"
99 99 Then "Post a comment" should not be visible within "#article"
  100 +
  101 + @selenium
  102 + Scenario: the newest post from a forum should be displayed first.
  103 + Given the following users
  104 + | login | name |
  105 + | joaosilva | Joao Silva |
  106 + And the following forums
  107 + | owner | name |
  108 + | joaosilva | Forum |
  109 + And the following articles
  110 + | owner | name | parent |
  111 + | joaosilva | Post one | Forum |
  112 + And the following comments
  113 + | article | author | title | body |
  114 + | Post one | joaosilva | Hi all | Hi all |
  115 + | Post one | joaosilva | Hello | Hello |
  116 + When I go to /joaosilva/forum/post-one
  117 + And I select "Newest first" from "comment_order" within ".comment-order"
  118 + Then I should see "Hello" within ".article-comment"
  119 +
  120 + @selenium
  121 + Scenario: the oldest post from a forum should be displayed first.
  122 + Given the following users
  123 + | login | name |
  124 + | joaosilva | Joao Silva |
  125 + And the following forums
  126 + | owner | name |
  127 + | joaosilva | Forum |
  128 + And the following articles
  129 + | owner | name | parent |
  130 + | joaosilva | Post one | Forum |
  131 + And the following comments
  132 + | article | author | title | body |
  133 + | Post one | joaosilva | Hi all | Hi all |
  134 + | Post one | joaosilva | Hello | Hello |
  135 + When I go to /joaosilva/forum/post-one
  136 + And I select "Oldest first" from "comment_order" within ".comment-order"
  137 + Then I should see "Hi all" within ".article-comment"
... ...
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/noosfero/i18n.rb
... ... @@ -6,9 +6,15 @@ class Object
6 6 alias :ngettext :n_
7 7 end
8 8  
  9 +
  10 +custom_locale_dir = Rails.root.join('custom_locales', Rails.env)
  11 +repos = []
  12 +if File.exists?(custom_locale_dir)
  13 + repos << FastGettext::TranslationRepository.build('environment', :type => 'po', :path => custom_locale_dir)
  14 +end
  15 +
9 16 # translations in place?
10 17 locale_dir = Rails.root.join('locale')
11   -repos = []
12 18 if File.exists?(locale_dir)
13 19 repos << FastGettext::TranslationRepository.build('noosfero', :type => 'mo', :path => locale_dir)
14 20 repos << FastGettext::TranslationRepository.build('iso_3166', :type => 'mo', :path => locale_dir)
... ...
lib/noosfero/plugin.rb
... ... @@ -16,14 +16,7 @@ class Noosfero::Plugin
16 16 end
17 17  
18 18 def init_system
19   - enabled_plugins = Dir.glob(File.join(Rails.root, 'config', 'plugins', '*'))
20   - if Rails.env.test? && !enabled_plugins.include?(File.join(Rails.root, 'config', 'plugins', 'foo'))
21   - enabled_plugins << File.join(Rails.root, 'plugins', 'foo')
22   - end
23   -
24   - enabled_plugins.select do |entry|
25   - File.directory?(entry)
26   - end.each do |dir|
  19 + available_plugins.each do |dir|
27 20 load_plugin dir
28 21 end
29 22 end
... ... @@ -76,12 +69,19 @@ class Noosfero::Plugin
76 69 klass(plugin_name)
77 70 end
78 71  
79   - def all
80   - @all ||= []
  72 + def available_plugins
  73 + unless @available_plugins
  74 + path = File.join(Rails.root, 'config', 'plugins', '*')
  75 + @available_plugins = Dir.glob(path).select{ |i| File.directory?(i) }
  76 + if Rails.env.test? && !@available_plugins.include?(File.join(Rails.root, 'config', 'plugins', 'foo'))
  77 + @available_plugins << File.join(Rails.root, 'plugins', 'foo')
  78 + end
  79 + end
  80 + @available_plugins
81 81 end
82 82  
83   - def inherited(subclass)
84   - all << subclass.to_s unless all.include?(subclass.to_s)
  83 + def all
  84 + @all ||= available_plugins.map{ |dir| (File.basename(dir) + "_plugin").camelize }
85 85 end
86 86  
87 87 def public_name
... ...
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/pg_search/lib/ext/active_record.rb
... ... @@ -2,11 +2,9 @@ require_dependency &#39;active_record&#39;
2 2  
3 3 class ActiveRecord::Base
4 4 def self.pg_search_plugin_search(query)
5   - query.gsub!(/\|/,' ')
6   - formatted_query = query.split.map{|w| w += ":*"}.join('|')
7   -
  5 + filtered_query = query.gsub(/[\|\(\)\\\/\s\[\]'"*%&!:]/,' ').split.map{|w| w += ":*"}.join('|')
8 6 if defined?(self::SEARCHABLE_FIELDS)
9   - where("to_tsvector('simple', #{pg_search_plugin_fields}) @@ to_tsquery('#{formatted_query}')")
  7 + where("to_tsvector('simple', #{pg_search_plugin_fields}) @@ to_tsquery('#{filtered_query}')")
10 8 else
11 9 raise "No searchable fields defined for #{self.name}"
12 10 end
... ...
plugins/pg_search/test/unit/pg_search_plugin_test.rb
... ... @@ -21,6 +21,11 @@ class PgSearchPluginTest &lt; ActiveSupport::TestCase
21 21 assert_includes search(Profile, 'admin deb'), profile2
22 22 end
23 23  
  24 + should 'locate profile escaping special characters' do
  25 + profile = fast_create(Profile, :name => 'John', :identifier => 'waterfall')
  26 + assert_includes search(Profile, ') ( /\/\/\/\/\ o_o oOo o_o /\/\/\/\/\ ) ((tx waterfall)'), profile
  27 + end
  28 +
24 29 # TODO This feature is available only on Postgresql 9.0
25 30 # http://www.postgresql.org/docs/9.0/static/unaccent.html
26 31 # should 'ignore accents' do
... ...
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
... ...
plugins/variables/doc/variables.textile 0 → 100644
... ... @@ -0,0 +1,39 @@
  1 +h1. Variables Plugin
  2 +
  3 +A set of simple variables to be used in a macro context.
  4 +
  5 +h2. Usage
  6 +
  7 +* Create a HTML content using RawHTMLBlock, TinyMceArticle or other
  8 + article with HTML support
  9 +* Add a HTML div tag with css class "macro" (see Example)
  10 +* Add inner that div tag the variable desired, like {profile}
  11 +
  12 +h2. Usage with TinyMceArticle
  13 +
  14 +The Noosfero's macros add a extra button in toolbar of the editor
  15 +to use macros in a single way, that way this plugin add a option
  16 +called "Variables" under this option.
  17 +
  18 +h2. Supported variables
  19 +
  20 +* {profile} - will be replaced by the identifier of the profile
  21 +* {name} - will be replaced by the name of the profile
  22 +
  23 +h2. Example
  24 +
  25 +<pre>
  26 +<div class="macro" data-macro="variables_plugin/profile">
  27 + the identifier of the profile = {profile}
  28 + the name of the profile = {name}
  29 +</div>
  30 +</pre>
  31 +
  32 +h2. Info
  33 +
  34 +This plugin was inspired by the solution proposed by the Serpro in
  35 +the merge-request #419 on the Gitorious:
  36 +
  37 +* https://gitorious.org/noosfero/noosfero/merge_requests/419
  38 +
  39 +And improved by the guys from the UnB.
... ...
plugins/variables/lib/variables_plugin.rb 0 → 100644
... ... @@ -0,0 +1,13 @@
  1 +class VariablesPlugin < Noosfero::Plugin
  2 +
  3 + def self.plugin_name
  4 + "Variables Plugin"
  5 + end
  6 +
  7 + def self.plugin_description
  8 + _("A set of simple variables to be used in a macro context")
  9 + end
  10 +
  11 +end
  12 +
  13 +require_dependency 'variables_plugin/macros/profile'
... ...
plugins/variables/lib/variables_plugin/macros/profile.rb 0 → 100644
... ... @@ -0,0 +1,37 @@
  1 +ActionView::Base.sanitized_allowed_attributes += ['data-macro']
  2 +
  3 +class VariablesPlugin::Profile < Noosfero::Plugin::Macro
  4 +
  5 + def self.configuration
  6 + {
  7 + :title => _('Variables'),
  8 + :skip_dialog => false,
  9 + :generator => method(:macro_default_generator),
  10 + :params => [
  11 + {
  12 + :name => 'variable',
  13 + :label => _('Select the desired variable'),
  14 + :type => 'select',
  15 + :values => ['{profile}', '{name}']
  16 + }
  17 + ],
  18 + }
  19 + end
  20 +
  21 + def self.macro_default_generator(macro)
  22 + "
  23 + '<div class=\"macro mceNonEditable\" data-macro=\"#{macro.identifier}\">'
  24 + + jQuery('*[name=variable]', dialog).val()
  25 + + '</div>';
  26 + "
  27 + end
  28 +
  29 + def parse(params, inner_html, source)
  30 + if context.profile
  31 + inner_html.gsub!(/\{profile\}/, context.profile.identifier)
  32 + inner_html.gsub!(/\{name\}/, context.profile.name)
  33 + end
  34 + inner_html
  35 + end
  36 +
  37 +end
... ...
plugins/variables/test/unit/profile_test.rb 0 → 100644
... ... @@ -0,0 +1,41 @@
  1 +class ProfileTest < ActiveSupport::TestCase
  2 +
  3 + def setup
  4 + @macro = VariablesPlugin::Profile.new
  5 + @macro.context = mock()
  6 + @profile = fast_create(Community)
  7 + @macro.context.stubs(:profile).returns(@profile)
  8 + end
  9 +
  10 + attr_reader :macro, :profile
  11 +
  12 + should 'have a configuration' do
  13 + assert VariablesPlugin::Profile.configuration
  14 + end
  15 +
  16 + should 'substitute the {profile} variable by the profile idenfifier' do
  17 + html = 'the profile identifier is {profile}'
  18 + content = macro.parse({}, html, profile)
  19 + assert_equal "the profile identifier is #{profile.identifier}", content
  20 + end
  21 +
  22 + should 'substitute the {name} variable by the profile name' do
  23 + html = 'the profile name is {name}'
  24 + content = macro.parse({}, html, profile)
  25 + assert_equal "the profile name is #{profile.name}", content
  26 + end
  27 +
  28 + should 'do not change the content if the variable is not supported' do
  29 + html = 'the variable {unsupported} is not supported'
  30 + content = macro.parse({}, html, profile)
  31 + assert_equal html, content
  32 + end
  33 +
  34 + should 'do nothing out of profile context' do
  35 + macro.context.stubs(:profile).returns(nil)
  36 + html = 'there is no {support} out of profile context'
  37 + content = macro.parse({}, html, profile)
  38 + assert_equal html, content
  39 + end
  40 +
  41 +end
... ...
plugins/variables/test/unit/variables_plugin_test.rb 0 → 100644
... ... @@ -0,0 +1,20 @@
  1 +require 'test_helper'
  2 +
  3 +class VariablesPluginTest < ActiveSupport::TestCase
  4 +
  5 + def setup
  6 + @environment = Environment.default
  7 + @plugin = VariablesPlugin.new
  8 + end
  9 +
  10 + attr_reader :environment, :plugin
  11 +
  12 + should 'have a name' do
  13 + assert_not_equal Noosfero::Plugin.plugin_name, VariablesPlugin::plugin_name
  14 + end
  15 +
  16 + should 'describe yourself' do
  17 + assert_not_equal Noosfero::Plugin.plugin_description, VariablesPlugin::plugin_description
  18 + end
  19 +
  20 +end
... ...
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-undo { background-image: url(Tango/16x16/actions/edit-undo.png) }
4 5 .icon-home { background-image: url(Tango/16x16/actions/go-home.png) }
... ...
public/designs/themes/base/style.css
... ... @@ -1275,6 +1275,11 @@ hr.pre-posts, hr.sep-posts {
1275 1275 padding-right: 9px;
1276 1276 }
1277 1277  
  1278 +.comment-order {
  1279 + float: right;
  1280 + display: block;
  1281 +}
  1282 +
1278 1283 .comment-from-owner .comment-created-at {
1279 1284 color: #333;
1280 1285 }
... ...
public/images/drag-and-drop.png 0 → 100644

1.11 KB

public/javascripts/application.js
... ... @@ -1101,4 +1101,4 @@ jQuery(document).ready(function(){
1101 1101 jQuery("#article_has_terms_of_use").click(function(){
1102 1102 showHideTermsOfUse();
1103 1103 });
1104   -});
1105 1104 \ No newline at end of file
  1105 +});
... ...
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/comment_order.js 0 → 100644
... ... @@ -0,0 +1,21 @@
  1 +function send_order(order, url) {
  2 + open_loading(DEFAULT_LOADING_MESSAGE);
  3 +
  4 + jQuery.ajax({
  5 + url:url,
  6 + data: {"comment_order":order},
  7 + success: function(response) {
  8 + close_loading();
  9 + jQuery(".article-comments-list").html(response);
  10 + },
  11 + error: function() { close_loading() }
  12 + });
  13 +}
  14 +
  15 +
  16 +jQuery(document).ready(function(){
  17 + jQuery("#comment_order").change(function(){
  18 + var url = jQuery("#page_url").val();
  19 + send_order(this.value, url);
  20 + });
  21 +});
0 22 \ No newline at end of file
... ...
public/javascripts/edit-link-list.js 0 → 100644
... ... @@ -0,0 +1,39 @@
  1 +function send_ajax(source_url) {
  2 + jQuery(".link-address").autocomplete({
  3 + source : function(request, response){
  4 + jQuery.ajax({
  5 + type: "GET",
  6 + url: source_url,
  7 + data: {query: request.term},
  8 + success: function(result){
  9 + response(result);
  10 + },
  11 + error: function(ajax, stat, errorThrown) {
  12 + console.log('Link not found : ' + errorThrown);
  13 + }
  14 + });
  15 + },
  16 +
  17 + minLength: 3
  18 + });
  19 +}
  20 +
  21 +function new_link_action(){
  22 + send_ajax(jQuery("#page_url").val());
  23 +
  24 + jQuery(".delete-link-list-row").click(function(){
  25 + jQuery(this).parent().parent().remove();
  26 + return false;
  27 + });
  28 +
  29 + jQuery(document).scrollTop(jQuery('#dropable-link-list').scrollTop());
  30 +}
  31 +
  32 +jQuery(document).ready(function(){
  33 + new_link_action();
  34 +
  35 + jQuery("#dropable-link-list").sortable({
  36 + revert: true,
  37 + axis: "y"
  38 + });
  39 +});
0 40 \ No newline at end of file
... ...
public/javascripts/sign_up_password_rate.js 0 → 100644
... ... @@ -0,0 +1,121 @@
  1 +// This jQuery plugin is written by firas kassem [2007.04.05] and was modified to fit noosfero
  2 +// Firas Kassem phiras.wordpress.com || phiras at gmail {dot} com
  3 +// for more information : http://phiras.wordpress.com/2007/04/08/password-strength-meter-a-jquery-plugin/
  4 +
  5 +var blankPass = -1
  6 +var shortPass = 0
  7 +var badPass = 1
  8 +var goodPass = 2
  9 +var strongPass = 3
  10 +
  11 +
  12 +function passwordStrength(password,username)
  13 +{
  14 + score = 0
  15 +
  16 + if(password.length == 0) return blankPass
  17 +
  18 + //password < 4
  19 + if (password.length < 4 ) { return shortPass }
  20 +
  21 + //password == username
  22 + if (password.toLowerCase()==username.toLowerCase()) badPass
  23 +
  24 + //password length
  25 + score += password.length * 4
  26 + score += ( checkRepetition(1,password).length - password.length ) * 1
  27 + score += ( checkRepetition(2,password).length - password.length ) * 1
  28 + score += ( checkRepetition(3,password).length - password.length ) * 1
  29 + score += ( checkRepetition(4,password).length - password.length ) * 1
  30 +
  31 + //password has 3 numbers
  32 + if (password.match(/(.*[0-9].*[0-9].*[0-9])/)) score += 5
  33 +
  34 + //password has 2 sybols
  35 + if (password.match(/(.*[!,@,#,$,%,^,&,*,?,_,~].*[!,@,#,$,%,^,&,*,?,_,~])/)) score += 5
  36 +
  37 + //password has Upper and Lower chars
  38 + if (password.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/)) score += 10
  39 +
  40 + //password has number and chars
  41 + if (password.match(/([a-zA-Z])/) && password.match(/([0-9])/)) score += 15
  42 + //
  43 + //password has number and symbol
  44 + if (password.match(/([!,@,#,$,%,^,&,*,?,_,~])/) && password.match(/([0-9])/)) score += 15
  45 +
  46 + //password has char and symbol
  47 + if (password.match(/([!,@,#,$,%,^,&,*,?,_,~])/) && password.match(/([a-zA-Z])/)) score += 15
  48 +
  49 + //password is just a nubers or chars
  50 + if (password.match(/^\w+$/) || password.match(/^\d+$/) ) score -= 10
  51 +
  52 + //verifing 0 < score < 100
  53 + if ( score < 0 ) score = 0
  54 + if ( score > 100 ) score = 100
  55 +
  56 + if (score < 34 ) return badPass
  57 + if (score < 68 ) return goodPass
  58 + return strongPass
  59 +}
  60 +
  61 +function checkRepetition(pLen,str)
  62 +{
  63 + res = ""
  64 + for ( i=0; i<str.length ; i++ )
  65 + {
  66 + repeated=true
  67 + for (j=0;j < pLen && (j+i+pLen) < str.length;j++)
  68 + repeated=repeated && (str.charAt(j+i)==str.charAt(j+i+pLen))
  69 + if (j<pLen) repeated=false
  70 + if (repeated)
  71 + {
  72 + i+=pLen-1
  73 + repeated=false
  74 + }
  75 + else
  76 + {
  77 + res+=str.charAt(i)
  78 + }
  79 + }
  80 + return res
  81 +}
  82 +
  83 +jQuery(document).ready(function() {
  84 + jQuery('#user_pw').keyup(function()
  85 + {
  86 + var result = passwordStrength(jQuery('#user_pw').val(),jQuery('#user_login').val())
  87 + if(result == blankPass)
  88 + {
  89 + showRateField('#result-blank')
  90 + } else
  91 + if(result == shortPass)
  92 + {
  93 + showRateField('#result-short')
  94 + } else
  95 + if( result == badPass )
  96 + {
  97 + showRateField('#result-bad')
  98 + } else
  99 + if( result == goodPass )
  100 + {
  101 + showRateField('#result-good')
  102 + } else
  103 + if( result == strongPass )
  104 + {
  105 + showRateField('#result-strong')
  106 + }
  107 +
  108 + })
  109 +})
  110 +
  111 +function showRateField(validation)
  112 +{
  113 + jQuery('#result-blank').addClass('hidden')
  114 + jQuery('#result-short').addClass('hidden')
  115 + jQuery('#result-bad').addClass('hidden')
  116 + jQuery('#result-good').addClass('hidden')
  117 + jQuery('#result-strong').addClass('hidden')
  118 +
  119 + jQuery(validation).removeClass('hidden')
  120 +
  121 +}
0 122 \ No newline at end of file
... ...
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
... ... @@ -1859,20 +1859,70 @@ a.button.disabled, input.disabled {
1859 1859 text-decoration: none;
1860 1860 }
1861 1861 /* ==> blocks/link-list-block.css <<= */
1862   -
1863 1862 #edit-link-list-block {
1864   - width: 820px;
  1863 + width: 620px;
  1864 + position: relative;
  1865 + left: -24px;
1865 1866 }
1866   -
1867   -#edit-link-list-block table {
1868   - width: auto;
1869   - margin-bottom: 10px;
  1867 +.link-list-header {
  1868 + width: 98%;
  1869 + height: 25px;
  1870 + padding: 10px 1px 10px 10px;
  1871 + margin-bottom: 5px;
  1872 + cursor: pointer;
1870 1873 }
1871   -#edit-link-list-block table .cel-address {
1872   - width: 220px;
  1874 +.link-list-header li {
  1875 + list-style-type: none;
  1876 + display: inline;
  1877 + font-weight: bold;
  1878 + font-size: 14px;
  1879 + text-align: center;
1873 1880 }
1874   -#edit-link-list-block table .cel-address input {
1875   - width: 100%;
  1881 +#dropable-link-list {
  1882 + padding-left: 23px;
  1883 + margin-top: -12px;
  1884 +}
  1885 +#dropable-link-list li {
  1886 + list-style-type: none;
  1887 +}
  1888 +.link-list-row {
  1889 + line-height: 25px;
  1890 + margin-bottom: 5px;
  1891 + padding: 10px 1px 10px 10px;
  1892 + cursor: pointer;
  1893 + width: 97%;
  1894 +}
  1895 +.link-list-row:hover {
  1896 + background: #ddd url(/images/drag-and-drop.png) no-repeat;
  1897 + background-position: 98% 15px;
  1898 +}
  1899 +.link-list-row li {
  1900 + list-style-type: none;
  1901 + display: inline;
  1902 + margin-left: 5px;
  1903 +}
  1904 +.link-list-row li div {
  1905 + float: left;
  1906 + margin-top: 4px;
  1907 +}
  1908 +.link-list-row li a {
  1909 + line-height: 27px !important;
  1910 + padding-right: 5px;
  1911 +}
  1912 +.link-list-icon {
  1913 + margin-left: 14px;
  1914 +}
  1915 +.link-list-name {
  1916 + margin-left: 40px;
  1917 +}
  1918 +.link-list-address {
  1919 + margin-left: 90px;
  1920 +}
  1921 +.link-list-target {
  1922 + margin-left: 77px;
  1923 +}
  1924 +.new_link_row li {
  1925 + margin-left: 7px;
1876 1926 }
1877 1927 #content .link-list-block {
1878 1928 padding: 10px 0px 10px 10px;
... ... @@ -5989,8 +6039,14 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img {
5989 6039 text-align: right;
5990 6040 }
5991 6041  
  6042 +#url-check .suggested_usernames,
  6043 +#url-check .suggested_usernames a {
  6044 + color: #005000;
  6045 +}
  6046 +
5992 6047 #email-check,
5993 6048 #fake-check,
  6049 +#password-rate,
5994 6050 #password-check {
5995 6051 margin: -2px 16px -5px 13px;
5996 6052 text-align: right;
... ... @@ -5999,10 +6055,20 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img {
5999 6055  
6000 6056 #email-check p,
6001 6057 #fake-check p,
  6058 +#password-rate p,
6002 6059 #password-check p {
6003 6060 margin: 0;
6004 6061 }
6005 6062  
  6063 +#password-rate {
  6064 + font-weight:bold;
  6065 +}
  6066 +
  6067 +.hidden {
  6068 + visibility: hidden;
  6069 + display: none;
  6070 +}
  6071 +
6006 6072 .available {
6007 6073 color: #88BD00;
6008 6074 }
... ... @@ -6016,6 +6082,7 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img {
6016 6082 }
6017 6083  
6018 6084 #email-check p,
  6085 +#password-rate p,
6019 6086 #password-check p,
6020 6087 #url-check p {
6021 6088 margin: 0;
... ... @@ -6607,3 +6674,19 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img {
6607 6674 .diff li.diff-block-info {
6608 6675 background: none repeat scroll 0 0 gray;
6609 6676 }
  6677 +
  6678 +#signup-form #result-short {
  6679 + color: red;
  6680 +}
  6681 +
  6682 +#signup-form #result-bad {
  6683 + color: #825A2C;
  6684 +}
  6685 +
  6686 +#signup-form #result-good {
  6687 + color: #32CD32;
  6688 +}
  6689 +
  6690 +#signup-form #result-strong {
  6691 + color: green;
  6692 +}
... ...
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  
... ... @@ -656,21 +655,28 @@ class AccountControllerTest &lt; ActionController::TestCase
656 655 assert_redirected_to :controller => 'home', :action => 'index'
657 656 end
658 657  
659   - should 'check_url is available on environment' do
  658 + should 'check_valid_name is available on environment' do
660 659 env = fast_create(Environment, :name => 'Environment test')
661 660 @controller.expects(:environment).returns(env).at_least_once
662 661 profile = create_user('mylogin').person
663   - get :check_url, :identifier => 'mylogin'
  662 + get :check_valid_name, :identifier => 'mylogin'
664 663 assert_equal 'validated', assigns(:status_class)
665 664 end
666 665  
667 666 should 'check if url is not available on environment' do
668 667 @controller.expects(:environment).returns(Environment.default).at_least_once
669 668 profile = create_user('mylogin').person
670   - get :check_url, :identifier => 'mylogin'
  669 + get :check_valid_name, :identifier => 'mylogin'
671 670 assert_equal 'invalid', assigns(:status_class)
672 671 end
673 672  
  673 + should 'suggest a list with three possible usernames' do
  674 + profile = create_user('mylogin').person
  675 + get :check_valid_name, :identifier => 'mylogin'
  676 +
  677 + assert_equal 3, assigns(:suggested_usernames).uniq.size
  678 + end
  679 +
674 680 should 'check if e-mail is available on environment' do
675 681 env = fast_create(Environment, :name => 'Environment test')
676 682 @controller.expects(:environment).returns(env).at_least_once
... ... @@ -699,6 +705,7 @@ class AccountControllerTest &lt; ActionController::TestCase
699 705 {:test => 5}
700 706 end
701 707 end
  708 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
702 709  
703 710 e = User.find_by_login('ze').environment
704 711 e.enable_plugin(Plugin1.name)
... ... @@ -789,6 +796,7 @@ class AccountControllerTest &lt; ActionController::TestCase
789 796 lambda {"<strong>Plugin2 text</strong>"}
790 797 end
791 798 end
  799 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
792 800  
793 801 Environment.default.enable_plugin(Plugin1.name)
794 802 Environment.default.enable_plugin(Plugin2.name)
... ... @@ -805,6 +813,7 @@ class AccountControllerTest &lt; ActionController::TestCase
805 813 User.new(:login => 'testuser')
806 814 end
807 815 end
  816 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name])
808 817 Environment.default.enable_plugin(Plugin1.name)
809 818  
810 819 post :login, :user => {:login => "testuser"}
... ... @@ -819,6 +828,7 @@ class AccountControllerTest &lt; ActionController::TestCase
819 828 nil
820 829 end
821 830 end
  831 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name])
822 832 Environment.default.enable_plugin(Plugin1.name)
823 833 post :login, :user => {:login => 'johndoe', :password => 'test'}
824 834 assert session[:user]
... ... @@ -832,6 +842,7 @@ class AccountControllerTest &lt; ActionController::TestCase
832 842 false
833 843 end
834 844 end
  845 + Noosfero::Plugin.stubs(:all).returns([TestRegistrationPlugin.name])
835 846 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([TestRegistrationPlugin.new])
836 847  
837 848 post :signup, :user => { :login => 'testuser', :password => '123456', :password_confirmation => '123456', :email => 'testuser@example.com' }
... ... @@ -850,6 +861,7 @@ class AccountControllerTest &lt; ActionController::TestCase
850 861 true
851 862 end
852 863 end
  864 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
853 865 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([Plugin1.new, Plugin2.new])
854 866  
855 867 get :login
... ... @@ -863,6 +875,7 @@ class AccountControllerTest &lt; ActionController::TestCase
863 875 false
864 876 end
865 877 end
  878 + Noosfero::Plugin.stubs(:all).returns([TestRegistrationPlugin.name])
866 879 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([TestRegistrationPlugin.new])
867 880  
868 881 #Redirect on get action
... ... @@ -886,6 +899,7 @@ class AccountControllerTest &lt; ActionController::TestCase
886 899 true
887 900 end
888 901 end
  902 + Noosfero::Plugin.stubs(:all).returns([Plugin1.new, Plugin2.new])
889 903 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([Plugin1.new, Plugin2.new])
890 904  
891 905 get :login
... ... @@ -904,6 +918,7 @@ class AccountControllerTest &lt; ActionController::TestCase
904 918 lambda {"<strong>Plugin2 text</strong>"}
905 919 end
906 920 end
  921 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
907 922  
908 923 Environment.default.enable_plugin(Plugin1.name)
909 924 Environment.default.enable_plugin(Plugin2.name)
... ... @@ -927,6 +942,30 @@ class AccountControllerTest &lt; ActionController::TestCase
927 942 assert @response.body.blank?
928 943 end
929 944  
  945 + should "Search for state" do
  946 + create_state_and_city
  947 +
  948 + xhr :get, :search_state, :state_name=>"Rio Grande"
  949 +
  950 + json_response = ActiveSupport::JSON.decode(@response.body)
  951 + label = json_response[0]['label']
  952 +
  953 + assert_equal label, "Rio Grande do Sul"
  954 + end
  955 +
  956 + should "Search for city" do
  957 + create_state_and_city
  958 +
  959 + xhr :get, :search_cities, :state_name=>"Rio Grande do Sul", :city_name=>"Lavras"
  960 +
  961 + json_response = ActiveSupport::JSON.decode(@response.body)
  962 + label = json_response[0]['label']
  963 + category = json_response[0]['category']
  964 +
  965 + assert_equal category, "Rio Grande do Sul"
  966 + assert_equal label, "Lavras do Sul"
  967 + end
  968 +
930 969 protected
931 970 def new_user(options = {}, extra_options ={})
932 971 data = {:profile_data => person_data}
... ... @@ -955,4 +994,18 @@ class AccountControllerTest &lt; ActionController::TestCase
955 994 environment.min_signup_delay = 0
956 995 environment.save!
957 996 end
  997 +
  998 + def create_state_and_city
  999 + city = 'Lavras do Sul'
  1000 + state = 'Rio Grande do Sul'
  1001 +
  1002 + parent_region = fast_create(NationalRegion, :name => state,
  1003 + :national_region_code => '43',
  1004 + :national_region_type_id => NationalRegionType::STATE)
  1005 +
  1006 + fast_create(NationalRegion, :name => city,
  1007 + :national_region_code => '431150',
  1008 + :national_region_type_id => NationalRegionType::CITY,
  1009 + :parent_national_region_code => parent_region.national_region_code)
  1010 + end
958 1011 end
... ...
test/functional/application_controller_test.rb
... ... @@ -374,6 +374,8 @@ class ApplicationControllerTest &lt; ActionController::TestCase
374 374 end
375 375 plugin2_path = '/plugin2/style.css'
376 376  
  377 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
  378 +
377 379 environment = Environment.default
378 380 environment.enable_plugin(Plugin1.name)
379 381 environment.enable_plugin(Plugin2.name)
... ... @@ -405,6 +407,8 @@ class ApplicationControllerTest &lt; ActionController::TestCase
405 407 plugin2_path2 = '/plugin2/'+js2
406 408 plugin2_path3 = '/plugin2/'+js3
407 409  
  410 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
  411 +
408 412 environment = Environment.default
409 413 environment.enable_plugin(Plugin1.name)
410 414 environment.enable_plugin(Plugin2.name)
... ... @@ -428,6 +432,8 @@ class ApplicationControllerTest &lt; ActionController::TestCase
428 432 end
429 433 end
430 434  
  435 + Noosfero::Plugin.stubs(:all).returns([TestBodyBeginning1Plugin.name, TestBodyBeginning2Plugin.name])
  436 +
431 437 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([TestBodyBeginning1Plugin.new, TestBodyBeginning2Plugin.new])
432 438  
433 439 get :index
... ... @@ -449,6 +455,8 @@ class ApplicationControllerTest &lt; ActionController::TestCase
449 455 end
450 456 end
451 457  
  458 + Noosfero::Plugin.stubs(:all).returns([TestHeadEnding1Plugin.name, TestHeadEnding2Plugin.name])
  459 +
452 460 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([TestHeadEnding1Plugin.new, TestHeadEnding2Plugin.new])
453 461  
454 462 get :index
... ... @@ -513,6 +521,7 @@ class ApplicationControllerTest &lt; ActionController::TestCase
513 521 :block => lambda {} }
514 522 end
515 523 end
  524 + Noosfero::Plugin.stubs(:all).returns([FilterPlugin.name])
516 525  
517 526 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([FilterPlugin.new])
518 527  
... ... @@ -531,6 +540,7 @@ class ApplicationControllerTest &lt; ActionController::TestCase
531 540 :block => lambda {'plugin block called'} }
532 541 end
533 542 end
  543 + Noosfero::Plugin.stubs(:all).returns([OtherFilterPlugin.name])
534 544  
535 545 environment1 = fast_create(Environment, :name => 'test environment')
536 546 environment1.enable_plugin(OtherFilterPlugin.name)
... ...
test/functional/catalog_controller_test.rb
... ... @@ -91,6 +91,7 @@ class CatalogControllerTest &lt; ActionController::TestCase
91 91 lambda {"<span id='plugin2'>This is Plugin2 speaking!</span>"}
92 92 end
93 93 end
  94 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
94 95  
95 96 product = fast_create(Product, :profile_id => @enterprise.id)
96 97 environment = Environment.default
... ...
test/functional/content_viewer_controller_test.rb
... ... @@ -1197,6 +1197,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
1197 1197 class Plugin2 < Noosfero::Plugin
1198 1198 def content_remove_edit(content); false; end
1199 1199 end
  1200 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
1200 1201  
1201 1202 environment.enable_plugin(Plugin1.name)
1202 1203 environment.enable_plugin(Plugin2.name)
... ... @@ -1213,6 +1214,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
1213 1214 class Plugin2 < Noosfero::Plugin
1214 1215 def content_expire_edit(content); nil; end
1215 1216 end
  1217 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
1216 1218  
1217 1219 environment.enable_plugin(Plugin1.name)
1218 1220 environment.enable_plugin(Plugin2.name)
... ... @@ -1258,6 +1260,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
1258 1260 }
1259 1261 end
1260 1262 end
  1263 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
1261 1264  
1262 1265 Environment.default.enable_plugin(Plugin1.name)
1263 1266 Environment.default.enable_plugin(Plugin2.name)
... ... @@ -1282,6 +1285,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
1282 1285 scope.where(:referrer => 'kernel.org')
1283 1286 end
1284 1287 end
  1288 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
1285 1289  
1286 1290 Environment.default.enable_plugin(Plugin1)
1287 1291 Environment.default.enable_plugin(Plugin2)
... ... @@ -1339,6 +1343,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
1339 1343 }
1340 1344 end
1341 1345 end
  1346 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
1342 1347  
1343 1348 Environment.default.enable_plugin(Plugin1.name)
1344 1349 Environment.default.enable_plugin(Plugin2.name)
... ...
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/enterprise_registration_controller_test.rb
... ... @@ -193,6 +193,7 @@ class EnterpriseRegistrationControllerTest &lt; ActionController::TestCase
193 193 {'plugin2' => 'Plugin 2'}
194 194 end
195 195 end
  196 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
196 197  
197 198 environment = Environment.default
198 199 environment.enable_plugin(Plugin1.name)
... ...
test/functional/environment_design_controller_test.rb
... ... @@ -370,4 +370,47 @@ class EnvironmentDesignControllerTest &lt; ActionController::TestCase
370 370 assert @controller.instance_variable_get('@side_block_types').include?(CustomBlock8)
371 371 end
372 372  
  373 + should 'clone a block' do
  374 + login_as(create_admin_user(Environment.default))
  375 + block = TagsBlock.create!
  376 + assert_difference TagsBlock, :count, 1 do
  377 + post :clone_block, :id => block.id
  378 + assert_response :redirect
  379 + end
  380 + end
  381 +
  382 + should 'return a list of paths from portal related to the words used in the query search' do
  383 + env = Environment.default
  384 + login_as(create_admin_user(env))
  385 + community = fast_create(Community, :environment_id => env)
  386 + env.portal_community = community
  387 + env.enable('use_portal_community')
  388 + env.save
  389 + @controller.stubs(:boxes_holder).returns(env)
  390 + article1 = fast_create(Article, :profile_id => community.id, :name => "Some thing")
  391 + article2 = fast_create(Article, :profile_id => community.id, :name => "Some article")
  392 + article3 = fast_create(Article, :profile_id => community.id, :name => "Not an article")
  393 +
  394 + xhr :get, :search_autocomplete, :query => 'Some'
  395 +
  396 + json_response = ActiveSupport::JSON.decode(@response.body)
  397 +
  398 + assert_response :success
  399 + assert_equal json_response.include?("/{portal}/"+article1.path), true
  400 + assert_equal json_response.include?("/{portal}/"+article2.path), true
  401 + assert_equal json_response.include?("/{portal}/"+article3.path), false
  402 + end
  403 +
  404 + should 'return empty if portal not configured' do
  405 + env = Environment.default
  406 + login_as(create_admin_user(env))
  407 +
  408 + xhr :get, :search_autocomplete, :query => 'Some'
  409 +
  410 + json_response = ActiveSupport::JSON.decode(@response.body)
  411 +
  412 + assert_response :success
  413 + assert_equal json_response, []
  414 + end
  415 +
373 416 end
... ...
test/functional/friends_controller_test.rb
... ... @@ -68,6 +68,7 @@ class FriendsControllerTest &lt; ActionController::TestCase
68 68 false
69 69 end
70 70 end
  71 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
71 72  
72 73 e = profile.environment
73 74 e.enable_plugin(Plugin1.name)
... ...
test/functional/home_controller_test.rb
... ... @@ -107,6 +107,7 @@ class HomeControllerTest &lt; ActionController::TestCase
107 107 lambda {"<a href='plugin2'>Plugin2 link</a>"}
108 108 end
109 109 end
  110 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
110 111  
111 112 Environment.default.enable_plugin(Plugin1)
112 113 Environment.default.enable_plugin(Plugin2)
... ... @@ -129,6 +130,7 @@ class HomeControllerTest &lt; ActionController::TestCase
129 130 true
130 131 end
131 132 end
  133 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
132 134 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([Plugin1.new, Plugin2.new])
133 135  
134 136 get :index
... ...
test/functional/memberships_controller_test.rb
... ... @@ -234,6 +234,7 @@ class MembershipsControllerTest &lt; ActionController::TestCase
234 234 {'plugin2' => 'Plugin 2'}
235 235 end
236 236 end
  237 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
237 238  
238 239 environment = Environment.default
239 240 environment.enable_plugin(Plugin1.name)
... ...
test/functional/plugins_controller_test.rb
... ... @@ -47,7 +47,7 @@ class PluginsControllerTest &lt; ActionController::TestCase
47 47 end
48 48 end
49 49  
50   - Noosfero::Plugin.stubs(:all).returns([Plugin1.to_s,Plugin2.to_s])
  50 + Noosfero::Plugin.stubs(:all).returns([Plugin1.to_s, Plugin2.to_s])
51 51  
52 52 get :index
53 53  
... ...
test/functional/profile_controller_test.rb
... ... @@ -1255,6 +1255,7 @@ class ProfileControllerTest &lt; ActionController::TestCase
1255 1255 {:title => 'Plugin2 tab', :id => 'plugin2_tab', :content => lambda { 'Content from plugin2.' }}
1256 1256 end
1257 1257 end
  1258 + Noosfero::Plugin.stubs(:all).returns([Plugin1.to_s, Plugin2.to_s])
1258 1259  
1259 1260 e = profile.environment
1260 1261 e.enable_plugin(Plugin1.name)
... ...
test/functional/profile_design_controller_test.rb
... ... @@ -173,7 +173,8 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase
173 173 should 'have options to display blocks' do
174 174 get :edit, :profile => 'designtestuser', :id => @b1.id
175 175 %w[always home_page_only except_home_page never].each do |option|
176   - assert_tag :input, :attributes => { :type => 'radio', :value => option}
  176 + assert_tag :select, :attributes => {:name => 'block[display]'},
  177 + :descendant => {:tag => 'option', :attributes => {:value => option}}
177 178 end
178 179 end
179 180  
... ... @@ -302,24 +303,42 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase
302 303  
303 304 should 'not edit main block with never option' do
304 305 get :edit, :profile => 'designtestuser', :id => @b4.id
305   - assert_no_tag :input, :attributes => { :type => 'radio', :value => 'never'}
  306 + assert_no_tag :select, :attributes => {:name => 'block[display]'},
  307 + :descendant => {:tag => 'option', :attributes => {:value => 'never'}}
306 308 end
307 309  
308 310 should 'not edit main block with home_page_only option' do
309 311 get :edit, :profile => 'designtestuser', :id => @b4.id
310   - assert_no_tag :input, :attributes => { :type => 'radio', :value => 'home_page_only'}
  312 + assert_no_tag :select, :attributes => {:name => 'block[display]'},
  313 + :descendant => {:tag => 'option', :attributes => {:value => 'home_page_only'}}
311 314 end
312 315  
313 316 should 'edit main block with always option' do
314 317 get :edit, :profile => 'designtestuser', :id => @b4.id
315   - assert_tag :input, :attributes => { :type => 'radio', :value => 'always'}
  318 + assert_tag :select, :attributes => {:name => 'block[display]'},
  319 + :descendant => {:tag => 'option', :attributes => {:value => 'always'}}
316 320 end
317 321  
318 322 should 'edit main block with except_home_page option' do
319 323 get :edit, :profile => 'designtestuser', :id => @b4.id
320   - assert_tag :input, :attributes => { :type => 'radio', :value => 'except_home_page'}
  324 + assert_tag :select, :attributes => {:name=> 'block[display]'},
  325 + :descendant => {:tag => 'option', :attributes => {:value => 'except_home_page'}}
321 326 end
322 327  
  328 + should 'return a list of paths related to the words used in the query search' do
  329 + article1 = fast_create(Article, :profile_id => @profile.id, :name => "Some thing")
  330 + article2 = fast_create(Article, :profile_id => @profile.id, :name => "Some article")
  331 + article3 = fast_create(Article, :profile_id => @profile.id, :name => "Not an article")
  332 +
  333 + xhr :get, :search_autocomplete, :profile => 'designtestuser' , :query => 'Some'
  334 +
  335 + json_response = ActiveSupport::JSON.decode(@response.body)
  336 +
  337 + assert_response :success
  338 + assert_equal json_response.include?("/{profile}/"+article1.path), true
  339 + assert_equal json_response.include?("/{profile}/"+article2.path), true
  340 + assert_equal json_response.include?("/{profile}/"+article3.path), false
  341 + end
323 342  
324 343 ######################################################
325 344 # END - tests for BoxOrganizerController features
... ... @@ -739,7 +758,7 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase
739 758 should 'clone a block' do
740 759 block = ProfileImageBlock.create!(:box => profile.boxes.first)
741 760 assert_difference ProfileImageBlock, :count, 1 do
742   - post :clone, :id => block.id, :profile => profile.identifier
  761 + post :clone_block, :id => block.id, :profile => profile.identifier
743 762 assert_response :redirect
744 763 end
745 764 end
... ...
test/functional/profile_editor_controller_test.rb
... ... @@ -868,6 +868,7 @@ class ProfileEditorControllerTest &lt; ActionController::TestCase
868 868 {:title => "Plugin2 button", :icon => 'plugin2_icon', :url => 'plugin2_url'}
869 869 end
870 870 end
  871 + Noosfero::Plugin.stubs(:all).returns([TestControlPanelButtons1.to_s, TestControlPanelButtons2.to_s])
871 872  
872 873 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([TestControlPanelButtons1.new, TestControlPanelButtons2.new])
873 874  
... ... @@ -883,6 +884,7 @@ class ProfileEditorControllerTest &lt; ActionController::TestCase
883 884 "<input id='field_added_by_plugin' value='value_of_field_added_by_plugin'/>"
884 885 end
885 886 end
  887 + Noosfero::Plugin.stubs(:all).returns([TestProfileEditPlugin.to_s])
886 888  
887 889 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([TestProfileEditPlugin.new])
888 890  
... ... @@ -911,6 +913,7 @@ class ProfileEditorControllerTest &lt; ActionController::TestCase
911 913 lambda {"<strong>Plugin2 text</strong>"}
912 914 end
913 915 end
  916 + Noosfero::Plugin.stubs(:all).returns([Plugin1.to_s, Plugin2.to_s])
914 917  
915 918 Environment.default.enable_plugin(Plugin1)
916 919 Environment.default.enable_plugin(Plugin2)
... ... @@ -932,6 +935,7 @@ class ProfileEditorControllerTest &lt; ActionController::TestCase
932 935 lambda {"<strong>Plugin2 text</strong>"}
933 936 end
934 937 end
  938 + Noosfero::Plugin.stubs(:all).returns([Plugin1.to_s, Plugin2.to_s])
935 939  
936 940 Environment.default.enable_plugin(Plugin1)
937 941 Environment.default.enable_plugin(Plugin2)
... ...
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
... ... @@ -163,6 +163,7 @@ class SearchControllerTest &lt; ActionController::TestCase
163 163 lambda {"<span id='plugin2'>This is Plugin2 speaking!</span>"}
164 164 end
165 165 end
  166 + Noosfero::Plugin.stubs(:all).returns([Plugin1.to_s, Plugin2.to_s])
166 167  
167 168 enterprise = fast_create(Enterprise)
168 169 prod_cat = fast_create(ProductCategory)
... ... @@ -189,6 +190,7 @@ class SearchControllerTest &lt; ActionController::TestCase
189 190 return { :name => _('Property2'), :content => lambda { link_to(product.name, '/plugin2') } }
190 191 end
191 192 end
  193 + Noosfero::Plugin.stubs(:all).returns([Plugin1.to_s, Plugin2.to_s])
192 194 enterprise = fast_create(Enterprise)
193 195 prod_cat = fast_create(ProductCategory)
194 196 product = fast_create(Product, {:profile_id => enterprise.id, :name => "produto1", :product_category_id => prod_cat.id}, :search => true)
... ... @@ -257,10 +259,10 @@ class SearchControllerTest &lt; ActionController::TestCase
257 259  
258 260 should 'render specific action when only one asset is enabled' do
259 261 environment = Environment.default
260   - # article is not disabled
  262 + # article is not disabled
261 263 [:enterprises, :people, :communities, :products, :events].select do |key, name|
262   - environment.enable('disable_asset_' + key.to_s)
263   - end
  264 + environment.enable('disable_asset_' + key.to_s)
  265 + end
264 266 environment.save!
265 267 @controller.stubs(:environment).returns(environment)
266 268  
... ... @@ -272,25 +274,25 @@ class SearchControllerTest &lt; ActionController::TestCase
272 274 assert !assigns(:searches).has_key?(:communities)
273 275 assert !assigns(:searches).has_key?(:products)
274 276 assert !assigns(:searches).has_key?(:events)
275   - end
  277 + end
276 278  
277 279 should 'search all enabled assets in general search' do
278 280 ent1 = create_profile_with_optional_category(Enterprise, 'test enterprise')
279 281 prod_cat = ProductCategory.create!(:name => 'pctest', :environment => Environment.default)
280 282 prod = ent1.products.create!(:name => 'test product', :product_category => prod_cat)
281   - art = Article.create!(:name => 'test article', :profile_id => fast_create(Person).id)
282   - per = Person.create!(:name => 'test person', :identifier => 'test-person', :user_id => fast_create(User).id)
283   - com = Community.create!(:name => 'test community')
284   - 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)
285 287  
286 288 get :index, :query => 'test'
287 289  
288 290 [:articles, :enterprises, :people, :communities, :products, :events].select do |key, name|
289   - !assigns(:environment).enabled?('disable_asset_' + key.to_s)
290   - end.each do |asset|
291   - assert !assigns(:searches)[asset][:results].empty?
292   - end
293   - 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
294 296  
295 297 should 'display category image while in directory' do
296 298 parent = Category.create!(:name => 'category1', :environment => Environment.default)
... ... @@ -316,8 +318,8 @@ class SearchControllerTest &lt; ActionController::TestCase
316 318 person = create_user('someone').person
317 319 ten_days_ago = Date.today - 10.day
318 320  
319   - ev1 = create_event(person, :name => 'event 1', :category_ids => [@category.id], :start_date => ten_days_ago)
320   - 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)
321 323  
322 324 get :events, :day => ten_days_ago.day, :month => ten_days_ago.month, :year => ten_days_ago.year
323 325 assert_equal [ev1], assigns(:events)
... ... @@ -327,7 +329,7 @@ class SearchControllerTest &lt; ActionController::TestCase
327 329 person = create_user('someone').person
328 330 ten_days_ago = Date.today - 10.day
329 331  
330   - 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)
331 333 ev2 = create_event(person, :name => 'event 2', :start_date => ten_days_ago)
332 334  
333 335 get :events, :day => ten_days_ago.day, :month => ten_days_ago.month, :year => ten_days_ago.year, :category_path => @category.path.split('/')
... ... @@ -337,8 +339,8 @@ class SearchControllerTest &lt; ActionController::TestCase
337 339  
338 340 should 'return events of today when no date specified' do
339 341 person = create_user('someone').person
340   - ev1 = create_event(person, :name => 'event 1', :category_ids => [@category.id], :start_date => Date.today)
341   - 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)
342 344  
343 345 get :events
344 346  
... ... @@ -349,9 +351,9 @@ class SearchControllerTest &lt; ActionController::TestCase
349 351 person = create_user('someone').person
350 352  
351 353 ev1 = create_event(person, :name => 'event 1', :category_ids => [@category.id],
352   - :start_date => Date.today + 2.month)
  354 + :start_date => Date.today + 2.month)
353 355 ev2 = create_event(person, :name => 'event 2', :category_ids => [@category.id],
354   - :start_date => Date.today + 2.day)
  356 + :start_date => Date.today + 2.day)
355 357  
356 358 get :events
357 359  
... ... @@ -373,7 +375,7 @@ class SearchControllerTest &lt; ActionController::TestCase
373 375 should 'see the events paginated' do
374 376 person = create_user('testuser').person
375 377 30.times do |i|
376   - create_event(person, :name => "Event #{i}", :start_date => Date.today)
  378 + create_event(person, :name => "Event #{i}", :start_date => Date.today)
377 379 end
378 380 get :events
379 381 assert_equal 20, assigns(:events).count
... ... @@ -432,8 +434,8 @@ class SearchControllerTest &lt; ActionController::TestCase
432 434 end
433 435  
434 436 should 'show link to article asset in the see all foot link of the articles block in the category page' do
435   - (1..SearchController::MULTIPLE_SEARCH_LIMIT+1).each do |i|
436   - 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")
437 439 ArticleCategorization.add_category_to_article(@category, a)
438 440 end
439 441  
... ... @@ -579,55 +581,55 @@ class SearchControllerTest &lt; ActionController::TestCase
579 581 assert_not_includes assigns(:searches)[:communities][:results], p1
580 582 end
581 583  
582   - should 'keep old urls working' do
583   - get :assets, :asset => 'articles'
  584 + should 'keep old urls working' do
  585 + get :assets, :asset => 'articles'
584 586 assert_redirected_to :controller => :search, :action => :articles
585   - get :assets, :asset => 'people'
  587 + get :assets, :asset => 'people'
586 588 assert_redirected_to :controller => :search, :action => :people
587   - get :assets, :asset => 'communities'
  589 + get :assets, :asset => 'communities'
588 590 assert_redirected_to :controller => :search, :action => :communities
589   - get :assets, :asset => 'products'
  591 + get :assets, :asset => 'products'
590 592 assert_redirected_to :controller => :search, :action => :products
591   - get :assets, :asset => 'enterprises'
  593 + get :assets, :asset => 'enterprises'
592 594 assert_redirected_to :controller => :search, :action => :enterprises
593   - get :assets, :asset => 'events'
  595 + get :assets, :asset => 'events'
594 596 assert_redirected_to :controller => :search, :action => :events
595   - end
  597 + end
596 598  
597   - should 'show tag cloud' do
598   - @controller.stubs(:is_cache_expired?).returns(true)
  599 + should 'show tag cloud' do
  600 + @controller.stubs(:is_cache_expired?).returns(true)
599 601 a = Article.create!(:name => 'my article', :profile_id => fast_create(Person).id)
600 602 a.tag_list = ['one', 'two']
601   - a.save_tags
  603 + a.save_tags
602 604  
603   - get :tags
  605 + get :tags
604 606  
605   - assert assigns(:tags)["two"] = 1
606   - assert assigns(:tags)["one"] = 1
607   - end
  607 + assert assigns(:tags)["two"] = 1
  608 + assert assigns(:tags)["one"] = 1
  609 + end
608 610  
609 611 should 'show tagged content' do
610   - @controller.stubs(:is_cache_expired?).returns(true)
  612 + @controller.stubs(:is_cache_expired?).returns(true)
611 613 a = Article.create!(:name => 'my article', :profile_id => fast_create(Person).id)
612 614 a2 = Article.create!(:name => 'my article 2', :profile_id => fast_create(Person).id)
613 615 a.tag_list = ['one', 'two']
614 616 a2.tag_list = ['two', 'three']
615   - a.save_tags
  617 + a.save_tags
616 618 a2.save_tags
617 619  
618   - get :tag, :tag => 'two'
  620 + get :tag, :tag => 'two'
619 621  
620 622 assert_equivalent [a, a2], assigns(:searches)[:tag][:results]
621 623  
622   - get :tag, :tag => 'one'
  624 + get :tag, :tag => 'one'
623 625  
624 626 assert_equivalent [a], assigns(:searches)[:tag][:results]
625 627 end
626 628  
627 629 should 'not show assets from other environments' do
628 630 other_env = Environment.create!(:name => 'Another environment')
629   - p1 = Person.create!(:name => 'Hildebrando', :identifier => 'hild', :user_id => fast_create(User).id, :environment_id => other_env.id)
630   - 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)
631 633 art1 = Article.create!(:name => 'my article', :profile_id => p1.id)
632 634 art2 = Article.create!(:name => 'my article', :profile_id => p2.id)
633 635  
... ... @@ -638,9 +640,9 @@ class SearchControllerTest &lt; ActionController::TestCase
638 640  
639 641 should 'order articles by more recent' do
640 642 Article.destroy_all
641   - art1 = Article.create!(:name => 'review C', :profile_id => fast_create(Person).id, :created_at => Time.now-1.days)
642   - art2 = Article.create!(:name => 'review A', :profile_id => fast_create(Person).id, :created_at => Time.now)
643   - 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)
644 646  
645 647 get :articles, :filter => :more_recent
646 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/application_helper_test.rb
... ... @@ -676,6 +676,7 @@ class ApplicationHelperTest &lt; ActiveSupport::TestCase
676 676 should 'parse macros' do
677 677 class Plugin1 < Noosfero::Plugin
678 678 end
  679 + Noosfero::Plugin.stubs(:all).returns(['ApplicationHelperTest::Plugin1'])
679 680  
680 681 class Plugin1::Macro1 < Noosfero::Plugin::Macro
681 682 def parse(params, inner_html, source)
... ...
test/unit/block_test.rb
... ... @@ -223,6 +223,61 @@ 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 +
  236 + should 'default value for display_user is all' do
  237 + block = Block.new
  238 + assert_equal 'all', block.display_user
  239 + end
  240 +
  241 + should 'display block to not logged users for display_user = all' do
  242 + block = Block.new
  243 + assert block.display_to_user?(nil)
  244 + end
  245 +
  246 + should 'display block to logged users for display_user = all' do
  247 + block = Block.new
  248 + assert block.display_to_user?(User.new)
  249 + end
  250 +
  251 + should 'display block to logged users for display_user = logged' do
  252 + block = Block.new
  253 + block.display_user = 'logged'
  254 + assert block.display_to_user?(User.new)
  255 + end
  256 +
  257 + should 'do not display block to logged users for display_user = not_logged' do
  258 + block = Block.new
  259 + block.display_user = 'not_logged'
  260 + assert !block.display_to_user?(User.new)
  261 + end
  262 +
  263 + should 'do not display block to not logged users for display_user = logged' do
  264 + block = Block.new
  265 + block.display_user = 'logged'
  266 + assert !block.display_to_user?(nil)
  267 + end
  268 +
  269 + should 'display block to not logged users for display_user = not_logged' do
  270 + block = Block.new
  271 + block.display_user = 'not_logged'
  272 + assert block.display_to_user?(nil)
  273 + end
  274 +
  275 + should 'not be visible if display_to_user? is false' do
  276 + block = Block.new
  277 + block.expects(:display_to_user?).once.returns(false)
  278 + assert !block.visible?({})
  279 + end
  280 +
226 281 should 'accept user as parameter on cache_key without change its value' do
227 282 person = fast_create(Person)
228 283 block = Block.new
... ...
test/unit/boxes_helper_test.rb
... ... @@ -54,6 +54,7 @@ class BoxesHelperTest &lt; ActiveSupport::TestCase
54 54 expects(:display_block).with(b, '')
55 55 stubs(:request).returns(request)
56 56 stubs(:block_target).returns('')
  57 + stubs(:user).returns(nil)
57 58 expects(:locale).returns('en')
58 59 with_box_decorator self do
59 60 display_box_content(box, '')
... ... @@ -73,6 +74,7 @@ class BoxesHelperTest &lt; ActiveSupport::TestCase
73 74 box.save!
74 75 expects(:display_block).with(b, '').never
75 76 stubs(:request).returns(request)
  77 + stubs(:user).returns(nil)
76 78 stubs(:block_target).returns('')
77 79 expects(:locale).returns('en')
78 80 display_box_content(box, '')
... ... @@ -111,8 +113,9 @@ class BoxesHelperTest &lt; ActiveSupport::TestCase
111 113 request.expects(:path).returns('/')
112 114 request.expects(:params).returns({})
113 115 stubs(:request).returns(request)
  116 + stubs(:user).returns(nil)
114 117 expects(:locale).returns('en')
115   - box_decorator.expects(:select_blocks).with([], {:article => nil, :request_path => '/', :locale => 'en', :params => {}}).returns([])
  118 + box_decorator.expects(:select_blocks).with([], {:article => nil, :request_path => '/', :locale => 'en', :params => {}, :user => nil}).returns([])
116 119  
117 120 display_box_content(box, '')
118 121 end
... ...
test/unit/comment_test.rb
... ... @@ -468,8 +468,8 @@ class CommentTest &lt; ActiveSupport::TestCase
468 468 end
469 469 end
470 470  
471   -
472 471 should 'delegate spam detection to plugins' do
  472 + Noosfero::Plugin.stubs(:all).returns(['CommentTest::EverythingIsSpam'])
473 473 Environment.default.enable_plugin(EverythingIsSpam)
474 474  
475 475 c1 = create_comment
... ... @@ -495,6 +495,7 @@ class CommentTest &lt; ActiveSupport::TestCase
495 495 end
496 496  
497 497 should 'notify plugins of comments being marked as spam' do
  498 + Noosfero::Plugin.stubs(:all).returns(['CommentTest::SpamNotification'])
498 499 Environment.default.enable_plugin(SpamNotification)
499 500  
500 501 c = create_comment
... ... @@ -506,6 +507,7 @@ class CommentTest &lt; ActiveSupport::TestCase
506 507 end
507 508  
508 509 should 'notify plugins of comments being marked as ham' do
  510 + Noosfero::Plugin.stubs(:all).returns(['CommentTest::SpamNotification'])
509 511 Environment.default.enable_plugin(SpamNotification)
510 512  
511 513 c = create_comment
... ...
test/unit/forgot_password_helper_test.rb
... ... @@ -22,6 +22,7 @@ class ForgotPasswordHelperTest &lt; ActionView::TestCase
22 22 {:field => 'f3', :name => 'F3', :model => 'person'}]
23 23 end
24 24 end
  25 + Noosfero::Plugin.stubs(:all).returns(['ForgotPasswordHelperTest::Plugin1', 'ForgotPasswordHelperTest::Plugin2'])
25 26  
26 27 environment.enable_plugin(Plugin1)
27 28 environment.enable_plugin(Plugin2)
... ... @@ -43,6 +44,7 @@ class ForgotPasswordHelperTest &lt; ActionView::TestCase
43 44 {:field => 'f3', :name => 'F3', :model => 'person'}]
44 45 end
45 46 end
  47 + Noosfero::Plugin.stubs(:all).returns(['ForgotPasswordHelperTest::Plugin1', 'ForgotPasswordHelperTest::Plugin2'])
46 48  
47 49 environment.enable_plugin(Plugin1)
48 50 environment.enable_plugin(Plugin2)
... ... @@ -64,6 +66,7 @@ class ForgotPasswordHelperTest &lt; ActionView::TestCase
64 66 {:field => 'f3', :name => 'F3', :model => 'user'}]
65 67 end
66 68 end
  69 + Noosfero::Plugin.stubs(:all).returns(['ForgotPasswordHelperTest::Plugin1', 'ForgotPasswordHelperTest::Plugin2'])
67 70  
68 71 environment.enable_plugin(Plugin1)
69 72 environment.enable_plugin(Plugin2)
... ... @@ -85,6 +88,7 @@ class ForgotPasswordHelperTest &lt; ActionView::TestCase
85 88 {:field => 'f3', :name => 'F3', :model => 'user'}]
86 89 end
87 90 end
  91 + Noosfero::Plugin.stubs(:all).returns(['ForgotPasswordHelperTest::Plugin1', 'ForgotPasswordHelperTest::Plugin2'])
88 92  
89 93 environment.enable_plugin(Plugin1)
90 94 environment.enable_plugin(Plugin2)
... ...
test/unit/link_list_block_test.rb
... ... @@ -39,6 +39,32 @@ class LinkListBlockTest &lt; ActiveSupport::TestCase
39 39 assert_tag_in_string l.content, :tag => 'a', :attributes => {:href => '/test_profile/address'}
40 40 end
41 41  
  42 + should 'replace {portal} with environment portal identifier' do
  43 + env = Environment.default
  44 + env.enable('use_portal_community')
  45 + portal = fast_create(Community, :identifier => 'portal-community', :environment_id => env.id)
  46 + env.portal_community = portal
  47 + env.save
  48 +
  49 + stubs(:environment).returns(env)
  50 + l = LinkListBlock.new(:links => [{:name => 'categ', :address => '/{portal}/address'}])
  51 + l.stubs(:owner).returns(env)
  52 + assert_tag_in_string l.content, :tag => 'a', :attributes => {:href => '/portal-community/address'}
  53 + end
  54 +
  55 + should 'not change address if no {portal} there' do
  56 + env = Environment.default
  57 + env.enable('use_portal_community')
  58 + portal = fast_create(Community, :identifier => 'portal-community', :environment_id => env.id)
  59 + env.portal_community = portal
  60 + env.save
  61 +
  62 + stubs(:environment).returns(env)
  63 + l = LinkListBlock.new(:links => [{:name => 'categ', :address => '/address'}])
  64 + l.stubs(:owner).returns(env)
  65 + assert_tag_in_string l.content, :tag => 'a', :attributes => {:href => '/address'}
  66 + end
  67 +
42 68 should 'display options for icons' do
43 69 l = LinkListBlock.new
44 70 l.icons_options.each do |option|
... ...
test/unit/macros_helper_test.rb
... ... @@ -28,6 +28,7 @@ class MacrosHelperTest &lt; ActiveSupport::TestCase
28 28 end
29 29  
30 30 def setup
  31 + Noosfero::Plugin.stubs(:all).returns(['MacrosHelperTest::Plugin1'])
31 32 @environment = Environment.default
32 33 @environment.enable_plugin(Plugin1)
33 34 @plugins = Noosfero::Plugin::Manager.new(@environment, self)
... ... @@ -129,4 +130,27 @@ class MacrosHelperTest &lt; ActiveSupport::TestCase
129 130 assert_equal 'macro_generator', macro_generator(Plugin1::Macro)
130 131 end
131 132  
  133 + should 'get macro default generator' do
  134 + class Plugin1::Macro < Noosfero::Plugin::Macro
  135 + def self.configuration
  136 + { :params => [] }
  137 + end
  138 + end
  139 + assert_nothing_raised NoMethodError do
  140 + assert macro_generator(Plugin1::Macro)
  141 + end
  142 + end
  143 +
  144 + should 'can use a code reference as macro generator' do
  145 + class Plugin1::Macro < Noosfero::Plugin::Macro
  146 + def self.configuration
  147 + { :params => [], :generator => method(:macro_generator_method) }
  148 + end
  149 + def self.macro_generator_method(macro)
  150 + "macro generator method return"
  151 + end
  152 + end
  153 + assert_equal "macro generator method return", macro_generator(Plugin1::Macro)
  154 + end
  155 +
132 156 end
... ...
test/unit/person_test.rb
... ... @@ -1255,6 +1255,7 @@ class PersonTest &lt; ActiveSupport::TestCase
1255 1255 false
1256 1256 end
1257 1257 end
  1258 + Noosfero::Plugin.stubs(:all).returns(['PersonTest::Plugin1', 'PersonTest::Plugin2'])
1258 1259  
1259 1260 e = Environment.default
1260 1261 e.enable_plugin(Plugin1.name)
... ... @@ -1424,6 +1425,7 @@ class PersonTest &lt; ActiveSupport::TestCase
1424 1425 Profile.memberships_of(Person.find_by_identifier('person2'))
1425 1426 end
1426 1427 end
  1428 + Noosfero::Plugin.stubs(:all).returns(['PersonTest::Plugin1', 'PersonTest::Plugin2'])
1427 1429  
1428 1430 Environment.default.enable_plugin(Plugin1)
1429 1431 Environment.default.enable_plugin(Plugin2)
... ...
test/unit/plugin_manager_test.rb
... ... @@ -26,6 +26,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase
26 26 class Plugin2 < Noosfero::Plugin; end;
27 27 class Plugin3 < Noosfero::Plugin; end;
28 28 class Plugin4 < Noosfero::Plugin; end;
  29 + Noosfero::Plugin.stubs(:all).returns(['PluginManagerTest::Plugin1', 'PluginManagerTest::Plugin2', 'PluginManagerTest::Plugin3', 'PluginManagerTest::Plugin4'])
29 30 environment.stubs(:enabled_plugins).returns([Plugin1.to_s, Plugin2.to_s, Plugin4.to_s])
30 31 Noosfero::Plugin.stubs(:all).returns([Plugin1.to_s, Plugin3.to_s, Plugin4.to_s])
31 32 results = plugins.enabled_plugins.map { |instance| instance.class.to_s }
... ... @@ -51,6 +52,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase
51 52 'Plugin 2 action.'
52 53 end
53 54 end
  55 + Noosfero::Plugin.stubs(:all).returns(['PluginManagerTest::Plugin1', 'PluginManagerTest::Plugin2'])
54 56  
55 57 environment.stubs(:enabled_plugins).returns([Plugin1.to_s, Plugin2.to_s])
56 58  
... ... @@ -83,6 +85,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase
83 85 'Plugin 3 action.'
84 86 end
85 87 end
  88 + Noosfero::Plugin.stubs(:all).returns(['PluginManagerTest::Plugin1', 'PluginManagerTest::Plugin2', 'PluginManagerTest::Plugin3'])
86 89  
87 90 environment.stubs(:enabled_plugins).returns([Plugin1.to_s, Plugin2.to_s, Plugin3.to_s])
88 91 p1 = Plugin1.new
... ... @@ -107,6 +110,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase
107 110 'Plugin3'
108 111 end
109 112 end
  113 + Noosfero::Plugin.stubs(:all).returns(['PluginManagerTest::Plugin1', 'PluginManagerTest::Plugin2', 'PluginManagerTest::Plugin3'])
110 114  
111 115 environment.enable_plugin(Plugin1.name)
112 116 environment.enable_plugin(Plugin2.name)
... ... @@ -134,6 +138,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase
134 138 true
135 139 end
136 140 end
  141 + Noosfero::Plugin.stubs(:all).returns(['PluginManagerTest::Plugin1', 'PluginManagerTest::Plugin2', 'PluginManagerTest::Plugin3'])
137 142  
138 143 environment.enable_plugin(Plugin1.name)
139 144 environment.enable_plugin(Plugin2.name)
... ... @@ -162,6 +167,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase
162 167 true
163 168 end
164 169 end
  170 + Noosfero::Plugin.stubs(:all).returns(['PluginManagerTest::Plugin1', 'PluginManagerTest::Plugin2', 'PluginManagerTest::Plugin3'])
165 171  
166 172 environment.enable_plugin(Plugin1.name)
167 173 environment.enable_plugin(Plugin2.name)
... ... @@ -178,6 +184,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase
178 184 [Macro1, Macro2]
179 185 end
180 186 end
  187 + Noosfero::Plugin.stubs(:all).returns(['PluginManagerTest::Plugin1'])
181 188  
182 189 class Plugin1::Macro1 < Noosfero::Plugin::Macro
183 190 def convert(macro, source)
... ... @@ -212,6 +219,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase
212 219 [v1 * v, v2 * v]
213 220 end
214 221 end
  222 + Noosfero::Plugin.stubs(:all).returns(['PluginManagerTest::Plugin1', 'PluginManagerTest::Plugin2'])
215 223  
216 224 environment.enable_plugin(Plugin1)
217 225 environment.enable_plugin(Plugin2)
... ... @@ -231,6 +239,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase
231 239 value * 5
232 240 end
233 241 end
  242 + Noosfero::Plugin.stubs(:all).returns(['PluginManagerTest::Plugin1', 'PluginManagerTest::Plugin2'])
234 243  
235 244 environment.enable_plugin(Plugin1)
236 245 environment.enable_plugin(Plugin2)
... ... @@ -252,6 +261,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase
252 261 [v1 * v, v2 * v, 666]
253 262 end
254 263 end
  264 + Noosfero::Plugin.stubs(:all).returns(['PluginManagerTest::Plugin1', 'PluginManagerTest::Plugin2'])
255 265  
256 266 environment.enable_plugin(Plugin1)
257 267 environment.enable_plugin(Plugin2)
... ... @@ -273,6 +283,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase
273 283 numbers.reject {|n| n<=5}
274 284 end
275 285 end
  286 + Noosfero::Plugin.stubs(:all).returns(['PluginManagerTest::Plugin1', 'PluginManagerTest::Plugin2'])
276 287  
277 288 environment.enable_plugin(Plugin1)
278 289 environment.enable_plugin(Plugin2)
... ...
test/unit/plugin_test.rb
... ... @@ -9,15 +9,9 @@ class PluginTest &lt; ActiveSupport::TestCase
9 9  
10 10 include Noosfero::Plugin::HotSpot
11 11  
12   - should 'keep the list of all loaded subclasses' do
13   - class Plugin1 < Noosfero::Plugin
14   - end
15   -
16   - class Plugin2 < Noosfero::Plugin
17   - end
18   -
19   - assert_includes Noosfero::Plugin.all, Plugin1.to_s
20   - assert_includes Noosfero::Plugin.all, Plugin2.to_s
  12 + should 'keep the list of all available plugins' do
  13 + assert File.directory?(File.join(Rails.root, 'plugins', 'foo'))
  14 + assert_includes Noosfero::Plugin.all, 'FooPlugin'
21 15 end
22 16  
23 17 should 'returns url to plugin management if plugin has admin_controller' do
... ...
test/unit/profile_test.rb
... ... @@ -1790,6 +1790,7 @@ class ProfileTest &lt; ActiveSupport::TestCase
1790 1790 Person.members_of(Community.find_by_identifier('community2'))
1791 1791 end
1792 1792 end
  1793 + Noosfero::Plugin.stubs(:all).returns(['ProfileTest::Plugin1', 'ProfileTest::Plugin2'])
1793 1794 Environment.default.enable_plugin(Plugin1)
1794 1795 Environment.default.enable_plugin(Plugin2)
1795 1796  
... ... @@ -1947,6 +1948,7 @@ class ProfileTest &lt; ActiveSupport::TestCase
1947 1948 end
1948 1949  
1949 1950 environment = Environment.default
  1951 + Noosfero::Plugin.stubs(:all).returns(['ProfileTest::Plugin1'])
1950 1952 environment.enable_plugin(Plugin1)
1951 1953 plugins = Noosfero::Plugin::Manager.new(environment, self)
1952 1954 p = fast_create(Profile)
... ...
test/unit/suggest_article_test.rb
... ... @@ -7,6 +7,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
7 7 ActionMailer::Base.perform_deliveries = true
8 8 ActionMailer::Base.deliveries = []
9 9 @profile = create_user('test_user').person
  10 + Noosfero::Plugin.stubs(:all).returns(['SuggestArticleTest::EverythingIsSpam', 'SuggestArticleTest::SpamNotification'])
10 11 end
11 12 attr_reader :profile
12 13  
... ...
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
... ...