Commit 1bd11fcdeaa85d7fc9f0c10e23293d2e4da457d9

Authored by Weblate
2 parents cb14670c 0ac87b78

Merge remote-tracking branch 'origin/master'

app/controllers/my_profile/profile_design_controller.rb
... ... @@ -3,7 +3,16 @@ class ProfileDesignController < BoxOrganizerController
3 3 needs_profile
4 4  
5 5 protect 'edit_profile_design', :profile
6   -
  6 +
  7 + before_filter :protect_fixed_block, :only => [:save, :move_block]
  8 +
  9 + def protect_fixed_block
  10 + block = boxes_holder.blocks.find(params[:id].gsub(/^block-/, ''))
  11 + if block.fixed && !current_person.is_admin?
  12 + render_access_denied
  13 + end
  14 + end
  15 +
7 16 def available_blocks
8 17 blocks = [ ArticleBlock, TagsBlock, RecentDocumentsBlock, ProfileInfoBlock, LinkListBlock, MyNetworkBlock, FeedReaderBlock, ProfileImageBlock, LocationBlock, SlideshowBlock, ProfileSearchBlock, HighlightsBlock ]
9 18  
... ...
app/helpers/application_helper.rb
... ... @@ -945,9 +945,9 @@ module ApplicationHelper
945 945 # from Article model for an ArticleBlock.
946 946 def reference_to_article(text, article, anchor=nil)
947 947 if article.profile.domains.empty?
948   - href = "/#{article.url[:profile]}/"
  948 + href = "#{Noosfero.root}/#{article.url[:profile]}/"
949 949 else
950   - href = "http://#{article.profile.domains.first.name}/"
  950 + href = "http://#{article.profile.domains.first.name}#{Noosfero.root}/"
951 951 end
952 952 href += article.url[:page].join('/')
953 953 href += '#' + anchor if anchor
... ...
app/helpers/article_helper.rb
... ... @@ -77,12 +77,59 @@ module ArticleHelper
77 77 content_tag('div',
78 78 radio_button(:article, :published, false) +
79 79 content_tag('label', _('Private'), :for => 'article_published_false', :id => "label_private")
80   - ) +
81   - (article.profile.community? ? content_tag('div',
82   - content_tag('label', _('Fill in the search field to add the exception users to see this content'), :id => "text-input-search-exception-users") +
83   - token_input_field_tag(:q, 'search-article-privacy-exceptions', {:action => 'search_article_privacy_exceptions'},
84   - {:focus => false, :hint_text => _('Type in a search term for a user'), :pre_populate => tokenized_children})) :
85   - ''))
  80 + ) +
  81 + privacity_exceptions(article, tokenized_children)
  82 + )
  83 + end
  84 +
  85 + def privacity_exceptions(article, tokenized_children)
  86 + content_tag('div',
  87 + content_tag('div',
  88 + (
  89 + if article.profile
  90 + add_option_to_followers(article, tokenized_children)
  91 + else
  92 + ''
  93 + end
  94 + )
  95 + ),
  96 + :style => "margin-left:10px"
  97 + )
  98 + end
  99 +
  100 + def add_option_to_followers(article, tokenized_children)
  101 + label_message = article.profile.organization? ? _('For all community members') : _('For all your friends')
  102 +
  103 + check_box(
  104 + :article,
  105 + :show_to_followers,
  106 + {:class => "custom_privacy_option"}
  107 + ) +
  108 + content_tag(
  109 + 'label',
  110 + label_message,
  111 + :for => 'article_show_to_followers',
  112 + :id => 'label_show_to_followers'
  113 + ) +
  114 + (article.profile.community? ?
  115 + content_tag(
  116 + 'div',
  117 + content_tag(
  118 + 'label',
  119 + _('Fill in the search field to add the exception users to see this content'),
  120 + :id => "text-input-search-exception-users"
  121 + ) +
  122 + token_input_field_tag(
  123 + :q,
  124 + 'search-article-privacy-exceptions',
  125 + {:action => 'search_article_privacy_exceptions'},
  126 + {
  127 + :focus => false,
  128 + :hint_text => _('Type in a search term for a user'),
  129 + :pre_populate => tokenized_children
  130 + }
  131 + )
  132 + ) : '')
