How to test views with Nested Resources and Partials

Hi everyone,

I am relatively new to rspec and I am running into a wall in testing my
views. I have a RESTful resource Contracts with a nested resource of
Line_items.

I am trying to figure out how to test the “edit” form of the Line_items.
What complicates this is the nested routing and how to account for it,
and that there is a partial form (_form.haml) that both the edit.haml
and new.haml views use (app/views/line_items).

My spec keeps failing and it seems to be from a routing issue. I’m
pretty sure template.expect_render/template.stub_render should be in
there somewhere, but that just generates more errors.

I am running edge rails and edge rspec. My other spec’s are working
fine.

See the output from running the spec and the associated files below
(edit.haml_spec.rb, edit.haml, _form.haml)

Thanks for your help,
Troy

######## Output from running edit.haml_spec.r ########

F

ActionView::TemplateError in ‘/line_items/edit.haml should render edit
form’
contract_line_item_url failed to generate from
{:contract_id=>“1”, :action=>“show”, :controller=>“line_items”},
expected: {:action=>“show”, :controller=>“line_items”}, diff:
{:contract_id=>“1”}
On line #6 of app/views/line_items/edit.haml

3:
4: #section1
5:   = error_messages_for :line_item
6:   - form_for(:line_item, :url =>

contract_line_item_path(@contract.id), :html => { :method => :put }) do
|f|
7: = render :partial => “form”, :locals => { :f => f }
8:
9: %p

app/views/line_items/edit.haml:6
vendor/rails/actionpack/lib/action_controller/routing.rb:1406:in

raise_named_route_error' vendor/rails/actionpack/lib/action_controller/routing.rb:1370:ingenerate’
vendor/rails/actionpack/lib/action_controller/url_rewriter.rb:124:in
rewrite_path' vendor/rails/actionpack/lib/action_controller/url_rewriter.rb:103:inrewrite_url’
vendor/rails/actionpack/lib/action_controller/url_rewriter.rb:81:in
rewrite' vendor/rails/actionpack/lib/action_controller/base.rb:605:inurl_for’
vendor/rails/actionpack/lib/action_view/helpers/url_helper.rb:71:in
send' vendor/rails/actionpack/lib/action_view/helpers/url_helper.rb:71:inurl_for’
(eval):17:in contract_line_item_path' (eval):15:in_render_haml_1’
vendor/plugins/stable/lib/haml/engine.rb:435:in send' vendor/plugins/stable/lib/haml/engine.rb:435:incompile’
vendor/plugins/stable/lib/haml/engine.rb:186:in to_html' vendor/plugins/stable/lib/haml/template.rb:69:inrender’
vendor/rails/actionpack/lib/action_view/base.rb:529:in
delegate_render' vendor/rails/actionpack/lib/action_view/base.rb:351:inrender_template_old’
vendor/plugins/stable/lib/haml/template.rb:96:in render_template' vendor/rails/actionpack/lib/action_view/base.rb:303:inrender_file’
vendor/rails/actionpack/lib/action_controller/base.rb:1079:in
render_for_file' vendor/rails/actionpack/lib/action_controller/base.rb:831:inrender_with_no_layout’
vendor/rails/actionpack/lib/action_controller/layout.rb:269:in
render_without_benchmark' vendor/rails/actionpack/lib/action_controller/benchmarking.rb:51:inrender’
/usr/local/lib/ruby/1.8/benchmark.rb:293:in measure' vendor/rails/actionpack/lib/action_controller/benchmarking.rb:51:inrender’

