Browse files

Spree 2.1 compatibility.

Key changes:

1. Replace Rails 3 mass assignment with strong parameters
2. Update gemspec and Gemfile to reference unreleased 2.1.0.beta
3. Update JS and CSS files to refer to the broken out source files (spree_frontend, spree_backend) instead of spree_core
4. Remove unused model class
5. Reorganize engine class into a dedicated file, use include in lib/spree_store_credits.
6. Change translations to use Spree.t
7. Update FactoryGirl syntax
8. Add a number of specs
9. Update existing specs for compatibility with Spree 2.1 changes
10. Move spec/requests to spec/features
11. Add simplecov
12. Use database_cleaner for database cleanup
13. Update .travis.yml to run against all branches, remove notifications, and add xvfb
  • Loading branch information...
1 parent 168cc4a commit 448d2f0e09e35572606fb1b935b047ab4d144b2c @petergoldstein petergoldstein committed with JDutil Aug 24, 2013
Showing with 684 additions and 311 deletions.
  1. +1 −0 .gitignore
  2. +5 −0 .simplecov
  3. +2 −9 .travis.yml
  4. +7 −8 Gemfile
  5. +1 −1 Rakefile
  6. +1 −1 app/assets/javascripts/admin/spree_store_credits.js
  7. +1 −1 app/assets/javascripts/store/spree_store_credits.js
  8. +1 −1 app/assets/stylesheets/admin/spree_store_credits.css
  9. +1 −1 app/assets/stylesheets/store/spree_store_credits.css
  10. +14 −3 app/controllers/spree/admin/store_credits_controller.rb
  11. +4 −0 app/controllers/spree/checkout_controller_decorator.rb
  12. +0 −1 app/models/spree/order_decorator.rb
  13. +15 −4 app/models/spree/promotion/actions/give_store_credit.rb
  14. +0 −3 app/models/spree/store_credit.rb
  15. +0 −3 app/models/spree/store_credit_adjustment.rb
  16. +8 −2 app/models/store_credit_minimum_validator.rb
  17. +3 −3 app/views/spree/checkout/_store_credits.html.erb
  18. +4 −25 lib/spree_store_credits.rb
  19. +25 −0 lib/spree_store_credits/engine.rb
  20. +120 −0 spec/controllers/admin/store_credits_controller_spec.rb
  21. +19 −14 spec/factories/store_credits_factory.rb
  22. +149 −0 spec/features/spree/store_credits_spec.rb
  23. +9 −0 spec/models/spree/adjustment_spec.rb
  24. +10 −0 spec/models/spree/app_configuration_spec.rb
  25. +29 −17 spec/models/spree/order_spec.rb
  26. +54 −0 spec/models/spree/promotion/actions/give_store_credit_spec.rb
  27. +37 −0 spec/models/spree/store_credit_spec.rb
  28. +25 −7 spec/models/spree/user_spec.rb
  29. +0 −193 spec/requests/spree/store_credits_spec.rb
  30. +27 −7 spec/spec_helper.rb
  31. +1 −1 spec/support/authentication_helpers.rb
  32. +30 −0 spec/support/checkout_helpers.rb
  33. +70 −0 spec/validators/store_credit_minimum_validator_spec.rb
  34. +11 −6 spree_store_credits.gemspec