86 133 end
87 134  
88 135 def prepare_to_token_input(array)
... ...
app/helpers/boxes_helper.rb
... ... @@ -170,49 +170,54 @@ module BoxesHelper
170 170 else
171 171 "before-block-#{block.id}"
172 172 end
173   -
174   - content_tag('div', ' ', :id => id, :class => 'block-target' ) + drop_receiving_element(id, :url => { :action => 'move_block', :target => id }, :accept => box.acceptable_blocks, :hoverclass => 'block-target-hover')
  173 + if block.nil? or modifiable?(block)
  174 + content_tag('div', ' ', :id => id, :class => 'block-target' ) + drop_receiving_element(id, :url => { :action => 'move_block', :target => id }, :accept => box.acceptable_blocks, :hoverclass => 'block-target-hover')
  175 + else
  176 + ""
  177 + end
175 178 end
176 179  
177 180 # makes the given block draggable so it can be moved away.
178 181 def block_handle(block)
179   - draggable_element("block-#{block.id}", :revert => true)
  182 + modifiable?(block) ? draggable_element("block-#{block.id}", :revert => true) : ""
180 183 end
181 184  
182 185 def block_edit_buttons(block)
183 186 buttons = []
184 187 nowhere = 'javascript: return false;'
185 188  
186   - if block.first?
187   - buttons << icon_button('up-disabled', _("Can't move up anymore."), nowhere)
188   - else
189   - buttons << icon_button('up', _('Move block up'), { :action => 'move_block_up', :id => block.id }, { :method => 'post' })
190   - end
  189 + if modifiable?(block)
  190 + if block.first?
  191 + buttons << icon_button('up-disabled', _("Can't move up anymore."), nowhere)
  192 + else
  193 + buttons << icon_button('up', _('Move block up'), { :action => 'move_block_up', :id => block.id }, { :method => 'post' })
  194 + end
191 195  
192   - if block.last?
193   - buttons << icon_button('down-disabled', _("Can't move down anymore."), nowhere)
194   - else
195   - buttons << icon_button(:down, _('Move block down'), { :action => 'move_block_down' ,:id => block.id }, { :method => 'post'})
196   - end
  196 + if block.last?
  197 + buttons << icon_button('down-disabled', _("Can't move down anymore."), nowhere)
  198 + else
  199 + buttons << icon_button(:down, _('Move block down'), { :action => 'move_block_down' ,:id => block.id }, { :method => 'post'})
  200 + end
197 201  
198   - holder = block.owner
199   - # move to opposite side
200   - # FIXME too much hardcoded stuff
201   - if holder.layout_template == 'default'
202   - if block.box.position == 2 # area 2, left side => move to right side
203   - buttons << icon_button('right', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[2].id.to_s, :id => block.id }, :method => 'post' )
204   - elsif block.box.position == 3 # area 3, right side => move to left side
205   - buttons << icon_button('left', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[1].id.to_s, :id => block.id }, :method => 'post' )
  202 + holder = block.owner
  203 + # move to opposite side
  204 + # FIXME too much hardcoded stuff
  205 + if holder.layout_template == 'default'
  206 + if block.box.position == 2 # area 2, left side => move to right side
  207 + buttons << icon_button('right', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[2].id.to_s, :id => block.id }, :method => 'post' )
  208 + elsif block.box.position == 3 # area 3, right side => move to left side
  209 + buttons << icon_button('left', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[1].id.to_s, :id => block.id }, :method => 'post' )
  210 + end
206 211 end
207   - end
208 212  
209   - if block.editable?
210   - buttons << colorbox_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id })
211   - end
  213 + if block.editable?
  214 + buttons << colorbox_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id })
  215 + end
