Commit d0561132a9af7bcd87550258ef5e4358b6c0ea0c

Authored by Daniela Feitosa
2 parents abdf6fab 49e6135e

Merge branch 'stable'

Conflicts:
	app/controllers/my_profile/profile_themes_controller.rb
	test/unit/comment_test.rb
	vendor/plugins/action_tracker_has_comments/init.rb
app/controllers/admin/users_controller.rb
... ... @@ -7,7 +7,7 @@ class UsersController < AdminController
7 7 include UsersHelper
8 8  
9 9 def index
10   - @filter = params[:filter]
  10 + @filter = params[:filter] || 'all_users'
11 11 scope = environment.people.no_templates
12 12 if @filter == 'admin_users'
13 13 scope = scope.admins
... ... @@ -16,6 +16,7 @@ class UsersController < AdminController
16 16 elsif @filter == 'deactivated_users'
17 17 scope = scope.deactivated
18 18 end
  19 + scope = scope.order('name ASC')
19 20 @q = params[:q]
20 21 @collection = find_by_contents(:people, scope, @q, {:per_page => per_page, :page => params[:npage]})[:results]
21 22 end
... ...
app/controllers/application_controller.rb
... ... @@ -21,6 +21,7 @@ class ApplicationController < ActionController::Base
21 21 include ApplicationHelper
22 22 layout :get_layout
23 23 def get_layout
  24 + return nil if request.format == :js
24 25 theme_layout = theme_option(:layout)
25 26 if theme_layout
26 27 theme_view_file('layouts/'+theme_layout) || theme_layout
... ...
app/controllers/box_organizer_controller.rb
... ... @@ -70,7 +70,7 @@ class BoxOrganizerController < ApplicationController
70 70 else
71 71 @center_block_types = (Box.acceptable_center_blocks & available_blocks) + plugins.dispatch(:extra_blocks, :type => boxes_holder.class, :position => 1)
72 72 @side_block_types = (Box.acceptable_side_blocks & available_blocks) + plugins.dispatch(:extra_blocks, :type => boxes_holder.class, :position => [2,3])
73   - @boxes = boxes_holder.boxes
  73 + @boxes = boxes_holder.boxes.with_position
74 74 render :action => 'add_block', :layout => false
75 75 end
76 76 end
... ...
app/helpers/boxes_helper.rb
... ... @@ -39,7 +39,7 @@ module BoxesHelper
39 39 end
40 40  
41 41 def display_boxes(holder, main_content)
42   - boxes = holder.boxes.first(holder.boxes_limit)
  42 + boxes = holder.boxes.with_position.first(holder.boxes_limit)
43 43 content = boxes.reverse.map { |item| display_box(item, main_content) }.join("\n")
44 44 content = main_content if (content.blank?)
45 45  
... ...
app/models/box.rb
... ... @@ -5,6 +5,8 @@ class Box < ActiveRecord::Base
5 5  
6 6 include Noosfero::Plugin::HotSpot
7 7  
  8 + named_scope :with_position, :conditions => ['boxes.position > 0']
  9 +
8 10 def environment
9 11 owner ? (owner.kind_of?(Environment) ? owner : owner.environment) : nil
10 12 end
... ...
app/models/environment.rb
... ... @@ -186,7 +186,7 @@ class Environment < ActiveRecord::Base
186 186 has_many :product_categories, :conditions => { :type => 'ProductCategory'}
187 187 has_many :regions
188 188  
189   - has_many :roles
  189 + has_many :roles, :dependent => :destroy
190 190  
191 191 has_many :qualifiers
192 192 has_many :certifiers
... ...
app/views/blocks/location.html.erb
... ... @@ -3,7 +3,6 @@
3 3 <div class='the-localization-map'>
4 4 <img src="https://maps.google.com/maps/api/staticmap?center=<%=profile.lat%>,<%=profile.lng%>&zoom=<%=block.zoom%>&size=190x250&maptype=<%=block.map_type%>&markers=<%=profile.lat%>,<%=profile.lng%>&sensor=false"/>
5 5 </div>
6   -</div>
7 6 <% else %>
8 7 <i><%= _('This profile has no geographical position registered.') %></i>
9 8 <% end %>
... ...
debian/changelog
  1 +noosfero (0.46.1) unstable; urgency=low
  2 +
  3 + * Bugfixes release
  4 +
  5 + -- Daniela Soares Feitosa <daniela@colivre.coop.br> Fri, 07 Mar 2014 10:33:11 +0000
  6 +
