views:

43

answers:

0

I am trying to write a view spec to drive out a form with a nested model. In my example every Organization has many Users. When you create a new organization you create the first user at the same time. This part works:


require 'spec_helper'

describe 'organization/new.html.erb' do
  let(:organization) do
    mock_model("Organization").as_new_record.as_null_object
  end
  let(:user) do
    mock_model("User").as_new_record.as_null_object
  end

  before(:each) do
    assign(:organization, organization)
    assign(:user, user)
  end

  it 'renders a form to create an organization' do
    render
    rendered.should have_selector('form', :method => "post", :action => organizations_path) do |form|
      form.should have_selector('input', :type => 'submit')
    end
  end

  it 'renders a text_fields for the organization name' do
    organization.stub(:name => 'a name')
    render
    rendered.should have_selector('form') do |form|
      form.should have_selector('input', type:"text", name:"organization[name]", value:'a name')
    end
  end

  it 'renders a text_field for the organization subdomain' do
    organization.stub(:subdomain => 'a subdomain')
    render
    rendered.should have_selector('form') do |form|
      form.should have_selector('input', type:"text", name:"organization[subdomain]", value:'a subdomain')
    end
  end

end

And produces this:

<%= form_for(@organization) do |f| %>
  <%= f.text_field :name %>
  <%= f.text_field :subdomain %>
  <%= f.submit "Sign Up!" %>
<% end %>

However, I want to drive out something like this:

<%= form_for(@organization) do |f| %>
  <%= f.text_field :name %>
  <%= f.text_field :subdomain %>
  <% f.fields_for :users do |builder| %>
    <%= builder.text_field :email %>
  <% end %>
  <%= f.submit "Sign Up!" %>
<% end %>

The controller's new action would contain something like:

@organization = Organization.new
@organization.users.build

Here is my rspec example thus far:


  it 'renders a text_field for user email' do
    user.stub(:email => '[email protected]')
    organization.stub(:users => user)
    render
    rendered.should have_selector('form') do |form|
      form.should have_selector('input', type:"text", name:"organization[user_attributes][0][email]", value:'[email protected]')
    end
  end

That fails (expectedly...). When I do run it with the code in the view this is my error message:

Failures:
  1) organization/new.html.erb renders a text_field for user email
     Failure/Error: form.should have_selector('input', type:"text", name:"organization[user_attributes][0][email]", value:'[email protected]')
     expected following output to contain a <input type='text' name='organization[user_attributes][0][email]' value='[email protected]'/> tag:
     <form accept-charset="UTF-8" action="/organizations" class="new_organization" id="new_organization" method="post">
     <div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#10003;"></div>
       <input id="organization_name" name="organization[name]" size="30" type="text" value="Organization_#&lt;RSpec::Core::ExampleGroup::Nested_1:0x000001011c4560&gt;">
       <input id="organization_subdomain" name="organization[subdomain]" size="30" type="text" value="Organization_#&lt;RSpec::Core::ExampleGroup::Nested_1:0x000001011c4560&gt;">
       <input id="organization_submit" name="commit" type="submit" value="Sign Up!">
     </form>
     # ./spec/views/organization/new.html.erb_spec.rb:43:in `block (3 levels) in <top (required)>'
     # ./spec/views/organization/new.html.erb_spec.rb:42:in `block (2 levels) in <top (required)>'

I am pretty darn certain there are errors in my mocks and stubbed methods and possibly elsewhere. There are no traces of the nested form in the rendered html. This is pretty easy to do standalone, but I wanted to do this from a BDD/TDD approach.

If it is not clear I am using rails3 with ruby1.9.2 and rspec2.0.0.

Can someone please point me in the right direction? Thanks!