212 216  
213   - if !block.main?
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_block', :id => block.id }, { :method => 'post' })
  217 + if !block.main?
  218 + buttons << icon_button(:delete, _('Remove block'), { :action => 'remove', :id => block.id }, { :method => 'post', :confirm => _('Are you sure you want to remove this block?')})
  219 + buttons << icon_button(:clone, _('Clone'), { :action => 'clone_block', :id => block.id }, { :method => 'post' })
  220 + end
216 221 end
217 222  
218 223 if block.respond_to?(:help)
... ... @@ -248,5 +253,7 @@ module BoxesHelper
248 253 classes
249 254 end
250 255  
251   -
  256 + def modifiable?(block)
  257 + return !block.fixed || environment.admins.include?(user)
  258 + end
252 259 end
... ...
app/helpers/layout_helper.rb
... ... @@ -2,6 +2,7 @@ module LayoutHelper
2 2  
3 3 def body_classes
4 4 # Identify the current controller and action for the CSS:
  5 + (logged_in? ? " logged-in" : "") +
5 6 " controller-#{controller.controller_name}" +
6 7 " action-#{controller.controller_name}-#{controller.action_name}" +
7 8 " template-#{@layout_template || if profile.blank? then 'default' else profile.layout_template end}" +
... ...
app/helpers/search_helper.rb
... ... @@ -21,6 +21,12 @@ module SearchHelper
21 21 'more_comments' => _('More comments')
22 22 }
23 23  
  24 + COMMON_PROFILE_LIST_BLOCK = [
  25 + :enterprises,
  26 + :people,
  27 + :communities
  28 + ]
  29 +
24 30 # FIXME remove it after search_controler refactored
25 31 include EventsHelper
26 32  
... ... @@ -94,7 +100,7 @@ module SearchHelper
94 100 compact_link = display?(asset, :compact) ? (display == 'compact' ? _('Compact') : link_to(_('Compact'), params.merge(:display => 'compact'))) : nil
95 101 map_link = display?(asset, :map) ? (display == 'map' ? _('Map') : link_to(_('Map'), params.merge(:display => 'map'))) : nil
96 102 full_link = display?(asset, :full) ? (display == 'full' ? _('Full') : link_to(_('Full'), params.merge(:display => 'full'))) : nil
97   - content_tag('div',
  103 + content_tag('div',
98 104 content_tag('strong', _('Display')) + ': ' + [compact_link, map_link, full_link].compact.join(' | ').html_safe,
99 105 :class => 'search-customize-options'
100 106 )
... ...
app/models/article.rb
... ... @@ -2,7 +2,14 @@ require &#39;hpricot&#39;
2 2  
3 3 class Article < ActiveRecord::Base
4 4  
5   - attr_accessible :name, :body, :abstract, :profile, :tag_list, :parent, :allow_members_to_edit, :translation_of_id, :language, :license_id, :parent_id, :display_posts_in_current_language, :category_ids, :posts_per_page, :moderate_comments, :accept_comments, :feed, :published, :source, :highlighted, :notify_comments, :display_hits, :slug, :external_feed_builder, :display_versions, :external_link, :image_builder
  5 + attr_accessible :name, :body, :abstract, :profile, :tag_list, :parent,
  6 + :allow_members_to_edit, :translation_of_id, :language,
  7 + :license_id, :parent_id, :display_posts_in_current_language,
  8 + :category_ids, :posts_per_page, :moderate_comments,
  9 + :accept_comments, :feed, :published, :source,
  10 + :highlighted, :notify_comments, :display_hits, :slug,
  11 + :external_feed_builder, :display_versions, :external_link,
  12 + :image_builder, :show_to_followers
6 13  
7 14 acts_as_having_image
8 15  
... ... @@ -333,7 +340,7 @@ class Article &lt; ActiveRecord::Base
333 340 def belongs_to_blog?
334 341 self.parent and self.parent.blog?
335 342 end
336   -
  343 +
337 344 def belongs_to_forum?
338 345 self.parent and self.parent.forum?
339 346 end
... ... @@ -445,6 +452,7 @@ class Article &lt; ActiveRecord::Base
445 452 if self.parent && !self.parent.published?
446 453 return false
447 454 end
  455 +
448 456 true
449 457 else
450 458 false
... ... @@ -476,14 +484,17 @@ class Article &lt; ActiveRecord::Base
476 484 {:conditions => [" articles.published = ? OR
477 485 articles.last_changed_by_id = ? OR
478 486 articles.profile_id = ? OR
479   - ?",
480   - true, user.id, user.id, user.has_permission?(:view_private_content, profile)] }
  487 + ? OR articles.show_to_followers = ? AND ?",
  488 + true, user.id, user.id, user.has_permission?(:view_private_content, profile),
  489 + true, user.follows?(profile)]}