1 7 noosfero (0.46.0) unstable; urgency=low
2 8  
3 9 * New features release
... ...
lib/noosfero.rb
... ... @@ -3,7 +3,7 @@ require &#39;fast_gettext&#39;
3 3  
4 4 module Noosfero
5 5 PROJECT = 'noosfero'
6   - VERSION = '0.46.0'
  6 + VERSION = '0.46.1'
7 7  
8 8 def self.pattern_for_controllers_in_directory(dir)
9 9 disjunction = controllers_in_directory(dir).join('|')
... ...
lib/noosfero/core_ext.rb
1 1 require 'noosfero/core_ext/string'
2 2 require 'noosfero/core_ext/integer'
  3 +require 'noosfero/core_ext/array'
3 4 require 'noosfero/core_ext/object'
4 5 require 'noosfero/core_ext/active_record'
... ...
lib/noosfero/core_ext/array.rb 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +class Array
  2 +
  3 + def uniq_by
  4 + hash, array = {}, []
  5 + each { |i| hash[yield(i)] ||= (array << i) }
  6 + array
  7 + end
  8 +
  9 +end
... ...
lib/noosfero/plugin/routes.rb
... ... @@ -15,12 +15,16 @@ Dir.glob(File.join(Rails.root, plugins_root, &#39;*&#39;, &#39;controllers&#39;)) do |controller
15 15 controllers_by_folder.each do |folder, controllers|
16 16 controllers.each do |controller|
17 17 controller_name = controller.gsub("#{plugin_name}_plugin_",'')
18   - map.connect "#{prefixes_by_folder[folder]}/#{plugin_name}/#{controller_name}/:action/:id", :controller => controller
  18 + if %w[profile myprofile].include?(folder)
  19 + map.connect "#{prefixes_by_folder[folder]}/#{plugin_name}/#{controller_name}/:action/:id", :controller => controller, :profile => /#{Noosfero.identifier_format}/
  20 + else
  21 + map.connect "#{prefixes_by_folder[folder]}/#{plugin_name}/#{controller_name}/:action/:id", :controller => controller
  22 + end
19 23 end
20 24 end
21 25  
22 26 map.connect 'plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin'
23   - map.connect 'profile/:profile/plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin_profile'
24   - map.connect 'myprofile/:profile/plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin_myprofile'
  27 + map.connect 'profile/:profile/plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin_profile', :profile => /#{Noosfero.identifier_format}/
  28 + map.connect 'myprofile/:profile/plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin_myprofile', :profile => /#{Noosfero.identifier_format}/
25 29 map.connect 'admin/plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin_admin'
26 30 end
... ...
plugins/container_block/lib/container_block_plugin.rb
... ... @@ -16,4 +16,8 @@ class ContainerBlockPlugin &lt; Noosfero::Plugin
16 16 true
17 17 end
18 18  
  19 + def js_files
  20 + 'container_block.js'
  21 + end
  22 +
19 23 end
... ...
plugins/container_block/lib/container_block_plugin/container_block.rb
... ... @@ -7,6 +7,16 @@ class ContainerBlockPlugin::ContainerBlock &lt; Block
7 7 settings_items :container_box_id, :type => Integer, :default => nil
8 8 settings_items :children_settings, :type => Hash, :default => {}
9 9  
  10 + validate :no_cyclical_reference, :if => 'container_box_id.present?'
  11 +
  12 + def no_cyclical_reference
  13 + errors.add(:box_id, _('cyclical reference is not allowed.')) if box_id == container_box_id
  14 + end
  15 +
  16 + before_save do |b|
  17 + raise "cyclical reference is not allowed" if b.box_id == b.container_box_id && !b.container_box_id.blank?
  18 + end
  19 +
10 20 def self.description
11 21 _('Container')
12 22 end
... ... @@ -15,6 +25,10 @@ class ContainerBlockPlugin::ContainerBlock &lt; Block
15 25 _('This block acts as a container for another blocks')
16 26 end
17 27  
  28 + def cacheable?
  29 + false
  30 + end
  31 +
18 32 def layout_template
19 33 nil
20 34 end
... ... @@ -24,8 +38,9 @@ class ContainerBlockPlugin::ContainerBlock &lt; Block
24 38 end
25 39  
26 40 def create_box
27   - box = Box.create!(:owner => owner)
28   - settings[:container_box_id] = box.id
  41 + container_box = Box.create!(:owner => owner)
  42 + container_box.update_attribute(:position, nil)
  43 + settings[:container_box_id] = container_box.id
29 44 save!
30 45 end
31 46  
... ...
plugins/container_block/public/container_block.js 0 → 100644
... ... @@ -0,0 +1,28 @@
  1 +function enableMoveContainerChildren(container, box) {
  2 + var div = jQuery('#box-'+box+' > .block-outer > .block');
  3 + if(!div.is('.ui-resizable')) {
  4 + div.resizable({
  5 + handles: 'e, w',
  6 + containment: '#block-'+container+' .block-inner-2',
  7 + resize: function( event, ui ) {
  8 + ui.element.height('auto');
  9 + }
  10 + });
  11 + }
  12 +}
  13 +
  14 +function disableMoveContainerChildren(container, box) {
  15 + var div = jQuery('#box-'+box+' > .block-outer > .block');
  16 + if(div.is('.ui-resizable')) {
  17 + div.resizable('destroy');
  18 + }
  19 +}
  20 +
  21 +function containerChildrenWidth(container, box) {
  22 + widths = "";
  23 + jQuery('#box-'+box+' > .block-outer > .block').each(function(i) {
  24 + childId = jQuery(this).attr('id').match(/block-(\d+)/)[1];
  25 + widths+=childId+","+jQuery(this).width()+"|";
  26 + });
  27 + return "widths="+widths;
  28 +}
... ...
plugins/container_block/public/style.css
  1 +#box-organizer .container-block-plugin_container-block > .block-inner-1 > .block-inner-2 > .button-bar {
  2 + height: 22px;
  3 + padding-bottom: 0px;
  4 + width: auto;
  5 +}
  6 +
1 7 #content .boxes .container-block-plugin_container-block .container_block_child, .container-block-plugin_container-block .block-outer {
2 8 display: inline-block;
3 9 vertical-align: top;
... ... @@ -17,14 +23,10 @@
17 23 background-image: url(/designs/icons/default/Tango/16x16/actions/go-previous.png);
18 24 }
19 25  
20   -#content .boxes .container-block-plugin_container-block .block {
21   - outline-offset: -2px;
22   -}
23   -
24 26 #content .boxes .container-block-plugin_container-block .block .ui-resizable-handle {
25 27 width: 10px;
26 28 height: 28px;
27   - z-index: 0;
  29 + z-index: 1000;
