require "spec_helper" [NestedForm::Builder, NestedForm::SimpleBuilder, defined?(NestedForm::FormtasticBuilder) ? NestedForm::FormtasticBuilder : nil].compact.each do |builder| describe builder do let(:project) do Project.new end let(:template) do template = ActionView::Base.new template.output_buffer = "" template end context "with no options" do subject do builder.new(:item, project, template, {}, proc {}) end describe '#link_to_add' do it "behaves similar to a Rails link_to" do subject.link_to_add("Add", :tasks).should == 'Add' subject.link_to_add("Add", :tasks, :class => "foo", :href => "url").should == 'Add' subject.link_to_add(:tasks) { "Add" }.should == 'Add' end context 'when missing association is provided' do it 'raises Argument error' do expect{ subject.link_to_add('Add', :bugs) }.to raise_error(ArgumentError, 'Failed to find Project association by name "bugs"') end end end describe '#link_to_remove' do it "behaves similar to a Rails link_to" do subject.link_to_remove("Remove").should == 'Remove' subject.link_to_remove("Remove", :class => "foo", :href => "url").should == 'Remove' subject.link_to_remove { "Remove" }.should == 'Remove' end it 'has data-association attribute' do project.tasks.build subject.fields_for(:tasks, :builder => builder) do |tf| tf.link_to_remove 'Remove' end.should match 'Remove' end context 'when association is declared in a model by the class_name' do it 'properly detects association name' do project.assignments.build subject.fields_for(:assignments, :builder => builder) do |tf| tf.link_to_remove 'Remove' end.should match 'Remove' end end context 'when there is more than one nested level' do it 'properly detects association name' do task = project.tasks.build task.milestones.build subject.fields_for(:tasks, :builder => builder) do |tf| tf.fields_for(:milestones, :builder => builder) do |mf| mf.link_to_remove 'Remove' end end.should match 'Remove' end end end describe '#fields_for' do it "wraps nested fields each in a div with class" do 2.times { project.tasks.build } subject.fields_for(:tasks) do "Task" end.should == '
Task
Task
' end end it "wraps nested fields marked for destruction with an additional class" do task = project.tasks.build task.mark_for_destruction fields = subject.fields_for(:tasks) { 'Task' } fields.should eq('
Task
') end it "puts blueprint into data-blueprint attribute" do task = project.tasks.build task.mark_for_destruction subject.fields_for(:tasks) { 'Task' } subject.link_to_add('Add', :tasks) output = template.send(:after_nested_form_callbacks) expected = ERB::Util.html_escape '
Task
' output.should match(/div.+data-blueprint="#{expected}"/) end it "adds parent association name to the blueprint div id" do task = project.tasks.build task.milestones.build subject.fields_for(:tasks, :builder => builder) do |tf| tf.fields_for(:milestones, :builder => builder) { 'Milestone' } tf.link_to_add('Add', :milestones) end output = template.send(:after_nested_form_callbacks) output.should match(/div.+id="tasks_milestones_fields_blueprint"/) end it "doesn't render wrapper div" do task = project.tasks.build fields = subject.fields_for(:tasks, :wrapper => false) { 'Task' } fields.should eq('Task') subject.link_to_add 'Add', :tasks output = template.send(:after_nested_form_callbacks) output.should match(/div.+data-blueprint="Task"/) end end context "with options" do subject { builder.new(:item, project, template, {}, proc {}) } context "when model_object given" do it "should use it instead of new generated" do subject.fields_for(:tasks) {|f| f.object.name } subject.link_to_add("Add", :tasks, :model_object => Task.new(:name => 'for check')) output = template.send(:after_nested_form_callbacks) expected = ERB::Util.html_escape '
for check
' output.should match(/div.+data-blueprint="#{expected}"/) end end end end end