481 490 end
482 491  
  492 +
483 493 def display_unpublished_article_to?(user)
484 494 user == author || allow_view_private_content?(user) || user == profile ||
485 495 user.is_admin?(profile.environment) || user.is_admin?(profile) ||
486   - article_privacy_exceptions.include?(user)
  496 + article_privacy_exceptions.include?(user) ||
  497 + (self.show_to_followers && user.follows?(profile))
487 498 end
488 499  
489 500 def display_to?(user = nil)
... ...
app/models/block.rb
1 1 class Block < ActiveRecord::Base
2 2  
3   - attr_accessible :title, :display, :limit, :box_id, :posts_per_page, :visualization_format, :language, :display_user, :box
  3 + attr_accessible :title, :display, :limit, :box_id, :posts_per_page, :visualization_format, :language, :display_user, :box, :fixed
4 4  
5 5 # to be able to generate HTML
6 6 include ActionView::Helpers::UrlHelper
... ... @@ -110,6 +110,9 @@ class Block &lt; ActiveRecord::Base
110 110 # * <tt>'all'</tt>: the block is always displayed
111 111 settings_items :language, :type => :string, :default => 'all'
112 112  
  113 + # The block can be configured to be fixed. Only can be edited by environment admins
  114 + settings_items :fixed, :type => :boolean, :default => false
  115 +
113 116 # returns the description of the block, used when the user sees a list of
114 117 # blocks to choose one to include in the design.
115 118 #
... ...
app/views/box_organizer/edit.html.erb
... ... @@ -5,6 +5,12 @@
5 5  
6 6 <%= labelled_form_field(_('Custom title for this block: '), text_field(:block, :title, :maxlength => 20)) %>
7 7  
  8 + <% if environment.admins.include?(user) %>
  9 + <div class="fixed_block">
  10 + <%= labelled_check_box(_("Fixed"), "block[fixed]", value = "1", checked = @block.fixed) %>
  11 + </div>
  12 + <% end %>
  13 +
8 14 <%= render :partial => partial_for_class(@block.class) %>
9 15  
10 16 <div class="display">
... ...
app/views/events/events.html.erb
... ... @@ -3,7 +3,7 @@
3 3 <div id='agenda-toolbar'>
4 4 <%= button :back, _('Back to %s') % profile.name, profile.url %>
5 5 <% if user && user.has_permission?('post_content', profile) %>
6   - <%= button :new, _('New event'), myprofile_url(:controller => 'cms', :action => 'new', :type => 'Event') %>
  6 + <%= button :new, _('New event'), myprofile_path(:controller => 'cms', :action => 'new', :type => 'Event') %>
7 7 <% end %>
8 8 </div>
9 9  
... ...
app/views/search/_display_results.html.erb
... ... @@ -14,7 +14,7 @@
14 14  
15 15 <% display = display_filter(name, params[:display]) %>
16 16  
17   - <div class="search-results-innerbox search-results-type-<%= name.to_s.singularize %> <%= 'common-profile-list-block' if [:enterprises, :people, :communities].include?(name) %>">
  17 + <div class="search-results-innerbox search-results-type-<%= name.to_s.singularize %> <%= 'common-profile-list-block' if SearchHelper::COMMON_PROFILE_LIST_BLOCK.include?(name) %>">
