8

I have a rails controller, defined here:

https://github.com/abonec/Simple-Store/blob/master/app/controllers/carts_controller.rb

On the cart page a user can specify the quantity of line_items by posting nested attributes. The parameters look like this:

{ "cart" => {
  "line_items_attributes" => {
    "0" => {
      "quantity" => "2",
      "id" => "36" } } },
  "commit" => "Update Cart",
  "authenticity_token" => "UdtQ+lchSKaHHkN2E1bEX00KcdGIekGjzGKgKfH05So=",
  "utf8"=>"\342\234\223" }

In my controller action these params are saved like this:

@cart.update_attributes(params[:cart])

But I don't know how to test this behavior in a test. @cart.attributes only generates model attributes not nested attributes.

How can I test this behavior? How to simulate post request with nested attributes in my functional tests?

abonec
  • 1,379
  • 1
  • 14
  • 23

4 Answers4

8

A little late to the party, but you shouldn't be testing that behavior from the controller. Nested attributes is model behavior. The controller just passes anything to the model. In your controller example, there is no mention of any nested attributes. You want to test for the existence of the behavior created by accepts_nested_attributes_for in your model

You can test this with rSpec like this:

it "should accept nested attributes for units" do
  expect {
    Cart.update_attributes(:cart => {:line_items_attributes=>{'0'=>{'quantity'=>2, 'other_attr'=>"value"}})
  }.to change { LineItems.count }.by(1)
end
stuartc
  • 2,244
  • 2
  • 24
  • 31
3

Assuming you're using Test::Unit, and you have a cart in @cart in the setup, try something like this in your update test:

cart_attributes = @cart.attributes
line_items_attributes = @cart.line_items.map(&:attributes)
cart_attributes[:line_items] = line_items_attributes
put :update, :id => @cart.to_param, :cart => cart_attributes
Francis Potter
  • 1,629
  • 1
  • 17
  • 19
2

Using test/unit in Rails3, first generate a integration test:

rails g integration_test cart_flows_test

in the generated file you include you test, something like:

test "if it adds line_item through the cart" do
  line_items_before = LineItem.all
  # don't forget to sign in some user or you can be redirected to login page
  post_via_redirect '/carts', :cart => {:line_items_attributes=>{'0'=>{'quantity'=>2, 'other_attr'=>"value"}}}

  assert_template 'show'
  assert_equal line_items_before+1, LineItem.all
end

I hope that helped.

Matthias
  • 1,884
  • 2
  • 18
  • 35
Marco Antonio
  • 1,359
  • 1
  • 9
  • 8
0

After you update the cart with the nested attributes, you can access the nested attributes by doing

@cart.line_items
Mike Lewis
  • 63,433
  • 20
  • 141
  • 111
  • How to access to nested attributes I know, but I don't know how to simulate post request with nested attributes in my functional tests. – abonec Mar 13 '11 at 09:02