28 30 }
29 31  
30 32 #content .boxes .container-block-plugin_container-block .block .ui-resizable-e {
... ... @@ -37,6 +39,21 @@
37 39 background-image: url(/plugins/container_block/images/handle_w.png);
38 40 }
39 41  
40   -.container-block-plugin_container-block .button-bar .icon-resize {
  42 +.container-block-plugin_container-block .container-block-button-bar .icon-resize {
41 43 background-image: url(/designs/icons/default/Tango/16x16/actions/view-fullscreen.png);
42 44 }
  45 +
  46 +#box-organizer .block .container-block-button-bar {
  47 + right: 0px;
  48 + bottom: 0px;
  49 + height: auto;
  50 +}
  51 +
  52 +#box-organizer .container-block-plugin_container-block:hover .block {
  53 + outline: 1px dashed black;
  54 + outline-offset: -1px;
  55 +}
  56 +
  57 +.container-block-plugin_container-block .block-target {
  58 + background: #afd;
  59 +}
... ...
plugins/container_block/test/functional/container_block_home_controller_test.rb
... ... @@ -31,6 +31,13 @@ class HomeControllerTest &lt; ActionController::TestCase
31 31 assert_tag :div, :attributes => { :class => 'block container-block-plugin_container-block' }
32 32 end
33 33  
  34 + should 'display block title' do
  35 + @block.title = "Block Title"
  36 + @block.save!
  37 + get :index
  38 + assert_tag :div, :attributes => { :class => 'block container-block-plugin_container-block' }, :descendant => {:tag => 'h3', :attributes => { :class => "block-title"}, :content => @block.title }
  39 + end
  40 +