18 18 <ul>
19 19 <% search[:results].each do |hit| %>
20 20 <% partial = partial_for_class(hit.class, display) %>
... ...
db/migrate/20150113131617_add_show_to_followers_for_article.rb 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +class AddShowToFollowersForArticle < ActiveRecord::Migration
  2 + def up
  3 + add_column :articles, :show_to_followers, :boolean, :default => false
  4 + end
  5 +
  6 + def down
  7 + remove_column :articles, :show_to_followers
  8 + end
  9 +end
... ...
features/edit_article.feature
... ... @@ -47,6 +47,28 @@ Feature: edit article
47 47 Then I should see "Access denied"
48 48  
49 49 @selenium
  50 + Scenario: Hide token field when show to members is activated
  51 + Given the following communities
  52 + | name | identifier | owner |
  53 + | Free Software | freesoftware | joaosilva |
  54 + And the following users
  55 + | login | name |
  56 + | mario | Mario Souto |
  57 + | maria | Maria Silva |
  58 + And "Mario Souto" is a member of "Free Software"
  59 + And "Maria Silva" is a member of "Free Software"
  60 + And I am on freesoftware's control panel
  61 + And I follow "Manage Content"
  62 + And I should see "New content"
  63 + And I follow "New content"
  64 + And I should see "Folder"
  65 + When I follow "Folder"
  66 + And I fill in "Title" with "My Folder"
  67 + And I choose "article_published_false"
  68 + And I check "article_show_to_followers"
  69 + Then I should not see "Fill in the search"
  70 +
  71 + @selenium
