spec/formtastic_spec.rb in nofxx-formtastic-0.1.8 vs spec/formtastic_spec.rb in nofxx-formtastic-0.1.9

- old
+ new

@@ -234,10 +234,14 @@ @new_post.stub!(:title) @new_post.stub!(:body) @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :string, :limit => 255)) end + after do + Formtastic::SemanticFormHelper.builder = Formtastic::SemanticFormBuilder + end + it "can be overridden" do class CustomFormBuilder < Formtastic::SemanticFormBuilder def custom(arg1, arg2, options = {}) [arg1, arg2, options] @@ -285,10 +289,107 @@ output_buffer.should have_tag('form fieldset.inputs #post_author_1_login_input') output_buffer.should_not have_tag('form fieldset.inputs #post[author]_1_login_input') end end + describe '#label' do + it 'should humanize the given attribute' do + semantic_form_for(@new_post) do |builder| + builder.label(:login).should have_tag('label', :with => /Login/) + end + end + + it 'should be printed as span' do + semantic_form_for(@new_post) do |builder| + builder.label(:login, nil, { :required => true, :as_span => true }).should have_tag('span.label abbr') + end + end + + describe 'when required is given' do + it 'should append a required note' do + semantic_form_for(@new_post) do |builder| + builder.label(:login, nil, :required => true).should have_tag('label abbr') + end + end + + it 'should allow require option to be given as second argument' do + semantic_form_for(@new_post) do |builder| + builder.label(:login, :required => true).should have_tag('label abbr') + end + end + end + + describe 'when label is given' do + it 'should allow the text to be given as label option' do + semantic_form_for(@new_post) do |builder| + builder.label(:login, :required => true, :label => 'My label').should have_tag('label', :with => /My label/) + end + end + + it 'should return nil if label is false' do + semantic_form_for(@new_post) do |builder| + builder.label(:login, :label => false).should be_nil + end + end + end + end + + describe '#errors_on' do + before(:each) do + @title_errors = ['must not be blank', 'must be longer than 10 characters', 'must be awesome'] + @errors = mock('errors') + @errors.stub!(:on).with('title').and_return(@title_errors) + @errors.stub!(:on).with('body').and_return(nil) + @new_post.stub!(:errors).and_return(@errors) + end + + describe 'and the errors will be displayed as a sentence' do + it 'should render a paragraph with the errors joined into a sentence' do + Formtastic::SemanticFormBuilder.inline_errors = :sentence + semantic_form_for(@new_post) do |builder| + builder.errors_on(:title).should have_tag('p.inline-errors', @title_errors.to_sentence) + end + end + end + + describe 'and the errors will be displayed as a list' do + it 'should render an unordered list with the class errors' do + Formtastic::SemanticFormBuilder.inline_errors = :list + semantic_form_for(@new_post) do |builder| + builder.errors_on(:title).should have_tag('ul.errors') + end + end + + it 'should include a list element for each of the errors within the unordered list' do + Formtastic::SemanticFormBuilder.inline_errors = :list + semantic_form_for(@new_post) do |builder| + @title_errors.each do |error| + builder.errors_on(:title).should have_tag('ul.errors li', error) + end + end + end + end + + describe 'but the errors will not be shown' do + it 'should return nil' do + Formtastic::SemanticFormBuilder.inline_errors = :none + semantic_form_for(@new_post) do |builder| + builder.errors_on(:title).should be_nil + end + end + end + + describe 'and no error is found on the method' do + it 'should return nil' do + Formtastic::SemanticFormBuilder.inline_errors = :sentence + semantic_form_for(@new_post) do |builder| + builder.errors_on(:body).should be_nil + end + end + end + end + describe '#input' do before do @new_post.stub!(:title) @new_post.stub!(:body) @@ -538,10 +639,14 @@ default_input_type(:integer).should == :numeric default_input_type(:float).should == :numeric default_input_type(:decimal).should == :numeric end + it 'should default to :country for :string columns named country' do + default_input_type(:string, :country).should == :country + end + describe 'defaulting to file column' do Formtastic::SemanticFormBuilder.file_methods.each do |method| it "should default to :file for attributes that respond to ##{method}" do @new_post.stub!(:column_for_attribute).and_return(nil) column = mock('column') @@ -560,11 +665,11 @@ end end it 'should call the corresponding input method' do - [:select, :time_zone, :radio, :date, :datetime, :time, :boolean].each do |input_style| + [:select, :time_zone, :radio, :date, :datetime, :time, :boolean, :check_boxes, :hidden].each do |input_style| @new_post.stub!(:generic_column_name) @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :string, :limit => 255)) semantic_form_for(@new_post) do |builder| builder.should_receive(:"#{input_style}_input").once.and_return("fake HTML output from #input") concat(builder.input(:generic_column_name, :as => input_style)) @@ -647,10 +752,34 @@ end end end + describe ':size option' do + describe 'when provided' do + it 'should be passed down to the input tag' do + semantic_form_for(@new_post) do |builder| + concat(builder.input(:title, :size => 17)) + end + output_buffer.should have_tag('form li input#post_title[@size=17]') + end + end + + describe 'when not provided' do + it 'should default to the configured default text size' do + # Temporarily rewrite the value so that we know the output size isn't just a coincidence + old_value = Formtastic::SemanticFormBuilder.default_text_field_size + Formtastic::SemanticFormBuilder.default_text_field_size = 31 + semantic_form_for(@new_post) do |builder| + concat(builder.input(:title)) + end + Formtastic::SemanticFormBuilder.default_text_field_size = old_value + output_buffer.should have_tag('form li input#post_title[@size=31]') + end + end + end + describe ':wrapper_html option' do describe 'when provided' do it 'should be passed down to the li tag' do semantic_form_for(@new_post) do |builder| @@ -700,11 +829,10 @@ end output_buffer.should have_tag('form li', :count => 2) end describe 'when there are errors on the object for this method' do - before do @title_errors = ['must not be blank', 'must be longer than 10 characters', 'must be awesome'] @errors = mock('errors') @errors.stub!(:on).with('title').and_return(@title_errors) @new_post.stub!(:errors).and_return(@errors) @@ -722,69 +850,28 @@ concat(builder.input(:title)) end output_buffer.should_not have_tag('div.fieldWithErrors') end - describe 'and the errors will be displayed as a sentence' do - - before do - Formtastic::SemanticFormBuilder.inline_errors = :sentence - semantic_form_for(@new_post) do |builder| - concat(builder.input(:title)) - end + it 'should render a paragraph for the errors' do + Formtastic::SemanticFormBuilder.inline_errors = :sentence + semantic_form_for(@new_post) do |builder| + concat(builder.input(:title)) end - - it 'should render a paragraph with the errors joined into a sentence' do - output_buffer.should have_tag('form li.error p.inline-errors', @title_errors.to_sentence) - end - + output_buffer.should have_tag('form li.error p.inline-errors') end - describe 'and the errors will be displayed as a list' do - - before do - Formtastic::SemanticFormBuilder.inline_errors = :list - semantic_form_for(@new_post) do |builder| - concat(builder.input(:title)) - end + it 'should not display an error list' do + Formtastic::SemanticFormBuilder.inline_errors = :list + semantic_form_for(@new_post) do |builder| + concat(builder.input(:title)) end - - it 'should render an unordered list with the class errors' do - output_buffer.should have_tag('form li.error ul.errors') - end - - it 'should include a list element for each of the errors within the unordered list' do - @title_errors.each do |error| - output_buffer.should have_tag('form li.error ul.errors li', error) - end - end - + output_buffer.should have_tag('form li.error ul.errors') end - - describe 'but the errors will not be shown' do - - before do - Formtastic::SemanticFormBuilder.inline_errors = :none - semantic_form_for(@new_post) do |builder| - concat(builder.input(:title)) - end - end - - it 'should not display an error sentence' do - output_buffer.should_not have_tag('form li.error p.inline-errors') - end - - it 'should not display an error list' do - output_buffer.should_not have_tag('form li.error ul.errors') - end - - end - end describe 'when there are no errors on the object for this method' do - before do semantic_form_for(@new_post) do |builder| concat(builder.input(:title)) end end @@ -798,15 +885,13 @@ end it 'should not display an error list' do output_buffer.should_not have_tag('form li.error ul.errors') end - end describe 'when no object is provided' do - before do semantic_form_for(:project, :url => 'http://test.host') do |builder| concat(builder.input(:title)) end end @@ -820,11 +905,10 @@ end it 'should not display an error list' do output_buffer.should_not have_tag('form li.error ul.errors') end - end end # Test string_mappings: :string, :password and :numeric string_mappings = Formtastic::SemanticFormBuilder::INPUT_MAPPINGS.slice(*Formtastic::SemanticFormBuilder::STRING_MAPPINGS) @@ -987,34 +1071,69 @@ output_buffer.should have_tag("form li #{input_type}.myclass") end end - it 'should generate input and labels even if no object is given' do - semantic_form_for(:project, :url => 'http://test.host/') do |builder| - concat(builder.input(:title, :as => type)) + describe 'when no object is given' do + before(:each) do + semantic_form_for(:project, :url => 'http://test.host/') do |builder| + concat(builder.input(:title, :as => type)) + end end - output_buffer.should have_tag('form li label') - output_buffer.should have_tag('form li label[@for="project_title"') - output_buffer.should have_tag('form li label', /Title/) + it 'should generate input' do + if template_method.to_s =~ /_field$/ # password_field + output_buffer.should have_tag("form li input") + output_buffer.should have_tag("form li input#project_title") + output_buffer.should have_tag("form li input[@type=\"#{input_type}\"]") + output_buffer.should have_tag("form li input[@name=\"project[title]\"]") + else + output_buffer.should have_tag("form li #{input_type}") + output_buffer.should have_tag("form li #{input_type}#project_title") + output_buffer.should have_tag("form li #{input_type}[@name=\"project[title]\"]") + end + end - if template_method.to_s =~ /_field$/ # password_field - output_buffer.should have_tag("form li input") - output_buffer.should have_tag("form li input#project_title") - output_buffer.should have_tag("form li input[@type=\"#{input_type}\"]") - output_buffer.should have_tag("form li input[@name=\"project[title]\"]") - else - output_buffer.should have_tag("form li #{input_type}") - output_buffer.should have_tag("form li #{input_type}#project_title") - output_buffer.should have_tag("form li #{input_type}[@name=\"project[title]\"]") + it 'should generate labels' do + output_buffer.should have_tag('form li label') + output_buffer.should have_tag('form li label[@for="project_title"') + output_buffer.should have_tag('form li label', /Title/) end end end end + describe ":as => :hidden" do + before do + @new_post.stub!(:hidden) + @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :string)) + + semantic_form_for(@new_post) do |builder| + concat(builder.input(:hidden, :as => :hidden)) + end + end + + it "should have a hidden class on the wrapper" do + output_buffer.should have_tag('form li.hidden') + end + + it 'should have a post_hidden_input id on the wrapper' do + output_buffer.should have_tag('form li#post_hidden_input') + end + + it 'should not generate a label for the input' do + output_buffer.should_not have_tag('form li label') + end + + it "should generate a input field" do + output_buffer.should have_tag("form li input#post_hidden") + output_buffer.should have_tag("form li input[@type=\"hidden\"]") + output_buffer.should have_tag("form li input[@name=\"post[hidden]\"]") + end + end + describe ":as => :time_zone" do before do @new_post.stub!(:time_zone) @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :string)) @@ -1048,31 +1167,114 @@ concat(builder.input(:time_zone, :input_html => { :class => 'myclass' })) end output_buffer.should have_tag("form li select.myclass") end - it 'should generate input and labels even if no object is given' do - semantic_form_for(:project, :url => 'http://test.host/') do |builder| - concat(builder.input(:time_zone, :as => :time_zone)) + describe 'when no object is given' do + before(:each) do + semantic_form_for(:project, :url => 'http://test.host/') do |builder| + concat(builder.input(:time_zone, :as => :time_zone)) + end end - output_buffer.should have_tag('form li label') - output_buffer.should have_tag('form li label[@for="project_time_zone"') - output_buffer.should have_tag('form li label', /Time zone/) + it 'should generate labels' do + output_buffer.should have_tag('form li label') + output_buffer.should have_tag('form li label[@for="project_time_zone"') + output_buffer.should have_tag('form li label', /Time zone/) + end - output_buffer.should have_tag("form li select") - output_buffer.should have_tag("form li select#project_time_zone") - output_buffer.should have_tag("form li select[@name=\"project[time_zone]\"]") + it 'should generate select inputs' do + output_buffer.should have_tag("form li select") + output_buffer.should have_tag("form li select#project_time_zone") + output_buffer.should have_tag("form li select[@name=\"project[time_zone]\"]") + end end end + describe ":as => :country" do + + before do + @new_post.stub!(:country) + @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :string)) + end + + describe "when country_select is not available as a helper from a plugin" do + + it "should raise an error, sugesting the author installs a plugin" do + lambda { + semantic_form_for(@new_post) do |builder| + concat(builder.input(:country, :as => :country)) + end + }.should raise_error + end + + end + + describe "when country_select is available as a helper (from a plugin)" do + + before do + semantic_form_for(@new_post) do |builder| + builder.stub!(:country_select).and_return("<select><option>...</option></select>") + concat(builder.input(:country, :as => :country)) + end + end + + it "should have a time_zone class on the wrapper" do + output_buffer.should have_tag('form li.country') + end + + it 'should have a post_title_input id on the wrapper' do + output_buffer.should have_tag('form li#post_country_input') + end + + it 'should generate a label for the input' do + output_buffer.should have_tag('form li label') + output_buffer.should have_tag('form li label[@for="post_country"') + output_buffer.should have_tag('form li label', /Country/) + end + + it "should generate a select" do + output_buffer.should have_tag("form li select") + end + + end + + describe ":priority_countries option" do + + it "should be passed down to the country_select helper when provided" do + priority_countries = ["Foo", "Bah"] + semantic_form_for(@new_post) do |builder| + builder.stub!(:country_select).and_return("<select><option>...</option></select>") + builder.should_receive(:country_select).with(:country, priority_countries, {}, {}).and_return("<select><option>...</option></select>") + + concat(builder.input(:country, :as => :country, :priority_countries => priority_countries)) + end + end + + it "should default to the @@priority_countries config when absent" do + priority_countries = Formtastic::SemanticFormBuilder.priority_countries + priority_countries.should_not be_empty + priority_countries.should_not be_nil + + semantic_form_for(@new_post) do |builder| + builder.stub!(:country_select).and_return("<select><option>...</option></select>") + builder.should_receive(:country_select).with(:country, priority_countries, {}, {}).and_return("<select><option>...</option></select>") + + concat(builder.input(:country, :as => :country)) + end + end + + end + + end + describe ':as => :radio' do before do @new_post.stub!(:author).and_return(@bob) @new_post.stub!(:author_id).and_return(@bob.id) - @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :integer, :limit => 255)) + Post.stub!(:reflect_on_association).and_return { |column_name| mock('reflection', :klass => Author, :macro => :belongs_to) } end describe 'for belongs_to association' do before do semantic_form_for(@new_post) do |builder| @@ -1082,11 +1284,11 @@ it 'should have a radio class on the wrapper' do output_buffer.should have_tag('form li.radio') end - it 'should have a post_author_id_input id on the wrapper' do + it 'should have a post_author_input id on the wrapper' do output_buffer.should have_tag('form li#post_author_input') end it 'should generate a fieldset and legend containing label text for the input' do output_buffer.should have_tag('form li fieldset') @@ -1097,22 +1299,20 @@ it 'should generate an ordered list with a list item for each choice' do output_buffer.should have_tag('form li fieldset ol') output_buffer.should have_tag('form li fieldset ol li', :count => Author.find(:all).size) end - it 'should have one option with a "selected" attribute' do + it 'should have one option with a "checked" attribute' do output_buffer.should have_tag('form li input[@checked]', :count => 1) end describe "each choice" do it 'should contain a label for the radio input with a nested input and label text' do Author.find(:all).each do |author| - output_buffer.should have_tag('form li fieldset ol li label') output_buffer.should have_tag('form li fieldset ol li label', /#{author.to_label}/) output_buffer.should have_tag("form li fieldset ol li label[@for='post_author_id_#{author.id}']") - output_buffer.should have_tag("form li fieldset ol li label input") end end it 'should use values as li.class when value_as_class is true' do Author.find(:all).each do |author| @@ -1140,33 +1340,43 @@ output_buffer.should have_tag("form li fieldset ol li label input[@checked='checked']") end end - it 'should generate a fieldset, legend, labels and inputs even if no object is given' do - output_buffer.replace '' + describe 'and no object is given' do + before(:each) do + output_buffer.replace '' + semantic_form_for(:project, :url => 'http://test.host') do |builder| + concat(builder.input(:author_id, :as => :radio, :collection => Author.find(:all))) + end + end - semantic_form_for(:project, :url => 'http://test.host') do |builder| - concat(builder.input(:author_id, :as => :radio, :collection => Author.find(:all))) + it 'should generate a fieldset with legend' do + output_buffer.should have_tag('form li fieldset legend', /Author/) end - output_buffer.should have_tag('form li fieldset legend', /Author/) - output_buffer.should have_tag('form li fieldset ol li', :count => Author.find(:all).size) + it 'shold generate an li tag for each item in the collection' do + output_buffer.should have_tag('form li fieldset ol li', :count => Author.find(:all).size) + end - Author.find(:all).each do |author| - output_buffer.should have_tag('form li fieldset ol li label', /#{author.to_label}/) - output_buffer.should have_tag("form li fieldset ol li label[@for='project_author_id_#{author.id}']") + it 'should generate labels for each item' do + Author.find(:all).each do |author| + output_buffer.should have_tag('form li fieldset ol li label', /#{author.to_label}/) + output_buffer.should have_tag("form li fieldset ol li label[@for='project_author_id_#{author.id}']") + end + end - output_buffer.should have_tag("form li fieldset ol li label input#project_author_id_#{author.id}") - output_buffer.should have_tag("form li fieldset ol li label input[@type='radio']") - output_buffer.should have_tag("form li fieldset ol li label input[@value='#{author.id}']") - output_buffer.should have_tag("form li fieldset ol li label input[@name='project[author_id]']") + it 'should generate inputs for each item' do + Author.find(:all).each do |author| + output_buffer.should have_tag("form li fieldset ol li label input#project_author_id_#{author.id}") + output_buffer.should have_tag("form li fieldset ol li label input[@type='radio']") + output_buffer.should have_tag("form li fieldset ol li label input[@value='#{author.id}']") + output_buffer.should have_tag("form li fieldset ol li label input[@name='project[author_id]']") + end end end - end - end describe ':as => :select' do before do @@ -1320,36 +1530,143 @@ it 'should have a select with prompt' do output_buffer.should have_tag("form li select option[@value='']", /choose author/) end end - it 'should generate label, select and options even if object is not given' do - semantic_form_for(:project, :url => 'http://test.host') do |builder| - concat(builder.input(:author, :as => :select, :collection => Author.find(:all))) + describe 'when no object is given' do + before(:each) do + semantic_form_for(:project, :url => 'http://test.host') do |builder| + concat(builder.input(:author, :as => :select, :collection => Author.find(:all))) + end end - output_buffer.should have_tag('form li label', /Author/) - output_buffer.should have_tag("form li label[@for='project_author']") + it 'should generate label' do + output_buffer.should have_tag('form li label', /Author/) + output_buffer.should have_tag("form li label[@for='project_author']") + end - output_buffer.should have_tag('form li select#project_author') - output_buffer.should have_tag('form li select option', :count => Author.find(:all).size) + it 'should generate select inputs' do + output_buffer.should have_tag('form li select#project_author') + output_buffer.should have_tag('form li select option', :count => Author.find(:all).size) + end - Author.find(:all).each do |author| - output_buffer.should have_tag("form li select option[@value='#{author.id}']", /#{author.to_label}/) + it 'should generate an option to each item' do + Author.find(:all).each do |author| + output_buffer.should have_tag("form li select option[@value='#{author.id}']", /#{author.to_label}/) + end end end end + describe ':as => :check_boxes' do + + describe 'for a has_many association' do + before do + semantic_form_for(@fred) do |builder| + concat(builder.input(:posts, :as => :check_boxes, :value_as_class => true)) + end + end + + it 'should have a check_boxes class on the wrapper' do + output_buffer.should have_tag('form li.check_boxes') + end + + it 'should have a author_posts_input id on the wrapper' do + output_buffer.should have_tag('form li#author_posts_input') + end + + it 'should generate a fieldset and legend containing label text for the input' do + output_buffer.should have_tag('form li fieldset') + output_buffer.should have_tag('form li fieldset legend') + output_buffer.should have_tag('form li fieldset legend', /Posts/) + end + + it 'should generate an ordered list with a list item for each choice' do + output_buffer.should have_tag('form li fieldset ol') + output_buffer.should have_tag('form li fieldset ol li', :count => Post.find(:all).size) + end + + it 'should have one option with a "checked" attribute' do + output_buffer.should have_tag('form li input[@checked]', :count => 1) + end + + it 'should generate hidden inputs with default value blank' do + output_buffer.should have_tag("form li fieldset ol li label input[@type='hidden'][@value='']", :count => Post.find(:all).size) + end + + describe "each choice" do + + it 'should contain a label for the radio input with a nested input and label text' do + Post.find(:all).each do |post| + output_buffer.should have_tag('form li fieldset ol li label', /#{post.to_label}/) + output_buffer.should have_tag("form li fieldset ol li label[@for='author_post_ids_#{post.id}']") + end + end + + it 'should use values as li.class when value_as_class is true' do + Post.find(:all).each do |post| + output_buffer.should have_tag("form li fieldset ol li.#{post.id} label") + end + end + + it 'should have a checkbox input for each post' do + Post.find(:all).each do |post| + output_buffer.should have_tag("form li fieldset ol li label input#author_post_ids_#{post.id}") + output_buffer.should have_tag("form li fieldset ol li label input[@name='author[post_ids][]']", :count => 2) + end + end + + it "should mark input as checked if it's the the existing choice" do + Post.find(:all).include?(@fred.posts.first).should be_true + output_buffer.should have_tag("form li fieldset ol li label input[@checked='checked']") + end + end + + describe 'and no object is given' do + before(:each) do + output_buffer.replace '' + semantic_form_for(:project, :url => 'http://test.host') do |builder| + concat(builder.input(:author_id, :as => :check_boxes, :collection => Author.find(:all))) + end + end + + it 'should generate a fieldset with legend' do + output_buffer.should have_tag('form li fieldset legend', /Author/) + end + + it 'shold generate an li tag for each item in the collection' do + output_buffer.should have_tag('form li fieldset ol li', :count => Author.find(:all).size) + end + + it 'should generate labels for each item' do + Author.find(:all).each do |author| + output_buffer.should have_tag('form li fieldset ol li label', /#{author.to_label}/) + output_buffer.should have_tag("form li fieldset ol li label[@for='project_author_id_#{author.id}']") + end + end + + it 'should generate inputs for each item' do + Author.find(:all).each do |author| + output_buffer.should have_tag("form li fieldset ol li label input#project_author_id_#{author.id}") + output_buffer.should have_tag("form li fieldset ol li label input[@type='checkbox']") + output_buffer.should have_tag("form li fieldset ol li label input[@value='#{author.id}']") + output_buffer.should have_tag("form li fieldset ol li label input[@name='project[author_id][]']") + end + end + end + end + end + describe 'for collections' do before do @new_post.stub!(:author).and_return(@bob) @new_post.stub!(:author_id).and_return(@bob.id) @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :integer, :limit => 255)) end - { :select => :option, :radio => :input }.each do |type, countable| + { :select => :option, :radio => :input, :check_boxes => :'input[@type="checkbox"]' }.each do |type, countable| describe ":as => #{type.inspect}" do describe 'when the :collection option is not provided' do it 'should perform a basic find on the association class' do Author.should_receive(:find) @@ -1400,13 +1717,13 @@ it "should use the string as the label text and value for each #{countable}" do semantic_form_for(@new_post) do |builder| concat(builder.input(:category_name, :as => type, :collection => @categories)) end - @categories.each do |item| - output_buffer.should have_tag("form li.#{type}", /#{item}/) - output_buffer.should have_tag("form li.#{type} #{countable}[@value=#{item}]") + @categories.each do |value| + output_buffer.should have_tag("form li.#{type}", /#{value}/) + output_buffer.should have_tag("form li.#{type} #{countable}[@value='#{value}']") end end if type == :radio it 'should generate a sanitized label for attribute' do @@ -1435,11 +1752,11 @@ concat(builder.input(:category_name, :as => type, :collection => @categories)) end @categories.each do |label, value| output_buffer.should have_tag("form li.#{type}", /#{label}/) - output_buffer.should have_tag("form li.#{type} #{countable}[@value=#{value}]") + output_buffer.should have_tag("form li.#{type} #{countable}[@value='#{value}']") end end end describe 'and the :collection is an array of arrays' do @@ -1448,16 +1765,17 @@ @categories = { 'General' => 'gen', 'Design' => 'des','Development' => 'dev' }.to_a end it "should use the first value as the label text and the last value as the value attribute for #{countable}" do semantic_form_for(@new_post) do |builder| - concat(builder.input(:category_name, :as => :radio, :collection => @categories)) + concat(builder.input(:category_name, :as => type, :collection => @categories)) end - @categories.each do |label, value| - output_buffer.should have_tag('form li fieldset ol li label', /#{label}/i) - output_buffer.should have_tag('form li fieldset ol li label input[@value='+value+']') + @categories.each do |text, value| + label = type == :select ? :option : :label + output_buffer.should have_tag("form li.#{type} #{label}", /#{text}/i) + output_buffer.should have_tag("form li.#{type} #{countable}[@value='#{value.to_s}']") end end end describe 'and the :collection is an array of symbols' do @@ -1466,16 +1784,17 @@ @categories = [ :General, :Design, :Development ] end it "should use the symbol as the label text and value for each #{countable}" do semantic_form_for(@new_post) do |builder| - concat(builder.input(:category_name, :as => :radio, :collection => @categories)) + concat(builder.input(:category_name, :as => type, :collection => @categories)) end @categories.each do |value| - output_buffer.should have_tag('form li fieldset ol li label', /#{value}/i) - output_buffer.should have_tag('form li fieldset ol li label input[@value='+value.to_s+']') + label = type == :select ? :option : :label + output_buffer.should have_tag("form li.#{type} #{label}", /#{value}/i) + output_buffer.should have_tag("form li.#{type} #{countable}[@value='#{value.to_s}']") end end end describe 'when the :label_method option is provided' do @@ -1528,13 +1847,20 @@ end end end end + end + end - describe 'when attribute is a boolean' do + describe 'for boolean attributes' do + { :select => :option, :radio => :input }.each do |type, countable| + checked_or_selected = { :select => :selected, :radio => :checked }[type] + + describe ":as => #{type.inspect}" do + before do @new_post.stub!(:allow_comments) @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :boolean)) semantic_form_for(@new_post) do |builder| @@ -1577,12 +1903,10 @@ output_buffer.should have_tag("form li.#{type}", /Absolutely\!/) output_buffer.should have_tag("form li.#{type}", /Never\!/) end end - checked_or_selected = { :select => :selected, :radio => :checked }[type] - describe 'when the value is nil' do before do @new_post.stub!(:allow_comments).and_return(nil) @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :boolean)) @@ -1645,10 +1969,11 @@ output_buffer.should have_tag("form li.#{type}", /Absolutely/) output_buffer.should have_tag("form li.#{type}", /No Way/) end end end + end end end describe ':as => :date' do @@ -1753,20 +2078,20 @@ it 'should use default hidden value equals to 1 when attribute returns nil' do semantic_form_for(@new_post) do |builder| concat(builder.input(:publish_at, :as => :datetime, :discard_day => true)) end - output_buffer.should have_tag("form li fieldset input[@type='hidden'][@value='1']") + output_buffer.should have_tag("form li input[@type='hidden'][@value='1']") end it 'should use default attribute value when it is not nil' do @new_post.stub!(:publish_at).and_return(Date.new(2007,12,27)) semantic_form_for(@new_post) do |builder| concat(builder.input(:publish_at, :as => :datetime, :discard_day => true)) end - output_buffer.should have_tag("form li fieldset input[@type='hidden'][@value='27']") + output_buffer.should have_tag("form li input[@type='hidden'][@value='27']") end end describe 'when :include_blank => true is set' do before do @@ -1835,20 +2160,29 @@ output_buffer.should have_tag('form li.datetime fieldset ol li label', /The Hour/) output_buffer.should have_tag('form li.datetime fieldset ol li label', /The Minute/) end end - it 'should have fieldset, legend, label and selects even if object is not given' do - output_buffer.replace '' + describe 'when no object is given' do + before(:each) do + output_buffer.replace '' + semantic_form_for(:project, :url => 'http://test.host') do |@builder| + concat(@builder.input(:publish_at, :as => :datetime)) + end + end - semantic_form_for(:project, :url => 'http://test.host') do |@builder| - concat(@builder.input(:publish_at, :as => :datetime)) + it 'should have fieldset with legend' do + output_buffer.should have_tag('form li.datetime fieldset legend', /Publish at/) end - output_buffer.should have_tag('form li.datetime fieldset legend', /Publish at/) - output_buffer.should have_tag('form li.datetime fieldset ol li label', :count => 5) - output_buffer.should have_tag('form li.datetime fieldset ol li select', :count => 5) + it 'should have labels for each input' do + output_buffer.should have_tag('form li.datetime fieldset ol li label', :count => 5) + end + + it 'should have selects for each inputs' do + output_buffer.should have_tag('form li.datetime fieldset ol li select', :count => 5) + end end end describe ':as => :time' do before do @@ -1881,12 +2215,13 @@ output_buffer.should have_tag('form li.time fieldset li label', :count => 2) output_buffer.should have_tag('form li.time fieldset li label', /hour/i) output_buffer.should have_tag('form li.time fieldset li label', /minute/i) end - it 'should have five selects for hour and minute' do - output_buffer.should have_tag('form li.time fieldset li select', :count => 2) + it 'should have two selects for hour and minute' do + #output_buffer.should have_tag('form li.time fieldset ol li select', :count => 2) + output_buffer.should have_tag('form li.time fieldset ol li', :count => 2) end end [:boolean_select, :boolean_radio].each do |type| describe ":as => #{type.inspect}" do @@ -1961,11 +2296,10 @@ end end end - describe '#inputs' do describe 'with a block' do describe 'when no options are provided' do @@ -2517,44 +2851,50 @@ describe "Nested Js Helpers" do it "should have a add method" do @new_post.stub!(:authors).and_return(mock("Authors", :build => mock('Author'))) + should_receive(:render).with(hash_including(:partial => "mock")).and_return('"attributes___idx___test__idxx__"') semantic_form_for(@new_post) do |builder| - builder.should_receive(:render).with(hash_including(:partial => "mock")).and_return('"attributes___idx___test__idxx__"') builder.inputs :name => "Contacts", :id => "contacts" do concat(builder.add_associated_link(:name, :authors)) end end output_buffer.should have_tag('form fieldset a[@href=#]') output_buffer.should match(/\\&quot;attributes___idx___test__idxx__\\&quot;&quot;.replace/) end - it "should have a remove method" do - semantic_form_for(@new_post) do |builder| - builder.semantic_fields_for(:links) do |link_builder| - concat(link_builder.remove_link("Remove")) - end - end - output_buffer.should eql("<form action=\"/posts\" class=\"formtastic post\" id=\"new_post\" method=\"post\"><input id=\"post_links__delete\" name=\"post[links][_delete]\" type=\"hidden\" /><a href=\"#\" onclick=\"$(this).parents('.nil_class').hide(); $(this).prev(':input').val('1');; return false;\">Remove</a></form>") - end it "should have a show method" do @new_post.stub!(:authors).and_return([mock("Author")]) + should_receive(:render).with(hash_including(:partial => "mock")).and_return("fields") semantic_form_for(@new_post) do |builder| - builder.should_receive(:render).with(hash_including(:partial => "mock")).and_return("fields") builder.inputs :name => "Contacts" do concat(builder.render_associated_form @new_post.authors) end end + # output_buffer.shou output_buffer.should eql("<form action=\"/posts\" class=\"formtastic post\" id=\"new_post\" method=\"post\"><fieldset class=\"inputs\"><legend><span>Contacts</span></legend><ol>fields</ol></fieldset></form>") end + + it "should have a remove method" do + semantic_form_for(@new_post) do |builder| + builder.semantic_fields_for(:links) do |link_builder| + concat(link_builder.remove_link("Remove")) + end + end + + output_buffer.should have_tag("form input[@type=hidden]") + output_buffer.should have_tag("form a[@href=#]") + # output_buffer.should match(/$(this).parents('.nil_class').hide(); $(this).prev(':input').val('1');; return false;) + # output_buffer.should eql("<<input id=\"post_links__delete\" name=\"post[links][_delete]\" type=\"hidden\" /><a href=\"#\" onclick=\"$(this).parents('.nil_class').hide(); $(this).prev(':input').val('1');; return false;\">Remove</a></form>") + end end end end