34 41 should 'display container children' do
35 42 c1 = RawHTMLBlock.create!(:box => @block.container_box, :html => 'child1 content')
36 43 c2 = RawHTMLBlock.create!(:box => @block.container_box, :html => 'child2 content')
... ...
plugins/container_block/test/unit/block_test.rb
... ... @@ -1,31 +0,0 @@
1   -require 'test_helper'
2   -
3   -class BlockTest < ActiveSupport::TestCase
4   -
5   - def setup
6   - @environment = fast_create(Environment)
7   - @box = Box.create!(:owner => @environment)
8   - @container = ContainerBlockPlugin::ContainerBlock.create!(:box => @box)
9   - end
10   -
11   - should 'return environment box if block owner is not a ContainerBlock' do
12   - block = Block.create!(:box => @box)
13   - assert_equal @box, block.box
14   - end
15   -
16   - should 'return container box if block owner is a ContainerBlock' do
17   - block = Block.create!(:box => @container.container_box)
18   - assert_equal @container.container_box, block.box
19   - end
20   -
21   - should 'return block owner if block onwer is not a ContainerBlock' do
22   - block = Block.create!(:box => @box)
23   - assert_equal @environment, block.owner
24   - end
25   -
26   - should 'return environment as owner if block onwer is a ContainerBlock' do
27   - block = Block.create!(:box => @container.container_box)
28   - assert_equal @environment, block.owner
29   - end
30   -
31   -end
plugins/container_block/test/unit/container_block_plugin/container_block_test.rb
... ... @@ -20,6 +20,11 @@ class ContainerBlockPlugin::ContainerBlockTest &lt; ActiveSupport::TestCase
20 20 assert @block.container_box_id
21 21 end
22 22  
  23 + should 'created box should have nil as position' do
  24 + @block.save!
  25 + assert_equal nil, @block.container_box.position
  26 + end
  27 +
23 28 should 'return created box' do
24 29 @block.save!
25 30 assert @block.container_box
... ... @@ -89,4 +94,27 @@ class ContainerBlockPlugin::ContainerBlockTest &lt; ActiveSupport::TestCase
89 94 end
90 95 end
91 96  
  97 + should 'not mess up with boxes positions when destroyed' do
  98 + env = fast_create(Environment)
  99 + box1 = fast_create(Box, :owner_id => env.id, :owner_type => 'Environment', :position => 1)
  100 + box2 = fast_create(Box, :owner_id => env.id, :owner_type => 'Environment', :position => 2)
  101 + box3 = fast_create(Box, :owner_id => env.id, :owner_type => 'Environment', :position => 3)
  102 + block = ContainerBlockPlugin::ContainerBlock.create!(:box => box1)
  103 + block.destroy
  104 + assert_equal [1, 2, 3], [box1.reload.position, box2.reload.position, box3.reload.position]
  105 + end
  106 +
  107 + should 'be able to change box' do
  108 + @block.save!
  109 + @block.box = Box.new(:owner => Environment.default)
  110 + @block.save!
  111 + end
  112 +
  113 + should 'not able to change box to be the same as container_box' do
  114 + @block.save!
  115 + @block.box = @block.container_box
  116 + @block.save
  117 + assert @block.errors.invalid?(:box_id)
  118 + end
  119 +