50 72 Scenario: show exception users field when you choose the private option
51 73 Given the following communities
52 74 | name | identifier | owner |
... ...
public/javascripts/article.js
... ... @@ -136,7 +136,7 @@ jQuery(function($) {
136 136 if (data.length && data.length > 0) {
137 137 $('#media-search-results').slideDown();
138 138 }
139   - $('#media-search-box .header').toggleClass('icon-loading');
  139 + $('#media-search-box .header').toggleClass('icon-loading');
140 140 });
141 141 return false;
142 142 });
... ... @@ -144,20 +144,20 @@ jQuery(function($) {
144 144 $('#media-upload-form form').ajaxForm({
145 145 resetForm: true,
146 146 beforeSubmit:
147   - function() {
148   - $('#media-upload-form').slideUp();
149   - $('#media-upload-box .header').toggleClass('icon-loading');
150   - },
  147 + function() {
  148 + $('#media-upload-form').slideUp();
  149 + $('#media-upload-box .header').toggleClass('icon-loading');
  150 + },
151 151 success:
152   - function(text) {
153   - text = text.replace('<pre>', '').replace('</pre>', ''); // old firefox
154   - var data = $.parseJSON(text);
155   - list_items(data, '#media-upload-results .items', true);
156   - if (data.length && data.length > 0) {
157   - $('#media-upload-results').slideDown();
158   - }
159   - $('#media-upload-box .header').toggleClass('icon-loading');
  152 + function(text) {
  153 + text = text.replace('<pre>', '').replace('</pre>', ''); // old firefox
  154 + var data = $.parseJSON(text);
  155 + list_items(data, '#media-upload-results .items', true);
  156 + if (data.length && data.length > 0) {
  157 + $('#media-upload-results').slideDown();
160 158 }
  159 + $('#media-upload-box .header').toggleClass('icon-loading');
  160 + }
161 161 });
162 162  
163 163 $('#media-upload-more-files').click(function() {
... ... @@ -166,19 +166,45 @@ jQuery(function($) {
166 166 return false;
167 167 });
168 168  
  169 + function is_public_article() {
  170 + return $("#article_published_true").attr('checked');
  171 + }
  172 +
  173 + function show_hide_privacy_options() {
  174 + var show_privacy_options = $("#article_published_false").attr('checked');
  175 + var custom_privacy_option = $(".custom_privacy_option").parent("div");
  176 +
  177 + if( show_privacy_options ) {
  178 + custom_privacy_option.show();
  179 + } else {
  180 + custom_privacy_option.hide();
  181 + }
  182 + show_hide_token_input();
  183 + }
  184 +
169 185 function show_hide_token_input() {
170   - if($("#article_published_false").attr('checked'))
171   - $("#text-input-search-exception-users").parent("div").css('display', 'block');
172   - else
173   - $("#text-input-search-exception-users").parent("div").css('display', 'none');
  186 + var display_token = $(".custom_privacy_option:checked").length == 0;
  187 + var token_field = $("#text-input-search-exception-users").parent("div");
  188 +
  189 + if( display_token && !is_public_article() ) {
  190 + token_field.css('display', 'block');
  191 + } else {
  192 + token_field.css('display', 'none');
  193 + }
174 194 }
175 195  
176 196 if( $("#token-input-search-article-privacy-exceptions").length == 1 ) {
  197 + show_hide_privacy_options();
177 198 show_hide_token_input();
178   -
179   - //Hide / Show the text area
180   - $("#article_published_false").click(show_hide_token_input);
181   - $("#article_published_true").click(show_hide_token_input);
182 199 }
183 200  
  201 + $(document).ready(function(){
  202 + show_hide_privacy_options();
  203 + });
  204 +
  205 + //Hide / Show the text area
  206 + $("#article_published_false").click(show_hide_privacy_options);
  207 + $("#article_published_true").click(show_hide_privacy_options);
  208 + $(".custom_privacy_option").click(show_hide_token_input);
  209 +
184 210 });
... ...
test/functional/content_viewer_controller_test.rb
... ... @@ -661,8 +661,8 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
661 661 get :view_page, :profile => owner.identifier, :page => folder.path
662 662 assert_response :success
663 663 assert_select '.image-gallery-item', 0
664   - end
665   -
  664 + end
  665 +
666 666  
667 667 should 'display default image in the slideshow if thumbnails were not processed' do
668 668 @controller.stubs(:per_page).returns(1)
... ... @@ -1296,14 +1296,14 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
1296 1296 def comment_form_extra_contents(args)
1297 1297 proc {
1298 1298 hidden_field_tag('comment[some_field_id]', 1)
1299   - }
  1299 + }
1300 1300 end
1301 1301 end
1302 1302 class Plugin2 < Noosfero::Plugin
1303 1303 def comment_form_extra_contents(args)
1304 1304 proc {
1305 1305 hidden_field_tag('comment[another_field_id]', 1)
1306   - }
  1306 + }
1307 1307 end
1308 1308 end
1309 1309 Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
... ... @@ -1373,20 +1373,20 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
1373 1373 get :view_page, :profile => profile.identifier, :page => [blog.path]
1374 1374 assert_tag :tag => 'strong', :content => /bold/
1375 1375 end
1376   -
  1376 +
1377 1377 should 'add extra content on article header from plugins' do
1378 1378 class Plugin1 < Noosfero::Plugin
1379 1379 def article_header_extra_contents(args)
1380 1380 proc {
1381 1381 content_tag('div', '', :class => 'plugin1')
1382   - }
  1382 + }
1383 1383 end
1384 1384 end
1385 1385 class Plugin2 < Noosfero::Plugin
1386 1386 def article_header_extra_contents(args)
1387 1387 proc {
1388 1388 content_tag('div', '', :class => 'plugin2')
1389   - }
  1389 + }
