11.1 Iteration F1: Moving the Cart 10.3 Iteration E3: Finishing the Cart
Once again, get the tests working, and add tests for the smarter cart.
See that the tests fail.
rails test
Run options: --seed 42885
# Running:
..F
Failure:
LineItemsControllerTest#test_should_create_line_item [/home/rubys/git/awdwr/edition4/work-233-50/depot/test/controllers/line_items_controller_test.rb:26]:
<Your Pragmatic Cart> expected but was
<Your Cart>..
Expected 0 to be >= 1.
bin/rails test test/controllers/line_items_controller_test.rb:19
.............F
Failure:
CartsControllerTest#test_should_destroy_cart [/home/rubys/git/awdwr/edition4/work-233-50/depot/test/controllers/carts_controller_test.rb:42]:
"Cart.count" didn't change by -1.
Expected: 1
Actual: 2
bin/rails test test/controllers/carts_controller_test.rb:41
...........
Finished in 0.784187s, 35.7058 runs/s, 71.4115 assertions/s.
28 runs, 56 assertions, 2 failures, 0 errors, 0 skips
Update the value of the header that we are looking for
edit test/controllers/line_items_controller_test.rb
test "should create line_item" do
assert_difference('LineItem.count') do
post line_items_url, params: { product_id: products(:ruby).id }
end
follow_redirect!
assert_select 'h2', 'Your Cart'
assert_select 'td', "Programming Ruby 1.9"
end
Update expected target of redirect: Cart#destroy.
avoid using session in integration tests
edit test/controllers/carts_controller_test.rb
test "should destroy cart" do
post line_items_url, params: { product_id: products(:ruby).id }
@cart = Cart.find(session[:cart_id])
assert_difference('Cart.count', -1) do
delete cart_url(@cart)
end
assert_redirected_to store_index_url
end
Test both unique and duplicate products.
edit test/models/cart_test.rb
require 'test_helper'
class CartTest < ActiveSupport::TestCase
test "add unique products" do
cart = Cart.create
book_one = products(:one)
book_two = products(:two)
cart.add_product(book_one).save!
cart.add_product(book_two).save!
assert_equal 2, cart.line_items.size
assert_equal book_one.price + book_two.price, cart.total_price
end
test "add_duplicate_product" do
cart = Cart.create
ruby_book = products(:ruby)
cart.add_product(ruby_book).save!
cart.add_product(ruby_book).save!
assert_equal 2*book_one.price, cart.total_price
assert_equal 1, cart.line_items.size
assert_equal 2, cart.line_items[0].quantity
end
end
rails test test/models/cart_test.rb
Run options: --seed 45427
# Running:
E
Error:
CartTest#test_add_duplicate_product:
NameError: undefined local variable or method `book_one' for #<CartTest:0x000000051f97d0>
test/models/cart_test.rb:24:in `block in <class:CartTest>'
bin/rails test test/models/cart_test.rb:19
.
Finished in 0.101843s, 19.6380 runs/s, 19.6380 assertions/s.
2 runs, 2 assertions, 0 failures, 1 errors, 0 skips
Refactor.
edit test/models/cart_test.rb
require 'test_helper'
class CartTest < ActiveSupport::TestCase
def setup
@cart = Cart.create
@book_one = products(:ruby)
@book_two = products(:two)
end
test "add unique products" do
@cart.add_product(@book_one).save!
@cart.add_product(@book_two).save!
assert_equal 2, @cart.line_items.size
assert_equal @book_one.price + @book_two.price, @cart.total_price
end
test "add duplicate product" do
@cart.add_product(@book_one).save!
@cart.add_product(@book_one).save!
assert_equal 2*@book_one.price, @cart.total_price
assert_equal 1, @cart.line_items.size
assert_equal 2, @cart.line_items[0].quantity
end
end
rails test test/models/cart_test.rb
Run options: --seed 54633
# Running:
..
Finished in 0.081031s, 24.6819 runs/s, 61.7048 assertions/s.
2 runs, 5 assertions, 0 failures, 0 errors, 0 skips
Verify that the tests pass.
rails test
Run options: --seed 21979
# Running:
..............................
Finished in 0.741236s, 40.4729 runs/s, 84.9932 assertions/s.
30 runs, 63 assertions, 0 failures, 0 errors, 0 skips
Now the tests should pass.
rails test
Run options: --seed 38792
# Running:
..............................
Finished in 0.749806s, 40.0103 runs/s, 84.0217 assertions/s.
30 runs, 63 assertions, 0 failures, 0 errors, 0 skips
Add price to line item
rails generate migration add_price_to_line_item price:decimal
invoke active_record
create db/migrate/20170603044154_add_price_to_line_item.rb
edit db/migrate/20170603044154_add_price_to_line_item.rb
class AddPriceToLineItem < ActiveRecord::Migration[5.0]
def change
add_column :line_items, :price, :decimal
LineItem.all.each do |li|
li.price = li.product.price
end
end
end
rails db:migrate
mv 20170603044154_add_price_to_line_item.rb 20170603000006_add_price_to_line_item.rb
== 20170603000006 AddPriceToLineItem: migrating ===============================
-- add_column(:line_items, :price, :decimal)
-> 0.0021s
== 20170603000006 AddPriceToLineItem: migrated (0.0230s) ======================
edit app/models/cart.rb
class Cart < ApplicationRecord
has_many :line_items, dependent: :destroy
def add_product(product)
current_item = line_items.find_by(product_id: product.id)
if current_item
current_item.quantity += 1
else
current_item = line_items.build(product_id: product.id)
current_item.price = current_item.product.price
end
current_item
end
def total_price
line_items.to_a.sum { |item| item.total_price }
end
end
git commit -a -m "Adding a Cart"
[master 2f85e92] Adding a Cart
4 files changed, 60 insertions(+), 11 deletions(-)
git tag iteration-d
11.1 Iteration F1: Moving the Cart 10.3 Iteration E3: Finishing the Cart