Commit af190be9024982c5d0fdd088782174420a3bf65c
Exists in
master
and in
29 other branches
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 | ... | ... |
... | ... | @@ -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 < 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
app/controllers/public/account_controller.rb
... | ... | @@ -246,15 +246,19 @@ class AccountController < 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 < 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 < 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 + " | ... | ... |
... | ... | @@ -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 < 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 < 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 < 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 < 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 < 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
app/models/national_region.rb
... | ... | @@ -12,7 +12,7 @@ class NationalRegion < 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 < 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 < 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> </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> </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"> | ... | ... |
... | ... | @@ -0,0 +1 @@ |
1 | +<%= display_block(@block) %> | ... | ... |
... | ... | @@ -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> | ... | ... |
... | ... | @@ -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
plugins/pg_search/lib/ext/active_record.rb
... | ... | @@ -2,11 +2,9 @@ require_dependency 'active_record' |
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 < 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 | ... | ... |
... | ... | @@ -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 | ... | ... |
... | ... | @@ -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 | ... | ... |
... | ... | @@ -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 | +} | ... | ... |
... | ... | @@ -0,0 +1 @@ |
1 | +require File.dirname(__FILE__) + '/../../../test/test_helper' | ... | ... |
... | ... | @@ -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
plugins/relevant_content/views/profile_design/relevant_content_plugin
0 → 120000
... | ... | @@ -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. | ... | ... |
... | ... | @@ -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 | ... | ... |
... | ... | @@ -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 | ... | ... |
... | ... | @@ -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
1.11 KB
public/javascripts/application.js
... | ... | @@ -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 | +} | ... | ... |
... | ... | @@ -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 | ... | ... |
... | ... | @@ -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 | ... | ... |
... | ... | @@ -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 | ... | ... |
... | ... | @@ -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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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) | ... | ... |
... | ... | @@ -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 < 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 < 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
test/functional/home_controller_test.rb
... | ... | @@ -107,6 +107,7 @@ class HomeControllerTest < 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 < 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 < 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
test/functional/profile_controller_test.rb
... | ... | @@ -1255,6 +1255,7 @@ class ProfileControllerTest < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 | ... | ... |
... | ... | @@ -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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 | ... | ... |