92 120 end
... ...
plugins/container_block/test/unit/environment_test.rb
... ... @@ -1,32 +0,0 @@
1   -require 'test_helper'
2   -
3   -class EnvironmentTest < ActiveSupport::TestCase
4   -
5   - def setup
6   - @environment = fast_create(Environment)
7   -
8   - @box = Box.create!(:owner => @environment)
9   - @block = Block.create!(:box => @box)
10   -
11   - @container = ContainerBlockPlugin::ContainerBlock.create!(:box => @box)
12   - end
13   -
14   - should 'return blocks as usual' do
15   - assert_equal [@block, @container], @environment.blocks
16   - end
17   -
18   - should 'return blocks with container children' do
19   - child = Block.create!(:box => @container.container_box)
20   - assert_equal [@block, @container, child], @environment.blocks
21   - end
22   -
23   - should 'return block with id at find method' do
24   - assert_equal @block, @environment.blocks.find(@block.id)
25   - end
26   -
27   - should 'return child block with id at find method' do
28   - child = Block.create!(:box => @container.container_box)
29   - assert_equal child, @environment.blocks.find(child.id)
30   - end
31   -
32   -end
plugins/container_block/test/unit/profile_test.rb
... ... @@ -1,32 +0,0 @@
1   -require 'test_helper'
2   -
3   -class ProfileTest < ActiveSupport::TestCase
4   -
5   - def setup
6   - @profile = fast_create(Profile)
7   -
8   - @box = Box.create!(:owner => @profile)
9   - @block = Block.create!(:box => @box)
10   -
11   - @container = ContainerBlockPlugin::ContainerBlock.create!(:box => @box)
12   - end
13   -
14   - should 'return blocks as usual' do
15   - assert_equal [@block, @container], @profile.blocks
16   - end
17   -
18   - should 'return blocks with container children' do
19   - child = Block.create!(:box => @container.container_box)
20   - assert_equal [@block, @container, child], @profile.blocks
21   - end
22   -
23   - should 'return block with id at find method' do
24   - assert_equal @block, @profile.blocks.find(@block.id)
25   - end
26   -
27   - should 'return child block with id at find method' do
28   - child = Block.create!(:box => @container.container_box)
29   - assert_equal child, @profile.blocks.find(child.id)
30   - end
31   -
32   -end
plugins/container_block/views/blocks/container.rhtml
1 1 <% edit_mode = @controller.send(:boxes_editor?) && @controller.send(:uses_design_blocks?) %>
2 2 <% box_decorator = edit_mode ? self : BoxesHelper::DontMoveBlocks %>
3 3  
  4 +<%= block_title(block.title) %>
4 5  
5 6 <div class="box" id="box-<%= block.container_box.id %>">
6 7 <%= display_box_content(block.container_box, nil) %>
... ... @@ -15,8 +16,18 @@
15 16 </style>
16 17  
17 18 <% if edit_mode %>
18   - <div class="button-bar">
19   - <a href="#" onclick="toggleMoveContainerChildren(<%= block.id %>, <%= block.container_box.id %>); return false;" class="button icon-resize" title=<%= _('Resize blocks').to_json %>></a>
  19 +
  20 + <script>
  21 + jQuery("#block-<%= block.id %>").hover(
  22 + function() {
  23 + enableMoveContainerChildren(<%= block.id %>, <%= block.container_box.id %>);
  24 + }, function() {
  25 + disableMoveContainerChildren(<%= block.id %>, <%= block.container_box.id %>);
  26 + }
  27 + );
  28 + </script>
  29 +
  30 + <div class="container-block-button-bar button-bar">
