require 'spec_helper' describe Effective::OrdersController, type: :controller do routes { EffectiveOrders::Engine.routes } let(:purchased_order) { FactoryGirl.create(:purchased_order) } let(:order) { FactoryGirl.create(:order) } let(:cart) { FactoryGirl.create(:cart) } let(:address) { FactoryGirl.create(:address) } let(:billing_address) { FactoryGirl.create(:address) } let(:billing_atts) { billing_address.attributes.reject { |k, v| ['id', 'addressable_type', 'addressable_id', 'category', 'updated_at', 'created_at'].include?(k) } } let(:shipping_address) { FactoryGirl.create(:address) } let(:shipping_atts) { shipping_address.attributes.reject { |k, v| ['id', 'addressable_type', 'addressable_id', 'category', 'updated_at', 'created_at'].include?(k) } } let(:valid_order_attributes) do { :effective_order => { :billing_address => billing_atts, :save_billing_address => false, :shipping_address => shipping_atts, :save_shipping_address => false, } } end it 'uses authenticate_user! to redirect to sign in if not signed in' do get :new response.should redirect_to '/users/sign_in' end describe '#new' do it 'should assign an @order based off the user cart' do sign_in cart.user get :new assigns(:order).user.should eq cart.user assigns(:order).order_items.size.should eq cart.cart_items.size assigns(:order).total.should eq cart.total end it 'redirects if there is an empty order' do sign_in cart.user cart.cart_items.destroy_all get :new flash[:danger].downcase.include?('add one or more item to your cart').should eq true response.should redirect_to '/cart' # cart_path end it 'redirects if order total is less than minimum charge' do sign_in cart.user cart.cart_items.each do |cart_item| cart_item.purchasable.update_column(:price, 10) end get :new flash[:danger].downcase.include?('a minimum order of $0.50 is required').should eq true response.should redirect_to '/cart' # cart_path end end # "effective_order"=> { # "order_items_attributes"=> { # "0"=> { # "class"=>"Effective::Subscription", "stripe_coupon_id"=>"50OFF", "id"=>"2"}}, # "billing_address"=>{"address1"=>"1234 Fake street", "address2"=>"", "city"=>"Edmonton", "country_code"=>"KH", "state_code"=>"1", "postal_code"=>"T5T2T1"}, # "save_billing_address"=>"1", # "shipping_address"=>{"address1"=>"123 Shipping street", "address2"=>"", "city"=>"Edmonton", "country_code"=>"KH", "state_code"=>"10", "postal_code"=>"t5t2t1"}, # "save_shipping_address"=>"1"}, # "commit"=>"Continue Checkout" # } describe '#create' do before(:each) do sign_in cart.user end it 'should assign an @order based off the user cart' do post :create assigns(:order).user.should eq cart.user assigns(:order).order_items.size.should eq cart.cart_items.size assigns(:order).total.should eq cart.total assigns(:order).purchased?.should eq false end it 'assign appropriate User fields' do post :create, :effective_order => { :billing_address => billing_atts, :save_billing_address => false, :shipping_address => shipping_atts, :save_shipping_address => false, :shipping_address_same_as_billing => false, :user_attributes => {:first_name => 'First', :last_name => 'Last', :email => 'email@somwhere.com'} } (assigns(:order).valid? && assigns(:order).persisted?).should eq true assigns(:order).user.first_name.should eq 'First' assigns(:order).user.last_name.should eq 'Last' assigns(:order).user.email.should_not eq 'email@somwhere.com' end it 'assign addresses to the order and not the user' do post :create, :effective_order => { :billing_address => billing_atts, :save_billing_address => false, :shipping_address => shipping_atts, :save_shipping_address => false, :shipping_address_same_as_billing => false } (assigns(:order).valid? && assigns(:order).persisted?).should eq true assigns(:order).billing_address.address1.should eq billing_atts['address1'] assigns(:order).shipping_address.address1.should eq shipping_atts['address1'] assigns(:order).user.billing_address.present?.should eq false assigns(:order).user.shipping_address.present?.should eq false end it 'assign addresses to the order and the user' do post :create, :effective_order => { :billing_address => billing_atts, :save_billing_address => true, :shipping_address => shipping_atts, :save_shipping_address => true, :shipping_address_same_as_billing => false } (assigns(:order).valid? && assigns(:order).persisted?).should eq true assigns(:order).billing_address.address1.should eq billing_atts['address1'] assigns(:order).shipping_address.address1.should eq shipping_atts['address1'] assigns(:order).user.billing_address.address1.should eq billing_atts['address1'] assigns(:order).user.shipping_address.address1.should eq shipping_atts['address1'] response.should redirect_to "/orders/#{assigns(:order).to_param}" end it 'does not assign the billing_address to user if save_billing_address is false' do post :create, :effective_order => { :billing_address => billing_atts, :save_billing_address => false, :shipping_address => shipping_atts, :save_shipping_address => true, :shipping_address_same_as_billing => false } (assigns(:order).valid? && assigns(:order).persisted?).should eq true assigns(:order).billing_address.address1.should eq billing_atts['address1'] assigns(:order).shipping_address.address1.should eq shipping_atts['address1'] assigns(:order).user.billing_address.present?.should eq false assigns(:order).user.shipping_address.address1.should eq shipping_atts['address1'] response.should redirect_to "/orders/#{assigns(:order).to_param}" end it 'does not assign the shipping_address to user if save_shipping_address is false' do post :create, :effective_order => { :billing_address => billing_atts, :save_billing_address => true, :shipping_address => shipping_atts, :save_shipping_address => false, :shipping_address_same_as_billing => false } (assigns(:order).valid? && assigns(:order).persisted?).should eq true assigns(:order).billing_address.address1.should eq billing_atts['address1'] assigns(:order).shipping_address.address1.should eq shipping_atts['address1'] assigns(:order).user.billing_address.address1.should eq billing_atts['address1'] assigns(:order).user.shipping_address.present?.should eq false response.should redirect_to "/orders/#{assigns(:order).to_param}" end it 'assign billing address to the order shipping_address when shipping_address_same_as_billing' do post :create, :effective_order => { :billing_address => billing_atts, :save_billing_address => true, :shipping_address => shipping_atts, :save_shipping_address => true, :shipping_address_same_as_billing => true } (assigns(:order).valid? && assigns(:order).persisted?).should eq true assigns(:order).billing_address.address1.should eq billing_atts['address1'] assigns(:order).shipping_address.address1.should eq billing_atts['address1'] assigns(:order).user.billing_address.address1.should eq billing_atts['address1'] assigns(:order).user.shipping_address.address1.should eq billing_atts['address1'] response.should redirect_to "/orders/#{assigns(:order).to_param}" end it 'assign billing address to the order shipping_address when shipping_address_same_as_billing and no shipping provided' do post :create, :effective_order => { :billing_address => billing_atts, :save_billing_address => true, :shipping_address_same_as_billing => true } (assigns(:order).valid? && assigns(:order).persisted?).should eq true assigns(:order).billing_address.address1.should eq billing_atts['address1'] assigns(:order).shipping_address.address1.should eq billing_atts['address1'] assigns(:order).user.billing_address.address1.should eq billing_atts['address1'] assigns(:order).user.shipping_address.address1.should eq billing_atts['address1'] response.should redirect_to "/orders/#{assigns(:order).to_param}" end it 'assign billing address to the order shipping_address but not the user when shipping_address_same_as_billing provided' do post :create, :effective_order => { :billing_address => billing_atts, :save_billing_address => false, :save_shipping_address => false, :shipping_address_same_as_billing => true } (assigns(:order).valid? && assigns(:order).persisted?).should eq true assigns(:order).billing_address.address1.should eq billing_atts['address1'] assigns(:order).shipping_address.address1.should eq billing_atts['address1'] assigns(:order).user.billing_address.present?.should eq false assigns(:order).user.shipping_address.present?.should eq false response.should redirect_to "/orders/#{assigns(:order).to_param}" end it 'is invalid when passed an invalid address' do post :create, :effective_order => { :billing_address => billing_atts, :save_billing_address => true, :shipping_address => shipping_atts.tap { |x| x[:address1] = nil }, :save_shipping_address => true, :shipping_address_same_as_billing => false } (assigns(:order).valid? && assigns(:order).persisted?).should eq false assigns(:order).errors[:shipping_address].present?.should eq true response.should render_template(:new) end it 'is invalid when passed an invalid order_item' do Effective::OrderItem.any_instance.stub(:valid?).and_return(false) post :create, :effective_order => { :billing_address => billing_atts, :save_billing_address => true, :shipping_address => shipping_atts, :save_shipping_address => true, } (assigns(:order).valid? && assigns(:order).persisted?).should eq false response.should render_template(:new) end it 'is invalid when passed an invalid user' do User.any_instance.stub(:valid?).and_return(false) post :create, :effective_order => { :billing_address => billing_atts, :save_billing_address => true, :shipping_address => shipping_atts, :save_shipping_address => true, } (assigns(:order).valid? && assigns(:order).persisted?).should eq false response.should render_template(:new) end it 'is invalid when passed an invalid purchasable' do Product.any_instance.stub(:valid?).and_return(false) post :create, :effective_order => { :billing_address => billing_atts, :save_billing_address => true, :shipping_address => shipping_atts, :save_shipping_address => true, } (assigns(:order).valid? && assigns(:order).persisted?).should eq false response.should render_template(:new) end it 'prevents the order from proceeding when missing a required address' do post :create, :effective_order => { :billing_address => billing_atts, :save_billing_address => true, :shipping_address_same_as_billing => false } (assigns(:order).valid? && assigns(:order).persisted?).should eq false assigns(:order).errors[:shipping_address].present?.should eq true response.should render_template(:new) end end describe '#create with a Stripe Subscription object' do let(:cart_with_subscription) { FactoryGirl.create(:cart_with_subscription) } let(:subscription) { cart_with_subscription.cart_items.find { |obj| obj.purchasable.kind_of?(Effective::Subscription)}.purchasable } let(:valid_order_with_new_subscription_coupon_attributes) do valid_order_attributes.tap { |x| x[:effective_order]['order_items_attributes'] = {'0' => {"class"=>"Effective::Subscription", "stripe_coupon_id"=>"#{FactoryGirl.create(:stripe_coupon).id}", 'id' => "#{subscription.id}"}} } end before do StripeMock.start sign_in cart_with_subscription.user end after { StripeMock.stop } it 'has an OrderItem that is a Subscription' do post :create, valid_order_attributes assigns(:order).persisted?.should eq true subscription = assigns(:order).order_items.find { |obj| obj.purchasable.kind_of?(Effective::Subscription) } subscription.present?.should eq true end it 'does not alter the subscription.stripe_coupon_id' do post :create, valid_order_attributes assigns(:order).persisted?.should eq true order_subscription = assigns(:order).order_items.find { |obj| obj.purchasable.kind_of?(Effective::Subscription) }.purchasable order_subscription.stripe_coupon_id.should eq subscription.stripe_coupon_id end it 'updates the subscription.stripe_coupon_id when passed' do post :create, valid_order_with_new_subscription_coupon_attributes assigns(:order).persisted?.should eq true order_subscription = assigns(:order).order_items.find { |obj| obj.purchasable.kind_of?(Effective::Subscription) }.purchasable order_subscription.stripe_coupon_id.should_not eq subscription.stripe_coupon_id end it 'is invalid when passed an invalid coupon code' do invalid_coupon_atts = valid_order_with_new_subscription_coupon_attributes.tap { |x| x[:effective_order]['order_items_attributes']['0']['stripe_coupon_id'] = 'SOMETHING INVALID' } post :create, invalid_coupon_atts assigns(:order).errors['order_items.purchasable'].present?.should eq true assigns(:order).errors['order_items.purchasable.stripe_coupon_id'].present?.should eq true assigns(:order).persisted?.should eq false end end describe '#order_purchased (with a free order)' do before(:each) do sign_in cart.user cart.cart_items.each { |cart_item| cart_item.purchasable.update_attributes(:price => 0.0) } end it 'creates a purchased order' do post :create, valid_order_attributes assigns(:order).purchased?.should eq true assigns(:order).payment[:details].should eq 'automatic purchase of free order.' end it 'destroys the current user cart' do post :create, valid_order_attributes expect { Effective::Cart.find(cart.id) }.to raise_error(ActiveRecord::RecordNotFound) ci_ids = assigns(:cart).cart_items.collect(&:id) expect(Effective::CartItem.where(:id => ci_ids).count).to be 0 end it 'redirects to the purchased page' do post :create, valid_order_attributes response.should redirect_to "/orders/#{assigns(:order).to_param}/purchased" end end describe '#show' do it 'finds the order by obfuscated ID' do sign_in purchased_order.user get :show, :id => purchased_order.to_param assigns(:order).id.should eq purchased_order.id end it 'does not find an order by regular ID' do sign_in purchased_order.user expect { get :show, :id => purchased_order.id }.to raise_error(ActiveRecord::RecordNotFound) end it 'renders the show template for a purchased order' do sign_in purchased_order.user get :show, :id => purchased_order.to_param response.should render_template(:show) end it 'renders the checkout template for a non-purchased order' do sign_in order.user get :show, :id => order.to_param response.should render_template(:checkout) end end describe '#purchased' do before(:each) do sign_in purchased_order.user end it 'finds the order by obfuscated ID' do get :purchased, :id => purchased_order.to_param assigns(:order).id.should eq purchased_order.id end it 'does not find an order by regular ID' do expect { get :purchased, :id => purchased_order.id }.to raise_error(ActiveRecord::RecordNotFound) end end describe '#declined' do before(:each) do sign_in purchased_order.user end it 'finds the order by obfuscated ID' do get :declined, :id => purchased_order.to_param assigns(:order).id.should eq purchased_order.id end it 'does not find an order by regular ID' do expect { get :declined, :id => purchased_order.id }.to raise_error(ActiveRecord::RecordNotFound) end end end