Commit 71015018b67f3a77c8876cace01c60fb581d81f0
1 parent
1f128345
Exists in
master
and in
29 other branches
r222@sede: terceiro | 2007-07-28 15:54:13 -0300
ActionItem0: implementing a better interface for the old flexible_template git-svn-id: https://svn.colivre.coop.br/svn/noosfero/trunk@226 3f533792-8f58-4932-b0fe-aaf55b0a4547
Showing
15 changed files
with
318 additions
and
0 deletions
Show diff stats
| ... | ... | @@ -0,0 +1,22 @@ |
| 1 | +require 'rake' | |
| 2 | +require 'rake/testtask' | |
| 3 | +require 'rake/rdoctask' | |
| 4 | + | |
| 5 | +desc 'Default: run unit tests.' | |
| 6 | +task :default => :test | |
| 7 | + | |
| 8 | +desc 'Test the design plugin.' | |
| 9 | +Rake::TestTask.new(:test) do |t| | |
| 10 | + t.libs << 'lib' | |
| 11 | + t.pattern = 'test/**/*_test.rb' | |
| 12 | + t.verbose = true | |
| 13 | +end | |
| 14 | + | |
| 15 | +desc 'Generate documentation for the design plugin.' | |
| 16 | +Rake::RDocTask.new(:rdoc) do |rdoc| | |
| 17 | + rdoc.rdoc_dir = 'rdoc' | |
| 18 | + rdoc.title = 'Design' | |
| 19 | + rdoc.options << '--line-numbers' << '--inline-source' | |
| 20 | + rdoc.rdoc_files.include('README') | |
| 21 | + rdoc.rdoc_files.include('lib/**/*.rb') | |
| 22 | +end | ... | ... |
| ... | ... | @@ -0,0 +1,25 @@ |
| 1 | +require 'design' | |
| 2 | + | |
| 3 | +class ActionController::Base | |
| 4 | + | |
| 5 | + # Declares that this controller uses design plugin to generate its layout. | |
| 6 | + # See the plugin README for options that can be passed to this method. | |
| 7 | + def self.design(config = {}) | |
| 8 | + if (config.has_key?(:holder) && config.has_key?(:fixed)) || (!config.has_key?(:holder) && !config.has_key?(:fixed)) | |
| 9 | + raise ArgumentError.new("You must supply either <tt>:holder</tt> or <tt>:fixed</tt> to design.") | |
| 10 | + end | |
| 11 | + | |
| 12 | + @design_plugin_config = config | |
| 13 | + | |
| 14 | + include Design | |
| 15 | + end | |
| 16 | + | |
| 17 | + # declares this controller as a design editor, including in it all the | |
| 18 | + # functionalities to do that (besides those for using a design). Accepts the | |
| 19 | + # same options as design. | |
| 20 | + def self.design_editor(config = {}) | |
| 21 | + self.design(config) | |
| 22 | + include Design::Editor | |
| 23 | + end | |
| 24 | + | |
| 25 | +end | ... | ... |
| ... | ... | @@ -0,0 +1 @@ |
| 1 | +# Install hook code here | ... | ... |
| ... | ... | @@ -0,0 +1,29 @@ |
| 1 | +require 'design/fixed_design_holder' | |
| 2 | +require 'design/proxy_design_holder' | |
| 3 | + | |
| 4 | +require 'design/helper' | |
| 5 | +require 'design/editor' | |
| 6 | + | |
| 7 | +module Design | |
| 8 | + | |
| 9 | + # gets the Design object for this controller | |
| 10 | + def design | |
| 11 | + @design_plugin_data ||= Hash.new | |
| 12 | + data = @design_plugin_data | |
| 13 | + | |
| 14 | + return data[:design] if data.has_key?(:design) | |
| 15 | + | |
| 16 | + config = self.class.instance_variable_get("@design_plugin_config") | |
| 17 | + | |
| 18 | + if config.has_key?(:holder) | |
| 19 | + holder_variable_name = config[:holder] | |
| 20 | + data[:design] = Design::ProxyDesignHolder.new(self.instance_variable_get("@#{holder_variable_name}")) | |
| 21 | + else | |
| 22 | + options = (config[:fixed].kind_of? Hash) ? config[:fixed] : {} | |
| 23 | + data[:design] = Design::FixedDesignHolder.new(options) | |
| 24 | + end | |
| 25 | + | |
| 26 | + data[:design] # redundant, but makes more clear the return value | |
| 27 | + end | |
| 28 | + protected :design | |
| 29 | +end | ... | ... |
| ... | ... | @@ -0,0 +1,25 @@ |
| 1 | +module Design | |
| 2 | + | |
| 3 | + class FixedDesignHolder | |
| 4 | + attr_reader :template, :theme, :icon_theme, :boxes | |
| 5 | + def initialize(options = {}) | |
| 6 | + @template = options[:template] || 'default' | |
| 7 | + @theme = options[:theme] || 'default' | |
| 8 | + @icon_theme = options[:icon_theme] || 'default' | |
| 9 | + @boxes = options[:boxes] || default_boxes | |
| 10 | + end | |
| 11 | + | |
| 12 | + # creates some default boxes | |
| 13 | + def default_boxes | |
| 14 | + box1 = Box.new | |
| 15 | + box2 = Box.new | |
| 16 | + box2.blocks << MainBlock.new | |
| 17 | + box3 = Box.new | |
| 18 | + | |
| 19 | + [box1, box2, box3] | |
| 20 | + end | |
| 21 | + private :default_boxes | |
| 22 | + end | |
| 23 | + | |
| 24 | +end | |
| 25 | + | ... | ... |
| ... | ... | @@ -0,0 +1,43 @@ |
| 1 | +module Design | |
| 2 | + | |
| 3 | + # This class uses an external holder object to hold the details of the | |
| 4 | + # design, and proxies all access to the template data to it. This object can | |
| 5 | + # be any object that responds to the following methods: | |
| 6 | + # | |
| 7 | + # * +template+ | |
| 8 | + # * +template=+ | |
| 9 | + # * +theme+ | |
| 10 | + # * +theme=+ | |
| 11 | + # * +icon_theme+ | |
| 12 | + # * +icon_theme=+ | |
| 13 | + # * +boxes+ | |
| 14 | + # * +boxes=+ | |
| 15 | + # | |
| 16 | + # These methods must implement get/set semantics for atrributes with their | |
| 17 | + # names, and can be implemented with +attr_accessor+, as ActiveRecord | |
| 18 | + # columns, or event explicity by writing the methods and storing the values | |
| 19 | + # wherever you want. | |
| 20 | + # | |
| 21 | + # +template+, +theme+ and +icon_theme+ must return (and accept in the | |
| 22 | + # setters) strings, while +boxes+ must be an array of Box objects. | |
| 23 | + class ProxyDesignHolder | |
| 24 | + | |
| 25 | + attr_reader :holder | |
| 26 | + | |
| 27 | + # creates a new proxy for +holder+ | |
| 28 | + def initialize(holder) | |
| 29 | + @holder = holder | |
| 30 | + end | |
| 31 | + | |
| 32 | + # proxies all calls to +template+, +theme+, +icon_theme+ and +boxes+ (as | |
| 33 | + # well as their setters counterparts) to the holder object | |
| 34 | + def method_missing(method_id, *args) | |
| 35 | + if method_id.to_s =~ /^(template|theme|icon_theme|boxes)=?$/ | |
| 36 | + holder.send(method_id, *args) | |
| 37 | + else | |
| 38 | + raise NoMethodError.new("Design has no method \"#{method_id}\"") | |
| 39 | + end | |
| 40 | + end | |
| 41 | + end | |
| 42 | + | |
| 43 | +end | ... | ... |
| ... | ... | @@ -0,0 +1,24 @@ |
| 1 | +require File.join(File.dirname(__FILE__), 'test_helper') | |
| 2 | + | |
| 3 | +class FixedDesignHolderTest < Test::Unit::TestCase | |
| 4 | + | |
| 5 | + def test_design_should_include_design_module | |
| 6 | + assert FixedDesignTestController.included_modules.include?(Design) | |
| 7 | + end | |
| 8 | + | |
| 9 | + def test_design_editor_should_include_design_and_design_editor_module | |
| 10 | + assert DesignEditorTestController.included_modules.include?(Design) | |
| 11 | + assert DesignEditorTestController.included_modules.include?(Design::Editor) | |
| 12 | + end | |
| 13 | + | |
| 14 | + def test_should_not_accept_no_holder_and_no_fixed | |
| 15 | + assert_raise ArgumentError do | |
| 16 | + DesignEditorTestController.design | |
| 17 | + end | |
| 18 | + end | |
| 19 | + def test_should_not_accept_both_holder_and_fixed | |
| 20 | + assert_raise ArgumentError do | |
| 21 | + DesignEditorTestController.design :holder => 'something', :fixed => true end | |
| 22 | + end | |
| 23 | + | |
| 24 | +end | ... | ... |
| ... | ... | @@ -0,0 +1,53 @@ |
| 1 | +require File.join(File.dirname(__FILE__), 'test_helper') | |
| 2 | + | |
| 3 | +class FixedDesignHolderTest < Test::Unit::TestCase | |
| 4 | + | |
| 5 | + include Design | |
| 6 | + | |
| 7 | + def test_explicit_design | |
| 8 | + controller = FixedDesignTestController.new | |
| 9 | + assert_kind_of Design::FixedDesignHolder, controller.design | |
| 10 | + assert_equal 'some_template', controller.design.template | |
| 11 | + assert_equal 'some_theme', controller.design.theme | |
| 12 | + assert_equal 'some_icon_theme', controller.design.icon_theme | |
| 13 | + assert_equal [FixedDesignTestController::BOX1, FixedDesignTestController::BOX2, FixedDesignTestController::BOX3], controller.design.boxes | |
| 14 | + end | |
| 15 | + | |
| 16 | + def test_explicit_design_should_have_sensible_defaults | |
| 17 | + controller = FixedDesignDefaultTestController.new | |
| 18 | + assert_kind_of Design::FixedDesignHolder, controller.design | |
| 19 | + assert_equal 'default', controller.design.template | |
| 20 | + assert_equal 'default', controller.design.theme | |
| 21 | + assert_equal 'default', controller.design.icon_theme | |
| 22 | + assert_kind_of Array, controller.design.boxes | |
| 23 | + assert_equal 3, controller.design.boxes.size | |
| 24 | + end | |
| 25 | + | |
| 26 | + def test_should_not_be_able_to_assign_template | |
| 27 | + # FixedDesignHolder does not implement assigment, on purpose | |
| 28 | + assert_raise NoMethodError do | |
| 29 | + FixedDesignHolder.new.template = 'break' | |
| 30 | + end | |
| 31 | + end | |
| 32 | + | |
| 33 | + def test_should_not_be_able_to_assign_theme | |
| 34 | + # FixedDesignHolder does not implement assigment, on purpose | |
| 35 | + assert_raise NoMethodError do | |
| 36 | + FixedDesignHolder.new.theme = 'break' | |
| 37 | + end | |
| 38 | + end | |
| 39 | + | |
| 40 | + def test_should_not_be_able_to_assign_icon_theme | |
| 41 | + assert_raise NoMethodError do | |
| 42 | + FixedDesignHolder.new.icon_theme = 'break' | |
| 43 | + end | |
| 44 | + end | |
| 45 | + | |
| 46 | + def test_should_not_be_able_to_assign_boxes | |
| 47 | + assert_raise NoMethodError do | |
| 48 | + FixedDesignHolder.new.boxes = [] | |
| 49 | + end | |
| 50 | + end | |
| 51 | + | |
| 52 | + | |
| 53 | +end | ... | ... |
| ... | ... | @@ -0,0 +1,32 @@ |
| 1 | +require File.join(File.dirname(__FILE__), 'test_helper') | |
| 2 | + | |
| 3 | + | |
| 4 | +class ProxyDesignHolderTest < Test::Unit::TestCase | |
| 5 | + | |
| 6 | + # FIXME: rewrite this test with mocha | |
| 7 | + def test_design_should_interact_with_sample_holder | |
| 8 | + design = Design::ProxyDesignHolder.new(SampleHolderForTestingProxyDesignHolder.new) | |
| 9 | + design.template = 'bli' | |
| 10 | + assert_equal 'bli', design.template | |
| 11 | + design.theme = 'bli' | |
| 12 | + assert_equal 'bli', design.theme | |
| 13 | + design.icon_theme = 'bli' | |
| 14 | + assert_equal 'bli', design.icon_theme | |
| 15 | + design.boxes = [] | |
| 16 | + assert_equal [], design.boxes | |
| 17 | + end | |
| 18 | + | |
| 19 | + def test_design_user_controller_should_get_a_proper_design | |
| 20 | + controller = ProxyDesignHolderTestController.new | |
| 21 | + design = controller.send(:design) | |
| 22 | + design.template = 'bli' | |
| 23 | + assert_equal 'bli', design.template | |
| 24 | + design.theme = 'bli' | |
| 25 | + assert_equal 'bli', design.theme | |
| 26 | + design.icon_theme = 'bli' | |
| 27 | + assert_equal 'bli', design.icon_theme | |
| 28 | + design.boxes = [] | |
| 29 | + assert_equal [], design.boxes | |
| 30 | + end | |
| 31 | + | |
| 32 | +end | ... | ... |
| ... | ... | @@ -0,0 +1,44 @@ |
| 1 | +ENV["RAILS_ENV"] = "test" | |
| 2 | +require File.expand_path(File.dirname(__FILE__) + "/../../../../config/environment") | |
| 3 | + | |
| 4 | +require 'test/unit' | |
| 5 | + | |
| 6 | +######################## | |
| 7 | +# test clases below here | |
| 8 | +######################## | |
| 9 | + | |
| 10 | +class FixedDesignTestController < ActionController::Base | |
| 11 | + | |
| 12 | + BOX1 = Box.new | |
| 13 | + BOX2 = Box.new | |
| 14 | + BOX3 = Box.new | |
| 15 | + | |
| 16 | + design :fixed => { | |
| 17 | + :template => 'some_template', | |
| 18 | + :theme => 'some_theme', | |
| 19 | + :icon_theme => 'some_icon_theme', | |
| 20 | + :boxes => [ BOX1, BOX2, BOX3 ], | |
| 21 | + } | |
| 22 | +end | |
| 23 | + | |
| 24 | +class FixedDesignDefaultTestController < ActionController::Base | |
| 25 | + design :fixed => true | |
| 26 | +end | |
| 27 | + | |
| 28 | +class SampleHolderForTestingProxyDesignHolder | |
| 29 | + attr_accessor :template, :theme, :icon_theme, :boxes | |
| 30 | +end | |
| 31 | + | |
| 32 | +class ProxyDesignHolderTestController < ActionController::Base | |
| 33 | + design :holder => 'sample_object' | |
| 34 | + def initialize | |
| 35 | + @sample_object = SampleHolderForTestingProxyDesignHolder.new | |
| 36 | + end | |
| 37 | +end | |
| 38 | + | |
| 39 | +class DesignEditorTestController < ActionController::Base | |
| 40 | + design_editor :holder => 'sample_object' | |
| 41 | + def initialize | |
| 42 | + @sample_object = SampleHolderForTestingProxyDesignHolder.new | |
| 43 | + end | |
| 44 | +end | ... | ... |
| ... | ... | @@ -0,0 +1 @@ |
| 1 | +# Uninstall hook code here | ... | ... |