20 31 <%= link_to_remote '', :url => { :controller => @controller.boxes_holder.kind_of?(Environment) ? 'container_block_plugin_admin' : 'container_block_plugin_myprofile', :action => 'saveWidths', :id => block.id },
21 32 :with => "containerChildrenWidth(#{block.id}, #{block.container_box.id})",
22 33 :html => {:class => "button icon-save container_block_save", :id => "container_block_save_#{block.id}", :title => _('Save') },
... ... @@ -24,37 +35,4 @@
24 35 :loaded => "close_loading();",
25 36 :complete => "display_notice(request.responseText);"%>
26 37 </div>
27   -
28   - <script>
29   - function toggleMoveContainerChildren(container, box) {
30   - var div = jQuery('#box-'+box+' > .block-outer > .block');
31   - var targetDiv = jQuery('#box-'+box+' .block-outer .block-target');
32   - if(div.is('.ui-resizable')) {
33   - targetDiv.show();
34   - div.find("a").die("click");
35   - div.resizable('destroy');
36   - } else {
37   - targetDiv.hide();
38   - div.find("a").live("click", function(e) {
39   - e.preventDefault();
40   - });
41   - div.resizable({
42   - handles: 'e, w',
43   - containment: '#block-'+container+' .block-inner-2',
44   - resize: function( event, ui ) {
45   - ui.element.height('auto');
46   - }
47   - });
48   - }
49   - }
50   -
51   - function containerChildrenWidth(container, box) {
52   - widths = "";
53   - jQuery('#box-'+box+' > .block-outer > .block').each(function(i) {
54   - childId = jQuery(this).attr('id').match(/block-(\d+)/)[1];
55   - widths+=childId+","+jQuery(this).width()+"|";
56   - });
57   - return "widths="+widths;
58   - }
59   - </script>
60 38 <% end %>
... ...
plugins/require_auth_to_comment/public/hide_comment_form.js
1 1 (function($) {
2 2 $(window).bind('userDataLoaded', function(event, data) {
3   - if (data.login || $('meta[name=profile.allow_unauthenticated_comments]').length > 0) {
  3 + if (data.login || $('meta[name="profile.allow_unauthenticated_comments"]').length > 0) {
4 4 $('.post-comment-button').livequery(function() {
5 5 $(this).show();
6 6 });
... ... @@ -8,7 +8,7 @@
8 8 $(this).show();
9 9 });
10 10 $('.comment-footer').livequery(function() {
11   - $(this).show();
  11 + $(this).show();
12 12 });
13 13 }
14 14 });
... ...
public/stylesheets/application.css
  1 +/* browser fixes */
  2 +
  3 +img:-moz-broken {
  4 + -moz-force-broken-image-icon:1;
  5 +}
  6 +
  7 +/* general styles */
  8 +
1 9 body {
2 10 padding: 0px;
3 11 margin: 0px;
... ... @@ -1727,8 +1735,8 @@ a.button.disabled, input.disabled {
1727 1735 display: none;
1728 1736 }
1729 1737  
1730   -#box-organizer .block:focus .button-bar,
1731   -#box-organizer .block:hover .button-bar {
  1738 +#box-organizer .block-outer:focus .button-bar,
  1739 +#box-organizer .block-outer:hover .button-bar {
1732 1740 display: block;
1733 1741 }
1734 1742  
... ...
test/functional/profile_themes_controller_test.rb
... ... @@ -310,4 +310,23 @@ class ProfileThemesControllerTest &lt; ActionController::TestCase
310 310 assert_no_tag :content => "Select theme"
311 311 end
312 312  
  313 + should 'not duplicate themes that are included by the user and by the environment' do
  314 + t1 = Theme.create('theme1')
  315 + t2 = Theme.create('theme2')
  316 + Environment.any_instance.stubs('themes').returns([t1,t2])
  317 + Theme.stubs(:approved_themes).returns([t2])
  318 +
  319 + get :index, :profile => "testinguser"
  320 + assert_equivalent [t1, t2], assigns(:themes)
  321 + end
  322 +
  323 + should 'sort themes by name' do
  324 + t1 = Theme.create('bill-theme')
  325 + t2 = Theme.create('ana-theme')
  326 + Theme.stubs(:approved_themes).returns([t1,t2])
  327 +
  328 + get :index, :profile => "testinguser"
  329 + assert_equal [t2, t1], assigns(:themes)
  330 + end
  331 +
313 332 end
... ...
test/functional/users_controller_test.rb
... ... @@ -107,6 +107,21 @@ class UsersControllerTest &lt; ActionController::TestCase
107 107 assert_equal false, u.activated?
108 108 end
109 109  
  110 + should 'order users by name' do
  111 + create_user('jeremy')
  112 + create_user('bill')
  113 + create_user('ana')
  114 + create_user('creed')
  115 + get :index
  116 +
  117 + assert_order ['ana', 'bill', 'creed', 'jeremy'], assigns(:collection).map(&:name)
  118 + end
  119 +
  120 + should 'set filter to all_users by default' do
  121 + get :index
  122 + assert_equal 'all_users', assigns(:filter)
  123 + end
  124 +
110 125 should 'response as XML to export users' do
111 126 get :download, :format => 'xml'
112 127 assert_equal 'text/xml', @response.content_type
... ...
test/test_helper.rb
... ... @@ -177,6 +177,19 @@ class ActiveSupport::TestCase
177 177 assert !tag, "expected no tag #{options.inspect}, but tag found in #{text.inspect}"
178 178 end
179 179  
  180 + def assert_order(reference, original)
  181 + original.each do |value|
  182 + if reference.include?(value)
  183 + if reference.first == value
  184 + reference.shift
  185 + else
  186 + assert false, "'#{value}' was found before it should be on: #{original.inspect}"
  187 + end
  188 + end
  189 + end
  190 + assert reference.blank?, "The following elements are not in the collection: #{reference.inspect}"
  191 + end
  192 +
180 193 # For models that render views (blocks, articles, ...)
181 194 def render(*args)
182 195 view_paths = @explicit_view_paths || ActionController::Base.view_paths
... ...
test/unit/array_core_ext_test.rb 0 → 100644
... ... @@ -0,0 +1,11 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +# tests for Array core extension. See lib/noosfero/core_ext/array.rb
  4 +class StringCoreExtTest < ActiveSupport::TestCase
  5 +
  6 + should 'allow uniq by a block' do
  7 + array = [0,1,2,3,4,5,6]
  8 + assert_equal [0,1], array.uniq_by {|number| number%2 }
  9 + end
  10 +
  11 +end
... ...
test/unit/box_test.rb
... ... @@ -140,4 +140,11 @@ class BoxTest &lt; ActiveSupport::TestCase
140 140 assert !blocks.include?('box-test_plugin-block')
141 141 end
142 142  
  143 + should 'list only boxes with a postion greater than zero' do
  144 + profile = fast_create(Profile)
  145 + box = fast_create(Box, :owner_id => profile.id, :owner_type => 'Profile', :position => 0)
  146 + box2 = fast_create(Box, :owner_id => profile.id, :owner_type => 'Profile', :position => 1)
  147 + assert_equal [box2], profile.boxes.with_position
  148 + end
  149 +
143 150 end
... ...
test/unit/boxes_helper_test.rb
... ... @@ -13,7 +13,8 @@ class BoxesHelperTest &lt; ActiveSupport::TestCase
13 13  
14 14 should 'include profile-specific header' do
15 15 holder = mock
16   - holder.stubs(:boxes).returns([])
  16 + holder.stubs(:boxes).returns(boxes = [])
  17 + boxes.stubs(:with_position).returns([])
17 18 holder.stubs(:boxes_limit).returns(0)
18 19 holder.stubs(:custom_header_expanded).returns('my custom header')
19 20 @controller.stubs(:boxes_holder).returns(holder)
... ... @@ -23,7 +24,8 @@ class BoxesHelperTest &lt; ActiveSupport::TestCase
23 24  
24 25 should 'include profile-specific footer' do
25 26 holder = mock
26   - holder.stubs(:boxes).returns([])
  27 + holder.stubs(:boxes).returns(boxes = [])
  28 + boxes.stubs(:with_position).returns([])
27 29 holder.stubs(:boxes_limit).returns(0)
28 30 holder.stubs(:custom_footer_expanded).returns('my custom footer')
29 31 @controller.stubs(:boxes_holder).returns(holder)
... ...
test/unit/comment_test.rb
... ... @@ -285,6 +285,37 @@ class CommentTest &lt; ActiveSupport::TestCase
285 285 assert_equal [c1,c3], c.reload.children
286 286 end
287 287  
  288 + should "return activities comments as a thread" do
  289 + person = fast_create(Person)
  290 + a = TextileArticle.create!(:profile => person, :name => 'My article', :body => 'Article body')
  291 + c0 = Comment.create!(:source => a, :body => 'My comment', :author => person)
  292 + c1 = Comment.create!(:reply_of_id => c0.id, :source => a, :body => 'bla', :author => person)
  293 + c2 = Comment.create!(:reply_of_id => c1.id, :source => a, :body => 'bla', :author => person)
  294 + c3 = Comment.create!(:reply_of_id => c0.id, :source => a, :body => 'bla', :author => person)
  295 + c4 = Comment.create!(:source => a, :body => 'My comment', :author => person)
  296 + result = a.activity.comments
  297 + assert_equal c0, result[0]
  298 + assert_equal [c1, c3], result[0].replies
  299 + assert_equal [c2], result[0].replies[0].replies
  300 + assert_equal c4, result[1]
  301 + assert result[1].replies.empty?
  302 + end
  303 +
  304 + should "return activities comments when some comment on thread is spam and not display its replies" do
  305 + person = fast_create(Person)
  306 + a = TextileArticle.create!(:profile => person, :name => 'My article', :body => 'Article body')
  307 + c0 = Comment.create(:source => a, :body => 'Root comment', :author => person)
  308 + c1 = Comment.create(:reply_of_id => c0.id, :source => a, :body => 'c1', :author => person)
  309 + c2 = Comment.create(:source => a, :body => 'c2', :author => person)
  310 + spam = Comment.create(:spam => true, :reply_of_id => c2.id, :source => a, :body => 'spam', :author => person)
  311 + spam_reply = Comment.create(:reply_of_id => spam.id, :source => a, :body => 'spam reply', :author => person)
  312 + result = a.activity.comments
  313 + assert_equal c0, result[0]
  314 + assert_equal [c1], result[0].replies.without_spam
  315 + assert_equal c2, result[1]
  316 + assert_equal [], result[1].replies.without_spam
  317 + end
  318 +
288 319 should 'provide author url for authenticated user' do
289 320 author = Person.new
290 321 author.expects(:url).returns('http://blabla.net/author')
... ... @@ -389,6 +420,7 @@ class CommentTest &lt; ActiveSupport::TestCase
389 420 end
390 421  
391 422 should 'be able to select non-spam comments' do
  423 + Comment.destroy_all
392 424 c1 = fast_create(Comment)
393 425 c2 = fast_create(Comment, :spam => false)
394 426 c3 = fast_create(Comment, :spam => true)
... ... @@ -660,6 +692,7 @@ class CommentTest &lt; ActiveSupport::TestCase
660 692 end
661 693  
662 694 should 'be able to select non-reply comments' do
  695 + Comment.destroy_all
663 696 c1 = fast_create(Comment)
664 697 c2 = fast_create(Comment, :reply_of_id => c1.id)
665 698 c3 = fast_create(Comment, :reply_of_id => c2.id)
... ...
test/unit/environment_test.rb
... ... @@ -783,6 +783,18 @@ class EnvironmentTest &lt; ActiveSupport::TestCase
783 783 assert role2.valid?
784 784 end
785 785  
  786 + should 'destroy roles when its environment is destroyed' do
  787 + e1 = fast_create(Environment)
  788 + role1 = Role.create!(:name => 'test_role', :environment => e1, :key => 'a_member')
  789 + e2 = fast_create(Environment)
  790 + role2 = Role.create!(:name => 'test_role', :environment => e2, :key => 'a_member')
  791 +
  792 + e2.destroy
  793 +
  794 + assert_nothing_raised {Role.find(role1.id)}
  795 + assert_raise(ActiveRecord::RecordNotFound) {Role.find(role2.id)}
  796 + end
  797 +
786 798 should 'have a help_message_to_add_enterprise attribute' do
787 799 env = Environment.new
788 800  
... ...
test/unit/profile_test.rb
... ... @@ -1461,7 +1461,7 @@ class ProfileTest &lt; ActiveSupport::TestCase
1461 1461 should 'list events by month' do
1462 1462 profile = fast_create(Profile)
1463 1463  
1464   - today = Date.today
  1464 + today = Date.new(2014, 03, 2)
1465 1465 yesterday_event = Event.new(:name => 'Joao Birthday', :start_date => today - 1.day)
1466 1466 today_event = Event.new(:name => 'Ze Birthday', :start_date => today)
1467 1467 tomorrow_event = Event.new(:name => 'Mane Birthday', :start_date => today + 1.day)
... ...
vendor/plugins/action_tracker_has_comments/init.rb
... ... @@ -11,5 +11,6 @@ Rails.configuration.to_prepare do
11 11 type, id = (self.target_type == 'Article' ? ['Article', self.target_id] : [self.class.to_s, self.id])
12 12 "source_type = '#{type}' AND source_id = '#{id}' AND spam IS NOT TRUE AND reply_of_id IS NULL"
13 13 end
  14 +
14 15 end
15 16 end
... ...