require File.dirname(__FILE__) + '/spec_helper' describe Resourceful::Builder, " applied without any modification" do include ControllerMocks before :each do mock_kontroller create_builder end it "should remove all resourceful actions" do @kontroller.expects(:send).with do |name, action_module| name == :include && (action_module.instance_methods & Resourceful::ACTIONS.map(&:to_s)).empty? end @builder.apply end it "shouldn't un-hide any actions" do @builder.apply @kontroller.hidden_actions.should == Resourceful::ACTIONS end it "shouldn't set any callbacks" do @builder.apply callbacks.should == {:before => {}, :after => {}} end it "shouldn't set any responses" do @builder.apply responses.should be_empty end it "shouldn't set any parents" do @builder.apply parents.should be_empty end it "should set the controller as made_resourceful" do @builder.apply @kontroller.made_resourceful.should be_true end it "should set load_parent_object as a before_action for no actions" do @kontroller.expects(:before_action).with(:load_parent_object, :only => []) @builder.apply end end describe Resourceful::Builder, " with some actions set" do include ControllerMocks before :each do mock_kontroller create_builder @actions = [:show, :index, :new, :create] @builder.actions *@actions end it "should include the given actions" do @kontroller.expects(:send).with do |name, action_module| name == :include && (action_module.instance_methods & Resourceful::ACTIONS.map(&:to_s)).sort == @actions.map(&:to_s).sort end @builder.apply end it "should un-hide the given actions" do @builder.apply (@kontroller.hidden_actions & @actions).should be_empty end it "should set load_parent_object as a before_action for the given actions" do @kontroller.expects(:before_action).with(:load_parent_object, :only => [:show, :index, :new, :create]) @builder.apply end end describe Resourceful::Builder, " with all actions set for a plural controller" do include ControllerMocks before :each do mock_kontroller @kontroller.class_eval { def plural?; true; end } create_builder @builder.actions :all end it "should include all actions" do @kontroller.expects(:send).with do |name, action_module| name == :include && (action_module.instance_methods & Resourceful::ACTIONS.map(&:to_s)).sort == Resourceful::ACTIONS.map(&:to_s).sort end @builder.apply end end describe Resourceful::Builder, " with all actions set for a singular controller" do include ControllerMocks before :each do mock_kontroller @kontroller.class_eval { def plural?; false; end } create_builder @builder.actions :all end it "should include all singular actions" do @kontroller.expects(:send).with do |name, action_module| name == :include && (action_module.instance_methods & Resourceful::ACTIONS.map(&:to_s)).sort == Resourceful::SINGULAR_ACTIONS.map(&:to_s).sort end @builder.apply end end describe Resourceful::Builder, " with several before and after callbacks set" do include ControllerMocks before :each do mock_kontroller create_builder @builder.before(:create, :update, 'destroy', &(should_be_called { times(3) })) @builder.after('index', &should_be_called) @builder.after(:update, &should_be_called) @builder.apply end it "should save the callbacks as the :resourceful_callbacks inheritable_attribute" do callbacks[:before][:create].each(&:call) callbacks[:before][:update].each(&:call) callbacks[:before][:destroy].each(&:call) callbacks[:after][:index].each(&:call) callbacks[:after][:update].each(&:call) end end describe Resourceful::Builder, " with chained before and after callbacks" do include ControllerMocks before :each do mock_kontroller create_builder @before_value = '' @builder.before(:index, &lambda { @before_value += 'A' }) @builder.before(:index, &lambda { @before_value += 'B' }) @after_value = '' @builder.after(:index, &lambda { @after_value += 'A' }) @builder.after(:index, &lambda { @after_value += 'B' }) @builder.apply end it "should save as array in the :resourceful_callbacks inheritable_attribute and execute in order" do callbacks[:before][:index].each { |callback| callback.call } @before_value.should == 'AB' callbacks[:after][:index].each { |callback| callback.call } @after_value.should == 'AB' end end describe Resourceful::Builder, " with responses set for several formats" do include ControllerMocks before :each do mock_kontroller create_builder @builder.response_for('create') do |f| f.html(&should_be_called) f.js(&should_be_called) f.yaml(&should_be_called) f.xml(&should_be_called) f.txt(&should_be_called) end @builder.response_for(:remove_failed, 'update') do |f| f.yaml(&(should_be_called { times(2) })) f.png(&(should_be_called { times(2) })) end @builder.apply end it "should save the responses as the :resourceful_responses inheritable_attribute" do responses[:create].map(&:first).should == [:html, :js, :yaml, :xml, :txt] responses[:create].map(&:last).each(&:call) responses[:remove_failed].map(&:first).should == [:yaml, :png] responses[:remove_failed].map(&:last).each(&:call) responses[:update].map(&:first).should == [:yaml, :png] responses[:update].map(&:last).each(&:call) end end describe Resourceful::Builder, " with a response set for the default format" do include ControllerMocks before :each do mock_kontroller create_builder @builder.response_for('index', &should_be_called) @builder.apply end it "should save the response as a response for HTML in the :resourceful_responses inheritable_attribute" do responses[:index].map(&:first).should == [:html] responses[:index].map(&:last).each(&:call) end end describe Resourceful::Builder, " with a response set for no actions" do include ControllerMocks before :each do mock_kontroller create_builder end it "should raise an error" do lambda { @builder.response_for {} }.should raise_error("Must specify one or more actions for response_for.") end end describe Resourceful::Builder, " publishing without an attributes hash" do include ControllerMocks before :each do mock_kontroller create_builder end it "should raise an error" do proc { @builder.publish :xml, :yaml }.should raise_error("Must specify :attributes option") end end describe Resourceful::Builder, " publishing several formats" do include ControllerMocks before :each do mock_kontroller create_builder @model = stub_model("Thing") @kontroller.stubs(:current_object).returns(@model) @models = (1..5).map { stub_model("Thing") } @kontroller.stubs(:current_objects).returns(@models) @builder.publish :yaml, :json, 'xml', :additional => 'option', :attributes => [:name, :stuff] @builder.apply end it "should add a list of types as responses for index and show" do responses[:index].map(&:first).should == [:yaml, :json, :xml] responses[:show].map(&:first).should == [:yaml, :json, :xml] end it "should respond by rendering the serialized model with the proper type, passing along un-recognized options" do @model.expects(:serialize).with(:yaml, :additional => 'option', :attributes => [:name, :stuff]).returns('serialized') @kontroller.expects(:render).with(:text => 'serialized') @kontroller.instance_eval(&responses[:index].find { |type, _| type == :yaml }[1]) end it "should respond render XML and JSON with the proper action" do @model.expects(:serialize).with(:xml, :additional => 'option', :attributes => [:name, :stuff]).returns('XML serialized') @model.expects(:serialize).with(:json, :additional => 'option', :attributes => [:name, :stuff]).returns('JSON serialized') @kontroller.expects(:render).with(:xml => 'XML serialized') @kontroller.expects(:render).with(:json => 'JSON serialized') @kontroller.instance_eval(&responses[:index].find { |type, _| type == :xml }[1]) @kontroller.instance_eval(&responses[:index].find { |type, _| type == :json }[1]) end it "should render current_objects if the action is plural" do @kontroller.stubs(:plural_action?).returns(true) @models.expects(:serialize).with(:yaml, :additional => 'option', :attributes => [:name, :stuff]).returns('serialized') @kontroller.expects(:render).with(:text => 'serialized') @kontroller.instance_eval(&responses[:index].find { |type, _| type == :yaml }[1]) end end describe Resourceful::Builder, " publishing only to #show" do include ControllerMocks before :each do mock_kontroller create_builder @model = stub_model("Thing") @kontroller.stubs(:current_object).returns(@model) @builder.publish :json, :yaml, :only => :show, :attributes => [:name, :stuff] @builder.apply end it "should add responses for show" do responses[:show].map(&:first).should == [:json, :yaml] end it "shouldn't add responses for index" do responses[:index].should be_nil end it "shouldn't pass the :only option to the serialize call" do @model.expects(:serialize).with(:yaml, :attributes => [:name, :stuff]) @kontroller.stubs(:render) @kontroller.instance_eval(&responses[:show].find { |type, _| type == :yaml }[1]) end end describe Resourceful::Builder, " publishing in addition to other responses" do include ControllerMocks before :each do mock_kontroller create_builder @builder.response_for(:index) {} @builder.publish :json, :yaml, :attributes => [:name, :stuff] @builder.response_for :show do |f| f.html {} f.js {} end @builder.apply end it "should add published responses in addition to pre-existing ones" do responses[:show].map(&:first).should == [:html, :js, :json, :yaml] responses[:index].map(&:first).should == [:html, :json, :yaml] end end describe Resourceful::Builder, " belonging to several parents" do include ControllerMocks before :each do mock_kontroller create_builder @builder.belongs_to :post, :blat, :stang @builder.apply end it "should save the parents as the :parents inheritable_attribute" do parents.should == ['post', 'blat', 'stang'] end end