1390 1390 end
1391 1391 end
1392 1392 Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
... ... @@ -1447,4 +1447,35 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
1447 1447 assert_tag :tag => 'meta', :attributes => { :property => 'og:image', :content => /\/images\/x.png/ }
1448 1448 end
1449 1449  
  1450 + should 'manage private article visualization' do
  1451 + community = Community.create(:name => 'test-community')
  1452 + community.add_member(@profile)
  1453 + community.save!
  1454 +
  1455 + blog = community.articles.find_by_name("Blog")
  1456 +
  1457 + article = TinyMceArticle.create(:name => 'Article to be shared with images',
  1458 + :body => 'This article should be shared with all social networks',
  1459 + :profile => @profile,
  1460 + :published => false,
  1461 + :show_to_followers => true)
  1462 + article.parent = blog
  1463 + article.save!
  1464 +
  1465 + otheruser = create_user('otheruser').person
  1466 + community.add_member(otheruser)
  1467 + login_as(otheruser.identifier)
  1468 +
  1469 + get :view_page, :profile => community.identifier, "page" => 'blog'
  1470 +
  1471 + assert_response :success
  1472 + assert_tag :tag => 'h1', :attributes => { :class => /title/ }, :content => article.name
  1473 +
  1474 + article.show_to_followers = false
  1475 + article.save!
  1476 +
  1477 + get :view_page, :profile => community.identifier, "page" => 'blog'
  1478 +
  1479 + assert_no_tag :tag => 'h1', :attributes => { :class => /title/ }, :content => article.name
  1480 + end
1450 1481 end
... ...
test/functional/profile_design_controller_test.rb
... ... @@ -737,4 +737,22 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase
737 737 end
738 738 end
739 739  
  740 + test 'should forbid POST to save for fixed blocks' do
  741 + block = profile.blocks.last
  742 + block.fixed = true
  743 + block.save!
  744 +
  745 + post :save, id: block.id, profile: profile.identifier
  746 + assert_response :forbidden
  747 + end
  748 +
  749 + test 'should forbid POST to move_block for fixed blocks' do
  750 + block = profile.blocks.last
  751 + block.fixed = true
  752 + block.save!
  753 +
  754 + post :move_block, id: block.id, profile: profile.identifier, target: "end-of-box-#{@box3.id}"
  755 + assert_response :forbidden
  756 + end
  757 +
740 758 end
... ...
test/unit/boxes_helper_test.rb
1 1 require File.dirname(__FILE__) + '/../test_helper'
  2 +require File.dirname(__FILE__) + '/../../app/helpers/boxes_helper'
2 3  
3 4 class BoxesHelperTest < ActionView::TestCase
4 5  
... ... @@ -119,4 +120,31 @@ class BoxesHelperTest &lt; ActionView::TestCase
119 120 display_box_content(box, '')
120 121 end
121 122  
  123 + should 'not show move options on block when block is fixed' do
  124 + p = create_user_with_blocks
  125 +
  126 + b = p.blocks.select{|bk| !bk.kind_of?(MainBlock) }[0]
  127 + b.fixed = true
  128 + b.save!
  129 +
  130 + stubs(:environment).returns(p.environment)
  131 + stubs(:user).returns(p)
  132 +
  133 + assert_equal false, modifiable?(b)
  134 + end
  135 +
  136 + should 'show move options on block when block is fixed and user is admin' do
  137 + p = create_user_with_blocks
  138 +
  139 + b = p.blocks.select{|bk| !bk.kind_of?(MainBlock) }[0]
  140 + b.fixed = true
  141 + b.save!
  142 +
  143 + p.environment.add_admin(p)
  144 +
  145 + stubs(:environment).returns(p.environment)
  146 + stubs(:user).returns(p)
  147 +
  148 + assert_equal true, modifiable?(b)
  149 + end
122 150 end
... ...
test/unit/layout_helper_test.rb 0 → 100644
... ... @@ -0,0 +1,17 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class LayoutHelperTest < ActionView::TestCase
  4 +
  5 + should 'append logged-in class in body when user is logged-in' do
  6 + expects(:logged_in?).returns(true)
  7 + expects(:profile).returns(nil).at_least_once
  8 + assert_includes body_classes.split, 'logged-in'
  9 + end
  10 +
  11 + should 'not append logged-in class when user is not logged-in' do
  12 + expects(:logged_in?).returns(false)
  13 + expects(:profile).returns(nil).at_least_once
  14 + assert_not_includes body_classes.split, 'logged-in'
  15 + end
  16 +
  17 +end
... ...