vendor/plugins/rspec_on_rails/lib/spec/rails/example/behaviour/view_example.rb:129:in
`send’

vendor/plugins/rspec_on_rails/lib/spec/rails/example/behaviour/view_example.rb:129:in
render' spec/views/line_items/edit.haml_spec.rb:57 vendor/plugins/rspec/lib/spec/example/example_methods.rb:14:ininstance_eval’
vendor/plugins/rspec/lib/spec/example/example_methods.rb:14:in run' vendor/plugins/rspec/lib/spec/example/example_runner.rb:57:inrun_example’
vendor/plugins/rspec/lib/spec/example/example_runner.rb:23:in run' /usr/local/lib/ruby/1.8/timeout.rb:48:intimeout’
vendor/plugins/rspec/lib/spec/example/example_runner.rb:21:in run' vendor/plugins/rspec/lib/spec/example/example_suite.rb:28:inrspec_run’
vendor/plugins/rspec/lib/spec/example/example_suite.rb:24:in each' vendor/plugins/rspec/lib/spec/example/example_suite.rb:24:inrspec_run’

vendor/plugins/rspec/lib/spec/extensions/test/unit/example_suite.rb:7:in
run' vendor/plugins/rspec/lib/spec/runner/behaviour_runner.rb:22:inrun’
vendor/plugins/rspec/lib/spec/runner/behaviour_runner.rb:21:in
each' vendor/plugins/rspec/lib/spec/runner/behaviour_runner.rb:21:inrun’
vendor/plugins/rspec/lib/spec/runner/options.rb:77:in run_examples' vendor/plugins/rspec/lib/spec/runner/command_line.rb:19:inrun’
vendor/plugins/rspec/bin/spec:3

Finished in 0.081986 seconds

1 example, 1 failure

######## edit.haml_spec.rb ########
require File.dirname(FILE) + ‘/…/…/spec_helper’

describe “/line_items/edit.haml” do
include LineItemsHelper

before do
@contract = mock_model(Contract)
@contract.stub!(:id).and_return(“1”)
@contract.stub!(:sdc_ref).and_return(“MyString”)
@contract.stub!(:description).and_return(“MyString”)
@contract.stub!(:sales_rep_id).and_return(“1”)
@contract.stub!(:office_id).and_return(“1”)
@contract.stub!(:account_id).and_return(“MyString”)
@contract.stub!(:cust_po_num).and_return(“MyString”)
@contract.stub!(:payment_terms).and_return(“MyString”)
@contract.stub!(:hp3000).and_return(false)
@contract.stub!(:revenue).and_return(“MyString”)
@contract.stub!(:annual_hw_rev).and_return(“1.5”)
@contract.stub!(:annual_sw_rev).and_return(“1.5”)
@contract.stub!(:annual_ce_rev).and_return(“1.5”)
@contract.stub!(:annual_sa_rev).and_return(“1.5”)
@contract.stub!(:annual_dr_rev).and_return(“1.5”)
@contract.stub!(:start_date).and_return(Date.today)
@contract.stub!(:end_date).and_return(Date.today)
@contract.stub!(:multiyr_end).and_return(Date.today)
@contract.stub!(:expired).and_return(“MyString”)
@contract.stub!(:hw_support_level_id).and_return(“1”)
@contract.stub!(:sw_support_level_id).and_return(“1”)
@contract.stub!(:updates).and_return(“MyString”)
@contract.stub!(:ce_days).and_return(“1”)
@contract.stub!(:sa_days).and_return(“1”)
@contract.stub!(:discount_pref_hw).and_return(“1.5”)
@contract.stub!(:discount_pref_sw).and_return(“1.5”)
@contract.stub!(:discount_prepay).and_return(“1.5”)
@contract.stub!(:discount_multiyear).and_return(“1.5”)
@contract.stub!(:discount_ce_day).and_return(“1.5”)
@contract.stub!(:discount_sa_day).and_return(“1.5”)
@contract.stub!(:primary_office).and_return(“MyString”)
@contract.stub!(:replacement_sdc_ref).and_return(“MyString”)
assigns[:contract] = @contract

@line_item = mock_model(LineItem)
@line_item.stub!(:contract_id).and_return("1")
@line_item.stub!(:support_type).and_return("MyString")
@line_item.stub!(:product_num).and_return("MyString")
@line_item.stub!(:serial_num).and_return("MyString")
@line_item.stub!(:description).and_return("MyString")
@line_item.stub!(:begins).and_return(Date.today)
@line_item.stub!(:ends).and_return(Date.today)
@line_item.stub!(:qty).and_return("1")
@line_item.stub!(:list_price).and_return("1")
assigns[:line_item] = @line_item

end

it “should render edit form” do

render "line_items/edit.haml"

response.should

have_tag(“form[action=#{contract_line_item_path(@contract.id,@line_item.id)}][method=post]”)
do
with_tag(‘input#line_item_support_type[name=?]’,
“line_item[support_type]”)
with_tag(‘input#line_item_product_num[name=?]’,
“line_item[product_num]”)
with_tag(‘input#line_item_serial_num[name=?]’,
“line_item[serial_num]”)
with_tag(‘input#line_item_description[name=?]’,
“line_item[description]”)
with_tag(‘input#line_item_qty[name=?]’, “line_item[qty]”)
with_tag(‘input#line_item_list_price[name=?]’,
“line_item[list_price]”)
end
end
end

######## edit.haml ########

  • content_for :subtitle do
    Edit Line Item

#section1
= error_messages_for :line_item

  • form_for(:line_item, :url =>
    contract_line_item_path(@contract.id), :html => { :method => :put }) do
    |f|
    = render :partial => “form”, :locals => { :f => f }

    %p
    = submit_tag “Update”

#section2
= link_to(‘Show’, contract_path(@contract)) + ’ | ’ + link_to(‘Back’,
contracts_path)

######## _form.haml ########
#section1
#results.boxed
%h2 Details
%p
%label{:for => “line_item_support_type”}
Type
= f.text_field :support_type

%p
  %label{:for => "line_item_product_num"}
    Product num
  = f.text_field :product_num

%p
  %label{:for => "line_item_serial_num"}
    Serial num
  = f.text_field :serial_num

%p
  %label{:for => "line_item_description"}
    Description
  = f.text_field :description

%p
  %label{:for => "line_item_begins"}
    Begins
  = f.text_field :begins

%p
  %label{:for => "line_item_ends"}
    Ends
  = f.text_field :ends

%p
  %label{:for => "line_item_qty"}
    Qty
  = f.text_field :qty

%p
  %label{:for => "line_list_price"}
    List Price
  = f.text_field :list_price

Hi Troy,

On 20.11.2007, at 22.21, Troy Nini wrote:

{:contract_id=>“1”}
On line #6 of app/views/line_items/edit.haml

3:
4: #section1
5:   = error_messages_for :line_item
6:   - form_for(:line_item, :url => contract_line_item_path 

(@contract.id)

contract_line_item_path (and _url) expects two parameters, contract
and line item (or their ids). The errors the routing code outputs are
often pretty cryptic.

//jarkko


Jarkko L.

http://www.railsecommerce.com
http://odesign.fi

Thanks Jarkko!

OK that was embarrassingly simple. Maybe, I was just testing you, or
not.