View
1 .gitignore
@@ -3,4 +3,5 @@ Gemfile.lock
*.swp
.bundle
.rvmrc
+coverage
.sass-cache
View
5 .simplecov
@@ -0,0 +1,5 @@
+require 'simplecov'
+
+# .simplecov
+SimpleCov.start 'rails' do
+end
View
11 .travis.yml
@@ -1,15 +1,8 @@
before_script:
+ - "sh -e /etc/init.d/xvfb start"
- "bundle exec rake test_app"
script: "DISPLAY=:99.0 bundle exec rspec spec"
-notifications:
- email:
- - brian@spreecommerce.com
-irc: "irc.freenode.org#spree"
-branches:
- only:
- - master
- - 0-7-stable
language: ruby
rvm:
- - 1.8.7
- 1.9.3
+ - 2.0.0
View
15 Gemfile
@@ -1,13 +1,12 @@
-source 'http://rubygems.org'
+source 'https://rubygems.org'
group :development, :test do
- if ENV['USE_LOCAL_SPREE']
- gem "spree_auth_devise", :path => "~/code/spree_auth_devise"
- gem 'spree_core', :path => '~/code/spree'
- gem 'spree_promo', :path => '~/code/spree'
- else
- gem "spree_auth_devise", :git => 'git://github.com/spree/spree_auth_devise.git', :branch => '1-3-stable'
- end
+ gem 'spree_api', github: 'spree/spree', branch: 'master'
+ gem 'spree_core', github: 'spree/spree', branch: 'master'
+ gem 'spree_frontend', github: 'spree/spree', branch: 'master'
+ gem 'spree_backend', github: 'spree/spree', branch: 'master'
+ gem 'spree_sample', github: 'spree/spree', branch: 'master'
+ gem "spree_auth_devise", :github => 'spree/spree_auth_devise', :branch => 'master'
end
gemspec
View
2 Rakefile
@@ -3,7 +3,7 @@ require 'rake/testtask'
require 'rake/packagetask'
require 'rubygems/package_task'
require 'rspec/core/rake_task'
-require 'spree/core/testing_support/common_rake'
+require 'spree/testing_support/common_rake'
RSpec::Core::RakeTask.new
View
2 app/assets/javascripts/admin/spree_store_credits.js
@@ -1 +1 @@
-//= require admin/spree_core
+//= require admin/spree_backend
View
2 app/assets/javascripts/store/spree_store_credits.js
@@ -1 +1 @@
-//= require store/spree_core
+//= require store/spree_frontend
View
2 app/assets/stylesheets/admin/spree_store_credits.css
@@ -1,3 +1,3 @@
/*
- *= require admin/spree_core
+ *= require admin/spree_backend
*/
View
2 app/assets/stylesheets/store/spree_store_credits.css
@@ -1,3 +1,3 @@
/*
- *= require store/spree_core
+ *= require store/spree_frontend
*/
View
17 app/controllers/spree/admin/store_credits_controller.rb
@@ -3,20 +3,31 @@ class Admin::StoreCreditsController < Admin::ResourceController
before_filter :check_amounts, :only => [:edit, :update]
prepend_before_filter :set_remaining_amount, :only => [:create, :update]
+ protected
+ def permitted_resource_params
+ params.require(:store_credit).permit(permitted_store_credit_attributes)
+ end
+
private
def check_amounts
if (@store_credit.remaining_amount < @store_credit.amount)
flash[:error] = Spree.t(:cannot_edit_used)
- redirect_to admin_store_credits_path
+ redirect_to spree.admin_store_credits_path
end
end
def set_remaining_amount
- params[:store_credit][:remaining_amount] = params[:store_credit][:amount]
+ params[:store_credit][:remaining_amount] = params[:store_credit][:amount] if params[:store_credit]
end
def collection
- super.page(params[:page])
+ # TODO: PMG - Figure out how we can integrate with accessible_by
+ Spree::StoreCredit.all.page(params[:page] || 1)
end
+
+ def permitted_store_credit_attributes
+ [:user_id, :amount, :reason, :remaining_amount]
+ end
+
end
end
View
4 app/controllers/spree/checkout_controller_decorator.rb
@@ -2,6 +2,10 @@ module Spree
CheckoutController.class_eval do
before_filter :remove_payments_attributes_if_total_is_zero
+ [:store_credit_amount, :remove_store_credits].each do |attrib|
+ Spree::PermittedAttributes.checkout_attributes << attrib unless Spree::PermittedAttributes.checkout_attributes.include?(attrib)
+ end
+
private
def remove_payments_attributes_if_total_is_zero
load_order
View
1 app/models/spree/order_decorator.rb
@@ -1,5 +1,4 @@
Spree::Order.class_eval do
- attr_accessible :store_credit_amount, :remove_store_credits
attr_accessor :store_credit_amount, :remove_store_credits
# the check for user? below is to ensure we don't break the
View
19 app/models/spree/promotion/actions/give_store_credit.rb
@@ -1,12 +1,23 @@
module Spree
class Promotion::Actions::GiveStoreCredit < PromotionAction
preference :amount, :decimal, :default => 0.0
- attr_accessible :preferred_amount
def perform(options = {})
- if _user = options[:user]
- _user.store_credits.create(:amount => preferred_amount, :remaining_amount => preferred_amount, :reason => "Promotion: #{promotion.name}")
- end
+ user = lookup_user(options)
+ give_store_credit(user) if user.present?
+ end
+
+ def lookup_user(options)
+ options[:user]
+ end
+
+ def give_store_credit(user)
+ user.store_credits.create(:amount => preferred_amount, :remaining_amount => preferred_amount,
+ :reason => credit_reason)
+ end
+
+ def credit_reason
+ "#{Spree.t(:promotion)} #{promotion.name}"
end
end
end
View
3 app/models/spree/store_credit.rb
@@ -1,13 +1,10 @@
class Spree::StoreCredit < ActiveRecord::Base
- attr_accessible :user_id, :amount, :reason, :remaining_amount
-
validates :amount, :presence => true, :numericality => true
validates :reason, :presence => true
validates :user, :presence => true
if Spree.user_class
belongs_to :user, :class_name => Spree.user_class.to_s
else
belongs_to :user
- attr_accessible :amount, :remaining_amount, :reason, :user_id
end
end
View
3 app/models/spree/store_credit_adjustment.rb
@@ -1,3 +0,0 @@
-class Spree::StoreCreditAdjustment < Spree::Adjustment
-
-end
View
10 app/models/store_credit_minimum_validator.rb
@@ -2,9 +2,15 @@ class StoreCreditMinimumValidator < ActiveModel::Validator
include ActionView::Helpers::NumberHelper
def validate(record)
+ return unless Spree::Config[:use_store_credit_minimum]
+ return if record.item_total >= Spree::Config[:use_store_credit_minimum]
+ return unless record.errors.empty?
+
store_credit_amount = record.instance_variable_get(:@store_credit_amount).to_f
- if Spree::Config[:use_store_credit_minimum] and record.item_total < Spree::Config[:use_store_credit_minimum].to_f and store_credit_amount > 0 and record.errors.empty?
- record.errors.add :base, Spree.t("errors.messages.store_credit_minimum_order_not_reach", :amount => number_to_currency(Spree::Config[:use_store_credit_minimum].to_f))
+ if store_credit_amount > 0
+ record.errors.add :base,
+ Spree.t("errors.messages.store_credit_minimum_order_not_reach",
+ amount: number_to_currency(Spree::Config[:use_store_credit_minimum].to_f))
end
end
end
View
6 app/views/spree/checkout/_store_credits.html.erb
@@ -1,11 +1,11 @@
<% if (spree_current_user && spree_current_user.store_credits_total > 0) %>
<% usable_amount = number_with_precision(@order.store_credit_maximum_usable_amount, :precision => 2, :separator => '.', :delimiter => '') %>
<br style='clear:both;' />
-<p><%= t('you_have_store_credit',
+<p><%= Spree.t('you_have_store_credit',
:amount => number_to_currency(spree_current_user.store_credits_total))%>
</p>
<p>
- <label><%= t('enter_desired_amount_of_store_credit') %></label><br />
- <%= form.text_field :store_credit_amount, :size => 19, :value => usable_amount, :data => { :store_credit_maximum_amount => usable_amount, :store_credit_maximum_amount_message => t('store_credit_maximum_amount', :amount => number_to_currency(@order.store_credit_maximum_usable_amount)) } %>
+ <label><%= Spree.t('enter_desired_amount_of_store_credit') %></label><br />
+ <%= form.text_field :store_credit_amount, :size => 19, :value => usable_amount, :data => { :store_credit_maximum_amount => usable_amount, :store_credit_maximum_amount_message => Spree.t('store_credit_maximum_amount', :amount => number_to_currency(@order.store_credit_maximum_usable_amount)) } %>
</p>
<% end %>
View
29 lib/spree_store_credits.rb
@@ -1,26 +1,5 @@
require 'spree_core'
-
-module SpreeStoreCredits
- class Engine < Rails::Engine
- engine_name 'spree_store_credits'
-
- # use rspec for tests
- config.generators do |g|
- g.test_framework :rspec
- end
-
- def self.activate
- Dir.glob(File.join(File.dirname(__FILE__), "../app/**/*_decorator*.rb")) do |c|
- Rails.env == "production" ? require(c) : load(c)
- end
- end
-
- initializer 'spree_store_credits.register.promotion.actions', :after => 'spree.promo.register.promotions.actions' do |app|
- app.config.spree.promotions.actions << Spree::Promotion::Actions::GiveStoreCredit
- end
-
- config.to_prepare &method(:activate).to_proc
- config.autoload_paths += %W(#{config.root}/lib)
-
- end
-end
+require 'spree_api'
+require 'spree_frontend'
+require 'spree_backend'
+require 'spree_store_credits/engine'
View
25 lib/spree_store_credits/engine.rb
@@ -0,0 +1,25 @@
+module SpreeStoreCredits
+ class Engine < Rails::Engine
+ isolate_namespace Spree
+ engine_name 'spree_store_credits'
+
+ # use rspec for tests
+ config.generators do |g|
+ g.test_framework :rspec
+ end
+
+ def self.activate
+ Dir.glob(File.join(File.dirname(__FILE__), "../../app/**/*_decorator*.rb")) do |c|
+ Rails.configuration.cache_classes ? require(c) : load(c)
+ end
+ end
+
+ initializer 'spree_store_credits.register.promotion.actions', :after => 'spree.promo.register.promotions.actions' do |app|
+ app.config.spree.promotions.actions << Spree::Promotion::Actions::GiveStoreCredit
+ end
+
+ config.to_prepare &method(:activate).to_proc
+ config.autoload_paths += %W(#{config.root}/lib)
+
+ end
+end
View
120 spec/controllers/admin/store_credits_controller_spec.rb
@@ -0,0 +1,120 @@
+require 'spec_helper'
+
+describe Spree::Admin::StoreCreditsController do
+ stub_authorization!
+
+ before do
+ user = create(:admin_user)
+ controller.stub(:spree_current_user => user)
+ end
+
+ context '#index' do
+ context "with store credits" do
+ let!(:store_credits) { 3.times.map{ create(:store_credit) } }
+
+ it "should display the index page" do
+ spree_get :index
+ response.status.should eq(200)
+ response.should render_template(:index)
+ assigned_credits = assigns(:collection)
+ store_credits.each do |c|
+ assigned_credits.should include(c)
+ end
+ end
+ end
+
+ context "without store credits" do
+ it "should display an empty" do
+ spree_get :index
+ response.status.should eq(200)
+ response.should render_template(:index)
+ assigns(:collection).should be_empty
+ end
+ end
+ end
+
+ context '#new' do
+ it 'should render the correct template' do
+ spree_get :new
+ response.status.should eq(200)
+ response.should render_template(:new)
+ end
+ end
+
+ context '#create' do
+ let(:user) { create(:user) }
+ let(:reason) { SecureRandom.hex(5) }
+ let(:amount) { BigDecimal.new(rand()*100, 2).to_f }
+
+ it 'should create a store credit for the user when arguments are provided' do
+ lambda {
+ spree_post :create, store_credit: { amount: amount, reason: reason, user_id: user.id }
+ response.should redirect_to(spree.admin_store_credits_path)
+ }.should change(Spree::StoreCredit, :count).by(1)
+ user.reload
+ store_credit = user.store_credits.first
+ store_credit.should_not be_nil
+ store_credit.user.should eq(user)
+ store_credit.reason.should eq(reason)
+ store_credit.amount.should eq(amount)
+ store_credit.remaining_amount.should eq(amount)
+ end
+ end
+
+ context '#edit' do
+ let(:new_store_credit) { create(:store_credit, amount: 40.0, remaining_amount: 40.0) }
+ let(:used_store_credit) { create(:store_credit, amount: 40.0, remaining_amount: 20.0) }
+
+ it 'should render the correct template for a new store credit' do
+ spree_get :edit, id: new_store_credit
+ response.status.should eq(200)
+ response.should render_template(:edit)
+ end
+
+ it 'should redirect to spree.admin_store_credits_path for a used store credit' do
+ spree_get :edit, id: used_store_credit
+ response.should redirect_to(spree.admin_store_credits_path)
+ flash[:error].should eq("Cannot be edited because it has been used")
+ end
+ end
+
+ context '#update' do
+ let(:new_store_credit) { create(:store_credit, amount: 40.0, remaining_amount: 40.0) }
+ let(:used_store_credit) { create(:store_credit, amount: 40.0, remaining_amount: 20.0) }
+
+ it 'should update the value and redirect for a new store credit' do
+ new_reason = SecureRandom.hex(5)
+ spree_put :update, id: new_store_credit, store_credit: { amount: new_store_credit.amount,
+ remaining_amount: new_store_credit.remaining_amount,
+ user_id: new_store_credit.user,
+ reason: new_reason }
+ new_store_credit.reload
+ new_store_credit.reason.should eq(new_reason)
+ flash[:error].should be_nil
+ response.should redirect_to(spree.admin_store_credits_path)
+ end
+
+ it 'should redirect to spree.admin_store_credits_path for a used store credit' do
+ old_reason = used_store_credit.reason
+ new_reason = SecureRandom.hex(5)
+ spree_put :update, id: used_store_credit, store_credit: { amount: used_store_credit.amount,
+ remaining_amount: used_store_credit.remaining_amount,
+ user_id: used_store_credit.user,
+ reason: new_reason }
+ response.should redirect_to(spree.admin_store_credits_path)
+ flash[:error].should eq("Cannot be edited because it has been used")
+ used_store_credit.reload
+ used_store_credit.reason.should eq(old_reason)
+ end
+ end
+
+ context '#destroy' do
+ let!(:store_credit) { create(:store_credit) }
+ it 'should destroy the store credit' do
+ lambda {
+ spree_delete :destroy, id: store_credit.id
+ response.should redirect_to(spree.admin_store_credits_path)
+ }.should change(Spree::StoreCredit, :count).by(-1)
+ end
+ end
+end
View
33 spec/factories/store_credits_factory.rb
@@ -1,20 +1,25 @@
-# this :promotion factory is defined in spree_promo, but I can't reuse it (i believe) b/c it is in spec/factories vs. lib/....
-Factory.define :promotion, :class => Spree::Promotion, :parent => :activator do |f|
- f.name 'Promo'
-end
+require 'bigdecimal'
+FactoryGirl.define do
+ factory :store_credit, class: Spree::StoreCredit do
+ amount { BigDecimal.new(rand()*100, 2) }
+ reason { SecureRandom.hex(5) }
+ user
+ end
-Factory.define :give_store_credit_action, :class => Spree::Promotion::Actions::GiveStoreCredit do |f|
- f.association :promotion
+ factory :give_store_credit_action, :class => Spree::Promotion::Actions::GiveStoreCredit do |f|
+ association :promotion
- f.after_create do |action|
- action.set_preference(:amount, 1234.56)
- action.save!
+ after(:create) do |action|
+ action.set_preference(:amount, 1234.56)
+ action.save!
+ end
end
-end
-Factory.define :promotion_for_store_credits, :parent => :promotion do |f|
- f.event_name "spree.user.signup"
- f.after_create do |p|
- p.promotion_actions [FactoryGirl.create(:give_store_credit_action, :promotion => p)]
+ factory :promotion_for_store_credits, :parent => :promotion do
+ event_name "spree.user.signup"
+ after(:create) do |p|
+ p.promotion_actions [create(:give_store_credit_action, :promotion => p)]
+ end
end
end
+
View
149 spec/features/spree/store_credits_spec.rb
@@ -0,0 +1,149 @@
+require 'spec_helper'
+
+describe "Promotion for Store Credits" do
+ let!(:country) { create(:country, :states_required => true) }
+ let!(:state) { create(:state, :country => country) }
+ let!(:shipping_method) { create(:shipping_method) }
+ let!(:stock_location) { create(:stock_location) }
+ let!(:mug) { create(:product, :name => "RoR Mug") }
+ let!(:payment_method) { create(:payment_method) }
+ let!(:zone) { create(:zone) }
+
+ context "#new user" do
+ let(:address) { create(:address, :state => Spree::State.first) }
+
+ before do
+ shipping_method.calculator.set_preference(:amount, 10)
+ end
+
+ it "should give me a store credit when I register", :js => true do
+ email = 'paul@gmail.com'
+ setup_new_user_and_sign_up(email)
+ new_user = Spree.user_class.find_by_email email
+ new_user.store_credits.size.should == 1
+ end
+
+ it "should not allow the user to apply the store credit if minimum order amount is not reached", :js => true do
+ reset_spree_preferences do |config|
+ config.use_store_credit_minimum = 100
+ end
+ email = 'george@gmail.com'
+ setup_new_user_and_sign_up(email)
+
+ # regression fix double giving store credits
+ Spree.user_class.find_by_email(email).store_credits(true).count.should == 1
+ click_button "Checkout"
+
+ fill_in_address
+ click_button "Save and Continue"
+ click_button "Save and Continue"
+ page.should have_content("You have $1,234.56 of store credits")
+ fill_in "order_store_credit_amount", :with => "50"
+
+ click_button "Save and Continue"
+ page.should have_content("Order's item total is less than the minimum allowed ($100.00) to use store credit")
+
+ reset_spree_preferences do |config|
+ config.use_store_credit_minimum = 1
+ end
+ click_button "Save and Continue"
+ # Store credits MAXIMUM => item_total - 0.01 in order to be valid ex : paypal orders
+ page.should have_content("$-19.98")
+ page.should have_content("Your order has been processed successfully")
+ Spree::Order.count.should == 2 # 1 Purchased + 1 new empty cart order
+
+
+ # store credits should be consumed
+ visit spree.account_path
+ page.should have_content("Current store credit: $1,214.58")
+
+ end
+
+ it "should allow if not using store credit and minimum order is not reached", :js => true do
+ reset_spree_preferences do |config|
+ config.use_store_credit_minimum = 100
+ end
+
+ email = 'patrick@gmail.com'
+ setup_new_user_and_sign_up(email)
+
+ Spree.user_class.find_by_email(email).store_credits(true).count.should == 1
+
+ click_button "Checkout"
+
+ fill_in_address
+ click_button "Save and Continue"
+ click_button "Save and Continue"
+ fill_in "order_store_credit_amount", :with => "0"
+
+ click_button "Save and Continue"
+ page.should have_content("Your order has been processed successfully")
+ Spree::Order.count.should == 2 # 1 Purchased + 1 new empty cart order
+
+ # store credits should be unchanged
+ visit spree.account_path
+ page.should have_content("Current store credit: $1,234.56")
+ end
+
+ it "should allow using store credit if minimum order amount is reached", :js => true do
+ reset_spree_preferences do |config|
+ config.use_store_credit_minimum = 10
+ end
+ email = 'sam@gmail.com'
+ setup_new_user_and_sign_up(email)
+ Spree.user_class.find_by_email(email).store_credits(true).count.should == 1
+
+ click_button "Checkout"
+
+ fill_in_address
+ click_button "Save and Continue"
+ click_button "Save and Continue"
+
+ fill_in "order_store_credit_amount", :with => "10"
+ click_button "Save and Continue"
+
+ page.should have_content("$-10.00")
+ page.should have_content("Your order has been processed successfully")
+ Spree::Order.count.should == 2 # 1 Purchased + 1 new empty cart order
+
+ # store credits should be consumed
+ visit spree.account_path
+ page.should have_content("Current store credit: $1,224.56")
+ end
+
+ it "should allow even when admin is giving store credits", :js => true do
+ sign_in_as! user = FactoryGirl.create(:admin_user)
+ visit spree.new_admin_user_store_credit_path(user)
+ fill_in "Amount", :with => 10
+ fill_in "Reason", :with => "Gift"
+
+ click_button "Create"
+
+ reset_spree_preferences do |config|
+ config.use_store_credit_minimum = 10
+ end
+
+ visit spree.product_path(mug)
+
+ click_button "Add To Cart"
+ click_button "Checkout"
+
+ fill_in_address
+ click_button "Save and Continue"
+ click_button "Save and Continue"
+ fill_in "order_store_credit_amount", :with => "10"
+
+ click_button "Save and Continue"
+ page.should have_content("$-10.00")
+ page.should have_content("Your order has been processed successfully")
+
+ # store credits should be consumed
+ visit spree.account_path
+
+ page.should_not have_content('Current store credit: $10.00')
+ Spree::Order.count.should == 2 # 1 Purchased + 1 new empty cart order
+ end
+
+ after(:each) { reset_spree_preferences }
+ end
+end
View
9 spec/models/spree/adjustment_spec.rb
@@ -0,0 +1,9 @@
+require 'spec_helper'
+
+module Spree
+ describe Adjustment do
+ it 'has a scope method for store credits' do
+ Spree::Adjustment.should respond_to(:store_credits)
+ end
+ end
+end
View
10 spec/models/spree/app_configuration_spec.rb
@@ -0,0 +1,10 @@
+require 'spec_helper'
+
+describe Spree::AppConfiguration do
+ subject { Spree::AppConfiguration.new }
+
+ it 'should have the use_store_credit_minimum preference' do
+ subject.should respond_to(:preferred_use_store_credit_minimum)
+ subject.should respond_to(:preferred_use_store_credit_minimum=)
+ end
+end
View
46 spec/models/spree/order_spec.rb
@@ -2,16 +2,20 @@
module Spree
describe Order do
- let(:user) { mock_model User, :email => 'spree@example.com', :store_credits_total => 45.00 }
- let(:line_item) { mock_model(LineItem, :variant => mock('variant'), :quantity => 5, :price => 10) }
- let(:order) { Order.create }
+ let(:user) { create(:user) }
+ let!(:store_credit) { create(:store_credit, user: user, amount: 45.00, remaining_amount: 45.00)}
+ let(:line_item) { mock_model(LineItem, :variant => double('variant'), :quantity => 5, :price => 10) }
+ let(:order) { create(:order, user: user) }
before do
reset_spree_preferences { |config| config.use_store_credit_minimum = 0 }
- order.stub(:user => user, :total => 50 )
end
context "process_store_credit" do
+ before do
+ order.stub(:user => user, :total => 50 )
+ end
+
it "should create store credit adjustment when user has sufficient credit" do
order.store_credit_amount = 5.0
order.save
@@ -48,7 +52,7 @@ module Spree
end
it "should update payment amount if credit is applied" do
- order.stub_chain(:pending_payments, :first => mock('payment', :payment_method => mock('payment method', :payment_profiles_supported? => true)))
+ order.stub_chain(:pending_payments, :first => double('payment', :payment_method => double('payment method', :payment_profiles_supported? => true)))
order.pending_payments.first.should_receive(:amount=)
order.store_credit_amount = 5.0
order.save
@@ -117,7 +121,8 @@ module Spree
let(:store_credit_1) { mock_model(StoreCredit, :amount => 100, :remaining_amount => 100) }
let(:store_credit_2) { mock_model(StoreCredit, :amount => 10, :remaining_amount => 5) }
let(:store_credit_3) { mock_model(StoreCredit, :amount => 60, :remaining_amount => 50 ) }
- before { order.stub(:completed? => true, :store_credit_amount => 35) }
+
+ before { order.stub(:completed? => true, :store_credit_amount => 35, :total => 50) }
it "should reduce remaining amount on a single credit when that credit satisfies the entire amount" do
user.stub(:store_credits => [store_credit_1])
@@ -145,7 +150,7 @@ module Spree
# regression
it 'should do nothing on guest checkout' do
- order.stub!(:user => nil)
+ order.stub(:user => nil)
expect {
order.send(:consume_users_credit)
}.to_not raise_error
@@ -154,34 +159,41 @@ module Spree
context "ensure_sufficient_credit" do
- let(:payment) { mock_model(Payment, :checkout? => true, :amount => 50)}
- before do
- order.adjustments.store_credits.create(:label => I18n.t(:store_credit) , :amount => -10)
- order.stub(:completed? => true, :store_credit_amount => 35, :payment => payment )
+ let(:order) { create(:completed_order_with_totals, store_credit_amount: 35, user: user)}
+ let!(:payment) { create(:payment, order: order, amount: 40, state: 'completed')}
+ before do
+ order.adjustments.store_credits.create(label: I18n.t(:store_credit) , amount: -10, eligible: true)
+ order.update!
end
it "should do nothing when user has credits" do
order.adjustments.store_credits.should_not_receive(:destroy_all)
- order.payment.should_not_receive(:update_attributes_without_callbacks)
+ order.should_not_receive(:update!)
order.send(:ensure_sufficient_credit)
end
context "when user no longer has sufficient credit to cover entire credit amount" do
before do
- payment.stub(:amount => 40)
- user.stub(:store_credits_total => 0.0)
+ store_credit.remaining_amount = 0.0
+ store_credit.save!
+ user.reload
end
it "should destroy all store credit adjustments" do
- order.payment.stub(:update_attributes_without_callbacks)
+ order.adjustment_total.should eq(-10)
+ order.total.should eq(40)
order.send(:ensure_sufficient_credit)
order.adjustments.store_credits.size.should == 0
+ order.reload
+ order.adjustment_total.should eq(0)
end
- it "should update payment" do
- order.payment.should_receive(:update_attributes_without_callbacks).with(:amount => 50)
+ it "should update the order's payment state" do
+ order.payment_state.should eq('paid')
order.send(:ensure_sufficient_credit)
+ order.reload
+ order.payment_state.should eq('balance_due')
end
end
View
54 spec/models/spree/promotion/actions/give_store_credit_spec.rb
@@ -0,0 +1,54 @@
+require 'spec_helper'
+
+describe Spree::Promotion::Actions::GiveStoreCredit do
+ let(:promotion) { create(:promotion) }
+ subject {
+ a = Spree::Promotion::Actions::GiveStoreCredit.new
+ a.promotion = promotion
+ a.preferred_amount = 20.0
+ a
+ }
+
+ context '#perform' do
+ it 'passes the argument to lookup user, and passes a not nil return value to give_store_credit' do
+ options_double = double
+ user_double = double
+ subject.should_receive(:lookup_user).with(options_double).and_return(user_double)
+ subject.should_receive(:give_store_credit).with(user_double)
+ subject.perform(options_double)
+ end
+
+ it 'passes the argument to lookup user, and does not give a store credit if no user is found' do
+ options_double = double
+ subject.should_receive(:lookup_user).with(options_double).and_return(nil)
+ subject.should_not_receive(:give_store_credit)
+ subject.perform(options_double)
+ end
+ end
+
+ context '#lookup_user' do
+ it 'pulls the user from the options hash' do
+ user_double = double
+ options = { user: user_double }
+ subject.lookup_user(options).should eq(user_double)
+ end
+ end
+
+ context '#give_store_credit' do
+ let!(:user) { create(:user) }
+
+ it 'adds a store credit with the specified amount and reason to the user' do
+ lambda {
+ subject.give_store_credit(user)
+ }.should change(Spree::StoreCredit, :count).by(1)
+ user.reload
+ user.store_credits.size.should eq(1)
+ last_credit = user.store_credits.first
+ last_credit.should_not be_nil
+ last_credit.amount.should eq(subject.preferred_amount)
+ last_credit.reason.should eq(subject.credit_reason)
+ last_credit.remaining_amount.should eq(last_credit.amount)
+ end
+ end
+
+end
View
37 spec/models/spree/store_credit_spec.rb
@@ -0,0 +1,37 @@
+require 'spec_helper'
+
+describe Spree::StoreCredit do
+ it { should respond_to(:amount) }
+ it { should respond_to(:reason) }
+ it { should respond_to(:user) }
+
+ context '#validations' do
+ it 'should ensure the presence of an amount' do
+ sc = build(:store_credit)
+ sc.should be_valid
+ sc.amount = nil
+ sc.should_not be_valid
+ end
+
+ it 'should ensure the numericality of an amount' do
+ sc = build(:store_credit)
+ sc.should be_valid
+ sc.amount = 'not_a_number'
+ sc.should_not be_valid
+ end
+
+ it 'should ensure the presence of a reason' do
+ sc = build(:store_credit)
+ sc.should be_valid
+ sc.reason = nil
+ sc.should_not be_valid
+ end
+
+ it 'should ensure the presence of a user' do
+ sc = build(:store_credit)
+ sc.should be_valid
+ sc.user = nil
+ sc.should_not be_valid
+ end
+ end
+end
View
32 spec/models/spree/user_spec.rb
@@ -2,16 +2,34 @@
module Spree
describe User do
- let(:user) { User.create(:email => "foo@bar.com", :password => "secret", :password_confirmation => "secret") }
+ it { should respond_to(:store_credits)}
- context "store_credits_total" do
- before do
- user.store_credits.create(:amount => 100, :remaining_amount => 100, :reason => "A")
- user.store_credits.create(:amount => 60, :remaining_amount => 55, :reason => "B")
+ let(:user_with_credits) {
+ u = create(:user)
+ u.store_credits.create(:amount => 100, :remaining_amount => 100, :reason => "A")
+ u.store_credits.create(:amount => 60, :remaining_amount => 55, :reason => "B")
+ u
+ }
+
+ let(:user_without_credits) { create(:user) }
+
+ context '#has_store_credit?' do
+ it 'should return true for users with credits' do
+ user_with_credits.has_store_credit?.should be_true
+ end
+
+ it 'should return false for users without credits' do
+ user_without_credits.has_store_credit?.should be_false
+ end
+ end
+
+ context '#store_credits_total' do
+ it 'should return the total remaining amount for users store credits' do
+ user_with_credits.store_credits_total.should == 155.00
end
- it "should return the total remaining amount for users store credits" do
- user.store_credits_total.should == 155.00
+ it 'should not error out on users without any credits, and should return 0.00' do
+ user_without_credits.store_credits_total.should == 0.00
end
end
end
View
193 spec/requests/spree/store_credits_spec.rb
@@ -1,193 +0,0 @@
-require 'spec_helper'
-
-module Spree
- describe "Promotion for Store Credits" do
-
- context "#new user" do
- before do
- sm = create(:shipping_method, :zone => Spree::Zone.find_by_name('North America'))
- sm.calculator.set_preference(:amount, 10)
-
- create(:payment_method, :environment => 'test')
- @product = FactoryGirl.create(:product, :name => "RoR Mug")
- end
- let!(:address) { FactoryGirl.create(:address, :state => Spree::State.first) }
-
- it "should give me a store credit when I register" do
- create(:promotion_for_store_credits, :event_name => "spree.user.signup", :created_at => 2.days.ago)
-
- visit "/signup"
-
- fill_in "Email", :with => "paul@gmail.com"
- fill_in "Password", :with => "qwerty"
- fill_in "Password Confirmation", :with => "qwerty"
- click_button "Create"
-
- new_user = User.find_by_email "paul@gmail.com"
- new_user.store_credits.size.should == 1
- end
-
- it "should not allow if minimum order is not reached", :js => true do
- reset_spree_preferences do |config|
- config.use_store_credit_minimum = 100
- end
- create(:promotion_for_store_credits, :event_name => "spree.user.signup", :created_at => 2.days.ago)
- visit "/signup"
-
- fill_in "Email", :with => "george@gmail.com"
- fill_in "Password", :with => "qwerty"
- fill_in "Password Confirmation", :with => "qwerty"
- click_button "Create"
-
- visit spree.product_path(@product)
- click_button "Add To Cart"
-
- # regression fix double giving store credits
- User.find_by_email("george@gmail.com").store_credits(true).count.should == 1
- click_button "Checkout"
-
- str_addr = "bill_address"
- select "United States", :from => "order_#{str_addr}_attributes_country_id"
- ['firstname', 'lastname', 'address1', 'city', 'zipcode', 'phone'].each do |field|
- fill_in "order_#{str_addr}_attributes_#{field}", :with => "#{address.send(field)}"
- end
-
- select "#{address.state.name}", :from => "order_#{str_addr}_attributes_state_id"
- check "order_use_billing"
-
- click_button "Save and Continue"
- click_button "Save and Continue"
- page.should have_content("You have $1,234.56 of store credits")
- fill_in "order_store_credit_amount", :with => "50"
-
- click_button "Save and Continue"
- page.should have_content("Order's item total is less than the minimum allowed ($100.00) to use store credit")
-
- reset_spree_preferences do |config|
- config.use_store_credit_minimum = 1
- end
- click_button "Save and Continue"
- # Store credits MAXIMUM => item_total - 0.01 in order to be valid ex : paypal orders
- page.should have_content("$-19.98")
- page.should have_content("Your order has been processed successfully")
- Spree::Order.count.should == 2 # 1 Purchased + 1 new empty cart order
- end
-
- it "should allow if not using store credit and minimum order is not reached", :js => true do
- reset_spree_preferences do |config|
- config.use_store_credit_minimum = 100
- end
-
- create(:promotion_for_store_credits, :event_name => "spree.user.signup", :created_at => 2.days.ago)
- visit "/signup"
-
- fill_in "Email", :with => "patrick@gmail.com"
- fill_in "Password", :with => "qwerty"
- fill_in "Password Confirmation", :with => "qwerty"
- click_button "Create"
-
- User.find_by_email("patrick@gmail.com").store_credits(true).count.should == 1
-
- visit spree.product_path(@product)
-
- click_button "Add To Cart"
- click_button "Checkout"
-
- str_addr = "bill_address"
- select "United States", :from => "order_#{str_addr}_attributes_country_id"
- ['firstname', 'lastname', 'address1', 'city', 'zipcode', 'phone'].each do |field|
- fill_in "order_#{str_addr}_attributes_#{field}", :with => "#{address.send(field)}"
- end
-
- select "#{address.state.name}", :from => "order_#{str_addr}_attributes_state_id"
- check "order_use_billing"
- click_button "Save and Continue"
- click_button "Save and Continue"
- fill_in "order_store_credit_amount", :with => "0"
-
- click_button "Save and Continue"
- page.should have_content("Your order has been processed successfully")
- Spree::Order.count.should == 2 # 1 Purchased + 1 new empty cart order
- end
-
- it "should allow if using store credit and minimum order is not reached", :js => true do
- reset_spree_preferences do |config|
- config.use_store_credit_minimum = 10
- end
- create(:promotion_for_store_credits, :event_name => "spree.user.signup", :created_at => 2.days.ago)
- visit "/signup"
- fill_in "Email", :with => "sam@gmail.com"
- fill_in "Password", :with => "qwerty"
- fill_in "Password Confirmation", :with => "qwerty"
- click_button "Create"
-
- User.find_by_email("sam@gmail.com").store_credits(true).count.should == 1
-
- visit spree.product_path(@product)
-
- click_button "Add To Cart"
- click_button "Checkout"
-
- str_addr = "bill_address"
- select "United States", :from => "order_#{str_addr}_attributes_country_id"
- ['firstname', 'lastname', 'address1', 'city', 'zipcode', 'phone'].each do |field|
- fill_in "order_#{str_addr}_attributes_#{field}", :with => "#{address.send(field)}"
- end
-
- select "#{address.state.name}", :from => "order_#{str_addr}_attributes_state_id"
- check "order_use_billing"
- click_button "Save and Continue"
- click_button "Save and Continue"
-
- fill_in "order_store_credit_amount", :with => "10"
- click_button "Save and Continue"
-
- page.should have_content("$-10.00")
- page.should have_content("Your order has been processed successfully")
- Spree::Order.count.should == 2 # 1 Purchased + 1 new empty cart order
- end
-
- it "should allow even when admin is giving store credits", :js => true do
- sign_in_as! user = FactoryGirl.create(:admin_user)
- visit spree.new_admin_user_store_credit_path(user)
- fill_in "Amount", :with => 10
- fill_in "Reason", :with => "Gift"
-
- click_button "Create"
-
- reset_spree_preferences do |config|
- config.use_store_credit_minimum = 10
- end
-
- visit spree.product_path(@product)
-
- click_button "Add To Cart"
- click_button "Checkout"
-
- str_addr = "bill_address"
- select "United States", :from => "order_#{str_addr}_attributes_country_id"
- ['firstname', 'lastname', 'address1', 'city', 'zipcode', 'phone'].each do |field|
- fill_in "order_#{str_addr}_attributes_#{field}", :with => "#{address.send(field)}"
- end
-
- select "#{address.state.name}", :from => "order_#{str_addr}_attributes_state_id"
- check "order_use_billing"
- click_button "Save and Continue"
- click_button "Save and Continue"
- fill_in "order_store_credit_amount", :with => "10"
-
- click_button "Save and Continue"
- page.should have_content("$-10.00")
- page.should have_content("Your order has been processed successfully")
-
- # store credits should be consumed
- visit spree.account_path
-
- page.should_not have_content('Current store credit: $10.00')
- Spree::Order.count.should == 2 # 1 Purchased + 1 new empty cart order
- end
-
- after(:each) { reset_spree_preferences }
- end
- end
-end
View
34 spec/spec_helper.rb
@@ -1,23 +1,26 @@
# Configure Rails Environment
ENV["RAILS_ENV"] = "test"
+require 'simplecov' if ENV["COVERAGE"]
require File.expand_path("../dummy/config/environment.rb", __FILE__)
require 'rspec/rails'
require 'factory_girl'
-require 'spree/core/url_helpers'
+require 'spree/testing_support/url_helpers'
require 'database_cleaner'
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[File.join(File.dirname(__FILE__), "support/**/*.rb")].each {|f| require f }
+# Requires factories defined in spree_core
+require 'spree/testing_support/factories'
+
# include local factories
Dir["#{File.dirname(__FILE__)}/factories/**/*.rb"].each { |f| require File.expand_path(f)}
-# Requires factories defined in spree_core
-require 'spree/core/testing_support/factories'
-require 'spree/core/testing_support/fixtures'
+require 'spree/testing_support/controller_requests'
+require 'spree/testing_support/authorization_helpers'
require 'ffaker'
@@ -30,9 +33,26 @@
# If you're not using ActiveRecord, or you'd prefer not to run each of your
# examples within a transaction, comment the following line or assign false
# instead of true.
- config.use_transactional_fixtures = true
+ config.use_transactional_fixtures = false
+ config.before(:each) do
+ if example.metadata[:js]
+ DatabaseCleaner.strategy = :truncation
+ else
+ DatabaseCleaner.strategy = :transaction
+ end
+ end
+
+ config.before(:each) do
+ DatabaseCleaner.start
+ end
+
+ config.after(:each) do
+ DatabaseCleaner.clean
+ end
- config.include Spree::Core::UrlHelpers
config.include FactoryGirl::Syntax::Methods
- config.include Rack::Test::Methods, :type => :requests
+ config.include Spree::TestingSupport::UrlHelpers
+ config.include Spree::TestingSupport::ControllerRequests, :type => :controller
+ config.include Rack::Test::Methods, :type => :feature
+ config.include Capybara::DSL
end
View
2 spec/support/authentication_helpers.rb
@@ -9,5 +9,5 @@ def sign_in_as!(user)
end
RSpec.configure do |c|
- c.include AuthenticationHelpers, :type => :request
+ c.include AuthenticationHelpers, :type => :feature
end
View
30 spec/support/checkout_helpers.rb
@@ -0,0 +1,30 @@
+def add_mug_to_cart
+ visit spree.root_path
+ click_link mug.name
+ click_button "add-to-cart-button"
+end
+
+def setup_new_user_and_sign_up(email)
+ create(:promotion_for_store_credits, :event_name => "spree.user.signup", :created_at => 2.days.ago)
+ lambda {
+ visit spree.signup_path
+
+ fill_in "Email", :with => email
+ fill_in "Password", :with => "qwerty"
+ fill_in "Password Confirmation", :with => "qwerty"
+ click_button "Create"
+ add_mug_to_cart
+ }.should change(Spree::StoreCredit, :count).by(1)
+end
+
+def fill_in_address
+ address = "order_bill_address_attributes"
+ fill_in "#{address}_firstname", :with => "Ryan"
+ fill_in "#{address}_lastname", :with => "Bigg"
+ fill_in "#{address}_address1", :with => "143 Swan Street"
+ fill_in "#{address}_city", :with => "Richmond"
+ select "United States of America", :from => "#{address}_country_id"
+ select "Alabama", :from => "#{address}_state_id"
+ fill_in "#{address}_zipcode", :with => "12345"
+ fill_in "#{address}_phone", :with => "(555) 555-5555"
+end
View
70 spec/validators/store_credit_minimum_validator_spec.rb
@@ -0,0 +1,70 @@
+require 'spec_helper'
+
+require 'active_model'
+require 'rspec/rails/extensions'
+
+class StoreCreditMinimumValidatable
+ include ActiveModel::Validations
+ attr_accessor :store_credit_amount
+ attr_accessor :item_total
+ attr_accessor :other_validated_attr
+ validates :other_validated_attr, presence: true
+ validates_with StoreCreditMinimumValidator
+end
+
+describe StoreCreditMinimumValidator do
+ subject { StoreCreditMinimumValidatable.new }
+
+ before do
+ subject.other_validated_attr = 'valid'
+ end
+
+ context 'when the use_store_credit_minimum configuration value is not set' do
+ before do
+ Spree::Config[:use_store_credit_minimum] = nil
+ subject.item_total = 200.00
+ end
+
+ it 'should not validate if there is no store credit' do
+ expect(subject).to be_valid
+ end
+
+ it 'should not validate if there is a store credit' do
+ subject.store_credit_amount = 100.00
+ expect(subject).to be_valid
+ end
+ end
+
+ context 'when the use_store_credit_minimum configuration value is set' do
+ before do
+ Spree::Config[:use_store_credit_minimum] = 20.00
+ subject.item_total = 10.00
+ end
+
+ it 'should not validate if there is no store credit' do
+ expect(subject).to be_valid
+ end
+
+ it 'should not validate if there is a store credit and the total is below the minimum' do
+ subject.store_credit_amount = 10.00
+ expect(subject).not_to be_valid
+ expect(subject.errors[:base]).not_to be_empty
+ expect(subject.errors[:base]).to eq(["Order's item total is less than the minimum allowed ($20.00) to use store credit."])
+ end
+
+ it 'should not add a validation error if an error already exists' do
+ subject.other_validated_attr = nil
+ expect(subject).not_to be_valid
+
+ subject.store_credit_amount = 10.00
+ expect(subject).not_to be_valid
+ expect(subject.errors[:base]).to be_empty
+ end
+
+ it 'should validate if there is a store credit and the total is below the minimum' do
+ subject.item_total = 20.00
+ subject.store_credit_amount = 10.00
+ expect(subject).to be_valid
+ end
+ end
+end
View
17 spree_store_credits.gemspec
@@ -17,17 +17,22 @@ Gem::Specification.new do |s|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
s.require_paths = ["lib"]
- s.add_dependency 'spree_core', '~> 2.0.0'
+ s.add_dependency 'spree_api'
+ s.add_dependency 'spree_core', '~> 2.1.0.beta'
+ s.add_dependency 'spree_frontend'
+ s.add_dependency 'spree_backend'
- s.add_development_dependency 'capybara', '1.0.1'
+ s.add_development_dependency 'capybara', '~> 2.1'
s.add_development_dependency 'ffaker'
- s.add_development_dependency 'rspec-rails', '~> 2.9'
+ s.add_development_dependency 'rspec-rails', '~> 2.14'
s.add_development_dependency 'sqlite3'
- s.add_development_dependency 'factory_girl_rails', '~> 1.5.0'
- s.add_development_dependency 'database_cleaner'
+ s.add_development_dependency 'factory_girl_rails', '~> 4.2.1'
+ s.add_development_dependency 'database_cleaner', '1.0.1'
s.add_development_dependency 'launchy'
s.add_development_dependency 'debugger'
s.add_development_dependency 'sass-rails'
s.add_development_dependency 'coffee-rails'
- s.add_development_dependency 'spree_sample', "~> 1.3.0"
+ s.add_development_dependency 'selenium-webdriver', '2.35.0'
+ s.add_development_dependency 'spree_sample', "~> 2.1.0.beta"
+ s.add_development_dependency 'simplecov'
end

0 comments on commit 448d2f0

Please sign in to comment.