From 260f0d799b8520b7de6f9c6c802266e3b1bc052a Mon Sep 17 00:00:00 2001 From: Leandro Nunes dos Santos Date: Wed, 20 Feb 2013 11:15:09 -0300 Subject: [PATCH] Adding macro support for TinyMCE articles and a plugin called CommentGroupMacro that uses the macro support --- app/controllers/public/content_viewer_controller.rb | 9 ++++++--- app/helpers/application_helper.rb | 37 +++++++++++++++++++++++++++++++++---- app/helpers/boxes_helper.rb | 4 ++-- app/helpers/macros_helper.rb | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ app/models/comment.rb | 8 ++++++++ app/models/environment.rb | 4 ++++ app/views/comment/_comment_form.rhtml | 2 ++ app/views/content_viewer/view_page.rhtml | 2 +- app/views/shared/tiny_mce.rhtml | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------ lib/noosfero/plugin.rb | 42 +++++++++++++++++++++++++++++++++++++++--- lib/noosfero/plugin/manager.rb | 14 +++++++++++--- plugins/comment_group_macro/controllers/profile/comment_group_macro_plugin_profile_controller.rb | 16 ++++++++++++++++ plugins/comment_group_macro/db/migrate/20121220201629_add_group_id_to_comment.rb | 9 +++++++++ plugins/comment_group_macro/lib/comment_group_macro_plugin.rb | 44 ++++++++++++++++++++++++++++++++++++++++++++ plugins/comment_group_macro/lib/comment_group_macro_plugin/ext/article.rb | 21 +++++++++++++++++++++ plugins/comment_group_macro/lib/comment_group_macro_plugin/ext/comment.rb | 12 ++++++++++++ plugins/comment_group_macro/public/comment_group.css | 6 ++++++ plugins/comment_group_macro/public/comment_group.js | 47 +++++++++++++++++++++++++++++++++++++++++++++++ plugins/comment_group_macro/public/images/comments.gif | Bin 0 -> 1700 bytes plugins/comment_group_macro/test/functional/comment_group_macro_plugin_profile_controller_test.rb | 38 ++++++++++++++++++++++++++++++++++++++ plugins/comment_group_macro/test/unit/comment_group_macro_plugin_test.rb | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ plugins/comment_group_macro/views/_comment_group.rhtml | 47 +++++++++++++++++++++++++++++++++++++++++++++++ plugins/send_email/lib/send_email_plugin.rb | 4 +++- test/functional/content_viewer_controller_test.rb | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ test/unit/application_helper_test.rb | 40 ++++++++++++++++++++++++++++++++++++++++ test/unit/comment_test.rb | 15 +++++++++++++++ test/unit/macros_helper_test.rb | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ test/unit/plugin_manager_test.rb | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------- test/unit/plugin_test.rb | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 29 files changed, 1007 insertions(+), 56 deletions(-) create mode 100644 app/helpers/macros_helper.rb create mode 100644 plugins/comment_group_macro/controllers/profile/comment_group_macro_plugin_profile_controller.rb create mode 100644 plugins/comment_group_macro/db/migrate/20121220201629_add_group_id_to_comment.rb create mode 100644 plugins/comment_group_macro/lib/comment_group_macro_plugin.rb create mode 100644 plugins/comment_group_macro/lib/comment_group_macro_plugin/ext/article.rb create mode 100644 plugins/comment_group_macro/lib/comment_group_macro_plugin/ext/comment.rb create mode 100644 plugins/comment_group_macro/public/comment_group.css create mode 100644 plugins/comment_group_macro/public/comment_group.js create mode 100644 plugins/comment_group_macro/public/images/comments.gif create mode 100644 plugins/comment_group_macro/test/functional/comment_group_macro_plugin_profile_controller_test.rb create mode 100644 plugins/comment_group_macro/test/unit/comment_group_macro_plugin_test.rb create mode 100644 plugins/comment_group_macro/views/_comment_group.rhtml create mode 100644 test/unit/macros_helper_test.rb diff --git a/app/controllers/public/content_viewer_controller.rb b/app/controllers/public/content_viewer_controller.rb index 6a017fb..bf8089e 100644 --- a/app/controllers/public/content_viewer_controller.rb +++ b/app/controllers/public/content_viewer_controller.rb @@ -98,10 +98,13 @@ class ContentViewerController < ApplicationController session[:notice] = _("Notification of new comments to '%s' was successfully canceled") % params[:email] end end + + @comments = @plugins.dispatch_first(:load_comments, @page) + @comments ||= @page.comments.without_spam.as_thread + @comments = [@comments] unless @comments.is_a?(Array) + + @comments_count = Comment.count_thread(@comments) - comments = @page.comments.without_spam - @comments = comments.as_thread - @comments_count = comments.count if params[:slideshow] render :action => 'slideshow', :layout => 'slideshow' end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 2c3b35a..f1f2326 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -988,10 +988,7 @@ module ApplicationHelper options.merge!(:page => params[:npage]) content = article.to_html(options) content = content.kind_of?(Proc) ? self.instance_eval(&content) : content - @plugins && @plugins.each do |plugin| - content = plugin.parse_content(content) - end - content + filter_html(content, article) end def colorpicker_field(object_name, method, options = {}) @@ -1425,4 +1422,36 @@ module ApplicationHelper @no_design_blocks = true end + def filter_html(html, source) + if @plugins + html = convert_macro(html, source) + end + html + end + + def convert_macro(html, source) + doc = Hpricot(html) + while element = doc.search('.macro').first + macro_name = element['data-macro'] + method_name = "macro_#{macro_name}" + attrs = collect_macro_attributes(element) + plugin_instance = Environment.macros[environment.id][method_name] + if plugin_instance + result = plugin_instance.send(method_name, attrs, element.inner_html, source) + element.inner_html = result.kind_of?(Proc) ? self.instance_eval(&result) : result + element['class'] = "parsed-macro #{macro_name}" + else + element.inner_html = _("Unsupported macro %s!") % macro_name + element['class'] = "failed-macro #{macro_name}" + end + attrs.each {|key, value| element.remove_attribute("data-macro-#{key}")} + end + doc.html + end + + def collect_macro_attributes(element) + element.attributes.to_hash.select {|key, value| key[0..10] == 'data-macro-'}. + inject({}){|result, a| result.merge({a[0][11..-1] => a[1]})}.with_indifferent_access + end + end diff --git a/app/helpers/boxes_helper.rb b/app/helpers/boxes_helper.rb index db9dee7..4835553 100644 --- a/app/helpers/boxes_helper.rb +++ b/app/helpers/boxes_helper.rb @@ -99,8 +99,8 @@ module BoxesHelper unless block.visible? options[:title] = _("This block is invisible. Your visitors will not see it.") end - @controller.send(:content_editor?) || @plugins.each do |plugin| - result = plugin.parse_content(result) + if @controller.send(:content_editor?) + result = filter_html(result, block) end box_decorator.block_target(block.box, block) + content_tag('div', diff --git a/app/helpers/macros_helper.rb b/app/helpers/macros_helper.rb new file mode 100644 index 0000000..73ad966 --- /dev/null +++ b/app/helpers/macros_helper.rb @@ -0,0 +1,96 @@ +module MacrosHelper + + def macros_in_menu + Environment.macros[@environment.id].reject{ |macro_name, plugin_instance| macro_configuration(macro_name)[:icon_path] } + end + + def macros_with_buttons + Environment.macros[@environment.id].reject{ |macro_name, plugin_instance| !macro_configuration(macro_name)[:icon_path] } + end + + def macro_configuration(macro_name) + plugin_instance = Environment.macros[@environment.id][macro_name] + plugin_instance.send("config_#{macro_name}") + end + + def macro_title(macro_name) + macro_configuration(macro_name)[:title] || macro_name.to_s.humanize + end + + def generate_macro_config_dialog(macro_name) + if macro_configuration(macro_name)[:skip_dialog] + "function(){#{macro_generator(macro_name)}}" + else + "function(){ + jQuery('
'+#{macro_configuration_dialog(macro_name).to_json}+'
').dialog({ + title: #{macro_title(macro_name).to_json}, + modal: true, + buttons: [ + {text: #{_('Ok').to_json}, click: function(){ + tinyMCE.activeEditor.execCommand('mceInsertContent', false, + (function(dialog){ #{macro_generator(macro_name)} })(this)); + jQuery(this).dialog('close'); + }}, + {text: #{_('Cancel').to_json}, click: function(){jQuery(this).dialog('close');}} + ] + }); + }" + end + end + + def include_macro_js_files + plugins_javascripts = [] + Environment.macros[environment.id].map do |macro_name, plugin_instance| + if macro_configuration(macro_name)[:js_files] + macro_configuration(macro_name)[:js_files].map { |js| plugins_javascripts << plugin_instance.class.public_path(js) } + end + end + javascript_include_tag(plugins_javascripts, :cache => 'cache/plugins-' + Digest::MD5.hexdigest(plugins_javascripts.to_s)) unless plugins_javascripts.empty? + end + + def macro_css_files + plugins_css = [] + Environment.macros[environment.id].map do |macro_name, plugin_instance| + if macro_configuration(macro_name)[:css_files] + macro_configuration(macro_name)[:css_files].map { |css| plugins_css << plugin_instance.class.public_path(css) } + end + end + plugins_css.join(',') + end + + protected + + def macro_generator(macro_name) + if macro_configuration(macro_name)[:generator] + macro_configuration(macro_name)[:generator] + else + macro_default_generator(macro_name) + end + end + + def macro_default_generator(macro_name) + code = "var params = {};" + configuration = macro_configuration(macro_name) + configuration[:params].map do |field| + code += "params.#{field[:name]} = jQuery('*[name=#{field[:name]}]', dialog).val();" + end + code + " + var html = jQuery('
'+#{macro_title(macro_name).to_json}+'
')[0]; + for(key in params) html.setAttribute('data-macro-'+key,params[key]); + return html.outerHTML; + " + end + + def macro_configuration_dialog(macro_name) + macro_configuration(macro_name)[:params].map do |field| + label_name = field[:label] || field[:name].to_s.humanize + case field[:type] + when 'text' + labelled_form_field(label_name, text_field_tag(field[:name], field[:default])) + when 'select' + labelled_form_field(label_name, select_tag(field[:name], options_for_select(field[:values], field[:default]))) + end + end.join("\n") + end + +end diff --git a/app/models/comment.rb b/app/models/comment.rb index 0671597..56c1754 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -157,6 +157,14 @@ class Comment < ActiveRecord::Base @replies = comments_list end + def self.count_thread(comments) + count = comments.length + comments.each do |c| + count+=count_thread(c.replies) + end + count + end + def self.as_thread result = {} root = [] diff --git a/app/models/environment.rb b/app/models/environment.rb index 77c3f2c..b7afb81 100644 --- a/app/models/environment.rb +++ b/app/models/environment.rb @@ -16,6 +16,10 @@ class Environment < ActiveRecord::Base filename end + class << self + attr_accessor :macros + end + PERMISSIONS['Environment'] = { 'view_environment_admin_panel' => N_('View environment admin panel'), 'edit_environment_features' => N_('Edit environment features'), diff --git a/app/views/comment/_comment_form.rhtml b/app/views/comment/_comment_form.rhtml index a9a8982..d9d43d8 100644 --- a/app/views/comment/_comment_form.rhtml +++ b/app/views/comment/_comment_form.rhtml @@ -89,6 +89,8 @@ function check_captcha(button, confirm_action) { <%= required labelled_form_field(_('Enter your comment'), f.text_area(:body, :rows => 5)) %> <%= f.hidden_field(:reply_of_id) %> + <%= @plugins.dispatch(:comment_form_extra_contents, local_assigns).collect { |content| instance_eval(&content) }.join("") %> + <% button_bar do %> <%= submit_button('add', _('Post comment'), :onclick => "if(check_captcha(this)) { save_comment(this) } else { check_captcha(this, save_comment)};return false;") %> <%= button_to_function :cancel, _('Cancel'), "jQuery.colorbox.close();f=jQuery(this).parents('.post_comment_box'); f.removeClass('opened'); f.addClass('closed'); return false" %> diff --git a/app/views/content_viewer/view_page.rhtml b/app/views/content_viewer/view_page.rhtml index 651d840..dbde281 100644 --- a/app/views/content_viewer/view_page.rhtml +++ b/app/views/content_viewer/view_page.rhtml @@ -91,7 +91,7 @@ <% if @page.accept_comments? || @comments_count > 0 %>

> - <%= number_of_comments(@page) %> + <%= display_number_of_comments(@comments_count) %>

<% end %> diff --git a/app/views/shared/tiny_mce.rhtml b/app/views/shared/tiny_mce.rhtml index 80e0cf0..25d5106 100644 --- a/app/views/shared/tiny_mce.rhtml +++ b/app/views/shared/tiny_mce.rhtml @@ -1,6 +1,8 @@ +<% extend MacrosHelper %> <%= javascript_include_tag 'tinymce/jscripts/tiny_mce/tiny_mce.js' %> +<%= include_macro_js_files %> + + diff --git a/plugins/send_email/lib/send_email_plugin.rb b/plugins/send_email/lib/send_email_plugin.rb index 639f2fe..8e91e03 100644 --- a/plugins/send_email/lib/send_email_plugin.rb +++ b/plugins/send_email/lib/send_email_plugin.rb @@ -12,12 +12,14 @@ class SendEmailPlugin < Noosfero::Plugin true end - def parse_content(raw_content) + def parse_content(args) + raw_content = args[:html] if context.profile raw_content.gsub(/\{sendemail\}/, "/profile/#{context.profile.identifier}/plugins/send_email/deliver") else raw_content.gsub(/\{sendemail\}/, '/plugin/send_email/deliver') end + args.clone.merge({:html => raw_content}) end end diff --git a/test/functional/content_viewer_controller_test.rb b/test/functional/content_viewer_controller_test.rb index fc291c1..50e65dc 100644 --- a/test/functional/content_viewer_controller_test.rb +++ b/test/functional/content_viewer_controller_test.rb @@ -1229,4 +1229,118 @@ class ContentViewerControllerTest < ActionController::TestCase assert_equal 1, assigns(:comments_count) end + should 'add extra content on comment form from plugins' do + class Plugin1 < Noosfero::Plugin + def comment_form_extra_contents(args) + lambda { + hidden_field_tag('comment[some_field_id]', 1) + } + end + end + class Plugin2 < Noosfero::Plugin + def comment_form_extra_contents(args) + lambda { + hidden_field_tag('comment[another_field_id]', 1) + } + end + end + + Environment.default.enable_plugin(Plugin1.name) + Environment.default.enable_plugin(Plugin2.name) + + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') + + get :view_page, :profile => profile.identifier, :page => [ 'myarticle' ] + + assert_tag :tag => 'input', :attributes => {:name => 'comment[some_field_id]', :type => 'hidden'} + assert_tag :tag => 'input', :attributes => {:name => 'comment[another_field_id]', :type => 'hidden'} + end + + should 'collect comments as plugin definition' do + class Plugin1 < Noosfero::Plugin + def load_comments(page) + [page.comments.find(4)] + end + end + Environment.default.enable_plugin(Plugin1.name) + Comment.delete_all + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') + page.comments.build(:author => profile, :title => 'hi', :body => 'hello 1' ).save! + page.comments.build(:author => profile, :title => 'hi', :body => 'hello 2' ).save! + page.comments.build(:author => profile, :title => 'hi', :body => 'hello 3' ).save! + c = page.comments.build(:author => profile, :title => 'hi', :body => 'hello 4' ) + c.save! + + + get :view_page, :profile => profile.identifier, :page => [ 'myarticle' ] + + assert_equal [c], assigns(:comments) + end + + should 'not be a problem if loaded comments of plugins not be an array' do + class Plugin1 < Noosfero::Plugin + def load_comments(page) + page.comments.find(4) + end + end + Environment.default.enable_plugin(Plugin1.name) + Comment.delete_all + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') + page.comments.build(:author => profile, :title => 'hi', :body => 'hello 1' ).save! + page.comments.build(:author => profile, :title => 'hi', :body => 'hello 2' ).save! + page.comments.build(:author => profile, :title => 'hi', :body => 'hello 3' ).save! + c = page.comments.build(:author => profile, :title => 'hi', :body => 'hello 4' ) + c.save! + + + get :view_page, :profile => profile.identifier, :page => [ 'myarticle' ] + + assert_equal [c], assigns(:comments) + end + + + should 'take in consideration only the first plugin comments definition' do + class Plugin1 < Noosfero::Plugin + def load_comments(page) + page.comments.first + end + end + class Plugin2 < Noosfero::Plugin + def load_comments(page) + page.comments.last + end + end + Environment.default.enable_plugin(Plugin1.name) + Environment.default.enable_plugin(Plugin2.name) + + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') + c1 = page.comments.build(:author => profile, :title => 'hi', :body => 'hello 1' ) + c1.save! + page.comments.build(:author => profile, :title => 'hi', :body => 'hello 2' ).save! + page.comments.build(:author => profile, :title => 'hi', :body => 'hello 3' ).save! + c2 = page.comments.build(:author => profile, :title => 'hi', :body => 'hello 4' ) + c2.save! + + get :view_page, :profile => profile.identifier, :page => [ 'myarticle' ] + + assert_equal [c1], assigns(:comments) + end + + should 'empty array of comments collected by plugin make the comments variable be an empty array' do + class Plugin1 < Noosfero::Plugin + def load_comments(page) + [] + end + end + Environment.default.enable_plugin(Plugin1.name) + + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') + page.comments.build(:author => profile, :title => 'hi', :body => 'hello 1' ).save! + page.comments.build(:author => profile, :title => 'hi', :body => 'hello 2' ).save! + + + get :view_page, :profile => profile.identifier, :page => [ 'myarticle' ] + + assert_equal [], assigns(:comments) + end end diff --git a/test/unit/application_helper_test.rb b/test/unit/application_helper_test.rb index 0efbddf..0bc7d74 100644 --- a/test/unit/application_helper_test.rb +++ b/test/unit/application_helper_test.rb @@ -3,6 +3,7 @@ require File.dirname(__FILE__) + '/../test_helper' class ApplicationHelperTest < ActiveSupport::TestCase include ApplicationHelper + include Noosfero::Plugin::HotSpot def setup self.stubs(:session).returns({}) @@ -657,6 +658,45 @@ class ApplicationHelperTest < ActiveSupport::TestCase assert_not_nil add_zoom_to_images end + should 'parse macros' do + class Plugin1 < Noosfero::Plugin + def macro_test1(params, inner_html, source) + 'Test1' + end + def macro_test2(params, inner_html, source) + 'Test2' + end + + def macro_methods + ['macro_test1', 'macro_test2'] + end + end + + @environment = Environment.default + Environment.macros = {@environment.id => {}} + context = mock() + context.stubs(:environment).returns(@environment) + Plugin1.new(context) + html = ' +
+
+
+ ' + parsed_html = convert_macro(html, mock()) + parsed_divs = Hpricot(parsed_html).search('div') + expected_divs = Hpricot(' +
Test1
+
Test2
+
Unsupported macro unexistent!
+ ').search('div') + + # comparing div attributes between parsed and expected html + parsed_divs.each_with_index do |div, i| + assert_equal expected_divs[i].attributes.to_hash, div.attributes.to_hash + assert_equal expected_divs[i].inner_text, div.inner_text + end + end + protected include NoosferoTestHelper diff --git a/test/unit/comment_test.rb b/test/unit/comment_test.rb index 5791f4c..9975669 100644 --- a/test/unit/comment_test.rb +++ b/test/unit/comment_test.rb @@ -571,6 +571,21 @@ class CommentTest < ActiveSupport::TestCase SpammerLogger.clean_log end + should 'count a thread of comments' do + Comment.delete_all + comments = [] + comments.push(create_comment) + c1 = create_comment + comments.push(c1) + create_comment(:reply_of_id => c1.id) + create_comment(:reply_of_id => c1.id) + c2 = create_comment + comments.push(c2) + create_comment(:reply_of_id => c2.id) + + assert_equal 6, Comment.count_thread(comments) + end + private def create_comment(args = {}) diff --git a/test/unit/macros_helper_test.rb b/test/unit/macros_helper_test.rb new file mode 100644 index 0000000..382614b --- /dev/null +++ b/test/unit/macros_helper_test.rb @@ -0,0 +1,124 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class MacrosHelperTest < ActiveSupport::TestCase + include MacrosHelper + include ApplicationHelper + include ActionView::Helpers::FormOptionsHelper + include ActionView::Helpers::FormTagHelper + include ActionView::Helpers::TagHelper + + CONFIG = { + :params => [ + { :name => :identifier, :type => 'text'}, + { :name => :size, :type => 'select', + :values => [ + [_('Big'), :big], + [_('Icon'), :icon], + [_('Minor'), :minor], + [_('Portrait'), :portrait], + [_('Thumb'), :thumb] + ], + :default => :portrait + } + ], + :title => _('Profile Image Link') + } + + should 'generate html for macro configuration' do + @environment = Environment.default + Environment.macros = {} + macros = Environment.macros[@environment.id] = {} + plugin_instance = mock + plugin_instance.stubs('config_macro_example').returns(CONFIG) + macros['macro_example'] = plugin_instance + html = macro_configuration_dialog('macro_example') + assert_tag_in_string html, :tag => 'label', :content => _('Identifier') + assert_tag_in_string html, :tag => 'input', :attributes => {:name => 'identifier'} + assert_tag_in_string html, :tag => 'label', :content => 'size'.humanize + assert_tag_in_string html, :tag => 'select', :attributes => {:name => 'size'}, :descendant => {:tag => 'option', :attributes => {:value => 'big'}, :content => _('Big')} + assert_tag_in_string html, :tag => 'select', :attributes => {:name => 'size'}, :descendant => {:tag => 'option', :attributes => {:value => 'icon'}, :content => _('Icon')} + assert_tag_in_string html, :tag => 'select', :attributes => {:name => 'size'}, :descendant => {:tag => 'option', :attributes => {:value => 'minor'}, :content => _('Minor')} + assert_tag_in_string html, :tag => 'select', :attributes => {:name => 'size'}, :descendant => {:tag => 'option', :attributes => {:value => 'portrait', :selected => true}, :content => _('Portrait')} + assert_tag_in_string html, :tag => 'select', :attributes => {:name => 'size'}, :descendant => {:tag => 'option', :attributes => {:value => 'thumb'}, :content => _('Thumb')} + end + + should 'get macro title' do + @environment = Environment.default + Environment.macros = {} + macros = Environment.macros[@environment.id] = {} + plugin_instance = mock + plugin_instance.stubs('config_macro_example').returns(CONFIG) + macros['macro_example'] = plugin_instance + title = macro_title('macro_example') + assert _('Profile Image Link'), title + end + + should 'get only macros in menu' do + @environment = Environment.default + Environment.macros = {} + macros = Environment.macros[@environment.id] = {} + plugin_instance = mock + plugin_instance.stubs('config_macro_example').returns({}) + macros['macro_example'] = plugin_instance + plugin_instance_other = mock + plugin_instance_other.stubs('config_macro_example_other').returns({:icon_path => 'icon.png'}) + macros['macro_example_other'] = plugin_instance_other + assert_equal [plugin_instance], macros_in_menu.values + end + + should 'get only macros with buttons' do + @environment = Environment.default + Environment.macros = {} + macros = Environment.macros[@environment.id] = {} + plugin_instance = mock + plugin_instance.stubs('config_macro_example').returns({}) + macros['macro_example'] = plugin_instance + plugin_instance_other = mock + plugin_instance_other.stubs('config_macro_example_other').returns({:icon_path => 'icon.png'}) + macros['macro_example_other'] = plugin_instance_other + assert_equal [plugin_instance_other], macros_with_buttons.values + end + + should 'skip macro config dialog and call generator directly' do + @environment = Environment.default + Environment.macros = {} + macros = Environment.macros[@environment.id] = {} + plugin_instance = mock + plugin_instance.stubs('config_macro_example').returns({:skip_dialog => true, :generator => '', :params => [] }) + macros['macro_example'] = plugin_instance + assert_equal 'function(){}', generate_macro_config_dialog('macro_example') + end + + should 'include js files' do + @environment = Environment.default + Environment.macros = {} + macros = Environment.macros[@environment.id] = {} + plugin_instance = mock + plugin_instance.stubs('config_macro_example').returns({:js_files => 'macro.js' }) + plugin_instance.class.stubs(:public_path).with('macro.js').returns('macro.js') + macros['macro_example'] = plugin_instance + assert_equal '', include_macro_js_files + end + + should 'get macro css files' do + @environment = Environment.default + Environment.macros = {} + macros = Environment.macros[@environment.id] = {} + plugin_instance = mock + plugin_instance.stubs('config_macro_example').returns({:css_files => 'macro.css' }) + plugin_instance.class.stubs(:public_path).with('macro.css').returns('macro.css') + macros['macro_example'] = plugin_instance + assert_equal 'macro.css', macro_css_files + end + + should 'get macro specific generator' do + @environment = Environment.default + Environment.macros = {} + macros = Environment.macros[@environment.id] = {} + plugin_instance = mock + plugin_instance.stubs('config_macro_example').returns({:generator => 'macro_generator' }) + macros['macro_example'] = plugin_instance + assert_equal 'macro_generator', macro_generator('macro_example') + end + +end diff --git a/test/unit/plugin_manager_test.rb b/test/unit/plugin_manager_test.rb index 0da0348..3199a35 100644 --- a/test/unit/plugin_manager_test.rb +++ b/test/unit/plugin_manager_test.rb @@ -2,22 +2,12 @@ require File.dirname(__FILE__) + '/../test_helper' class PluginManagerTest < ActiveSupport::TestCase + include Noosfero::Plugin::HotSpot + def setup @environment = Environment.default - @controller = mock() - @controller.stubs(:profile).returns() - @controller.stubs(:request).returns() - @controller.stubs(:response).returns() - @controller.stubs(:params).returns() - @manager = Noosfero::Plugin::Manager.new(@environment, @controller) end attr_reader :environment - attr_reader :manager - - should 'give access to environment and context' do - assert_same @environment, @manager.environment - assert_same @controller, @manager.context - end should 'return the intersection between environment\'s enabled plugins and system available plugins' do class Plugin1 < Noosfero::Plugin; end; @@ -26,8 +16,8 @@ class PluginManagerTest < ActiveSupport::TestCase class Plugin4 < Noosfero::Plugin; end; environment.stubs(:enabled_plugins).returns([Plugin1.to_s, Plugin2.to_s, Plugin4.to_s]) Noosfero::Plugin.stubs(:all).returns([Plugin1.to_s, Plugin3.to_s, Plugin4.to_s]) - plugins = manager.enabled_plugins.map { |instance| instance.class.to_s } - assert_equal [Plugin1.to_s, Plugin4.to_s], plugins + results = plugins.enabled_plugins.map { |instance| instance.class.to_s } + assert_equal [Plugin1.to_s, Plugin4.to_s], results end should 'map events to registered plugins' do @@ -55,8 +45,62 @@ class PluginManagerTest < ActiveSupport::TestCase p1 = Plugin1.new p2 = Plugin2.new - assert_equal [p1.random_event, p2.random_event], manager.dispatch(:random_event) + assert_equal [p1.random_event, p2.random_event], plugins.dispatch(:random_event) + end + + should 'dispatch_first method returns the first plugin response if there is many plugins to responde the event' do + + class Plugin1 < Noosfero::Plugin + def random_event + 'Plugin 1 action.' + end + end + + class Plugin2 < Noosfero::Plugin + def random_event + 'Plugin 2 action.' + end + end + + class Plugin3 < Noosfero::Plugin + def random_event + 'Plugin 3 action.' + end + end + + environment.stubs(:enabled_plugins).returns([Plugin1.to_s, Plugin2.to_s, Plugin3.to_s]) + p1 = Plugin1.new + + assert_equal p1.random_event, plugins.dispatch_first(:random_event) end + should 'dispatch_first method returns the first plugin response if there is many plugins to responde the event and the first one respond nil' do + + class Plugin1 < Noosfero::Plugin + def random_event + nil + end + end + + class Plugin2 < Noosfero::Plugin + def random_event + 'Plugin 2 action.' + end + end + + class Plugin3 < Noosfero::Plugin + def random_event + 'Plugin 3 action.' + end + end + + environment.stubs(:enabled_plugins).returns([Plugin1.to_s, Plugin2.to_s, Plugin3.to_s]) + + p2 = Plugin2.new + + assert_equal p2.random_event, plugins.dispatch_first(:random_event) + end + + end diff --git a/test/unit/plugin_test.rb b/test/unit/plugin_test.rb index b16e4cc..d548b21 100644 --- a/test/unit/plugin_test.rb +++ b/test/unit/plugin_test.rb @@ -7,6 +7,8 @@ class PluginTest < ActiveSupport::TestCase end attr_reader :environment + include Noosfero::Plugin::HotSpot + should 'keep the list of all loaded subclasses' do class Plugin1 < Noosfero::Plugin end @@ -26,4 +28,59 @@ class PluginTest < ActiveSupport::TestCase assert_equal({:controller => 'plugin_test/plugin1_admin', :action => 'index'}, Plugin1.admin_url) end + should 'register its macros in the environment when instantiated' do + class Plugin1 < Noosfero::Plugin + def macro_example1(params, inner_html, source) + end + + def example2(params, inner_html, source) + end + + def not_macro + end + + def macro_methods + ['macro_example1', 'example2'] + end + end + + Environment.macros = {} + Environment.macros[environment.id] = {} + macros = Environment.macros[environment.id] + context = mock() + context.stubs(:environment).returns(environment) + + plugin_instance = Plugin1.new(context) + + assert_equal plugin_instance, macros['macro_example1'] + assert_equal plugin_instance, macros['example2'] + assert_nil macros['not_macro'] + end + + should 'load_comments return nil by default' do + + class Plugin1 < Noosfero::Plugin; end; + + environment.stubs(:enabled_plugins).returns([Plugin1.to_s]) + + profile = fast_create(Profile, :name => 'test profile', :identifier => 'test_profile') + a = fast_create(Article, :name => 'my article', :profile_id => profile.id) + assert_nil plugins.dispatch_first(:load_comments, a) + end + + should 'load_comments return the value defined by plugin' do + + class Plugin1 < Noosfero::Plugin + def load_comments(page) + 'some value' + end + end + + environment.stubs(:enabled_plugins).returns([Plugin1.to_s]) + + profile = fast_create(Profile, :name => 'test profile', :identifier => 'test_profile') + a = fast_create(Article, :name => 'my article', :profile_id => profile.id) + assert_equal 'some value', plugins.dispatch_first(:load_comments, a) + end + end -- libgit2 0.21.2